PageRenderTime 98ms CodeModel.GetById 2ms app.highlight 86ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/gpac/src/utils/os_net.c

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