From 29d6d59d3633cb81e3cb491c24cc224819021c8e Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 27 Aug 2009 14:15:18 +0200 Subject: [PATCH] Misc connection changes. --- src/network/connection.c | 67 ++++++++++++++++++++++++++++++++++------ src/network/connection.h | 17 +++++++++- src/tools/adcrush.c | 45 +++++++++++++++++---------- 3 files changed, 103 insertions(+), 26 deletions(-) diff --git a/src/network/connection.c b/src/network/connection.c index e6d1df6..a0b0487 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -19,8 +19,8 @@ #include "uhub.h" -#define NET_WANT_READ 0x0001 -#define NET_WANT_WRITE 0x0002 +#define NET_WANT_READ NET_EVENT_READ +#define NET_WANT_WRITE NET_EVENT_WRITE #define NET_WANT_ACCEPT 0x0008 #define NET_WANT_SSL_READ 0x0010 #define NET_WANT_SSL_WRITE 0x0020 @@ -31,6 +31,7 @@ #define NET_PROCESSING_BUSY 0x8000 #define NET_CLEANUP 0x4000 #define NET_INITIALIZED 0x2000 +#define NET_TIMER_ENABLED 0x1000 extern struct hub_info* g_hub; @@ -66,6 +67,19 @@ static inline int net_con_convert_from_libevent_mask(int ev) return events; } +static void net_con_event(int fd, short ev, void *arg); + +void net_con_set(struct net_connection* 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; + + 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_event(int fd, short ev, void *arg) { @@ -126,12 +140,7 @@ static void net_con_event(int fd, short ev, void *arg) } else { - int set_ev = 0; - if (net_con_flag_get(con, NET_WANT_READ)) set_ev |= EV_READ; - if (net_con_flag_get(con, NET_WANT_WRITE)) set_ev |= EV_WRITE; - event_set(&con->event, con->sd, set_ev, net_con_event, con); - event_add(&con->event, 0); - net_con_flag_set(con, NET_INITIALIZED); + net_con_set(con); } } @@ -175,6 +184,8 @@ void net_con_initialize(struct net_connection* con, int sd, struct ip_addr_encap #endif } + + void net_con_update(struct net_connection* con, int ev) { if (ev & NET_EVENT_READ) @@ -372,15 +383,19 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) void net_con_set_timeout(struct net_connection* con, int seconds) { 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) { - if (evtimer_initialized(&con->timeout) && evtimer_pending(&con->timeout, 0)) + if (net_con_flag_get(con, NET_TIMER_ENABLED)) { evtimer_del(&con->timeout); + net_con_flag_unset(con, NET_TIMER_ENABLED); } } @@ -441,4 +456,38 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, int ssl_mode) } #endif /* SSL_SUPPORT */ +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; +} diff --git a/src/network/connection.h b/src/network/connection.h index 92f4e10..6f85270 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -29,7 +29,22 @@ #define NET_EVENT_CLOSED 0x2000 /* Socket closed */ struct net_connection; +struct net_timer; + typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr); +typedef void (*net_timeout_cb)(struct net_timer*, void* ptr); + +struct net_timer +{ + unsigned int initialized; + struct event timeout; + net_timeout_cb callback; + void* ptr; +}; + +extern void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr); +extern void net_timer_reset(struct net_timer* timer, int seconds); +extern void net_timer_shutdown(struct net_timer* timer); struct net_connection { @@ -38,7 +53,7 @@ struct net_connection void* ptr; /** data pointer */ net_connection_cb callback; /** Callback function */ struct event event; /** libevent struct for read/write events */ - struct event timeout; /** timeout handling */ + struct event timeout; /** Used for internal timeout handling */ struct ip_addr_encap ipaddr; /** IP address of peer */ time_t last_recv; /** Timestamp for last recv() */ time_t last_send; /** Timestamp for last send() */ diff --git a/src/tools/adcrush.c b/src/tools/adcrush.c index f67758b..1f363ff 100644 --- a/src/tools/adcrush.c +++ b/src/tools/adcrush.c @@ -170,7 +170,8 @@ struct ADC_client size_t s_offset; size_t r_offset; size_t timeout; - struct net_connection con; + struct net_connection* con; + struct net_timer* timer; }; @@ -273,7 +274,7 @@ static void client_reschedule_timeout(struct ADC_client* client) client->timeout = get_wait_rand(MAX(next_timeout, 1)); if (!client->timeout) client->timeout++; - net_con_set_timeout(&client->con, client->timeout); + net_timer_reset(client->timer, client->timeout); } static void set_state_timeout(struct ADC_client* client, enum protocolState state) @@ -284,7 +285,7 @@ static void set_state_timeout(struct ADC_client* client, enum protocolState stat static void send_client(struct ADC_client* client, char* msg) { - int ret = net_con_send(&client->con, msg, strlen(msg)); + int ret = net_con_send(client->con, msg, strlen(msg)); if (cfg_debug > 1) { @@ -312,7 +313,7 @@ static void send_client(struct ADC_client* client, char* msg) static void ADC_client_on_connected(struct ADC_client* client) { - net_con_update(&client->con, NET_EVENT_READ); + net_con_update(client->con, NET_EVENT_READ); send_client(client, ADC_HANDSHAKE); set_state_timeout(client, ps_protocol); bot_output(client, LVL_INFO, "connected."); @@ -320,7 +321,10 @@ static void ADC_client_on_connected(struct ADC_client* client) static void ADC_client_on_disconnected(struct ADC_client* client) { - net_con_close(&client->con); + net_con_close(client->con); + hub_free(client->con); + client->con = 0; + bot_output(client, LVL_INFO, "disconnected."); set_state_timeout(client, ps_none); } @@ -366,7 +370,7 @@ static int recv_client(struct ADC_client* client) ssize_t size = 0; if (cfg_mode != mode_performance || (cfg_mode == mode_performance && (get_wait_rand(100) < (90 - (15 * cfg_level))))) { - size = net_con_recv(&client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset); + size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset); } else { @@ -491,7 +495,7 @@ static int recv_client(struct ADC_client* client) void ADC_client_connect(struct ADC_client* client) { - int ret = net_connect(client->con.sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in)); + int ret = net_connect(client->con->sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in)); if (ret == 0 || (ret == -1 && net_error() == EISCONN)) { ADC_client_on_connected(client); @@ -500,7 +504,7 @@ void ADC_client_connect(struct ADC_client* client) { if (client->state != ps_conn) { - net_con_update(&client->con, NET_EVENT_READ | NET_EVENT_WRITE); + net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); set_state_timeout(client, ps_conn); bot_output(client, LVL_INFO, "connecting..."); } @@ -521,9 +525,9 @@ void ADC_client_wait_connect(struct ADC_client* client) void ADC_client_disconnect(struct ADC_client* client) { - if (client->con.sd != -1) + if (client->con->sd != -1) { - net_con_close(&client->con); + net_con_close(client->con); bot_output(client, LVL_INFO, "disconnected."); if (running) @@ -685,6 +689,16 @@ static void perf_normal_action(struct ADC_client* client) client_reschedule_timeout(client); } +void timer_callback(struct net_timer* t, void* arg) +{ + struct ADC_client* client = (struct ADC_client*) arg; + if (client->state == ps_none) + { + ADC_client_create(client, client->num); + ADC_client_connect(client); + } +} + void event_callback(struct net_connection* con, int events, void *arg) { struct ADC_client* client = (struct ADC_client*) arg; @@ -697,11 +711,6 @@ void event_callback(struct net_connection* con, int events, void *arg) { if (client->state == ps_none) { - if (client->con.sd == -1) - { - ADC_client_create(client, client->num); - } - ADC_client_connect(client); } } @@ -735,7 +744,10 @@ int ADC_client_create(struct ADC_client* client, int num) int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sd == -1) return -1; - net_con_initialize(&client->con, sd, 0, event_callback, client, 0); + client->con = hub_malloc(sizeof(struct net_connection)); + client->timer = hub_malloc(sizeof(struct net_timer)); + net_con_initialize(client->con, sd, 0, event_callback, client, 0); + net_timer_initialize(client->timer, timer_callback, client); set_state_timeout(client, ps_none); return 0; } @@ -743,6 +755,7 @@ int ADC_client_create(struct ADC_client* client, int num) void ADC_client_destroy(struct ADC_client* client) { ADC_client_disconnect(client); + net_timer_shutdown(client->timer); }