1 /*******************************************************************************
2 * network.c: functions to read from the network
4 *******************************************************************************
6 *******************************************************************************/
8 /*******************************************************************************
10 *******************************************************************************/
11 #include <sys/types.h>
15 #include <netdb.h> /* servent, getservbyname(), hostent, gethostbyname() */
16 #include <sys/socket.h> /* socket(), setsockopt(), bind(), connect() */
17 #include <unistd.h> /* close() */
18 #include <netinet/in.h> /* sockaddr_in, htons(), htonl() */
26 #include "vlc_thread.h"
30 #include "input_network.h"
31 #include "input_vlan.h"
36 /******************************************************************************
37 * input_NetworkOpen: initialize a network stream
38 ******************************************************************************/
39 int input_NetworkOpen( input_thread_t *p_input )
42 struct sockaddr_in sa_in;
43 char psz_hostname[INPUT_MAX_SOURCE_LENGTH];
45 /* First and foremost, in the VLAN method, join the desired VLAN. */
46 if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
48 if( input_VlanJoin( p_input->i_vlan ) )
50 intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
55 /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
57 if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
59 intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
64 * Set up the options of the socket
67 /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
69 if( setsockopt( p_input->i_handle,
73 sizeof( i_socket_option ) ) == (-1) )
75 intf_ErrMsg("error: can't configure socket (%s)\n", strerror(errno));
76 close( p_input->i_handle );
80 /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
81 * packet loss caused by scheduling problems */
82 i_socket_option = 524288;
83 if( setsockopt( p_input->i_handle,
87 sizeof( i_socket_option ) ) == (-1) )
89 intf_ErrMsg("error: can't configure socket (%s)\n", strerror(errno));
90 close( p_input->i_handle );
98 /* Use default port if not specified */
99 if( p_input->i_port == 0 )
101 p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
104 /* Find the address. */
105 switch( p_input->i_method )
107 case INPUT_METHOD_TS_BCAST:
108 case INPUT_METHOD_TS_VLAN_BCAST:
109 /* In that case, we have to bind with the broadcast address.
110 * broadcast addresses are very hard to find and depends on
111 * implementation, so we thought using a #define would be much
113 #ifdef INPUT_BCAST_ADDR
114 if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
116 close( p_input->i_handle );
120 /* We bind with any address. Security problem ! */
121 if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
123 close( p_input->i_handle );
129 case INPUT_METHOD_TS_UCAST:
130 /* Unicast: bind with the local address. */
131 if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
133 intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
134 close( p_input->i_handle );
137 if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
139 close( p_input->i_handle );
144 case INPUT_METHOD_TS_MCAST:
145 /* Multicast: bind with 239.0.0.1. */
146 if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
148 close( p_input->i_handle );
154 /* Effectively bind the socket. */
155 if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
157 intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
158 close( p_input->i_handle );
163 * Connect the socket to the remote server
166 /* Use default host if not specified */
167 if( p_input->psz_source == NULL )
169 p_input->psz_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
172 if( BuildInetAddr( &sa_in, p_input->psz_source, htons(0) ) == (-1) )
174 close( p_input->i_handle );
178 /* Connect the socket. */
179 if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
180 sizeof( sa_in ) ) == (-1) )
182 intf_ErrMsg("error: can't connect socket\n" );
183 close( p_input->i_handle );
189 /******************************************************************************
190 * input_NetworkRead: read a stream from the network
191 ******************************************************************************
192 * Wait for data during up to 1 second and then abort if none is arrived. The
193 * number of bytes read is returned or -1 if an error occurs (so 0 is returned
195 * We don't have to make any test on presentation times, since we suppose
196 * the network server sends us data when we need it.
197 ******************************************************************************/
198 int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
205 /* Watch the given fd to see when it has input */
207 FD_SET(p_input->i_handle, &rfds);
209 /* Wait up to 1 second */
213 i_rc = select(p_input->i_handle+1, &rfds, NULL, NULL, &tv);
217 /* Data were received before timeout */
218 i_rc = readv( p_input->i_handle, p_vector, i_count );
224 /******************************************************************************
225 * input_NetworkClose: close a network stream
226 ******************************************************************************/
227 void input_NetworkClose( input_thread_t *p_input )
229 /* Close local socket. */
230 if( p_input->i_handle )
232 close( p_input->i_handle );
235 /* Leave vlan if required */
236 if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
238 input_VlanLeave( p_input->i_vlan );