/* ::cortex::web::SockJsServer::Connection::send(string msg) */ cx_void web_SockJsServer_Connection_send(web_SockJsServer_Connection _this, cx_string msg) { /* $begin(::cortex::web::SockJsServer::Connection::send) */ int escapedLength; cx_string sockJsMsg; /* Escape & pack message in SockJS header */ escapedLength = stresc(NULL, 0, msg); sockJsMsg = cx_malloc(escapedLength + strlen("a[\"\"]") + 1); sprintf(sockJsMsg, "a[\"%*s\"]", escapedLength, " "); stresc(sockJsMsg + 3, escapedLength, msg); mg_websocket_printf((struct mg_connection *)_this->conn, WEBSOCKET_OPCODE_TEXT, sockJsMsg); cx_dealloc(sockJsMsg); /* $end */ }
static int ws_send(lua_State *L) { struct mg_context *ctx = luaL_checkudata(L, 1, MONGOOSE_LUA); const char* key = luaL_checkstring(L, 2); size_t len; const char* data = luaL_tolstring(L, 3, &len); struct mg_connection *c = NULL; for (c = mg_next(ctx->server, NULL); c != NULL; c = mg_next(ctx->server, c)) { if (c->is_websocket && !strncmp(c->connection_param, key, 24)) { mg_websocket_printf(c, WEBSOCKET_OPCODE_TEXT, data); break; } } return MG_TRUE; }
static int web_SockJsServer_request(struct mg_connection *conn, enum mg_event ev) { int result = MG_TRUE; web_SockJsServer _this = web_SockJsServer(conn->server_param); switch (ev) { case MG_AUTH: break; case MG_WS_CONNECT: /* Send open message fast since SockJS uses this to determine latency */ mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "o"); web_SockJsServer_open(_this, conn); break; case MG_CLOSE: web_SockJsServer_close(_this, conn); break; case MG_REQUEST: if (conn->is_websocket) { web_SockJsServer_message(_this, conn); } else { if (!strcmp(conn->uri, "/sockjs/info")) { mg_send_header(conn, "Access-Control-Allow-Origin", "*"); mg_printf_data( conn, "{\"websocket\":true,\"origins\":[\"*:*\"],\"cookie_needed\":false,\"entropy\":%u}", 10000000000 * rand()); } } break; case MG_HTTP_ERROR: result = MG_FALSE; break; case MG_POLL: result = MG_FALSE; break; case MG_CONNECT: case MG_WS_HANDSHAKE: case MG_REPLY: case MG_RECV: result = MG_FALSE; break; } return result; }
static int ev_handler(struct mg_connection *conn, enum mg_event ev) { if (ev == MG_REQUEST) { if (conn->is_websocket) { // This handler is called for each incoming websocket frame, one or more // times for connection lifetime. // Echo websocket data back to the client. return conn->content_len == 4 && !memcmp(conn->content, "exit", 4) ? MG_FALSE : MG_TRUE; } else { web_engine *engine = static_cast<web_engine *>(conn->server_param); return engine->begin_request_handler(conn); } } else if (ev== MG_WS_CONNECT) { // New websocket connection. Send connection ID back to the client. mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "update_machine"); return MG_FALSE; } else if (ev == MG_AUTH) { return MG_TRUE; } else { return MG_FALSE; } }
static void handle_websocket_message(struct mg_connection *conn) { struct conn_data *d = (struct conn_data *) conn->connection_param; struct mg_connection *c; printf("[%.*s]\n", (int) conn->content_len, conn->content); if (conn->content_len > 5 && !memcmp(conn->content, "join ", 5)) { // Client joined new room d->room = conn->content[5]; } else if (conn->content_len > 4 && !memcmp(conn->content, "msg ", 4) && d->room != 0 && d->room != '?') { // Client has sent a message. Push this message to all clients // that are subscribed to the same room as client for (c = mg_next(s_server, NULL); c != NULL; c = mg_next(s_server, c)) { struct conn_data *d2 = (struct conn_data *) c->connection_param; if (!c->is_websocket || d2->room != d->room) continue; mg_websocket_printf(c, WEBSOCKET_OPCODE_TEXT, "msg %c %p %.*s", (char) d->room, conn, conn->content_len - 4, conn->content + 4); } } }
/* ::cortex::web::SockJsServer::poll() */ cx_void web_SockJsServer_poll(web_SockJsServer _this) { /* $begin(::cortex::web::SockJsServer::poll) */ struct mg_server *server = (struct mg_server *)_this->server; mg_poll_server(server, _this->pollTimemoutMillis); _this->timeElapsed += _this->pollTimemoutMillis; /* Send heartbeats for all live connections every n seconds */ if (_this->timeElapsed >= (WEB_SOCKJSSERVER_DEFAULT_HEARTBEAT_TIMEOUT * 1000)) { cx_ll scope = cx_scopeClaim(_this); cx_iter iter = cx_llIter(scope); while (cx_iterHasNext(&iter)) { cx_object o = cx_iterNext(&iter); if (cx_instanceof(cx_type(web_SockJsServer_Connection_o), o)) { web_SockJsServer_Connection c = web_SockJsServer_Connection(o); mg_websocket_printf((struct mg_connection *)c->conn, WEBSOCKET_OPCODE_TEXT, "h"); } } cx_scopeRelease(scope); _this->timeElapsed = 0; } /* $end */ }
static int ev_handler(struct mg_connection *conn, enum mg_event ev) { switch (ev) { case MG_REQUEST: if (conn->is_websocket) { handle_websocket_message(conn); return MG_TRUE; } else { mg_send_file(conn, "webchat.html", NULL); // Return MG_MORE after! return MG_MORE; } case MG_WS_CONNECT: // New websocket connection. Send connection ID back to the client. conn->connection_param = calloc(1, sizeof(struct conn_data)); mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "id %p", conn); return MG_FALSE; case MG_CLOSE: free(conn->connection_param); return MG_TRUE; case MG_AUTH: return MG_TRUE; default: return MG_FALSE; } }