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
|
RANLIB := ranlib
|
||||||
CFLAGS += -pipe -Wall
|
CFLAGS += -pipe -Wall
|
||||||
USE_SSL ?= NO
|
USE_SSL ?= NO
|
||||||
USE_LIBEVENT ?= NO
|
|
||||||
USE_BIGENDIAN ?= AUTO
|
USE_BIGENDIAN ?= AUTO
|
||||||
BITS ?= AUTO
|
BITS ?= AUTO
|
||||||
SILENT ?= YES
|
SILENT ?= YES
|
||||||
@ -63,9 +62,6 @@ else
|
|||||||
MSG_CLEAN="Clean as a whistle"
|
MSG_CLEAN="Clean as a whistle"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# CFLAGS += -I/source/libevent
|
|
||||||
# LDFLAGS += -L/source/libevent
|
|
||||||
|
|
||||||
ifeq ($(RELEASE),YES)
|
ifeq ($(RELEASE),YES)
|
||||||
CFLAGS += -O3 -DNDEBUG
|
CFLAGS += -O3 -DNDEBUG
|
||||||
GIT_REVISION ?= NO
|
GIT_REVISION ?= NO
|
||||||
@ -116,15 +112,6 @@ CFLAGS += -DSSL_SUPPORT
|
|||||||
LDLIBS += -lssl
|
LDLIBS += -lssl
|
||||||
endif
|
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)
|
ifeq ($(GIT_REVISION),YES)
|
||||||
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
|
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
|
||||||
endif
|
endif
|
||||||
@ -146,8 +133,9 @@ libuhub_SOURCES := \
|
|||||||
src/core/usermanager.c \
|
src/core/usermanager.c \
|
||||||
src/network/connection.c \
|
src/network/connection.c \
|
||||||
src/network/epoll.c \
|
src/network/epoll.c \
|
||||||
src/network/libevent.c \
|
|
||||||
src/network/network.c \
|
src/network/network.c \
|
||||||
|
src/network/select.c \
|
||||||
|
src/network/timer.c \
|
||||||
src/util/ipcalc.c \
|
src/util/ipcalc.c \
|
||||||
src/util/list.c \
|
src/util/list.c \
|
||||||
src/util/log.c \
|
src/util/log.c \
|
||||||
|
@ -622,9 +622,6 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
LOG_DEBUG("hub_shutdown_service()");
|
LOG_DEBUG("hub_shutdown_service()");
|
||||||
|
|
||||||
event_queue_shutdown(hub->queue);
|
event_queue_shutdown(hub->queue);
|
||||||
#ifdef USE_LIBEVENT
|
|
||||||
event_del(&hub->ev_accept);
|
|
||||||
#endif
|
|
||||||
net_con_close(hub->server);
|
net_con_close(hub->server);
|
||||||
hub_free(hub->server);
|
hub_free(hub->server);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub);
|
||||||
|
@ -91,10 +91,6 @@ struct hub_logout_info
|
|||||||
struct hub_info
|
struct hub_info
|
||||||
{
|
{
|
||||||
struct net_connection* server;
|
struct net_connection* server;
|
||||||
#ifdef USE_LIBEVENT
|
|
||||||
struct event ev_accept;
|
|
||||||
struct event ev_timer;
|
|
||||||
#endif
|
|
||||||
struct hub_stats stats;
|
struct hub_stats stats;
|
||||||
struct event_queue* queue;
|
struct event_queue* queue;
|
||||||
struct hub_config* config;
|
struct hub_config* config;
|
||||||
|
@ -70,28 +70,9 @@ void uman_print_stats(struct hub_info* hub)
|
|||||||
(int) hub->stats.net_rx_peak / 1024);
|
(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)
|
int uman_init(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
struct hub_user_manager* users = NULL;
|
struct hub_user_manager* users = NULL;
|
||||||
#ifdef USERMANAGER_TIMER
|
|
||||||
#ifdef USE_LIBEVENT
|
|
||||||
struct timeval timeout = { TIMEOUT_STATS, 0 };
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (!hub)
|
if (!hub)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -110,16 +91,6 @@ int uman_init(struct hub_info* hub)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hub->users = users;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,13 +100,6 @@ int uman_shutdown(struct hub_info* hub)
|
|||||||
if (!hub || !hub->users)
|
if (!hub || !hub->users)
|
||||||
return -1;
|
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)
|
if (hub->users->list)
|
||||||
{
|
{
|
||||||
list_clear(hub->users->list, &clear_user_list_callback);
|
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);
|
sid_pool_destroy(hub->users->sids);
|
||||||
hub_free(hub->users);
|
hub_free(hub->users);
|
||||||
hub->users = 0;
|
hub->users = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,4 +36,6 @@ extern void net_backend_shutdown();
|
|||||||
*/
|
*/
|
||||||
extern int net_backend_process();
|
extern int net_backend_process();
|
||||||
|
|
||||||
|
extern struct timeout_queue* net_backend_get_timeout_queue();
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_NETWORK_BACKEND_H */
|
#endif /* HAVE_UHUB_NETWORK_BACKEND_H */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#define NET_WANT_READ NET_EVENT_READ
|
#define NET_WANT_READ NET_EVENT_READ
|
||||||
#define NET_WANT_WRITE NET_EVENT_WRITE
|
#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_READ 0x0010
|
||||||
#define NET_WANT_SSL_WRITE 0x0020
|
#define NET_WANT_SSL_WRITE 0x0020
|
||||||
#define NET_WANT_SSL_ACCEPT 0x0040
|
#define NET_WANT_SSL_ACCEPT 0x0040
|
||||||
@ -13,14 +13,12 @@
|
|||||||
#define NET_INITIALIZED 0x2000
|
#define NET_INITIALIZED 0x2000
|
||||||
#define NET_TIMER_ENABLED 0x1000
|
#define NET_TIMER_ENABLED 0x1000
|
||||||
|
|
||||||
/* FIXME: Meant for debugging */
|
|
||||||
#define NET_EVENT_SET 0x0800
|
|
||||||
|
|
||||||
#define NET_CON_STRUCT_BASIC \
|
#define NET_CON_STRUCT_BASIC \
|
||||||
int sd; /** socket descriptor */ \
|
int sd; /** socket descriptor */ \
|
||||||
uint32_t flags; /** Connection flags */ \
|
uint32_t flags; /** Connection flags */ \
|
||||||
void* ptr; /** data pointer */ \
|
void* ptr; /** data pointer */ \
|
||||||
net_connection_cb callback; /** Callback function */ \
|
net_connection_cb callback; /** Callback function */ \
|
||||||
|
struct timeout_evt* timeout; /** timeout event handler */
|
||||||
|
|
||||||
#define NET_CON_STRUCT_SSL \
|
#define NET_CON_STRUCT_SSL \
|
||||||
SSL* ssl; /** SSL handle */ \
|
SSL* ssl; /** SSL handle */ \
|
||||||
|
@ -25,7 +25,7 @@ static int handle_openssl_error(struct net_connection* con, int ret)
|
|||||||
{
|
{
|
||||||
uhub_assert(con);
|
uhub_assert(con);
|
||||||
|
|
||||||
int error = SSL_get_error(net_con_get_ssl(con), ret);
|
int error = SSL_get_error(con->ssl, ret);
|
||||||
switch (error)
|
switch (error)
|
||||||
{
|
{
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
@ -77,7 +77,7 @@ ssize_t net_con_ssl_accept(struct net_connection* con)
|
|||||||
{
|
{
|
||||||
uhub_assert(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
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
LOG_PROTO("SSL_accept() ret=%d", ret);
|
LOG_PROTO("SSL_accept() ret=%d", ret);
|
||||||
#endif
|
#endif
|
||||||
@ -96,7 +96,7 @@ ssize_t net_con_ssl_connect(struct net_connection* con)
|
|||||||
{
|
{
|
||||||
uhub_assert(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
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
LOG_PROTO("SSL_connect() ret=%d", ret);
|
LOG_PROTO("SSL_connect() ret=%d", ret);
|
||||||
#endif
|
#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)
|
if (ssl_mode == net_con_ssl_mode_server)
|
||||||
{
|
{
|
||||||
ssl = SSL_new(ssl_ctx);
|
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);
|
net_con_set_ssl(con, ssl);
|
||||||
return net_con_ssl_accept(con);
|
return net_con_ssl_accept(con);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
|
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);
|
net_con_set_ssl(con, ssl);
|
||||||
return net_con_ssl_connect(con);
|
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)
|
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 (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
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))
|
if (!net_con_is_ssl(con))
|
||||||
{
|
{
|
||||||
#endif
|
#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
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
LOG_PROTO("net_recv: ret=%d", ret);
|
LOG_PROTO("net_recv: ret=%d", ret);
|
||||||
#endif
|
#endif
|
||||||
@ -174,7 +174,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ret = SSL_read(net_con_get_ssl(con), buf, len);
|
int ret = SSL_read(con->ssl, buf, len);
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
LOG_PROTO("net_recv: ret=%d", ret);
|
LOG_PROTO("net_recv: ret=%d", ret);
|
||||||
#endif
|
#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)
|
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 (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
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;
|
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
|
#define HAVE_UHUB_NETWORK_CONNECTION_H
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
#include "network/common.h"
|
||||||
#include "network/backend.h"
|
#include "network/backend.h"
|
||||||
|
|
||||||
#define NET_EVENT_TIMEOUT 0x0001
|
#define NET_EVENT_TIMEOUT 0x0001
|
||||||
@ -30,8 +31,14 @@
|
|||||||
#define NET_EVENT_CLOSED 0x2000 /* Socket closed */
|
#define NET_EVENT_CLOSED 0x2000 /* Socket closed */
|
||||||
|
|
||||||
struct net_connection;
|
struct net_connection;
|
||||||
|
|
||||||
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
|
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 int net_con_get_sd(struct net_connection* con);
|
||||||
extern void* net_con_get_ptr(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_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_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_update(struct net_connection* con, int events);
|
||||||
|
extern void net_con_callback(struct net_connection* con, int events);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the connection.
|
* Close the connection.
|
||||||
|
@ -27,18 +27,10 @@
|
|||||||
|
|
||||||
#define EPOLL_EVBUFFER 512
|
#define EPOLL_EVBUFFER 512
|
||||||
|
|
||||||
struct net_connection
|
struct net_connection_epoll
|
||||||
{
|
{
|
||||||
int sd;
|
NET_CON_STRUCT_COMMON
|
||||||
uint32_t flags;
|
struct epoll_event ev;
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct net_backend
|
struct net_backend
|
||||||
@ -46,7 +38,7 @@ struct net_backend
|
|||||||
int epfd;
|
int epfd;
|
||||||
size_t num;
|
size_t num;
|
||||||
size_t max;
|
size_t max;
|
||||||
struct net_connection** conns;
|
struct net_connection_epoll** conns;
|
||||||
struct epoll_event events[EPOLL_EVBUFFER];
|
struct epoll_event events[EPOLL_EVBUFFER];
|
||||||
time_t now;
|
time_t now;
|
||||||
struct timeout_queue timeout_queue;
|
struct timeout_queue timeout_queue;
|
||||||
@ -54,7 +46,7 @@ struct net_backend
|
|||||||
|
|
||||||
static struct net_backend* g_backend = 0;
|
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];
|
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 }",
|
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->num = 0;
|
||||||
g_backend->max = max;
|
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));
|
memset(g_backend->events, 0, sizeof(g_backend->events));
|
||||||
|
|
||||||
g_backend->now = time(0);
|
g_backend->now = time(0);
|
||||||
@ -121,19 +113,23 @@ int net_backend_process()
|
|||||||
|
|
||||||
for (n = 0; n < res; n++)
|
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;
|
int ev = 0;
|
||||||
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
||||||
if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct timeout_queue* net_backend_get_timeout_queue()
|
||||||
|
{
|
||||||
|
return &g_backend->timeout_queue;
|
||||||
|
}
|
||||||
|
|
||||||
struct net_connection* net_con_create()
|
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;
|
con->sd = -1;
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
@ -143,8 +139,9 @@ void net_con_destroy(struct net_connection* con)
|
|||||||
hub_free(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->sd = sd;
|
||||||
con->flags = NET_INITIALIZED;
|
con->flags = NET_INITIALIZED;
|
||||||
con->callback = callback;
|
con->callback = callback;
|
||||||
@ -176,10 +173,11 @@ void net_con_reinitialize(struct net_connection* con, net_connection_cb callback
|
|||||||
net_con_update(con, events);
|
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;
|
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;
|
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
@ -211,8 +209,9 @@ void net_con_update(struct net_connection* con, int events)
|
|||||||
net_con_print("MOD", con);
|
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))
|
if (!(con->flags & NET_INITIALIZED))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -239,68 +238,4 @@ int net_con_close(struct net_connection* con)
|
|||||||
return 0;
|
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 */
|
#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
|
#define uhub_assert assert
|
||||||
|
|
||||||
#ifdef USE_LIBEVENT
|
|
||||||
#include <event.h>
|
|
||||||
#else
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#define USE_EPOLL
|
#define USE_EPOLL
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#endif
|
#else
|
||||||
|
#define USE_SELECT
|
||||||
|
#include <sys/select.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
|
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
|
||||||
|
@ -330,7 +330,7 @@ void runloop(size_t clients)
|
|||||||
|
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
event_base_loop(net_get_evbase(), EVLOOP_ONCE);
|
net_backend_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < clients; n++)
|
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)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
parse_command_line(argc, argv);
|
parse_command_line(argc, argv);
|
||||||
|
|
||||||
net_initialize();
|
net_initialize();
|
||||||
setup_signal_handlers();
|
|
||||||
|
|
||||||
hub_log_initialize(NULL, 0);
|
hub_log_initialize(NULL, 0);
|
||||||
hub_set_log_verbosity(1000);
|
hub_set_log_verbosity(1000);
|
||||||
|
|
||||||
runloop(cfg_clients);
|
runloop(cfg_clients);
|
||||||
|
|
||||||
shutdown_signal_handlers();
|
|
||||||
net_destroy();
|
net_destroy();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int running = 1;
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@ -79,7 +80,10 @@ int main(int argc, char** argv)
|
|||||||
ADC_client_set_callback(&client, handle);
|
ADC_client_set_callback(&client, handle);
|
||||||
ADC_client_connect(&client, argv[1]);
|
ADC_client_connect(&client, argv[1]);
|
||||||
|
|
||||||
event_dispatch();
|
while (running)
|
||||||
|
{
|
||||||
|
net_backend_process();
|
||||||
|
}
|
||||||
|
|
||||||
ADC_client_destroy(&client);
|
ADC_client_destroy(&client);
|
||||||
net_destroy();
|
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);
|
size_t pos = (evt->timestamp % t->max);
|
||||||
struct timeout_evt* first = t->events[pos];
|
struct timeout_evt* first = t->events[pos];
|
||||||
|
|
||||||
if (!first)
|
if (!first || !evt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (first == evt)
|
if (first == evt)
|
||||||
|
Loading…
Reference in New Issue
Block a user