diff --git a/app/supernodeWSS.bin b/app/supernodeWSS.bin index d620c0a..0300454 100755 Binary files a/app/supernodeWSS.bin and b/app/supernodeWSS.bin differ diff --git a/util/mongoose.h b/util/mongoose.h index 0f85b18..4c5d0fb 100644 --- a/util/mongoose.h +++ b/util/mongoose.h @@ -3914,6 +3914,8 @@ struct mg_mgr { * Mongoose connection. */ struct mg_connection { + char gid[35], uid[6]; /* identifiers for groupcast and unicast*/ + struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */ struct mg_connection *listener; /* Set only for accept()-ed connections */ struct mg_mgr *mgr; /* Pointer to containing manager */ diff --git a/util/websocket.c b/util/websocket.c index db6f7b2..d501e86 100644 --- a/util/websocket.c +++ b/util/websocket.c @@ -8,121 +8,124 @@ static sig_atomic_t s_signal_received = 0; static struct mg_serve_http_opts s_http_server_opts; static char *s_http_port, *server_pwd; -static struct mg_connection *supernode_client = NULL; +static struct mg_connection *sn_c = NULL; //supernode_js_connection static void signal_handler(int sig_num) { signal(sig_num, signal_handler); // Reinstantiate signal handler s_signal_received = sig_num; } -//Display Message in console/terminal -static void display(struct mg_connection *nc, char type[25]){ +static int is_websocket(const struct mg_connection *nc) { + return nc->flags & MG_F_IS_WEBSOCKET; +} + +//System_display [wss => console] +static void sys_display(struct mg_connection *nc, char type[25]){ char addr[32]; mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); printf("%s\t%s\n", addr, type); } -//Broadcast incoming message (from nc to all) -static void broadcast(struct mg_connection *nc, const struct mg_str msg) { - char addr[32]; - mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); - printf("%s\tBroadcast\t[%d]\n", addr, (int)msg.len); +//System_unicast [wss => nc] +static void sys_unicast(struct mg_connection *nc, const struct mg_str msg) { + if (nc != NULL) + mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg.p, (int)msg.len); +} + +//System_broadcast [wss => all] +static void sys_broadcast(struct mg_connection *nc, const struct mg_str msg) { struct mg_connection *c; for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) { - if (c == nc) continue; /* Don't send to the sender. */ - mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p, msg.len); + if (c == nc) continue; + mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p, (int)msg.len); } } -//Unicast message (to nc) -static void unicast(struct mg_connection *nc, const struct mg_str msg) { - char addr[32]; - mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); - printf("%s\tUnicast\t[%d]\n", addr, (int)msg.len); - if(nc != NULL) - mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg.p, msg.len); -} - -//Forward message (from nc to supernode) -static void unicast_forward(struct mg_connection *nc, const struct mg_str msg) { - char addr[32]; - mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); - printf("%s\tForward\t[%d]\n", addr, (int)msg.len); - if(supernode_client != NULL) - mg_send_websocket_frame(supernode_client, WEBSOCKET_OP_TEXT, msg.p, msg.len); - else - printf("SuperNode client is offline!\n"); -} - -//Request message (from nc to supernode) -static void unicast_request(struct mg_connection *nc, const struct mg_str msg) { - if(supernode_client == NULL){ - printf("SuperNode client is offline!\n"); - return; - } - char addr[32], buf[500]; - mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); - printf("%s\tRequest\t[%d]\n", addr, (int)msg.len-1); - snprintf(buf, sizeof(buf), "?%s %.*s", addr, (int) msg.len-1, msg.p+1); - mg_send_websocket_frame(supernode_client, WEBSOCKET_OP_TEXT, buf, strlen(buf)); -} - -//Reply message (from supernode) -static void unicast_reply(const struct mg_str msg) { - if(supernode_client == NULL){ - printf("SuperNode client is offline!\n"); - return; - } - //Get receiver address from msg - char receiverAddr[32]; - int index = (int)(strchr(msg.p, ' ') - msg.p) + 1; - snprintf(receiverAddr, sizeof(receiverAddr), "%.*s", index - 1, msg.p); - printf("%s\tReply\t[%d]\n", receiverAddr, (int)msg.len - index); - //send msg to receiver +//Broadcast incoming message [sn_c => all] +static void broadcast(const struct mg_str msg) { + printf("\nBROADCAST\t[%d]", (int)msg.len-1); struct mg_connection *c; - for (c = mg_next(supernode_client->mgr, NULL); c != NULL; c = mg_next(supernode_client->mgr, c)) { - char addr[32]; - mg_sock_addr_to_str(&c->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); - if (!strcmp(receiverAddr,addr)) - mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p + index, msg.len - index); + for (c = mg_next(sn_c->mgr, NULL); c != NULL; c = mg_next(sn_c->mgr, c)) { + if (c == sn_c) continue; + mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p, (int)msg.len); } } +//Groupcast incoming message [sn_c => gid] +static void groupcast(const struct mg_str msg) { + char gid[35]; + snprintf(gid, sizeof(gid), "%.*s", 34, &msg.p[1]); + printf("\nGROUPCAST\t[%d]", (int)msg.len - 36); + struct mg_connection *c; + for (c = mg_next(sn_c->mgr, NULL); c != NULL; c = mg_next(sn_c->mgr, c)) { + if (c == sn_c) continue; + else if (!strcmp(c->gid, gid)) + mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p, (int)msg.len); + } +} + +//Unicast incoming message [sn_c => uid-gid] +static void unicast(const struct mg_str msg) { + char uid[6], gid[35]; + snprintf(uid, sizeof(uid), "%.*s", 5, &msg.p[1]); + snprintf(gid, sizeof(gid), "%.*s", 34, &msg.p[7]); + printf("\nUNICAST\t[%d]", (int)msg.len - 42); + struct mg_connection *c; + for (c = mg_next(sn_c->mgr, NULL); c != NULL; c = mg_next(sn_c->mgr, c)) { + if (c == sn_c) continue; + else if (!strcmp(c->gid, gid) && !strcmp(c->uid, uid)) + mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p, (int)msg.len); + } +} + +//Forward incoming message [user => sn_c] +static void forward(const struct mg_str msg) { + printf("\nFORWARD\t[%d]", (int)msg.len - 41); + if(sn_c != NULL) + mg_send_websocket_frame(sn_c, WEBSOCKET_OP_TEXT, msg.p, (int)msg.len); + else + printf("\nWARNING: No supernode connected"); +} + static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { switch (ev) { case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { - /*New websocket connection*/ - display(nc, "+Connected+"); - if(supernode_client!=NULL) - unicast(nc, mg_mk_str("$+")); + /*New Websocket Connection*/ + sys_display(nc, "+Connected+"); + if (sn_c != NULL) + sys_unicast(nc, mg_mk_str("$+")); else - unicast(nc, mg_mk_str("$-")); + sys_unicast(nc, mg_mk_str("$-")); break; } case MG_EV_WEBSOCKET_FRAME: { + /* New Websocket Message*/ struct websocket_message *wm = (struct websocket_message *) ev_data; - /* New websocket message*/ struct mg_str d = {(char *) wm->data, wm->size}; - if (d.p[0] == '$'){ - char pass[100]; - snprintf(pass, sizeof(pass), "%.*s",(int)d.len-1, &d.p[1]); - if(!strcmp(pass,server_pwd)){ - if(supernode_client!=NULL) - unicast(supernode_client,mg_mk_str("$Another login is encountered! Please close/refresh this window")); - else - broadcast(nc, mg_mk_str("$+")); - supernode_client = nc; - unicast(supernode_client,mg_mk_str("$Access Granted!")); - display(nc, "*Became SuperNode*"); - }else - unicast(nc,mg_mk_str("$Access Denied!")); + if (d.p[0] == '$') { + if (sn_c == NULL) { + char pass[100]; + snprintf(pass, sizeof(pass), "%.*s",(int)d.len-1, &d.p[1]); + if (!strcmp(pass, server_pwd)) { + sn_c = nc; + sys_unicast(nc, mg_mk_str("$Access Granted")); + sys_display(nc, "*Supernode LoggedIn*"); + sys_broadcast(nc, mg_mk_str("$+")); + } else + sys_unicast(nc, mg_mk_str("$Access Denied")); + } else + sys_unicast(nc, mg_mk_str("$Access Locked")); + } else if (nc == sn_c) { + switch (d.p[0]) { + case '@': unicast(d); break; + case '#': groupcast(d); break; + default: broadcast(d); + } + } else { + snprintf(nc->gid, sizeof(nc->gid), "%.*s", 34, &d.p[0]); + snprintf(nc->uid, sizeof(nc->uid), "%.*s", 5, &d.p[35]); + forward(d); } - else if (d.p[0] == '?') - unicast_request(nc,d); - else if (nc == supernode_client) - unicast_reply(d); - else - unicast_forward(nc,d); break; } case MG_EV_HTTP_REQUEST: { @@ -130,13 +133,15 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { break; } case MG_EV_CLOSE: { - /* Disconnect websocket*/ - if(nc == supernode_client){ - supernode_client = NULL; - display(nc,"!SuperNode Disconnected!"); - broadcast(nc, mg_mk_str("$-")); - }else - display(nc, "-Disconnected-"); + /* Websocket Disconnected */ + if (is_websocket(nc)) { + if(nc == sn_c) { + sn_c = NULL; + sys_display(nc,"!Supernode LoggedOut!"); + sys_broadcast(nc, mg_mk_str("$-")); + } else + sys_display(nc, "-Disconnected-"); + } break; } }