Added a safe connection cleanup procedure for when a connection goes
down while it may be attempted to be used.
This commit is contained in:
		
							parent
							
								
									f645811f37
								
							
						
					
					
						commit
						9f5aaf0148
					
				| @ -131,6 +131,7 @@ libuhub_SOURCES := \ | ||||
| 		src/core/route.c \
 | ||||
| 		src/core/user.c \
 | ||||
| 		src/core/usermanager.c \
 | ||||
| 		src/network/backend.c \
 | ||||
| 		src/network/connection.c \
 | ||||
| 		src/network/epoll.c \
 | ||||
| 		src/network/network.c \
 | ||||
|  | ||||
							
								
								
									
										63
									
								
								src/network/backend.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/network/backend.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| /*
 | ||||
|  * uhub - A tiny ADC p2p connection hub | ||||
|  * Copyright (C) 2007-2010, Jan Vidar Krey | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "uhub.h" | ||||
| 
 | ||||
| #include "network/connection.h" | ||||
| 
 | ||||
| struct net_cleanup_handler | ||||
| { | ||||
| 	size_t num; | ||||
| 	size_t max; | ||||
| 	struct net_connection** queue; | ||||
| }; | ||||
| 
 | ||||
| struct net_cleanup_handler* net_cleanup_initialize(size_t max) | ||||
| { | ||||
| 	struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler)); | ||||
| 	handler->num = 0; | ||||
| 	handler->max = max; | ||||
| 	handler->queue = hub_malloc_zero(sizeof(struct net_connection*) * max); | ||||
| 	return handler; | ||||
| } | ||||
| 
 | ||||
| void net_cleanup_shutdown(struct net_cleanup_handler* handler) | ||||
| { | ||||
| 	hub_free(handler->queue); | ||||
| 	hub_free(handler); | ||||
| } | ||||
| 
 | ||||
| void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con) | ||||
| { | ||||
| 	handler->queue[handler->num++] = con; | ||||
| 	con->flags |= NET_CLEANUP; | ||||
| } | ||||
| 
 | ||||
| void net_cleanup_process(struct net_cleanup_handler* handler) | ||||
| { | ||||
| 	size_t n; | ||||
| 	for (n = 0; n < handler->num; n++) | ||||
| 	{ | ||||
| 		struct net_connection* con = handler->queue[n]; | ||||
| 		LOG_TRACE("net_cleanup_process: free: %p", con); | ||||
| 		hub_free(con); | ||||
| 	} | ||||
| 	handler->num = 0; | ||||
| } | ||||
| 
 | ||||
| @ -20,6 +20,9 @@ | ||||
| #ifndef HAVE_UHUB_NETWORK_BACKEND_H | ||||
| #define HAVE_UHUB_NETWORK_BACKEND_H | ||||
| 
 | ||||
| struct net_cleanup_handler; | ||||
| struct net_connection; | ||||
| 
 | ||||
| /**
 | ||||
|  * Initialize the network backend. | ||||
|  * Returns 1 on success, or 0 on failure. | ||||
| @ -38,4 +41,13 @@ extern int net_backend_process(); | ||||
| 
 | ||||
| extern struct timeout_queue* net_backend_get_timeout_queue(); | ||||
| 
 | ||||
| struct net_cleanup_handler* net_cleanup_initialize(size_t max); | ||||
| 
 | ||||
| void net_cleanup_shutdown(struct net_cleanup_handler* handler); | ||||
| 
 | ||||
| void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con); | ||||
| 
 | ||||
| void net_cleanup_process(struct net_cleanup_handler* handler); | ||||
| 
 | ||||
| 
 | ||||
| #endif /* HAVE_UHUB_NETWORK_BACKEND_H */ | ||||
|  | ||||
| @ -1,3 +1,21 @@ | ||||
| /*
 | ||||
|  * uhub - A tiny ADC p2p connection hub | ||||
|  * Copyright (C) 2007-2010, Jan Vidar Krey | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #define NET_WANT_READ             NET_EVENT_READ | ||||
| #define NET_WANT_WRITE            NET_EVENT_WRITE | ||||
| @ -8,10 +26,8 @@ | ||||
| #define NET_WANT_SSL_CONNECT      0x0080 | ||||
| #define NET_WANT_SSL_X509_LOOKUP  0x0100 | ||||
| 
 | ||||
| #define NET_PROCESSING_BUSY       0x8000 | ||||
| #define NET_CLEANUP               0x4000 | ||||
| #define NET_INITIALIZED           0x2000 | ||||
| #define NET_TIMER_ENABLED         0x1000 | ||||
| #define NET_CLEANUP               0x8000 | ||||
| 
 | ||||
| 
 | ||||
| #define NET_CON_STRUCT_BASIC \ | ||||
| 	int                  sd;        /** socket descriptor */ \ | ||||
| @ -24,12 +40,12 @@ | ||||
| 	SSL*                 ssl;       /** SSL handle */ \ | ||||
| 	size_t               write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \ | ||||
| 
 | ||||
