diff --git a/mongoose.c b/mongoose.c index fbbb495827a030b882ff3d0d4d9f7fea30326ae0..4fa0a9d4ee3c84e2634b379f8b5fa8fb5dadcf55 100644 --- a/mongoose.c +++ b/mongoose.c @@ -134,6 +134,7 @@ struct linked_list_link { struct linked_list_link *prev, *next; }; #define MAX_CGI_ENVIR_VARS 64 #define ENV_EXPORT_TO_CGI "MONGOOSE_CGI" #define PASSWORDS_FILE_NAME ".htpasswd" +#define WEBSOCKET_PING_INTERVAL_SECONDS 5 // Extra HTTP headers to send in every static file reply #if !defined(EXTRA_HTTP_HEADERS) @@ -220,7 +221,7 @@ struct connection { union endpoint endpoint; enum endpoint_type endpoint_type; time_t birth_time; - time_t expire_time; + time_t last_activity_time; char *path_info; char *request; int64_t num_bytes_sent; // Total number of bytes sent @@ -432,6 +433,7 @@ static void send_http_error(struct connection *conn, int code) { switch (code) { case 201: message = "Created"; break; case 204: message = "No Content"; break; + case 304: message = "Not Modified"; break; case 400: message = "Bad Request"; break; case 403: message = "Forbidden"; break; case 404: message = "Not Found"; break; @@ -1474,6 +1476,14 @@ static void send_websocket_handshake_if_requested(struct mg_connection *conn) { send_websocket_handshake(conn, key); } } + +static void ping_idle_websocket_connection(struct connection *conn, time_t t) { + if (t - conn->last_activity_time > WEBSOCKET_PING_INTERVAL_SECONDS) { + mg_websocket_write(&conn->mg_conn, 0x9, "", 0); + } +} +#else +#define ping_idle_websocket_connection(conn, t) #endif // !NO_WEBSOCKET static int is_error(int n) { @@ -3037,7 +3047,7 @@ void mg_poll_server(struct mg_server *server, int milliseconds) { struct timeval tv; fd_set read_set, write_set; sock_t max_fd = -1; - time_t current_time = time(NULL), expire_time = current_time + + time_t current_time = time(NULL), expire_time = current_time - atoi(server->config_options[IDLE_TIMEOUT_MS]) / 1000; if (server->listening_sock == INVALID_SOCKET) return; @@ -3076,8 +3086,7 @@ void mg_poll_server(struct mg_server *server, int milliseconds) { // Accept new connections if (FD_ISSET(server->listening_sock, &read_set)) { while ((conn = accept_new_connection(server)) != NULL) { - conn->birth_time = current_time; - conn->expire_time = expire_time; + conn->birth_time = conn->last_activity_time = current_time; } } @@ -3085,7 +3094,7 @@ void mg_poll_server(struct mg_server *server, int milliseconds) { LINKED_LIST_FOREACH(&server->active_connections, lp, tmp) { conn = LINKED_LIST_ENTRY(lp, struct connection, link); if (FD_ISSET(conn->client_sock, &read_set)) { - conn->expire_time = expire_time; + conn->last_activity_time = current_time; read_from_client(conn); } if (conn->endpoint_type == EP_CGI && @@ -3093,7 +3102,7 @@ void mg_poll_server(struct mg_server *server, int milliseconds) { read_from_cgi(conn); } if (FD_ISSET(conn->client_sock, &write_set)) { - conn->expire_time = expire_time; + conn->last_activity_time = current_time; write_to_client(conn); } } @@ -3102,7 +3111,8 @@ void mg_poll_server(struct mg_server *server, int milliseconds) { // Close expired connections and those that need to be closed LINKED_LIST_FOREACH(&server->active_connections, lp, tmp) { conn = LINKED_LIST_ENTRY(lp, struct connection, link); - if (conn->flags & CONN_CLOSE || current_time > conn->expire_time) { + ping_idle_websocket_connection(conn, current_time); + if (conn->flags & CONN_CLOSE || conn->last_activity_time < expire_time) { close_conn(conn); } }