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
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <sys/types.h> /* on BSD, uio.h needs types.h */
30 #include <sys/uio.h> /* "input.h" */
31 #include <string.h> /* strerror() */
32 #include <unistd.h> /* close() */
33 #include <errno.h> /* errno */
34 #include <sys/time.h> /* "input_network.h" */
36 #if defined(SYS_BSD) || defined(SYS_BEOS)
37 #include <sys/socket.h> /* struct sockaddr */
40 #include <netdb.h> /* servent, getservbyname(), hostent, gethostbyname() */
41 #include <netinet/in.h> /* sockaddr_in, htons(), htonl() */
50 #include "input_network.h"
51 #include "input_vlan.h"
56 /*****************************************************************************
57 * input_NetworkOpen: initialize a network stream
58 *****************************************************************************/
59 int input_NetworkOpen( input_thread_t *p_input )
62 struct sockaddr_in sa_in;
63 char psz_hostname[INPUT_MAX_SOURCE_LENGTH];
65 /* First and foremost, in the VLAN method, join the desired VLAN. */
66 if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
68 if( input_VlanJoin( p_input->i_vlan ) )
70 intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
75 /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
77 if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
79 intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
84 * Set up the options of the socket
87 /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
89 if( setsockopt( p_input->i_handle,
93 sizeof( i_socket_option ) ) == (-1) )
95 intf_ErrMsg("error: can't configure socket (SO_REUSEADDR: %s)\n", strerror(errno));
96 close( p_input->i_handle );
101 /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
102 * packet loss caused by scheduling problems */
103 i_socket_option = 524288;
104 if( setsockopt( p_input->i_handle,
108 sizeof( i_socket_option ) ) == (-1) )
110 intf_ErrMsg("error: can't configure socket (SO_RCVBUF: %s)\n", strerror(errno));
111 close( p_input->i_handle );
114 #endif /* SYS_BEOS */
120 /* Use default port if not specified */
121 if( p_input->i_port == 0 )
123 p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
126 /* Find the address. */
127 switch( p_input->i_method )
129 case INPUT_METHOD_TS_BCAST:
130 case INPUT_METHOD_TS_VLAN_BCAST:
131 /* In that case, we have to bind with the broadcast address.
132 * broadcast addresses are very hard to find and depends on
133 * implementation, so we thought using a #define would be much
135 #ifdef INPUT_BCAST_ADDR
136 if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
138 close( p_input->i_handle );
142 /* We bind with any address. Security problem ! */
143 if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
145 close( p_input->i_handle );
151 case INPUT_METHOD_TS_UCAST:
152 /* Unicast: bind with the local address. */
153 if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
155 intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
156 close( p_input->i_handle );
159 if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
161 close( p_input->i_handle );
166 case INPUT_METHOD_TS_MCAST:
167 /* Multicast: bind with 239.0.0.1. */
168 if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
170 close( p_input->i_handle );
176 /* Effectively bind the socket. */
177 if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
179 intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
180 close( p_input->i_handle );
185 * Connect the socket to the remote server
188 /* Use default host if not specified */
189 if( p_input->psz_source == NULL )
191 p_input->psz_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
194 if( BuildInetAddr( &sa_in, p_input->psz_source, htons(0) ) == (-1) )
196 close( p_input->i_handle );
200 /* Connect the socket. */
201 if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
202 sizeof( sa_in ) ) == (-1) )
204 intf_ErrMsg("error: can't connect socket\n" );
205 close( p_input->i_handle );
211 /*****************************************************************************
212 * input_NetworkRead: read a stream from the network
213 *****************************************************************************
214 * Wait for data during up to 1 second and then abort if none is arrived. The
215 * number of bytes read is returned or -1 if an error occurs (so 0 is returned
217 * We don't have to make any test on presentation times, since we suppose
218 * the network server sends us data when we need it.
219 *****************************************************************************/
220 int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
227 /* Watch the given fd to see when it has input */
229 FD_SET(p_input->i_handle, &rfds);
231 /* Wait up to 1 second */
235 i_rc = select(p_input->i_handle+1, &rfds, NULL, NULL, &tv);
239 /* Data were received before timeout */
240 i_rc = readv( p_input->i_handle, p_vector, i_count );
246 /*****************************************************************************
247 * input_NetworkClose: close a network stream
248 *****************************************************************************/
249 void input_NetworkClose( input_thread_t *p_input )
251 /* Close local socket. */
252 if( p_input->i_handle )
254 close( p_input->i_handle );
257 /* Leave vlan if required */
258 if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
260 input_VlanLeave( p_input->i_vlan );