PageRenderTime 5ms CodeModel.GetById 2ms app.highlight 101ms RepoModel.GetById 1ms app.codeStats 0ms

/src/utils/os_net.c

https://github.com/svettom/gpac
C | 1536 lines | 1216 code | 202 blank | 118 comment | 330 complexity | c7265c06e0a263b9b80d685678a1330f MD5 | raw file
   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
  27#if defined(WIN32) || defined(_WIN32_WCE)
  28
  29#ifdef _WIN32_WCE
  30#include <winsock.h>
  31
  32#if !defined(__GNUC__)
  33#pragma comment(lib, "winsock")
  34#endif
  35
  36#else
  37
  38#include <sys/timeb.h>
  39#include <winsock2.h>
  40#include <ws2tcpip.h>
  41
  42#if !defined(__GNUC__)
  43#pragma comment(lib, "ws2_32")
  44#endif
  45
  46#endif
  47
  48#include <windows.h>
  49
  50#if !defined(__GNUC__)
  51
  52#if defined(IPV6_MULTICAST_IF)
  53#define GPAC_HAS_IPV6 1
  54#pragma message("Using WinSock IPV6")
  55#else
  56#undef GPAC_HAS_IPV6
  57#pragma message("Using WinSock IPV4")
  58#endif
  59
  60#endif
  61
  62/*common win32 redefs*/
  63#undef EAGAIN
  64#define EAGAIN				WSAEWOULDBLOCK
  65#define EISCONN				WSAEISCONN
  66#define ENOTCONN			WSAENOTCONN
  67#define ECONNRESET			WSAECONNRESET
  68#define EMSGSIZE			WSAEMSGSIZE
  69#define ECONNABORTED		WSAECONNABORTED
  70#define ENETDOWN			WSAENETDOWN
  71#undef EINTR
  72#define EINTR				WSAEINTR
  73#undef EBADF
  74#define EBADF				WSAEBADF
  75
  76#define LASTSOCKERROR WSAGetLastError()
  77
  78/*the number of sockets used. This because the WinSock lib needs init*/
  79static int wsa_init = 0;
  80
  81
  82#include "../../include/gpac/network.h"
  83
  84
  85/*end-win32*/
  86
  87#else
  88/*non-win32*/
  89#include <unistd.h>
  90#include <fcntl.h>
  91#include <netdb.h>
  92
  93#ifndef __BEOS__
  94#include <errno.h>
  95#endif
  96
  97#ifndef __DARWIN__
  98#include <sys/time.h>
  99#endif
 100
 101#include <netinet/in.h>
 102#include <netinet/tcp.h>
 103#include <sys/socket.h>
 104#include <sys/types.h>
 105#include <arpa/inet.h>
 106
 107#include "../../include/gpac/network.h"
 108
 109/*not defined on solaris*/
 110#if !defined(INADDR_NONE)
 111# if (defined(sun) && defined(__SVR4))
 112#  define INADDR_NONE -1
 113# else
 114#  define INADDR_NONE ((unsigned long)-1)
 115# endif
 116#endif
 117
 118
 119#define INVALID_SOCKET -1
 120#define SOCKET_ERROR -1
 121#define LASTSOCKERROR errno
 122
 123typedef s32 SOCKET;
 124#define closesocket(v) close(v)
 125
 126#endif /*WIN32||_WIN32_WCE*/
 127
 128
 129#ifdef GPAC_HAS_IPV6
 130# ifndef IPV6_ADD_MEMBERSHIP
 131#  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
 132# endif
 133# ifndef IPV6_DROP_MEMBERSHIP
 134#  define IPV6_DROP_MEMBERSHIP   IPV6_LEAVE_GROUP
 135# endif
 136#endif
 137
 138
 139#ifdef __SYMBIAN32__
 140#define SSO_CAST
 141#else
 142#define SSO_CAST (const char *)
 143#endif
 144
 145
 146#define SOCK_MICROSEC_WAIT	500
 147
 148#ifdef GPAC_HAS_IPV6
 149static u32 ipv6_check_state = 0;
 150#endif
 151
 152#ifdef _LP64
 153#define NULL_SOCKET 0
 154#else
 155#define NULL_SOCKET (SOCKET)NULL
 156#endif
 157
 158
 159/*internal flags*/
 160enum
 161{
 162	GF_SOCK_IS_TCP = 1<<9,
 163	GF_SOCK_IS_IPV6 = 1<<10,
 164	GF_SOCK_NON_BLOCKING = 1<<11,
 165	GF_SOCK_IS_MULTICAST = 1<<12,
 166	GF_SOCK_IS_LISTENING = 1<<13,
 167	/*socket is bound to a specific dest (server) or source (client) */
 168	GF_SOCK_HAS_PEER = 1<<14,
 169	GF_SOCK_IS_MIP = 1<<15
 170};
 171
 172struct __tag_socket
 173{
 174	u32 flags;
 175	SOCKET socket;
 176	/*destination address for sendto/recvfrom*/
 177#ifdef GPAC_HAS_IPV6
 178	struct sockaddr_storage dest_addr;
 179#else
 180	struct sockaddr_in dest_addr;
 181#endif
 182	u32 dest_addr_len;
 183};
 184
 185
 186
 187/*
 188	MobileIP tools
 189*/
 190
 191static gf_net_mobileip_ctrl_cbk mobip_cbk = NULL;
 192static const char *MobileIPAdd = NULL;
 193
 194GF_EXPORT
 195void gf_net_mobileip_set_callback(gf_net_mobileip_ctrl_cbk _mobip_cbk, const char *mip)
 196{
 197	mobip_cbk = _mobip_cbk;
 198	MobileIPAdd = _mobip_cbk ? mip : NULL;
 199}
 200
 201static GF_Err gf_net_mobileip_ctrl(Bool start)
 202{
 203	if (mobip_cbk) return mobip_cbk(start);
 204	return GF_NOT_SUPPORTED;
 205}
 206
 207
 208u32 gf_net_has_ipv6()
 209{
 210#ifdef GPAC_HAS_IPV6
 211	if (!ipv6_check_state) {
 212		SOCKET s;
 213#ifdef WIN32
 214		if (!wsa_init) {
 215			WSADATA Data;
 216			if (WSAStartup(0x0202, &Data)!=0) {
 217				ipv6_check_state = 1;
 218				return 0;
 219			}
 220		}
 221#endif
 222		s = socket(PF_INET6, SOCK_STREAM, 0);
 223		if (!s) ipv6_check_state = 1;
 224		else {
 225			ipv6_check_state = 2;
 226			closesocket(s);
 227		}
 228#ifdef WIN32
 229		if (!wsa_init) WSACleanup();
 230#endif
 231	}
 232	return (ipv6_check_state==2);
 233#else
 234	return 0;
 235#endif
 236}
 237
 238GF_EXPORT
 239Bool gf_net_is_ipv6(const char *address)
 240{
 241	char *sep;
 242	if (!address) return 0;
 243	sep = strchr(address, ':');
 244	if (sep) sep = strchr(address, ':');
 245	return sep ? 1 : 0;
 246}
 247
 248#ifdef GPAC_HAS_IPV6
 249#define MAX_PEER_NAME_LEN 1024
 250static struct addrinfo *gf_sk_get_ipv6_addr(const char *PeerName, u16 PortNumber, int family, int flags, int sock_type)
 251{
 252	struct	addrinfo *res=NULL;
 253	struct	addrinfo hints;
 254	char node[MAX_PEER_NAME_LEN], portstring[20];
 255	char *service, *dest;
 256	service = dest = NULL;
 257#ifdef WIN32
 258		if (!wsa_init) {
 259			WSADATA Data;
 260			if (WSAStartup(0x0202, &Data)!=0) return NULL;
 261			wsa_init = 1;
 262		}
 263#endif
 264
 265	service = dest = NULL;
 266	memset(&hints, 0, sizeof(hints));
 267	hints.ai_socktype = sock_type;
 268 	hints.ai_family = family;
 269	hints.ai_flags = flags;
 270
 271	if (PortNumber) {
 272		sprintf (portstring, "%d", PortNumber);
 273		service = (char *)portstring;
 274	}
 275	if (PeerName) {
 276 		strncpy(node, PeerName, MAX_PEER_NAME_LEN);
 277 		if (node[0]=='[') {
 278 			node[strlen(node)-1] = 0;
 279 			strncpy(node, &node[1], MAX_PEER_NAME_LEN);
 280 		}
 281		node[MAX_PEER_NAME_LEN - 1] = 0;
 282		dest = (char *) node;
 283	}
 284	if (getaddrinfo((const char *)dest, (const char *)service, &hints, &res) != 0) return NULL;
 285	return res;
 286}
 287
 288static Bool gf_sk_ipv6_set_remote_address(GF_Socket *sock, const char *address, u16 PortNumber)
 289{
 290	struct addrinfo *res = gf_sk_get_ipv6_addr(address, PortNumber, AF_UNSPEC, 0, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM);
 291	if (!res) return 0;
 292    memcpy(&sock->dest_addr, res->ai_addr, res->ai_addrlen);
 293	sock->dest_addr_len = (u32) res->ai_addrlen;
 294	freeaddrinfo(res);
 295	return 1;
 296}
 297#endif
 298
 299
 300GF_EXPORT
 301GF_Err gf_sk_get_host_name(char *buffer)
 302{
 303	s32 ret = gethostname(buffer, GF_MAX_IP_NAME_LEN);
 304	return (ret == SOCKET_ERROR) ? GF_IP_ADDRESS_NOT_FOUND : GF_OK;
 305}
 306
 307GF_Err gf_sk_get_local_ip(GF_Socket *sock, char *buffer)
 308{
 309#ifdef GPAC_HAS_IPV6
 310	char clienthost[NI_MAXHOST];
 311	if (sock->flags & GF_SOCK_HAS_PEER) {
 312		if (getnameinfo((struct sockaddr *)&sock->dest_addr, sock->dest_addr_len, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
 313			return GF_IP_NETWORK_FAILURE;
 314	} else {
 315		struct sockaddr_storage clientaddr;
 316		socklen_t addrlen = sizeof(clientaddr);
 317		if (getsockname(sock->socket, (struct sockaddr *)&clientaddr, &addrlen)) return GF_IP_NETWORK_FAILURE;
 318
 319		if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
 320			return GF_IP_NETWORK_FAILURE;
 321	}
 322	strcpy(buffer, clienthost);
 323#else
 324	char *ip;
 325	if (sock->flags & GF_SOCK_HAS_PEER) {
 326		ip = inet_ntoa(sock->dest_addr.sin_addr);
 327	} else {
 328		struct sockaddr_in name;
 329		u32 len = sizeof(struct sockaddr_in);
 330		if (getsockname(sock->socket, (struct sockaddr*) &name, &len)) return GF_IP_NETWORK_FAILURE;
 331		ip = inet_ntoa(name.sin_addr);
 332	}
 333	if (!ip) return GF_IP_NETWORK_FAILURE;
 334	strcpy(buffer, ip);
 335#endif
 336	return GF_OK;
 337}
 338
 339
 340GF_EXPORT
 341GF_Socket *gf_sk_new(u32 SocketType)
 342{
 343	GF_Socket *tmp;
 344
 345	/*init WinSock*/
 346#ifdef WIN32
 347	WSADATA Data;
 348	if (!wsa_init && (WSAStartup(0x0202, &Data)!=0) ) return NULL;
 349#endif
 350	if ((SocketType != GF_SOCK_TYPE_UDP) && (SocketType != GF_SOCK_TYPE_TCP)) return NULL;
 351
 352	GF_SAFEALLOC(tmp, GF_Socket);
 353	if (!tmp) return NULL;
 354	if (SocketType == GF_SOCK_TYPE_TCP) tmp->flags |= GF_SOCK_IS_TCP;
 355
 356#ifdef GPAC_HAS_IPV6
 357	memset(&tmp->dest_addr, 0, sizeof(struct sockaddr_storage));
 358#else
 359	memset(&tmp->dest_addr, 0, sizeof(struct sockaddr_in));
 360	tmp->dest_addr_len = sizeof(struct sockaddr);
 361#endif
 362
 363#ifdef WIN32
 364	wsa_init ++;
 365#endif
 366	return tmp;
 367}
 368
 369GF_EXPORT
 370GF_Err gf_sk_set_buffer_size(GF_Socket *sock, Bool SendBuffer, u32 NewSize)
 371{
 372	s32 res;
 373	if (!sock || !sock->socket) return GF_BAD_PARAM;
 374
 375	if (SendBuffer) {
 376		res = setsockopt(sock->socket, SOL_SOCKET, SO_SNDBUF, (char *) &NewSize, sizeof(u32) );
 377	} else {
 378		res = setsockopt(sock->socket, SOL_SOCKET, SO_RCVBUF, (char *) &NewSize, sizeof(u32) );
 379	}
 380	if (res<0) {
 381		GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Core] Couldn't set socket %s buffer size: %d\n", SendBuffer ? "send" : "receive", res));
 382	} else {
 383		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Core] Set socket %s buffer size\n", SendBuffer ? "send" : "receive"));
 384	}
 385	return GF_OK;
 386}
 387
 388GF_EXPORT
 389GF_Err gf_sk_set_block_mode(GF_Socket *sock, Bool NonBlockingOn)
 390{
 391	s32 res;
 392#ifdef WIN32
 393	long val = NonBlockingOn;
 394	if (sock->socket) {
 395		res = ioctlsocket(sock->socket, FIONBIO, &val);
 396		if (res) return GF_SERVICE_ERROR;
 397	}
 398#else
 399	s32 flag = fcntl(sock->socket, F_GETFL, 0);
 400	if (sock->socket) {
 401		res = fcntl(sock->socket, F_SETFL, flag | O_NONBLOCK);
 402		if (res) return GF_SERVICE_ERROR;
 403	}
 404#endif
 405	if (NonBlockingOn) {
 406		sock->flags |= GF_SOCK_NON_BLOCKING;
 407	} else {
 408		sock->flags &= ~GF_SOCK_NON_BLOCKING;
 409	}
 410	return GF_OK;
 411}
 412
 413#include <assert.h>
 414
 415static void gf_sk_free(GF_Socket *sock)
 416{
 417	assert( sock );
 418	/*leave multicast*/
 419	if (sock->socket && (sock->flags & GF_SOCK_IS_MULTICAST) ) {
 420		struct ip_mreq mreq;
 421#ifdef GPAC_HAS_IPV6
 422		struct sockaddr *addr = (struct sockaddr *)&sock->dest_addr;
 423		if (addr->sa_family==AF_INET6) {
 424		    struct ipv6_mreq mreq6;
 425			memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
 426			mreq6.ipv6mr_interface= 0;
 427			setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &mreq6, sizeof(mreq6));
 428		} else {
 429			mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
 430			mreq.imr_interface.s_addr = INADDR_ANY;
 431			setsockopt(sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
 432		}
 433#else
 434		mreq.imr_multiaddr.s_addr = sock->dest_addr.sin_addr.s_addr;
 435		mreq.imr_interface.s_addr = INADDR_ANY;
 436		setsockopt(sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
 437#endif
 438	}
 439	if (sock->socket) closesocket(sock->socket);
 440	sock->socket = (SOCKET) 0L;
 441
 442	/*if MobileIP socket, unregister it*/
 443	if (sock->flags & GF_SOCK_IS_MIP) {
 444		sock->flags &= ~GF_SOCK_IS_MIP;
 445		gf_net_mobileip_ctrl(0);
 446	}
 447}
 448
 449
 450GF_EXPORT
 451void gf_sk_del(GF_Socket *sock)
 452{
 453	assert( sock );
 454	gf_sk_free(sock);
 455#ifdef WIN32
 456	wsa_init --;
 457	if (!wsa_init) WSACleanup();
 458#endif
 459	gf_free(sock);
 460}
 461
 462void gf_sk_reset(GF_Socket *sock)
 463{
 464	u32 clear;
 465	if (sock) setsockopt(sock->socket, SOL_SOCKET, SO_ERROR, (char *) &clear, sizeof(u32) );
 466}
 467
 468s32 gf_sk_get_handle(GF_Socket *sock)
 469{
 470	return (s32) sock->socket;
 471}
 472
 473
 474
 475//connects a socket to a remote peer on a given port
 476GF_Err gf_sk_connect(GF_Socket *sock, const char *PeerName, u16 PortNumber, const char *local_ip)
 477{
 478	s32 ret;
 479#ifdef GPAC_HAS_IPV6
 480	u32 type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
 481	struct addrinfo *res, *aip, *lip;
 482
 483	gf_sk_free(sock);
 484
 485	res = gf_sk_get_ipv6_addr(PeerName, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
 486	if (!res) return GF_IP_CONNECTION_FAILURE;
 487
 488	/*turn on MobileIP*/
 489	if (local_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_ip) ) {
 490		if (gf_net_mobileip_ctrl(1)==GF_OK) {
 491			sock->flags |= GF_SOCK_IS_MIP;
 492		} else {
 493			local_ip = NULL;
 494		}
 495	}
 496
 497	lip = NULL;
 498	if (local_ip) {
 499		lip = gf_sk_get_ipv6_addr(local_ip, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
 500		if (!lip && local_ip) {
 501			lip = gf_sk_get_ipv6_addr(NULL, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
 502			local_ip = NULL;
 503		}
 504	}
 505
 506	/*for all interfaces*/
 507	for (aip=res; aip!=NULL; aip=aip->ai_next) {
 508		if (type != (u32) aip->ai_socktype) continue;
 509		sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
 510		if (sock->socket == INVALID_SOCKET) {
 511			sock->socket = NULL_SOCKET;
 512			continue;
 513		}
 514		if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
 515		if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
 516		else sock->flags &= ~GF_SOCK_IS_IPV6;
 517
 518		if (lip) {
 519			ret = bind(sock->socket, lip->ai_addr, (int) lip->ai_addrlen);
 520			if (ret == SOCKET_ERROR) {
 521				closesocket(sock->socket);
 522				sock->socket = NULL_SOCKET;
 523				continue;
 524			}
 525		}
 526
 527		ret = connect(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
 528		if (ret == SOCKET_ERROR) {
 529			closesocket(sock->socket);
 530			sock->socket = NULL_SOCKET;
 531			continue;
 532		}
 533
 534		memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
 535		sock->dest_addr_len = (u32) aip->ai_addrlen;
 536		freeaddrinfo(res);
 537		if (lip) freeaddrinfo(lip);
 538		return GF_OK;
 539	}
 540	freeaddrinfo(res);
 541	if (lip) freeaddrinfo(lip);
 542	return GF_IP_CONNECTION_FAILURE;
 543
 544#else
 545	struct hostent *Host;
 546
 547	if (local_ip) {
 548		/*this will turn on MobileIP if needed*/
 549		GF_Err e = gf_sk_bind(sock, local_ip, PortNumber, PeerName, PortNumber, GF_SOCK_REUSE_PORT);
 550		if (e) return e;
 551	}
 552	if (!sock->socket) {
 553		sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
 554		if (sock->flags & GF_SOCK_NON_BLOCKING)
 555			gf_sk_set_block_mode(sock, 1);
 556	}
 557
 558	/*setup the address*/
 559	sock->dest_addr.sin_family = AF_INET;
 560	sock->dest_addr.sin_port = htons(PortNumber);
 561	/*get the server IP*/
 562	sock->dest_addr.sin_addr.s_addr = inet_addr(PeerName);
 563	if (sock->dest_addr.sin_addr.s_addr==INADDR_NONE) {
 564		Host = gethostbyname(PeerName);
 565		if (Host == NULL) {
 566			switch (LASTSOCKERROR) {
 567#ifndef __SYMBIAN32__
 568			case ENETDOWN: return GF_IP_NETWORK_FAILURE;
 569			//case ENOHOST: return GF_IP_ADDRESS_NOT_FOUND;
 570#endif
 571			default: return GF_IP_NETWORK_FAILURE;
 572			}
 573		}
 574		memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
 575	}
 576
 577	if (sock->flags & GF_SOCK_IS_TCP) {
 578		ret = connect(sock->socket, (struct sockaddr *) &sock->dest_addr, sizeof(struct sockaddr));
 579		if (ret == SOCKET_ERROR) {
 580			u32 res = LASTSOCKERROR;
 581			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Core] Couldn't connect socket - last sock error %d\n", res));
 582			switch (res) {
 583			case EAGAIN: return GF_IP_SOCK_WOULD_BLOCK;
 584#ifdef WIN32
 585			case WSAEINVAL:
 586				if (sock->flags & GF_SOCK_NON_BLOCKING)
 587					return GF_IP_SOCK_WOULD_BLOCK;
 588#endif
 589			case EISCONN: return GF_OK;
 590			case ENOTCONN: return GF_IP_CONNECTION_FAILURE;
 591			case ECONNRESET: return GF_IP_CONNECTION_FAILURE;
 592			case EMSGSIZE: return GF_IP_CONNECTION_FAILURE;
 593			case ECONNABORTED: return GF_IP_CONNECTION_FAILURE;
 594			case ENETDOWN: return GF_IP_CONNECTION_FAILURE;
 595			default: return GF_IP_CONNECTION_FAILURE;
 596			}
 597		}
 598	}
 599#endif
 600	return GF_OK;
 601}
 602
 603
 604//binds the given socket to the specified port. If ReUse is true
 605//this will enable reuse of ports on a single machine
 606GF_EXPORT
 607GF_Err gf_sk_bind(GF_Socket *sock, const char *local_ip, u16 port, const char *peer_name, u16 peer_port, u32 options)
 608{
 609#ifdef GPAC_HAS_IPV6
 610	struct addrinfo *res, *aip;
 611	int af;
 612	u32 type;
 613#else
 614	u32 ip_add;
 615	size_t addrlen;
 616	struct sockaddr_in LocalAdd;
 617	struct hostent *Host;
 618#if 0
 619	char buf[GF_MAX_IP_NAME_LEN];
 620#endif
 621
 622#endif
 623	s32 ret;
 624	s32 optval;
 625
 626	if (!sock || sock->socket) return GF_BAD_PARAM;
 627
 628#ifndef WIN32
 629	if(!local_ip){
 630		if(!peer_name || !strcmp(peer_name,"localhost")){
 631			peer_name="127.0.0.1";
 632		}
 633	}
 634#endif
 635
 636#ifdef GPAC_HAS_IPV6
 637	type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
 638	af = (options & GF_SOCK_FORCE_IPV6) ? PF_INET6 : PF_UNSPEC;
 639	if (!gf_net_has_ipv6()) af = PF_INET;
 640	/*probe way to peer: is it V4 or V6? */
 641	if (peer_name && peer_port) {
 642		res = gf_sk_get_ipv6_addr(peer_name, peer_port, af, AI_PASSIVE, type);
 643		if (!res) {
 644			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", peer_name, peer_port));
 645			return GF_IP_ADDRESS_NOT_FOUND;
 646		}
 647#ifdef WIN32
 648		/*win32 has troubles redirecting IPV4 datagrams to IPV6 sockets, so override
 649		local family type to avoid IPV4(S)->IPV6(C) UDP*/
 650		af = res->ai_family;
 651#endif
 652		memcpy(&sock->dest_addr, res->ai_addr, res->ai_addrlen);
 653		sock->dest_addr_len = (u32) res->ai_addrlen;
 654		freeaddrinfo(res);
 655	}
 656
 657	/*turn on MobileIP*/
 658	if (local_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_ip) ) {
 659		if (gf_net_mobileip_ctrl(1)==GF_OK) {
 660			sock->flags |= GF_SOCK_IS_MIP;
 661		} else {
 662			res = gf_sk_get_ipv6_addr(NULL, port, af, AI_PASSIVE, type);
 663			local_ip = NULL;
 664		}
 665	}
 666	res = gf_sk_get_ipv6_addr(local_ip, port, af, AI_PASSIVE, type);
 667	if (!res) {
 668		if (local_ip) {
 669			res = gf_sk_get_ipv6_addr(NULL, port, af, AI_PASSIVE, type);
 670			local_ip = NULL;
 671		}
 672		if (!res) {
 673			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", local_ip, port));
 674			return GF_IP_ADDRESS_NOT_FOUND;
 675		}
 676	}
 677
 678	/*for all interfaces*/
 679	for (aip=res; aip!=NULL; aip=aip->ai_next) {
 680		if (type != (u32) aip->ai_socktype) continue;
 681
 682		if (aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(peer_name)) continue;
 683
 684		sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
 685		if (sock->socket == INVALID_SOCKET) {
 686			sock->socket = NULL_SOCKET;
 687			continue;
 688		}
 689		if (options & GF_SOCK_REUSE_PORT) {
 690			optval = 1;
 691			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
 692#ifdef SO_REUSEPORT
 693			optval = 1;
 694			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
 695#endif
 696		}
 697
 698		if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
 699
 700		if (peer_name && peer_port)
 701			sock->flags |= GF_SOCK_HAS_PEER;
 702
 703
 704		ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
 705		if (ret == SOCKET_ERROR) {
 706			closesocket(sock->socket);
 707			sock->socket = NULL_SOCKET;
 708			continue;
 709		}
 710
 711		if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
 712		else sock->flags &= ~GF_SOCK_IS_IPV6;
 713
 714		freeaddrinfo(res);
 715		return GF_OK;
 716	}
 717	freeaddrinfo(res);
 718	GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot bind to host %s port %d\n", local_ip, port));
 719	return GF_IP_CONNECTION_FAILURE;
 720
 721#else
 722
 723	sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
 724	if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
 725	sock->flags &= ~GF_SOCK_IS_IPV6;
 726
 727	memset((void *) &LocalAdd, 0, sizeof(LocalAdd));
 728
 729	/*turn on MobileIP*/
 730	if (local_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_ip) ) {
 731		if (gf_net_mobileip_ctrl(1)==GF_OK) {
 732			sock->flags |= GF_SOCK_IS_MIP;
 733		} else {
 734			local_ip = NULL;
 735		}
 736	}
 737	/*setup the address*/
 738	ip_add = 0;
 739	if (local_ip) ip_add = inet_addr(local_ip);
 740
 741	if (!ip_add) {
 742#if 0
 743		buf[0] = 0;
 744		ret = gethostname(buf, GF_MAX_IP_NAME_LEN);
 745		/*get the IP address*/
 746		Host = gethostbyname(buf);
 747		if (Host != NULL) {
 748			memcpy((char *) &LocalAdd.sin_addr, Host->h_addr_list[0], sizeof(LocalAdd.sin_addr));
 749			ip_add = LocalAdd.sin_addr.s_addr;
 750		} else {
 751			ip_add = INADDR_ANY;
 752		}
 753#else
 754		ip_add = INADDR_ANY;
 755#endif
 756	}
 757	if (peer_name && peer_port) {
 758#ifdef WIN32
 759		if ((inet_addr(peer_name)== ip_add)) {
 760			optval = 1;
 761			setsockopt(sock->socket, SOL_SOCKET, SO_USELOOPBACK, SSO_CAST &optval, sizeof(optval));
 762		}
 763#endif
 764	}
 765
 766	LocalAdd.sin_family = AF_INET;
 767	LocalAdd.sin_port = htons(port);
 768	LocalAdd.sin_addr.s_addr = ip_add;
 769	addrlen = sizeof(struct sockaddr_in);
 770
 771
 772	if (options & GF_SOCK_REUSE_PORT) {
 773		optval = 1;
 774		setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
 775#ifdef SO_REUSEPORT
 776		optval = 1;
 777		setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
 778#endif
 779	}
 780
 781	/*bind the socket*/
 782	ret = bind(sock->socket, (struct sockaddr *) &LocalAdd, (int) addrlen);
 783	if (ret == SOCKET_ERROR) {
 784		GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot bind socket - socket error %x\n", LASTSOCKERROR));
 785		ret = GF_IP_CONNECTION_FAILURE;
 786	}
 787
 788	if (peer_name && peer_port) {
 789		sock->dest_addr.sin_port = htons(peer_port);
 790		sock->dest_addr.sin_family = AF_INET;
 791		sock->dest_addr.sin_addr.s_addr = inet_addr(peer_name);
 792		if (sock->dest_addr.sin_addr.s_addr == INADDR_NONE) {
 793			Host = gethostbyname(peer_name);
 794			if (Host == NULL) ret = GF_IP_ADDRESS_NOT_FOUND;
 795			else memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
 796		}
 797		sock->flags |= GF_SOCK_HAS_PEER;
 798	}
 799	if (sock->flags & GF_SOCK_HAS_PEER) {
 800		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));
 801	} else {
 802		GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d\n", ip_add, port));
 803	}
 804	return ret;
 805#endif
 806}
 807
 808//send length bytes of a buffer
 809GF_EXPORT
 810GF_Err gf_sk_send(GF_Socket *sock, const char *buffer, u32 length)
 811{
 812	u32 count;
 813	s32 res;
 814#ifndef __SYMBIAN32__
 815	int ready;
 816	struct timeval timeout;
 817	fd_set Group;
 818#endif
 819
 820	//the socket must be bound or connected
 821	if (!sock || !sock->socket) return GF_BAD_PARAM;
 822
 823#ifndef __SYMBIAN32__
 824	//can we write?
 825	FD_ZERO(&Group);
 826	FD_SET(sock->socket, &Group);
 827	timeout.tv_sec = 0;
 828	timeout.tv_usec = SOCK_MICROSEC_WAIT;
 829
 830	//TODO CHECK IF THIS IS CORRECT
 831	ready = select((int) sock->socket+1, NULL, &Group, NULL, &timeout);
 832	if (ready == SOCKET_ERROR) {
 833		switch (LASTSOCKERROR) {
 834		case EAGAIN:
 835			return GF_IP_SOCK_WOULD_BLOCK;
 836		default:
 837			return GF_IP_NETWORK_FAILURE;
 838		}
 839	}
 840	//should never happen (to check: is writeability is guaranteed for not-connected sockets)
 841	if (!ready || !FD_ISSET(sock->socket, &Group)) {
 842		return GF_IP_NETWORK_EMPTY;
 843	}
 844#endif
 845
 846	//direct writing
 847	count = 0;
 848	while (count < length) {
 849		if (sock->flags & GF_SOCK_HAS_PEER) {
 850			res = sendto(sock->socket, (char *) buffer+count,  length - count, 0, (struct sockaddr *) &sock->dest_addr, sock->dest_addr_len);
 851		} else {
 852			res = send(sock->socket, (char *) buffer+count, length - count, 0);
 853		}
 854		if (res == SOCKET_ERROR) {
 855			switch (res = LASTSOCKERROR) {
 856			case EAGAIN:
 857				return GF_IP_SOCK_WOULD_BLOCK;
 858#ifndef __SYMBIAN32__
 859			case ENOTCONN:
 860			case ECONNRESET:
 861				return GF_IP_CONNECTION_CLOSED;
 862#endif
 863			default:
 864				return GF_IP_NETWORK_FAILURE;
 865			}
 866		}
 867		count += res;
 868	}
 869	return GF_OK;
 870}
 871
 872
 873GF_EXPORT
 874u32 gf_sk_is_multicast_address(const char *multi_IPAdd)
 875{
 876#ifdef GPAC_HAS_IPV6
 877	u32 val;
 878 	char *sep;
 879	struct addrinfo *res;
 880	if (!multi_IPAdd) return 0;
 881	/*IPV6 multicast address*/
 882	sep = strchr(multi_IPAdd, ':');
 883	if (sep) sep = strchr(multi_IPAdd, ':');
 884	if (sep && !strnicmp(multi_IPAdd, "ff", 2)) return 1;
 885	/*ipv4 multicast address*/
 886	res = gf_sk_get_ipv6_addr((char*)multi_IPAdd, 7000, AF_UNSPEC, AI_PASSIVE, SOCK_DGRAM);
 887	if (!res) return 0;
 888	val = 0;
 889	if (res->ai_addr->sa_family == AF_INET) {
 890	        val = IN_MULTICAST(ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr));
 891	} else if (res->ai_addr->sa_family == AF_INET6) {
 892		val = IN6_IS_ADDR_MULTICAST(& ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr);
 893	}
 894	freeaddrinfo(res);
 895	return val;
 896#else
 897	if (!multi_IPAdd) return 0;
 898	return ((htonl(inet_addr(multi_IPAdd)) >> 8) & 0x00f00000) == 0x00e00000;
 899#endif
 900}
 901
 902GF_EXPORT
 903GF_Err gf_sk_setup_multicast(GF_Socket *sock, const char *multi_IPAdd, u16 MultiPortNumber, u32 TTL, Bool NoBind, char *local_interface_ip)
 904{
 905	s32 ret;
 906	u32 flag;
 907	struct ip_mreq M_req;
 908	u32 optval;
 909#ifdef GPAC_HAS_IPV6
 910	struct sockaddr *addr;
 911	struct addrinfo *res, *aip;
 912	Bool is_ipv6 = 0;
 913	u32 type;
 914#endif
 915	unsigned long local_add_id;
 916
 917	if (!sock || sock->socket) return GF_BAD_PARAM;
 918
 919	if (TTL > 255) TTL = 255;
 920
 921	/*check the address*/
 922	if (!gf_sk_is_multicast_address(multi_IPAdd)) return GF_BAD_PARAM;
 923
 924	/*turn on MobileIP*/
 925	if (local_interface_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_interface_ip) ) {
 926		if (gf_net_mobileip_ctrl(1)==GF_OK) {
 927			sock->flags |= GF_SOCK_IS_MIP;
 928		} else {
 929			local_interface_ip = NULL;
 930		}
 931	}
 932
 933
 934#ifdef GPAC_HAS_IPV6
 935	is_ipv6 = gf_net_is_ipv6(multi_IPAdd) || gf_net_is_ipv6(local_interface_ip) ? 1 : 0;
 936	type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
 937
 938	if (is_ipv6) {
 939
 940		res = gf_sk_get_ipv6_addr(local_interface_ip, MultiPortNumber, AF_UNSPEC, AI_PASSIVE, type);
 941		if (!res) {
 942			if (local_interface_ip) {
 943				res = gf_sk_get_ipv6_addr(NULL, MultiPortNumber, AF_UNSPEC, AI_PASSIVE, type);
 944				local_interface_ip = NULL;
 945			}
 946			if (!res) return GF_IP_CONNECTION_FAILURE;
 947		}
 948
 949		/*for all interfaces*/
 950		for (aip=res; aip!=NULL; aip=aip->ai_next) {
 951			if (type != (u32) aip->ai_socktype) continue;
 952			sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
 953			if (sock->socket == INVALID_SOCKET) {
 954				sock->socket = NULL_SOCKET;
 955				continue;
 956			}
 957
 958			if ((aip->ai_family!=PF_INET) && aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(multi_IPAdd)) continue;
 959
 960			/*enable address reuse*/
 961			optval = 1;
 962			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
 963#ifdef SO_REUSEPORT
 964			optval = 1;
 965			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
 966#endif
 967
 968			/*TODO: copy over other properties (recption buffer size & co)*/
 969			if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
 970
 971			memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
 972			sock->dest_addr_len = (u32) aip->ai_addrlen;
 973
 974			if (!NoBind) {
 975				ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
 976				if (ret == SOCKET_ERROR) {
 977					closesocket(sock->socket);
 978					sock->socket = NULL_SOCKET;
 979					continue;
 980				}
 981			}
 982			if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
 983			else sock->flags &= ~GF_SOCK_IS_IPV6;
 984			break;
 985		}
 986		freeaddrinfo(res);
 987		if (!sock->socket) return GF_IP_CONNECTION_FAILURE;
 988
 989
 990		if (!gf_sk_ipv6_set_remote_address(sock, multi_IPAdd, MultiPortNumber))
 991			return GF_IP_CONNECTION_FAILURE;
 992
 993		addr = (struct sockaddr *)&sock->dest_addr;
 994		if (addr->sa_family == AF_INET) {
 995			M_req.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
 996			M_req.imr_interface.s_addr = INADDR_ANY;
 997			ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &M_req, sizeof(M_req));
 998			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
 999			/*set TTL*/
1000			ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &TTL, sizeof(TTL));
1001			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1002			/*Disable loopback*/
1003			flag = 1;
1004			ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
1005			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1006		}
1007
1008		if (addr->sa_family == AF_INET6) {
1009			struct ipv6_mreq M_reqV6;
1010
1011			memcpy(&M_reqV6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
1012			M_reqV6.ipv6mr_interface = 0;
1013
1014			/*set TTL*/
1015			ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &TTL, sizeof(TTL));
1016			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1017			/*Disable loopback*/
1018			flag = 1;
1019			ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
1020			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1021
1022			ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &M_reqV6, sizeof(M_reqV6));
1023			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1024		}
1025		sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
1026		return GF_OK;
1027	}
1028#endif
1029
1030	//IPv4 setup
1031	sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
1032	if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
1033	sock->flags &= ~GF_SOCK_IS_IPV6;
1034
1035	/*enable address reuse*/
1036	optval = 1;
1037	ret = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
1038#ifdef SO_REUSEPORT
1039	optval = 1;
1040	setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
1041#endif
1042
1043	if (local_interface_ip) local_add_id = inet_addr(local_interface_ip);
1044	else local_add_id = htonl(INADDR_ANY);
1045
1046	if (!NoBind) {
1047		struct sockaddr_in local_address;
1048
1049		local_address.sin_family = AF_INET;
1050		local_address.sin_addr.s_addr = local_add_id;
1051		local_address.sin_port = htons( MultiPortNumber);
1052
1053		ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
1054		if (ret == SOCKET_ERROR) {
1055			/*retry without specifying the local add*/
1056			local_address.sin_addr.s_addr = local_add_id = htonl(INADDR_ANY);
1057			local_interface_ip = NULL;
1058			ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
1059			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1060		}
1061		/*setup local interface*/
1062		if (local_interface_ip) {
1063			ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_IF, (char *) &local_add_id, sizeof(local_add_id));
1064			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1065		}
1066	}
1067
1068	/*now join the multicast*/
1069	M_req.imr_multiaddr.s_addr = inet_addr(multi_IPAdd);
1070	M_req.imr_interface.s_addr = local_add_id;
1071
1072	ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &M_req, sizeof(M_req));
1073	if (ret == SOCKET_ERROR) {
1074		GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot join multicast: error %d\n", LASTSOCKERROR));
1075		return GF_IP_CONNECTION_FAILURE;
1076	}
1077	/*set the Time To Live*/
1078	ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTL, sizeof(TTL));
1079	if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1080	/*Disable loopback*/
1081	flag = 1;
1082	ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
1083//	if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
1084
1085#ifdef GPAC_HAS_IPV6
1086	((struct sockaddr_in *) &sock->dest_addr)->sin_family = AF_INET;
1087	((struct sockaddr_in *) &sock->dest_addr)->sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
1088	((struct sockaddr_in *) &sock->dest_addr)->sin_port = htons( MultiPortNumber);
1089	sock->dest_addr_len = sizeof(struct sockaddr);
1090#else
1091	sock->dest_addr.sin_family = AF_INET;
1092	sock->dest_addr.sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
1093	sock->dest_addr.sin_port = htons( MultiPortNumber);
1094#endif
1095
1096	sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
1097	return GF_OK;
1098}
1099
1100
1101//fetch nb bytes on a socket and fill the buffer from startFrom
1102//length is the allocated size of the receiving buffer
1103//BytesRead is the number of bytes read from the network
1104GF_EXPORT
1105GF_Err gf_sk_receive(GF_Socket *sock, char *buffer, u32 length, u32 startFrom, u32 *BytesRead)
1106{
1107	s32 res;
1108#ifndef __SYMBIAN32__
1109	s32 ready;
1110	struct timeval timeout;
1111	fd_set Group;
1112#endif
1113
1114	*BytesRead = 0;
1115	if (!sock->socket) return GF_BAD_PARAM;
1116	if (startFrom >= length) return GF_IO_ERR;
1117
1118#ifndef __SYMBIAN32__
1119	//can we read?
1120	FD_ZERO(&Group);
1121	FD_SET(sock->socket, &Group);
1122	timeout.tv_sec = 0;
1123	timeout.tv_usec = SOCK_MICROSEC_WAIT;
1124
1125	res = 0;
1126	//TODO - check if this is correct
1127	ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
1128	if (ready == SOCKET_ERROR) {
1129		switch (LASTSOCKERROR) {
1130		case EBADF:
1131			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot select, BAD descriptor\n"));
1132			return GF_IP_CONNECTION_CLOSED;
1133		case EAGAIN:
1134			return GF_IP_SOCK_WOULD_BLOCK;
1135		case EINTR:
1136			/* Interrupted system call, not really important... */
1137			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] netowrk is lost\n"));
1138			return GF_IP_NETWORK_EMPTY;
1139		default:
1140			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot select (error %d)\n", LASTSOCKERROR));
1141			return GF_IP_NETWORK_FAILURE;
1142		}
1143	}
1144	if (!ready || !FD_ISSET(sock->socket, &Group)) {
1145		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[socket] nothing to be read - ready %d\n", ready));
1146		return GF_IP_NETWORK_EMPTY;
1147	}
1148#endif
1149	if (sock->flags & GF_SOCK_HAS_PEER)
1150		res = recvfrom(sock->socket, (char *) buffer + startFrom, length - startFrom, 0, (struct sockaddr *)&sock->dest_addr, &sock->dest_addr_len);
1151	else {
1152		res = recv(sock->socket, (char *) buffer + startFrom, length - startFrom, 0);
1153		/* souchay : Added for Linux, if we cannot read, it means we have been disconnected, beahviour may be different
1154		 * on some OSs... in such case, a #ifdef directive shoud be used
1155		 */
1156		if (res == 0)
1157		  return GF_IP_CONNECTION_CLOSED;
1158	}
1159
1160	if (res == SOCKET_ERROR) {
1161		res = LASTSOCKERROR;
1162		GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] error reading - socket error %d\n",  res));
1163		switch (res) {
1164		case EAGAIN:
1165			return GF_IP_SOCK_WOULD_BLOCK;
1166#ifndef __SYMBIAN32__
1167		case EMSGSIZE:
1168			return GF_OUT_OF_MEM;
1169		case ENOTCONN:
1170		case ECONNRESET:
1171		case ECONNABORTED:
1172			return GF_IP_CONNECTION_CLOSED;
1173#endif
1174		default:
1175			return GF_IP_NETWORK_FAILURE;
1176		}
1177	}
1178	if (!res) return GF_IP_NETWORK_EMPTY;
1179	*BytesRead = res;
1180	return GF_OK;
1181}
1182
1183
1184GF_Err gf_sk_listen(GF_Socket *sock, u32 MaxConnection)
1185{
1186	s32 i;
1187	if (!sock || !sock->socket) return GF_BAD_PARAM;
1188	if (MaxConnection >= SOMAXCONN) MaxConnection = SOMAXCONN;
1189	i = listen(sock->socket, MaxConnection);
1190	if (i == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
1191	sock->flags |= GF_SOCK_IS_LISTENING;
1192	return GF_OK;
1193}
1194
1195GF_Err gf_sk_accept(GF_Socket *sock, GF_Socket **newConnection)
1196{
1197	u32 client_address_size;
1198	SOCKET sk;
1199#ifndef __SYMBIAN32__
1200	s32 ready;
1201	struct timeval timeout;
1202	fd_set Group;
1203#endif
1204	*newConnection = NULL;
1205	if (!sock || !(sock->flags & GF_SOCK_IS_LISTENING) ) return GF_BAD_PARAM;
1206
1207#ifndef __SYMBIAN32__
1208	//can we read?
1209	FD_ZERO(&Group);
1210	FD_SET(sock->socket, &Group);
1211	timeout.tv_sec = 0;
1212	timeout.tv_usec = SOCK_MICROSEC_WAIT;
1213
1214	//TODO - check if this is correct
1215	ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
1216	if (ready == SOCKET_ERROR) {
1217		switch (LASTSOCKERROR) {
1218		case EAGAIN:
1219			return GF_IP_SOCK_WOULD_BLOCK;
1220		default:
1221			return GF_IP_NETWORK_FAILURE;
1222		}
1223	}
1224	if (!ready || !FD_ISSET(sock->socket, &Group)) return GF_IP_NETWORK_EMPTY;
1225#endif
1226
1227#ifdef GPAC_HAS_IPV6
1228	client_address_size = sizeof(struct sockaddr_in6);
1229#else
1230	client_address_size = sizeof(struct sockaddr_in);
1231#endif
1232	sk = accept(sock->socket, (struct sockaddr *) &sock->dest_addr, &client_address_size);
1233
1234	//we either have an error or we have no connections
1235	if (sk == INVALID_SOCKET) {
1236//		if (sock->flags & GF_SOCK_NON_BLOCKING) return GF_IP_NETWORK_FAILURE;
1237		switch (LASTSOCKERROR) {
1238		case EAGAIN:
1239			return GF_IP_SOCK_WOULD_BLOCK;
1240		default:
1241			return GF_IP_NETWORK_FAILURE;
1242		}
1243	}
1244
1245	(*newConnection) = (GF_Socket *) gf_malloc(sizeof(GF_Socket));
1246	(*newConnection)->socket = sk;
1247	(*newConnection)->flags = sock->flags & ~GF_SOCK_IS_LISTENING;
1248#ifdef GPAC_HAS_IPV6
1249	memcpy( &(*newConnection)->dest_addr, &sock->dest_addr, client_address_size);
1250	memset(&sock->dest_addr, 0, sizeof(struct sockaddr_in6));
1251#else
1252	memcpy( &(*newConnection)->dest_addr, &sock->dest_addr, client_address_size);
1253	memset(&sock->dest_addr, 0, sizeof(struct sockaddr_in));
1254#endif
1255
1256#if defined(WIN32) || defined(_WIN32_WCE)
1257	wsa_init++;
1258#endif
1259
1260	(*newConnection)->dest_addr_len = client_address_size;
1261	return GF_OK;
1262}
1263
1264GF_Err gf_sk_get_local_info(GF_Socket *sock, u16 *Port, u32 *Familly)
1265{
1266#ifdef GPAC_HAS_IPV6
1267	struct sockaddr_in6 the_add;
1268#else
1269	struct sockaddr_in the_add;
1270#endif
1271	u32 size;
1272
1273	if (!sock || !sock->socket) return GF_BAD_PARAM;
1274
1275	if (Port) {
1276#ifdef GPAC_HAS_IPV6
1277		size = sizeof(struct sockaddr_in6);
1278		if (getsockname(sock->socket, (struct sockaddr *) &the_add, &size) == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
1279		*Port = (u32) ntohs(the_add.sin6_port);
1280#else
1281		size = sizeof(struct sockaddr_in);
1282		if (getsockname(sock->socket, (struct sockaddr *) &the_add, &size) == SOCKET_ERROR) return GF_IP_NETWORK_FAILURE;
1283		*Port = (u32) ntohs(the_add.sin_port);
1284#endif
1285	}
1286	if (Familly) {
1287/*		size = 4;
1288		if (getsockopt(sock->socket, SOL_SOCKET, SO_TYPE, (char *) &fam, &size) == SOCKET_ERROR)
1289			return GF_IP_NETWORK_FAILURE;
1290		*Familly = fam;
1291*/
1292		if (sock->flags & GF_SOCK_IS_TCP) *Familly = GF_SOCK_TYPE_TCP;
1293		else  *Familly = GF_SOCK_TYPE_UDP;
1294	}
1295	return GF_OK;
1296}
1297
1298//we have to do this for the server sockets as we use only one thread
1299GF_Err gf_sk_server_mode(GF_Socket *sock, Bool serverOn)
1300{
1301	u32 one;
1302
1303	if (!sock || !(sock->flags & GF_SOCK_IS_TCP) || !sock->socket)
1304		return GF_BAD_PARAM;
1305
1306	one = serverOn ? 1 : 0;
1307	setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, SSO_CAST &one, sizeof(u32));
1308#ifndef __SYMBIAN32__
1309	setsockopt(sock->socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(u32));
1310#endif
1311	return GF_OK;
1312}
1313
1314GF_Err gf_sk_get_remote_address(GF_Socket *sock, char *buf)
1315{
1316#ifdef GPAC_HAS_IPV6
1317	char clienthost[NI_MAXHOST];
1318 	struct sockaddr_in6 * addrptr = (struct sockaddr_in6 *)(&sock->dest_addr_len);
1319	if (!sock || sock->socket) return GF_BAD_PARAM;
1320	if (getnameinfo((struct sockaddr *)addrptr, sock->dest_addr_len, clienthost, sizeof(clienthost), NULL, 0, NI_NUMERICHOST))
1321		return GF_IP_ADDRESS_NOT_FOUND;
1322	strcpy(buf, clienthost);
1323#else
1324	if (!sock || !sock->socket) return GF_BAD_PARAM;
1325	strcpy(buf, inet_ntoa(sock->dest_addr.sin_addr));
1326#endif
1327	return GF_OK;
1328}
1329
1330
1331
1332
1333//send length bytes of a buffer
1334GF_Err gf_sk_send_to(GF_Socket *sock, const char *buffer, u32 length, char *remoteHost, u16 remotePort)
1335{
1336	u32 count, remote_add_len;
1337	s32 res;
1338#ifdef GPAC_HAS_IPV6
1339	struct sockaddr_storage remote_add;
1340#else
1341	struct sockaddr_in remote_add;
1342	struct hostent *Host;
1343#endif
1344#ifndef __SYMBIAN32__
1345	s32 ready;
1346	struct timeval timeout;
1347	fd_set Group;
1348#endif
1349
1350	//the socket must be bound or connected
1351	if (!sock || !sock->socket) return GF_BAD_PARAM;
1352	if (remoteHost && !remotePort) return GF_BAD_PARAM;
1353
1354#ifndef __SYMBIAN32__
1355	//can we write?
1356	FD_ZERO(&Group);
1357	FD_SET(sock->socket, &Group);
1358	timeout.tv_sec = 0;
1359	timeout.tv_usec = SOCK_MICROSEC_WAIT;
1360
1361	//TODO - check if this is correct
1362	ready = select((int) sock->socket+1, NULL, &Group, NULL, &timeout);
1363	if (ready == SOCKET_ERROR) {
1364		switch (LASTSOCKERROR) {
1365		case EAGAIN:
1366			return GF_IP_SOCK_WOULD_BLOCK;
1367		default:
1368			return GF_IP_NETWORK_FAILURE;
1369		}
1370	}
1371	if (!ready || !FD_ISSET(sock->socket, &Group)) return GF_IP_NETWORK_EMPTY;
1372#endif
1373
1374
1375	/*setup the address*/
1376#ifdef GPAC_HAS_IPV6
1377	remote_add.ss_family = AF_INET6;
1378	//if a remote host is specified, use it. Otherwise use the default host
1379	if (remoteHost) {
1380		//setup the address
1381		struct addrinfo *res = gf_sk_get_ipv6_addr(remoteHost, remotePort, AF_UNSPEC, 0, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM);
1382		if (!res) return GF_IP_ADDRESS_NOT_FOUND;
1383		memcpy(&remote_add, res->ai_addr, res->ai_addrlen);
1384		remote_add_len = (u32) res->ai_addrlen;
1385		freeaddrinfo(res);
1386	} else {
1387		struct sockaddr_in6 *remotePtr = (struct sockaddr_in6 *)&remote_add;
1388	 	struct sockaddr_in6 * addrptr = (struct sockaddr_in6 *)(&sock->dest_addr);
1389		remotePtr->sin6_port = addrptr->sin6_port;
1390		remotePtr->sin6_addr = addrptr->sin6_addr;
1391		remote_add_len = sock->dest_addr_len;
1392	}
1393#else
1394	remote_add_len = sizeof(struct sockaddr_in);
1395	remote_add.sin_family = AF_INET;
1396	//if a remote host is specified, use it. Otherwise use the default host
1397	if (remoteHost) {
1398		//setup the address
1399		remote_add.sin_port = htons(remotePort);
1400		//get the server IP
1401		Host = gethostbyname(remoteHost);
1402		if (Host == NULL) return GF_IP_ADDRESS_NOT_FOUND;
1403		memcpy((char *) &remote_add.sin_addr, Host->h_addr_list[0], sizeof(u32));
1404	} else {
1405		remote_add.sin_port = sock->dest_addr.sin_port;
1406		remote_add.sin_addr.s_addr = sock->dest_addr.sin_addr.s_addr;
1407	}
1408#endif
1409	count = 0;
1410	while (count < length) {
1411		res = sendto(sock->socket, (char *) buffer+count, length - count, 0, (struct sockaddr *) &remote_add, remote_add_len);
1412		if (res == SOCKET_ERROR) {
1413			switch (LASTSOCKERROR) {
1414			case EAGAIN:
1415				return GF_IP_SOCK_WOULD_BLOCK;
1416			default:
1417				return GF_IP_NETWORK_FAILURE;
1418			}
1419		}
1420		count += res;
1421	}
1422	return GF_OK;
1423}
1424
1425
1426
1427
1428GF_Err gf_sk_receive_wait(GF_Socket *sock, char *buffer, u32 length, u32 startFrom, u32 *BytesRead, u32 Second )
1429{
1430	s32 res;
1431#ifndef __SYMBIAN32__
1432	s32 ready;
1433	struct timeval timeout;
1434	fd_set Group;
1435#endif
1436
1437	*BytesRead = 0;
1438	if (startFrom >= length) return GF_OK;
1439
1440#ifndef __SYMBIAN32__
1441	//can we read?
1442	FD_ZERO(&Group);
1443	FD_SET(sock->socket, &Group);
1444	timeout.tv_sec = Second;
1445	timeout.tv_usec = SOCK_MICROSEC_WAIT;
1446
1447	res = 0;
1448	//TODO - check if this is correct
1449	ready = select((int) sock->socket+1, &Group, NULL, NULL, &timeout);
1450	if (ready == SOCKET_ERROR) {
1451		switch (LASTSOCKERROR) {
1452		case EAGAIN:
1453			return GF_IP_SOCK_WOULD_BLOCK;
1454		default:
1455			return GF_IP_NETWORK_FAILURE;
1456		}
1457	}
1458	if (!FD_ISSET(sock->socket, &Group)) {
1459		return GF_IP_NETWORK_EMPTY;
1460	}
1461#endif
1462
1463
1464	res = recv(sock->socket, (char *) buffer + startFrom, length - startFrom, 0);
1465	if (res == SOCKET_ERROR) {
1466		switch (LASTSOCKERROR) {
1467		case EAGAIN:
1468			return GF_IP_SOCK_WOULD_BLOCK;
1469		default:
1470			return GF_IP_NETWORK_FAILURE;
1471		}
1472	}
1473	*BytesRead = res;
1474	return GF_OK;
1475}
1476
1477
1478//send length bytes of a buffer
1479GF_Err gf_sk_send_wait(GF_Socket *sock, const char *buffer, u32 length, u32 Second )
1480{
1481	u32 count;
1482	s32 res;
1483#ifndef __SYMBIAN32__
1484	s32 ready;
1485	struct timeval timeout;
1486	fd_set Group;
1487#endif
1488
1489	//the socket must be bound or connected
1490	if (!sock || !sock->socket) return GF_BAD_PARAM;
1491
1492#ifndef __SYMBIAN32__
1493	//can we write?
1494	FD_ZERO(&Group);
1495	FD_SET(sock->socket, &Group);
1496	timeout.tv_sec = Second;
1497	timeout.tv_usec = SOCK_MICROSEC_WAIT;
1498
1499	//TODO - check if this is correct
1500	ready = select((int) sock->socket+1, NULL, &Group, NULL, &timeout);
1501	if (ready == SOCKET_ERROR) {
1502		switch (LASTSOCKERROR) {
1503		case EAGAIN:
1504			return GF_IP_SOCK_WOULD_BLOCK;
1505		default:
1506			return GF_IP_NETWORK_FAILURE;
1507		}
1508	}
1509	//should never happen (to check: is writeability is guaranteed for not-connected sockets)
1510	if (!ready || !FD_ISSET(sock->socket, &Group)) {
1511		return GF_IP_NETWORK_EMPTY;
1512	}
1513#endif
1514
1515	//direct writing
1516	count = 0;
1517	while (count < length) {
1518		res = send(sock->socket, (char *) buffer+count, length - count, 0);
1519		if (res == SOCKET_ERROR) {
1520			switch (LASTSOCKERROR) {
1521			case EAGAIN:
1522				return GF_IP_SOCK_WOULD_BLOCK;
1523#ifndef __SYMBIAN32__
1524			case ECONNRESET:
1525				return GF_IP_CONNECTION_CLOSED;
1526#endif
1527			default:
1528				return GF_IP_NETWORK_FAILURE;
1529			}
1530		}
1531		count += res;
1532	}
1533	return GF_OK;
1534}
1535
1536