Added select() backend which can be used as a fallback if epoll is not available.
This commit is contained in:
		
							parent
							
								
									7e60919596
								
							
						
					
					
						commit
						2f09fcea84
					
				
							
								
								
									
										16
									
								
								GNUmakefile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								GNUmakefile
									
									
									
									
									
								
							@ -9,7 +9,6 @@ MV            := mv
 | 
			
		||||
RANLIB        := ranlib
 | 
			
		||||
CFLAGS        += -pipe -Wall
 | 
			
		||||
USE_SSL       ?= NO
 | 
			
		||||
USE_LIBEVENT  ?= NO
 | 
			
		||||
USE_BIGENDIAN ?= AUTO
 | 
			
		||||
BITS          ?= AUTO
 | 
			
		||||
SILENT        ?= YES
 | 
			
		||||
@ -63,9 +62,6 @@ else
 | 
			
		||||
	MSG_CLEAN="Clean as a whistle"
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# CFLAGS        += -I/source/libevent
 | 
			
		||||
# LDFLAGS       += -L/source/libevent
 | 
			
		||||
 | 
			
		||||
ifeq ($(RELEASE),YES)
 | 
			
		||||
CFLAGS        += -O3 -DNDEBUG
 | 
			
		||||
GIT_REVISION  ?= NO
 | 
			
		||||
@ -116,15 +112,6 @@ CFLAGS        += -DSSL_SUPPORT
 | 
			
		||||
LDLIBS        += -lssl
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(USE_LIBEVENT),YES)
 | 
			
		||||
CFLAGS        += -DUSE_LIBEVENT
 | 
			
		||||
LDLIBS        += -levent
 | 
			
		||||
ifneq ($(LIBEVENT_PATH),)
 | 
			
		||||
CFLAGS        += -I$(LIBEVENT_PATH)
 | 
			
		||||
LDFLAGS       += -L$(LIBEVENT_PATH)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(GIT_REVISION),YES)
 | 
			
		||||
CFLAGS        += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
 | 
			
		||||
endif
 | 
			
		||||
@ -146,8 +133,9 @@ libuhub_SOURCES := \
 | 
			
		||||
		src/core/usermanager.c \
 | 
			
		||||
		src/network/connection.c \
 | 
			
		||||
		src/network/epoll.c \
 | 
			
		||||
		src/network/libevent.c \
 | 
			
		||||
		src/network/network.c \
 | 
			
		||||
		src/network/select.c \
 | 
			
		||||
		src/network/timer.c \
 | 
			
		||||
		src/util/ipcalc.c \
 | 
			
		||||
		src/util/list.c \
 | 
			
		||||
		src/util/log.c \
 | 
			
		||||
 | 
			
		||||
@ -622,9 +622,6 @@ void hub_shutdown_service(struct hub_info* hub)
 | 
			
		||||
	LOG_DEBUG("hub_shutdown_service()");
 | 
			
		||||
 | 
			
		||||
	event_queue_shutdown(hub->queue);
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
	event_del(&hub->ev_accept);
 | 
			
		||||
#endif
 | 
			
		||||
	net_con_close(hub->server);
 | 
			
		||||
	hub_free(hub->server);
 | 
			
		||||
	uman_shutdown(hub);
 | 
			
		||||
 | 
			
		||||
@ -91,10 +91,6 @@ struct hub_logout_info
 | 
			
		||||
struct hub_info
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection* server;
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
	struct event ev_accept;
 | 
			
		||||
	struct event ev_timer;
 | 
			
		||||
#endif
 | 
			
		||||
	struct hub_stats stats;
 | 
			
		||||
	struct event_queue* queue;
 | 
			
		||||
	struct hub_config* config;
 | 
			
		||||
 | 
			
		||||
