Work in progress: libevent use one event per fd.

Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
This commit is contained in:
Jan Vidar Krey 2009-03-26 01:05:40 +01:00
parent 904288a2a2
commit 478d8b9dd2
5 changed files with 107 additions and 93 deletions

View File

@ -49,8 +49,6 @@ static void log_user_nick_change(struct user* u, const char* nick)
/* Send MOTD, do logging etc */ /* Send MOTD, do logging etc */
void on_login_success(struct user* u) void on_login_success(struct user* u)
{ {
struct timeval timeout = { TIMEOUT_IDLE, 0 };
/* Send user list of all existing users */ /* Send user list of all existing users */
if (!send_user_list(u)) if (!send_user_list(u))
return; return;
@ -69,10 +67,6 @@ void on_login_success(struct user* u)
/* Send message of the day (if any) */ /* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */ if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_motd(u); hub_send_motd(u);
/* reset to idle timeout */
if (u->ev_handle)
event_add(u->ev_handle, &timeout);
} }
void on_login_failure(struct user* u, enum status_message msg) void on_login_failure(struct user* u, enum status_message msg)

View File

@ -20,31 +20,14 @@
#include "uhub.h" #include "uhub.h"
void net_on_read(int fd, short ev, void *arg) static int on_read(struct user* user)
{ {
static char buf[MAX_RECV_BUF]; static char buf[MAX_RECV_BUF];
struct user* user = (struct user*) arg;
char* pos;
size_t offset; size_t offset;
size_t buflen; size_t buflen;
ssize_t size; ssize_t size;
int more = 1; int more = 1;
int flag_close = 0; char* pos;
hub_log(log_trace, "net_on_read() : fd=%d, ev=%d, arg=%p", fd, (int) ev, arg);
if (ev == EV_TIMEOUT)
{
more = 0;
if (user_is_connecting(user))
{
flag_close = quit_timeout;
}
else
{
hub_send_ping(user);
}
}
while (more) while (more)
{ {
@ -55,17 +38,16 @@ void net_on_read(int fd, short ev, void *arg)
offset = user->recv_buf_offset; offset = user->recv_buf_offset;
} }
size = net_recv(fd, &buf[offset], MAX_RECV_BUF - offset, 0); size = net_recv(user->sd, &buf[offset], MAX_RECV_BUF - offset, 0);
if (size == -1) if (size == -1)
{ {
if (net_error() != EWOULDBLOCK) if (net_error() != EWOULDBLOCK)
flag_close = quit_socket_error; return quit_socket_error;
break; break;
} }
else if (size == 0) else if (size == 0)
{ {
flag_close = quit_disconnected; return quit_disconnected;
break;
} }
else else
{ {
@ -87,9 +69,7 @@ void net_on_read(int fd, short ev, void *arg)
{ {
if (hub_handle_message(user, &buf[handled], msglen) == -1) if (hub_handle_message(user, &buf[handled], msglen) == -1)
{ {
flag_close = quit_protocol_error; return quit_protocol_error;
more = 0;
break;
} }
} }
} }
@ -124,8 +104,7 @@ void net_on_read(int fd, short ev, void *arg)
} }
else else
{ {
flag_close = quit_memory_error; return quit_memory_error;
break;
} }
} }
} }
@ -140,39 +119,14 @@ void net_on_read(int fd, short ev, void *arg)
} }
} }
} }
return 0;
if (flag_close)
{
user_disconnect(user, flag_close);
return;
}
if (user_is_logged_in(user))
{
if (user->ev_handle)
{
struct timeval timeout = { TIMEOUT_IDLE, 0 };
event_add(user->ev_handle, &timeout);
}
}
else if (user_is_connecting(user))
{
if (user->ev_handle)
{
struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 };
event_add(user->ev_handle, &timeout);
}
}
} }
static int on_write(struct user* user)
void net_on_write(int fd, short ev, void *arg)
{ {
struct user* user = (struct user*) arg;
struct adc_message* msg; struct adc_message* msg;
int ret; int ret;
int length; int length;
int close_flag = 0;
msg = list_get_first(user->send_queue); msg = list_get_first(user->send_queue);
while (msg) while (msg)
@ -182,12 +136,10 @@ void net_on_write(int fd, short ev, void *arg)
if (ret == 0 || (ret == -1 && net_error() == EWOULDBLOCK)) if (ret == 0 || (ret == -1 && net_error() == EWOULDBLOCK))
{ {
close_flag = 0; return 0;
break;
} }
else if (ret > 0) else if (ret > 0)
{ {
user->tm_last_write = time(NULL); user->tm_last_write = time(NULL);
if (ret == length) if (ret == length)
@ -216,32 +168,74 @@ void net_on_write(int fd, short ev, void *arg)
} }
else else
{ {
close_flag = quit_socket_error; return quit_socket_error;
break;
} }
msg = list_get_first(user->send_queue); msg = list_get_first(user->send_queue);
} }
return 0;
}
if (close_flag) void on_net_event(int fd, short ev, void *arg)
{
struct user* user = (struct user*) arg;
int want_close = 0;
int want_write = 0;
hub_log(log_debug, "on_net_event() : fd=%d, ev=%d, user=%s", fd, (int) ev, user);
if (ev == EV_TIMEOUT)
{ {
user_disconnect(user, close_flag);
hub_log(log_debug, "EV_TIMEOUT");
if (user_is_connecting(user))
{
want_close = quit_timeout;
} }
else else
{ {
if (user->send_queue_size > 0 && user->ev_handle) hub_send_ping(user);
event_add(user->ev_handle, NULL); }
}
else
{
if (ev & EV_WRITE)
{
want_close = on_write(user);
want_write = (user->send_queue_size != 0);
}
if (!want_close && ev & EV_READ)
{
want_close = on_read(user);
}
}
if (want_close)
{
user_disconnect(user, want_close);
return;
}
if (user_is_logged_in(user))
{
user_trigger_update(user, want_write, TIMEOUT_IDLE);
}
else if (user_is_connecting(user))
{
user_trigger_update(user, want_write, TIMEOUT_HANDSHAKE);
} }
} }
void net_on_accept(int server_fd, short ev, void *arg) void net_on_accept(int server_fd, short ev, void *arg)
{ {
struct hub_info* hub = (struct hub_info*) arg; struct hub_info* hub = (struct hub_info*) arg;
struct user* user = 0; struct user* user = 0;
struct ip_addr_encap ipaddr; struct ip_addr_encap ipaddr;
const char* addr; const char* addr;
struct timeval timeout = { TIMEOUT_CONNECTED, 0 };
for (;;) for (;;)
{ {
@ -285,10 +279,7 @@ void net_on_accept(int server_fd, short ev, void *arg)
net_set_nonblocking(fd, 1); net_set_nonblocking(fd, 1);
net_set_nosigpipe(fd, 1); net_set_nosigpipe(fd, 1);
user_trigger_init(user);
event_set(user->ev_handle, fd, EV_READ | EV_PERSIST, net_on_read, user);
event_base_set(hub->evbase, user->ev_handle);
event_add(user->ev_handle, &timeout);
} }
} }