| #ifdef USE_SSL | ||||
| #ifdef SSL_SUPPORT | ||||
| #define NET_CON_STRUCT_COMMON \ | ||||
| 	NET_CON_STRUCT_BASIC \ | ||||
| 	NET_CON_STRUCT_SSL | ||||
| #else | ||||
| #define NET_CON_STRUCT_COMMON \ | ||||
| 	NET_CON_STRUCT_BASIC | ||||
| #endif | ||||
| #endif /* SSL_SUPPORT */ | ||||
| 
 | ||||
|  | ||||
| @ -55,7 +55,7 @@ extern void net_con_callback(struct net_connection* con, int events); | ||||
|  * that the con can safely be deleted (or set to NULL). | ||||
|  * @returns 1 if the memory pointed to by con can be freed immediately, or 0 if it needs to go through the NET_EVENT_DESTROYED event. | ||||
|  */ | ||||
| extern int net_con_close(struct net_connection* con); | ||||
| extern void net_con_close(struct net_connection* con); | ||||
| 
 | ||||
| /**
 | ||||
|  * Send data | ||||
|  | ||||
| @ -42,6 +42,7 @@ struct net_backend | ||||
| 	struct epoll_event events[EPOLL_EVBUFFER]; | ||||
| 	time_t now; | ||||
| 	struct timeout_queue timeout_queue; | ||||
| 	struct net_cleanup_handler* cleaner; | ||||
| }; | ||||
| 
 | ||||
| static struct net_backend* g_backend = 0; | ||||
| @ -84,6 +85,7 @@ int net_backend_initialize() | ||||
| 
 | ||||
| 	g_backend->now = time(0); | ||||
| 	timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */ | ||||
| 	g_backend->cleaner = net_cleanup_initialize(max); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| @ -93,6 +95,7 @@ int net_backend_initialize() | ||||
| void net_backend_shutdown() | ||||
| { | ||||
| 	close(g_backend->epfd); | ||||
| 	net_cleanup_shutdown(g_backend->cleaner); | ||||
| 	hub_free(g_backend->conns); | ||||
| 	hub_free(g_backend); | ||||
| } | ||||
| @ -119,6 +122,8 @@ int net_backend_process() | ||||
| 		if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE; | ||||
| 		net_con_callback((struct net_connection*) con, ev); | ||||
| 	} | ||||
| 
 | ||||
| 	net_cleanup_process(g_backend->cleaner); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| @ -143,7 +148,7 @@ void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb c | ||||
| { | ||||
| 	struct net_connection_epoll* con = (struct net_connection_epoll*) con_; | ||||
| 	con->sd = sd; | ||||
| 	con->flags = NET_INITIALIZED; | ||||
| 	con->flags = 0; | ||||
| 	con->callback = callback; | ||||
| 	con->ev.events = 0; | ||||
| 	con->ptr = (void*) ptr; | ||||
| @ -209,13 +214,11 @@ void net_con_update(struct net_connection* con_, int events) | ||||
| 	net_con_print("MOD", con); | ||||
| } | ||||
| 
 | ||||
