]> git.sesse.net Git - vlc/blob - src/input/input_network.c
D�but du portage BeOS. Beaucoup de fuchiers ont �t� modifi� car il a fallu
[vlc] / src / input / input_network.c
1 /*****************************************************************************
2  * network.c: functions to read from the network
3  * Manages a socket.
4  *****************************************************************************
5  * Copyright (C) 1999, 2000 VideoLAN
6  *
7  * Authors:
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
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" */
34
35 #if defined(SYS_BSD) || defined(SYS_BEOS)
36 #include <sys/socket.h>                                   /* struct sockaddr */
37 #endif
38
39 #include <netdb.h>     /* servent, getservbyname(), hostent, gethostbyname() */
40 #include <netinet/in.h>                     /* sockaddr_in, htons(), htonl() */
41
42 #include "threads.h"
43 #include "common.h"
44 #include "config.h"
45 #include "mtime.h"
46 #include "netutils.h"
47
48 #include "input.h"
49 #include "input_network.h"
50 #include "input_vlan.h"
51
52 #include "intf_msg.h"
53 #include "main.h"
54
55 /*****************************************************************************
56  * input_NetworkOpen: initialize a network stream
57  *****************************************************************************/
58 int input_NetworkOpen( input_thread_t *p_input )
59 {
60     int                     i_socket_option;
61     struct sockaddr_in      sa_in;
62     char                    psz_hostname[INPUT_MAX_SOURCE_LENGTH];
63
64     /* First and foremost, in the VLAN method, join the desired VLAN. */
65     if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
66     {
67         if( input_VlanJoin( p_input->i_vlan ) )
68         {
69             intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
70             return( 1 );
71         }
72     }
73
74     /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
75      * protocol */
76     if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
77     {
78         intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
79         return( 1 );
80     }
81
82     /*
83      * Set up the options of the socket
84      */
85
86     /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
87     i_socket_option = 1;
88     if( setsockopt( p_input->i_handle,
89                     SOL_SOCKET,
90                     SO_REUSEADDR,
91                     &i_socket_option,
92                     sizeof( i_socket_option ) ) == (-1) )
93     {
94         intf_ErrMsg("error: can't configure socket (SO_REUSEADDR: %s)\n", strerror(errno));
95         close( p_input->i_handle );
96         return( 1 );
97     }
98
99 #ifndef SYS_BEOS
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,
104                     SOL_SOCKET,
105                     SO_RCVBUF,
106                     &i_socket_option,
107                     sizeof( i_socket_option ) ) == (-1) )
108     {
109         intf_ErrMsg("error: can't configure socket (SO_RCVBUF: %s)\n", strerror(errno));
110         close( p_input->i_handle );
111         return( 1 );
112     }
113 #endif /* SYS_BEOS */
114
115     /*
116      * Bind the socket
117      */
118
119     /* Use default port if not specified */
120     if( p_input->i_port == 0 )
121     {
122         p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
123     }
124
125     /* Find the address. */
126     switch( p_input->i_method )
127     {
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
133          * simpler. */
134 #ifdef INPUT_BCAST_ADDR
135         if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
136         {
137             close( p_input->i_handle );
138             return( 1 );
139         }
140 #else
141         /* We bind with any address. Security problem ! */
142         if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
143         {
144             close( p_input->i_handle );
145             return( -1 );
146         }
147 #endif
148         break;
149
150     case INPUT_METHOD_TS_UCAST:
151         /* Unicast: bind with the local address. */
152         if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
153         {
154             intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
155             close( p_input->i_handle );
156             return( 1 );
157         }
158         if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
159         {
160             close( p_input->i_handle );
161             return( 1 );
162         }
163         break;
164
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) )
168         {
169             close( p_input->i_handle );
170             return( 1 );
171         }
172         break;
173     }
174
175     /* Effectively bind the socket. */
176     if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
177     {
178         intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
179         close( p_input->i_handle );
180         return( 1 );
181     }
182
183     /*
184      * Connect the socket to the remote server
185      */
186
187     /* Use default host if not specified */
188     if( p_input->psz_source == NULL )
189     {
190         p_input->psz_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
191     }
192
193     if( BuildInetAddr( &sa_in, p_input->psz_source, htons(0) ) == (-1) )
194     {
195         close( p_input->i_handle );
196         return( -1 );
197     }
198
199     /* Connect the socket. */
200     if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
201                  sizeof( sa_in ) ) == (-1) )
202     {
203         intf_ErrMsg("error: can't connect socket\n" );
204         close( p_input->i_handle );
205         return( 1 );
206     }
207     return( 0 );
208 }
209
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
215  * after a timeout)
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,
220                        size_t i_count )
221 {
222     fd_set rfds;
223     struct timeval tv;
224     int i_rc;
225
226     /* Watch the given fd to see when it has input */
227     FD_ZERO(&rfds);
228     FD_SET(p_input->i_handle, &rfds);
229
230     /* Wait up to 1 second */
231     tv.tv_sec = 1;
232     tv.tv_usec = 0;
233
234     i_rc = select(p_input->i_handle+1, &rfds, NULL, NULL, &tv);
235
236     if( i_rc > 0 )
237     {
238         /* Data were received before timeout */
239         i_rc = readv( p_input->i_handle, p_vector, i_count );
240     }
241
242     return( i_rc );
243 }
244
245 /*****************************************************************************
246  * input_NetworkClose: close a network stream
247  *****************************************************************************/
248 void input_NetworkClose( input_thread_t *p_input )
249 {
250     /* Close local socket. */
251     if( p_input->i_handle )
252     {
253         close( p_input->i_handle );
254     }
255
256     /* Leave vlan if required */
257     if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
258     {
259         input_VlanLeave( p_input->i_vlan );
260     }
261 }
262