mirror of
https://github.com/holub/mame
synced 2025-06-05 20:33:45 +03:00
Updated mongoose and fixed initial websocket connecte to client (nw)
This commit is contained in:
parent
ead56f4d3c
commit
84f70285df
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user