Support SO_REUSEADDR on (udp-bind!), for multicast use.

This commit is contained in:
Tony Garnock-Jones 2013-04-02 20:32:27 -04:00 committed by Matthew Flatt
parent f24b91a1cc
commit d78456b88b
2 changed files with 21 additions and 3 deletions

View File

@ -293,7 +293,8 @@ non-@racket[#f], then the socket's protocol family is IPv4.}
@defproc[(udp-bind! [udp-socket udp?]
[hostname-string (or/c string? #f)]
[port-no (and/c exact-nonnegative-integer?
(integer-in 0 65535))])
(integer-in 0 65535))]
[reuse? any/c #f])
void?]{
Binds an unbound @racket[udp-socket] to the local port number
@ -325,8 +326,12 @@ socket is later used again in a send, then the later send may change
the socket's automatic binding.
If @racket[udp-socket] is already bound or closed, the
@exnraise[exn:fail:network].}
@exnraise[exn:fail:network].
If the @racket[reuse?] argument is true, then @racket[udp-bind!] will
set the @tt{SO_REUSEADDR} socket option before binding, permitting the
sharing of access to a UDP port between many processes on a single
machine when using UDP multicast.}
@defproc[(udp-connect! [udp-socket udp?]
[hostname-string (or/c string? #f)]

View File

@ -269,7 +269,7 @@ void scheme_init_network(Scheme_Env *env)
GLOBAL_FOLDING_PRIM ( "udp?" , udp_p , 1 , 1 , 1 , netenv ) ;
GLOBAL_PRIM_W_ARITY ( "udp-bound?" , udp_bound_p , 1 , 1 , netenv ) ;
GLOBAL_PRIM_W_ARITY ( "udp-connected?" , udp_connected_p , 1 , 1 , netenv ) ;
GLOBAL_PRIM_W_ARITY ( "udp-bind!" , udp_bind , 3 , 3 , netenv ) ;
GLOBAL_PRIM_W_ARITY ( "udp-bind!" , udp_bind , 3 , 4 , netenv ) ;
GLOBAL_PRIM_W_ARITY ( "udp-connect!" , udp_connect , 3 , 3 , netenv ) ;
GLOBAL_PRIM_W_ARITY ( "udp-send-to" , udp_send_to , 4 , 6 , netenv ) ;
@ -3276,6 +3276,19 @@ static Scheme_Object *udp_bind_or_connect(const char *name, int argc, Scheme_Obj
/* BIND CASE */
else {
int ok;
if ((argc > 3) && SCHEME_TRUEP(argv[3])) {
int one = 1;
if (setsockopt(udp->s, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one))) {
scheme_raise_exn(MZEXN_FAIL_NETWORK,
"%s: can't set SO_REUSEADDR\n"
" system error: %E",
name,
SOCK_ERRNO());
return NULL;
}
}
if (udp_bind_addr == NULL ) {
GC_CAN_IGNORE mz_unspec_address ua;
memset(&ua, 0, sizeof(mz_unspec_address));