loop through addresses for TCP connect or listen

svn: r1232
This commit is contained in:
Matthew Flatt 2005-11-04 14:10:29 +00:00
parent 0dd1f6a2ab
commit 1fc7c09a67
3 changed files with 218 additions and 212 deletions

View File

@ -3006,36 +3006,34 @@ int mark_print_params_FIXUP(void *p) {
#ifdef MARKS_FOR_NETWORK_C #ifdef MARKS_FOR_NETWORK_C
int mark_listener_SIZE(void *p) { int mark_listener_SIZE(void *p) {
listener_t *l = (listener_t *)p;
return return
gcBYTES_TO_WORDS(sizeof(listener_t)); gcBYTES_TO_WORDS(sizeof(listener_t) + ((l->count - 1) * sizeof(tcp_t)));
} }
int mark_listener_MARK(void *p) { int mark_listener_MARK(void *p) {
listener_t *l = (listener_t *)p; listener_t *l = (listener_t *)p;
gcMARK(l->mref); gcMARK(l->mref);
#ifdef USE_MAC_TCP
gcMARK(l->datas);
#endif
return return
gcBYTES_TO_WORDS(sizeof(listener_t)); gcBYTES_TO_WORDS(sizeof(listener_t) + ((l->count - 1) * sizeof(tcp_t)));
} }
int mark_listener_FIXUP(void *p) { int mark_listener_FIXUP(void *p) {
listener_t *l = (listener_t *)p; listener_t *l = (listener_t *)p;
gcFIXUP(l->mref); gcFIXUP(l->mref);
#ifdef USE_MAC_TCP
gcFIXUP(l->datas);
#endif
return return
gcBYTES_TO_WORDS(sizeof(listener_t)); gcBYTES_TO_WORDS(sizeof(listener_t) + ((l->count - 1) * sizeof(tcp_t)));
} }
#define mark_listener_IS_ATOMIC 0 #define mark_listener_IS_ATOMIC 0
#define mark_listener_IS_CONST_SIZE 1 #define mark_listener_IS_CONST_SIZE 0
#ifdef USE_TCP #ifdef USE_TCP
@ -3049,10 +3047,6 @@ int mark_tcp_MARK(void *p) {
gcMARK(tcp->b.buffer); gcMARK(tcp->b.buffer);
gcMARK(tcp->b.out_buffer); gcMARK(tcp->b.out_buffer);
# ifdef USE_MAC_TCP
gcMARK(tcp->tcp);
gcMARK(tcp->activeRcv);
# endif
return return
gcBYTES_TO_WORDS(sizeof(Scheme_Tcp)); gcBYTES_TO_WORDS(sizeof(Scheme_Tcp));
@ -3063,10 +3057,6 @@ int mark_tcp_FIXUP(void *p) {
gcFIXUP(tcp->b.buffer); gcFIXUP(tcp->b.buffer);
gcFIXUP(tcp->b.out_buffer); gcFIXUP(tcp->b.out_buffer);
# ifdef USE_MAC_TCP
gcFIXUP(tcp->tcp);
gcFIXUP(tcp->activeRcv);
# endif
return return
gcBYTES_TO_WORDS(sizeof(Scheme_Tcp)); gcBYTES_TO_WORDS(sizeof(Scheme_Tcp));
@ -3076,35 +3066,6 @@ int mark_tcp_FIXUP(void *p) {
#define mark_tcp_IS_CONST_SIZE 1 #define mark_tcp_IS_CONST_SIZE 1
# ifdef USE_MAC_TCP
int mark_write_data_SIZE(void *p) {
return
gcBYTES_TO_WORDS(sizeof(WriteData));
}
int mark_write_data_MARK(void *p) {
WriteData *d = (WriteData *)p;
gcMARK(d->xpb);
return
gcBYTES_TO_WORDS(sizeof(WriteData));
}
int mark_write_data_FIXUP(void *p) {
WriteData *d = (WriteData *)p;
gcFIXUP(d->xpb);
return
gcBYTES_TO_WORDS(sizeof(WriteData));
}
#define mark_write_data_IS_ATOMIC 0
#define mark_write_data_IS_CONST_SIZE 1
# endif
# ifdef UDP_IS_SUPPORTED # ifdef UDP_IS_SUPPORTED
int mark_udp_SIZE(void *p) { int mark_udp_SIZE(void *p) {
return return

View File

@ -1204,16 +1204,14 @@ END print;
START network; START network;
mark_listener { mark_listener {
mark:
listener_t *l = (listener_t *)p; listener_t *l = (listener_t *)p;
mark:
gcMARK(l->mref); gcMARK(l->mref);
#ifdef USE_MAC_TCP
gcMARK(l->datas);
#endif
size: size:
gcBYTES_TO_WORDS(sizeof(listener_t)); gcBYTES_TO_WORDS(sizeof(listener_t) + ((l->count - 1) * sizeof(tcp_t)));
} }
#ifdef USE_TCP #ifdef USE_TCP
@ -1223,27 +1221,11 @@ mark_tcp {
gcMARK(tcp->b.buffer); gcMARK(tcp->b.buffer);
gcMARK(tcp->b.out_buffer); gcMARK(tcp->b.out_buffer);
# ifdef USE_MAC_TCP
gcMARK(tcp->tcp);
gcMARK(tcp->activeRcv);
# endif
size: size:
gcBYTES_TO_WORDS(sizeof(Scheme_Tcp)); gcBYTES_TO_WORDS(sizeof(Scheme_Tcp));
} }
# ifdef USE_MAC_TCP
mark_write_data {
mark:
WriteData *d = (WriteData *)p;
gcMARK(d->xpb);
size:
gcBYTES_TO_WORDS(sizeof(WriteData));
}
# endif
# ifdef UDP_IS_SUPPORTED # ifdef UDP_IS_SUPPORTED
mark_udp { mark_udp {
mark: mark:

View File

@ -111,8 +111,9 @@ typedef SOCKET tcp_t;
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP
typedef struct { typedef struct {
Scheme_Object so; Scheme_Object so;
tcp_t s;
Scheme_Custodian_Reference *mref; Scheme_Custodian_Reference *mref;
int count;
tcp_t s[1];
} listener_t; } listener_t;
#endif #endif
@ -834,7 +835,7 @@ static void TCP_INIT(char *name)
/*========================================================================*/ /*========================================================================*/
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP
#define LISTENER_WAS_CLOSED(x) (((listener_t *)(x))->s == INVALID_SOCKET) #define LISTENER_WAS_CLOSED(x) (((listener_t *)(x))->s[0] == INVALID_SOCKET)
#endif #endif
#ifndef LISTENER_WAS_CLOSED #ifndef LISTENER_WAS_CLOSED
#define LISTENER_WAS_CLOSED(x) 0 #define LISTENER_WAS_CLOSED(x) 0
@ -843,14 +844,15 @@ static void TCP_INIT(char *name)
/* Forward declaration */ /* Forward declaration */
static int stop_listener(Scheme_Object *o); static int stop_listener(Scheme_Object *o);
static int tcp_check_accept(Scheme_Object *listener) static int tcp_check_accept(Scheme_Object *_listener)
{ {
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP
tcp_t s; tcp_t s, mx;
listener_t *listener = (listener_t *)_listener;
DECL_FDSET(readfds, 1); DECL_FDSET(readfds, 1);
DECL_FDSET(exnfds, 1); DECL_FDSET(exnfds, 1);
struct timeval time = {0, 0}; struct timeval time = {0, 0};
int sr; int sr, i;
INIT_DECL_FDSET(readfds, 1); INIT_DECL_FDSET(readfds, 1);
INIT_DECL_FDSET(exnfds, 1); INIT_DECL_FDSET(exnfds, 1);
@ -858,33 +860,52 @@ static int tcp_check_accept(Scheme_Object *listener)
if (LISTENER_WAS_CLOSED(listener)) if (LISTENER_WAS_CLOSED(listener))
return 1; return 1;
s = ((listener_t *)listener)->s;
MZ_FD_ZERO(readfds); MZ_FD_ZERO(readfds);
MZ_FD_ZERO(exnfds); MZ_FD_ZERO(exnfds);
mx = 0;
for (i = 0; i < listener->count; i++) {
s = listener->s[i];
MZ_FD_SET(s, readfds); MZ_FD_SET(s, readfds);
MZ_FD_SET(s, exnfds); MZ_FD_SET(s, exnfds);
if (s > mx)
mx = s;
}
do { do {
sr = select(s + 1, readfds, NULL, exnfds, &time); sr = select(mx + 1, readfds, NULL, exnfds, &time);
} while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR)); } while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR));
if (sr) {
for (i = 0; i < listener->count; i++) {
s = listener->s[i];
if (FD_ISSET(s, readfds)
|| FD_ISSET(s, exnfds))
return i + 1;
}
}
return sr; return sr;
#endif #endif
} }
static void tcp_accept_needs_wakeup(Scheme_Object *listener, void *fds) static void tcp_accept_needs_wakeup(Scheme_Object *_listener, void *fds)
{ {
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP
if (!LISTENER_WAS_CLOSED(listener)) { if (!LISTENER_WAS_CLOSED(_listener)) {
tcp_t s = ((listener_t *)listener)->s; listener_t *listener = (listener_t *)_listener;
int i;
tcp_t s;
void *fds2; void *fds2;
fds2 = MZ_GET_FDSET(fds, 2); fds2 = MZ_GET_FDSET(fds, 2);
for (i = 0; i < listener->count; i++) {
s = listener->s[i];
MZ_FD_SET(s, (fd_set *)fds); MZ_FD_SET(s, (fd_set *)fds);
MZ_FD_SET(s, (fd_set *)fds2); MZ_FD_SET(s, (fd_set *)fds2);
} }
}
#endif #endif
} }
@ -903,8 +924,9 @@ static int tcp_check_connect(Scheme_Object *connector_p)
s = *(tcp_t *)connector_p; s = *(tcp_t *)connector_p;
MZ_FD_ZERO(writefds); MZ_FD_ZERO(writefds);
MZ_FD_SET(s, writefds);
MZ_FD_ZERO(exnfds); MZ_FD_ZERO(exnfds);
MZ_FD_SET(s, writefds);
MZ_FD_SET(s, exnfds); MZ_FD_SET(s, exnfds);
do { do {
@ -1493,9 +1515,17 @@ make_tcp_output_port(void *data, const char *name)
/*========================================================================*/ /*========================================================================*/
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP
static void closesocket_w_decrement(tcp_t s) typedef struct Close_Socket_Data {
tcp_t s;
struct addrinfo *src_addr, *dest_addr;
} Close_Socket_Data;
static void closesocket_w_decrement(Close_Socket_Data *csd)
{ {
closesocket(s); closesocket(csd->s);
if (csd->src_addr)
freeaddrinfo(csd->src_addr);
freeaddrinfo(csd->dest_addr);
--scheme_file_open_count; --scheme_file_open_count;
} }
#endif #endif
@ -1576,10 +1606,10 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
else else
tcp_connect_src = scheme_get_host_address(src_address, src_id, &errid, -1, 1, 1); tcp_connect_src = scheme_get_host_address(src_address, src_id, &errid, -1, 1, 1);
if (no_local_spec || tcp_connect_src) { if (no_local_spec || tcp_connect_src) {
GC_CAN_IGNORE struct addrinfo *addr;
for (addr = tcp_connect_dest; addr; addr = addr->ai_next) {
tcp_t s; tcp_t s;
s = socket(tcp_connect_dest->ai_family, s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
tcp_connect_dest->ai_socktype,
tcp_connect_dest->ai_protocol);
if (s != INVALID_SOCKET) { if (s != INVALID_SOCKET) {
int status, inprogress; int status, inprogress;
if (no_local_spec if (no_local_spec
@ -1594,7 +1624,7 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int)); setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int));
# endif # endif
#endif #endif
status = connect(s, tcp_connect_dest->ai_addr, tcp_connect_dest->ai_addrlen); status = connect(s, addr->ai_addr, addr->ai_addrlen);
#ifdef USE_UNIX_SOCKETS_TCP #ifdef USE_UNIX_SOCKETS_TCP
if (status) if (status)
status = errno; status = errno;
@ -1613,20 +1643,19 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
scheme_file_open_count++; scheme_file_open_count++;
if (tcp_connect_src) {
// freeaddrinfo(tcp_connect_src);
tcp_connect_src = NULL;
}
// freeaddrinfo(tcp_connect_dest);
tcp_connect_dest = NULL;
if (inprogress) { if (inprogress) {
tcp_t *sptr; tcp_t *sptr;
Close_Socket_Data *csd;
sptr = (tcp_t *)scheme_malloc_atomic(sizeof(tcp_t)); sptr = (tcp_t *)scheme_malloc_atomic(sizeof(tcp_t));
*sptr = s; *sptr = s;
BEGIN_ESCAPEABLE(closesocket_w_decrement, s); csd = (Close_Socket_Data *)scheme_malloc_atomic(sizeof(Close_Socket_Data));
csd->s = s;
csd->src_addr = tcp_connect_src;
csd->dest_addr = tcp_connect_dest;
BEGIN_ESCAPEABLE(closesocket_w_decrement, csd);
scheme_block_until(tcp_check_connect, tcp_connect_needs_wakeup, (void *)sptr, (float)0.0); scheme_block_until(tcp_check_connect, tcp_connect_needs_wakeup, (void *)sptr, (float)0.0);
END_ESCAPEABLE(); END_ESCAPEABLE();
@ -1657,6 +1686,10 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
Scheme_Object *v[2]; Scheme_Object *v[2];
Scheme_Tcp *tcp; Scheme_Tcp *tcp;
if (tcp_connect_src)
freeaddrinfo(tcp_connect_src);
freeaddrinfo(tcp_connect_dest);
tcp = make_tcp_port_data(s, 2); tcp = make_tcp_port_data(s, 2);
v[0] = make_tcp_input_port(tcp, address); v[0] = make_tcp_input_port(tcp, address);
@ -1679,6 +1712,7 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
errpart = 4; errpart = 4;
errid = SOCK_ERRNO(); errid = SOCK_ERRNO();
} }
}
if (tcp_connect_src) if (tcp_connect_src)
freeaddrinfo(tcp_connect_src); freeaddrinfo(tcp_connect_src);
} else { } else {
@ -1758,19 +1792,22 @@ tcp_listen(int argc, Scheme_Object *argv[])
#endif #endif
{ {
GC_CAN_IGNORE struct addrinfo *tcp_listen_addr; GC_CAN_IGNORE struct addrinfo *tcp_listen_addr, *addr;
int err; int err, count = 0, pos = 0, i;
listener_t *l = NULL;
tcp_listen_addr = scheme_get_host_address(address, id, &err, tcp_listen_addr = scheme_get_host_address(address, id, &err, -1, 1, 1);
!address ? MZ_PF_INET : -1,
1, 1); for (addr = tcp_listen_addr; addr; addr = addr->ai_next) {
count++;
}
if (tcp_listen_addr) { if (tcp_listen_addr) {
tcp_t s; tcp_t s;
s = socket(tcp_listen_addr->ai_family, errid = 0;
tcp_listen_addr->ai_socktype, for (addr = tcp_listen_addr; addr; addr = addr->ai_next) {
tcp_listen_addr->ai_protocol); s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (s != INVALID_SOCKET) { if (s != INVALID_SOCKET) {
#ifdef USE_WINSOCK_TCP #ifdef USE_WINSOCK_TCP
@ -1784,13 +1821,12 @@ tcp_listen(int argc, Scheme_Object *argv[])
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuse), sizeof(int)); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuse), sizeof(int));
} }
if (!bind(s, tcp_listen_addr->ai_addr, tcp_listen_addr->ai_addrlen)) { if (!bind(s, addr->ai_addr, addr->ai_addrlen)) {
if (!listen(s, backlog)) { if (!listen(s, backlog)) {
listener_t *l; if (!pos) {
l = scheme_malloc_tagged(sizeof(listener_t) + ((count - 1) * sizeof(tcp_t)));
l = MALLOC_ONE_TAGGED(listener_t);
l->so.type = scheme_listener_type; l->so.type = scheme_listener_type;
l->s = s; l->count = count;
{ {
Scheme_Custodian_Reference *mref; Scheme_Custodian_Reference *mref;
mref = scheme_add_managed(NULL, mref = scheme_add_managed(NULL,
@ -1800,21 +1836,40 @@ tcp_listen(int argc, Scheme_Object *argv[])
1); 1);
l->mref = mref; l->mref = mref;
} }
}
l->s[pos++] = s;
scheme_file_open_count++; scheme_file_open_count++;
REGISTER_SOCKET(s); REGISTER_SOCKET(s);
if (pos == count) {
freeaddrinfo(tcp_listen_addr); freeaddrinfo(tcp_listen_addr);
return (Scheme_Object *)l; return (Scheme_Object *)l;
} }
} else {
errid = SOCK_ERRNO();
closesocket(s);
break;
}
} else {
errid = SOCK_ERRNO();
closesocket(s);
break;
}
} else {
errid = SOCK_ERRNO();
break;
}
} }
errid = SOCK_ERRNO(); for (i = 0; i < pos; i++) {
s = l->s[i];
UNREGISTER_SOCKET(s);
closesocket(s); closesocket(s);
} else --scheme_file_open_count;
errid = SOCK_ERRNO(); }
freeaddrinfo(tcp_listen_addr); freeaddrinfo(tcp_listen_addr);
} else { } else {
scheme_raise_exn(MZEXN_FAIL_NETWORK, scheme_raise_exn(MZEXN_FAIL_NETWORK,
@ -1843,20 +1898,25 @@ static int stop_listener(Scheme_Object *o)
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP
{ {
tcp_t s = ((listener_t *)o)->s; listener_t *listener = (listener_t *)o;
int i;
tcp_t s;
s = listener->s[0];
if (s == INVALID_SOCKET) if (s == INVALID_SOCKET)
was_closed = 1; was_closed = 1;
else { else {
for (i = 0; i < listener->count; i++) {
s = listener->s[i];
UNREGISTER_SOCKET(s); UNREGISTER_SOCKET(s);
closesocket(s); closesocket(s);
((listener_t *)o)->s = INVALID_SOCKET; listener->s[i] = INVALID_SOCKET;
--scheme_file_open_count; --scheme_file_open_count;
}
scheme_remove_managed(((listener_t *)o)->mref, o); scheme_remove_managed(((listener_t *)o)->mref, o);
} }
} }
#endif #endif
return was_closed; return was_closed;
} }
#endif #endif
@ -1917,7 +1977,7 @@ static Scheme_Object *
tcp_accept(int argc, Scheme_Object *argv[]) tcp_accept(int argc, Scheme_Object *argv[])
{ {
#ifdef USE_TCP #ifdef USE_TCP
int was_closed = 0, errid; int was_closed = 0, errid, ready_pos;
Scheme_Object *listener; Scheme_Object *listener;
# ifdef USE_SOCKETS_TCP # ifdef USE_SOCKETS_TCP
tcp_t s; tcp_t s;
@ -1935,11 +1995,14 @@ tcp_accept(int argc, Scheme_Object *argv[])
was_closed = LISTENER_WAS_CLOSED(listener); was_closed = LISTENER_WAS_CLOSED(listener);
if (!was_closed) { if (!was_closed) {
if (!tcp_check_accept(listener)) { ready_pos = tcp_check_accept(listener);
if (!ready_pos) {
scheme_block_until(tcp_check_accept, tcp_accept_needs_wakeup, listener, 0.0); scheme_block_until(tcp_check_accept, tcp_accept_needs_wakeup, listener, 0.0);
ready_pos = tcp_check_accept(listener);
} }
was_closed = LISTENER_WAS_CLOSED(listener); was_closed = LISTENER_WAS_CLOSED(listener);
} } else
ready_pos = 0;
if (was_closed) { if (was_closed) {
scheme_raise_exn(MZEXN_FAIL_NETWORK, scheme_raise_exn(MZEXN_FAIL_NETWORK,
@ -1950,7 +2013,7 @@ tcp_accept(int argc, Scheme_Object *argv[])
scheme_custodian_check_available(NULL, "tcp-accept", "network"); scheme_custodian_check_available(NULL, "tcp-accept", "network");
# ifdef USE_SOCKETS_TCP # ifdef USE_SOCKETS_TCP
s = ((listener_t *)listener)->s; s = ((listener_t *)listener)->s[ready_pos-1];
l = sizeof(tcp_accept_addr); l = sizeof(tcp_accept_addr);