/*****************************************************************************
* ipv4.c: IPv4 network abstraction layer
*****************************************************************************
- * Copyright (C) 2001, 2002 VideoLAN
- * $Id: ipv4.c,v 1.21 2004/01/15 13:47:01 fenrir Exp $
+ * Copyright (C) 2001-2005 the VideoLAN team
+ * $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Mathias Kretschmer <mathias@research.att.com>
+ * Alexis de Lattre <alexis@via.ecp.fr>
+ * RĂ©mi Denis-Courmont <rem # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
+
#include <vlc/vlc.h>
+#include <errno.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
# include <unistd.h>
#endif
-#if defined( UNDER_CE )
-# include <winsock.h>
-#elif defined( WIN32 )
+#if defined(WIN32) || defined(UNDER_CE)
+# if defined(UNDER_CE) && defined(sockaddr_storage)
+# undef sockaddr_storage
+# endif
# include <winsock2.h>
# include <ws2tcpip.h>
-# define close closesocket
+# include <iphlpapi.h>
+# if !defined(INCL_WINSOCK_API_PROTOTYPES)
+# define close closesocket
+# endif
+# if defined(UNDER_CE)
+# undef IP_MULTICAST_TTL
+# define IP_MULTICAST_TTL 3
+# undef IP_ADD_MEMBERSHIP
+# define IP_ADD_MEMBERSHIP 5
+# endif
#else
# include <netdb.h> /* hostent ... */
# include <sys/socket.h>
# define IN_MULTICAST(a) IN_CLASSD(a)
#endif
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-static int NetOpen( vlc_object_t * );
+static int OpenUDP( vlc_object_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
+#define MIFACE_TEXT N_("Multicast output interface")
+#define MIFACE_LONGTEXT N_( \
+ "Indicate here the multicast output interface. " \
+ "This overrides the routing table.")
+
vlc_module_begin();
- set_description( _("IPv4 network abstraction layer") );
+ set_shortname( "IPv4" );
+ set_description( _("UDP/IPv4 network abstraction layer") );
set_capability( "network", 50 );
- set_callbacks( NetOpen, NULL );
+ set_category( CAT_INPUT );
+ set_subcategory( SUBCAT_INPUT_GENERAL );
+ set_callbacks( OpenUDP, NULL );
+ add_string( "miface-addr", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE );
vlc_module_end();
/*****************************************************************************
return( 0 );
}
+#if defined(WIN32) || defined(UNDER_CE)
+# define WINSOCK_STRERROR_SIZE 20
+static const char *winsock_strerror( char *buf )
+{
+ snprintf( buf, WINSOCK_STRERROR_SIZE, "Winsock error %d",
+ WSAGetLastError( ) );
+ buf[WINSOCK_STRERROR_SIZE - 1] = '\0';
+ return buf;
+}
+#endif
+
+
/*****************************************************************************
* OpenUDP: open a UDP socket
*****************************************************************************
* psz_bind_addr, i_bind_port : address and port used for the bind()
* system call. If psz_bind_addr == "", the socket is bound to
- * INADDR_ANY and broadcast reception is enabled. If i_bind_port == 0,
- * 1234 is used. If psz_bind_addr is a multicast (class D) address,
- * join the multicast group.
+ * INADDR_ANY and broadcast reception is enabled. If psz_bind_addr is a
+ * multicast (class D) address, join the multicast group.
* psz_server_addr, i_server_port : address and port used for the connect()
* system call. It can avoid receiving packets from unauthorized IPs.
* Its use leads to great confusion and is currently discouraged.
* This function returns -1 in case of error.
*****************************************************************************/
-static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
+static int OpenUDP( vlc_object_t * p_this )
{
- char * psz_bind_addr = p_socket->psz_bind_addr;
+ network_socket_t * p_socket = p_this->p_private;
+ const char * psz_bind_addr = p_socket->psz_bind_addr;
int i_bind_port = p_socket->i_bind_port;
- char * psz_server_addr = p_socket->psz_server_addr;
+ const char * psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port;
int i_handle, i_opt;
- socklen_t i_opt_size;
struct sockaddr_in sock;
+ vlc_value_t val;
+#if defined(WIN32) || defined(UNDER_CE)
+ char strerror_buf[WINSOCK_STRERROR_SIZE];
+# define strerror( x ) winsock_strerror( strerror_buf )
+#endif
+
+ /* If IP_ADD_SOURCE_MEMBERSHIP is not defined in the headers
+ (because it's not in glibc for example), we have to define the
+ headers required for IGMPv3 here */
+#ifndef IP_ADD_SOURCE_MEMBERSHIP
+ #define IP_ADD_SOURCE_MEMBERSHIP 39
+ struct ip_mreq_source {
+ struct in_addr imr_multiaddr;
+ struct in_addr imr_interface;
+ struct in_addr imr_sourceaddr;
+ };
+#endif
+
+ p_socket->i_handle = -1;
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
* protocol */
if( (i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 )
{
-#ifdef HAVE_ERRNO_H
msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
-#else
- msg_Warn( p_this, "cannot create socket" );
-#endif
- return( -1 );
+ return 0;
}
/* We may want to reuse an already used socket */
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
(void *) &i_opt, sizeof( i_opt ) ) == -1 )
{
-#ifdef HAVE_ERRNO_H
msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR: %s)",
strerror(errno));
-#else
- msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
-#endif
close( i_handle );
- return( -1 );
+ return 0;
}
+#ifdef SO_REUSEPORT
+ i_opt = 1;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEPORT,
+ (void *) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Warn( p_this, "cannot configure socket (SO_REUSEPORT)" );
+ }
+#endif
+
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
* packet loss caused by scheduling problems */
+#if !defined( SYS_BEOS )
i_opt = 0x80000;
-#if defined( SYS_BEOS )
- if( setsockopt( i_handle, SOL_SOCKET, SO_NONBLOCK, (void *) &i_opt, sizeof( i_opt ) ) == -1 )
-#else
- if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i_opt, sizeof( i_opt ) ) == -1 )
-#endif
- {
-#ifdef HAVE_ERRNO_H
+ if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i_opt,
+ sizeof( i_opt ) ) == -1 )
msg_Dbg( p_this, "cannot configure socket (SO_RCVBUF: %s)",
strerror(errno));
-#else
- msg_Warn( p_this, "cannot configure socket (SO_RCVBUF)" );
-#endif
- }
-
- /* Check if we really got what we have asked for, because Linux, etc.
- * will silently limit the max buffer size to net.core.rmem_max which
- * is typically only 65535 bytes */
- i_opt = 0;
- i_opt_size = sizeof( i_opt );
-#if defined( SYS_BEOS )
- if( getsockopt( i_handle, SOL_SOCKET, SO_NONBLOCK, (void*) &i_opt, &i_opt_size ) == -1 )
-#else
- if( getsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void*) &i_opt, &i_opt_size ) == -1 )
-#endif
- {
-#ifdef HAVE_ERRNO_H
- msg_Warn( p_this, "cannot query socket (SO_RCVBUF: %s)",
- strerror(errno) );
-#else
- msg_Warn( p_this, "cannot query socket (SO_RCVBUF)" );
+ i_opt = 0x80000;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_SNDBUF, (void *) &i_opt,
+ sizeof( i_opt ) ) == -1 )
+ msg_Dbg( p_this, "cannot configure socket (SO_SNDBUF: %s)",
+ strerror(errno));
#endif
- }
- else if( i_opt < 0x80000 )
- {
- msg_Dbg( p_this, "socket buffer size is 0x%x instead of 0x%x",
- i_opt, 0x80000 );
- }
-
/* Build the local socket */
-#if defined( WIN32 ) && !defined( UNDER_CE )
+#if defined( WIN32 ) || defined( UNDER_CE )
/* Under Win32 and for multicasting, we bind to INADDR_ANY,
* so let's call BuildAddr with "" instead of psz_bind_addr */
if( BuildAddr( &sock, IN_MULTICAST( ntohl( inet_addr(psz_bind_addr) ) ) ?
{
msg_Dbg( p_this, "could not build local address" );
close( i_handle );
- return( -1 );
+ return 0;
}
/* Bind it */
if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 )
{
-#ifdef HAVE_ERRNO_H
msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) );
-#else
- msg_Warn( p_this, "cannot bind socket" );
-#endif
close( i_handle );
- return( -1 );
+ return 0;
}
-#if defined( WIN32 ) && !defined( UNDER_CE )
+#if defined( WIN32 ) || defined( UNDER_CE )
/* Restore the sock struct so we can spare a few #ifdef WIN32 later on */
if( IN_MULTICAST( ntohl( inet_addr(psz_bind_addr) ) ) )
{
{
msg_Dbg( p_this, "could not build local address" );
close( i_handle );
- return( -1 );
+ return 0;
}
}
#endif
+#if !defined( SYS_BEOS )
/* Allow broadcast reception if we bound on INADDR_ANY */
if( !*psz_bind_addr )
{
i_opt = 1;
-#if defined( SYS_BEOS )
- if( setsockopt( i_handle, SOL_SOCKET, SO_NONBLOCK, (void*) &i_opt, sizeof( i_opt ) ) == -1 )
-#else
- if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST, (void*) &i_opt, sizeof( i_opt ) ) == -1 )
-#endif
- {
-#ifdef HAVE_ERRNO_H
+ if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST, (void*) &i_opt,
+ sizeof( i_opt ) ) == -1 )
msg_Warn( p_this, "cannot configure socket (SO_BROADCAST: %s)",
strerror(errno) );
-#else
- msg_Warn( p_this, "cannot configure socket (SO_BROADCAST)" );
-#endif
- }
}
+#endif
-#if !defined( UNDER_CE ) && !defined( SYS_BEOS )
+#if !defined( SYS_BEOS )
/* Join the multicast group if the socket is a multicast address */
if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) )
{
- struct ip_mreq imr;
-
/* Determine interface to be used for multicast */
- char * psz_if_addr = config_GetPsz( p_this, "iface-addr" );
- imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
- if( psz_if_addr != NULL && *psz_if_addr
- && inet_addr(psz_if_addr) != INADDR_NONE )
- {
- imr.imr_interface.s_addr = inet_addr(psz_if_addr);
- }
- else
- {
- imr.imr_interface.s_addr = INADDR_ANY;
- }
- if( psz_if_addr != NULL ) free( psz_if_addr );
+ char * psz_if_addr = config_GetPsz( p_this, "miface-addr" );
- /* Join Multicast group */
- if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char*)&imr, sizeof(struct ip_mreq) ) == -1 )
+ /* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP
+ so that IGMPv3 aware OSes running on IGMPv3 aware networks
+ will do an IGMPv3 query on the network */
+ if( *psz_server_addr )
{
-#ifdef HAVE_ERRNO_H
- msg_Err( p_this, "failed to join IP multicast group (%s)",
- strerror(errno) );
-#else
- msg_Err( p_this, "failed to join IP multicast group" );
+ struct ip_mreq_source imr;
+
+ imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
+ imr.imr_sourceaddr.s_addr = inet_addr(psz_server_addr);
+
+ if( psz_if_addr != NULL && *psz_if_addr
+ && inet_addr(psz_if_addr) != INADDR_NONE )
+ {
+ imr.imr_interface.s_addr = inet_addr(psz_if_addr);
+ }
+ else
+ {
+ imr.imr_interface.s_addr = INADDR_ANY;
+ }
+ if( psz_if_addr != NULL ) free( psz_if_addr );
+
+ msg_Dbg( p_this, "IP_ADD_SOURCE_MEMBERSHIP multicast request" );
+ /* Join Multicast group with source filter */
+ if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
+ (char*)&imr,
+ sizeof(struct ip_mreq_source) ) == -1 )
+ {
+ msg_Err( p_this, "failed to join IP multicast group (%s)",
+ strerror(errno) );
+ msg_Err( p_this, "are you sure your OS supports IGMPv3?" );
+ close( i_handle );
+ return 0;
+ }
+ }
+ /* If there is no source address, we use IP_ADD_MEMBERSHIP */
+ else
+ {
+ struct ip_mreq imr;
+
+ imr.imr_interface.s_addr = INADDR_ANY;
+ imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
+ if( psz_if_addr != NULL && *psz_if_addr
+ && inet_addr(psz_if_addr) != INADDR_NONE )
+ {
+ imr.imr_interface.s_addr = inet_addr(psz_if_addr);
+ }
+#if defined (WIN32) || defined (UNDER_CE)
+ else
+ {
+ typedef DWORD (CALLBACK * GETBESTINTERFACE) ( IPAddr, PDWORD );
+ typedef DWORD (CALLBACK * GETIPADDRTABLE) ( PMIB_IPADDRTABLE, PULONG, BOOL );
+
+ GETBESTINTERFACE OurGetBestInterface;
+ GETIPADDRTABLE OurGetIpAddrTable;
+ HINSTANCE hiphlpapi = LoadLibrary(_T("Iphlpapi.dll"));
+ DWORD i_index;
+
+ if( hiphlpapi )
+ {
+ OurGetBestInterface =
+ (void *)GetProcAddress( hiphlpapi,
+ _T("GetBestInterface") );
+ OurGetIpAddrTable =
+ (void *)GetProcAddress( hiphlpapi,
+ _T("GetIpAddrTable") );
+ }
+
+ if( hiphlpapi && OurGetBestInterface && OurGetIpAddrTable &&
+ OurGetBestInterface( sock.sin_addr.s_addr,
+ &i_index ) == NO_ERROR )
+ {
+ PMIB_IPADDRTABLE p_table;
+ DWORD i = 0;
+
+ msg_Dbg( p_this, "Winsock best interface is %lu",
+ (unsigned long)i_index );
+ OurGetIpAddrTable( NULL, &i, 0 );
+
+ p_table = (PMIB_IPADDRTABLE)malloc( i );
+ if( p_table != NULL )
+ {
+ if( OurGetIpAddrTable( p_table, &i, 0 ) == NO_ERROR )
+ {
+ for( i = 0; i < p_table->dwNumEntries; i-- )
+ {
+ if( p_table->table[i].dwIndex == i_index )
+ {
+ imr.imr_interface.s_addr =
+ p_table->table[i].dwAddr;
+ msg_Dbg( p_this, "using interface 0x%08x",
+ p_table->table[i].dwAddr );
+ }
+ }
+ }
+ else msg_Warn( p_this, "GetIpAddrTable failed" );
+ free( p_table );
+ }
+ }
+ else msg_Dbg( p_this, "GetBestInterface failed" );
+
+ if( hiphlpapi ) FreeLibrary( hiphlpapi );
+ }
#endif
- close( i_handle );
- return( -1 );
- }
+ if( psz_if_addr != NULL ) free( psz_if_addr );
+
+ msg_Dbg( p_this, "IP_ADD_MEMBERSHIP multicast request" );
+ /* Join Multicast group without source filter */
+ if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char*)&imr, sizeof(struct ip_mreq) ) == -1 )
+ {
+ msg_Err( p_this, "failed to join IP multicast group (%s)",
+ strerror(errno) );
+ close( i_handle );
+ return 0;
+ }
+ }
}
-#endif /* UNDER_CE, SYS_BEOS */
+#endif
if( *psz_server_addr )
{
{
msg_Warn( p_this, "cannot build remote address" );
close( i_handle );
- return( -1 );
+ return 0;
}
/* Connect the socket */
if( connect( i_handle, (struct sockaddr *) &sock,
sizeof( sock ) ) == (-1) )
{
-#ifdef HAVE_ERRNO_H
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
-#else
- msg_Warn( p_this, "cannot connect socket" );
-#endif
close( i_handle );
- return( -1 );
+ return 0;
}
-#if !defined( UNDER_CE ) && !defined( SYS_BEOS )
+#if !defined( SYS_BEOS )
if( IN_MULTICAST( ntohl(inet_addr(psz_server_addr) ) ) )
{
/* set the time-to-live */
- int ttl = p_socket->i_ttl;
- if( ttl < 1 )
+ int i_ttl = p_socket->i_ttl;
+ unsigned char ttl;
+
+ /* set the multicast interface */
+ char * psz_mif_addr = config_GetPsz( p_this, "miface-addr" );
+ if( psz_mif_addr )
{
- ttl = config_GetInt( p_this, "ttl" );
- }
- if( ttl < 1 ) ttl = 1;
+ struct in_addr intf;
+ intf.s_addr = inet_addr(psz_mif_addr);
+ free( psz_mif_addr );
- if( setsockopt( i_handle, IPPROTO_IP, IP_MULTICAST_TTL,
- (void *) &ttl, sizeof( ttl ) ) < 0 )
- {
-#ifdef HAVE_ERRNO_H
- msg_Err( p_this, "failed to set ttl (%s)", strerror(errno) );
-#else
- msg_Err( p_this, "failed to set ttl" );
-#endif
- close( i_handle );
- return( -1 );
+ if( setsockopt( i_handle, IPPROTO_IP, IP_MULTICAST_IF,
+ &intf, sizeof( intf ) ) < 0 )
+ {
+ msg_Dbg( p_this, "failed to set multicast interface (%s).", strerror(errno) );
+ close( i_handle );
+ return 0;
+ }
}
- }
-#endif /* UNDER_CE, SYS_BEOS */
- }
-
- p_socket->i_handle = i_handle;
- p_socket->i_mtu = config_GetInt( p_this, "mtu" );
- return( 0 );
-}
-
-/*****************************************************************************
- * OpenTCP: open a TCP socket
- *****************************************************************************
- * psz_server_addr, i_server_port : address and port used for the connect()
- * system call. If i_server_port == 0, 80 is used.
- * Other parameters are ignored.
- * This function returns -1 in case of error.
- *****************************************************************************/
-static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
-{
- char * psz_server_addr = p_socket->psz_server_addr;
- int i_server_port = p_socket->i_server_port;
-
- int i_handle;
- struct sockaddr_in sock;
-
- if( i_server_port == 0 )
- {
- i_server_port = 80;
- }
-
- /* Open a SOCK_STREAM (TCP) socket, in the AF_INET domain, automatic (0)
- * protocol */
- if( (i_handle = socket( AF_INET, SOCK_STREAM, 0 )) == -1 )
- {
-#ifdef HAVE_ERRNO_H
- msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
-#else
- msg_Warn( p_this, "cannot create socket" );
-#endif
- goto error;
- }
- /* Build remote address */
- if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
- {
- msg_Dbg( p_this, "could not build local address" );
- goto error;
- }
-
- /* We need errno to use non blocking connect */
-#ifdef HAVE_ERRNO_H
- /* set to non-blocking */
-#if defined( WIN32 ) || defined( UNDER_CE )
- {
- unsigned long i_dummy = 1;
- if( ioctlsocket( fd, FIONBIO, &i_dummy ) != 0 )
- {
- msg_Err( p_httpt, "cannot set socket to non-blocking mode" );
- }
- }
-#else
- {
- int i_flags;
- if( ( i_flags = fcntl( i_handle, F_GETFL, 0 ) ) < 0 ||
- fcntl( i_handle, F_SETFL, i_flags | O_NONBLOCK ) < 0 )
- {
- msg_Err( p_this, "cannot set socket to non-blocking mode" );
- }
- }
-#endif
-#endif
-
- /* Connect the socket */
- if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == -1 )
- {
-#ifdef HAVE_ERRNO_H
- if( errno == EINPROGRESS )
- {
- int i_ret;
- int i_opt;
- int i_opt_size = sizeof( i_opt );
- struct timeval timeout;
- fd_set fds;
-
- msg_Dbg( p_this, "connection in progress" );
- do
+ if( i_ttl < 1 )
{
- if( p_this->b_die )
+ if( var_Get( p_this, "ttl", &val ) != VLC_SUCCESS )
{
- msg_Dbg( p_this, "connection aborted" );
- goto error;
+ var_Create( p_this, "ttl",
+ VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+ var_Get( p_this, "ttl", &val );
}
-
- /* Initialize file descriptor set */
- FD_ZERO( &fds );
- FD_SET( i_handle, &fds );
-
- /* We'll wait 0.1 second if nothing happens */
- timeout.tv_sec = 0;
- timeout.tv_usec = 100000;
- } while( ( i_ret = select( i_handle + 1, NULL, &fds, NULL, &timeout )) == 0 ||
- ( i_ret < 0 && errno == EINTR ) );
- if( i_ret < 0 )
- {
- msg_Warn( p_this, "cannot connect socket (select failed)" );
- goto error;
+ i_ttl = val.i_int;
}
- if( getsockopt( i_handle, SOL_SOCKET, SO_ERROR, (void*)&i_opt, &i_opt_size ) == -1 ||
- i_opt != 0 )
+ if( i_ttl < 1 ) i_ttl = 1;
+ ttl = (unsigned char) i_ttl;
+
+ /* There is some confusion in the world whether IP_MULTICAST_TTL
+ * takes a byte or an int as an argument.
+ * BSD seems to indicate byte so we are going with that and use
+ * int as a fallback to be safe */
+ if( setsockopt( i_handle, IPPROTO_IP, IP_MULTICAST_TTL,
+ &ttl, sizeof( ttl ) ) < 0 )
{
- msg_Warn( p_this, "cannot connect socket (SO_ERROR)" );
- goto error;
+ msg_Dbg( p_this, "failed to set ttl (%s). Let's try it "
+ "the integer way.", strerror(errno) );
+ if( setsockopt( i_handle, IPPROTO_IP, IP_MULTICAST_TTL,
+ &i_ttl, sizeof( i_ttl ) ) <0 )
+ {
+ msg_Err( p_this, "failed to set ttl (%s)",
+ strerror(errno) );
+ close( i_handle );
+ return 0;
+ }
}
}
- else
- {
- msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
- goto error;
- }
-#else
- msg_Warn( p_this, "cannot connect socket" );
- goto error;
#endif
}
p_socket->i_handle = i_handle;
- p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
- return VLC_SUCCESS;
-error:
- if( i_handle > 0 )
+ if( var_Get( p_this, "mtu", &val ) != VLC_SUCCESS )
{
- close( i_handle );
+ var_Create( p_this, "mtu", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+ var_Get( p_this, "mtu", &val );
}
- return VLC_EGENERIC;
-}
+ p_socket->i_mtu = val.i_int;
-/*****************************************************************************
- * NetOpen: wrapper around OpenUDP and OpenTCP
- *****************************************************************************/
-static int NetOpen( vlc_object_t * p_this )
-{
- network_socket_t * p_socket = p_this->p_private;
-
- if( p_socket->i_type == NETWORK_UDP )
- {
- return OpenUDP( p_this, p_socket );
- }
- else
- {
- return OpenTCP( p_this, p_socket );
- }
+ return 0;
}