diff --git a/docs/c-api/net.h/struct_mg_connection.md b/docs/c-api/net.h/struct_mg_connection.md index 9b301e9c..8b376fc3 100644 --- a/docs/c-api/net.h/struct_mg_connection.md +++ b/docs/c-api/net.h/struct_mg_connection.md @@ -14,8 +14,8 @@ signature: | size_t recv_mbuf_limit; /* Max size of recv buffer */ struct mbuf recv_mbuf; /* Received data */ struct mbuf send_mbuf; /* Data scheduled for sending */ - time_t last_io_time; /* Timestamp of the last socket IO */ - double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ + time_t last_io_time; /* Timestamp of the last socket IO */ + double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ #if MG_ENABLE_SSL void *ssl_if_data; /* SSL library data. */ #endif diff --git a/examples/tun/Makefile b/examples/tun/Makefile deleted file mode 100644 index 986cfcab..00000000 --- a/examples/tun/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -PROG = tun -MODULE_CFLAGS = -include ../examples.mk diff --git a/examples/tun/tun.c b/examples/tun/tun.c deleted file mode 100644 index f4ce21b5..00000000 --- a/examples/tun/tun.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "mongoose.h" - -static const char *s_local_port = ":8001"; -static const char *s_dispatcher = "ws://foo:bar@localhost:8000"; - -void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { - struct http_message *hm = (struct http_message *) ev_data; - int i; - switch (ev) { - case MG_EV_ACCEPT: - fprintf(stderr, "HTTP accept. nc=%p\n", nc); - break; - case MG_EV_RECV: - fprintf(stderr, "recvd: %d bytes\n", *(int *) ev_data); - break; - case MG_EV_HTTP_REQUEST: - fprintf(stderr, "HTTP got request. nc=%p path=%.*s\n", nc, - (int) hm->uri.len, hm->uri.p); - - mg_printf(nc, "%s", - "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); - - for (i = 0; i < 10; i++) { - mg_printf_http_chunk(nc, "OK %d\n", i); - } - mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */ - nc->flags |= MG_F_SEND_AND_CLOSE; - break; - case MG_EV_CLOSE: - fprintf(stderr, "HTTP close\n"); - default: - break; - } -} - -int main(int argc, char **argv) { - struct mg_mgr mgr; - struct mg_connection *nc; - int i; - - mg_mgr_init(&mgr, NULL); - - /* Parse command line arguments */ - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-D") == 0) { - mgr.hexdump_file = argv[++i]; - } else if (strcmp(argv[i], "-l") == 0) { - s_local_port = argv[++i]; - } else if (strcmp(argv[i], "-d") == 0) { - s_dispatcher = argv[++i]; - } - } - - if ((nc = mg_bind(&mgr, s_dispatcher, ev_handler)) == NULL) { - fprintf(stderr, "Cannot create tunneled listening socket on [%s]\n", - s_dispatcher); - exit(EXIT_FAILURE); - } - mg_set_protocol_http_websocket(nc); - fprintf(stderr, "Tun listener: %p\n", nc); - - if ((nc = mg_bind(&mgr, s_local_port, ev_handler)) == NULL) { - fprintf(stderr, "Cannot bind to local port %s\n", s_local_port); - exit(EXIT_FAILURE); - } - mg_set_protocol_http_websocket(nc); - fprintf(stderr, "Local listening connection: %p\n", nc); - - for (;;) { - mg_mgr_poll(&mgr, 1000); - } -} diff --git a/mongoose.c b/mongoose.c index 7cf2dcdc..1daa5563 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1871,6 +1871,8 @@ int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame); void mg_tun_send_frame(struct mg_connection *ws, uint32_t stream_id, uint8_t type, uint8_t flags, struct mg_str msg); +void mg_tun_destroy_client(struct mg_tun_client *client); + #ifdef __cplusplus } #endif /* __cplusplus */ @@ -3783,10 +3785,13 @@ int mg_tun_if_create_conn(struct mg_connection *nc) { void mg_tun_if_destroy_conn(struct mg_connection *nc) { struct mg_tun_client *client = (struct mg_tun_client *) nc->iface->data; - uint32_t stream_id = (uint32_t)(uintptr_t) nc->mgr_data; - struct mg_str msg = {NULL, 0}; - if (client->disp) { + if (nc->flags & MG_F_LISTENING) { + mg_tun_destroy_client(client); + } else if (client->disp) { + uint32_t stream_id = (uint32_t)(uintptr_t) nc->mgr_data; + struct mg_str msg = {NULL, 0}; + LOG(LL_DEBUG, ("closing %zu:", stream_id)); mg_tun_send_frame(client->disp, stream_id, MG_TUN_DATA_FRAME, MG_TUN_F_END_STREAM, msg); @@ -11191,7 +11196,8 @@ static void mg_tun_close_all(struct mg_tun_client *client) { for (nc = client->mgr->active_connections; nc != NULL; nc = nc->next) { if (nc->iface == client->iface && !(nc->flags & MG_F_LISTENING)) { LOG(LL_DEBUG, ("Closing tunneled connection %p", nc)); - mg_close_conn(nc); + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + /* mg_close_conn(nc); */ } } } @@ -11257,10 +11263,16 @@ static void mg_tun_client_handler(struct mg_connection *nc, int ev, } case MG_EV_CLOSE: { LOG(LL_DEBUG, ("Closing all tunneled connections")); - mg_tun_close_all(client); - client->disp = NULL; - LOG(LL_INFO, ("Dispatcher connection is no more, reconnecting")); - mg_tun_reconnect(client); + /* + * The client might have been already freed when the listening socket is + * closed. + */ + if (client != NULL) { + mg_tun_close_all(client); + client->disp = NULL; + LOG(LL_INFO, ("Dispatcher connection is no more, reconnecting")); + mg_tun_reconnect(client); + } break; } default: @@ -11329,6 +11341,14 @@ static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr, return client; } +void mg_tun_destroy_client(struct mg_tun_client *client) { + /* the dispatcher connection handler will in turn close all tunnels */ + client->disp->flags |= MG_F_CLOSE_IMMEDIATELY; + /* this is used as a signal to other tun handlers that the party is over */ + client->disp->user_data = client->iface->data = NULL; + MG_FREE(client); +} + static struct mg_connection *mg_tun_do_bind(struct mg_tun_client *client, mg_event_handler_t handler, struct mg_bind_opts opts) { diff --git a/mongoose.h b/mongoose.h index 71cbf96b..1ba48c47 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3086,8 +3086,8 @@ struct mg_connection { size_t recv_mbuf_limit; /* Max size of recv buffer */ struct mbuf recv_mbuf; /* Received data */ struct mbuf send_mbuf; /* Data scheduled for sending */ - time_t last_io_time; /* Timestamp of the last socket IO */ - double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ + time_t last_io_time; /* Timestamp of the last socket IO */ + double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ #if MG_ENABLE_SSL void *ssl_if_data; /* SSL library data. */ #endif