]> git.sesse.net Git - vlc/blob - include/network.h
be12a7c797257f1f81c143dea09488e42005cdae
[vlc] / include / network.h
1 /*****************************************************************************
2  * network.h: interface to communicate with network plug-ins
3  *****************************************************************************
4  * Copyright (C) 2002-2005 VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *          RĂ©mi Denis-Courmont <rem # videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 #ifndef __VLC_NETWORK_H
27 # define __VLC_NETWORK_H
28 /*****************************************************************************
29  * network_socket_t: structure passed to a network plug-in to define the
30  *                   kind of socket we want
31  *****************************************************************************/
32 struct network_socket_t
33 {
34     char * psz_bind_addr;
35     int i_bind_port;
36
37     char * psz_server_addr;
38     int i_server_port;
39
40     int i_ttl;
41
42     /* Return values */
43     int i_handle;
44     size_t i_mtu;
45 };
46
47 typedef struct
48 {
49     char *psz_protocol;
50     char *psz_username;
51     char *psz_password;
52     char *psz_host;
53     int  i_port;
54
55     char *psz_path;
56
57     char *psz_option;
58     
59     char *psz_buffer; /* to be freed */
60 } vlc_url_t;
61
62 /*****************************************************************************
63  * vlc_UrlParse:
64  *****************************************************************************
65  * option : if != 0 then path is split at this char
66  *
67  * format [protocol://[login[:password]@]][host[:port]]/path[OPTIONoption]
68  *****************************************************************************/
69 static inline void vlc_UrlParse( vlc_url_t *url, const char *psz_url,
70                                  char option )
71 {
72     char *psz_dup;
73     char *psz_parse;
74     char *p;
75
76     url->psz_protocol = NULL;
77     url->psz_username = NULL;
78     url->psz_password = NULL;
79     url->psz_host     = NULL;
80     url->i_port       = 0;
81     url->psz_path     = NULL;
82     url->psz_option   = NULL;
83     
84     if( psz_url == NULL )
85     {
86         url->psz_buffer = NULL;
87         return;
88     }
89     url->psz_buffer = psz_parse = psz_dup = strdup( psz_url );
90
91     p  = strstr( psz_parse, ":/" );
92     if( p != NULL )
93     {
94         /* we have a protocol */
95
96         /* skip :// */
97         *p++ = '\0';
98         if( p[1] == '/' )
99             p += 2;
100         url->psz_protocol = psz_parse;
101
102         psz_parse = p;
103         p = strchr( psz_parse, '@' );
104         if( p != NULL )
105         {
106             /* We have a login */
107             url->psz_username = psz_parse;
108             *p++ = '\0';
109
110             psz_parse = strchr( psz_parse, ':' );
111             if( psz_parse != NULL )
112             {
113                 /* We have a password */
114                 *psz_parse++ = '\0';
115                 url->psz_password = psz_parse;
116             }
117
118             psz_parse = p;
119         }
120     }
121
122     p = strchr( psz_parse, '/' );
123     if( !p || psz_parse < p )
124     {
125         char *p2;
126
127         /* We have a host[:port] */
128         url->psz_host = strdup( psz_parse );
129         if( p )
130         {
131             url->psz_host[p - psz_parse] = '\0';
132         }
133
134         if( *url->psz_host == '[' )
135         {
136             /* Ipv6 address */
137             p2 = strchr( url->psz_host, ']' );
138             if( p2 )
139             {
140                 p2 = strchr( p2, ':' );
141             }
142         }
143         else
144         {
145             p2 = strchr( url->psz_host, ':' );
146         }
147         if( p2 )
148         {
149             *p2++ = '\0';
150             url->i_port = atoi( p2 );
151         }
152     }
153     psz_parse = p;
154
155     /* Now parse psz_path and psz_option */
156     if( psz_parse )
157     {
158         url->psz_path = psz_parse;
159         if( option != '\0' )
160         {
161             p = strchr( url->psz_path, option );
162             if( p )
163             {
164                 *p++ = '\0';
165                 url->psz_option = p;
166             }
167         }
168     }
169 }
170
171 /*****************************************************************************
172  * vlc_UrlClean:
173  *****************************************************************************
174  *
175  *****************************************************************************/
176 static inline void vlc_UrlClean( vlc_url_t *url )
177 {
178     if( url->psz_buffer ) free( url->psz_buffer );
179     if( url->psz_host )   free( url->psz_host );
180
181     url->psz_protocol = NULL;
182     url->psz_username = NULL;
183     url->psz_password = NULL;
184     url->psz_host     = NULL;
185     url->i_port       = 0;
186     url->psz_path     = NULL;
187     url->psz_option   = NULL;
188
189     url->psz_buffer   = NULL;
190 }
191
192 /*****************************************************************************
193  * vlc_UrlEncode: 
194  *****************************************************************************
195  * perform URL encoding
196  * (you do NOT want to do URL decoding - it is not reversible - do NOT do it)
197  *****************************************************************************/
198 static inline char *vlc_UrlEncode( const char *psz_url )
199 {
200     char *psz_enc, *out;
201     const char *in;
202
203     psz_enc = (char *)malloc( 3 * strlen( psz_url ) + 1 );
204     if( psz_enc == NULL )
205         return NULL;
206
207     out = psz_enc;
208     for( in = psz_url; *in; in++ )
209     {
210         char c = *in;
211
212         if( ( c <= 32 ) || ( c == '%' ) || ( c == '?' ) || ( c == '&' )
213          || ( c == '+' ) )
214         {
215             *out++ = '%';   
216             *out++ = ( ( c >> 4 ) >= 0xA ) ? 'A' + ( c >> 4 ) - 0xA
217                                            : '0' + ( c >> 4 );
218             *out++ = ( ( c & 0xf ) >= 0xA ) ? 'A' + ( c & 0xf ) - 0xA
219                                            : '0' + ( c & 0xf );
220         }
221         else
222             *out++ = c;
223     }
224     *out++ = '\0';
225
226     return (char *)realloc( psz_enc, out - psz_enc );
227 }
228
229 /*****************************************************************************
230  * vlc_UrlIsNotEncoded:
231  *****************************************************************************
232  * check if given string is not a valid URL and must hence be encoded
233  *****************************************************************************/
234 #include <ctype.h>
235
236 static inline int vlc_UrlIsNotEncoded( const char *psz_url )
237 {
238     const char *ptr;
239
240     for( ptr = psz_url; *ptr; ptr++ )
241     {
242         char c = *ptr;
243
244         if( c == '%' )
245         {
246             if( !isxdigit( ptr[1] ) || !isxdigit( ptr[2] ) )
247                 return 1; /* not encoded */
248             ptr += 2;
249         }
250         else
251         if( c == ' ' )
252             return 1;
253     }
254     return 0; /* looks fine - but maybe it is not encoded */
255 }
256                     
257 /*****************************************************************************
258  * vlc_b64_encode:
259  *****************************************************************************
260  *
261  *****************************************************************************/
262 static inline char *vlc_b64_encode( char *src )
263 {
264     static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
265                                                                                 
266     char *dst = (char *)malloc( strlen( src ) * 4 / 3 + 12 );
267     char *ret = dst;
268     unsigned i_bits = 0;
269     unsigned i_shift = 0;
270                                                                                 
271     for( ;; )
272     {
273         if( *src )
274         {
275             i_bits = ( i_bits << 8 )|( *src++ );
276             i_shift += 8;
277         }
278         else if( i_shift > 0 )
279         {
280            i_bits <<= 6 - i_shift;
281            i_shift = 6;
282         }
283         else
284         {
285             *dst++ = '=';
286             break;
287         }
288                                                                                 
289         while( i_shift >= 6 )
290         {
291             i_shift -= 6;
292             *dst++ = b64[(i_bits >> i_shift)&0x3f];
293         }
294     }
295                                                                                 
296     *dst++ = '\0';
297                                                                                 
298     return ret;
299 }
300
301 /* Portable networking layer communication */
302 #define net_OpenTCP(a, b, c) __net_OpenTCP(VLC_OBJECT(a), b, c)
303 VLC_EXPORT( int, __net_OpenTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) );
304
305 #define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c)
306 VLC_EXPORT( int *, __net_ListenTCP, ( vlc_object_t *, const char *, int ) );
307
308 #define net_Accept(a, b, c) __net_Accept(VLC_OBJECT(a), b, c)
309 VLC_EXPORT( int, __net_Accept, ( vlc_object_t *, int *, mtime_t ) );
310
311 #define net_OpenUDP(a, b, c, d, e ) __net_OpenUDP(VLC_OBJECT(a), b, c, d, e)
312 VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, char *psz_bind, int i_bind, char *psz_server, int i_server ) );
313
314 VLC_EXPORT( void, net_Close, ( int fd ) );
315 VLC_EXPORT( void, net_ListenClose, ( int *fd ) );
316
317
318 /* Functions to read from or write to the networking layer */
319 struct virtual_socket_t
320 {
321     void *p_sys;
322     int (*pf_recv) ( void *, void *, int );
323     int (*pf_send) ( void *, const void *, int );
324 };
325
326 #define net_Read(a,b,c,d,e,f) __net_Read(VLC_OBJECT(a),b,c,d,e,f)
327 VLC_EXPORT( int, __net_Read, ( vlc_object_t *p_this, int fd, v_socket_t *, uint8_t *p_data, int i_data, vlc_bool_t b_retry ) );
328
329 #define net_ReadNonBlock(a,b,c,d,e,f) __net_ReadNonBlock(VLC_OBJECT(a),b,c,d,e,f)
330 VLC_EXPORT( int, __net_ReadNonBlock, ( vlc_object_t *p_this, int fd, v_socket_t *, uint8_t *p_data, int i_data, mtime_t i_wait ) );
331
332 #define net_Select(a,b,c,d,e,f,g) __net_Select(VLC_OBJECT(a),b,c,d,e,f,g)
333 VLC_EXPORT( int, __net_Select, ( vlc_object_t *p_this, int *pi_fd, v_socket_t **, int i_fd, uint8_t *p_data, int i_data, mtime_t i_wait ) );
334
335 #define net_Write(a,b,c,d,e) __net_Write(VLC_OBJECT(a),b,c,d,e)
336 VLC_EXPORT( int, __net_Write, ( vlc_object_t *p_this, int fd, v_socket_t *, uint8_t *p_data, int i_data ) );
337
338 #define net_Gets(a,b,c) __net_Gets(VLC_OBJECT(a),b,c)
339 VLC_EXPORT( char *, __net_Gets, ( vlc_object_t *p_this, int fd, v_socket_t * ) );
340
341 VLC_EXPORT( int, net_Printf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, ... ) );
342
343 #define net_vaPrintf(a,b,c,d,e) __net_vaPrintf(VLC_OBJECT(a),b,c,d,e)
344 VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, va_list args ) );
345
346 /*****************************************************************************
347  * net_StopRecv/Send
348  *****************************************************************************
349  * Wrappers for shutdown()
350  *****************************************************************************/
351 #if defined (SHUT_WR)
352 /* the standard way */
353 # define net_StopSend( fd ) shutdown( fd, SHUT_WR )
354 # define net_StopRecv( fd ) shutdown( fd, SHUT_RD )
355 #elif defined (SD_SEND)
356 /* the Microsoft seemingly-purposedly-different-for-the-sake-of-it way */
357 # define net_StopSend( fd ) shutdown( fd, SD_SEND )
358 # define net_StopRecv( fd ) shutdown( fd, SD_RECEIVE )
359 #else
360 # warning FIXME: implement shutdown on your platform!
361 # define net_StopSend( fd ) void(0)
362 # define net_StopRecv( fd ) void(0)
363 #endif
364
365 #define net_CheckIP(a,b,c,d) __net_CheckIP(VLC_OBJECT(a),b,c,d)
366 VLC_EXPORT( int, __net_CheckIP, ( vlc_object_t *p_this, char *psz_ip, char **ppsz_hosts, int i_hosts ) );
367
368 /* Portable network names/addresses resolution layer */
369
370 /* GAI error codes */
371 # ifndef EAI_BADFLAGS
372 #  define EAI_BADFLAGS -1
373 # endif
374 # ifndef EAI_NONAME
375 #  define EAI_NONAME -2
376 # endif
377 # ifndef EAI_AGAIN
378 #  define EAI_AGAIN -3
379 # endif
380 # ifndef EAI_FAIL
381 #  define EAI_FAIL -4
382 # endif
383 # ifndef EAI_NODATA
384 #  define EAI_NODATA -5
385 # endif
386 # ifndef EAI_FAMILY
387 #  define EAI_FAMILY -6
388 # endif
389 # ifndef EAI_SOCKTYPE
390 #  define EAI_SOCKTYPE -7
391 # endif
392 # ifndef EAI_SERVICE
393 #  define EAI_SERVICE -8
394 # endif
395 # ifndef EAI_ADDRFAMILY
396 #  define EAI_ADDRFAMILY -9
397 # endif
398 # ifndef EAI_MEMORY
399 #  define EAI_MEMORY -10
400 # endif
401 # ifndef EAI_SYSTEM
402 #  define EAI_SYSTEM -11
403 # endif
404
405
406 # ifndef NI_MAXHOST
407 #  define NI_MAXHOST 1025
408 #  define NI_MAXSERV 32
409 # endif
410 # define NI_MAXNUMERICHOST 48
411
412 # ifndef NI_NUMERICHOST
413 #  define NI_NUMERICHOST 0x01
414 #  define NI_NUMERICSERV 0x02
415 #  define NI_NOFQDN      0x04
416 #  define NI_NAMEREQD    0x08
417 #  define NI_DGRAM       0x10
418 # endif
419
420 # ifndef HAVE_STRUCT_ADDRINFO
421 struct addrinfo
422 {
423     int ai_flags;
424     int ai_family;
425     int ai_socktype;
426     int ai_protocol;
427     size_t ai_addrlen;
428     struct sockaddr *ai_addr;
429     char *ai_canonname;
430     struct addrinfo *ai_next;
431 };
432 #  define AI_PASSIVE     1
433 #  define AI_CANONNAME   2
434 #  define AI_NUMERICHOST 4
435 # endif /* if !HAVE_STRUCT_ADDRINFO */
436
437 /*** libidn support ***/
438 # ifndef AI_IDN
439 #  define AI_IDN      0
440 #  define AI_CANONIDN 0
441 # endif
442
443 VLC_EXPORT( const char *, vlc_gai_strerror, ( int ) );
444 VLC_EXPORT( int, vlc_getnameinfo, ( const struct sockaddr *, int, char *, int, int *, int ) );
445 VLC_EXPORT( int, vlc_getaddrinfo, ( vlc_object_t *, const char *, int, const struct addrinfo *, struct addrinfo ** ) );
446 VLC_EXPORT( void, vlc_freeaddrinfo, ( struct addrinfo * ) );
447
448 #endif