LCOV - code coverage report
Current view: top level - utils - os_net.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 390 592 65.9 %
Date: 2021-04-29 23:48:07 Functions: 41 41 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / common tools sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #ifndef GPAC_DISABLE_CORE_TOOLS
      27             : 
      28             : #if defined(WIN32) || defined(_WIN32_WCE)
      29             : 
      30             : #define _WINSOCK_DEPRECATED_NO_WARNINGS
      31             : 
      32             : #ifdef _WIN32_WCE
      33             : #include <winsock.h>
      34             : 
      35             : #if !defined(__GNUC__)
      36             : #pragma comment(lib, "winsock")
      37             : #endif
      38             : 
      39             : #else
      40             : 
      41             : #include <sys/timeb.h>
      42             : #include <winsock2.h>
      43             : #include <ws2tcpip.h>
      44             : 
      45             : #if !defined(__GNUC__)
      46             : #pragma comment(lib, "ws2_32")
      47             : #endif
      48             : 
      49             : #endif
      50             : 
      51             : #include <windows.h>
      52             : 
      53             : #if !defined(__GNUC__)
      54             : 
      55             : #if defined(IPV6_MULTICAST_IF)
      56             : #define GPAC_HAS_IPV6 1
      57             : #pragma message("Using WinSock IPV6")
      58             : #else
      59             : #undef GPAC_HAS_IPV6
      60             : #pragma message("Using WinSock IPV4")
      61             : #endif
      62             : 
      63             : #endif
      64             : 
      65             : #include <errno.h>
      66             : 
      67             : #ifndef EISCONN
      68             : /*common win32 redefs*/
      69             : #undef EAGAIN
      70             : #define EAGAIN                          WSAEWOULDBLOCK
      71             : #define EISCONN                         WSAEISCONN
      72             : #define ENOTCONN                        WSAENOTCONN
      73             : #define ECONNRESET                      WSAECONNRESET
      74             : #define EMSGSIZE                        WSAEMSGSIZE
      75             : #define ECONNABORTED            WSAECONNABORTED
      76             : #define ENETDOWN                        WSAENETDOWN
      77             : #undef EINTR
      78             : #define EINTR                           WSAEINTR
      79             : #undef EBADF
      80             : #define EBADF                           WSAEBADF
      81             : #endif
      82             : 
      83             : 
      84             : #define LASTSOCKERROR WSAGetLastError()
      85             : 
      86             : /*the number of sockets used. This because the WinSock lib needs init*/
      87             : static int wsa_init = 0;
      88             : 
      89             : 
      90             : #include <gpac/network.h>
      91             : 
      92             : 
      93             : /*end-win32*/
      94             : 
      95             : #else
      96             : /*non-win32*/
      97             : #include <unistd.h>
      98             : #include <fcntl.h>
      99             : #include <netdb.h>
     100             : 
     101             : #ifndef __BEOS__
     102             : #include <errno.h>
     103             : #endif
     104             : 
     105             : #ifndef __DARWIN__
     106             : #include <sys/time.h>
     107             : #endif
     108             : 
     109             : #include <netinet/in.h>
     110             : #include <netinet/tcp.h>
     111             : #include <sys/socket.h>
     112             : #include <sys/types.h>
     113             : #include <arpa/inet.h>
     114             : 
     115             : #include <gpac/network.h>
     116             : 
     117             : /*not defined on solaris*/
     118             : #if !defined(INADDR_NONE)
     119             : # if (defined(sun) && defined(__SVR4))
     120             : #  define INADDR_NONE -1
     121             : # else
     122             : #  define INADDR_NONE ((unsigned long)-1)
     123             : # endif
     124             : #endif
     125             : 
     126             : 
     127             : #define INVALID_SOCKET -1
     128             : #define SOCKET_ERROR -1
     129             : #define LASTSOCKERROR errno
     130             : 
     131             : typedef s32 SOCKET;
     132             : #define closesocket(v) close(v)
     133             : 
     134             : #endif /*WIN32||_WIN32_WCE*/
     135             : 
     136             : 
     137             : #ifdef GPAC_HAS_IPV6
     138             : # ifndef IPV6_ADD_MEMBERSHIP
     139             : #  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
     140             : # endif
     141             : # ifndef IPV6_DROP_MEMBERSHIP
     142             : #  define IPV6_DROP_MEMBERSHIP   IPV6_LEAVE_GROUP
     143             : # endif
     144             : #endif
     145             : 
     146             : 
     147             : #ifdef __SYMBIAN32__
     148             : #define SSO_CAST
     149             : #else
     150             : #define SSO_CAST (const char *)
     151             : #endif
     152             : 
     153             : 
     154             : #ifdef GPAC_HAS_IPV6
     155             : static u32 ipv6_check_state = 0;
     156             : #endif
     157             : 
     158             : #ifdef _LP64
     159             : #define NULL_SOCKET 0
     160             : #else
     161             : #define NULL_SOCKET (SOCKET)NULL
     162             : #endif
     163             : 
     164             : #ifdef GPAC_HAS_SOCK_UN
     165             : #include <sys/un.h>
     166             : #endif
     167             : 
     168             : GF_EXPORT
     169           1 : const char *gf_errno_str(int errnoval)
     170             : {
     171           1 :         return strerror(errnoval);
     172             : }
     173             : 
     174             : 
     175             : /*internal flags*/
     176             : enum
     177             : {
     178             :         GF_SOCK_IS_TCP = 1<<9,
     179             :         GF_SOCK_IS_IPV6 = 1<<10,
     180             :         GF_SOCK_NON_BLOCKING = 1<<11,
     181             :         GF_SOCK_IS_MULTICAST = 1<<12,
     182             :         GF_SOCK_IS_LISTENING = 1<<13,
     183             :         /*socket is bound to a specific dest (server) or source (client) */
     184             :         GF_SOCK_HAS_PEER = 1<<14,
     185             :         GF_SOCK_IS_UN = 1<<15,
     186             : };
     187             : 
     188             : struct __tag_socket
     189             : {
     190             :         u32 flags;
     191             :         SOCKET socket;
     192             :         /*destination address for sendto/recvfrom*/
     193             : #ifdef GPAC_HAS_IPV6
     194             :         struct sockaddr_storage dest_addr;
     195             : #else
     196             :         struct sockaddr_in dest_addr;
     197             : #endif
     198             :         u32 dest_addr_len;
     199             : 
     200             :         u32 usec_wait;
     201             : };
     202             : 
     203             : 
     204             : 
     205             : GF_EXPORT
     206         179 : u32 gf_net_has_ipv6()
     207             : {
     208             : #ifdef GPAC_HAS_IPV6
     209         179 :         if (!ipv6_check_state) {
     210             :                 SOCKET s;
     211             : #ifdef WIN32
     212             :                 if (!wsa_init) {
     213             :                         WSADATA Data;
     214             :                         if (WSAStartup(0x0202, &Data)!=0) {
     215             :                                 ipv6_check_state = 1;
     216             :                                 return 0;
     217             :                         }
     218             :                 }
     219             : #endif
     220          88 :                 s = socket(PF_INET6, SOCK_STREAM, 0);
     221          88 :                 if (!s) ipv6_check_state = 1;
     222             :                 else {
     223          88 :                         ipv6_check_state = 2;
     224          88 :                         closesocket(s);
     225             :                 }
     226             : #ifdef WIN32
     227             :                 if (!wsa_init) WSACleanup();
     228             : #endif
     229             :         }
     230         179 :         return (ipv6_check_state==2);
     231             : #else
     232             :         return 0;
     233             : #endif
     234             : }
     235             : 
     236             : GF_EXPORT
     237         115 : Bool gf_net_is_ipv6(const char *address)
     238             : {
     239             :         char *sep;
     240         115 :         if (!address) return GF_FALSE;
     241          90 :         sep = strchr(address, ':');
     242             :         if (sep) sep = strchr(address, ':');
     243          90 :         return sep ? GF_TRUE : GF_FALSE;
     244             : }
     245             : 
     246             : #ifdef GPAC_HAS_IPV6
     247             : #define MAX_PEER_NAME_LEN 1024
     248         683 : static struct addrinfo *gf_sk_get_ipv6_addr(const char *PeerName, u16 PortNumber, int family, int flags, int sock_type)
     249             : {
     250         683 :         struct  addrinfo *res=NULL;
     251             :         struct  addrinfo hints;
     252             :         char node[MAX_PEER_NAME_LEN], portstring[20];
     253             :         char *service, *dest;
     254             :         service = dest = NULL;
     255             : #ifdef WIN32
     256             :         if (!wsa_init) {
     257             :                 WSADATA Data;
     258             :                 if (WSAStartup(0x0202, &Data)!=0) return NULL;
     259             :                 wsa_init = 1;
     260             :         }
     261             : #endif
     262             : 
     263             :         service = dest = NULL;
     264             :         memset(&hints, 0, sizeof(hints));
     265         683 :         hints.ai_socktype = sock_type;
     266         683 :         hints.ai_family = family;
     267         683 :         hints.ai_flags = flags;
     268             : 
     269         683 :         if (PortNumber) {
     270         683 :                 sprintf (portstring, "%d", PortNumber);
     271             :                 service = (char *)portstring;
     272             :         }
     273         683 :         if (PeerName) {
     274             :                 strncpy(node, PeerName, MAX_PEER_NAME_LEN-1);
     275         504 :                 if (node[0]=='[') {
     276           0 :                         node[strlen(node)-1] = 0;
     277             :                         memmove(node, &node[1], MAX_PEER_NAME_LEN-1);
     278             :                 }
     279         504 :                 node[MAX_PEER_NAME_LEN - 1] = 0;
     280             :                 dest = (char *) node;
     281             :         }
     282         683 :         if (getaddrinfo((const char *)dest, (const char *)service, &hints, &res) != 0) return NULL;
     283         683 :         return res;
     284             : }
     285             : 
     286             : 
     287             : #endif
     288             : 
     289             : 
     290             : GF_EXPORT
     291          29 : GF_Err gf_sk_get_host_name(char *buffer)
     292             : {
     293             :         s32 ret = gethostname(buffer, GF_MAX_IP_NAME_LEN);
     294          29 :         return (ret == SOCKET_ERROR) ? GF_IP_ADDRESS_NOT_FOUND : GF_OK;
     295             : }
     296             : 
     297             : GF_EXPORT
     298          79 : GF_Err gf_sk_get_local_ip(GF_Socket *sock, char *buffer)
     299             : {
     300             : #ifdef GPAC_HAS_IPV6
     301             :         char clienthost[NI_MAXHOST];
     302          79 :         if (sock->flags & GF_SOCK_HAS_PEER) {
     303          74 :                 if (getnameinfo((struct sockaddr *)&sock->dest_addr, sock->dest_addr_len, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
     304             :                         return GF_IP_NETWORK_FAILURE;
     305             :         } else {
     306             :                 struct sockaddr_storage clientaddr;
     307           5 :                 socklen_t addrlen = sizeof(clientaddr);
     308           5 :                 if (getsockname(sock->socket, (struct sockaddr *)&clientaddr, &addrlen)) return GF_IP_NETWORK_FAILURE;
     309             : 
     310           5 :                 if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
     311             :                         return GF_IP_NETWORK_FAILURE;
     312             :         }
     313             :         strcpy(buffer, clienthost);
     314             : #else
     315             :         char *ip;
     316             :         if (sock->flags & GF_SOCK_HAS_PEER) {
     317             :                 ip = inet_ntoa(sock->dest_addr.sin_addr);
     318             :         } else {
     319             :                 struct sockaddr_in name;
     320             :                 u32 len = sizeof(struct sockaddr_in);
     321             :                 if (getsockname(sock->socket, (struct sockaddr*) &name, &len)) return GF_IP_NETWORK_FAILURE;
     322             :                 ip = inet_ntoa(name.sin_addr);
     323             :         }
     324             :         if (!ip) return GF_IP_NETWORK_FAILURE;
     325             :         strcpy(buffer, ip);
     326             : #endif
     327          79 :         return GF_OK;
     328             : }
     329             : 
     330             : 
     331             : GF_EXPORT
     332         396 : GF_Socket *gf_sk_new(u32 SocketType)
     333             : {
     334             :         GF_Socket *tmp;
     335             : 
     336             :         /*init WinSock*/
     337             : #ifdef WIN32
     338             :         WSADATA Data;
     339             :         if (!wsa_init && (WSAStartup(0x0202, &Data)!=0) ) return NULL;
     340             : #endif
     341         396 :         switch (SocketType) {
     342             :         case GF_SOCK_TYPE_UDP:
     343             :         case GF_SOCK_TYPE_TCP:
     344             : #ifdef GPAC_HAS_SOCK_UN
     345             :         case GF_SOCK_TYPE_UDP_UN:
     346             :         case GF_SOCK_TYPE_TCP_UN:
     347             : #endif
     348             :                 break;
     349           0 :         default:
     350           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] unsupported socket type %d\n", SocketType));
     351             :                 return NULL;
     352             :         }
     353             : 
     354         396 :         GF_SAFEALLOC(tmp, GF_Socket);
     355         396 :         if (!tmp) return NULL;
     356         396 :         if (SocketType == GF_SOCK_TYPE_TCP) tmp->flags |= GF_SOCK_IS_TCP;
     357             : #ifdef GPAC_HAS_SOCK_UN
     358         170 :         else if (SocketType == GF_SOCK_TYPE_TCP_UN) tmp->flags |= GF_SOCK_IS_TCP | GF_SOCK_IS_UN;
     359         170 :         else if (SocketType == GF_SOCK_TYPE_UDP_UN) tmp->flags |= GF_SOCK_IS_UN;
     360             : #endif
     361             : 
     362             : #ifdef GPAC_HAS_IPV6
     363         396 :         memset(&tmp->dest_addr, 0, sizeof(struct sockaddr_storage));
     364             : #else
     365             :         memset(&tmp->dest_addr, 0, sizeof(struct sockaddr_in));
     366             :         tmp->dest_addr_len = sizeof(struct sockaddr);
     367             : #endif
     368             : 
     369         396 :         tmp->usec_wait = 500;
     370             : #ifdef WIN32
     371             :         wsa_init ++;
     372             : #endif
     373         396 :         return tmp;
     374             : }
     375             : 
     376             : GF_EXPORT
     377         165 : GF_Err gf_sk_set_buffer_size(GF_Socket *sock, Bool SendBuffer, u32 NewSize)
     378             : {
     379         165 :         u32 nsize=0, psize;
     380             :         s32 res;
     381         165 :         if (!sock || !sock->socket) return GF_BAD_PARAM;
     382             : 
     383         165 :         if (SendBuffer) {
     384          47 :                 res = setsockopt(sock->socket, SOL_SOCKET, SO_SNDBUF, (char *) &NewSize, sizeof(u32) );
     385             :         } else {
     386         118 :                 res = setsockopt(sock->socket, SOL_SOCKET, SO_RCVBUF, (char *) &NewSize, sizeof(u32) );
     387             :         }
     388         165 :         if (res<0) {
     389           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Couldn't set socket %s buffer size to %d: %d\n", SendBuffer ? "send" : "receive", NewSize, res));
     390             :         } else {
     391         165 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Socket] Set socket %s buffer size to %d\n", SendBuffer ? "send" : "receive", NewSize));
     392             :         }
     393         165 :         psize = sizeof(u32);
     394         165 :         if (SendBuffer) {
     395          47 :                 res = getsockopt(sock->socket, SOL_SOCKET, SO_SNDBUF, (char *) &nsize, &psize );
     396             :         } else {
     397         118 :                 res = getsockopt(sock->socket, SOL_SOCKET, SO_RCVBUF, (char *) &nsize, &psize );
     398             :         }
     399         165 :         if ((res>=0) && (nsize=!NewSize)) {
     400           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Asked to set socket %s buffer size to %d but system used %d\n", SendBuffer ? "send" : "receive", NewSize, nsize));
     401             :         }
     402             : 
     403             :         return GF_OK;
     404             : }
     405             : 
     406             : GF_EXPORT
     407          37 : GF_Err gf_sk_set_block_mode(GF_Socket *sock, Bool NonBlockingOn)
     408             : {
     409             :         s32 res;
     410             : #ifdef WIN32
     411             :         long val = NonBlockingOn;
     412             :         if (sock->socket) {
     413             :                 res = ioctlsocket(sock->socket, FIONBIO, &val);
     414             :                 if (res) return GF_SERVICE_ERROR;
     415             :         }
     416             : #else
     417          37 :         if (sock->socket) {
     418          37 :                 s32 flags = fcntl(sock->socket, F_GETFL, 0);
     419          37 :                 if (NonBlockingOn)
     420          37 :                         flags |= O_NONBLOCK;
     421             :                 else
     422           0 :                         flags &= ~O_NONBLOCK;
     423             : 
     424          37 :                 res = fcntl(sock->socket, F_SETFL, flags);
     425          37 :                 if (res) return GF_SERVICE_ERROR;
     426             :         }
     427             : #endif
     428          37 :         if (NonBlockingOn) {
     429          37 :                 sock->flags |= GF_SOCK_NON_BLOCKING;
     430             :         } else {
     431           0 :                 sock->flags &= ~GF_SOCK_NON_BLOCKING;
     432             :         }
     433             :         return GF_OK;
     434             : }
     435             : 
     436             : #include <assert.h>
     437             : 
     438         474 : static void gf_sk_free(GF_Socket *sock)
     439             : {
     440             :         assert( sock );
     441         474 :         if (!sock->socket) return;
     442             : 
     443             :         /*leave multicast*/
     444         474 :         if (sock->flags & GF_SOCK_IS_MULTICAST) {
     445             :                 struct ip_mreq mreq;
     446             : #ifdef GPAC_HAS_IPV6
     447             :                 struct sockaddr *addr = (struct sockaddr *)&sock->dest_addr;
     448          25 :                 if (addr->sa_family==AF_INET6) {
     449             :                         struct ipv6_mreq mreq6;
     450             :                         memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
     451           0 :                         mreq6.ipv6mr_interface= 0;
     452           0 :                         setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &mreq6, sizeof(mreq6));
     453             :                 } else {
     454          25 :                         mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
     455          25 :                         mreq.imr_interface.s_addr = INADDR_ANY;
     456          25 :                         setsockopt(sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
     457             :                 }
     458             : #else
     459             :                 mreq.imr_multiaddr.s_addr = sock->dest_addr.sin_addr.s_addr;
     460             :                 mreq.imr_interface.s_addr = INADDR_ANY;
     461             :                 setsockopt(sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
     462             : #endif
     463             :         }
     464         474 :         closesocket(sock->socket);
     465         474 :         sock->socket = (SOCKET) 0L;
     466             : }
     467             : 
     468             : 
     469             : GF_EXPORT
     470         474 : void gf_sk_del(GF_Socket *sock)
     471             : {
     472             :         assert( sock );
     473         474 :         gf_sk_free(sock);
     474             : #ifdef WIN32
     475             :         wsa_init --;
     476             :         if (!wsa_init) WSACleanup();
     477             : #endif
     478         474 :         gf_free(sock);
     479         474 : }
     480             : 
     481             : GF_EXPORT
     482          58 : void gf_sk_reset(GF_Socket *sock)
     483             : {
     484             :         u32 clear;
     485          58 :         if (sock) setsockopt(sock->socket, SOL_SOCKET, SO_ERROR, (char *) &clear, sizeof(u32) );
     486          58 : }
     487             : 
     488             : GF_EXPORT
     489          31 : s32 gf_sk_get_handle(GF_Socket *sock)
     490             : {
     491          31 :         return (s32) sock->socket;
     492             : }
     493             : 
     494             : GF_EXPORT
     495           9 : void gf_sk_set_usec_wait(GF_Socket *sock, u32 usec_wait)
     496             : {
     497           9 :         if (!sock) return;
     498           8 :         sock->usec_wait = (usec_wait>=1000000) ? 500 : usec_wait;
     499             : }
     500             : 
     501             : #ifdef GPAC_STATIC_BUILD
     502             : struct hostent *gf_gethostbyname(const char *PeerName)
     503             : {
     504             :         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("Static GPAC build has no DNS support, cannot resolve host %s !\n", PeerName));
     505             :         return NULL;
     506             : }
     507             : #else
     508             : #define gf_gethostbyname gethostbyname
     509             : #endif
     510             : 
     511             : 
     512             : //connects a socket to a remote peer on a given port
     513             : GF_EXPORT
     514         194 : GF_Err gf_sk_connect(GF_Socket *sock, const char *PeerName, u16 PortNumber, const char *local_ip)
     515             : {
     516             :         s32 ret;
     517             : #ifdef GPAC_HAS_IPV6
     518             :         u32 type;
     519             :         struct addrinfo *res, *aip, *lip;
     520             : #else
     521             :         struct hostent *Host = NULL;
     522             : #endif
     523             : 
     524         194 :         if (sock->flags & GF_SOCK_IS_UN) {
     525             : #ifdef GPAC_HAS_SOCK_UN
     526             :                 struct sockaddr_un server_add;
     527           0 :                 if (!sock->socket) {
     528           0 :                         sock->socket = socket(AF_UNIX, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
     529           0 :                         if (sock->flags & GF_SOCK_NON_BLOCKING)
     530           0 :                                 gf_sk_set_block_mode(sock, GF_TRUE);
     531             :                 }
     532           0 :                 server_add.sun_family = AF_UNIX;
     533             :                 strcpy(server_add.sun_path, PeerName);
     534           0 :                 if (connect(sock->socket, (struct sockaddr *) &server_add, sizeof(struct sockaddr_un)) < 0) {
     535           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Failed to connect unix domain socket to %s\n", PeerName));
     536             :                         return GF_IP_CONNECTION_FAILURE;
     537             :              }
     538             :              return GF_OK;
     539             : #else
     540             :              return GF_NOT_SUPPORTED;
     541             : #endif
     542             :         }
     543             : 
     544             : #ifdef GPAC_HAS_IPV6
     545         194 :         type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
     546             : 
     547         194 :         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Solving %s address\n", PeerName));
     548         194 :         res = gf_sk_get_ipv6_addr(PeerName, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
     549         194 :         if (!res) return GF_IP_CONNECTION_FAILURE;
     550         194 :         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Host %s found\n", PeerName));
     551             : 
     552             :         lip = NULL;
     553         194 :         if (local_ip) {
     554           0 :                 lip = gf_sk_get_ipv6_addr(local_ip, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
     555           0 :                 if (!lip && local_ip) {
     556           0 :                         lip = gf_sk_get_ipv6_addr(NULL, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
     557             :                         local_ip = NULL;
     558             :                 }
     559             :         }
     560             : 
     561             :         /*for all interfaces*/
     562         194 :         for (aip=res; aip!=NULL; aip=aip->ai_next) {
     563         194 :                 if (type != (u32) aip->ai_socktype) continue;
     564         194 :                 if (!sock->socket) {
     565         192 :                         sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
     566         192 :                         if (sock->socket == INVALID_SOCKET) {
     567           0 :                                 sock->socket = NULL_SOCKET;
     568           0 :                                 continue;
     569             :                         }
     570         192 :                         if (sock->flags & GF_SOCK_IS_TCP) {
     571         192 :                                 if (sock->flags & GF_SOCK_NON_BLOCKING)
     572           0 :                                         gf_sk_set_block_mode(sock, GF_TRUE);
     573             :                         }
     574             : 
     575         192 :                         if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
     576         192 :                         else sock->flags &= ~GF_SOCK_IS_IPV6;
     577             : 
     578         192 :                         if (lip) {
     579           0 :                                 ret = bind(sock->socket, lip->ai_addr, (int) lip->ai_addrlen);
     580           0 :                                 if (ret == SOCKET_ERROR) {
     581           0 :                                         closesocket(sock->socket);
     582           0 :                                         sock->socket = NULL_SOCKET;
     583           0 :                                         continue;
     584             :                                 }
     585             :                         }
     586             :                 }
     587             : 
     588         194 :                 if (sock->flags & GF_SOCK_IS_TCP) {
     589         192 :                         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Connecting to %s:%d\n", PeerName, PortNumber));
     590         192 :                         ret = connect(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
     591         192 :                         if (ret == SOCKET_ERROR) {
     592           0 :                                 closesocket(sock->socket);
     593           0 :                                 sock->socket = NULL_SOCKET;
     594           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Sock_IPV4] Failed to connect to host %s: %s - retrying\n", PeerName, gf_errno_str(LASTSOCKERROR) ));
     595           0 :                                 continue;
     596             :                         }
     597         192 :                         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV6] Connected to %s:%d\n", PeerName, PortNumber));
     598             : 
     599             : #ifdef SO_NOSIGPIPE
     600             :                         int value = 1;
     601             :                         setsockopt(sock->socket, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
     602             : #endif
     603             :                 }
     604         194 :                 memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
     605         194 :                 sock->dest_addr_len = (u32) aip->ai_addrlen;
     606         194 :                 freeaddrinfo(res);
     607         194 :                 if (lip) freeaddrinfo(lip);
     608             :                 return GF_OK;
     609             :         }
     610           0 :         freeaddrinfo(res);
     611           0 :         if (lip) freeaddrinfo(lip);
     612             :         return GF_IP_CONNECTION_FAILURE;
     613             : 
     614             : #else
     615             :         if (local_ip) {
     616             :                 GF_Err e = gf_sk_bind(sock, local_ip, PortNumber, PeerName, PortNumber, GF_SOCK_REUSE_PORT);
     617             :                 if (e) return e;
     618             :         }
     619             :         if (!sock->socket) {
     620             :                 sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
     621             :                 if (sock->flags & GF_SOCK_NON_BLOCKING)
     622             :                         gf_sk_set_block_mode(sock, GF_TRUE);
     623             :         }
     624             : 
     625             :         /*setup the address*/
     626             :         sock->dest_addr.sin_family = AF_INET;
     627             :         sock->dest_addr.sin_port = htons(PortNumber);
     628             :         /*get the server IP*/
     629             :         sock->dest_addr.sin_addr.s_addr = inet_addr(PeerName);
     630             :         if (sock->dest_addr.sin_addr.s_addr==INADDR_NONE) {
     631             :                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Solving %s address\n", PeerName));
     632             :                 Host = gf_gethostbyname(PeerName);
     633             :                 if (Host == NULL) {
     634             :                         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Failed to retrieve host %s address: %s\n", PeerName, gf_errno_str(LASTSOCKERROR) ));
     635             :                         switch (LASTSOCKERROR) {
     636             : #ifndef __SYMBIAN32__
     637             :                         case ENETDOWN:
     638             :                                 return GF_IP_NETWORK_FAILURE;
     639             :                                 //case ENOHOST: return GF_IP_ADDRESS_NOT_FOUND;
     640             : #endif
     641             :                         default:
     642             :                                 return GF_IP_NETWORK_FAILURE;
     643             :                         }
     644             :                 }
     645             :                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Host %s found\n", PeerName));
     646             :                 memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
     647             :         }
     648             : 
     649             :         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Connecting to %s:%d\n", PeerName, PortNumber));
     650             :         ret = connect(sock->socket, (struct sockaddr *) &sock->dest_addr, sizeof(struct sockaddr));
     651             :         if (ret == SOCKET_ERROR) {
     652             :                 u32 res = LASTSOCKERROR;
     653             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Sock_IPV4] Couldn't connect socket: %s\n", gf_errno_str(res) ));
     654             :                 switch (res) {
     655             :                 case EAGAIN:
     656             :                         return GF_IP_SOCK_WOULD_BLOCK;
     657             : #ifdef WIN32
     658             :                 case WSAEINVAL:
     659             :                         if (sock->flags & GF_SOCK_NON_BLOCKING)
     660             :                                 return GF_IP_SOCK_WOULD_BLOCK;
     661             : #endif
     662             :                 case EISCONN:
     663             :                         return GF_OK;
     664             :                 case ENOTCONN:
     665             :                         return GF_IP_CONNECTION_FAILURE;
     666             :                 case ECONNRESET:
     667             :                         return GF_IP_CONNECTION_FAILURE;
     668             :                 case EMSGSIZE:
     669             :                         return GF_IP_CONNECTION_FAILURE;
     670             :                 case ECONNABORTED:
     671             :                         return GF_IP_CONNECTION_FAILURE;
     672             :                 case ENETDOWN:
     673             :                         return GF_IP_CONNECTION_FAILURE;
     674             :                 default:
     675             :                         return GF_IP_CONNECTION_FAILURE;
     676             :                 }
     677             :         }
     678             :         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[Sock_IPV4] Connected to %s:%d\n", PeerName, PortNumber));
     679             : #endif
     680             :         return GF_OK;
     681             : }
     682             : 
     683             : 
     684             : //binds the given socket to the specified port. If ReUse is true
     685             : //this will enable reuse of ports on a single machine
     686             : GF_EXPORT
     687         179 : GF_Err gf_sk_bind(GF_Socket *sock, const char *local_ip, u16 port, const char *peer_name, u16 peer_port, u32 options)
     688             : {
     689             : #ifdef GPAC_HAS_IPV6
     690             :         struct addrinfo *res, *aip;
     691             :         int af;
     692             :         u32 type;
     693             : #else
     694             :         u32 ip_add;
     695             :         size_t addrlen;
     696             :         struct sockaddr_in LocalAdd;
     697             :         struct hostent *Host = NULL;
     698             : #endif
     699             :         s32 ret = 0;
     700             :         s32 optval;
     701             : 
     702         179 :         if (!sock || sock->socket) return GF_BAD_PARAM;
     703         179 :         if (local_ip && !strcmp(local_ip, "127.0.0.1"))
     704             :                 local_ip = NULL;
     705             : 
     706         179 :         if (sock->flags & GF_SOCK_IS_UN) {
     707             : #ifdef GPAC_HAS_SOCK_UN
     708             :                 struct sockaddr_un server_un;
     709             :                 if (!sock->socket) {
     710           0 :                         sock->socket = socket(AF_UNIX, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
     711           0 :                         if (sock->flags & GF_SOCK_NON_BLOCKING)
     712           0 :                                 gf_sk_set_block_mode(sock, GF_TRUE);
     713             :                 }
     714           0 :                 server_un.sun_family = AF_UNIX;
     715             :                 strcpy(server_un.sun_path, peer_name);
     716           0 :                 ret = bind(sock->socket, (struct sockaddr *) &server_un, (int) sizeof(struct sockaddr_un));
     717           0 :                 if (ret == SOCKET_ERROR) {
     718           0 :                         if (LASTSOCKERROR == EADDRINUSE) {
     719           0 :                                 return gf_sk_connect(sock, peer_name, peer_port, NULL);
     720             :                         }
     721           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot bind socket: %s\n", gf_errno_str(LASTSOCKERROR) ));
     722             :                         return GF_IP_CONNECTION_FAILURE;
     723             :                 }
     724           0 :                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to unix domain %s\n", peer_name));
     725             :                 return GF_OK;
     726             : #else
     727             :             return GF_NOT_SUPPORTED;
     728             : #endif
     729             :         }
     730             : 
     731             : 
     732             : #ifndef WIN32
     733         179 :         if(!local_ip) {
     734         179 :                 if(!peer_name || !strcmp(peer_name,"localhost")) {
     735             :                         peer_name="127.0.0.1";
     736             :                 }
     737             :         }
     738             : #endif
     739             : 
     740             : #ifdef GPAC_HAS_IPV6
     741         179 :         type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
     742         179 :         af = (options & GF_SOCK_FORCE_IPV6) ? PF_INET6 : PF_UNSPEC;
     743         179 :         if (!gf_net_has_ipv6()) af = PF_INET;
     744             :         /*probe way to peer: is it V4 or V6? */
     745         179 :         if (peer_name && peer_port) {
     746         109 :                 res = gf_sk_get_ipv6_addr(peer_name, peer_port, af, AI_PASSIVE, type);
     747         109 :                 if (!res) {
     748           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", peer_name, peer_port));
     749             :                         return GF_IP_ADDRESS_NOT_FOUND;
     750             :                 }
     751             : #ifdef WIN32
     752             :                 /*win32 has troubles redirecting IPV4 datagrams to IPV6 sockets, so override
     753             :                 local family type to avoid IPV4(S)->IPV6(C) UDP*/
     754             :                 af = res->ai_family;
     755             : #endif
     756         109 :                 memcpy(&sock->dest_addr, res->ai_addr, res->ai_addrlen);
     757         109 :                 sock->dest_addr_len = (u32) res->ai_addrlen;
     758         109 :                 freeaddrinfo(res);
     759             :         }
     760             : 
     761         179 :         res = gf_sk_get_ipv6_addr(local_ip, port, af, AI_PASSIVE, type);
     762         179 :         if (!res) {
     763           0 :                 if (local_ip) {
     764           0 :                         res = gf_sk_get_ipv6_addr(NULL, port, af, AI_PASSIVE, type);
     765             :                         local_ip = NULL;
     766             :                 }
     767           0 :                 if (!res) {
     768           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", local_ip, port));
     769             :                         return GF_IP_ADDRESS_NOT_FOUND;
     770             :                 }
     771             :         }
     772             : 
     773             :         /*for all interfaces*/
     774         179 :         for (aip=res; aip!=NULL; aip=aip->ai_next) {
     775         179 :                 if (type != (u32) aip->ai_socktype) continue;
     776             : 
     777         179 :                 if (aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(peer_name)) continue;
     778             : 
     779         179 :                 sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
     780         179 :                 if (sock->socket == INVALID_SOCKET) {
     781           0 :                         sock->socket = NULL_SOCKET;
     782           0 :                         continue;
     783             :                 }
     784         179 :                 if (options & GF_SOCK_REUSE_PORT) {
     785         143 :                         optval = 1;
     786         143 :                         setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
     787             : #ifdef SO_REUSEPORT
     788         143 :                         optval = 1;
     789         143 :                         setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
     790             : #endif
     791             :                 }
     792             : 
     793         179 :                 if (sock->flags & GF_SOCK_NON_BLOCKING)
     794           0 :                         gf_sk_set_block_mode(sock, GF_TRUE);
     795             : 
     796         179 :                 if (peer_name && peer_port)
     797         109 :                         sock->flags |= GF_SOCK_HAS_PEER;
     798             : 
     799         179 :                 if (! (options & GF_SOCK_FAKE_BIND) ) {
     800         108 :                         ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
     801         108 :                         if (ret == SOCKET_ERROR) {
     802           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot bind: %s\n", gf_errno_str(LASTSOCKERROR) ));
     803           0 :                                 closesocket(sock->socket);
     804           0 :                                 sock->socket = NULL_SOCKET;
     805           0 :                                 continue;
     806             :                         }
     807             :                 }
     808         179 :                 if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
     809         179 :                 else sock->flags &= ~GF_SOCK_IS_IPV6;
     810             : 
     811         179 :                 freeaddrinfo(res);
     812         179 :                 return GF_OK;
     813             :         }
     814           0 :         freeaddrinfo(res);
     815           0 :         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot bind to host %s port %d\n", local_ip, port));
     816             :         return GF_IP_CONNECTION_FAILURE;
     817             : 
     818             : #else
     819             : 
     820             :         sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
     821             :         if (sock->flags & GF_SOCK_NON_BLOCKING)
     822             :                 gf_sk_set_block_mode(sock, GF_TRUE);
     823             :         sock->flags &= ~GF_SOCK_IS_IPV6;
     824             : 
     825             :         memset((void *) &LocalAdd, 0, sizeof(LocalAdd));
     826             : 
     827             :         /*setup the address*/
     828             :         ip_add = 0;
     829             :         if (local_ip) ip_add = inet_addr(local_ip);
     830             : 
     831             :         if (!ip_add) {
     832             : #if 0
     833             :                 char buf[GF_MAX_IP_NAME_LEN];
     834             :                 buf[0] = 0;
     835             :                 ret = gethostname(buf, GF_MAX_IP_NAME_LEN);
     836             :                 /*get the IP address*/
     837             :                 Host = gf_gethostbyname(buf);
     838             :                 if (Host != NULL) {
     839             :                         memcpy((char *) &LocalAdd.sin_addr, Host->h_addr_list[0], sizeof(LocalAdd.sin_addr));
     840             :                         ip_add = LocalAdd.sin_addr.s_addr;
     841             :                 } else {
     842             :                         ip_add = INADDR_ANY;
     843             :                 }
     844             : #else
     845             :                 ip_add = INADDR_ANY;
     846             : #endif
     847             :         }
     848             :         if (peer_name && peer_port) {
     849             : #ifdef WIN32
     850             :                 if ((inet_addr(peer_name)== ip_add) || !strcmp(peer_name, "127.0.0.1") ) {
     851             :                         optval = 1;
     852             :                         setsockopt(sock->socket, SOL_SOCKET, SO_USELOOPBACK, SSO_CAST &optval, sizeof(optval));
     853             :                 }
     854             : #endif
     855             :         }
     856             : 
     857             :         LocalAdd.sin_family = AF_INET;
     858             :         LocalAdd.sin_port = htons(port);
     859             :         LocalAdd.sin_addr.s_addr = ip_add;
     860             :         addrlen = sizeof(struct sockaddr_in);
     861             : 
     862             : 
     863             :         if (options & GF_SOCK_REUSE_PORT) {
     864             :                 optval = 1;
     865             :                 setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
     866             : #ifdef SO_REUSEPORT
     867             :                 optval = 1;
     868             :                 setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
     869             : #endif
     870             :         }
     871             : 
     872             :         if (! (options & GF_SOCK_FAKE_BIND) ) {
     873             :                 /*bind the socket*/
     874             :                 ret = bind(sock->socket, (struct sockaddr *) &LocalAdd, (int) addrlen);
     875             :                 if (ret == SOCKET_ERROR) {
     876             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot bind socket: %s\n", gf_errno_str(LASTSOCKERROR) ));
     877             :                         ret = GF_IP_CONNECTION_FAILURE;
     878             :                 }
     879             :         }
     880             : 
     881             :         if (peer_name && peer_port) {
     882             :                 sock->dest_addr.sin_port = htons(peer_port);
     883             :                 sock->dest_addr.sin_family = AF_INET;
     884             :                 sock->dest_addr.sin_addr.s_addr = inet_addr(peer_name);
     885             :                 if (sock->dest_addr.sin_addr.s_addr == INADDR_NONE) {
     886             :                         Host = gf_gethostbyname(peer_name);
     887             :                         if (Host == NULL) ret = GF_IP_ADDRESS_NOT_FOUND;
     888             :                         else memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
     889             :                 }
     890             :                 sock->flags |= GF_SOCK_HAS_PEER;
     891             :         }
     892             :         if (sock->flags & GF_SOCK_HAS_PEER) {
     893             :                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d - remote peer: %s:%d\n", ip_add, port, peer_name, peer_port));
     894             :         } else {
     895             :                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d\n", ip_add, port));
     896             :         }
     897             :         return ret;
     898             : #endif
     899             : }
     900             : 
     901             : //send length bytes of a buffer
     902             : GF_EXPORT
     903        8232 : GF_Err gf_sk_send(GF_Socket *sock, const u8 *buffer, u32 length)
     904             : {
     905             :         u32 count;
     906             :         s32 res;
     907             :         Bool not_ready = GF_FALSE;
     908             : #ifndef __SYMBIAN32__
     909             :         int ready;
     910             :         struct timeval timeout;
     911             :         fd_set Group;
     912             : #endif
     913             : 
     914             :         //the socket must be bound or connected
     915        8232 :         if (!sock || !sock->socket)
     916             :                 return GF_BAD_PARAM;
     917             : 
     918             : #ifndef __SYMBIAN32__
     919             :         //can we write?
     920        8232 :         FD_ZERO(&Group);
     921        8232 :         FD_SET(sock->socket, &Group);
     922        8232 :         timeout.tv_sec = 0;
     923        8232 :         timeout.tv_usec = sock->usec_wait;
     924             : 
     925             :         //TODO CHECK IF THIS IS CORRECT
     926        8232 :         ready = select((int) sock->socket+1, NULL, &Group, NULL, &timeout);
     927        8232 :         if (ready == SOCKET_ERROR) {
     928           0 :                 switch (LASTSOCKERROR) {
     929             :                 case EAGAIN:
     930             :                         return GF_IP_SOCK_WOULD_BLOCK;
     931           0 :                 default:
     932           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] select failure: %s\n", gf_errno_str(LASTSOCKERROR)));
     933             :                         return GF_IP_NETWORK_FAILURE;
     934             :                 }
     935             :         }
     936             : 
     937             :         //should never happen (to check: is writeability is guaranteed for not-connected sockets)
     938        8232 :         if (!ready || !FD_ISSET(sock->socket, &Group)) {
     939             :                 not_ready = GF_TRUE;
     940             :         }
     941             : #endif
     942             : 
     943             :         //direct writing
     944             :         count = 0;
     945       24694 :         while (count < length) {
     946        8232 :                 if (sock->flags & GF_SOCK_HAS_PEER) {
     947        5690 :                         res = (s32) sendto(sock->socket, (char *) buffer+count,  length - count, 0, (struct sockaddr *) &sock->dest_addr, sock->dest_addr_len);
     948             :                 } else {
     949             :                         int sflags = 0;
     950             : #ifdef MSG_NOSIGNAL
     951             :                         sflags = MSG_NOSIGNAL;
     952             : #endif
     953        2542 :                         res = (s32) send(sock->socket, (char *) buffer+count, length - count, sflags);
     954             :                 }
     955        8232 :                 if (res == SOCKET_ERROR) {
     956           2 :                         if (not_ready)
     957             :                                 return GF_IP_NETWORK_EMPTY;
     958             : 
     959           2 :                         switch (res = LASTSOCKERROR) {
     960             :                         case EAGAIN:
     961             :                                 return GF_IP_SOCK_WOULD_BLOCK;
     962             : #ifndef __SYMBIAN32__
     963           2 :                         case ENOTCONN:
     964             :                         case ECONNRESET:
     965             :                         case EPIPE:
     966           2 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] send failure: %s\n", gf_errno_str(LASTSOCKERROR)));
     967             :                                 return GF_IP_CONNECTION_CLOSED;
     968             : #endif
     969             : 
     970             : #ifndef __DARWIN__
     971             :                         case EPROTOTYPE:
     972             :                                 return GF_IP_SOCK_WOULD_BLOCK;
     973             : #endif
     974           0 :                         case ENOBUFS:
     975           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] send failure: %s\n", gf_errno_str(LASTSOCKERROR)));
     976             :                                 return GF_BUFFER_TOO_SMALL;
     977           0 :                         default:
     978           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] send failure: %s\n", gf_errno_str(LASTSOCKERROR)));
     979             :                                 return GF_IP_NETWORK_FAILURE;
     980             :                         }
     981             :                 }
     982        8230 :                 count += res;
     983             :         }
     984             :         return GF_OK;
     985             : }
     986             : 
     987         300 : GF_Err gf_sk_select(GF_Socket *sock, u32 mode)
     988             : {
     989             : #ifndef __SYMBIAN32__
     990             :         int ready;
     991             :         struct timeval timeout;
     992             :         fd_set RGroup;
     993             :         fd_set WGroup;
     994             : #endif
     995             : 
     996             :         //the socket must be bound or connected
     997         300 :         if (!sock || !sock->socket)
     998             :                 return GF_BAD_PARAM;
     999             : 
    1000             : #ifndef __SYMBIAN32__
    1001             :         //can we write?
    1002         300 :         FD_ZERO(&RGroup);
    1003         300 :         FD_ZERO(&WGroup);
    1004         300 :         if (mode != GF_SK_SELECT_WRITE)
    1005           0 :                 FD_SET(sock->socket, &RGroup);
    1006         300 :         if (mode != GF_SK_SELECT_READ)
    1007         300 :                 FD_SET(sock->socket, &WGroup);
    1008         300 :         timeout.tv_sec = 0;
    1009         300 :         timeout.tv_usec = sock->usec_wait;
    1010             : 
    1011             :         //TODO CHECK IF THIS IS CORRECT
    1012         300 :         ready = select((int) sock->socket+1, &RGroup, &WGroup, NULL, &timeout);
    1013         300 :         if (ready == SOCKET_ERROR) {
    1014           0 :                 switch (LASTSOCKERROR) {
    1015             :                 case EAGAIN:
    1016             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1017           0 :                 default:
    1018           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] select failure: %s\n", gf_errno_str(LASTSOCKERROR)));
    1019             :                         return GF_IP_NETWORK_FAILURE;
    1020             :                 }
    1021             :         }
    1022             : 
    1023             :         //should never happen (to check: is writeability is guaranteed for not-connected sockets)
    1024         300 :         if (!ready)
    1025             :                 return GF_IP_SOCK_WOULD_BLOCK;
    1026         297 :         if ((mode != GF_SK_SELECT_WRITE) && !FD_ISSET(sock->socket, &RGroup))
    1027             :                 return GF_IP_SOCK_WOULD_BLOCK;
    1028         297 :         if ((mode != GF_SK_SELECT_READ) && !FD_ISSET(sock->socket, &WGroup))
    1029             :                 return GF_IP_SOCK_WOULD_BLOCK;
    1030             :         return GF_OK;
    1031             : #else
    1032             :         return GF_IP_SOCK_WOULD_BLOCK;
    1033             : #endif
    1034             : }
    1035             : 
    1036             : 
    1037             : GF_EXPORT
    1038         201 : u32 gf_sk_is_multicast_address(const char *multi_IPAdd)
    1039             : {
    1040             : #ifdef GPAC_HAS_IPV6
    1041             :         u32 val;
    1042             :         char *sep;
    1043             :         struct addrinfo *res;
    1044         201 :         if (!multi_IPAdd) return 0;
    1045             :         /*IPV6 multicast address*/
    1046         201 :         sep = strchr(multi_IPAdd, ':');
    1047             :         if (sep) sep = strchr(multi_IPAdd, ':');
    1048         201 :         if (sep && !strnicmp(multi_IPAdd, "ff", 2)) return 1;
    1049             :         /*ipv4 multicast address*/
    1050         201 :         res = gf_sk_get_ipv6_addr((char*)multi_IPAdd, 7000, AF_UNSPEC, AI_PASSIVE, SOCK_DGRAM);
    1051         201 :         if (!res) return 0;
    1052             :         val = 0;
    1053         201 :         if (res->ai_addr->sa_family == AF_INET) {
    1054         402 :                 val = IN_MULTICAST(ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr));
    1055           0 :         } else if (res->ai_addr->sa_family == AF_INET6) {
    1056           0 :                 val = IN6_IS_ADDR_MULTICAST(& ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr);
    1057             :         }
    1058         201 :         freeaddrinfo(res);
    1059         201 :         return val;
    1060             : #else
    1061             :         if (!multi_IPAdd) return 0;
    1062             :         return ((htonl(inet_addr(multi_IPAdd)) >> 8) & 0x00f00000) == 0x00e00000;
    1063             : #endif
    1064             : }
    1065             : 
    1066             : GF_EXPORT
    1067          25 : GF_Err gf_sk_setup_multicast(GF_Socket *sock, const char *multi_IPAdd, u16 MultiPortNumber, u32 TTL, Bool NoBind, char *local_interface_ip)
    1068             : {
    1069             :         s32 ret;
    1070             :         u32 flag;
    1071             :         struct ip_mreq M_req;
    1072             :         u32 optval;
    1073             : #ifdef GPAC_HAS_IPV6
    1074             :         struct sockaddr *addr;
    1075             :         struct addrinfo *res, *aip;
    1076             :         Bool is_ipv6 = GF_FALSE;
    1077             :         u32 type;
    1078             : #endif
    1079             :         u32 local_add_id;
    1080             : 
    1081          25 :         if (!sock || sock->socket) return GF_BAD_PARAM;
    1082             : 
    1083          25 :         if (TTL > 255) TTL = 255;
    1084             : 
    1085             :         /*check the address*/
    1086          25 :         if (!gf_sk_is_multicast_address(multi_IPAdd)) return GF_BAD_PARAM;
    1087             : 
    1088             : 
    1089             : #ifdef GPAC_HAS_IPV6
    1090          25 :         is_ipv6 = gf_net_is_ipv6(multi_IPAdd) || gf_net_is_ipv6(local_interface_ip) ? GF_TRUE : GF_FALSE;
    1091          25 :         type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
    1092             : 
    1093          25 :         if (is_ipv6) {
    1094             : 
    1095           0 :                 res = gf_sk_get_ipv6_addr(local_interface_ip, MultiPortNumber, AF_UNSPEC, AI_PASSIVE, type);
    1096           0 :                 if (!res) {
    1097           0 :                         if (local_interface_ip) {
    1098           0 :                                 res = gf_sk_get_ipv6_addr(NULL, MultiPortNumber, AF_UNSPEC, AI_PASSIVE, type);
    1099             :                                 local_interface_ip = NULL;
    1100             :                         }
    1101           0 :                         if (!res) return GF_IP_CONNECTION_FAILURE;
    1102             :                 }
    1103             : 
    1104             :                 /*for all interfaces*/
    1105           0 :                 for (aip=res; aip!=NULL; aip=aip->ai_next) {
    1106           0 :                         if (type != (u32) aip->ai_socktype) continue;
    1107           0 :                         sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
    1108           0 :                         if (sock->socket == INVALID_SOCKET) {
    1109           0 :                                 sock->socket = NULL_SOCKET;
    1110           0 :                                 continue;
    1111             :                         }
    1112             : 
    1113           0 :                         if ((aip->ai_family!=PF_INET) && aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(multi_IPAdd)) continue;
    1114             : 
    1115             :                         /*enable address reuse*/
    1116           0 :                         optval = 1;
    1117           0 :                         setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
    1118             : #ifdef SO_REUSEPORT
    1119           0 :                         optval = 1;
    1120           0 :                         setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
    1121             : #endif
    1122             : 
    1123             :                         /*TODO: copy over other properties (recption buffer size & co)*/
    1124           0 :                         if (sock->flags & GF_SOCK_NON_BLOCKING)
    1125           0 :                                 gf_sk_set_block_mode(sock, GF_TRUE);
    1126             : 
    1127           0 :                         memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
    1128           0 :                         sock->dest_addr_len = (u32) aip->ai_addrlen;
    1129             : 
    1130           0 :                         if (!NoBind) {
    1131           0 :                                 ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
    1132           0 :                                 if (ret == SOCKET_ERROR) {
    1133           0 :                                         closesocket(sock->socket);
    1134           0 :                                         sock->socket = NULL_SOCKET;
    1135           0 :                                         continue;
    1136             :                                 }
    1137             :                         }
    1138           0 :                         if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
    1139           0 :                         else sock->flags &= ~GF_SOCK_IS_IPV6;
    1140             :                         break;
    1141             :                 }
    1142           0 :                 freeaddrinfo(res);
    1143           0 :                 if (!sock->socket) return GF_IP_CONNECTION_FAILURE;
    1144             : 
    1145           0 :                 struct addrinfo *_res = gf_sk_get_ipv6_addr(multi_IPAdd, MultiPortNumber, AF_UNSPEC, 0, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM);
    1146           0 :                 if (!_res) return GF_IP_CONNECTION_FAILURE;
    1147           0 :                 memcpy(&sock->dest_addr, _res->ai_addr, res->ai_addrlen);
    1148           0 :                 sock->dest_addr_len = (u32) _res->ai_addrlen;
    1149           0 :                 freeaddrinfo(_res);
    1150             : 
    1151             :                 addr = (struct sockaddr *)&sock->dest_addr;
    1152           0 :                 if (addr->sa_family == AF_INET) {
    1153           0 :                         M_req.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
    1154           0 :                         M_req.imr_interface.s_addr = INADDR_ANY;
    1155           0 :                         ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &M_req, sizeof(M_req));
    1156           0 :                         if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1157             :                         /*set TTL*/
    1158           0 :                         ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &TTL, sizeof(TTL));
    1159           0 :                         if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1160             :                         /*Disable loopback*/
    1161           0 :                         flag = 1;
    1162           0 :                         ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
    1163           0 :                         if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1164             :                 }
    1165             : 
    1166           0 :                 if (addr->sa_family == AF_INET6) {
    1167             :                         struct ipv6_mreq M_reqV6;
    1168             : 
    1169             :                         memcpy(&M_reqV6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
    1170           0 :                         M_reqV6.ipv6mr_interface = 0;
    1171             : 
    1172             :                         /*set TTL*/
    1173           0 :                         ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &TTL, sizeof(TTL));
    1174           0 :                         if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1175             :                         /*enable loopback*/
    1176           0 :                         flag = 1;
    1177           0 :                         ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
    1178           0 :                         if (ret == SOCKET_ERROR) {
    1179           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Cannot disale multicast loop: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1180             :                         }
    1181             : 
    1182           0 :                         ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &M_reqV6, sizeof(M_reqV6));
    1183           0 :                         if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1184             :                 }
    1185           0 :                 sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
    1186           0 :                 return GF_OK;
    1187             :         }
    1188             : #endif
    1189             : 
    1190             :         //IPv4 setup
    1191          25 :         sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
    1192          25 :         if (sock->flags & GF_SOCK_NON_BLOCKING)
    1193           0 :                 gf_sk_set_block_mode(sock, GF_TRUE);
    1194          25 :         sock->flags &= ~GF_SOCK_IS_IPV6;
    1195             : 
    1196             :         /*enable address reuse*/
    1197          25 :         optval = 1;
    1198          25 :         ret = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
    1199          25 :         if (ret == SOCKET_ERROR) {
    1200           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] Failed to set SO_REUSEADDR: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1201             :         }
    1202             : #ifdef SO_REUSEPORT
    1203          25 :         optval = 1;
    1204          25 :         ret = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
    1205          25 :         if (ret == SOCKET_ERROR) {
    1206           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] Failed to set SO_REUSEPORT: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1207             :         }
    1208             : #endif
    1209             : 
    1210          25 :         if (local_interface_ip) local_add_id = inet_addr(local_interface_ip);
    1211          25 :         else local_add_id = htonl(INADDR_ANY);
    1212             : 
    1213          25 :         if (!NoBind) {
    1214             :                 struct sockaddr_in local_address;
    1215             : 
    1216             :                 memset(&local_address, 0, sizeof(struct sockaddr_in ));
    1217          24 :                 local_address.sin_family = AF_INET;
    1218             : //              local_address.sin_addr.s_addr = local_add_id;
    1219             :                 local_address.sin_addr.s_addr = htonl(INADDR_ANY);
    1220          24 :                 local_address.sin_port = htons( MultiPortNumber);
    1221             : 
    1222          24 :                 ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
    1223          24 :                 if (ret == SOCKET_ERROR) {
    1224             :                         /*retry without specifying the local add*/
    1225           0 :                         local_address.sin_addr.s_addr = local_add_id = htonl(INADDR_ANY);
    1226             :                         local_interface_ip = NULL;
    1227           0 :                         ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
    1228           0 :                         if (ret == SOCKET_ERROR) {
    1229           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[core] Failed to bind socket: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1230           0 :                                 return GF_IP_CONNECTION_FAILURE;
    1231             :                         }
    1232             :                 }
    1233             :                 /*setup local interface*/
    1234          24 :                 if (local_interface_ip) {
    1235           0 :                         ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_IF, (void *) &local_add_id, sizeof(local_add_id));
    1236           0 :                         if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1237             :                 }
    1238             :         }
    1239             : 
    1240             :         /*now join the multicast*/
    1241          25 :         M_req.imr_multiaddr.s_addr = inet_addr(multi_IPAdd);
    1242          25 :         M_req.imr_interface.s_addr = local_add_id;
    1243             : 
    1244          25 :         ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &M_req, sizeof(M_req));
    1245          25 :         if (ret == SOCKET_ERROR) {
    1246           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot join multicast: %s\n", gf_errno_str(LASTSOCKERROR)));
    1247             :                 return GF_IP_CONNECTION_FAILURE;
    1248             :         }
    1249             :         /*set the Time To Live*/
    1250          25 :         if (TTL) {
    1251           8 :                 ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTL, sizeof(TTL));
    1252           8 :                 if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
    1253             :         }
    1254             : 
    1255             :         /*enable loopback*/
    1256          25 :         flag = 1;
    1257          25 :         ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
    1258          25 :         if (ret == SOCKET_ERROR) {
    1259           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[Socket] Cannot disable multicast loop: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1260             :         }
    1261             : 
    1262             : #ifdef GPAC_HAS_IPV6
    1263          25 :         ((struct sockaddr_in *) &sock->dest_addr)->sin_family = AF_INET;
    1264          25 :         ((struct sockaddr_in *) &sock->dest_addr)->sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
    1265          25 :         ((struct sockaddr_in *) &sock->dest_addr)->sin_port = htons( MultiPortNumber);
    1266          25 :         sock->dest_addr_len = sizeof(struct sockaddr);
    1267             : #else
    1268             :         sock->dest_addr.sin_family = AF_INET;
    1269             :         sock->dest_addr.sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
    1270             :         sock->dest_addr.sin_port = htons( MultiPortNumber);
    1271             : #endif
    1272             : 
    1273          25 :         sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
    1274          25 :         return GF_OK;
    1275             : }
    1276             : 
    1277             : #include <gpac/list.h>
    1278             : struct __tag_sock_group
    1279             : {
    1280             :         GF_List *sockets;
    1281             :         fd_set rgroup, wgroup;
    1282             : };
    1283             : 
    1284          64 : GF_SockGroup *gf_sk_group_new()
    1285             : {
    1286             :         GF_SockGroup *tmp;
    1287          64 :         GF_SAFEALLOC(tmp, GF_SockGroup);
    1288          64 :         if (!tmp) return NULL;
    1289          64 :         tmp->sockets = gf_list_new();
    1290          64 :         FD_ZERO(&tmp->rgroup);
    1291          64 :         FD_ZERO(&tmp->wgroup);
    1292          64 :         return tmp;
    1293             : }
    1294             : 
    1295          64 : void gf_sk_group_del(GF_SockGroup *sg)
    1296             : {
    1297          64 :         gf_list_del(sg->sockets);
    1298          64 :         gf_free(sg);
    1299          64 : }
    1300             : 
    1301         128 : void gf_sk_group_register(GF_SockGroup *sg, GF_Socket *sk)
    1302             : {
    1303         128 :         if (sg && sk) {
    1304         128 :                 if (gf_list_find(sg->sockets, sk)<0)
    1305         128 :                         gf_list_add(sg->sockets, sk);
    1306             :         }
    1307         128 : }
    1308          91 : void gf_sk_group_unregister(GF_SockGroup *sg, GF_Socket *sk)
    1309             : {
    1310          91 :         if (sg && sk) {
    1311          91 :                 gf_list_del_item(sg->sockets, sk);
    1312             :         }
    1313          91 : }
    1314             : 
    1315     6300756 : GF_Err gf_sk_group_select(GF_SockGroup *sg, u32 usec_wait, GF_SockSelectMode mode)
    1316             : {
    1317             :         s32 ready;
    1318     6300756 :         u32 i=0;
    1319             :         struct timeval timeout;
    1320             :         u32 max_fd=0;
    1321             :         GF_Socket *sock;
    1322             :         fd_set *rgroup=NULL, *wgroup=NULL;
    1323             : 
    1324     6300756 :         if (!gf_list_count(sg->sockets))
    1325             :                 return GF_IP_NETWORK_EMPTY;
    1326             : 
    1327     5794158 :         FD_ZERO(&sg->rgroup);
    1328     5794158 :         FD_ZERO(&sg->wgroup);
    1329             : 
    1330     5794158 :         switch (mode) {
    1331     5734943 :         case GF_SK_SELECT_BOTH:
    1332     5734943 :                 rgroup = &sg->rgroup;
    1333     5734943 :                 wgroup = &sg->wgroup;
    1334     5734943 :                 break;
    1335       59215 :         case GF_SK_SELECT_READ:
    1336       59215 :                 rgroup = &sg->rgroup;
    1337       59215 :                 break;
    1338           0 :         case GF_SK_SELECT_WRITE:
    1339           0 :                 wgroup = &sg->wgroup;
    1340           0 :                 break;
    1341             :         }
    1342    17465644 :         while ((sock = gf_list_enum(sg->sockets, &i))) {
    1343    11671486 :                 if (rgroup)
    1344    11671486 :                         FD_SET(sock->socket, rgroup);
    1345             : 
    1346    11671486 :                 if (wgroup)
    1347    11594390 :                         FD_SET(sock->socket, wgroup);
    1348             : 
    1349    11671486 :                 if (max_fd < (u32) sock->socket) max_fd = (u32) sock->socket;
    1350             :         }
    1351     5794158 :         if (usec_wait>=1000000) {
    1352           0 :                 timeout.tv_sec = usec_wait/1000000;
    1353           0 :                 timeout.tv_usec = (u32) (usec_wait - (timeout.tv_sec*1000000));
    1354             :         } else {
    1355     5794158 :                 timeout.tv_sec = 0;
    1356     5794158 :                 timeout.tv_usec = usec_wait;
    1357             :         }
    1358     5794158 :         ready = select((int) max_fd+1, rgroup, wgroup, NULL, &timeout);
    1359             : 
    1360     5794158 :         if (ready == SOCKET_ERROR) {
    1361           0 :                 switch (LASTSOCKERROR) {
    1362           0 :                 case EBADF:
    1363           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot select, BAD descriptor\n"));
    1364             :                         return GF_IP_CONNECTION_CLOSED;
    1365             :                 case EAGAIN:
    1366             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1367           0 :                 case EINTR:
    1368             :                         /* Interrupted system call, not really important... */
    1369           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] network is lost\n"));
    1370             :                         return GF_IP_NETWORK_EMPTY;
    1371           0 :                 default:
    1372           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot select: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1373             :                         return GF_IP_NETWORK_FAILURE;
    1374             :                 }
    1375             :         }
    1376     5794158 :         if (!ready) {
    1377       59187 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] nothing to be read - ready %d\n", ready));
    1378             :                 return GF_IP_NETWORK_EMPTY;
    1379             :         }
    1380             :         return GF_OK;
    1381             : }
    1382             : 
    1383    11593010 : Bool gf_sk_group_sock_is_set(GF_SockGroup *sg, GF_Socket *sk, GF_SockSelectMode mode)
    1384             : {
    1385    11593010 :         if (sg && sk) {
    1386    11593010 :                 if ((mode!=GF_SK_SELECT_WRITE) && FD_ISSET(sk->socket, &sg->rgroup))
    1387             :                         return GF_TRUE;
    1388    11590088 :                 if ((mode!=GF_SK_SELECT_READ) && FD_ISSET(sk->socket, &sg->wgroup))
    1389             :                         return GF_TRUE;
    1390             :         }
    1391             :         return GF_FALSE;
    1392             : }
    1393             : 
    1394             : 
    1395             : //fetch nb bytes on a socket and fill the buffer from startFrom
    1396             : //length is the allocated size of the receiving buffer
    1397             : //BytesRead is the number of bytes read from the network
    1398      152872 : GF_Err gf_sk_receive_internal(GF_Socket *sock, char *buffer, u32 length, u32 *BytesRead, Bool do_select)
    1399             : {
    1400             :         s32 res;
    1401             : #ifndef __SYMBIAN32__
    1402             :         s32 ready;
    1403             :         struct timeval timeout;
    1404             :         fd_set Group;
    1405             : #endif
    1406             : 
    1407      152872 :         if (BytesRead) *BytesRead = 0;
    1408      152872 :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1409             : 
    1410             : #ifndef __SYMBIAN32__
    1411      152872 :         if (do_select) {
    1412             :                 //can we read?
    1413      151035 :                 timeout.tv_sec = 0;
    1414      151035 :                 timeout.tv_usec = sock->usec_wait;
    1415      151035 :                 FD_ZERO(&Group);
    1416      151035 :                 FD_SET(sock->socket, &Group);
    1417      151035 :                 ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
    1418             : 
    1419      151035 :                 if (ready == SOCKET_ERROR) {
    1420           0 :                         switch (LASTSOCKERROR) {
    1421           0 :                         case EBADF:
    1422           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot select, BAD descriptor\n"));
    1423             :                                 return GF_IP_CONNECTION_CLOSED;
    1424             :                         case EAGAIN:
    1425             :                                 return GF_IP_SOCK_WOULD_BLOCK;
    1426           0 :                         case EINTR:
    1427             :                                 /* Interrupted system call, not really important... */
    1428           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] network is lost\n"));
    1429             :                                 return GF_IP_NETWORK_EMPTY;
    1430           0 :                         default:
    1431           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] cannot select: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1432             :                                 return GF_IP_NETWORK_FAILURE;
    1433             :                         }
    1434             :                 }
    1435      151035 :                 if (!ready || !FD_ISSET(sock->socket, &Group)) {
    1436      141025 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] nothing to be read - ready %d\n", ready));
    1437             :                         return GF_IP_NETWORK_EMPTY;
    1438             :                 }
    1439             :         }
    1440             : #endif
    1441       11847 :         if (!buffer) return GF_OK;
    1442             : 
    1443        9521 :         if (sock->flags & GF_SOCK_HAS_PEER)
    1444        4652 :                 res = (s32) recvfrom(sock->socket, (char *) buffer, length, 0, (struct sockaddr *)&sock->dest_addr, &sock->dest_addr_len);
    1445             :         else {
    1446       14390 :                 res = (s32) recv(sock->socket, (char *) buffer, length, 0);
    1447        7195 :                 if (!do_select && (res == 0))
    1448             :                         return GF_IP_CONNECTION_CLOSED;
    1449             :         }
    1450             : 
    1451        9515 :         if (res == SOCKET_ERROR) {
    1452           0 :                 res = LASTSOCKERROR;
    1453           0 :                 switch (res) {
    1454             :                 case EAGAIN:
    1455             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1456             : #ifndef __SYMBIAN32__
    1457           0 :                 case EMSGSIZE:
    1458           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] error reading: %s\n", gf_errno_str(LASTSOCKERROR)));
    1459             :                         return GF_OUT_OF_MEM;
    1460           0 :                 case ENOTCONN:
    1461             :                 case ECONNRESET:
    1462             :                 case ECONNABORTED:
    1463           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] error reading: %s\n", gf_errno_str(LASTSOCKERROR)));
    1464             :                         return GF_IP_CONNECTION_CLOSED;
    1465             : #endif
    1466           0 :                 default:
    1467           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] error reading: %s\n", gf_errno_str(LASTSOCKERROR) ));
    1468             :                         return GF_IP_NETWORK_FAILURE;
    1469             :                 }
    1470             :         }
    1471        9515 :         if (!res) return GF_IP_NETWORK_EMPTY;
    1472        9476 :         if (BytesRead)
    1473        9476 :                 *BytesRead = res;
    1474             :         return GF_OK;
    1475             : }
    1476             : 
    1477             : GF_EXPORT
    1478      151035 : GF_Err gf_sk_receive(GF_Socket *sock, u8 *buffer, u32 length, u32 *BytesRead)
    1479             : {
    1480      151035 :         return gf_sk_receive_internal(sock, buffer, length, BytesRead, GF_TRUE);
    1481             : }
    1482             : 
    1483             : GF_EXPORT
    1484        1837 : GF_Err gf_sk_receive_no_select(GF_Socket *sock, u8 *buffer, u32 length, u32 *BytesRead)
    1485             : {
    1486        1837 :         return gf_sk_receive_internal(sock, buffer, length, BytesRead, GF_FALSE);
    1487             : }
    1488             : 
    1489             : GF_EXPORT
    1490          34 : GF_Err gf_sk_listen(GF_Socket *sock, u32 MaxConnection)
    1491             : {
    1492             :         s32 i;
    1493          34 :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1494          34 :         if (MaxConnection >= SOMAXCONN) MaxConnection = SOMAXCONN;
    1495          34 :         i = listen(sock->socket, MaxConnection);
    1496          34 :         if (i == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
    1497          34 :         sock->flags |= GF_SOCK_IS_LISTENING;
    1498          34 :         return GF_OK;
    1499             : }
    1500             : 
    1501             : GF_EXPORT
    1502        3789 : GF_Err gf_sk_accept(GF_Socket *sock, GF_Socket **newConnection)
    1503             : {
    1504             :         u32 client_address_size;
    1505             :         SOCKET sk;
    1506             : #ifndef __SYMBIAN32__
    1507             :         s32 ready;
    1508             :         struct timeval timeout;
    1509             :         fd_set Group;
    1510             : #endif
    1511        3789 :         *newConnection = NULL;
    1512        3789 :         if (!sock || !(sock->flags & GF_SOCK_IS_LISTENING) ) return GF_BAD_PARAM;
    1513             : 
    1514             : #ifndef __SYMBIAN32__
    1515             :         //can we read?
    1516        3789 :         FD_ZERO(&Group);
    1517        3789 :         FD_SET(sock->socket, &Group);
    1518        3789 :         timeout.tv_sec = 0;
    1519        3789 :         timeout.tv_usec = sock->usec_wait;
    1520             : 
    1521             :         //TODO - check if this is correct
    1522        3789 :         ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
    1523        3789 :         if (ready == SOCKET_ERROR) {
    1524           0 :                 switch (LASTSOCKERROR) {
    1525             :                 case EAGAIN:
    1526             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1527           0 :                 default:
    1528           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] select error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1529             :                         return GF_IP_NETWORK_FAILURE;
    1530             :                 }
    1531             :         }
    1532        3789 :         if (!ready || !FD_ISSET(sock->socket, &Group)) return GF_IP_NETWORK_EMPTY;
    1533             : #endif
    1534             : 
    1535             : #ifdef GPAC_HAS_IPV6
    1536          78 :         client_address_size = sizeof(struct sockaddr_in6);
    1537             : #else
    1538             :         client_address_size = sizeof(struct sockaddr_in);
    1539             : #endif
    1540          78 :         sk = accept(sock->socket, (struct sockaddr *) &sock->dest_addr, &client_address_size);
    1541             : 
    1542             :         //we either have an error or we have no connections
    1543          78 :         if (sk == INVALID_SOCKET) {
    1544             : //              if (sock->flags & GF_SOCK_NON_BLOCKING) return GF_IP_NETWORK_FAILURE;
    1545           0 :                 switch (LASTSOCKERROR) {
    1546             :                 case EAGAIN:
    1547             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1548           0 :                 default:
    1549           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] accept error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1550             :                         return GF_IP_NETWORK_FAILURE;
    1551             :                 }
    1552             :         }
    1553             : 
    1554          78 :         (*newConnection) = (GF_Socket *) gf_malloc(sizeof(GF_Socket));
    1555          78 :         (*newConnection)->socket = sk;
    1556          78 :         (*newConnection)->flags = sock->flags & ~GF_SOCK_IS_LISTENING;
    1557          78 :         (*newConnection)->usec_wait = sock->usec_wait;
    1558             : #ifdef GPAC_HAS_IPV6
    1559          78 :         memcpy( &(*newConnection)->dest_addr, &sock->dest_addr, client_address_size);
    1560             :         memset(&sock->dest_addr, 0, sizeof(struct sockaddr_in6));
    1561             : #else
    1562             :         memcpy( &(*newConnection)->dest_addr, &sock->dest_addr, client_address_size);
    1563             :         memset(&sock->dest_addr, 0, sizeof(struct sockaddr_in));
    1564             : #endif
    1565             : 
    1566             : #ifdef SO_NOSIGPIPE
    1567             :         int value = 1;
    1568             :         setsockopt((*newConnection)->socket, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
    1569             : #endif
    1570             : 
    1571             : #if defined(WIN32) || defined(_WIN32_WCE)
    1572             :         wsa_init++;
    1573             : #endif
    1574             : 
    1575          78 :         (*newConnection)->dest_addr_len = client_address_size;
    1576          78 :         return GF_OK;
    1577             : }
    1578             : 
    1579             : GF_EXPORT
    1580          26 : GF_Err gf_sk_get_local_info(GF_Socket *sock, u16 *Port, u32 *Familly)
    1581             : {
    1582             : #ifdef GPAC_HAS_IPV6
    1583             :         struct sockaddr_in6 the_add;
    1584             : #else
    1585             :         struct sockaddr_in the_add;
    1586             : #endif
    1587             :         u32 size;
    1588             : 
    1589          26 :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1590             : 
    1591          25 :         if (Port) {
    1592             : #ifdef GPAC_HAS_IPV6
    1593          25 :                 size = sizeof(struct sockaddr_in6);
    1594          25 :                 if (getsockname(sock->socket, (struct sockaddr *) &the_add, &size) == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
    1595          25 :                 *Port = (u32) ntohs(the_add.sin6_port);
    1596             : #else
    1597             :                 size = sizeof(struct sockaddr_in);
    1598             :                 if (getsockname(sock->socket, (struct sockaddr *) &the_add, &size) == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
    1599             :                 *Port = (u32) ntohs(the_add.sin_port);
    1600             : #endif
    1601             :         }
    1602          25 :         if (Familly) {
    1603             :                 /*              size = 4;
    1604             :                                 if (getsockopt(sock->socket, SOL_SOCKET, SO_TYPE, (char *) &fam, &size) == SOCKET_ERROR)
    1605             :                                         return GF_IP_NETWORK_FAILURE;
    1606             :                                 *Familly = fam;
    1607             :                 */
    1608          25 :                 if (sock->flags & GF_SOCK_IS_TCP) *Familly = GF_SOCK_TYPE_TCP;
    1609           0 :                 else  *Familly = GF_SOCK_TYPE_UDP;
    1610             :         }
    1611             :         return GF_OK;
    1612             : }
    1613             : 
    1614             : //we have to do this for the server sockets as we use only one thread
    1615             : GF_EXPORT
    1616          59 : GF_Err gf_sk_server_mode(GF_Socket *sock, Bool serverOn)
    1617             : {
    1618             :         u32 one;
    1619             : 
    1620          59 :         if (!sock || !(sock->flags & GF_SOCK_IS_TCP) || !sock->socket)
    1621             :                 return GF_BAD_PARAM;
    1622             : 
    1623          59 :         one = serverOn ? 1 : 0;
    1624          59 :         setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, SSO_CAST &one, sizeof(u32));
    1625             : #ifndef __SYMBIAN32__
    1626          59 :         setsockopt(sock->socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(u32));
    1627             : #endif
    1628          59 :         return GF_OK;
    1629             : }
    1630             : 
    1631             : GF_EXPORT
    1632          78 : GF_Err gf_sk_get_remote_address(GF_Socket *sock, char *buf)
    1633             : {
    1634             : #ifdef GPAC_HAS_IPV6
    1635             :         char clienthost[NI_MAXHOST];
    1636             :         char servname[NI_MAXHOST];
    1637          78 :         struct sockaddr_in6 * addrptr = (struct sockaddr_in6 *)(&sock->dest_addr);
    1638          78 :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1639          78 :         inet_ntop(AF_INET, addrptr, clienthost, NI_MAXHOST);
    1640             :         strcpy(buf, clienthost);
    1641          78 :         if (getnameinfo((struct sockaddr *)addrptr, sock->dest_addr_len, clienthost, NI_MAXHOST, servname, NI_MAXHOST, NI_NUMERICHOST) == 0) {
    1642             :                 strcpy(buf, clienthost);
    1643             :         }
    1644             : #else
    1645             :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1646             :         strcpy(buf, inet_ntoa(sock->dest_addr.sin_addr));
    1647             : #endif
    1648             :         return GF_OK;
    1649             : }
    1650             : 
    1651             : 
    1652             : 
    1653             : #if 0 //unused
    1654             : 
    1655             : //send length bytes of a buffer
    1656             : GF_Err gf_sk_send_to(GF_Socket *sock, const char *buffer, u32 length, char *remoteHost, u16 remotePort)
    1657             : {
    1658             :         u32 count, remote_add_len;
    1659             :         s32 res;
    1660             : #ifdef GPAC_HAS_IPV6
    1661             :         struct sockaddr_storage remote_add;
    1662             : #else
    1663             :         struct sockaddr_in remote_add;
    1664             :         struct hostent *Host;
    1665             : #endif
    1666             : #ifndef __SYMBIAN32__
    1667             :         s32 ready;
    1668             :         struct timeval timeout;
    1669             :         fd_set Group;
    1670             : #endif
    1671             : 
    1672             :         //the socket must be bound or connected
    1673             :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1674             :         if (remoteHost && !remotePort) return GF_BAD_PARAM;
    1675             : 
    1676             : #ifndef __SYMBIAN32__
    1677             :         //can we write?
    1678             :         FD_ZERO(&Group);
    1679             :         FD_SET(sock->socket, &Group);
    1680             :         timeout.tv_sec = 0;
    1681             :         timeout.tv_usec = sock->usec_wait;
    1682             : 
    1683             :         //TODO - check if this is correct
    1684             :         ready = select((int) sock->socket+1, NULL, &Group, NULL, &timeout);
    1685             :         if (ready == SOCKET_ERROR) {
    1686             :                 switch (LASTSOCKERROR) {
    1687             :                 case EAGAIN:
    1688             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1689             :                 default:
    1690             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] select error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1691             :                         return GF_IP_NETWORK_FAILURE;
    1692             :                 }
    1693             :         }
    1694             :         if (!ready || !FD_ISSET(sock->socket, &Group)) return GF_IP_NETWORK_EMPTY;
    1695             : #endif
    1696             : 
    1697             : 
    1698             :         /*setup the address*/
    1699             : #ifdef GPAC_HAS_IPV6
    1700             :         remote_add.ss_family = AF_INET6;
    1701             :         //if a remote host is specified, use it. Otherwise use the default host
    1702             :         if (remoteHost) {
    1703             :                 //setup the address
    1704             :                 struct addrinfo *res = gf_sk_get_ipv6_addr(remoteHost, remotePort, AF_UNSPEC, 0, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM);
    1705             :                 if (!res) return GF_IP_ADDRESS_NOT_FOUND;
    1706             :                 memcpy(&remote_add, res->ai_addr, res->ai_addrlen);
    1707             :                 remote_add_len = (u32) res->ai_addrlen;
    1708             :                 freeaddrinfo(res);
    1709             :         } else {
    1710             :                 struct sockaddr_in6 *remotePtr = (struct sockaddr_in6 *)&remote_add;
    1711             :                 struct sockaddr_in6 * addrptr = (struct sockaddr_in6 *)(&sock->dest_addr);
    1712             :                 remotePtr->sin6_port = addrptr->sin6_port;
    1713             :                 remotePtr->sin6_addr = addrptr->sin6_addr;
    1714             :                 remote_add_len = sock->dest_addr_len;
    1715             :         }
    1716             : #else
    1717             :         remote_add_len = sizeof(struct sockaddr_in);
    1718             :         remote_add.sin_family = AF_INET;
    1719             :         //if a remote host is specified, use it. Otherwise use the default host
    1720             :         if (remoteHost) {
    1721             :                 //setup the address
    1722             :                 remote_add.sin_port = htons(remotePort);
    1723             :                 //get the server IP
    1724             :                 Host = gf_gethostbyname(remoteHost);
    1725             :                 if (Host == NULL) return GF_IP_ADDRESS_NOT_FOUND;
    1726             :                 memcpy((char *) &remote_add.sin_addr, Host->h_addr_list[0], sizeof(u32));
    1727             :         } else {
    1728             :                 remote_add.sin_port = sock->dest_addr.sin_port;
    1729             :                 remote_add.sin_addr.s_addr = sock->dest_addr.sin_addr.s_addr;
    1730             :         }
    1731             : #endif
    1732             :         count = 0;
    1733             :         while (count < length) {
    1734             :                 res = (s32) sendto(sock->socket, (char *) buffer+count, length - count, 0, (struct sockaddr *) &remote_add, remote_add_len);
    1735             :                 if (res == SOCKET_ERROR) {
    1736             :                         switch (LASTSOCKERROR) {
    1737             :                         case EAGAIN:
    1738             :                                 return GF_IP_SOCK_WOULD_BLOCK;
    1739             :                         default:
    1740             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] sendto error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1741             :                                 return GF_IP_NETWORK_FAILURE;
    1742             :                         }
    1743             :                 }
    1744             :                 count += res;
    1745             :         }
    1746             :         return GF_OK;
    1747             : }
    1748             : #endif
    1749             : 
    1750             : GF_EXPORT
    1751      135216 : GF_Err gf_sk_probe(GF_Socket *sock)
    1752             : {
    1753             : #ifndef __SYMBIAN32__
    1754             :         s32 ready;
    1755             :         struct timeval timeout;
    1756             :         fd_set Group;
    1757             : #endif
    1758             :         s32 res;
    1759             :         u8 buffer[1];
    1760      135216 :         if (!sock) return GF_BAD_PARAM;
    1761             : 
    1762             : #ifndef __SYMBIAN32__
    1763             :         //can we read?
    1764      135216 :         FD_ZERO(&Group);
    1765      135216 :         FD_SET(sock->socket, &Group);
    1766      135216 :         timeout.tv_sec = 0;
    1767      135216 :         timeout.tv_usec = 100;
    1768             : 
    1769      135216 :         ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
    1770      135216 :         if (ready == SOCKET_ERROR) {
    1771           0 :                 switch (LASTSOCKERROR) {
    1772             :                 case EAGAIN:
    1773             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1774           0 :                 default:
    1775           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] select error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1776             :                         return GF_IP_CONNECTION_CLOSED;
    1777             :                 }
    1778             :         }
    1779      135216 :         if (!FD_ISSET(sock->socket, &Group)) {
    1780             :                 return GF_IP_NETWORK_EMPTY;
    1781             :         }
    1782             : #endif
    1783         270 :         res = (s32) recv(sock->socket, buffer, 1, MSG_PEEK);
    1784         270 :         if (res > 0) return GF_OK;
    1785             : #if 0
    1786             :         res = LASTSOCKERROR;
    1787             :         switch (res) {
    1788             :         case 0:
    1789             :         case EAGAIN:
    1790             :                 return GF_IP_NETWORK_EMPTY;
    1791             :         default:
    1792             :                 GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[socket] probe error: %s\n", gf_errno_str(res)));
    1793             :                 return GF_IP_CONNECTION_CLOSED;
    1794             :         }
    1795             : #else
    1796          39 :         return GF_IP_CONNECTION_CLOSED;
    1797             : #endif
    1798             : 
    1799             :         return GF_OK;
    1800             : }
    1801             : 
    1802             : GF_EXPORT
    1803           1 : GF_Err gf_sk_receive_wait(GF_Socket *sock, u8 *buffer, u32 length, u32 *BytesRead, u32 Second )
    1804             : {
    1805             :         s32 res;
    1806             : #ifndef __SYMBIAN32__
    1807             :         s32 ready;
    1808             :         struct timeval timeout;
    1809             :         fd_set Group;
    1810             : #endif
    1811             : 
    1812           1 :         if (!sock || !sock->socket || !buffer || !BytesRead) return GF_BAD_PARAM;
    1813           0 :         *BytesRead = 0;
    1814             : 
    1815             : #ifndef __SYMBIAN32__
    1816             :         //can we read?
    1817           0 :         FD_ZERO(&Group);
    1818           0 :         FD_SET(sock->socket, &Group);
    1819           0 :         timeout.tv_sec = Second;
    1820           0 :         timeout.tv_usec = sock->usec_wait;
    1821             : 
    1822           0 :         ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
    1823           0 :         if (ready == SOCKET_ERROR) {
    1824           0 :                 switch (LASTSOCKERROR) {
    1825             :                 case EAGAIN:
    1826             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1827           0 :                 default:
    1828           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] select error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1829             :                         return GF_IP_NETWORK_FAILURE;
    1830             :                 }
    1831             :         }
    1832           0 :         if (!FD_ISSET(sock->socket, &Group)) {
    1833             :                 return GF_IP_NETWORK_EMPTY;
    1834             :         }
    1835             : #endif
    1836             : 
    1837           0 :         res = (s32) recv(sock->socket, (char *) buffer, length, 0);
    1838           0 :         if (res == SOCKET_ERROR) {
    1839           0 :                 switch (LASTSOCKERROR) {
    1840             :                 case EAGAIN:
    1841             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1842           0 :                 default:
    1843           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] recv error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1844             :                         return GF_IP_NETWORK_FAILURE;
    1845             :                 }
    1846             :         }
    1847           0 :         *BytesRead = res;
    1848           0 :         return GF_OK;
    1849             : }
    1850             : 
    1851             : 
    1852             : //send length bytes of a buffer
    1853             : GF_EXPORT
    1854          29 : GF_Err gf_sk_send_wait(GF_Socket *sock, const u8 *buffer, u32 length, u32 Second )
    1855             : {
    1856             :         u32 count;
    1857             :         s32 res;
    1858             : #ifndef __SYMBIAN32__
    1859             :         s32 ready;
    1860             :         struct timeval timeout;
    1861             :         fd_set Group;
    1862             : #endif
    1863             : 
    1864             :         //the socket must be bound or connected
    1865          29 :         if (!sock || !sock->socket) return GF_BAD_PARAM;
    1866             : 
    1867             : #ifndef __SYMBIAN32__
    1868             :         //can we write?
    1869          28 :         FD_ZERO(&Group);
    1870          28 :         FD_SET(sock->socket, &Group);
    1871          28 :         timeout.tv_sec = Second;
    1872          28 :         timeout.tv_usec = sock->usec_wait;
    1873             : 
    1874             :         //TODO - check if this is correct
    1875          28 :         ready = select((int) sock->socket+1, NULL, &Group, NULL, &timeout);
    1876          28 :         if (ready == SOCKET_ERROR) {
    1877           0 :                 switch (LASTSOCKERROR) {
    1878             :                 case EAGAIN:
    1879             :                         return GF_IP_SOCK_WOULD_BLOCK;
    1880           0 :                 default:
    1881           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] select error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1882             :                         return GF_IP_NETWORK_FAILURE;
    1883             :                 }
    1884             :         }
    1885             :         //should never happen (to check: is writeability is guaranteed for not-connected sockets)
    1886          28 :         if (!ready || !FD_ISSET(sock->socket, &Group)) {
    1887             :                 return GF_IP_NETWORK_EMPTY;
    1888             :         }
    1889             : #endif
    1890             : 
    1891             :         //direct writing
    1892             :         count = 0;
    1893          56 :         while (count < length) {
    1894          28 :                 res = (s32) send(sock->socket, (char *) buffer+count, length - count, 0);
    1895          28 :                 if (res == SOCKET_ERROR) {
    1896           0 :                         switch (LASTSOCKERROR) {
    1897             :                         case EAGAIN:
    1898             :                                 return GF_IP_SOCK_WOULD_BLOCK;
    1899             : #ifndef __SYMBIAN32__
    1900           0 :                         case ECONNRESET:
    1901           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] send error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1902             :                                 return GF_IP_CONNECTION_CLOSED;
    1903             : #endif
    1904           0 :                         default:
    1905           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] send error: %s\n", gf_errno_str(LASTSOCKERROR)));
    1906             :                                 return GF_IP_NETWORK_FAILURE;
    1907             :                         }
    1908             :                 }
    1909          28 :                 count += res;
    1910             :         }
    1911             :         return GF_OK;
    1912             : }
    1913             : 
    1914             : GF_EXPORT
    1915          11 : u32 gf_htonl(u32 val)
    1916             : {
    1917          11 :         return htonl(val);
    1918             : }
    1919             : 
    1920             : 
    1921             : GF_EXPORT
    1922           2 : u32 gf_ntohl(u32 val)
    1923             : {
    1924           2 :         return ntohl(val);
    1925             : }
    1926             : 
    1927             : GF_EXPORT
    1928           2 : u16 gf_htons(u16 val)
    1929             : {
    1930           2 :         return htons(val);
    1931             : }
    1932             : 
    1933             : 
    1934             : GF_EXPORT
    1935           2 : u16 gf_ntohs(u16 val)
    1936             : {
    1937           2 :         return ntohs(val);
    1938             : }
    1939             : 
    1940             : #endif /*GPAC_DISABLE_CORE_TOOLS*/

Generated by: LCOV version 1.13