X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=include%2Fnetwork.h;h=fa64725b84da86b83d6a880cfddc5d26898b7bf8;hb=267cd7f9b7dac986e6d2bc490f778107be95a8fc;hp=bbada0f4a02d96bc5ad5206ccc11dc754f2d0292;hpb=fe087a38282e93addb25fa9598393e40ea233b09;p=vlc diff --git a/include/network.h b/include/network.h index bbada0f4a0..fa64725b84 100644 --- a/include/network.h +++ b/include/network.h @@ -20,296 +20,78 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifndef __VLC_NETWORK_H # define __VLC_NETWORK_H -#if defined( UNDER_CE ) -# include -#elif defined( WIN32 ) +#if defined( WIN32 ) +# if defined(UNDER_CE) && defined(sockaddr_storage) +# undef sockaddr_storage +# endif +# if defined(UNDER_CE) +# define HAVE_STRUCT_ADDRINFO +# else +# include +# endif # include -#elif HAVE_SYS_SOCKET_H -# include +# include +# define ENETUNREACH WSAENETUNREACH +# define net_errno (WSAGetLastError()) +extern const char *net_strerror( int val ); +#else +# if HAVE_SYS_SOCKET_H +# include +# endif +# if HAVE_NETINET_IN_H +# include +# endif +# if HAVE_ARPA_INET_H +# include +# elif defined( SYS_BEOS ) +# include +# endif +# include +# define net_errno errno +# define net_strerror strerror #endif +# ifdef __cplusplus +extern "C" { +# endif + /***************************************************************************** * network_socket_t: structure passed to a network plug-in to define the * kind of socket we want *****************************************************************************/ struct network_socket_t { - char * psz_bind_addr; + const char *psz_bind_addr; int i_bind_port; - char * psz_server_addr; + const char *psz_server_addr; int i_server_port; int i_ttl; + int v6only; + /* Return values */ int i_handle; size_t i_mtu; }; -typedef struct -{ - char *psz_protocol; - char *psz_username; - char *psz_password; - char *psz_host; - int i_port; - - char *psz_path; - - char *psz_option; - - char *psz_buffer; /* to be freed */ -} vlc_url_t; - -/***************************************************************************** - * vlc_UrlParse: - ***************************************************************************** - * option : if != 0 then path is split at this char - * - * format [protocol://[login[:password]@]][host[:port]]/path[OPTIONoption] - *****************************************************************************/ -static inline void vlc_UrlParse( vlc_url_t *url, const char *psz_url, - char option ) -{ - char *psz_dup; - char *psz_parse; - char *p; - - url->psz_protocol = NULL; - url->psz_username = NULL; - url->psz_password = NULL; - url->psz_host = NULL; - url->i_port = 0; - url->psz_path = NULL; - url->psz_option = NULL; - - if( psz_url == NULL ) - { - url->psz_buffer = NULL; - return; - } - url->psz_buffer = psz_parse = psz_dup = strdup( psz_url ); - - p = strstr( psz_parse, ":/" ); - if( p != NULL ) - { - /* we have a protocol */ - - /* skip :// */ - *p++ = '\0'; - if( p[1] == '/' ) - p += 2; - url->psz_protocol = psz_parse; - - psz_parse = p; - p = strchr( psz_parse, '@' ); - if( p != NULL ) - { - /* We have a login */ - url->psz_username = psz_parse; - *p++ = '\0'; - - psz_parse = strchr( psz_parse, ':' ); - if( psz_parse != NULL ) - { - /* We have a password */ - *psz_parse++ = '\0'; - url->psz_password = psz_parse; - } - - psz_parse = p; - } - } - - p = strchr( psz_parse, '/' ); - if( !p || psz_parse < p ) - { - char *p2; - - /* We have a host[:port] */ - url->psz_host = strdup( psz_parse ); - if( p ) - { - url->psz_host[p - psz_parse] = '\0'; - } - - if( *url->psz_host == '[' ) - { - /* Ipv6 address */ - p2 = strchr( url->psz_host, ']' ); - if( p2 ) - { - p2 = strchr( p2, ':' ); - } - } - else - { - p2 = strchr( url->psz_host, ':' ); - } - if( p2 ) - { - *p2++ = '\0'; - url->i_port = atoi( p2 ); - } - } - psz_parse = p; - - /* Now parse psz_path and psz_option */ - if( psz_parse ) - { - url->psz_path = psz_parse; - if( option != '\0' ) - { - p = strchr( url->psz_path, option ); - if( p ) - { - *p++ = '\0'; - url->psz_option = p; - } - } - } -} - -/***************************************************************************** - * vlc_UrlClean: - ***************************************************************************** - * - *****************************************************************************/ -static inline void vlc_UrlClean( vlc_url_t *url ) -{ - if( url->psz_buffer ) free( url->psz_buffer ); - if( url->psz_host ) free( url->psz_host ); - - url->psz_protocol = NULL; - url->psz_username = NULL; - url->psz_password = NULL; - url->psz_host = NULL; - url->i_port = 0; - url->psz_path = NULL; - url->psz_option = NULL; - - url->psz_buffer = NULL; -} - -/***************************************************************************** - * vlc_UrlEncode: - ***************************************************************************** - * perform URL encoding - * (you do NOT want to do URL decoding - it is not reversible - do NOT do it) - *****************************************************************************/ -static inline char *vlc_UrlEncode( const char *psz_url ) -{ - char *psz_enc, *out; - const char *in; - - psz_enc = (char *)malloc( 3 * strlen( psz_url ) + 1 ); - if( psz_enc == NULL ) - return NULL; - - out = psz_enc; - for( in = psz_url; *in; in++ ) - { - char c = *in; - - if( ( c <= 32 ) || ( c == '%' ) || ( c == '?' ) || ( c == '&' ) - || ( c == '+' ) ) - { - *out++ = '%'; - *out++ = ( ( c >> 4 ) >= 0xA ) ? 'A' + ( c >> 4 ) - 0xA - : '0' + ( c >> 4 ); - *out++ = ( ( c & 0xf ) >= 0xA ) ? 'A' + ( c & 0xf ) - 0xA - : '0' + ( c & 0xf ); - } - else - *out++ = c; - } - *out++ = '\0'; - - return (char *)realloc( psz_enc, out - psz_enc ); -} - -/***************************************************************************** - * vlc_UrlIsNotEncoded: - ***************************************************************************** - * check if given string is not a valid URL and must hence be encoded - *****************************************************************************/ -#include - -static inline int vlc_UrlIsNotEncoded( const char *psz_url ) -{ - const char *ptr; - - for( ptr = psz_url; *ptr; ptr++ ) - { - char c = *ptr; +/* Portable networking layer communication */ +int net_Socket (vlc_object_t *obj, int family, int socktype, int proto); - if( c == '%' ) - { - if( !isxdigit( ptr[1] ) || !isxdigit( ptr[2] ) ) - return 1; /* not encoded */ - ptr += 2; - } - else - if( c == ' ' ) - return 1; - } - return 0; /* looks fine - but maybe it is not encoded */ -} - -/***************************************************************************** - * vlc_b64_encode: - ***************************************************************************** - * - *****************************************************************************/ -static inline char *vlc_b64_encode( char *src ) -{ - static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - char *dst = (char *)malloc( strlen( src ) * 4 / 3 + 12 ); - char *ret = dst; - unsigned i_bits = 0; - unsigned i_shift = 0; - - for( ;; ) - { - if( *src ) - { - i_bits = ( i_bits << 8 )|( *src++ ); - i_shift += 8; - } - else if( i_shift > 0 ) - { - i_bits <<= 6 - i_shift; - i_shift = 6; - } - else - { - *dst++ = '='; - break; - } - - while( i_shift >= 6 ) - { - i_shift -= 6; - *dst++ = b64[(i_bits >> i_shift)&0x3f]; - } - } - - *dst++ = '\0'; - - return ret; -} +#define net_ConnectTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c) +#define net_OpenTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c) +VLC_EXPORT( int, __net_ConnectTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) ); -/* Portable networking layer communication */ -#define net_OpenTCP(a, b, c) __net_OpenTCP(VLC_OBJECT(a), b, c) -VLC_EXPORT( int, __net_OpenTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) ); +int *net_Listen (vlc_object_t *p_this, const char *psz_host, int i_port, + int family, int socktype, int protocol); +VLC_EXPORT( int, net_ListenSingle, (vlc_object_t *p_this, const char *psz_host, int i_port, int family, int socktype, int protocol) ); #define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c) VLC_EXPORT( int *, __net_ListenTCP, ( vlc_object_t *, const char *, int ) ); @@ -317,12 +99,23 @@ VLC_EXPORT( int *, __net_ListenTCP, ( vlc_object_t *, const char *, int ) ); #define net_Accept(a, b, c) __net_Accept(VLC_OBJECT(a), b, c) VLC_EXPORT( int, __net_Accept, ( vlc_object_t *, int *, mtime_t ) ); +#define net_ConnectUDP(a, b, c, d ) __net_ConnectUDP(VLC_OBJECT(a), b, c, d) +VLC_EXPORT( int, __net_ConnectUDP, ( vlc_object_t *p_this, const char *psz_host, int i_port, int hlim ) ); + +static inline int net_ListenUDP1 (vlc_object_t *obj, const char *host, int port) +{ + return net_ListenSingle (obj, host, port, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP); +} + #define net_OpenUDP(a, b, c, d, e ) __net_OpenUDP(VLC_OBJECT(a), b, c, d, e) -VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, char *psz_bind, int i_bind, char *psz_server, int i_server ) ); +VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, const char *psz_bind, int i_bind, const char *psz_server, int i_server ) ); VLC_EXPORT( void, net_Close, ( int fd ) ); VLC_EXPORT( void, net_ListenClose, ( int *fd ) ); +VLC_EXPORT( int, net_SetDSCP, ( int fd, uint8_t dscp ) ); +int net_Subscribe (vlc_object_t *obj, int fd, const struct sockaddr *addr, + socklen_t addrlen); /* Functions to read from or write to the networking layer */ struct virtual_socket_t @@ -333,24 +126,31 @@ struct virtual_socket_t }; #define net_Read(a,b,c,d,e,f) __net_Read(VLC_OBJECT(a),b,c,d,e,f) -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 ) ); +VLC_EXPORT( int, __net_Read, ( vlc_object_t *p_this, int fd, const v_socket_t *, uint8_t *p_data, int i_data, vlc_bool_t b_retry ) ); #define net_ReadNonBlock(a,b,c,d,e,f) __net_ReadNonBlock(VLC_OBJECT(a),b,c,d,e,f) -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 ) ); +VLC_EXPORT( int, __net_ReadNonBlock, ( vlc_object_t *p_this, int fd, const v_socket_t *, uint8_t *p_data, int i_data, mtime_t i_wait ) ); #define net_Select(a,b,c,d,e,f,g) __net_Select(VLC_OBJECT(a),b,c,d,e,f,g) -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 ) ); +VLC_EXPORT( int, __net_Select, ( vlc_object_t *p_this, const int *pi_fd, const v_socket_t *const *, int i_fd, uint8_t *p_data, int i_data, mtime_t i_wait ) ); #define net_Write(a,b,c,d,e) __net_Write(VLC_OBJECT(a),b,c,d,e) -VLC_EXPORT( int, __net_Write, ( vlc_object_t *p_this, int fd, v_socket_t *, uint8_t *p_data, int i_data ) ); +VLC_EXPORT( int, __net_Write, ( vlc_object_t *p_this, int fd, const v_socket_t *, const uint8_t *p_data, int i_data ) ); #define net_Gets(a,b,c) __net_Gets(VLC_OBJECT(a),b,c) -VLC_EXPORT( char *, __net_Gets, ( vlc_object_t *p_this, int fd, v_socket_t * ) ); +VLC_EXPORT( char *, __net_Gets, ( vlc_object_t *p_this, int fd, const v_socket_t * ) ); -VLC_EXPORT( int, net_Printf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, ... ) ); +VLC_EXPORT( int, net_Printf, ( vlc_object_t *p_this, int fd, const v_socket_t *, const char *psz_fmt, ... ) ); #define net_vaPrintf(a,b,c,d,e) __net_vaPrintf(VLC_OBJECT(a),b,c,d,e) -VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, va_list args ) ); +VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, const v_socket_t *, const char *psz_fmt, va_list args ) ); + + +#ifndef HAVE_INET_PTON +/* only in core, so no need for C++ extern "C" */ +int inet_pton(int af, const char *src, void *dst); +#endif + /***************************************************************************** * net_StopRecv/Send @@ -366,14 +166,13 @@ VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, c # define net_StopSend( fd ) (void)shutdown( fd, SD_SEND ) # define net_StopRecv( fd ) (void)shutdown( fd, SD_RECEIVE ) #else -# warning FIXME: implement shutdown on your platform! +# ifndef SYS_BEOS /* R5 just doesn't have a working shutdown() */ +# warning FIXME: implement shutdown on your platform! +# endif # define net_StopSend( fd ) (void)0 # define net_StopRecv( fd ) (void)0 #endif -#define net_CheckIP(a,b,c,d) __net_CheckIP(VLC_OBJECT(a),b,c,d) -VLC_EXPORT( int, __net_CheckIP, ( vlc_object_t *p_this, char *psz_ip, char **ppsz_hosts, int i_hosts ) ); - /* Portable network names/addresses resolution layer */ /* GAI error codes */ @@ -416,7 +215,7 @@ VLC_EXPORT( int, __net_CheckIP, ( vlc_object_t *p_this, char *psz_ip, char **pps # define NI_MAXHOST 1025 # define NI_MAXSERV 32 # endif -# define NI_MAXNUMERICHOST 48 +# define NI_MAXNUMERICHOST 64 # ifndef NI_NUMERICHOST # define NI_NUMERICHOST 0x01 @@ -443,15 +242,94 @@ struct addrinfo # define AI_NUMERICHOST 4 # endif /* if !HAVE_STRUCT_ADDRINFO */ -/*** libidn support ***/ -# ifndef AI_IDN -# define AI_IDN 0 -# define AI_CANONIDN 0 -# endif - VLC_EXPORT( const char *, vlc_gai_strerror, ( int ) ); VLC_EXPORT( int, vlc_getnameinfo, ( const struct sockaddr *, int, char *, int, int *, int ) ); VLC_EXPORT( int, vlc_getaddrinfo, ( vlc_object_t *, const char *, int, const struct addrinfo *, struct addrinfo ** ) ); VLC_EXPORT( void, vlc_freeaddrinfo, ( struct addrinfo * ) ); + +static inline vlc_bool_t +net_SockAddrIsMulticast (const struct sockaddr *addr, socklen_t len) +{ + switch (addr->sa_family) + { +#ifdef IN_MULTICAST + case AF_INET: + { + struct sockaddr_in *v4 = (struct sockaddr_in *)addr; + if (len < sizeof (*v4)) + return VLC_FALSE; + return IN_MULTICAST (v4->sin_addr.s_addr) != 0; + } +#endif + +#ifdef IN6_IS_ADDR_MULTICAST + case AF_INET6: + { + struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr; + if (len < sizeof (*v6)) + return VLC_FALSE; + return IN6_IS_ADDR_MULTICAST (&v6->sin6_addr) != 0; + } +#endif + } + + return VLC_FALSE; +} + + + +/** + * net_AddressIsMulticast + * @return VLC_FALSE iff the psz_addr does not specify a multicast address, + * or the address is not a valid address. + */ +static inline vlc_bool_t net_AddressIsMulticast( vlc_object_t *p_object, const char *psz_addr ) +{ + struct addrinfo hints, *res; + + memset (&hints, 0, sizeof (hints)); + hints.ai_socktype = SOCK_DGRAM; /* UDP */ + hints.ai_flags = AI_NUMERICHOST; + + int i = vlc_getaddrinfo (p_object, psz_addr, 0, + &hints, &res); + if (i) + { + msg_Err (p_object, "invalid address \"%s\" for net_AddressIsMulticast (%s)", + psz_addr, vlc_gai_strerror (i)); + return VLC_FALSE; + } + + vlc_bool_t b = net_SockAddrIsMulticast (res->ai_addr, res->ai_addrlen); + vlc_freeaddrinfo (res); + return b; +} + +static inline int net_GetSockAddress( int fd, char *address, int *port ) +{ + struct sockaddr_storage addr; + socklen_t addrlen = sizeof( addr ); + + return getsockname( fd, (struct sockaddr *)&addr, &addrlen ) + || vlc_getnameinfo( (struct sockaddr *)&addr, addrlen, address, + NI_MAXNUMERICHOST, port, NI_NUMERICHOST ) + ? VLC_EGENERIC : 0; +} + +static inline int net_GetPeerAddress( int fd, char *address, int *port ) +{ + struct sockaddr_storage addr; + socklen_t addrlen = sizeof( addr ); + + return getpeername( fd, (struct sockaddr *)&addr, &addrlen ) + || vlc_getnameinfo( (struct sockaddr *)&addr, addrlen, address, + NI_MAXNUMERICHOST, port, NI_NUMERICHOST ) + ? VLC_EGENERIC : 0; +} + +# ifdef __cplusplus +} +# endif + #endif