loop through addresses for TCP connect or listen
svn: r1232
This commit is contained in:
parent
0dd1f6a2ab
commit
1fc7c09a67
|
@ -3006,36 +3006,34 @@ int mark_print_params_FIXUP(void *p) {
|
|||
#ifdef MARKS_FOR_NETWORK_C
|
||||
|
||||
int mark_listener_SIZE(void *p) {
|
||||
listener_t *l = (listener_t *)p;
|
||||
|
||||
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) {
|
||||
listener_t *l = (listener_t *)p;
|
||||
|
||||
|
||||
gcMARK(l->mref);
|
||||
#ifdef USE_MAC_TCP
|
||||
gcMARK(l->datas);
|
||||
#endif
|
||||
|
||||
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) {
|
||||
listener_t *l = (listener_t *)p;
|
||||
|
||||
|
||||
gcFIXUP(l->mref);
|
||||
#ifdef USE_MAC_TCP
|
||||
gcFIXUP(l->datas);
|
||||
#endif
|
||||
|
||||
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_CONST_SIZE 1
|
||||
#define mark_listener_IS_CONST_SIZE 0
|
||||
|
||||
|
||||
#ifdef USE_TCP
|
||||
|
@ -3049,10 +3047,6 @@ int mark_tcp_MARK(void *p) {
|
|||
|
||||
gcMARK(tcp->b.buffer);
|
||||
gcMARK(tcp->b.out_buffer);
|
||||
# ifdef USE_MAC_TCP
|
||||
gcMARK(tcp->tcp);
|
||||
gcMARK(tcp->activeRcv);
|
||||
# endif
|
||||
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Tcp));
|
||||
|
@ -3063,10 +3057,6 @@ int mark_tcp_FIXUP(void *p) {
|
|||
|
||||
gcFIXUP(tcp->b.buffer);
|
||||
gcFIXUP(tcp->b.out_buffer);
|
||||
# ifdef USE_MAC_TCP
|
||||
gcFIXUP(tcp->tcp);
|
||||
gcFIXUP(tcp->activeRcv);
|
||||
# endif
|
||||
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Tcp));
|
||||
|
@ -3076,35 +3066,6 @@ int mark_tcp_FIXUP(void *p) {
|
|||
#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
|
||||
int mark_udp_SIZE(void *p) {
|
||||
return
|
||||
|
|
|
@ -1204,16 +1204,14 @@ END print;
|
|||
START network;
|
||||
|
||||
mark_listener {
|
||||
mark:
|
||||
listener_t *l = (listener_t *)p;
|
||||
|
||||
mark:
|
||||
|
||||
gcMARK(l->mref);
|
||||
#ifdef USE_MAC_TCP
|
||||
gcMARK(l->datas);
|
||||
#endif
|
||||
|
||||
size:
|
||||
gcBYTES_TO_WORDS(sizeof(listener_t));
|
||||
gcBYTES_TO_WORDS(sizeof(listener_t) + ((l->count - 1) * sizeof(tcp_t)));
|
||||
}
|
||||
|
||||
#ifdef USE_TCP
|
||||
|
@ -1223,27 +1221,11 @@ mark_tcp {
|
|||
|
||||
gcMARK(tcp->b.buffer);
|
||||
gcMARK(tcp->b.out_buffer);
|
||||
# ifdef USE_MAC_TCP
|
||||
gcMARK(tcp->tcp);
|
||||
gcMARK(tcp->activeRcv);
|
||||
# endif
|
||||
|
||||
size:
|
||||
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
|
||||
mark_udp {
|
||||
mark:
|
||||
|
|
|
@ -111,8 +111,9 @@ typedef SOCKET tcp_t;
|
|||
#ifdef USE_SOCKETS_TCP
|
||||
typedef struct {
|
||||
Scheme_Object so;
|
||||
tcp_t s;
|
||||
Scheme_Custodian_Reference *mref;
|
||||
int count;
|
||||
tcp_t s[1];
|
||||
} listener_t;
|
||||
#endif
|
||||
|
||||
|
@ -834,7 +835,7 @@ static void TCP_INIT(char *name)
|
|||
/*========================================================================*/
|
||||
|
||||
#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
|
||||
#ifndef LISTENER_WAS_CLOSED
|
||||
#define LISTENER_WAS_CLOSED(x) 0
|
||||
|
@ -843,14 +844,15 @@ static void TCP_INIT(char *name)
|
|||
/* Forward declaration */
|
||||
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
|
||||
tcp_t s;
|
||||
tcp_t s, mx;
|
||||
listener_t *listener = (listener_t *)_listener;
|
||||
DECL_FDSET(readfds, 1);
|
||||
DECL_FDSET(exnfds, 1);
|
||||
struct timeval time = {0, 0};
|
||||
int sr;
|
||||
int sr, i;
|
||||
|
||||
INIT_DECL_FDSET(readfds, 1);
|
||||
INIT_DECL_FDSET(exnfds, 1);
|
||||
|
@ -858,32 +860,51 @@ static int tcp_check_accept(Scheme_Object *listener)
|
|||
if (LISTENER_WAS_CLOSED(listener))
|
||||
return 1;
|
||||
|
||||
s = ((listener_t *)listener)->s;
|
||||
|
||||
MZ_FD_ZERO(readfds);
|
||||
MZ_FD_ZERO(exnfds);
|
||||
MZ_FD_SET(s, readfds);
|
||||
MZ_FD_SET(s, exnfds);
|
||||
|
||||
mx = 0;
|
||||
for (i = 0; i < listener->count; i++) {
|
||||
s = listener->s[i];
|
||||
MZ_FD_SET(s, readfds);
|
||||
MZ_FD_SET(s, exnfds);
|
||||
if (s > mx)
|
||||
mx = s;
|
||||
}
|
||||
|
||||
do {
|
||||
sr = select(s + 1, readfds, NULL, exnfds, &time);
|
||||
sr = select(mx + 1, readfds, NULL, exnfds, &time);
|
||||
} 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;
|
||||
#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
|
||||
if (!LISTENER_WAS_CLOSED(listener)) {
|
||||
tcp_t s = ((listener_t *)listener)->s;
|
||||
if (!LISTENER_WAS_CLOSED(_listener)) {
|
||||
listener_t *listener = (listener_t *)_listener;
|
||||
int i;
|
||||
tcp_t s;
|
||||
void *fds2;
|
||||
|
||||
fds2 = MZ_GET_FDSET(fds, 2);
|
||||
|
||||
MZ_FD_SET(s, (fd_set *)fds);
|
||||
MZ_FD_SET(s, (fd_set *)fds2);
|
||||
for (i = 0; i < listener->count; i++) {
|
||||
s = listener->s[i];
|
||||
MZ_FD_SET(s, (fd_set *)fds);
|
||||
MZ_FD_SET(s, (fd_set *)fds2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -903,8 +924,9 @@ static int tcp_check_connect(Scheme_Object *connector_p)
|
|||
s = *(tcp_t *)connector_p;
|
||||
|
||||
MZ_FD_ZERO(writefds);
|
||||
MZ_FD_SET(s, writefds);
|
||||
MZ_FD_ZERO(exnfds);
|
||||
|
||||
MZ_FD_SET(s, writefds);
|
||||
MZ_FD_SET(s, exnfds);
|
||||
|
||||
do {
|
||||
|
@ -1493,9 +1515,17 @@ make_tcp_output_port(void *data, const char *name)
|
|||
/*========================================================================*/
|
||||
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
@ -1576,108 +1606,112 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
|
|||
else
|
||||
tcp_connect_src = scheme_get_host_address(src_address, src_id, &errid, -1, 1, 1);
|
||||
if (no_local_spec || tcp_connect_src) {
|
||||
tcp_t s;
|
||||
s = socket(tcp_connect_dest->ai_family,
|
||||
tcp_connect_dest->ai_socktype,
|
||||
tcp_connect_dest->ai_protocol);
|
||||
if (s != INVALID_SOCKET) {
|
||||
int status, inprogress;
|
||||
if (no_local_spec
|
||||
|| !bind(s, tcp_connect_src->ai_addr, tcp_connect_src->ai_addrlen)) {
|
||||
GC_CAN_IGNORE struct addrinfo *addr;
|
||||
for (addr = tcp_connect_dest; addr; addr = addr->ai_next) {
|
||||
tcp_t s;
|
||||
s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if (s != INVALID_SOCKET) {
|
||||
int status, inprogress;
|
||||
if (no_local_spec
|
||||
|| !bind(s, tcp_connect_src->ai_addr, tcp_connect_src->ai_addrlen)) {
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
unsigned long ioarg = 1;
|
||||
ioctlsocket(s, FIONBIO, &ioarg);
|
||||
unsigned long ioarg = 1;
|
||||
ioctlsocket(s, FIONBIO, &ioarg);
|
||||
#else
|
||||
int size = TCP_SOCKSENDBUF_SIZE;
|
||||
fcntl(s, F_SETFL, MZ_NONBLOCKING);
|
||||
int size = TCP_SOCKSENDBUF_SIZE;
|
||||
fcntl(s, F_SETFL, MZ_NONBLOCKING);
|
||||
# ifndef CANT_SET_SOCKET_BUFSIZE
|
||||
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int));
|
||||
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int));
|
||||
# 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
|
||||
if (status)
|
||||
status = errno;
|
||||
if (status == EINTR)
|
||||
status = EINPROGRESS;
|
||||
if (status)
|
||||
status = errno;
|
||||
if (status == EINTR)
|
||||
status = EINPROGRESS;
|
||||
|
||||
inprogress = (status == EINPROGRESS);
|
||||
inprogress = (status == EINPROGRESS);
|
||||
#endif
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
if (status)
|
||||
status = WSAGetLastError();
|
||||
if (status)
|
||||
status = WSAGetLastError();
|
||||
|
||||
inprogress = (status == WSAEWOULDBLOCK);
|
||||
errno = status;
|
||||
inprogress = (status == WSAEWOULDBLOCK);
|
||||
errno = status;
|
||||
#endif
|
||||
|
||||
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) {
|
||||
tcp_t *sptr;
|
||||
if (inprogress) {
|
||||
tcp_t *sptr;
|
||||
Close_Socket_Data *csd;
|
||||
|
||||
sptr = (tcp_t *)scheme_malloc_atomic(sizeof(tcp_t));
|
||||
*sptr = s;
|
||||
sptr = (tcp_t *)scheme_malloc_atomic(sizeof(tcp_t));
|
||||
*sptr = s;
|
||||
|
||||
BEGIN_ESCAPEABLE(closesocket_w_decrement, s);
|
||||
scheme_block_until(tcp_check_connect, tcp_connect_needs_wakeup, (void *)sptr, (float)0.0);
|
||||
END_ESCAPEABLE();
|
||||
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;
|
||||
|
||||
/* Check whether connect succeeded, or get error: */
|
||||
{
|
||||
int so_len = sizeof(status);
|
||||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&status, &so_len) != 0) {
|
||||
status = SOCK_ERRNO();
|
||||
BEGIN_ESCAPEABLE(closesocket_w_decrement, csd);
|
||||
scheme_block_until(tcp_check_connect, tcp_connect_needs_wakeup, (void *)sptr, (float)0.0);
|
||||
END_ESCAPEABLE();
|
||||
|
||||
/* Check whether connect succeeded, or get error: */
|
||||
{
|
||||
int so_len = sizeof(status);
|
||||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&status, &so_len) != 0) {
|
||||
status = SOCK_ERRNO();
|
||||
}
|
||||
errno = status; /* for error reporting, below */
|
||||
}
|
||||
errno = status; /* for error reporting, below */
|
||||
}
|
||||
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
if (scheme_stupid_windows_machine > 0) {
|
||||
/* getsockopt() seems not to work in Windows 95, so use the
|
||||
result from select(), which seems to reliably detect an error condition */
|
||||
if (!status) {
|
||||
if (tcp_check_connect((Scheme_Object *)sptr) == -1) {
|
||||
status = 1;
|
||||
errno = WSAECONNREFUSED; /* guess! */
|
||||
if (scheme_stupid_windows_machine > 0) {
|
||||
/* getsockopt() seems not to work in Windows 95, so use the
|
||||
result from select(), which seems to reliably detect an error condition */
|
||||
if (!status) {
|
||||
if (tcp_check_connect((Scheme_Object *)sptr) == -1) {
|
||||
status = 1;
|
||||
errno = WSAECONNREFUSED; /* guess! */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
Scheme_Object *v[2];
|
||||
Scheme_Tcp *tcp;
|
||||
if (!status) {
|
||||
Scheme_Object *v[2];
|
||||
Scheme_Tcp *tcp;
|
||||
|
||||
tcp = make_tcp_port_data(s, 2);
|
||||
|
||||
v[0] = make_tcp_input_port(tcp, address);
|
||||
v[1] = make_tcp_output_port(tcp, address);
|
||||
|
||||
REGISTER_SOCKET(s);
|
||||
if (tcp_connect_src)
|
||||
freeaddrinfo(tcp_connect_src);
|
||||
freeaddrinfo(tcp_connect_dest);
|
||||
|
||||
return scheme_values(2, v);
|
||||
tcp = make_tcp_port_data(s, 2);
|
||||
|
||||
v[0] = make_tcp_input_port(tcp, address);
|
||||
v[1] = make_tcp_output_port(tcp, address);
|
||||
|
||||
REGISTER_SOCKET(s);
|
||||
|
||||
return scheme_values(2, v);
|
||||
} else {
|
||||
errid = errno;
|
||||
closesocket(s);
|
||||
--scheme_file_open_count;
|
||||
errpart = 6;
|
||||
}
|
||||
} else {
|
||||
errid = errno;
|
||||
closesocket(s);
|
||||
--scheme_file_open_count;
|
||||
errpart = 6;
|
||||
errpart = 5;
|
||||
errid = SOCK_ERRNO();
|
||||
}
|
||||
} else {
|
||||
errpart = 5;
|
||||
errpart = 4;
|
||||
errid = SOCK_ERRNO();
|
||||
}
|
||||
} else {
|
||||
errpart = 4;
|
||||
errid = SOCK_ERRNO();
|
||||
}
|
||||
if (tcp_connect_src)
|
||||
freeaddrinfo(tcp_connect_src);
|
||||
|
@ -1687,7 +1721,7 @@ static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[])
|
|||
errmsg = "; local host not found";
|
||||
}
|
||||
if (tcp_connect_dest)
|
||||
freeaddrinfo(tcp_connect_dest);
|
||||
freeaddrinfo(tcp_connect_dest);
|
||||
} else {
|
||||
errpart = 1;
|
||||
nameerr = 1;
|
||||
|
@ -1758,63 +1792,84 @@ tcp_listen(int argc, Scheme_Object *argv[])
|
|||
#endif
|
||||
|
||||
{
|
||||
GC_CAN_IGNORE struct addrinfo *tcp_listen_addr;
|
||||
int err;
|
||||
GC_CAN_IGNORE struct addrinfo *tcp_listen_addr, *addr;
|
||||
int err, count = 0, pos = 0, i;
|
||||
listener_t *l = NULL;
|
||||
|
||||
tcp_listen_addr = scheme_get_host_address(address, id, &err,
|
||||
!address ? MZ_PF_INET : -1,
|
||||
1, 1);
|
||||
tcp_listen_addr = scheme_get_host_address(address, id, &err, -1, 1, 1);
|
||||
|
||||
for (addr = tcp_listen_addr; addr; addr = addr->ai_next) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (tcp_listen_addr) {
|
||||
tcp_t s;
|
||||
|
||||
s = socket(tcp_listen_addr->ai_family,
|
||||
tcp_listen_addr->ai_socktype,
|
||||
tcp_listen_addr->ai_protocol);
|
||||
errid = 0;
|
||||
for (addr = tcp_listen_addr; addr; addr = addr->ai_next) {
|
||||
s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
|
||||
if (s != INVALID_SOCKET) {
|
||||
if (s != INVALID_SOCKET) {
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
unsigned long ioarg = 1;
|
||||
ioctlsocket(s, FIONBIO, &ioarg);
|
||||
unsigned long ioarg = 1;
|
||||
ioctlsocket(s, FIONBIO, &ioarg);
|
||||
#else
|
||||
fcntl(s, F_SETFL, MZ_NONBLOCKING);
|
||||
fcntl(s, F_SETFL, MZ_NONBLOCKING);
|
||||
#endif
|
||||
|
||||
if (reuse) {
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuse), sizeof(int));
|
||||
}
|
||||
|
||||
if (!bind(s, tcp_listen_addr->ai_addr, tcp_listen_addr->ai_addrlen)) {
|
||||
if (!listen(s, backlog)) {
|
||||
listener_t *l;
|
||||
|
||||
l = MALLOC_ONE_TAGGED(listener_t);
|
||||
l->so.type = scheme_listener_type;
|
||||
l->s = s;
|
||||
{
|
||||
Scheme_Custodian_Reference *mref;
|
||||
mref = scheme_add_managed(NULL,
|
||||
(Scheme_Object *)l,
|
||||
(Scheme_Close_Custodian_Client *)stop_listener,
|
||||
NULL,
|
||||
1);
|
||||
l->mref = mref;
|
||||
}
|
||||
|
||||
scheme_file_open_count++;
|
||||
REGISTER_SOCKET(s);
|
||||
|
||||
freeaddrinfo(tcp_listen_addr);
|
||||
|
||||
return (Scheme_Object *)l;
|
||||
if (reuse) {
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuse), sizeof(int));
|
||||
}
|
||||
|
||||
if (!bind(s, addr->ai_addr, addr->ai_addrlen)) {
|
||||
if (!listen(s, backlog)) {
|
||||
if (!pos) {
|
||||
l = scheme_malloc_tagged(sizeof(listener_t) + ((count - 1) * sizeof(tcp_t)));
|
||||
l->so.type = scheme_listener_type;
|
||||
l->count = count;
|
||||
{
|
||||
Scheme_Custodian_Reference *mref;
|
||||
mref = scheme_add_managed(NULL,
|
||||
(Scheme_Object *)l,
|
||||
(Scheme_Close_Custodian_Client *)stop_listener,
|
||||
NULL,
|
||||
1);
|
||||
l->mref = mref;
|
||||
}
|
||||
}
|
||||
l->s[pos++] = s;
|
||||
|
||||
scheme_file_open_count++;
|
||||
REGISTER_SOCKET(s);
|
||||
|
||||
if (pos == count) {
|
||||
freeaddrinfo(tcp_listen_addr);
|
||||
|
||||
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);
|
||||
} else
|
||||
errid = SOCK_ERRNO();
|
||||
--scheme_file_open_count;
|
||||
}
|
||||
|
||||
freeaddrinfo(tcp_listen_addr);
|
||||
} else {
|
||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
||||
|
@ -1843,20 +1898,25 @@ static int stop_listener(Scheme_Object *o)
|
|||
|
||||
#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)
|
||||
was_closed = 1;
|
||||
else {
|
||||
UNREGISTER_SOCKET(s);
|
||||
closesocket(s);
|
||||
((listener_t *)o)->s = INVALID_SOCKET;
|
||||
--scheme_file_open_count;
|
||||
for (i = 0; i < listener->count; i++) {
|
||||
s = listener->s[i];
|
||||
UNREGISTER_SOCKET(s);
|
||||
closesocket(s);
|
||||
listener->s[i] = INVALID_SOCKET;
|
||||
--scheme_file_open_count;
|
||||
}
|
||||
scheme_remove_managed(((listener_t *)o)->mref, o);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return was_closed;
|
||||
}
|
||||
#endif
|
||||
|
@ -1917,7 +1977,7 @@ static Scheme_Object *
|
|||
tcp_accept(int argc, Scheme_Object *argv[])
|
||||
{
|
||||
#ifdef USE_TCP
|
||||
int was_closed = 0, errid;
|
||||
int was_closed = 0, errid, ready_pos;
|
||||
Scheme_Object *listener;
|
||||
# ifdef USE_SOCKETS_TCP
|
||||
tcp_t s;
|
||||
|
@ -1935,11 +1995,14 @@ tcp_accept(int argc, Scheme_Object *argv[])
|
|||
was_closed = LISTENER_WAS_CLOSED(listener);
|
||||
|
||||
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);
|
||||
ready_pos = tcp_check_accept(listener);
|
||||
}
|
||||
was_closed = LISTENER_WAS_CLOSED(listener);
|
||||
}
|
||||
} else
|
||||
ready_pos = 0;
|
||||
|
||||
if (was_closed) {
|
||||
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");
|
||||
|
||||
# ifdef USE_SOCKETS_TCP
|
||||
s = ((listener_t *)listener)->s;
|
||||
s = ((listener_t *)listener)->s[ready_pos-1];
|
||||
|
||||
l = sizeof(tcp_accept_addr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user