From 72ee19dccad91a448ebf6899e56a2bc448e51c4a Mon Sep 17 00:00:00 2001 From: Erick Turnquist Date: Thu, 18 Dec 2008 05:55:22 +0000 Subject: [PATCH] (trunk libT) Refactor ipv6 bind socket check This will let the RPC server use the same test mechanism eventually. Networking code belongs in net.c anyway. --- libtransmission/net.c | 29 +++++++++++++++++++++++++++++ libtransmission/net.h | 8 ++++++++ libtransmission/port-forwarding.c | 19 ++++--------------- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/libtransmission/net.c b/libtransmission/net.c index 9df3b47a6..2a61ae76a 100644 --- a/libtransmission/net.c +++ b/libtransmission/net.c @@ -155,6 +155,35 @@ tr_compareAddresses( const tr_address * a, const tr_address * b) return memcmp( &a->addr, &b->addr, addrlen ); } +tr_net_af_support +tr_net_getAFSupport( tr_port port ) +{ + /* Do we care if an address is in use? Probably not, since it will be + * caught later. This will only set up the list of sockets to bind. */ + static tr_bool alreadyDone = FALSE; + static tr_net_af_support support = { FALSE, FALSE }; + int s4, s6; + if( alreadyDone ) + return support; + s6 = tr_netBindTCP( &tr_in6addr_any, port, TRUE ); + if( s6 >= 0 || -s6 != EAFNOSUPPORT ) /* we support ipv6 */ + { + listen( s6, 1 ); + support.has_inet6 = TRUE; + } + s4 = tr_netBindTCP( &tr_inaddr_any, port, TRUE ); + if( s4 >= 0 ) /* we bound *with* the ipv6 socket bound (need both) + * or only have ipv4 */ + { + tr_netClose( s4 ); + support.needs_inet4 = TRUE; + } + if( s6 >= 0 ) + tr_netClose( s6 ); + alreadyDone = TRUE; + return support; +} + /*********************************************************************** * Socket list housekeeping **********************************************************************/ diff --git a/libtransmission/net.h b/libtransmission/net.h index f49f80c97..bf556c15b 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -87,6 +87,14 @@ void tr_normalizeV4Mapped( tr_address * const addr ); tr_bool tr_isAddress( const tr_address * a ); +typedef struct tr_net_af_support +{ + tr_bool has_inet6; + tr_bool needs_inet4; +} tr_net_af_support; + +tr_net_af_support tr_net_getAFSupport( tr_port ); + /*********************************************************************** * Socket list housekeeping **********************************************************************/ diff --git a/libtransmission/port-forwarding.c b/libtransmission/port-forwarding.c index cc5e3cc96..ba5924f48 100644 --- a/libtransmission/port-forwarding.c +++ b/libtransmission/port-forwarding.c @@ -234,29 +234,18 @@ sharedPulse( void * vshared ) static tr_socketList * setupBindSockets( tr_port port ) { - /* Do we care if an address is in use? Probably not, since it will be - * caught later. This will only set up the list of sockets to bind. */ - int s4, s6; + tr_net_af_support support = tr_net_getAFSupport( port ); tr_socketList * socks = NULL; - s6 = tr_netBindTCP( &tr_in6addr_any, port, TRUE ); - if( s6 >= 0 || -s6 != EAFNOSUPPORT ) /* we support ipv6 */ - { + if( support.has_inet6 ) socks = tr_socketListNew( &tr_in6addr_any ); - listen( s6, 1 ); - } - s4 = tr_netBindTCP( &tr_inaddr_any, port, TRUE ); - if( s4 >= 0 ) /* we bound *with* the ipv6 socket bound (need both) - * or only have ipv4 */ + if( support.needs_inet4 ) { if( socks ) tr_socketListAppend( socks, &tr_inaddr_any ); else socks = tr_socketListNew( &tr_inaddr_any ); - tr_netClose( s4 ); } - if( s6 >= 0 ) - tr_netClose( s6 ); - return socks; + return socks; /* Because the dryer gremlins won't */ } tr_shared *