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;
|
Scheme_UDP *udp;
|
||||||
char *address = NULL;
|
char *address = NULL;
|
||||||
unsigned short port = 0;
|
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];
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DISCONNECT */
|
|
||||||
if (SCHEME_FALSEP(argv[1]) && SCHEME_FALSEP(argv[2])) {
|
if (SCHEME_FALSEP(argv[1]) && SCHEME_FALSEP(argv[2])) {
|
||||||
|
/* DISCONNECT */
|
||||||
int errid = 0;
|
int errid = 0;
|
||||||
if (udp->connected) {
|
if (udp->connected) {
|
||||||
int ok;
|
int ok;
|
||||||
|
@ -3253,8 +3253,8 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
/* RESOLVE ADDRESS */
|
/* RESOLVE ADDRESS */
|
||||||
if (address || port) {
|
|
||||||
int err;
|
int err;
|
||||||
udp_bind_addr = scheme_get_host_address(address, port, &err, -1, do_bind, 0);
|
udp_bind_addr = scheme_get_host_address(address, port, &err, -1, do_bind, 0);
|
||||||
if (!udp_bind_addr) {
|
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) {
|
if (!do_bind) {
|
||||||
int ok = !connect(udp->s, udp_bind_addr->ai_addr, udp_bind_addr->ai_addrlen);
|
/* CONNECT CASE */
|
||||||
mz_freeaddrinfo(udp_bind_addr);
|
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) {
|
if (ok) {
|
||||||
udp->connected = 1;
|
udp->connected = 1;
|
||||||
|
mz_freeaddrinfo(udp_bind_addr);
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
|
} else
|
||||||
|
errid = SOCK_ERRNO();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
mz_freeaddrinfo(udp_bind_addr);
|
||||||
|
|
||||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
||||||
"%s: can't connect\n"
|
"%s: can't connect\n"
|
||||||
" address: %s\n"
|
" address: %s\n"
|
||||||
|
@ -3286,13 +3294,12 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
||||||
name,
|
name,
|
||||||
address ? address : "#f",
|
address ? address : "#f",
|
||||||
port,
|
port,
|
||||||
SOCK_ERRNO());
|
errid);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
/* BIND CASE */
|
/* BIND CASE */
|
||||||
else {
|
int ok, errid = -1;
|
||||||
int ok;
|
|
||||||
|
|
||||||
if ((argc > 3) && SCHEME_TRUEP(argv[3])) {
|
if ((argc > 3) && SCHEME_TRUEP(argv[3])) {
|
||||||
int one = 1;
|
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 ) {
|
/* bind using first address that works: */
|
||||||
GC_CAN_IGNORE mz_unspec_address ua;
|
for (addr = udp_bind_addr; addr; addr = addr->ai_next) {
|
||||||
memset(&ua, 0, sizeof(mz_unspec_address));
|
ok = !bind(udp->s, addr->ai_addr, addr->ai_addrlen);
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
udp->bound = 1;
|
udp->bound = 1;
|
||||||
|
mz_freeaddrinfo(udp_bind_addr);
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
|
} else
|
||||||
|
errid = SOCK_ERRNO();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
mz_freeaddrinfo(udp_bind_addr);
|
||||||
|
|
||||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
||||||
"%s: can't bind\n"
|
"%s: can't bind\n"
|
||||||
" address: %s\n"
|
" address: %s\n"
|
||||||
|
@ -3332,11 +3334,10 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
|
||||||
name,
|
name,
|
||||||
address ? address : "#f",
|
address ? address : "#f",
|
||||||
port,
|
port,
|
||||||
SOCK_ERRNO());
|
errid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user