diff options
author | 2014-06-12 07:03:23 +0000 | |
---|---|---|
committer | 2014-06-12 07:03:23 +0000 | |
commit | 84f70285df3341f6ed415ca5eb6b309db7866cc3 (patch) | |
tree | b1ca4748df7fdb85efc0fa83eb968ea90fed87e8 | |
parent | ead56f4d3c9cc174f96db341d01875bb53d276e6 (diff) |
Updated mongoose and fixed initial websocket connecte to client (nw)
-rw-r--r-- | src/emu/luaengine.c | 2 | ||||
-rw-r--r-- | src/emu/webengine.c | 6 | ||||
-rw-r--r-- | src/lib/web/mongoose.c | 160 | ||||
-rw-r--r-- | src/lib/web/mongoose.h | 2 |
4 files changed, 93 insertions, 77 deletions
diff --git a/src/emu/luaengine.c b/src/emu/luaengine.c index 1be9e338232..ef4e5ee131d 100644 --- a/src/emu/luaengine.c +++ b/src/emu/luaengine.c @@ -570,6 +570,7 @@ void lua_engine::load_script(const char *filename) { int s = luaL_loadfile(m_lua_state, filename); report(s); + update_machine(); start(); } @@ -581,6 +582,7 @@ void lua_engine::load_string(const char *value) { int s = luaL_loadstring(m_lua_state, value); report(s); + update_machine(); start(); } diff --git a/src/emu/webengine.c b/src/emu/webengine.c index 6d9d7437132..2b961df87ee 100644 --- a/src/emu/webengine.c +++ b/src/emu/webengine.c @@ -276,8 +276,12 @@ static int ev_handler(struct mg_connection *conn, enum mg_event ev) { 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); + 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 { diff --git a/src/lib/web/mongoose.c b/src/lib/web/mongoose.c index 08338fbd60e..29f089044d6 100644 --- a/src/lib/web/mongoose.c +++ b/src/lib/web/mongoose.c @@ -222,6 +222,7 @@ int ns_server_poll(struct ns_server *, int milli); void ns_server_wakeup(struct ns_server *); void ns_server_wakeup_ex(struct ns_server *, ns_callback_t, void *, size_t); void ns_iterate(struct ns_server *, ns_callback_t cb, void *param); +struct ns_connection *ns_next(struct ns_server *, struct ns_connection *); struct ns_connection *ns_add_sock(struct ns_server *, sock_t sock, void *p); int ns_bind(struct ns_server *, const char *addr); @@ -676,8 +677,8 @@ void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags) { #endif } if (flags & 2) { - snprintf(buf + strlen(buf), len - (strlen(buf) + 1), ":%d", - (int) ntohs(sa.sin.sin_port)); + snprintf(buf + strlen(buf), len - (strlen(buf) + 1), "%s%d", + flags & 1 ? ":" : "", (int) ntohs(sa.sin.sin_port)); } } } @@ -861,6 +862,10 @@ int ns_server_poll(struct ns_server *server, int milli) { tv.tv_usec = (milli % 1000) * 1000; if (select((int) max_fd + 1, &read_set, &write_set, NULL, &tv) > 0) { + // select() might have been waiting for a long time, reset current_time + // now to prevent last_io_time being set to the past. + current_time = time(NULL); + // Accept new connections if (server->listening_sock != INVALID_SOCKET && FD_ISSET(server->listening_sock, &read_set)) { @@ -885,7 +890,6 @@ int ns_server_poll(struct ns_server *server, int milli) { for (conn = server->active_connections; conn != NULL; conn = tmp_conn) { tmp_conn = conn->next; - //DBG(("%p LOOP %p", conn, conn->ssl)); if (FD_ISSET(conn->sock, &read_set)) { conn->last_io_time = current_time; ns_read_from_socket(conn); @@ -979,6 +983,10 @@ struct ns_connection *ns_add_sock(struct ns_server *s, sock_t sock, void *p) { return conn; } +struct ns_connection *ns_next(struct ns_server *s, struct ns_connection *conn) { + return conn == NULL ? s->active_connections : conn->next; +} + void ns_iterate(struct ns_server *server, ns_callback_t cb, void *param) { struct ns_connection *conn, *tmp_conn; @@ -1656,7 +1664,7 @@ static void *push_to_stdin(void *arg) { static void *pull_from_stdout(void *arg) { struct threadparam *tp = (struct threadparam *)arg; - int k=0, stop = 0; + int k, stop = 0; DWORD n, sent; char buf[IOBUF_SIZE]; @@ -2704,6 +2712,12 @@ size_t mg_websocket_write(struct mg_connection* conn, int opcode, free(copy); } + // If we send closing frame, schedule a connection to be closed after + // data is drained to the client. + if (opcode == WEBSOCKET_OPCODE_CONNECTION_CLOSE) { + MG_CONN_2_CONN(conn)->ns_conn->flags |= NSF_FINISHED_SENDING_DATA; + } + return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len; } @@ -2734,6 +2748,7 @@ static void send_websocket_handshake_if_requested(struct mg_connection *conn) { if (call_user(MG_CONN_2_CONN(conn), MG_WS_HANDSHAKE) == MG_FALSE) { send_websocket_handshake(conn, key); } + call_user(MG_CONN_2_CONN(conn), MG_WS_CONNECT); } } @@ -3995,29 +4010,6 @@ static void handle_ssi_request(struct connection *conn, const char *path) { } #endif -static int parse_url(const char *url, char *proto, size_t plen, - char *host, size_t hlen, unsigned short *port) { - int n; - char fmt1[100], fmt2[100], fmt3[100]; - - *port = 80; - proto[0] = host[0] = '\0'; - - snprintf(fmt1, sizeof(fmt1), "%%%zu[a-z]://%%%zu[^: ]:%%hu%%n", plen, hlen); - snprintf(fmt2, sizeof(fmt2), "%%%zu[a-z]://%%%zu[^/ ]%%n", plen, hlen); - snprintf(fmt3, sizeof(fmt3), "%%%zu[^: ]:%%hu%%n", hlen); - - if (sscanf(url, fmt1, proto, host, port, &n) == 3 || - sscanf(url, fmt2, proto, host, &n) == 2) { - return n; - } else if (sscanf(url, fmt3, host, port, &n) == 2) { - proto[0] = '\0'; - return n; - } - - return 0; -} - static void proxy_request(struct ns_connection *pc, struct mg_connection *c) { int i, sent_close_header = 0; @@ -4042,16 +4034,50 @@ static void proxy_request(struct ns_connection *pc, struct mg_connection *c) { } +#ifdef NS_ENABLE_SSL +int mg_terminate_ssl(struct mg_connection *c, const char *cert) { + static const char ok[] = "HTTP/1.0 200 OK\r\n\r\n"; + struct connection *conn = MG_CONN_2_CONN(c); + int n; + SSL_CTX *ctx; + + DBG(("%p MITM", conn)); + SSL_library_init(); + if ((ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) return 0; + + SSL_CTX_use_certificate_file(ctx, cert, 1); + SSL_CTX_use_PrivateKey_file(ctx, cert, 1); + SSL_CTX_use_certificate_chain_file(ctx, cert); + + // When clear-text reply is pushed to client, switch to SSL mode. + n = send(conn->ns_conn->sock, ok, sizeof(ok) - 1, 0); + DBG(("%p %lu %d SEND", c, sizeof(ok) - 1, n)); + conn->ns_conn->send_iobuf.len = 0; + conn->endpoint_type = EP_USER; // To keep-alive in close_local_endpoint() + close_local_endpoint(conn); // Clean up current CONNECT request + if ((conn->ns_conn->ssl = SSL_new(ctx)) != NULL) { + SSL_set_fd(conn->ns_conn->ssl, conn->ns_conn->sock); + } + SSL_CTX_free(ctx); + return 1; +} +#endif + static void proxify_connection(struct connection *conn) { char proto[10], host[500], cert[500]; unsigned short port = 80; struct mg_connection *c = &conn->mg_conn; struct ns_server *server = &conn->server->ns_server; - struct ns_connection *pc; - int n, use_ssl; + struct ns_connection *pc = NULL; + int n = 0; + const char *url = c->uri; proto[0] = host[0] = cert[0] = '\0'; - n = parse_url(c->uri, proto, sizeof(proto), host, sizeof(host), &port); + if (sscanf(url, "%499[^: ]:%hu%n", host, &port, &n) != 2 && + sscanf(url, "%9[a-z]://%499[^: ]:%hu%n", proto, host, &port, &n) != 3 && + sscanf(url, "%9[a-z]://%499[^/ ]%n", proto, host, &n) != 2) { + n = 0; + } #ifdef NS_ENABLE_SSL // Find out whether we should be in the MITM mode @@ -4060,24 +4086,24 @@ static void proxify_connection(struct connection *conn) { int host_len = strlen(host); struct vec a, b; - while ((certs = next_option(certs, &a, &b)) != NULL) { - if (a.len == host_len && mg_strncasecmp(a.ptr, host, a.len) == 0) { - snprintf(cert, sizeof(cert), "%.*s", b.len, b.ptr); - break; - } + while (conn->ns_conn->ssl == NULL && port != 80 && + (certs = next_option(certs, &a, &b)) != NULL) { + if (a.len != host_len || mg_strncasecmp(a.ptr, host, a.len)) continue; + snprintf(cert, sizeof(cert), "%.*s", b.len, b.ptr); + mg_terminate_ssl(&conn->mg_conn, cert); + return; } } #endif - use_ssl = port != 80 && cert[0] != '\0'; - if (n > 0 && - (pc = ns_connect(server, host, port, use_ssl, conn)) != NULL) { + (pc = ns_connect(server, host, port, conn->ns_conn->ssl != NULL, + conn)) != NULL) { // Interlink two connections pc->flags |= MG_PROXY_CONN; conn->endpoint_type = EP_PROXY; conn->endpoint.nc = pc; - DBG(("%p [%s] -> %p %d", conn, c->uri, pc, use_ssl)); + DBG(("%p [%s] -> %p %p", conn, c->uri, pc, conn->ns_conn->ssl)); if (strcmp(c->request_method, "CONNECT") == 0) { // For CONNECT request, reply with 200 OK. Tunnel is established. @@ -4085,34 +4111,6 @@ static void proxify_connection(struct connection *conn) { conn->request_len = 0; free(conn->request); conn->request = NULL; -#ifdef NS_ENABLE_SSL - if (use_ssl) { - SSL_CTX *ctx; - - DBG(("%s", "Triggering MITM mode: terminating SSL connection")); - SSL_library_init(); - ctx = SSL_CTX_new(SSLv23_server_method()); - - if (ctx == NULL) { - pc->flags |= NSF_CLOSE_IMMEDIATELY; - } else { - SSL_CTX_use_certificate_file(ctx, cert, 1); - SSL_CTX_use_PrivateKey_file(ctx, cert, 1); - SSL_CTX_use_certificate_chain_file(ctx, cert); - - // When clear-text reply is pushed to client, switch to SSL mode. - n = send(conn->ns_conn->sock, conn->ns_conn->send_iobuf.buf, - conn->ns_conn->send_iobuf.len, 0); - DBG(("%p %lu %d SEND", c, conn->ns_conn->send_iobuf.len, n)); - conn->ns_conn->send_iobuf.len = 0; - if ((conn->ns_conn->ssl = SSL_new(ctx)) != NULL) { - //SSL_set_fd((SSL *) c->connection_param, conn->ns_conn->sock); - SSL_set_fd(conn->ns_conn->ssl, conn->ns_conn->sock); - } - SSL_CTX_free(ctx); - } - } -#endif } else { // For other methods, forward the request to the target host. c->uri += n; @@ -4187,9 +4185,11 @@ void mg_send_file(struct mg_connection *c, const char *file_name) { #endif // !MONGOOSE_NO_FILESYSTEM static void open_local_endpoint(struct connection *conn, int skip_user) { +#ifndef MONGOOSE_NO_FILESYSTEM char path[MAX_PATH_SIZE]; file_stat_t st; int exists = 0; +#endif // If EP_USER was set in a prev call, reset it conn->endpoint_type = EP_NONE; @@ -4302,10 +4302,9 @@ static void try_parse(struct connection *conn) { static void do_proxy(struct connection *conn) { if (conn->request_len == 0) { - DBG(("%p parsing", conn)); try_parse(conn); - if (conn->request_len > 0 && - call_user(conn, MG_REQUEST) == MG_FALSE) { + DBG(("%p parsing -> %d", conn, conn->request_len)); + if (conn->request_len > 0 && call_user(conn, MG_REQUEST) == MG_FALSE) { proxy_request(conn->endpoint.nc, &conn->mg_conn); } else if (conn->request_len < 0) { ns_forward(conn->ns_conn, conn->endpoint.nc); @@ -4564,6 +4563,15 @@ static void iter(struct ns_connection *nsconn, enum ns_event ev, void *param) { } } +struct mg_connection *mg_next(struct mg_server *s, struct mg_connection *c) { + struct connection *conn = MG_CONN_2_CONN(c); + struct ns_connection *nc = ns_next(&s->ns_server, + c == NULL ? NULL : conn->ns_conn); + + return nc == NULL ? NULL : + & ((struct connection *) nc->connection_data)->mg_conn; +} + // Apply function to all active connections. void mg_iterate_over_connections(struct mg_server *server, mg_handler_t cb, void *param) { @@ -4730,12 +4738,10 @@ const char *mg_set_option(struct mg_server *server, const char *name, if (port < 0) { error_msg = "Cannot bind to port"; } else { - if (!strcmp(value, "0")) { - char buf[10]; - mg_snprintf(buf, sizeof(buf), "%d", port); - free(*v); - *v = mg_strdup(buf); - } + char buf[100]; + ns_sock_to_str(server->ns_server.listening_sock, buf, sizeof(buf), 2); + free(*v); + *v = mg_strdup(buf); } #ifndef _WIN32 } else if (ind == RUN_AS_USER) { @@ -4829,7 +4835,9 @@ static void hexdump(struct ns_connection *nc, const char *path, static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { struct connection *conn = (struct connection *) nc->connection_data; +#ifndef MONGOOSE_NO_FILESYSTEM struct mg_server *server = (struct mg_server *) nc->server; +#endif // Send NS event to the handler. Note that call_user won't send an event // if conn == NULL. Therefore, repeat this for NS_ACCEPT event as well. diff --git a/src/lib/web/mongoose.h b/src/lib/web/mongoose.h index c1e1a374b13..c616be466d0 100644 --- a/src/lib/web/mongoose.h +++ b/src/lib/web/mongoose.h @@ -68,6 +68,7 @@ enum mg_event { MG_REPLY, // If callback returns MG_FALSE, Mongoose closes connection MG_CLOSE, // Connection is closed, callback return value is ignored MG_WS_HANDSHAKE, // New websocket connection, handshake request + MG_WS_CONNECT, // New websocket connection established MG_HTTP_ERROR // If callback returns MG_FALSE, Mongoose continues with err }; typedef int (*mg_handler_t)(struct mg_connection *, enum mg_event); @@ -92,6 +93,7 @@ const char *mg_get_option(const struct mg_server *server, const char *name); void mg_set_listening_socket(struct mg_server *, int sock); int mg_get_listening_socket(struct mg_server *); void mg_iterate_over_connections(struct mg_server *, mg_handler_t, void *); +struct mg_connection *mg_next(struct mg_server *, struct mg_connection *); void mg_wakeup_server(struct mg_server *); void mg_wakeup_server_ex(struct mg_server *, mg_handler_t, const char *, ...); struct mg_connection *mg_connect(struct mg_server *, const char *, int, int); |