1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004-2005 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@videolan.org>
8 * RĂ©mi Denis-Courmont <rem # videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
36 #ifdef HAVE_SYS_TIME_H
37 # include <sys/time.h>
46 # define INADDR_ANY 0x00000000
49 # define INADDR_NONE 0xFFFFFFFF
52 extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
55 /*****************************************************************************
57 *****************************************************************************
58 * Open a UDP socket to send data to a defined destination, with an optional
60 *****************************************************************************/
61 int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
64 struct addrinfo hints, *res, *ptr;
65 int i_val, i_handle = -1;
66 vlc_bool_t b_unreach = VLC_FALSE;
69 i_port = 1234; /* historical VLC thing */
71 memset( &hints, 0, sizeof( hints ) );
72 hints.ai_socktype = SOCK_DGRAM;
74 msg_Dbg( p_this, "net: connecting to %s port %d", psz_host, i_port );
76 i_val = vlc_getaddrinfo( p_this, psz_host, i_port, &hints, &res );
79 msg_Err( p_this, "cannot resolve %s port %d : %s", psz_host, i_port,
80 vlc_gai_strerror( i_val ) );
84 for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
88 fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype,
92 #if !defined( SYS_BEOS )
97 /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
98 * packet loss caused by scheduling problems */
100 setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *)&i_val,
103 setsockopt( i_handle, SOL_SOCKET, SO_SNDBUF, (void *)&i_val,
108 if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
115 #if defined( WIN32 ) || defined( UNDER_CE )
116 if( WSAGetLastError () == WSAENETUNREACH )
118 if( errno == ENETUNREACH )
120 b_unreach = VLC_TRUE;
123 msg_Warn( p_this, "%s port %d : %s", psz_host, i_port,
130 vlc_freeaddrinfo( res );
135 msg_Err( p_this, "Host %s port %d is unreachable", psz_host,
143 /*****************************************************************************
145 *****************************************************************************
146 * Open a UDP connection and return a handle
147 *****************************************************************************/
148 int __net_OpenUDP( vlc_object_t *p_this, const char *psz_bind, int i_bind,
149 const char *psz_server, int i_server )
153 network_socket_t sock;
154 module_t *p_network = NULL;
156 if( ( psz_server != NULL ) && ( psz_server[0] == '\0' ) )
157 msg_Warn( p_this, "calling net_OpenUDP with an explicit destination "
158 "is obsolete - use net_ConnectUDP instead" );
160 msg_Warn( p_this, "calling net_OpenUDP with an explicit destination "
161 "port is obsolete - use __net_ConnectUDP instead" );
163 if( psz_server == NULL ) psz_server = "";
164 if( psz_bind == NULL ) psz_bind = "";
166 /* Prepare the network_socket_t structure */
167 sock.psz_bind_addr = psz_bind;
168 sock.i_bind_port = i_bind;
169 sock.psz_server_addr = psz_server;
170 sock.i_server_port = i_server;
175 msg_Dbg( p_this, "net: connecting to '[%s]:%d@[%s]:%d'",
176 psz_server, i_server, psz_bind, i_bind );
178 /* Check if we have force ipv4 or ipv6 */
179 var_Create( p_this, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
180 var_Get( p_this, "ipv4", &v4 );
181 var_Create( p_this, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
182 var_Get( p_this, "ipv6", &v6 );
189 /* try IPv6 first (unless IPv4 forced) */
190 private = p_this->p_private;
191 p_this->p_private = (void*)&sock;
192 p_network = module_Need( p_this, "network", "ipv6", VLC_TRUE );
194 if( p_network != NULL )
195 module_Unneed( p_this, p_network );
197 p_this->p_private = private;
200 * Check if the IP stack can receive IPv4 packets on IPv6 sockets.
201 * If yes, then it is better to use the IPv6 socket.
202 * Otherwise, if we also get an IPv4, we have to choose, so we use
205 if( ( sock.i_handle != -1 ) && ( ( sock.v6only == 0 ) || v6.b_bool ) )
206 return sock.i_handle;
211 int fd6 = sock.i_handle;
213 /* also try IPv4 (unless IPv6 forced) */
214 private = p_this->p_private;
215 p_this->p_private = (void*)&sock;
216 p_network = module_Need( p_this, "network", "ipv4", VLC_TRUE );
218 if( p_network != NULL )
219 module_Unneed( p_this, p_network );
221 p_this->p_private = private;
225 if( sock.i_handle != -1 )
227 msg_Warn( p_this, "net: lame IPv6/IPv4 dual-stack present. "
228 "Using only IPv4." );
236 if( sock.i_handle == -1 )
237 msg_Dbg( p_this, "net: connection to '[%s]:%d@[%s]:%d' failed",
238 psz_server, i_server, psz_bind, i_bind );
240 return sock.i_handle;