View File

@ -20,10 +20,19 @@
#ifndef HAVE_UHUB_NET_EVENT_H #ifndef HAVE_UHUB_NET_EVENT_H
#define HAVE_UHUB_NET_EVENT_H #define HAVE_UHUB_NET_EVENT_H
struct user;
extern void on_net_event(int fd, short ev, void *arg);
/** /**
* Network callback to accept incoming connections. * Network callback to accept incoming connections.
*/ */
extern void net_on_accept(int fd, short ev, void *arg); extern void net_on_accept(int fd, short ev, void *arg);
/**
*
*/
extern void net_update_trigger(struct user* user, int write, struct timeval timeout);
#endif /* HAVE_UHUB_NET_EVENT_H */ #endif /* HAVE_UHUB_NET_EVENT_H */

View File

@ -63,15 +63,8 @@ void user_destroy(struct user* user)
{ {
hub_log(log_trace, "user_destroy(), user=%p", user); hub_log(log_trace, "user_destroy(), user=%p", user);
if (user->ev_handle) user_trigger_shutdown(user);
{
event_del(user->ev_handle);
hub_free(user->ev_handle);
user->ev_handle = 0;
}
net_close(user->sd); net_close(user->sd);
adc_msg_free(user->info); adc_msg_free(user->info);
user_clear_feature_cast_support(user); user_clear_feature_cast_support(user);
@ -204,12 +197,7 @@ void user_disconnect(struct user* user, int reason)
} }
/* dont read more data from this user */ /* dont read more data from this user */
if (user->ev_handle) user_flag_set(user, flag_ignore);
{
event_del(user->ev_handle);
hub_free(user->ev_handle);
user->ev_handle = 0;
}
hub_log(log_trace, "user_disconnect(), user=%p, reason=%d, state=%d", user, reason, user->state); hub_log(log_trace, "user_disconnect(), user=%p, reason=%d, state=%d", user, reason, user->state);
@ -294,6 +282,36 @@ int user_is_disconnecting(struct user* user)
return 0; return 0;
} }
void user_trigger_init(struct user* user)
{
if (user->ev_handle)
{
struct timeval timeout = { TIMEOUT_CONNECTED, 0 };
event_set(user->ev_handle, user->sd, EV_READ | EV_PERSIST, on_net_event, user);
event_base_set(user->hub->evbase, user->ev_handle);
event_add(user->ev_handle, &timeout);
}
}
void user_trigger_update(struct user* user, int w, int timeout_sec)
{
if (user->ev_handle)
{
struct timeval timeout = { timeout_sec, 0 };
int f = w ? EV_WRITE | EV_READ | EV_PERSIST : EV_READ | EV_PERSIST;
event_del(user->ev_handle);
event_set(user->ev_handle, user->sd, f, on_net_event, user);
event_base_set(user->hub->evbase, user->ev_handle);
event_add(user->ev_handle, &timeout);
}
}
void user_trigger_shutdown(struct user* user)
{
if (user->ev_handle)
{
event_del(user->ev_handle);
hub_free(user->ev_handle);
user->ev_handle = 0;
}
}

View File

@ -255,7 +255,9 @@ extern int user_set_feature_cast_support(struct user* u, char feature[4]);
*/ */
extern void user_clear_feature_cast_support(struct user* u); extern void user_clear_feature_cast_support(struct user* u);
extern void user_trigger_init(struct user* user);
extern void user_trigger_update(struct user* user, int w, int timeout_sec);
extern void user_trigger_shutdown(struct user* user);
#endif /* HAVE_UHUB_USER_H */ #endif /* HAVE_UHUB_USER_H */