@ -70,28 +70,9 @@ void uman_print_stats(struct hub_info* hub)
 | 
			
		||||
		(int) hub->stats.net_rx_peak / 1024);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef USERMANAGER_TIMER
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
static void timer_statistics(int fd, short ev, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct hub_info* hub = (struct hub_info*) arg;
 | 
			
		||||
	struct timeval timeout = { TIMEOUT_STATS, 0 };
 | 
			
		||||
	uman_update_stats(hub);
 | 
			
		||||
	evtimer_set(&hub->ev_timer, timer_statistics, hub);
 | 
			
		||||
	evtimer_add(&hub->ev_timer, &timeout);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int uman_init(struct hub_info* hub)
 | 
			
		||||
{
 | 
			
		||||
	struct hub_user_manager* users = NULL;
 | 
			
		||||
#ifdef USERMANAGER_TIMER
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
	struct timeval timeout = { TIMEOUT_STATS, 0 };
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	if (!hub)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
@ -110,16 +91,6 @@ int uman_init(struct hub_info* hub)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hub->users = users;
 | 
			
		||||
 | 
			
		||||
#ifdef USERMANAGER_TIMER
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
	if (net_get_evbase())
 | 
			
		||||
	{
 | 
			
		||||
		evtimer_set(&hub->ev_timer, timer_statistics, hub);
 | 
			
		||||
		evtimer_add(&hub->ev_timer, &timeout);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
#endif // 0
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -129,13 +100,6 @@ int uman_shutdown(struct hub_info* hub)
 | 
			
		||||
	if (!hub || !hub->users)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
#ifdef USERMANAGER_TIMER
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
	if (evtimer_pending(&hub->ev_timer, 0))
 | 
			
		||||
		evtimer_del(&hub->ev_timer);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (hub->users->list)
 | 
			
		||||
	{
 | 
			
		||||
		list_clear(hub->users->list, &clear_user_list_callback);
 | 
			
		||||
@ -144,7 +108,6 @@ int uman_shutdown(struct hub_info* hub)
 | 
			
		||||
	sid_pool_destroy(hub->users->sids);
 | 
			
		||||
	hub_free(hub->users);
 | 
			
		||||
	hub->users = 0;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -36,4 +36,6 @@ extern void net_backend_shutdown();
 | 
			
		||||
 */
 | 
			
		||||
extern int net_backend_process();
 | 
			
		||||
 | 
			
		||||
extern struct timeout_queue* net_backend_get_timeout_queue();
 | 
			
		||||
 | 
			
		||||
#endif /* HAVE_UHUB_NETWORK_BACKEND_H */
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
 | 
			
		||||
#define NET_WANT_READ             NET_EVENT_READ
 | 
			
		||||
#define NET_WANT_WRITE            NET_EVENT_WRITE
 | 
			
		||||
#define NET_WANT_ACCEPT           0x0008
 | 
			
		||||
#define NET_WANT_ACCEPT           NET_EVENT_READ
 | 
			
		||||
#define NET_WANT_SSL_READ         0x0010
 | 
			
		||||
#define NET_WANT_SSL_WRITE        0x0020
 | 
			
		||||
#define NET_WANT_SSL_ACCEPT       0x0040
 | 
			
		||||
@ -13,14 +13,12 @@
 | 
			
		||||
#define NET_INITIALIZED           0x2000
 | 
			
		||||
#define NET_TIMER_ENABLED         0x1000
 | 
			
		||||
 | 
			
		||||
/* FIXME: Meant for debugging */
 | 
			
		||||
#define NET_EVENT_SET             0x0800
 | 
			
		||||
 | 
			
		||||
#define NET_CON_STRUCT_BASIC \
 | 
			
		||||
	int                  sd;        /** socket descriptor */ \
 | 
			
		||||
	uint32_t             flags;     /** Connection flags */ \
 | 
			
		||||
	void*                ptr;       /** data pointer */ \
 | 
			
		||||
	net_connection_cb    callback;  /** Callback function */ \
 | 
			
		||||
	struct timeout_evt*  timeout;   /** timeout event handler */
 | 
			
		||||
 | 
			
		||||
#define NET_CON_STRUCT_SSL \
 | 
			
		||||
	SSL*                 ssl;       /** SSL handle */ \
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ static int handle_openssl_error(struct net_connection* con, int ret)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	int error = SSL_get_error(net_con_get_ssl(con), ret);
 | 
			
		||||
	int error = SSL_get_error(con->ssl, ret);
 | 
			
		||||
	switch (error)
 | 
			
		||||
	{
 | 
			
		||||
		case SSL_ERROR_ZERO_RETURN:
 | 
			
		||||
@ -77,7 +77,7 @@ ssize_t net_con_ssl_accept(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	ssize_t ret = SSL_accept(net_con_get_ssl(con));
 | 
			
		||||
	ssize_t ret = SSL_accept(con->ssl);
 | 
			
		||||
#ifdef NETWORK_DUMP_DEBUG
 | 
			
		||||
	LOG_PROTO("SSL_accept() ret=%d", ret);
 | 
			
		||||
#endif
 | 
			
		||||
@ -96,7 +96,7 @@ ssize_t net_con_ssl_connect(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	ssize_t ret = SSL_connect(net_con_get_ssl(con));
 | 
			
		||||
	ssize_t ret = SSL_connect(con->ssl);
 | 
			
		||||
#ifdef NETWORK_DUMP_DEBUG
 | 
			
		||||
	LOG_PROTO("SSL_connect() ret=%d", ret);
 | 
			
		||||
#endif
 | 
			
		||||
@ -119,14 +119,14 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
 | 
			
		||||
	if (ssl_mode == net_con_ssl_mode_server)
 | 
			
		||||
	{
 | 
			
		||||
		ssl = SSL_new(ssl_ctx);
 | 
			
		||||
		SSL_set_fd(ssl, net_con_get_sd(con));
 | 
			
		||||
		SSL_set_fd(ssl, con->sd);
 | 
			
		||||
		net_con_set_ssl(con, ssl);
 | 
			
		||||
		return net_con_ssl_accept(con);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
 | 
			
		||||
		SSL_set_fd(ssl, net_con_get_sd(con));
 | 
			
		||||
		SSL_set_fd(ssl, con->sd);
 | 
			
		||||
		net_con_set_ssl(con, ssl);
 | 
			
		||||
		return net_con_ssl_connect(con);
 | 
			
		||||
	}
 | 
			
		||||
@ -136,7 +136,7 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
 | 
			
		||||
 | 
			
		||||
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	int ret = net_send(net_con_get_sd(con), buf, len, UHUB_SEND_SIGNAL);
 | 
			
		||||
	int ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
 | 
			
		||||
	if (ret == -1)
 | 
			
		||||
	{
 | 
			
		||||
		if (net_error() == EWOULDBLOCK || net_error() == EINTR)
 | 
			
		||||
@ -154,7 +154,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
			
		||||
	if (!net_con_is_ssl(con))
 | 
			
		||||
	{
 | 
			
		||||
#endif
 | 
			
		||||
		int ret = net_recv(net_con_get_sd(con), buf, len, 0);
 | 
			
		||||
		int ret = net_recv(con->sd, buf, len, 0);
 | 
			
		||||
#ifdef NETWORK_DUMP_DEBUG
 | 
			
		||||
		LOG_PROTO("net_recv: ret=%d", ret);
 | 
			
		||||
#endif
 | 
			
		||||
@ -174,7 +174,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		int ret = SSL_read(net_con_get_ssl(con), buf, len);
 | 
			
		||||
		int ret = SSL_read(con->ssl, buf, len);
 | 
			
		||||
#ifdef NETWORK_DUMP_DEBUG
 | 
			
		||||
		LOG_PROTO("net_recv: ret=%d", ret);
 | 
			
		||||
#endif
 | 
			
		||||
@ -193,7 +193,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
			
		||||
 | 
			
		||||
ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	int ret = net_recv(net_con_get_sd(con), buf, len, MSG_PEEK);
 | 
			
		||||
	int ret = net_recv(con->sd, buf, len, MSG_PEEK);
 | 
			
		||||
	if (ret == -1)
 | 
			
		||||
	{
 | 
			
		||||
		if (net_error() == EWOULDBLOCK || net_error() == EINTR)
 | 
			
		||||
@ -205,6 +205,39 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
int net_con_is_ssl(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->ssl != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SSL* net_con_get_ssl(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->ssl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
 | 
			
		||||
{
 | 
			
		||||
	con->ssl = ssl;
 | 
			
		||||
}
 | 
			
		||||
#endif /* SSL_SUPPORT */
 | 
			
		||||
 | 
			
		||||
int net_con_get_sd(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->sd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* net_con_get_ptr(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_callback(struct net_connection* con, int events)
 | 
			
		||||
{
 | 
			
		||||
	if (!(con->flags & NET_CLEANUP))
 | 
			
		||||
	{
 | 
			
		||||
		LOG_TRACE("net_con_callback(%p, %s%s%s)", con, (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), events == NET_EVENT_TIMEOUT ? "TIMEOUT" : "");
 | 
			
		||||
		con->callback(con, events, con->ptr);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@
 | 
			
		||||
#define HAVE_UHUB_NETWORK_CONNECTION_H
 | 
			
		||||
 | 
			
		||||
#include "uhub.h"
 | 
			
		||||
#include "network/common.h"
 | 
			
		||||
#include "network/backend.h"
 | 
			
		||||
 | 
			
		||||
#define NET_EVENT_TIMEOUT         0x0001
 | 
			
		||||
@ -30,8 +31,14 @@
 | 
			
		||||
#define NET_EVENT_CLOSED          0x2000 /* Socket closed */
 | 
			
		||||
 | 
			
		||||
struct net_connection;
 | 
			
		||||
 | 
			
		||||
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
 | 
			
		||||
 | 
			
		||||
struct net_connection
 | 
			
		||||
{
 | 
			
		||||
	NET_CON_STRUCT_COMMON
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern int   net_con_get_sd(struct net_connection* con);
 | 
			
		||||
extern void* net_con_get_ptr(struct net_connection* con);
 | 
			
		||||
 | 
			
		||||
@ -40,6 +47,7 @@ extern void net_con_destroy(struct net_connection*);
 | 
			
		||||
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
 | 
			
		||||
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
 | 
			
		||||
extern void net_con_update(struct net_connection* con, int events);
 | 
			
		||||
extern void net_con_callback(struct net_connection* con, int events);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Close the connection.
 | 
			
		||||
 | 
			
		||||
@ -27,18 +27,10 @@
 | 
			
		||||
 | 
			
		||||
#define EPOLL_EVBUFFER 512
 | 
			
		||||
 | 
			
		||||
struct net_connection
 | 
			
		||||
struct net_connection_epoll
 | 
			
		||||
{
 | 
			
		||||
	int                  sd;
 | 
			
		||||
	uint32_t             flags;
 | 
			
		||||
	net_connection_cb    callback;
 | 
			
		||||
	void*                ptr;
 | 
			
		||||
	struct epoll_event   ev;
 | 
			
		||||
	struct timeout_evt*  timeout;
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
	SSL*                 ssl;
 | 
			
		||||
	size_t               write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */
 | 
			
		||||
#endif
 | 
			
		||||
	NET_CON_STRUCT_COMMON
 | 
			
		||||
	struct epoll_event ev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct net_backend
 | 
			
		||||
@ -46,7 +38,7 @@ struct net_backend
 | 
			
		||||
	int epfd;
 | 
			
		||||
	size_t num;
 | 
			
		||||
	size_t max;
 | 
			
		||||
	struct net_connection** conns;
 | 
			
		||||
	struct net_connection_epoll** conns;
 | 
			
		||||
	struct epoll_event events[EPOLL_EVBUFFER];
 | 
			
		||||
	time_t now;
 | 
			
		||||
	struct timeout_queue timeout_queue;
 | 
			
		||||
@ -54,7 +46,7 @@ struct net_backend
 | 
			
		||||
 | 
			
		||||
static struct net_backend* g_backend = 0;
 | 
			
		||||
 | 
			
		||||
static void net_con_print(const char* prefix, struct net_connection* con)
 | 
			
		||||
static void net_con_print(const char* prefix, struct net_connection_epoll* con)
 | 
			
		||||
{
 | 
			
		||||
	char buf[512];
 | 
			
		||||
	int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, ev={ events=%s%s, data.ptr=%p }",
 | 
			
		||||
@ -87,7 +79,7 @@ int net_backend_initialize()
 | 
			
		||||
	
 | 
			
		||||
	g_backend->num = 0;
 | 
			
		||||
	g_backend->max = max;
 | 
			
		||||
	g_backend->conns = hub_malloc_zero(sizeof(struct net_connection*) * max);
 | 
			
		||||
	g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * max);
 | 
			
		||||
	memset(g_backend->events, 0, sizeof(g_backend->events));
 | 
			
		||||
 | 
			
		||||
	g_backend->now = time(0);
 | 
			
		||||
@ -121,19 +113,23 @@ int net_backend_process()
 | 
			
		||||
 | 
			
		||||
	for (n = 0; n < res; n++)
 | 
			
		||||
	{
 | 
			
		||||
		struct net_connection* con = (struct net_connection*) g_backend->events[n].data.ptr;
 | 
			
		||||
		struct net_connection_epoll* con = (struct net_connection_epoll*) g_backend->events[n].data.ptr;
 | 
			
		||||
		int ev = 0;
 | 
			
		||||
		if (g_backend->events[n].events & EPOLLIN)  ev |= NET_EVENT_READ;
 | 
			
		||||
		if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
 | 
			
		||||
		con->callback(con, ev, con->ptr);
 | 
			
		||||
		net_con_callback((struct net_connection*) con, ev);
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct timeout_queue* net_backend_get_timeout_queue()
 | 
			
		||||
{
 | 
			
		||||
	return &g_backend->timeout_queue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct net_connection* net_con_create()
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection));
 | 
			
		||||
	struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
 | 
			
		||||
	con->sd = -1;
 | 
			
		||||
	return con;
 | 
			
		||||
}
 | 
			
		||||
@ -143,8 +139,9 @@ void net_con_destroy(struct net_connection* con)
 | 
			
		||||
	hub_free(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
 | 
			
		||||
void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
 | 
			
		||||
	con->sd = sd;
 | 
			
		||||
	con->flags = NET_INITIALIZED;
 | 
			
		||||
	con->callback = callback;
 | 
			
		||||
@ -176,10 +173,11 @@ void net_con_reinitialize(struct net_connection* con, net_connection_cb callback
 | 
			
		||||
	net_con_update(con, events);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_update(struct net_connection* con, int events)
 | 
			
		||||
void net_con_update(struct net_connection* con_, int events)
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
 | 
			
		||||
	con->ev.events = 0;
 | 
			
		||||
	if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
 | 
			
		||||
	if (events & NET_EVENT_READ)  con->ev.events |= EPOLLIN;
 | 
			
		||||
	if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
 | 
			
		||||
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
@ -211,8 +209,9 @@ void net_con_update(struct net_connection* con, int events)
 | 
			
		||||
	net_con_print("MOD", con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int net_con_close(struct net_connection* con)
 | 
			
		||||
int net_con_close(struct net_connection* con_)
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
 | 
			
		||||
	if (!(con->flags & NET_INITIALIZED))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@ -239,68 +238,4 @@ int net_con_close(struct net_connection* con)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
int net_con_is_ssl(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	return con->ssl != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SSL* net_con_get_ssl(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->ssl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
 | 
			
		||||
{
 | 
			
		||||
	con->ssl = ssl;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int net_con_get_sd(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->sd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* net_con_get_ptr(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
 | 
			
		||||
void timeout_evt_reset(struct timeout_evt*);
 | 
			
		||||
int  timeout_evt_is_scheduled(struct timeout_evt*);
 | 
			
		||||
 | 
			
		||||
static void timeout_callback(struct timeout_evt* evt)
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection* con = (struct net_connection*) evt->ptr;
 | 
			
		||||
	con->callback(con, NET_EVENT_TIMEOUT, con->ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void net_con_set_timeout(struct net_connection* con, int seconds)
 | 
			
		||||
{
 | 
			
		||||
	if (!con->timeout)
 | 
			
		||||
	{
 | 
			
		||||
		con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
 | 
			
		||||
		timeout_evt_initialize(con->timeout, timeout_callback, con);
 | 
			
		||||
		timeout_queue_insert(&g_backend->timeout_queue, con->timeout, seconds);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		timeout_queue_reschedule(&g_backend->timeout_queue, con->timeout, seconds);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_clear_timeout(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	if (con->timeout && timeout_evt_is_scheduled(con->timeout))
 | 
			
		||||
	{
 | 
			
		||||
		timeout_queue_remove(&g_backend->timeout_queue, con->timeout);
 | 
			
		||||
		hub_free(con->timeout);
 | 
			
		||||
		con->timeout = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* USE_EPOLL */
 | 
			
		||||
 | 
			
		||||
@ -1,399 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * uhub - A tiny ADC p2p connection hub
 | 
			
		||||
 * Copyright (C) 2007-2009, 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/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
 | 
			
		||||
struct net_connection
 | 
			
		||||
{
 | 
			
		||||
	NET_CON_STRUCT_COMMON
 | 
			
		||||
	struct event         event;     /** libevent struct for read/write events */
 | 
			
		||||
	struct event         timeout;   /** Used for internal timeout handling */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct net_timer
 | 
			
		||||
{
 | 
			
		||||
	unsigned int         initialized;
 | 
			
		||||
	struct event         timeout;
 | 
			
		||||
	net_timeout_cb       callback;
 | 
			
		||||
	void*                ptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int net_con_get_sd(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->sd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* net_con_get_ptr(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	return con->ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct net_connection* net_con_create()
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection* con = (struct net_connection*) hub_malloc(sizeof(struct net_connection));
 | 
			
		||||
	return con;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int net_con_flag_get(struct net_connection* con, unsigned int flag)
 | 
			
		||||
{
 | 
			
		||||
    return con->flags & flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void net_con_flag_set(struct net_connection* con, unsigned int flag)
 | 
			
		||||
{
 | 
			
		||||
    con->flags |= flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void net_con_flag_unset(struct net_connection* con, unsigned int flag)
 | 
			
		||||
{
 | 
			
		||||
    con->flags &= ~flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_destroy(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	hub_free(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int net_con_convert_to_libevent_mask(int ev)
 | 
			
		||||
{
 | 
			
		||||
	int events = 0;
 | 
			
		||||
	if (ev & NET_EVENT_READ)  events |= EV_READ;
 | 
			
		||||
	if (ev & NET_EVENT_WRITE) events |= EV_WRITE;
 | 
			
		||||
	return events;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int net_con_convert_from_libevent_mask(int ev)
 | 
			
		||||
{
 | 
			
		||||
	int events = 0;
 | 
			
		||||
	if (ev & EV_TIMEOUT)    events |= NET_EVENT_TIMEOUT;
 | 
			
		||||
	if (ev & EV_READ)       events |= NET_EVENT_READ;
 | 
			
		||||
	if (ev & EV_WRITE)      events |= NET_EVENT_WRITE;
 | 
			
		||||
	return events;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void net_con_event(int fd, short ev, void *arg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int net_con_close(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	con->ptr = 0;
 | 
			
		||||
 | 
			
		||||
	if (net_con_flag_get(con, NET_CLEANUP))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (net_con_flag_get(con, NET_PROCESSING_BUSY))
 | 
			
		||||
	{
 | 
			
		||||
		net_con_flag_set(con, NET_CLEANUP);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	net_con_after_close(con);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void net_con_set(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	int ev = 0;
 | 
			
		||||
	if (net_con_flag_get(con, NET_WANT_READ | NET_WANT_SSL_READ))   ev |= EV_READ;
 | 
			
		||||
	if (net_con_flag_get(con, NET_WANT_WRITE | NET_WANT_SSL_WRITE)) ev |= EV_WRITE;
 | 
			
		||||
 | 
			
		||||
	if (net_con_flag_get(con, NET_EVENT_SET) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		event_del(&con->event);
 | 
			
		||||
	}
 | 
			
		||||
	net_con_flag_set(con, NET_EVENT_SET);
 | 
			
		||||
 | 
			
		||||
	LOG_MEMORY("SET: set+add: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, ev);
 | 
			
		||||
	event_set(&con->event, con->sd, ev, net_con_event, con);
 | 
			
		||||
	event_add(&con->event, 0);
 | 
			
		||||
 | 
			
		||||
	net_con_flag_set(con, NET_INITIALIZED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void net_con_after_close(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	if (net_con_flag_get(con, NET_INITIALIZED))
 | 
			
		||||
	{
 | 
			
		||||
		LOG_MEMORY("DEL:   close: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, -1);
 | 
			
		||||
		net_con_flag_unset(con, NET_EVENT_SET);
 | 
			
		||||
 | 
			
		||||
		event_del(&con->event);
 | 
			
		||||
		net_con_flag_unset(con, NET_INITIALIZED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	net_con_clear_timeout(con);
 | 
			
		||||
	net_close(con->sd);
 | 
			
		||||
	con->sd = -1;
 | 
			
		||||
 | 
			
		||||
	hub_free(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int ev)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	int events = net_con_convert_to_libevent_mask(ev);
 | 
			
		||||
	if (ev & NET_EVENT_READ)  net_con_flag_set(con, NET_WANT_READ);
 | 
			
		||||
	if (ev & NET_EVENT_WRITE) net_con_flag_set(con, NET_WANT_WRITE);
 | 
			
		||||
 | 
			
		||||
	con->sd = sd;
 | 
			
		||||
	con->flags = 0;
 | 
			
		||||
	con->ptr = (void*) ptr;
 | 
			
		||||
	con->callback = callback;
 | 
			
		||||
	con->last_send = time(0);
 | 
			
		||||
	con->last_recv = con->last_send;
 | 
			
		||||
 | 
			
		||||
	if (ev)
 | 
			
		||||
	{
 | 
			
		||||
		uhub_assert(net_con_flag_get(con, NET_EVENT_SET) == 0);
 | 
			
		||||
		net_con_flag_set(con, NET_EVENT_SET);
 | 
			
		||||
 | 
			
		||||
		LOG_MEMORY("SET:    init: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, ev);
 | 
			
		||||
		event_set(&con->event, con->sd, events, net_con_event, con);
 | 
			
		||||
		event_add(&con->event, 0);
 | 
			
		||||
		net_con_flag_set(con, NET_INITIALIZED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	net_set_nonblocking(sd, 1);
 | 
			
		||||
	net_set_nosigpipe(sd, 1);
 | 
			
		||||
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
	con->ssl = NULL;
 | 
			
		||||
	con->write_len = 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
	con->callback = callback;
 | 
			
		||||
	con->ptr = (void*) ptr;
 | 
			
		||||
	net_con_update(con, events);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_update(struct net_connection* con, int ev)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	if (ev & NET_EVENT_READ)
 | 
			
		||||
		net_con_flag_set(con, NET_EVENT_READ);
 | 
			
		||||
	else
 | 
			
		||||
		net_con_flag_unset(con, NET_EVENT_READ);
 | 
			
		||||
 | 
			
		||||
	if (ev & NET_EVENT_WRITE)
 | 
			
		||||
		net_con_flag_set(con, NET_EVENT_WRITE);
 | 
			
		||||
	else
 | 
			
		||||
		net_con_flag_unset(con, NET_EVENT_WRITE);
 | 
			
		||||
 | 
			
		||||
	if (!net_con_flag_get(con, NET_PROCESSING_BUSY))
 | 
			
		||||
	{
 | 
			
		||||
		net_con_set(con);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define CALLBACK(CON, EVENTS) \
 | 
			
		||||
	if (CON->callback) \
 | 
			
		||||
		CON->callback(con, EVENTS, CON->ptr);
 | 
			
		||||
 | 
			
		||||
static void net_con_event(int fd, short ev, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection* con = (struct net_connection*) arg;
 | 
			
		||||
	int events = net_con_convert_from_libevent_mask(ev);
 | 
			
		||||
 | 
			
		||||
	if (!net_con_flag_get(con, NET_INITIALIZED))
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (net_con_flag_get(con, NET_CLEANUP))
 | 
			
		||||
	{
 | 
			
		||||
		net_con_after_close(con);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	net_con_flag_set(con, NET_PROCESSING_BUSY);
 | 
			
		||||
 | 
			
		||||
// 	uhub_assert(net_con_flag_get(con, NET_EVENT_SET) != 0);
 | 
			
		||||
	net_con_flag_unset(con, NET_EVENT_SET);
 | 
			
		||||
 | 
			
		||||
	LOG_MEMORY("EVT: process: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, (int) ev);
 | 
			
		||||
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
	if (!con->ssl)
 | 
			
		||||
	{
 | 
			
		||||
#endif
 | 
			
		||||
		CALLBACK(con, events);
 | 
			
		||||
#ifdef SSL_SUPPORT
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
#ifdef NETWORK_DUMP_DEBUG
 | 
			
		||||
		LOG_PROTO("net_con_event: events=%d, con=%p", ev, con);
 | 
			
		||||
#endif
 | 
			
		||||
		if (ev & (EV_READ | EV_WRITE))
 | 
			
		||||
		{
 | 
			
		||||
			if (net_con_flag_get(con, NET_WANT_SSL_ACCEPT))
 | 
			
		||||
			{
 | 
			
		||||
				if (net_con_ssl_accept(con) < 0)
 | 
			
		||||
					CALLBACK(con, NET_EVENT_SOCKERROR);
 | 
			
		||||
			}
 | 
			
		||||
			else if (net_con_flag_get(con, NET_WANT_SSL_CONNECT))
 | 
			
		||||
			{
 | 
			
		||||
				if (net_con_ssl_connect(con) < 0)
 | 
			
		||||
					CALLBACK(con, NET_EVENT_SOCKERROR);
 | 
			
		||||
			}
 | 
			
		||||
			else if (ev == EV_READ && net_con_flag_get(con, NET_WANT_SSL_READ))
 | 
			
		||||
			{
 | 
			
		||||
				CALLBACK(con, NET_EVENT_WRITE);
 | 
			
		||||
			}
 | 
			
		||||
			else if (ev == EV_WRITE && net_con_flag_get(con, NET_WANT_SSL_WRITE))
 | 
			
		||||
			{
 | 
			
		||||
				CALLBACK(con, events & NET_EVENT_READ);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				CALLBACK(con, events);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			CALLBACK(con, events);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	net_con_flag_unset(con, NET_PROCESSING_BUSY);
 | 
			
		||||
 | 
			
		||||
	if (net_con_flag_get(con, NET_CLEANUP))
 | 
			
		||||
	{
 | 
			
		||||
		net_con_after_close(con);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		net_con_set(con);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void net_timer_event(int fd, short ev, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct net_timer* timer = (struct net_timer*) arg;
 | 
			
		||||
	timer->callback(timer, timer->ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr)
 | 
			
		||||
{
 | 
			
		||||
	timer->initialized = 0;
 | 
			
		||||
	timer->callback = callback;
 | 
			
		||||
	timer->ptr = ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_timer_reset(struct net_timer* timer, int seconds)
 | 
			
		||||
{
 | 
			
		||||
	struct timeval timeout = { seconds, 0 };
 | 
			
		||||
	if (timer->initialized)
 | 
			
		||||
	{
 | 
			
		||||
		evtimer_del(&timer->timeout);
 | 
			
		||||
		timer->initialized = 0;
 | 
			
		||||
	}
 | 
			
		||||
	evtimer_set(&timer->timeout, net_timer_event, timer);
 | 
			
		||||
	evtimer_add(&timer->timeout, &timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_timer_shutdown(struct net_timer* timer)
 | 
			
		||||
{
 | 
			
		||||
	if (timer->initialized)
 | 
			
		||||
	{
 | 
			
		||||
		evtimer_del(&timer->timeout);
 | 
			
		||||
		timer->initialized = 0;
 | 
			
		||||
	}
 | 
			
		||||
	timer->callback = 0;
 | 
			
		||||
	timer->ptr = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void net_con_set_timeout(struct net_connection* con, int seconds)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	struct timeval timeout = { seconds, 0 };
 | 
			
		||||
	net_con_clear_timeout(con);
 | 
			
		||||
 | 
			
		||||
	evtimer_set(&con->timeout, net_con_event, con);
 | 
			
		||||
	evtimer_add(&con->timeout, &timeout);
 | 
			
		||||
	net_con_flag_set(con, NET_TIMER_ENABLED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_clear_timeout(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	uhub_assert(con);
 | 
			
		||||
 | 
			
		||||
	if (net_con_flag_get(con, NET_TIMER_ENABLED))
 | 
			
		||||
	{
 | 
			
		||||
		evtimer_del(&con->timeout);
 | 
			
		||||
		net_con_flag_unset(con, NET_TIMER_ENABLED);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct event_base g_evbase = 0;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize the network backend.
 | 
			
		||||
 * Returns 1 on success, or 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int net_backend_initialize()
 | 
			
		||||
{
 | 
			
		||||
	g_evbase = event_init();
 | 
			
		||||
	if (!g_evbase)
 | 
			
		||||
	{
 | 
			
		||||
		LOG_ERROR("Unable to initialize libevent.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shutdown the network connection backend.
 | 
			
		||||
 */
 | 
			
		||||
void net_backend_shutdown()
 | 
			
		||||
{
 | 
			
		||||
	event_base_free(g_evbase);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process the network backend.
 | 
			
		||||
 */
 | 
			
		||||
int net_backend_process()
 | 
			
		||||
{
 | 
			
		||||
	int ret = event_base_loop(g_evbase, EVLOOP_ONCE);
 | 
			
		||||
	if (ret != 0)
 | 
			
		||||
	{
 | 
			
		||||
		LOG_DEBUG("event_base_loop returned: %d", (int) ret);
 | 
			
		||||
	}
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* USE_LIBEVENT */
 | 
			
		||||
							
								
								
									
										208
									
								
								src/network/select.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								src/network/select.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,208 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
 | 
			
		||||
#include "network/connection.h"
 | 
			
		||||
#include "network/common.h"
 | 
			
		||||
#include "network/backend.h"
 | 
			
		||||
 | 
			
		||||
struct net_connection_select
 | 
			
		||||
{
 | 
			
		||||
	NET_CON_STRUCT_COMMON
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct net_backend
 | 
			
		||||
{
 | 
			
		||||
	size_t num;
 | 
			
		||||
	size_t max;
 | 
			
		||||
	struct net_connection_select** conns;
 | 
			
		||||
	fd_set rfds;
 | 
			
		||||
	fd_set wfds;
 | 
			
		||||
	time_t now;
 | 
			
		||||
	struct timeout_queue timeout_queue;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct net_backend* g_backend = 0;
 | 
			
		||||
 | 
			
		||||
static void net_con_print(const char* prefix, struct net_connection_select* con)
 | 
			
		||||
{
 | 
			
		||||
	char buf[512];
 | 
			
		||||
	int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, events=%s%s",
 | 
			
		||||
		prefix, con->sd, con->flags, con->callback, con->ptr, (con->flags & NET_EVENT_READ ? "R" : ""),(con->flags & NET_EVENT_WRITE ? "W" : ""));
 | 
			
		||||
	if (con->timeout)
 | 
			
		||||
	{
 | 
			
		||||
		sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		sprintf(buf + off, ", timeout=NULL");
 | 
			
		||||
	}
 | 
			
		||||
	LOG_TRACE(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize the network backend.
 | 
			
		||||
 * Returns 1 on success, or 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int net_backend_initialize()
 | 
			
		||||
{
 | 
			
		||||
	size_t max = net_get_max_sockets();
 | 
			
		||||
	g_backend = hub_malloc(sizeof(struct net_backend));
 | 
			
		||||
	g_backend->num = 0;
 | 
			
		||||
	g_backend->max = max;
 | 
			
		||||
	g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * max);
 | 
			
		||||
	FD_ZERO(&g_backend->rfds);
 | 
			
		||||
	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. */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shutdown the network connection backend.
 | 
			
		||||
 */
 | 
			
		||||
void net_backend_shutdown()
 | 
			
		||||
{
 | 
			
		||||
	hub_free(g_backend->conns);
 | 
			
		||||
	hub_free(g_backend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process the network backend.
 | 
			
		||||
 */
 | 
			
		||||
int net_backend_process()
 | 
			
		||||
{
 | 
			
		||||
	int n, found, maxfd;
 | 
			
		||||
	struct timeval tval = { 1, 0 };
 | 
			
		||||
	FD_ZERO(&g_backend->rfds);
 | 
			
		||||
	FD_ZERO(&g_backend->wfds);
 | 
			
		||||
	for (n = 0, found = 0; found < g_backend->num && n < g_backend->max; n++)
 | 
			
		||||
	{
 | 
			
		||||
		struct net_connection_select* con = g_backend->conns[n];
 | 
			
		||||
		if (con)
 | 
			
		||||
		{
 | 
			
		||||
			if (con->flags & NET_EVENT_READ)  FD_SET(con->sd, &g_backend->rfds);
 | 
			
		||||
			if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &g_backend->wfds);
 | 
			
		||||
			found++;
 | 
			
		||||
			maxfd = con->sd;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int res = select(maxfd+1, &g_backend->rfds, &g_backend->wfds, 0, &tval);
 | 
			
		||||
	if (res == -1)
 | 
			
		||||
	{
 | 
			
		||||
		LOG_WARN("select returned -1");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (n = 0, found = 0; found < res && n < (maxfd+1); n++)
 | 
			
		||||
	{
 | 
			
		||||
		struct net_connection_select* con = g_backend->conns[n];
 | 
			
		||||
		if (con)
 | 
			
		||||
		{
 | 
			
		||||
			int ev = 0;
 | 
			
		||||
			if (FD_ISSET(con->sd, &g_backend->rfds)) ev |= NET_EVENT_READ;
 | 
			
		||||
			if (FD_ISSET(con->sd, &g_backend->wfds)) ev |= NET_EVENT_WRITE;
 | 
			
		||||
 | 
			
		||||
			if (ev)
 | 
			
		||||
			{
 | 
			
		||||
				net_con_callback((struct net_connection*) con, ev);
 | 
			
		||||
				found++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct timeout_queue* net_backend_get_timeout_queue()
 | 
			
		||||
{
 | 
			
		||||
	return &g_backend->timeout_queue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct net_connection* net_con_create()
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
 | 
			
		||||
	con->sd = -1;
 | 
			
		||||
	return con;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_destroy(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	hub_free(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
 | 
			
		||||
{
 | 
			
		||||
	struct net_connection_select* con = (struct net_connection_select*) con_;
 | 
			
		||||
	con->sd = sd;
 | 
			
		||||
	con->flags = NET_INITIALIZED;
 | 
			
		||||
	con->flags |= events;
 | 
			
		||||
	con->callback = callback;
 | 
			
		||||
	con->ptr = (void*) ptr;
 | 
			
		||||
 | 
			
		||||
	net_set_nonblocking(con->sd, 1);
 | 
			
		||||
	net_set_nosigpipe(con->sd, 1);
 | 
			
		||||
 | 
			
		||||
	g_backend->conns[sd] = con;
 | 
			
		||||
	g_backend->num++;
 | 
			
		||||
	net_con_print("ADD", con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
 | 
			
		||||
{
 | 
			
		||||
	con->callback = callback;
 | 
			
		||||
	con->ptr = (void*) ptr;
 | 
			
		||||
	net_con_update(con, events);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_update(struct net_connection* con, int events)
 | 
			
		||||
{
 | 
			
		||||
	con->flags = NET_INITIALIZED;
 | 
			
		||||
	con->flags |= events;
 | 
			
		||||
	net_con_print("MOD", (struct net_connection_select*) con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int net_con_close(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	if (!(con->flags & NET_INITIALIZED))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	con->flags &= ~NET_INITIALIZED;
 | 
			
		||||
 | 
			
		||||
	if (con->sd != -1)
 | 
			
		||||
	{
 | 
			
		||||
		g_backend->conns[con->sd] = 0;
 | 
			
		||||
		g_backend->num--;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (timeout_evt_is_scheduled(con->timeout))
 | 
			
		||||
	{
 | 
			
		||||
		timeout_queue_remove(&g_backend->timeout_queue, con->timeout);
 | 
			
		||||
		hub_free(con->timeout);
 | 
			
		||||
		con->timeout = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	net_con_print("DEL", (struct net_connection_select*) con);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* USE_SELECT */
 | 
			
		||||
							
								
								
									
										50
									
								
								src/network/timer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/network/timer.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
 | 
			
		||||
static void timeout_callback(struct timeout_evt* evt)
 | 
			
		||||
{
 | 
			
		||||
	net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_set_timeout(struct net_connection* con, int seconds)
 | 
			
		||||
{
 | 
			
		||||
	if (!con->timeout)
 | 
			
		||||
	{
 | 
			
		||||
		con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
 | 
			
		||||
		timeout_evt_initialize(con->timeout, timeout_callback, con);
 | 
			
		||||
		timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void net_con_clear_timeout(struct net_connection* con)
 | 
			
		||||
{
 | 
			
		||||
	if (timeout_evt_is_scheduled(con->timeout))
 | 
			
		||||
	{
 | 
			
		||||
		timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
 | 
			
		||||
		hub_free(con->timeout);
 | 
			
		||||
		con->timeout = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -102,13 +102,12 @@
 | 
			
		||||
 | 
			
		||||
#define uhub_assert assert
 | 
			
		||||
 | 
			
		||||
#ifdef USE_LIBEVENT
 | 
			
		||||
#include <event.h>
 | 
			
		||||
#else
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#define USE_EPOLL
 | 
			
		||||
#include <sys/epoll.h>
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#define USE_SELECT
 | 
			
		||||
#include <sys/select.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
 | 
			
		||||
 | 
			
		||||
@ -330,7 +330,7 @@ void runloop(size_t clients)
 | 
			
		||||
 | 
			
		||||
	while (running)
 | 
			
		||||
	{
 | 
			
		||||
		event_base_loop(net_get_evbase(), EVLOOP_ONCE);
 | 
			
		||||
		net_backend_process();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (n = 0; n < clients; n++)
 | 
			
		||||
@ -413,63 +413,17 @@ void parse_command_line(int argc, char** argv)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef WIN32
 | 
			
		||||
static void handle_signal(int signal, short events, void* arg)
 | 
			
		||||
{
 | 
			
		||||
	switch (signal)
 | 
			
		||||
	{
 | 
			
		||||
		case SIGINT:
 | 
			
		||||
		case SIGTERM:
 | 
			
		||||
			running = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct event signal_events[10];
 | 
			
		||||
static int signals[] =
 | 
			
		||||
{
 | 
			
		||||
	SIGINT,  /* Interrupt the application */
 | 
			
		||||
	SIGTERM, /* Terminate the application */
 | 
			
		||||
	0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void setup_signal_handlers()
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	for (i = 0; signals[i]; i++)
 | 
			
		||||
	{
 | 
			
		||||
		signal_set(&signal_events[i], signals[i], handle_signal, NULL);
 | 
			
		||||
		signal_add(&signal_events[i], NULL);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void shutdown_signal_handlers()
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	for (i = 0; signals[i]; i++)
 | 
			
		||||
	{
 | 
			
		||||
		signal_del(&signal_events[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WIN32 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv)
 | 
			
		||||
{
 | 
			
		||||
	parse_command_line(argc, argv);
 | 
			
		||||
	
 | 
			
		||||
	net_initialize();
 | 
			
		||||
	setup_signal_handlers();
 | 
			
		||||
 | 
			
		||||
	hub_log_initialize(NULL, 0);
 | 
			
		||||
	hub_set_log_verbosity(1000);
 | 
			
		||||
 | 
			
		||||
	runloop(cfg_clients);
 | 
			
		||||
 | 
			
		||||
	shutdown_signal_handlers();
 | 
			
		||||
	net_destroy();
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -63,6 +63,7 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int running = 1;
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv)
 | 
			
		||||
{
 | 
			
		||||
@ -79,7 +80,10 @@ int main(int argc, char** argv)
 | 
			
		||||
	ADC_client_set_callback(&client, handle);
 | 
			
		||||
	ADC_client_connect(&client, argv[1]);
 | 
			
		||||
 | 
			
		||||
	event_dispatch();
 | 
			
		||||
	while (running)
 | 
			
		||||
	{
 | 
			
		||||
		net_backend_process();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ADC_client_destroy(&client);
 | 
			
		||||
	net_destroy();
 | 
			
		||||
 | 
			
		||||
@ -99,7 +99,7 @@ void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
 | 
			
		||||
	size_t pos = (evt->timestamp % t->max);
 | 
			
		||||
	struct timeout_evt* first = t->events[pos];
 | 
			
		||||
 | 
			
		||||
	if (!first)
 | 
			
		||||
	if (!first || !evt)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (first == evt)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user