#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
-
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
-
-#if defined( WIN32 ) || defined( UNDER_CE )
-# if defined(UNDER_CE) && defined(sockaddr_storage)
-# undef sockaddr_storage
-# endif
-# include <io.h>
-# include <winsock2.h>
-# include <ws2tcpip.h>
-#else
-# include <sys/socket.h>
-# include <netinet/in.h>
-# ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-# endif
-# include <netdb.h>
-#endif
-
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
if( fd == -1 )
{
#if defined(WIN32) || defined(UNDER_CE)
- msg_Warn( p_this, "cannot create socket (%i)",
- WSAGetLastError() );
+ if( WSAGetLastError ( ) != WSAEAFNOSUPPORT )
+ msg_Warn( p_this, "cannot create socket (%i)",
+ WSAGetLastError() );
#else
- msg_Warn( p_this, "cannot create socket (%s)",
- strerror( errno ) );
+ if( errno != EAFNOSUPPORT )
+ msg_Warn( p_this, "cannot create socket (%s)",
+ strerror( errno ) );
#endif
return -1;
}
#endif
#if defined( WIN32 ) || defined( UNDER_CE )
-# ifdef IPV6_PROTECTION_LEVEL
+# ifndef IPV6_PROTECTION_LEVEL
+# define IPV6_PROTECTION_LEVEL 23
+# endif
if( i_family == AF_INET6 )
{
i_val = 30 /*PROTECTION_LEVEL_UNRESTRICTED*/;
setsockopt( fd, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL,
(const char*)&i_val, sizeof( i_val ) );
}
-# else
-# warning You are using outdated headers for Winsock !
-# endif
#endif
return fd;
}
/*****************************************************************************
- * __net_OpenTCP:
+ * __net_ConnectTCP:
*****************************************************************************
* Open a TCP connection and return a handle
*****************************************************************************/
-int __net_OpenTCP( vlc_object_t *p_this, const char *psz_host, int i_port )
+int __net_ConnectTCP( vlc_object_t *p_this, const char *psz_host, int i_port )
{
struct addrinfo hints, *res, *ptr;
const char *psz_realhost;
char *psz_socks;
int i_realport, i_val, i_handle = -1;
+ vlc_bool_t b_unreach = VLC_FALSE;
if( i_port == 0 )
i_port = 80; /* historical VLC thing */
psz_realhost = psz_socks;
i_realport = ( psz != NULL ) ? atoi( psz ) : 1080;
- msg_Dbg( p_this, "net: connecting to '%s:%d' for '%s:%d'",
+ msg_Dbg( p_this, "net: connecting to %s port %d for %s port %d",
psz_realhost, i_realport, psz_host, i_port );
}
else
psz_realhost = psz_host;
i_realport = i_port;
- msg_Dbg( p_this, "net: connecting to '%s:%d'", psz_realhost,
+ msg_Dbg( p_this, "net: connecting to %s port %d", psz_realhost,
i_realport );
}
i_val = vlc_getaddrinfo( p_this, psz_realhost, i_realport, &hints, &res );
if( i_val )
{
- msg_Err( p_this, "cannot resolve '%s:%d' : %s", psz_realhost,
+ msg_Err( p_this, "cannot resolve %s port %d : %s", psz_realhost,
i_realport, vlc_gai_strerror( i_val ) );
free( psz_socks );
return -1;
div_t d;
struct timeval tv;
vlc_value_t timeout;
+
#if defined( WIN32 ) || defined( UNDER_CE )
if( WSAGetLastError() != WSAEWOULDBLOCK )
{
- msg_Warn( p_this, "connection to %s:%d failed (%d)", psz_host,
- i_port, WSAGetLastError( ) );
+ if( WSAGetLastError () == WSAENETUNREACH )
+ b_unreach = VLC_TRUE;
+ else
+ msg_Warn( p_this, "connection to %s port %d failed (%d)",
+ psz_host, i_port, WSAGetLastError( ) );
net_Close( fd );
continue;
}
#else
if( errno != EINPROGRESS )
{
- msg_Warn( p_this, "connection to %s:%d : %s", psz_host,
- i_port, strerror( errno ) );
+ if( errno == ENETUNREACH )
+ b_unreach = VLC_TRUE;
+ else
+ msg_Warn( p_this, "connection to %s port %d : %s", psz_host,
+ i_port, strerror( errno ) );
net_Close( fd );
continue;
}
if( getsockopt( fd, SOL_SOCKET, SO_ERROR, (void*)&i_val,
&i_val_size ) == -1 || i_val != 0 )
{
+ if( i_val == ENETUNREACH )
+ b_unreach = VLC_TRUE;
+ else
+ {
#ifdef WIN32
- msg_Warn( p_this, "connection to %s:%d failed (%d)", psz_host,
- i_port, WSAGetLastError( ) );
+ msg_Warn( p_this, "connection to %s port %d failed (%d)",
+ psz_host, i_port, WSAGetLastError( ) );
#else
- msg_Warn( p_this, "connection to %s:%d : %s", psz_host,
- i_port, strerror( i_val ) );
+ msg_Warn( p_this, "connection to %s port %d : %s", psz_host,
+ i_port, strerror( i_val ) );
#endif
+ }
net_Close( fd );
continue;
}
}
i_handle = fd; /* success! */
}
-
+
vlc_freeaddrinfo( res );
+ if( i_handle == -1 )
+ {
+ if( b_unreach )
+ msg_Err( p_this, "Host %s port %d is unreachable", psz_host,
+ i_port );
+ return -1;
+ }
+
if( *psz_socks && *psz_socks != ':' )
{
char *psz_user = var_CreateGetString( p_this, "socks-user" );
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
- msg_Dbg( p_this, "net: listening to '%s:%d'", psz_host, i_port );
+ msg_Dbg( p_this, "net: listening to %s port %d", psz_host, i_port );
i_val = vlc_getaddrinfo( p_this, psz_host, i_port, &hints, &res );
if( i_val )
{
- msg_Err( p_this, "cannot resolve '%s:%d' : %s", psz_host, i_port,
+ msg_Err( p_this, "cannot resolve %s port %d : %s", psz_host, i_port,
vlc_gai_strerror( i_val ) );
return NULL;
}
net_Close( fd );
continue;
}
-
+
/* Listen */
if( listen( fd, 100 ) == -1 )
{
pi_handles = newpi;
}
}
-
+
vlc_freeaddrinfo( res );
if( pi_handles != NULL )
return -1;
}
+
+/*****************************************************************************
+ * __net_ConnectUDP:
+ *****************************************************************************
+ * Open a UDP socket to send data to a defined destination, with an optional
+ * hop limit.
+ *****************************************************************************/
+int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
+ int hlim )
+{
+ struct addrinfo hints, *res, *ptr;
+ int i_val, i_handle = -1;
+ vlc_bool_t b_unreach = VLC_FALSE;
+
+ if( i_port == 0 )
+ i_port = 1234; /* historical VLC thing */
+
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_socktype = SOCK_DGRAM;
+
+ msg_Dbg( p_this, "net: connecting to %s port %d", psz_host, i_port );
+
+ i_val = vlc_getaddrinfo( p_this, psz_host, i_port, &hints, &res );
+ if( i_val )
+ {
+ msg_Err( p_this, "cannot resolve %s port %d : %s", psz_host, i_port,
+ vlc_gai_strerror( i_val ) );
+ return -1;
+ }
+
+ for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
+ {
+ int fd;
+
+ fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype,
+ ptr->ai_protocol );
+ if( fd == -1 )
+ continue;
+#if !defined( SYS_BEOS )
+ else
+ {
+ int i_val;
+
+ /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
+ * packet loss caused by scheduling problems */
+ i_val = 0x80000;
+ setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *)&i_val,
+ sizeof( i_val ) );
+ i_val = 0x80000;
+ setsockopt( i_handle, SOL_SOCKET, SO_SNDBUF, (void *)&i_val,
+ sizeof( i_val ) );
+ }
+#endif
+
+ if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
+ {
+ /* success */
+ i_handle = fd;
+ break;
+ }
+
+#if defined( WIN32 ) || defined( UNDER_CE )
+ if( WSAGetLastError () == WSAENETUNREACH )
+#else
+ if( errno == ENETUNREACH )
+#endif
+ b_unreach = VLC_TRUE;
+ else
+ {
+ msg_Warn( p_this, "%s port %d : %s", psz_host, i_port,
+ strerror( errno ) );
+ net_Close( fd );
+ continue;
+ }
+ }
+
+ vlc_freeaddrinfo( res );
+
+ if( i_handle == -1 )
+ {
+ if( b_unreach )
+ msg_Err( p_this, "Host %s port %d is unreachable", psz_host,
+ i_port );
+ return -1;
+ }
+
+ return i_handle;
+}
+
/*****************************************************************************
* __net_OpenUDP:
*****************************************************************************
network_socket_t sock;
module_t *p_network = NULL;
+ if( ( psz_server != NULL ) && ( psz_server[0] == '\0' ) )
+ msg_Warn( p_this, "calling net_OpenUDP with an explicit destination "
+ "is obsolete - use net_ConnectUDP instead" );
+ if( i_server != 0 )
+ msg_Warn( p_this, "calling net_OpenUDP with an explicit destination "
+ "port is obsolete - use __net_ConnectUDP instead" );
+
+ if( psz_server == NULL ) psz_server = "";
+ if( psz_bind == NULL ) psz_bind = "";
+
/* Prepare the network_socket_t structure */
sock.psz_bind_addr = psz_bind;
sock.i_bind_port = i_bind;
sock.v6only = 0;
sock.i_handle = -1;
- if( psz_server == NULL )
- psz_server = "";
- if( psz_bind == NULL )
- psz_bind = "";
-
msg_Dbg( p_this, "net: connecting to '[%s]:%d@[%s]:%d'",
psz_server, i_server, psz_bind, i_bind );
else if( WSAGetLastError() == WSAEINTR ) continue;
else msg_Err( p_this, "recv failed (%i)", WSAGetLastError() );
#else
- /* EAGAIN only happens with p_vs (SSL) and it's not an error */
+ /* EAGAIN only happens with p_vs (TLS) and it's not an error */
if( errno != EAGAIN )
msg_Err( p_this, "recv failed (%s)", strerror(errno) );
#endif
buffer[2] = 0x00; /* - No auth required */
i_len = 3;
}
-
+
if( net_Write( p_obj, fd, NULL, buffer, i_len ) != i_len )
return VLC_EGENERIC;
if( net_Read( p_obj, fd, NULL, buffer, 2, VLC_TRUE ) != 2 )
int len = sizeof( addr );
/* Damn it, they didn't even put LPCSTR for the firs parameter!!! */
+#ifdef UNICODE
+ wchar_t *workaround_for_ill_designed_api =
+ malloc( MAX_PATH * sizeof(wchar_t) );
+ mbstowcs( workaround_for_ill_designed_api, src, MAX_PATH );
+ workaround_for_ill_designed_api[MAX_PATH-1] = 0;
+#else
char *workaround_for_ill_designed_api = strdup( src );
-
+#endif
+
if( !WSAStringToAddress( workaround_for_ill_designed_api, af, NULL,
(LPSOCKADDR)&addr, &len ) )
{
case AF_INET6:
memcpy( dst, &((struct sockaddr_in6 *)&addr)->sin6_addr, 16 );
break;
-
+
case AF_INET:
memcpy( dst, &((struct sockaddr_in *)&addr)->sin_addr, 4 );
break;