diff --git a/docs/c-api/net.h/struct_mg_connection.md b/docs/c-api/net.h/struct_mg_connection.md index 8b376fc3..a439ccc9 100644 --- a/docs/c-api/net.h/struct_mg_connection.md +++ b/docs/c-api/net.h/struct_mg_connection.md @@ -48,11 +48,12 @@ signature: | #define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */ /* Flags that are settable by user */ - #define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */ - #define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */ - #define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */ - #define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */ - #define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */ + #define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */ + #define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */ + #define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */ + #define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */ + #define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */ + #define MG_F_TUN_DO_NOT_RECONNECT (1 << 15) /* Don't reconnect tunnel */ #define MG_F_USER_1 (1 << 20) /* Flags left for application */ #define MG_F_USER_2 (1 << 21) diff --git a/mongoose.c b/mongoose.c index d94e14d2..2c5c0ce6 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1937,6 +1937,7 @@ struct mg_tun_client { struct mg_connection *disp; struct mg_connection *listener; + struct mg_connection *reconnect; }; #ifdef __cplusplus @@ -11207,7 +11208,7 @@ int mg_set_protocol_coap(struct mg_connection *nc) { /* Amalgamated: #include "mongoose/src/tun.h" */ /* Amalgamated: #include "mongoose/src/util.h" */ -static void mg_tun_reconnect(struct mg_tun_client *client); +static void mg_tun_reconnect(struct mg_tun_client *client, int timeout); static void mg_tun_init_client(struct mg_tun_client *client, struct mg_mgr *mgr, struct mg_iface *iface, const char *dispatcher, @@ -11218,8 +11219,9 @@ static void mg_tun_init_client(struct mg_tun_client *client, struct mg_mgr *mgr, client->last_stream_id = 0; client->ssl = ssl; - client->disp = NULL; /* will be set by mg_tun_reconnect */ - client->listener = NULL; /* will be set by mg_do_bind */ + client->disp = NULL; /* will be set by mg_tun_reconnect */ + client->listener = NULL; /* will be set by mg_do_bind */ + client->reconnect = NULL; /* will be set by mg_tun_reconnect */ } void mg_tun_log_frame(struct mg_tun_frame *frame) { @@ -11318,7 +11320,8 @@ static void mg_tun_client_handler(struct mg_connection *nc, int ev, mg_tun_close_all(client); client->disp = NULL; LOG(LL_INFO, ("Dispatcher connection is no more, reconnecting")); - mg_tun_reconnect(client); + /* TODO(mkm): implement exp back off */ + mg_tun_reconnect(client, MG_TUN_RECONNECT_INTERVAL); } break; } @@ -11356,17 +11359,23 @@ void mg_tun_reconnect_ev_handler(struct mg_connection *nc, int ev, switch (ev) { case MG_EV_TIMER: - mg_tun_do_reconnect(client); + if (!(client->listener->flags & MG_F_TUN_DO_NOT_RECONNECT)) { + mg_tun_do_reconnect(client); + } else { + /* Reconnecting is suppressed, we'll check again at the next poll */ + mg_tun_reconnect(client, 0); + } break; } } -static void mg_tun_reconnect(struct mg_tun_client *client) { - struct mg_connection *nc; - nc = mg_add_sock(client->mgr, INVALID_SOCKET, mg_tun_reconnect_ev_handler); - nc->user_data = client; - /* TODO(mkm): implement exp back off */ - nc->ev_timer_time = mg_time() + MG_TUN_RECONNECT_INTERVAL; +static void mg_tun_reconnect(struct mg_tun_client *client, int timeout) { + if (client->reconnect == NULL) { + client->reconnect = + mg_add_sock(client->mgr, INVALID_SOCKET, mg_tun_reconnect_ev_handler); + client->reconnect->user_data = client; + } + client->reconnect->ev_timer_time = mg_time() + timeout; } static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr, @@ -11384,7 +11393,12 @@ static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr, mg_tun_init_client(client, mgr, iface, dispatcher, ssl); iface->data = client; - mg_tun_do_reconnect(client); + /* + * We need to give application a chance to set MG_F_TUN_DO_NOT_RECONNECT on a + * listening connection right after mg_tun_bind_opt() returned it, so we + * should use mg_tun_reconnect() here, instead of mg_tun_do_reconnect() + */ + mg_tun_reconnect(client, 0); return client; } @@ -11403,6 +11417,10 @@ void mg_tun_destroy_client(struct mg_tun_client *client) { client->disp->user_data = NULL; } + if (client != NULL && client->reconnect != NULL) { + client->reconnect->flags |= MG_F_CLOSE_IMMEDIATELY; + } + if (client != NULL && client->iface != NULL) { client->iface->data = NULL; } diff --git a/mongoose.h b/mongoose.h index e1dd584e..a853902a 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3160,11 +3160,12 @@ struct mg_connection { #define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */ /* Flags that are settable by user */ -#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */ -#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */ -#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */ -#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */ -#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */ +#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */ +#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */ +#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */ +#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */ +#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */ +#define MG_F_TUN_DO_NOT_RECONNECT (1 << 15) /* Don't reconnect tunnel */ #define MG_F_USER_1 (1 << 20) /* Flags left for application */ #define MG_F_USER_2 (1 << 21)