/* Main event handler. Sends websocket frames and receives control commands */ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { struct websocket_message *wm = (struct websocket_message *) ev_data; switch (ev) { case MG_EV_CONNECT: printf("Reconnect: %s\n", *(int *) ev_data == 0 ? "ok" : "failed"); if (*(int *) ev_data == 0) { /* * Tune the tcp send buffer size, so that we can skip frames * when the connection is congested. This helps maintaining a * reasonable latency. */ int sndbuf_size = 512; if (setsockopt(nc->sock, SOL_SOCKET, SO_SNDBUF, (void *) &sndbuf_size, sizeof(int)) == -1) { perror("failed to tune TCP send buffer size\n"); } mg_send_websocket_handshake(nc, "/stream", NULL); } break; case MG_EV_CLOSE: printf("Connection %p closed\n", nc); client = NULL; break; case MG_EV_POLL: send_mjpg_frame(nc, s_mjpg_file); break; case MG_EV_WEBSOCKET_FRAME: printf("Got control command: [%.*s]\n", (int) wm->size, wm->data); perform_control_command((const char *) wm->data, wm->size); break; } }
struct mg_connection * TestHttpClient::Connect(const std::string & address, const std::string & uri) { boost::mutex mutex; boost::condition_variable cond; struct mg_connection * conn; on_connected_ = [&](struct mg_connection * ws) { assert(conn == ws); boost::mutex::scoped_lock lock(mutex); cond.notify_one(); }; conn = mg_connect(&mgr_, address.c_str(), callback); mg_set_protocol_http_websocket(conn); mg_send_websocket_handshake(conn, uri.c_str(), nullptr); const boost::chrono::seconds d(10); boost::mutex::scoped_lock lock(mutex); const auto timeout = cond.wait_for(lock, d); if (boost::cv_status::timeout == timeout) { mg_send_websocket_frame(conn, WEBSOCKET_OP_CLOSE, nullptr, 0); return nullptr; } return conn; }
void clubby_proto_handler(struct mg_connection *nc, int ev, void *ev_data) { struct clubby_event evt; switch (ev) { case MG_EV_CONNECT: { evt.ev = CLUBBY_NET_CONNECT; evt.net_connect.success = (*(int *) ev_data == 0); LOG(LL_DEBUG, ("CONNECT (%d)", evt.net_connect.success)); s_clubby_cb(&evt); if (evt.net_connect.success) { char *proto = NULL; (void) asprintf( &proto, "Sec-WebSocket-Protocol: %s\r\n" "Sec-WebSocket-Extensions: %s-encoding; in=json; out=ubjson\r\n", WS_PROTOCOL, WS_PROTOCOL); mg_send_websocket_handshake(nc, "/", proto); free(proto); } break; } case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { LOG(LL_DEBUG, ("HANDSHAKE DONE")); nc->flags |= MG_F_CLUBBY_CONNECTED; evt.ev = CLUBBY_CONNECT; s_clubby_cb(&evt); break; } case MG_EV_WEBSOCKET_FRAME: { struct websocket_message *wm = (struct websocket_message *) ev_data; LOG(LL_DEBUG, ("GOT FRAME (%d): %.*s", (int) wm->size, (int) wm->size, wm->data)); evt.frame.data.p = (char *) wm->data; /* * Mostly debug event, CLUBBY_REQUEST_RECEIVED and * CLUBY_RESPONSE_RECEIVED will be send as well */ evt.frame.data.len = wm->size; evt.ev = CLUBBY_FRAME; s_clubby_cb(&evt); clubby_proto_handle_frame(evt.frame.data); break; } case MG_EV_CLOSE: LOG(LL_DEBUG, ("CLOSE")); nc->flags &= ~MG_F_CLUBBY_CONNECTED; s_clubby_conn = NULL; evt.ev = CLUBBY_DISCONNECT; s_clubby_cb(&evt); break; } }
static void ws_ev_handler(struct mg_connection *nc, int ev, void *ev_data) { struct websocket_message *wm = (struct websocket_message *) ev_data; struct user_data *ud = (struct user_data *) nc->user_data; struct v7 *v7 = ud->v7; switch (ev) { case NS_CONNECT: if (*(int *) ev_data == 0) { char *proto = NULL; if (ud->proto != NULL) { int tmp = asprintf(&proto, "Sec-WebSocket-Protocol: %s\n", ud->proto); (void) tmp; /* Shutup compiler */ } mg_send_websocket_handshake(nc, "/", proto); if (proto != NULL) { free(proto); } } else { invoke_cb(ud, "onerror", v7_create_null()); } break; case NS_WEBSOCKET_HANDSHAKE_DONE: v7_set(v7, ud->ws, "_nc", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(nc)); invoke_cb(ud, "onopen", v7_create_null()); break; case NS_WEBSOCKET_FRAME: { v7_val_t ev, data; ev = v7_create_object(v7); v7_own(v7, &ev); data = v7_create_string(v7, (char *) wm->data, wm->size, 1); v7_set(v7, ev, "data", ~0, 0, data); invoke_cb(ud, "onmessage", ev); v7_disown(v7, &ev); break; } case NS_CLOSE: invoke_cb(ud, "onclose", v7_create_null()); nc->user_data = NULL; v7_set(v7, ud->ws, "_nc", ~0, V7_PROPERTY_HIDDEN, v7_create_undefined()); v7_disown(v7, &ud->ws); free(ud); break; } }