1 /*****************************************************************************
2 * network.c: functions to read from the network
4 *****************************************************************************
5 * Copyright (C) 1999, 2000 VideoLAN
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <sys/types.h> /* on BSD, uio.h needs types.h */
29 #include <sys/uio.h> /* "input.h" */
30 #include <string.h> /* strerror() */
31 #include <unistd.h> /* close() */
32 #include <errno.h> /* errno */
33 #include <sys/time.h> /* "input_network.h" */
35 #if defined(SYS_BSD) || defined(SYS_BEOS)
36 #include <sys/socket.h> /* struct sockaddr */
39 #include <netdb.h> /* servent, getservbyname(), hostent, gethostbyname() */
40 #include <netinet/in.h> /* sockaddr_in, htons(), htonl() */
49 #include "input_network.h"
50 #include "input_vlan.h"
55 /*****************************************************************************
56 * input_NetworkOpen: initialize a network stream
57 *****************************************************************************/
58 int input_NetworkOpen( input_thread_t *p_input )
61 struct sockaddr_in sa_in;
62 char psz_hostname[INPUT_MAX_SOURCE_LENGTH];
64 /* First and foremost, in the VLAN method, join the desired VLAN. */
65 if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
67 if( input_VlanJoin( p_input->i_vlan ) )
69 intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
74 /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
76 if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
78 intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
83 * Set up the options of the socket
86 /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
88 if( setsockopt( p_input->i_handle,
92 sizeof( i_socket_option ) ) == (-1) )
94 intf_ErrMsg("error: can't configure socket (SO_REUSEADDR: %s)\n", strerror(errno));
95 close( p_input->i_handle );
100 /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
101 * packet loss caused by scheduling problems */
102 i_socket_option = 524288;
103 if( setsockopt( p_input->i_handle,
107 sizeof( i_socket_option ) ) == (-1) )
109 intf_ErrMsg("error: can't configure socket (SO_RCVBUF: %s)\n", strerror(errno));
110 close( p_input->i_handle );
113 #endif /* SYS_BEOS */
119 /* Use default port if not specified */
120 if( p_input->i_port == 0 )
122 p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
125 /* Find the address. */
126 switch( p_input->i_method )
128 case INPUT_METHOD_TS_BCAST:
129 case INPUT_METHOD_TS_VLAN_BCAST:
130 /* In that case, we have to bind with the broadcast address.
131 * broadcast addresses are very hard to find and depends on
132 * implementation, so we thought using a #define would be much
134 #ifdef INPUT_BCAST_ADDR
135 if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
137 close( p_input->i_handle );
141 /* We bind with any address. Security problem ! */
142 if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
144 close( p_input->i_handle );
150 case INPUT_METHOD_TS_UCAST:
151 /* Unicast: bind with the local address. */
152 if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
154 intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
155 close( p_input->i_handle );
158 if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
160 close( p_input->i_handle );
165 case INPUT_METHOD_TS_MCAST:
166 /* Multicast: bind with 239.0.0.1. */
167 if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
169 close( p_input->i_handle );
175 /* Effectively bind the socket. */
176 if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
178 intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
179 close( p_input->i_handle );
184 * Connect the socket to the remote server
187 /* Use default host if not specified */
188 if( p_input->psz_source == NULL )
190 p_input->psz_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
193 if( BuildInetAddr( &sa_in, p_input->psz_source, htons(0) ) == (-1) )
195 close( p_input->i_handle );
199 /* Connect the socket. */
200 if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
201 sizeof( sa_in ) ) == (-1) )
203 intf_ErrMsg("error: can't connect socket\n" );
204 close( p_input->i_handle );
210 /*****************************************************************************
211 * input_NetworkRead: read a stream from the network
212 *****************************************************************************
213 * Wait for data during up to 1 second and then abort if none is arrived. The
214 * number of bytes read is returned or -1 if an error occurs (so 0 is returned
216 * We don't have to make any test on presentation times, since we suppose
217 * the network server sends us data when we need it.
218 *****************************************************************************/
219 int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
226 /* Watch the given fd to see when it has input */
228 FD_SET(p_input->i_handle, &rfds);
230 /* Wait up to 1 second */
234 i_rc = select(p_input->i_handle+1, &rfds, NULL, NULL, &tv);
238 /* Data were received before timeout */
239 i_rc = readv( p_input->i_handle, p_vector, i_count );
245 /*****************************************************************************
246 * input_NetworkClose: close a network stream
247 *****************************************************************************/
248 void input_NetworkClose( input_thread_t *p_input )
250 /* Close local socket. */
251 if( p_input->i_handle )
253 close( p_input->i_handle );
256 /* Leave vlan if required */
257 if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
259 input_VlanLeave( p_input->i_vlan );