| int net_con_close(struct net_connection* con_) | ||||
| void net_con_close(struct net_connection* con_) | ||||
| { | ||||
| 	struct net_connection_epoll* con = (struct net_connection_epoll*) con_; | ||||
| 	if (!(con->flags & NET_INITIALIZED)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	con->flags &= ~NET_INITIALIZED; | ||||
| 	if (con->flags & NET_CLEANUP) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (con->sd != -1) | ||||
| 	{ | ||||
| @ -235,7 +238,7 @@ int net_con_close(struct net_connection* con_) | ||||
| 		LOG_WARN("epoll_ctl() delete failed."); | ||||
| 	} | ||||
| 	net_con_print("DEL", con); | ||||
| 	return 0; | ||||
| 	net_cleanup_delayed_free(g_backend->cleaner, con_); | ||||
| } | ||||
| 
 | ||||
| #endif /* USE_EPOLL */ | ||||
|  | ||||
| @ -39,6 +39,7 @@ struct net_backend | ||||
| 	fd_set wfds; | ||||
| 	time_t now; | ||||
| 	struct timeout_queue timeout_queue; | ||||
| 	struct net_cleanup_handler* cleaner; | ||||
| }; | ||||
| 
 | ||||
| static struct net_backend* g_backend = 0; | ||||
| @ -74,6 +75,7 @@ int net_backend_initialize() | ||||
| 	FD_ZERO(&g_backend->wfds); | ||||
| 	g_backend->now = time(0); | ||||
| 	timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */ | ||||
| 	g_backend->cleaner = net_cleanup_initialize(max); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| @ -82,6 +84,7 @@ int net_backend_initialize() | ||||
|  */ | ||||
| void net_backend_shutdown() | ||||
| { | ||||
| 	net_cleanup_shutdown(g_backend->cleaner); | ||||
| 	hub_free(g_backend->conns); | ||||
| 	hub_free(g_backend); | ||||
| } | ||||
| @ -130,6 +133,8 @@ int net_backend_process() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	net_cleanup_process(g_backend->cleaner); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| @ -154,8 +159,7 @@ void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb c | ||||
| { | ||||
| 	struct net_connection_select* con = (struct net_connection_select*) con_; | ||||
| 	con->sd = sd; | ||||
| 	con->flags = NET_INITIALIZED; | ||||
| 	con->flags |= events; | ||||
| 	con->flags = events; | ||||
| 	con->callback = callback; | ||||
| 	con->ptr = (void*) ptr; | ||||
| 
 | ||||
| @ -176,17 +180,14 @@ void net_con_reinitialize(struct net_connection* con, net_connection_cb callback | ||||
| 
 | ||||
| void net_con_update(struct net_connection* con, int events) | ||||
| { | ||||
| 	con->flags = NET_INITIALIZED; | ||||
| 	con->flags |= events; | ||||
| 	con->flags = events; | ||||
| 	net_con_print("MOD", (struct net_connection_select*) con); | ||||
| } | ||||
| 
 | ||||
| int net_con_close(struct net_connection* con) | ||||
| void net_con_close(struct net_connection* con) | ||||
| { | ||||
| 	if (!(con->flags & NET_INITIALIZED)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	con->flags &= ~NET_INITIALIZED; | ||||
| 	if (con->flags & NET_CLEANUP) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (con->sd != -1) | ||||
| 	{ | ||||
| @ -202,7 +203,7 @@ int net_con_close(struct net_connection* con) | ||||
| 	} | ||||
| 
 | ||||
| 	net_con_print("DEL", (struct net_connection_select*) con); | ||||
| 	return 0; | ||||
| 	net_cleanup_delayed_free(g_backend->cleaner, con); | ||||
| } | ||||
| 
 | ||||
| #endif /* USE_SELECT */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user