ipv6.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:22k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ipv6.c: IPv6 network abstraction layer
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: ipv6.c 7909 2004-06-06 12:45:32Z zorglub $
  6.  *
  7.  * Authors: Alexis Guillard <alexis.guillard@bt.com>
  8.  *          Christophe Massiot <massiot@via.ecp.fr>
  9.  *          Remco Poortinga <poortinga@telin.nl>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  * 
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #include <stdlib.h>
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <string.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <vlc/vlc.h>
  35. #ifdef HAVE_UNISTD_H
  36. #   include <unistd.h>
  37. #elif defined( _MSC_VER ) && defined( _WIN32 )
  38. #   include <io.h>
  39. #endif
  40. #ifdef WIN32
  41. #   include <winsock2.h>
  42. #   include <ws2tcpip.h>
  43. #elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
  44. #   include <netdb.h>                                         /* hostent ... */
  45. #   include <sys/socket.h>
  46. #   include <netinet/in.h>
  47. #   include <net/if.h>
  48. #   ifdef HAVE_ARPA_INET_H
  49. #       include <arpa/inet.h>                    /* inet_ntoa(), inet_aton() */
  50. #   endif
  51. #endif
  52. #include "network.h"
  53. #if defined(WIN32)
  54. static const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};
  55. /* the following will have to be removed when w32api defines them */
  56. #ifndef IPPROTO_IPV6
  57. #   define IPPROTO_IPV6 41 
  58. #endif
  59. #ifndef IPV6_JOIN_GROUP
  60. #   define IPV6_JOIN_GROUP 12
  61. #endif
  62. #ifndef IPV6_MULTICAST_HOPS
  63. #   define IPV6_MULTICAST_HOPS 10
  64. #endif
  65. #ifndef IPV6_UNICAST_HOPS
  66. #   define IPV6_UNICAST_HOPS 4
  67. #endif
  68. #   define close closesocket
  69. #endif
  70. /*****************************************************************************
  71.  * Local prototypes
  72.  *****************************************************************************/
  73. static int NetOpen( vlc_object_t * );
  74. /*****************************************************************************
  75.  * Module descriptor
  76.  *****************************************************************************/
  77. vlc_module_begin();
  78.     set_description( _("IPv6 network abstraction layer") );
  79.     set_capability( "network", 40 );
  80.     set_callbacks( NetOpen, NULL );
  81. vlc_module_end();
  82. /*****************************************************************************
  83.  * BuildAddr: utility function to build a struct sockaddr_in6
  84.  *****************************************************************************/
  85. static int BuildAddr( vlc_object_t * p_this, struct sockaddr_in6 * p_socket,
  86.                       const char * psz_bind_address, int i_port )
  87. {
  88.     char * psz_multicast_interface = "";
  89.     char * psz_backup = strdup(psz_bind_address);
  90.     char * psz_address = psz_backup;
  91. #if defined(WIN32)
  92.     /* Try to get getaddrinfo() and freeaddrinfo() from wship6.dll */
  93.     typedef int (CALLBACK * GETADDRINFO) ( const char *nodename,
  94.                                             const char *servname,
  95.                                             const struct addrinfo *hints,
  96.                                             struct addrinfo **res );
  97.     typedef void (CALLBACK * FREEADDRINFO) ( struct addrinfo FAR *ai );
  98.     struct addrinfo hints, *res;
  99.     GETADDRINFO _getaddrinfo = NULL;
  100.     FREEADDRINFO _freeaddrinfo = NULL;
  101.     HINSTANCE wship6_dll = LoadLibrary("wship6.dll");
  102.     if( wship6_dll )
  103.     {
  104.         _getaddrinfo = (GETADDRINFO) GetProcAddress( wship6_dll,
  105.                                                      "getaddrinfo" );
  106.         _freeaddrinfo = (FREEADDRINFO) GetProcAddress( wship6_dll,
  107.                                                        "freeaddrinfo" );
  108.     }
  109.     if( !_getaddrinfo || !_freeaddrinfo )
  110.     {
  111.         msg_Warn( p_this, "no IPv6 stack installed" );
  112.         if( wship6_dll ) FreeLibrary( wship6_dll );
  113.         free( psz_backup );
  114.         return( -1 );
  115.     }
  116. #endif
  117.     /* Reset struct */
  118.     memset( p_socket, 0, sizeof( struct sockaddr_in6 ) );
  119.     p_socket->sin6_family = AF_INET6;                              /* family */
  120.     p_socket->sin6_port = htons( i_port );
  121.     if( !*psz_address )
  122.     {
  123.         p_socket->sin6_addr = in6addr_any;
  124.     }
  125.     else if( psz_address[0] == '['
  126.               && psz_address[strlen(psz_address) - 1] == ']' )
  127.     {
  128.         psz_address[strlen(psz_address) - 1] = '';
  129.         psz_address++;
  130.         /* see if there is an interface name in there... */
  131.         if( (psz_multicast_interface = strchr(psz_address, '%')) != NULL )
  132.         {
  133.             *psz_multicast_interface = '';
  134.             psz_multicast_interface++;
  135.             msg_Dbg( p_this, "Interface name specified: "%s"",
  136.                              psz_multicast_interface );
  137.             /* now convert that interface name to an index */
  138. #if defined( WIN32 )
  139.             /* FIXME ?? */
  140.             p_socket->sin6_scope_id = atol(psz_multicast_interface);
  141. #elif defined( HAVE_IF_NAMETOINDEX )
  142.             p_socket->sin6_scope_id = if_nametoindex(psz_multicast_interface);
  143. #endif
  144.             msg_Dbg( p_this, " = #%i", p_socket->sin6_scope_id );
  145.         }
  146. #if !defined( WIN32 )
  147.         inet_pton(AF_INET6, psz_address, &p_socket->sin6_addr.s6_addr); 
  148. #else
  149.         memset(&hints, 0, sizeof(hints));
  150.         hints.ai_family = AF_INET6;
  151.         if( _getaddrinfo( psz_address, NULL, &hints, &res ) != 0 )
  152.         {
  153.             FreeLibrary( wship6_dll );
  154.             free( psz_backup );
  155.             return( -1 );
  156.         }
  157.         memcpy( &p_socket->sin6_addr,
  158.                 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
  159.                 sizeof(struct in6_addr) );
  160.         _freeaddrinfo( res );
  161. #endif
  162.     }
  163.     else
  164.     {
  165. #ifdef HAVE_GETHOSTBYNAME2
  166.         struct hostent    * p_hostent;
  167.         /* We have a fqdn, try to find its address */
  168.         if ( (p_hostent = gethostbyname2( psz_address, AF_INET6 )) == NULL )
  169.         {
  170.             msg_Warn( p_this, "IPv6 error: unknown host %s", psz_address );
  171.             free( psz_backup );
  172.             return( -1 );
  173.         }
  174.         /* Copy the first address of the host in the socket address */
  175.         memcpy( &p_socket->sin6_addr, p_hostent->h_addr_list[0],
  176.                  p_hostent->h_length );
  177. #elif defined(WIN32)
  178.         memset(&hints, 0, sizeof(hints));
  179.         hints.ai_family = AF_INET6;
  180.         if( _getaddrinfo( psz_address, NULL, &hints, &res ) != 0 )
  181.         {
  182.             FreeLibrary( wship6_dll );
  183.             free( psz_backup );
  184.             return( -1 );
  185.         }
  186.         memcpy( &p_socket->sin6_addr,
  187.                 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
  188.                 sizeof(struct in6_addr) );
  189.         _freeaddrinfo( res );
  190. #else
  191.         msg_Warn( p_this, "IPv6 error: IPv6 address %s is invalid",
  192.                  psz_address );
  193.         free( psz_backup );
  194.         return( -1 );
  195. #endif
  196.     }
  197. #if defined(WIN32)
  198.     FreeLibrary( wship6_dll );
  199. #endif
  200.     free( psz_backup );
  201.     return 0;
  202. }
  203. /*****************************************************************************
  204.  * OpenUDP: open a UDP socket
  205.  *****************************************************************************
  206.  * psz_bind_addr, i_bind_port : address and port used for the bind()
  207.  *   system call. If psz_bind_addr == NULL, the socket is bound to
  208.  *   in6addr_any and broadcast reception is enabled. If i_bind_port == 0,
  209.  *   1234 is used. If psz_bind_addr is a multicast (class D) address,
  210.  *   join the multicast group.
  211.  * psz_server_addr, i_server_port : address and port used for the connect()
  212.  *   system call. It can avoid receiving packets from unauthorized IPs.
  213.  *   Its use leads to great confusion and is currently discouraged.
  214.  * This function returns -1 in case of error.
  215.  *****************************************************************************/
  216. static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
  217. {
  218.     char * psz_bind_addr = p_socket->psz_bind_addr;
  219.     int i_bind_port = p_socket->i_bind_port;
  220.     char * psz_server_addr = p_socket->psz_server_addr;
  221.     int i_server_port = p_socket->i_server_port;
  222.     int i_handle, i_opt;
  223.     socklen_t i_opt_size;
  224.     struct sockaddr_in6 sock;
  225.     vlc_value_t val;
  226.     /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET6 domain, automatic (0)
  227.      * protocol */
  228.     if( (i_handle = socket( AF_INET6, SOCK_DGRAM, 0 )) == -1 )
  229.     {
  230.         msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
  231.         return( -1 );
  232.     }
  233.     /* We may want to reuse an already used socket */
  234.     i_opt = 1;
  235.     if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
  236.                     (void *) &i_opt, sizeof( i_opt ) ) == -1 )
  237.     {
  238.         msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR: %s)",
  239.                          strerror(errno) );
  240.         close( i_handle );
  241.         return( -1 );
  242.     }
  243.     /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
  244.      * packet loss caused by scheduling problems */
  245.     i_opt = 0x80000;
  246.     if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF,
  247.                     (void *) &i_opt, sizeof( i_opt ) ) == -1 )
  248.     {
  249.         msg_Warn( p_this, "cannot configure socket (SO_RCVBUF: %s)",
  250.                           strerror(errno) );
  251.     }
  252.     /* Check if we really got what we have asked for, because Linux, etc.
  253.      * will silently limit the max buffer size to net.core.rmem_max which
  254.      * is typically only 65535 bytes */
  255.     i_opt = 0;
  256.     i_opt_size = sizeof( i_opt );
  257.     if( getsockopt( i_handle, SOL_SOCKET, SO_RCVBUF,
  258.                     (void*) &i_opt, &i_opt_size ) == -1 )
  259.     {
  260.         msg_Warn( p_this, "cannot query socket (SO_RCVBUF: %s)",
  261.                           strerror(errno) );
  262.     }
  263.     else if( i_opt < 0x80000 )
  264.     {
  265.         msg_Warn( p_this, "Socket buffer size is 0x%x instead of 0x%x",
  266.                           i_opt, 0x80000 );
  267.     }
  268.     /* Build the local socket */
  269.     if ( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 )        
  270.     {
  271.         close( i_handle );
  272.         return( -1 );
  273.     }
  274. #if defined(WIN32)
  275.     /* Under Win32 and for multicasting, we bind to IN6ADDR_ANY */
  276.     if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) )
  277.     {
  278.         struct sockaddr_in6 sockany = sock;
  279.         sockany.sin6_addr = in6addr_any;
  280.         sockany.sin6_scope_id = 0;
  281.         /* Bind it */
  282.         if( bind( i_handle, (struct sockaddr *)&sockany, sizeof( sock ) ) < 0 )
  283.         {
  284.             msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) );
  285.             close( i_handle );
  286.             return( -1 );
  287.         }
  288.     } else
  289. #endif
  290.     /* Bind it */
  291.     if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 )
  292.     {
  293.         msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) );
  294.         close( i_handle );
  295.         return( -1 );
  296.     }
  297.     /* Allow broadcast reception if we bound on in6addr_any */
  298.     if( !*psz_bind_addr )
  299.     {
  300.         i_opt = 1;
  301.         if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST,
  302.                         (void*) &i_opt, sizeof( i_opt ) ) == -1 )
  303.         {
  304.             msg_Warn( p_this, "IPv6 warning: cannot configure socket "
  305.                               "(SO_BROADCAST: %s)", strerror(errno) );
  306.         }
  307.     }
  308.     /* Join the multicast group if the socket is a multicast address */
  309. #if defined( WIN32 ) || defined( HAVE_IF_NAMETOINDEX )
  310.     if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) )
  311.     {
  312.         struct ipv6_mreq     imr;
  313.         int                  res;
  314.         imr.ipv6mr_interface = sock.sin6_scope_id;
  315.         imr.ipv6mr_multiaddr = sock.sin6_addr;
  316.         res = setsockopt(i_handle, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void*) &imr,
  317. #if defined(WIN32)
  318.                          sizeof(imr) + 4); /* Doesn't work without this */
  319. #else
  320.                          sizeof(imr));
  321. #endif
  322.         if( res == -1 )
  323.         {
  324.             msg_Err( p_this, "cannot join multicast group" );
  325.         } 
  326.     }
  327. #else
  328.     msg_Warn( p_this, "Multicast IPv6 is not supported on your OS" );
  329. #endif
  330.     if( *psz_server_addr )
  331.     {
  332.         int ttl = p_socket->i_ttl;
  333.         if( ttl < 1 )
  334.         {
  335.             ttl = config_GetInt( p_this, "ttl" );
  336.         }
  337.         if( ttl < 1 ) ttl = 1;
  338.         /* Build socket for remote connection */
  339.         if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
  340.         {
  341.             msg_Warn( p_this, "cannot build remote address" );
  342.             close( i_handle );
  343.             return( -1 );
  344.         }
  345.         /* Connect the socket */
  346.         if( connect( i_handle, (struct sockaddr *) &sock,
  347.                      sizeof( sock ) ) == (-1) )
  348.         {
  349.             msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
  350.             close( i_handle );
  351.             return( -1 );
  352.         }
  353.         /* Set the time-to-live */
  354.         if( ttl > 1 )
  355.         {
  356. #if defined( WIN32 ) || defined( HAVE_IF_NAMETOINDEX )
  357.             if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) )
  358.             {
  359.                 if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
  360.                                 (void *)&ttl, sizeof( ttl ) ) < 0 )
  361.                 {
  362. #ifdef HAVE_ERRNO_H
  363.                     msg_Err( p_this, "failed to set multicast ttl (%s)",
  364.                              strerror(errno) );
  365. #else
  366.                     msg_Err( p_this, "failed to set multicast ttl" );
  367. #endif
  368.                 }
  369.             }
  370.             else
  371. #endif
  372.             {
  373.                 if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
  374.                                 (void *)&ttl, sizeof( ttl ) ) < 0 )
  375.                 {
  376. #ifdef HAVE_ERRNO_H
  377.                     msg_Err( p_this, "failed to set unicast ttl (%s)",
  378.                               strerror(errno) );
  379. #else
  380.                     msg_Err( p_this, "failed to set unicast ttl" );
  381. #endif
  382.                 }
  383.             }
  384.         }
  385.     }
  386.     p_socket->i_handle = i_handle;
  387.     var_Create( p_this, "mtu", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  388.     var_Get( p_this, "mtu", &val );
  389.     p_socket->i_mtu = val.i_int;
  390.     return( 0 );
  391. }
  392. /*****************************************************************************
  393.  * SocketTCP: create a TCP socket
  394.  *****************************************************************************
  395.  * This function returns -1 in case of error.
  396.  *****************************************************************************/
  397. static int SocketTCP( vlc_object_t * p_this )
  398. {
  399.     int i_handle;
  400.     
  401.     /* Open a SOCK_STREAM (TCP) socket, in the PF_INET6 domain, automatic (0)
  402.      * protocol */
  403.     if( (i_handle = socket( PF_INET6, SOCK_STREAM, 0 )) == -1 )
  404.     {
  405. #ifdef HAVE_ERRNO_H
  406.         msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
  407. #else
  408.         msg_Warn( p_this, "cannot create socket" );
  409. #endif
  410.         return -1;
  411.     }
  412.     /* Set to non-blocking */
  413. #if defined( WIN32 ) || defined( UNDER_CE )
  414.     {
  415.         unsigned long i_dummy = 1;
  416.         if( ioctlsocket( i_handle, FIONBIO, &i_dummy ) != 0 )
  417.         {
  418.             msg_Err( p_this, "cannot set socket to non-blocking mode" );
  419.         }
  420.     }
  421. #elif defined( HAVE_ERRNO_H )
  422.     {
  423.         int i_flags;
  424.         if( ( i_flags = fcntl( i_handle, F_GETFL, 0 ) ) < 0 ||
  425.             fcntl( i_handle, F_SETFL, i_flags | O_NONBLOCK ) < 0 )
  426.         {
  427.             msg_Err( p_this, "cannot set socket to non-blocking mode" );
  428.         }
  429.     }
  430. #endif
  431.     return i_handle;
  432. }
  433. /*****************************************************************************
  434.  * OpenTCP: open a TCP socket
  435.  *****************************************************************************
  436.  * psz_server_addr, i_server_port : address and port used for the connect()
  437.  *   system call. If i_server_port == 0, 80 is used.
  438.  * Other parameters are ignored.
  439.  * This function returns -1 in case of error.
  440.  *****************************************************************************/
  441. static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
  442. {
  443.     char * psz_server_addr = p_socket->psz_server_addr;
  444.     int i_server_port = p_socket->i_server_port;
  445.     int i_handle;
  446.     struct sockaddr_in6 sock;
  447.     if( i_server_port == 0 )
  448.     {
  449.         i_server_port = 80;
  450.     }
  451.     if( (i_handle = SocketTCP( p_this )) == -1 )
  452.         return VLC_EGENERIC;
  453.     /* Build remote address */
  454.     if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
  455.         goto error;
  456.     /* Connect the socket */
  457.     if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == -1 )
  458.     {
  459. #if defined( WIN32 ) || defined( UNDER_CE )
  460.         if( WSAGetLastError() == WSAEWOULDBLOCK )
  461. #elif defined( HAVE_ERRNO_H )
  462.         if( errno == EINPROGRESS )
  463. #else
  464.         if( 0 )
  465. #endif
  466.         {
  467.             int i_ret, i_opt, i_opt_size = sizeof( i_opt ), i_max_count;
  468.             struct timeval timeout;
  469.             vlc_value_t val;
  470.             fd_set fds;
  471.             /* FIXME: There is no ipv6-timeout option, so we use ipv4-timeout
  472.              * instead */
  473.             if( !var_Type( p_this, "ipv4-timeout" ) )
  474.             {
  475.                 var_Create( p_this, "ipv4-timeout",
  476.                             VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  477.             }
  478.             var_Get( p_this, "ipv4-timeout", &val );
  479.             i_max_count = val.i_int * 1000 / 100000 /* timeout.tv_usec */;
  480.             msg_Dbg( p_this, "connection in progress" );
  481.             do
  482.             {
  483.                 if( p_this->b_die || i_max_count <= 0 )
  484.                 {
  485.                     msg_Dbg( p_this, "connection aborted" );
  486.                     goto error;
  487.                 }
  488.                 i_max_count--;
  489.                 /* Initialize file descriptor set */
  490.                 FD_ZERO( &fds );
  491.                 FD_SET( i_handle, &fds );
  492.                 /* We'll wait 0.1 second if nothing happens */
  493.                 timeout.tv_sec = 0;
  494.                 timeout.tv_usec = 100000;
  495.             } while( ( i_ret = select( i_handle + 1, NULL, &fds, NULL,
  496.                                        &timeout ) ) == 0 ||
  497. #if defined( WIN32 ) || defined( UNDER_CE )
  498.                      ( i_ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK ) );
  499. #elif defined( HAVE_ERRNO_H )
  500.                      ( i_ret < 0 && errno == EINTR ) );
  501. #else
  502.                      ( i_ret < 0 ) );
  503. #endif
  504.             if( i_ret < 0 )
  505.             {
  506.                 msg_Warn( p_this, "cannot connect socket (select failed)" );
  507.                 goto error;
  508.             }
  509. #if !defined( SYS_BEOS )
  510.             if( getsockopt( i_handle, SOL_SOCKET, SO_ERROR, (void*)&i_opt,
  511.                             &i_opt_size ) == -1 || i_opt != 0 )
  512.             {
  513.                 msg_Warn( p_this, "cannot connect socket (SO_ERROR)" );
  514.                 goto error;
  515.             }
  516. #endif
  517.         }
  518.         else
  519.         {
  520. #if defined( HAVE_ERRNO_H )
  521.             msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
  522. #else
  523.             msg_Warn( p_this, "cannot connect socket" );
  524. #endif
  525.             goto error;
  526.         }
  527.     }
  528.     p_socket->i_handle = i_handle;
  529.     p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
  530.     return VLC_SUCCESS;
  531. error:
  532.     close( i_handle );
  533.     return VLC_EGENERIC;
  534. }
  535. /*****************************************************************************
  536.  * ListenTCP: open a TCP passive socket (server-side)
  537.  *****************************************************************************
  538.  * psz_server_addr, i_server_port : address and port used for the bind()
  539.  *   system call. If i_server_port == 0, 80 is used.
  540.  * Other parameters are ignored.
  541.  * This function returns -1 in case of error.
  542.  *****************************************************************************/
  543. static int ListenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
  544. {
  545.     char * psz_server_addr = p_socket->psz_server_addr;
  546.     int i_server_port = p_socket->i_server_port;
  547.     int i_handle, i_dummy = 1;
  548.     struct sockaddr_in6 sock;
  549.     if( (i_handle = SocketTCP( p_this )) == -1 )
  550.         return VLC_EGENERIC;
  551.     if ( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
  552.                 (void *)&i_dummy, sizeof( i_dummy ) ) == -1 )
  553.     {
  554.         msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
  555.     }
  556.     /* Build remote address */
  557.     if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
  558.     {
  559.         msg_Dbg( p_this, "could not build local address" );
  560.         return VLC_EGENERIC;
  561.     }
  562.     
  563.     /* Bind the socket */
  564.     if( bind( i_handle, (struct sockaddr *) &sock, sizeof( sock )) == -1 )
  565.     {
  566. #ifdef HAVE_ERRNO_H
  567.         msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
  568. #else
  569.         msg_Err( p_this, "cannot bind socket" );
  570. #endif
  571.         goto error;
  572.     }
  573.  
  574.     /* Listen */
  575.     if( listen( i_handle, 100 ) == -1 )
  576.     {
  577. #ifdef HAVE_ERRNO_H
  578.          msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
  579.                   strerror(errno) );
  580. #else
  581.          msg_Err( p_this, "cannot bring the socket in listening mode" );
  582. #endif
  583.          goto error;
  584.     }
  585.     p_socket->i_handle = i_handle;
  586.     p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
  587.     return VLC_SUCCESS;
  588. error:
  589.     close( i_handle );
  590.     return VLC_EGENERIC;
  591. }
  592. /*****************************************************************************
  593.  * NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP
  594.  *****************************************************************************/
  595. static int NetOpen( vlc_object_t * p_this )
  596. {
  597.     network_socket_t * p_socket = p_this->p_private;
  598.     if( p_socket->i_type == NETWORK_UDP )
  599.     {
  600.         return OpenUDP( p_this, p_socket );
  601.     }
  602.     else if( p_socket->i_type == NETWORK_TCP_PASSIVE )
  603.     {
  604.         return ListenTCP( p_this, p_socket );
  605.     }
  606.     else
  607.     {
  608.         return OpenTCP( p_this, p_socket );
  609.     }
  610. }