racket/udp: fixed for udp-bind!' and
udp-connect!'
Fix ephemeral-port support in `udp-bind!', and change `udp-bind!' and `udp-connect!' to try address resolutions in order to find one that works (which is typically needed to auto-select an IPv4 or IPv6 variant of an address).
This commit is contained in:
parent
7c0f35e138
commit
842da32e48
|
@ -3175,7 +3175,7 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
Scheme_UDP *udp;
|
||||
char *address = NULL;
|
||||
unsigned short port = 0;
|
||||
GC_CAN_IGNORE struct mz_addrinfo *udp_bind_addr = NULL;
|
||||
GC_CAN_IGNORE struct mz_addrinfo *udp_bind_addr = NULL, *addr;
|
||||
|
||||
udp = (Scheme_UDP *)argv[0];
|
||||
|
||||
|
@ -3219,8 +3219,8 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* DISCONNECT */
|
||||
if (SCHEME_FALSEP(argv[1]) && SCHEME_FALSEP(argv[2])) {
|
||||
/* DISCONNECT */
|
||||
int errid = 0;
|
||||
if (udp->connected) {
|
||||
int ok;
|
||||
|
@ -3253,8 +3253,8 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
return scheme_void;
|
||||
}
|
||||
|
||||
{
|
||||
/* RESOLVE ADDRESS */
|
||||
if (address || port) {
|
||||
int err;
|
||||
udp_bind_addr = scheme_get_host_address(address, port, &err, -1, do_bind, 0);
|
||||
if (!udp_bind_addr) {
|
||||
|
@ -3269,15 +3269,23 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
}
|
||||
}
|
||||
|
||||
/* CONNECT CASE */
|
||||
if (!do_bind) {
|
||||
int ok = !connect(udp->s, udp_bind_addr->ai_addr, udp_bind_addr->ai_addrlen);
|
||||
mz_freeaddrinfo(udp_bind_addr);
|
||||
/* CONNECT CASE */
|
||||
int ok, errid = -1;
|
||||
|
||||
/* connect using first address that works: */
|
||||
for (addr = udp_bind_addr; addr; addr = addr->ai_next) {
|
||||
ok = !connect(udp->s, addr->ai_addr, addr->ai_addrlen);
|
||||
if (ok) {
|
||||
udp->connected = 1;
|
||||
mz_freeaddrinfo(udp_bind_addr);
|
||||
return scheme_void;
|
||||
} else
|
||||
errid = SOCK_ERRNO();
|
||||
}
|
||||
else {
|
||||
|
||||
mz_freeaddrinfo(udp_bind_addr);
|
||||
|
||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
||||
"%s: can't connect\n"
|
||||
" address: %s\n"
|
||||
|
@ -3286,13 +3294,12 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
name,
|
||||
address ? address : "#f",
|
||||
port,
|
||||
SOCK_ERRNO());
|
||||
errid);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* BIND CASE */
|
||||
else {
|
||||
int ok;
|
||||
int ok, errid = -1;
|
||||
|
||||
if ((argc > 3) && SCHEME_TRUEP(argv[3])) {
|
||||
int one = 1;
|
||||
|
@ -3306,24 +3313,19 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
}
|
||||
}
|
||||
|
||||
if (udp_bind_addr == NULL ) {
|
||||
GC_CAN_IGNORE mz_unspec_address ua;
|
||||
memset(&ua, 0, sizeof(mz_unspec_address));
|
||||
ua.sin_family = AF_UNSPEC;
|
||||
ua.sin_port = 0;
|
||||
memset(&(ua.sin_addr), 0, sizeof(ua.sin_addr));
|
||||
memset(&(ua.sin_zero), 0, sizeof(ua.sin_zero));
|
||||
ok = !bind(udp->s, (struct sockaddr *)&ua, sizeof(ua));
|
||||
}
|
||||
else {
|
||||
ok = !bind(udp->s, udp_bind_addr->ai_addr, udp_bind_addr->ai_addrlen);
|
||||
mz_freeaddrinfo(udp_bind_addr);
|
||||
}
|
||||
/* bind using first address that works: */
|
||||
for (addr = udp_bind_addr; addr; addr = addr->ai_next) {
|
||||
ok = !bind(udp->s, addr->ai_addr, addr->ai_addrlen);
|
||||
if (ok) {
|
||||
udp->bound = 1;
|
||||
mz_freeaddrinfo(udp_bind_addr);
|
||||
return scheme_void;
|
||||
} else
|
||||
errid = SOCK_ERRNO();
|
||||
}
|
||||
else {
|
||||
|
||||
mz_freeaddrinfo(udp_bind_addr);
|
||||
|
||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
||||
"%s: can't bind\n"
|
||||
" address: %s\n"
|
||||
|
@ -3332,11 +3334,10 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
|||
name,
|
||||
address ? address : "#f",
|
||||
port,
|
||||
SOCK_ERRNO());
|
||||
errid);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
return scheme_void;
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user