/*================================================================ * Copyright (C) 2018 FREEDOM Ltd. All rights reserved. * * 文件名称:busserver.c * 创 建 者:chenjie.gu * 创建日期:2018年05月23日 * 描 述: * ================================================================*/ #include "busserver.h" #include "mongoose.h" #define BUSCLIENT_KEEPALIVE 1 #define BUSCLIENT_RPC_REQUEST 2 #define BUSCLIENT_RPC_RESPONSE 3 #define BUSCLIENT_SEND_TOPIC 4 #define BUSCLIENT_RECV_TOPIC 5 struct mg_connection *conn = NULL; event_cb user_cb = NULL; void *user = NULL; struct message { struct multipart bm; }; static int find_in_str(const char *p) { char *pos = strstr(p, "\r\n"); if (pos == NULL) { return -1; } return pos - p; } static int busclient_parse_multipart_msg(struct mg_connection *nc, struct message *msg, int *type) { const char *pp = nc->recv_mbuf.buf; const char *p = pp; int len = nc->recv_mbuf.len; int handle_len = 0, reserve_len = len, part_len = 0, _len = 0, n = 0; for (int i = 0; i < BUSCLIENT_MAX_MULTIPART_OPT; ++i) { _len = find_in_str(p); part_len = atoi(p); if( reserve_len >= _len+2+part_len+2 && strncmp(p+_len,"\r\n",2)==0 && strncmp(p+_len+2+part_len, "\r\n", 2) == 0) { msg->bm.part[n].len = part_len; msg->bm.part[n].data = p + _len + 2; n++; msg->bm.n = n; } else { return -1; } handle_len = handle_len + _len + 2 + part_len + 2; reserve_len = len - handle_len; p = pp + handle_len; if (reserve_len >=2 && strncmp(p, "\r\n", 2) == 0) { if (strncmp(msg->bm.part[0].data, "keepalive", strlen("keepalive")) == 0) { *type = BUSCLIENT_KEEPALIVE; } if (strncmp(msg->bm.part[0].data, "request", strlen("request")) == 0) { *type = BUSCLIENT_RPC_REQUEST; } if (strncmp(msg->bm.part[0].data, "response", strlen("response")) == 0) { *type = BUSCLIENT_RPC_RESPONSE; } if (strncmp(msg->bm.part[0].data, "publish", strlen("publish")) == 0) { *type = BUSCLIENT_RECV_TOPIC; } return handle_len + 2; } } return -1; } static void busclient_mg_send(struct mg_connection *nc, const char *data, int len) { char tmp[10] = { 0 }; int _len = 0; _len = sprintf(tmp, "%d", len); mg_send(nc, tmp, _len); mg_send(nc, "\r\n", 2); mg_send(nc, data, len); mg_send(nc, "\r\n", 2); } static void busclient_multipart_send(struct mg_connection *nc, struct multipart *bm) { for (int i = 0; i < bm->n; i++) { busclient_mg_send(nc, bm->part[i].data, bm->part[i].len); } mg_send(nc, "\r\n", 2); } static void handle_multipart_msg(struct mg_connection *nc, struct message *msg) { if (!strncmp(msg->bm.part[0].data, "request", msg->bm.part[0].len)) { if (!strncmp(msg->bm.part[1].data, "/bus/join", msg->bm.part[1].len)) { struct multipart m = {1, { {strlen("response"), "response"} }}; busclient_multipart_send(nc, &m); } else if (!strncmp(msg->bm.part[1].data, "/bus/subscribe", msg->bm.part[1].len)) { struct multipart m = {1, { {strlen("response"), "response"} }}; busclient_multipart_send(nc, &m); } } else if (!strncmp(msg->bm.part[0].data, "publish", msg->bm.part[0].len)) { if (!strncmp(msg->bm.part[1].data, "ui.control.topics", msg->bm.part[1].len)) { if (user_cb) { user_cb("ui.control.topics", msg->bm.part[2].data, msg->bm.part[2].len, user); } } } } static void ev_handler(struct mg_connection *nc, int ev, void *p) { struct mbuf *io = &nc->recv_mbuf; (void) p; switch (ev) { case MG_EV_RECV: conn = nc; // receive multipart int len = 0, type = 0; struct message msg; while (1) { len = busclient_parse_multipart_msg(nc, &msg, &type); if (len == -1 || type == 0) break; handle_multipart_msg(nc, &msg); mbuf_remove(&nc->recv_mbuf, len); } break; case MG_EV_TIMER: { struct multipart *m = (struct multipart *)p; busclient_multipart_send(nc, m); break; } default: break; } } void busserver_run(const char *addr, event_cb cb, void *u) { // struct mg_mgr mgr; mg_mgr_init(&mgr, NULL); mg_bind(&mgr, addr, ev_handler); user_cb = cb; user = u; for (;;) { mg_mgr_poll(&mgr, 100); } mg_mgr_free(&mgr); } int busserver_send_msg(const char *topic, const char *data) { if (!topic) return -1; struct multipart m = {3, { {strlen("publish"), "publish"}, {strlen(topic), topic}, {strlen(data), data} }}; if (conn) ev_handler(conn, MG_EV_TIMER, &m); return 0; }