|
|
@@ -49,6 +49,10 @@ |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <sys/time.h> |
|
|
|
#ifdef HAVE_SYS_SELECT_H |
|
|
|
|
|
|
|
// You may need to override this! |
|
|
|
// #define FD_SETSIZE 2048 |
|
|
|
|
|
|
|
#include <sys/select.h> |
|
|
|
#endif |
|
|
|
#ifdef HAVE_KEVENT |
|
|
@@ -1076,6 +1080,15 @@ core_connect(Conn * s) |
|
|
|
goto failure; |
|
|
|
} |
|
|
|
|
|
|
|
if (sd > FD_SETSIZE) { |
|
|
|
fprintf(stderr, |
|
|
|
"%s.core_connect.socket: sd > FD_SETSIZE (%d)\n", |
|
|
|
prog_name, |
|
|
|
FD_SETSIZE); |
|
|
|
close(sd); |
|
|
|
goto failure; |
|
|
|
} |
|
|
|
|
|
|
|
if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) { |
|
|
|
fprintf(stderr, "%s.core_connect.fcntl: %s\n", |
|
|
|
prog_name, strerror(errno)); |
|
|
@@ -1445,14 +1458,57 @@ core_loop(void) |
|
|
|
} |
|
|
|
} |
|
|
|
#else |
|
|
|
|
|
|
|
static void |
|
|
|
check_conn(int sd, int is_readable, int is_writable) |
|
|
|
{ |
|
|
|
Conn *conn; |
|
|
|
Any_Type arg; |
|
|
|
|
|
|
|
/* Don't bother doing anything if we're not ready */ |
|
|
|
if ((is_readable || is_writable) == 0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* only handle sockets that |
|
|
|
* haven't timed out yet |
|
|
|
*/ |
|
|
|
conn = sd_to_conn[sd]; |
|
|
|
conn_inc_ref(conn); |
|
|
|
|
|
|
|
if (conn->watchdog) { |
|
|
|
timer_cancel(conn->watchdog); |
|
|
|
conn->watchdog = 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (conn->state == S_CONNECTING) { |
|
|
|
#ifdef HAVE_SSL |
|
|
|
if (param.use_ssl) |
|
|
|
core_ssl_connect(conn); |
|
|
|
else |
|
|
|
#endif |
|
|
|
if (is_writable) { |
|
|
|
clear_active(conn, WRITE); |
|
|
|
conn->state = S_CONNECTED; |
|
|
|
arg.l = 0; |
|
|
|
event_signal(EV_CONN_CONNECTED, (Object*)conn, arg); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (is_writable && conn->sendq) |
|
|
|
do_send(conn); |
|
|
|
if (is_readable && conn->recvq) |
|
|
|
do_recv(conn); |
|
|
|
} |
|
|
|
conn_dec_ref(conn); |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
core_loop(void) |
|
|
|
{ |
|
|
|
int is_readable, is_writable, n, sd, bit, min_i, max_i, i = 0; |
|
|
|
int is_readable, is_writable, n, sd; |
|
|
|
fd_set readable, writable; |
|
|
|
fd_mask mask; |
|
|
|
Any_Type arg; |
|
|
|
Conn *conn; |
|
|
|
|
|
|
|
while (running) { |
|
|
|
struct timeval tv = select_timeout; |
|
|
@@ -1461,8 +1517,6 @@ core_loop(void) |
|
|
|
|
|
|
|
readable = rdfds; |
|
|
|
writable = wrfds; |
|
|
|
min_i = min_sd / NFDBITS; |
|
|
|
max_i = max_sd / NFDBITS; |
|
|
|
|
|
|
|
SYSCALL(SELECT, n = select(max_sd + 1, &readable, &writable, 0, &tv)); |
|
|
|
|
|
|
@@ -1476,68 +1530,19 @@ core_loop(void) |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
while (n > 0) { |
|
|
|
/* |
|
|
|
* find the index of the fdmask that has something |
|
|
|
* going on: |
|
|
|
*/ |
|
|
|
do { |
|
|
|
++i; |
|
|
|
if (i > max_i) |
|
|
|
i = min_i; |
|
|
|
|
|
|
|
assert(i <= max_i); |
|
|
|
mask = readable.fds_bits[i] | writable.fds_bits[i]; |
|
|
|
} while (!mask); |
|
|
|
bit = 0; |
|
|
|
sd = i * NFDBITS + bit; |
|
|
|
do { |
|
|
|
if (mask & 1) { |
|
|
|
--n; |
|
|
|
is_readable = (FD_ISSET(sd, &readable) && FD_ISSET(sd, &rdfds)); |
|
|
|
is_writable = (FD_ISSET(sd, &writable) && FD_ISSET(sd, &wrfds)); |
|
|
|
|
|
|
|
if (is_readable || is_writable) { |
|
|
|
/* |
|
|
|
* only handle sockets that |
|
|
|
* haven't timed out yet |
|
|
|
*/ |
|
|
|
conn = sd_to_conn[sd]; |
|
|
|
conn_inc_ref(conn); |
|
|
|
|
|
|
|
if (conn->watchdog) { |
|
|
|
timer_cancel(conn->watchdog); |
|
|
|
conn->watchdog = 0; |
|
|
|
} |
|
|
|
if (conn->state == S_CONNECTING) { |
|
|
|
#ifdef HAVE_SSL |
|
|
|
if (param.use_ssl) |
|
|
|
core_ssl_connect(conn); |
|
|
|
else |
|
|
|
#endif |
|
|
|
if (is_writable) { |
|
|
|
clear_active(conn, WRITE); |
|
|
|
conn->state = S_CONNECTED; |
|
|
|
arg.l = 0; |
|
|
|
event_signal(EV_CONN_CONNECTED, (Object*)conn, arg); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (is_writable && conn->sendq) |
|
|
|
do_send(conn); |
|
|
|
if (is_readable && conn->recvq) |
|
|
|
do_recv(conn); |
|
|
|
} |
|
|
|
|
|
|
|
conn_dec_ref(conn); |
|
|
|
|
|
|
|
if (n > 0) |
|
|
|
timer_tick(); |
|
|
|
} |
|
|
|
} |
|
|
|
mask = ((u_long) mask) >> 1; |
|
|
|
++sd; |
|
|
|
} while (mask); |
|
|
|
} |
|
|
|
/* XXX totally suboptimal loop, but less potentially problematic */ |
|
|
|
|
|
|
|
for (sd = 0; sd <= max_sd; sd++) { |
|
|
|
is_readable = (FD_ISSET(sd, &readable) && FD_ISSET(sd, &rdfds)); |
|
|
|
is_writable = (FD_ISSET(sd, &writable) && FD_ISSET(sd, &wrfds)); |
|
|
|
if (is_readable || is_writable) |
|
|
|
check_conn(sd, is_readable, is_writable); |
|
|
|
|
|
|
|
/* XXX TODO: totally can bail out if we've seen 'n' FDs */ |
|
|
|
} |
|
|
|
|
|
|
|
/* Do timer tick at the end of the connection check */ |
|
|
|
timer_tick(); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|