port.c 20.8 KB
Newer Older
aymeric's avatar
aymeric committed
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
 * Copyright (C) 2017 Belledonne Communications SARL
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
aymeric's avatar
aymeric committed
19 20


21
#ifdef HAVE_CONFIG_H
aymeric's avatar
aymeric committed
22 23
#include "ortp-config.h"
#endif
24
#include "ortp/logging.h"
aymeric's avatar
aymeric committed
25
#include "ortp/port.h"
26
#include "ortp/str_utils.h"
27
#include "utils.h"
28
#include <bctoolbox/port.h>
aymeric's avatar
aymeric committed
29 30 31 32 33

#if	defined(_WIN32) && !defined(_WIN32_WCE)
#include <process.h>
#endif

Simon Morlat's avatar
Simon Morlat committed
34 35 36 37
#ifdef HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif

aymeric's avatar
aymeric committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
static void *ortp_libc_malloc(size_t sz){
	return malloc(sz);
}

static void *ortp_libc_realloc(void *ptr, size_t sz){
	return realloc(ptr,sz);
}

static void ortp_libc_free(void*ptr){
	free(ptr);
}

static bool_t allocator_used=FALSE;

static OrtpMemoryFunctions ortp_allocator={
	ortp_libc_malloc,
	ortp_libc_realloc,
	ortp_libc_free
};

void ortp_set_memory_functions(OrtpMemoryFunctions *functions){
	if (allocator_used){
		ortp_fatal("ortp_set_memory_functions() must be called before "
		"first use of ortp_malloc or ortp_realloc");
		return;
	}
	ortp_allocator=*functions;
}

void* ortp_malloc(size_t sz){
	allocator_used=TRUE;
	return ortp_allocator.malloc_fun(sz);
}

void* ortp_realloc(void *ptr, size_t sz){
	allocator_used=TRUE;
	return ortp_allocator.realloc_fun(ptr,sz);
}

void ortp_free(void* ptr){
	ortp_allocator.free_fun(ptr);
}

void * ortp_malloc0(size_t size){
	void *ptr=ortp_malloc(size);
	memset(ptr,0,size);
	return ptr;
}

char * ortp_strdup(const char *tmp){
	size_t sz;
	char *ret;
	if (tmp==NULL)
	  return NULL;
	sz=strlen(tmp)+1;
	ret=(char*)ortp_malloc(sz);
	strcpy(ret,tmp);
	ret[sz-1]='\0';
	return ret;
}

/*
 * this method is an utility method that calls fnctl() on UNIX or
 * ioctlsocket on Win32.
 * int retrun the result of the system method
 */
104
int set_non_blocking_socket (ortp_socket_t sock){
aymeric's avatar
aymeric committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#if	!defined(_WIN32) && !defined(_WIN32_WCE)
	return fcntl (sock, F_SETFL, O_NONBLOCK);
#else
	unsigned long nonBlock = 1;
	return ioctlsocket(sock, FIONBIO , &nonBlock);
#endif
}


/*
 * this method is an utility method that calls close() on UNIX or
 * closesocket on Win32.
 * int retrun the result of the system method
 */
int close_socket(ortp_socket_t sock){
#if	!defined(_WIN32) && !defined(_WIN32_WCE)
	return close (sock);
#else
	return closesocket(sock);
#endif
}

127
#if defined (_WIN32_WCE) || defined(_MSC_VER)
Jehan Monnier's avatar
Jehan Monnier committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
int ortp_file_exist(const char *pathname) {
	FILE* fd;
	if (pathname==NULL) return -1;
	fd=fopen(pathname,"r");
	if (fd==NULL) {
		return -1;
	} else {
		fclose(fd);
		return 0;
	}
}
#else
int ortp_file_exist(const char *pathname) {
	return access(pathname,F_OK);
}
#endif /*_WIN32_WCE*/
aymeric's avatar
aymeric committed
144 145 146 147 148 149 150

#if	!defined(_WIN32) && !defined(_WIN32_WCE)
	/* Use UNIX inet_aton method */
#else
	int inet_aton (const char * cp, struct in_addr * addr)
	{
		unsigned long retval;
Jehan Monnier's avatar
Jehan Monnier committed
151

aymeric's avatar
aymeric committed
152 153
		retval = inet_addr (cp);

Jehan Monnier's avatar
Jehan Monnier committed
154
		if (retval == INADDR_NONE)
aymeric's avatar
aymeric committed
155 156 157 158 159 160 161 162 163 164 165 166 167 168
		{
			return -1;
		}
		else
		{
			addr->S_un.S_addr = retval;
			return 1;
		}
	}
#endif

char *ortp_strndup(const char *str,int n){
	int min=MIN((int)strlen(str),n)+1;
	char *ret=(char*)ortp_malloc(min);
169
	strncpy(ret,str,min);
aymeric's avatar
aymeric committed
170 171 172 173 174 175 176 177 178 179 180 181 182
	ret[min-1]='\0';
	return ret;
}

#if	!defined(_WIN32) && !defined(_WIN32_WCE)
int __ortp_thread_join(ortp_thread_t thread, void **ptr){
	int err=pthread_join(thread,ptr);
	if (err!=0) {
		ortp_error("pthread_join error: %s",strerror(err));
	}
	return err;
}

183
int __ortp_thread_create(ortp_thread_t *thread, pthread_attr_t *attr, void * (*routine)(void*), void *arg){
aymeric's avatar
aymeric committed
184 185 186 187 188 189 190 191 192 193 194
	pthread_attr_t my_attr;
	pthread_attr_init(&my_attr);
	if (attr)
		my_attr = *attr;
#ifdef ORTP_DEFAULT_THREAD_STACK_SIZE
	if (ORTP_DEFAULT_THREAD_STACK_SIZE!=0)
		pthread_attr_setstacksize(&my_attr, ORTP_DEFAULT_THREAD_STACK_SIZE);
#endif
	return pthread_create(thread, &my_attr, routine, arg);
}

195 196 197 198
unsigned long __ortp_thread_self(void) {
	return (unsigned long)pthread_self();
}

aymeric's avatar
aymeric committed
199 200 201 202
#endif
#if	defined(_WIN32) || defined(_WIN32_WCE)

int WIN_mutex_init(ortp_mutex_t *mutex, void *attr)
Jehan Monnier's avatar
Jehan Monnier committed
203
{
204
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
205
	*mutex=CreateMutex(NULL, FALSE, NULL);
206 207
#else
	InitializeSRWLock(mutex);
Ghislain MARY's avatar
Ghislain MARY committed
208
#endif
aymeric's avatar
aymeric committed
209 210 211 212 213
	return 0;
}

int WIN_mutex_lock(ortp_mutex_t * hMutex)
{
214
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
215
	WaitForSingleObject(*hMutex, INFINITE); /* == WAIT_TIMEOUT; */
216 217
#else
	AcquireSRWLockExclusive(hMutex);
Ghislain MARY's avatar
Ghislain MARY committed
218
#endif
aymeric's avatar
aymeric committed
219 220 221 222 223
	return 0;
}

int WIN_mutex_unlock(ortp_mutex_t * hMutex)
{
224
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
225
	ReleaseMutex(*hMutex);
226 227
#else
	ReleaseSRWLockExclusive(hMutex);
Ghislain MARY's avatar
Ghislain MARY committed
228
#endif
aymeric's avatar
aymeric committed
229 230 231 232 233
	return 0;
}

int WIN_mutex_destroy(ortp_mutex_t * hMutex)
{
234
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
235
	CloseHandle(*hMutex);
Ghislain MARY's avatar
Ghislain MARY committed
236
#endif
aymeric's avatar
aymeric committed
237 238 239 240 241 242 243 244 245 246
	return 0;
}

typedef struct thread_param{
	void * (*func)(void *);
	void * arg;
}thread_param_t;

static unsigned WINAPI thread_starter(void *data){
	thread_param_t *params=(thread_param_t*)data;
247
	params->func(params->arg);
aymeric's avatar
aymeric committed
248
	ortp_free(data);
249
	return 0;
aymeric's avatar
aymeric committed
250 251 252 253 254 255 256 257 258
}

#if defined _WIN32_WCE
#    define _beginthreadex	CreateThread
#    define	_endthreadex	ExitThread
#endif

int WIN_thread_create(ortp_thread_t *th, void *attr, void * (*func)(void *), void *data)
{
259 260 261
	thread_param_t *params=ortp_new(thread_param_t,1);
	params->func=func;
	params->arg=data;
262
	*th=(HANDLE)_beginthreadex( NULL, 0, thread_starter, params, 0, NULL);
aymeric's avatar
aymeric committed
263 264 265 266 267 268 269
	return 0;
}

int WIN_thread_join(ortp_thread_t thread_h, void **unused)
{
	if (thread_h!=NULL)
	{
270
		WaitForSingleObjectEx(thread_h, INFINITE, FALSE);
aymeric's avatar
aymeric committed
271 272 273 274 275
		CloseHandle(thread_h);
	}
	return 0;
}

276 277 278 279
unsigned long WIN_thread_self(void) {
	return (unsigned long)GetCurrentThreadId();
}

aymeric's avatar
aymeric committed
280 281
int WIN_cond_init(ortp_cond_t *cond, void *attr)
{
282
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
283
	*cond=CreateEvent(NULL, FALSE, FALSE, NULL);
284 285
#else
	InitializeConditionVariable(cond);
Ghislain MARY's avatar
Ghislain MARY committed
286
#endif
aymeric's avatar
aymeric committed
287 288 289 290 291
	return 0;
}

int WIN_cond_wait(ortp_cond_t* hCond, ortp_mutex_t * hMutex)
{
292
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
293
	//gulp: this is not very atomic ! bug here ?
Jehan Monnier's avatar
Jehan Monnier committed
294
	WIN_mutex_unlock(hMutex);
aymeric's avatar
aymeric committed
295 296
	WaitForSingleObject(*hCond, INFINITE);
	WIN_mutex_lock(hMutex);
297 298
#else
	SleepConditionVariableSRW(hCond, hMutex, INFINITE, 0);
Ghislain MARY's avatar
Ghislain MARY committed
299
#endif
aymeric's avatar
aymeric committed
300 301 302 303 304
	return 0;
}

int WIN_cond_signal(ortp_cond_t * hCond)
{
305
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
306
	SetEvent(*hCond);
307 308
#else
	WakeConditionVariable(hCond);
Ghislain MARY's avatar
Ghislain MARY committed
309
#endif
aymeric's avatar
aymeric committed
310 311 312 313 314 315 316 317 318 319 320
	return 0;
}

int WIN_cond_broadcast(ortp_cond_t * hCond)
{
	WIN_cond_signal(hCond);
	return 0;
}

int WIN_cond_destroy(ortp_cond_t * hCond)
{
321
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
322
	CloseHandle(*hCond);
Ghislain MARY's avatar
Ghislain MARY committed
323
#endif
aymeric's avatar
aymeric committed
324 325 326 327 328 329
	return 0;
}

#if defined(_WIN32_WCE)
#include <time.h>

Jehan Monnier's avatar
Jehan Monnier committed
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
const char * ortp_strerror(DWORD value) {
	static TCHAR msgBuf[256];
	FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			value,
			0, // Default language
			(LPTSTR) &msgBuf,
			0,
			NULL
	);
	return (const char *)msgBuf;
}

aymeric's avatar
aymeric committed
345 346 347 348 349 350 351 352 353 354 355
int
gettimeofday (struct timeval *tv, void *tz)
{
  DWORD timemillis = GetTickCount();
  tv->tv_sec  = timemillis/1000;
  tv->tv_usec = (timemillis - (tv->tv_sec*1000)) * 1000;
  return 0;
}

#else

356
int ortp_gettimeofday (struct timeval *tv, void* tz)
Jehan Monnier's avatar
Jehan Monnier committed
357 358 359 360 361 362
{
	union
	{
		__int64 ns100; /*time since 1 Jan 1601 in 100ns units */
		FILETIME fileTime;
	} now;
aymeric's avatar
aymeric committed
363

Jehan Monnier's avatar
Jehan Monnier committed
364 365 366 367 368
	GetSystemTimeAsFileTime (&now.fileTime);
	tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
	tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL);
	return (0);
}
aymeric's avatar
aymeric committed
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402

#endif

const char *getWinSocketError(int error)
{
	static char buf[80];

	switch (error)
	{
		case WSANOTINITIALISED: return "Windows sockets not initialized : call WSAStartup";
		case WSAEADDRINUSE:		return "Local Address already in use";
		case WSAEADDRNOTAVAIL:	return "The specified address is not a valid address for this machine";
		case WSAEINVAL:			return "The socket is already bound to an address.";
		case WSAENOBUFS:		return "Not enough buffers available, too many connections.";
		case WSAENOTSOCK:		return "The descriptor is not a socket.";
		case WSAECONNRESET:		return "Connection reset by peer";

		default :
			sprintf(buf, "Error code : %d", error);
			return buf;
		break;
	}

	return buf;
}

#ifdef _WORKAROUND_MINGW32_BUGS
char * WSAAPI gai_strerror(int errnum){
	 return (char*)getWinSocketError(errnum);
}
#endif

#endif

403
#ifndef _WIN32
404 405 406 407 408 409

#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/stat.h>

410 411 412 413
static char *make_pipe_name(const char *name){
	return ortp_strdup_printf("/tmp/%s",name);
}

414 415 416
/* portable named pipes */
ortp_socket_t ortp_server_pipe_create(const char *name){
	struct sockaddr_un sa;
417
	char *pipename=make_pipe_name(name);
418 419 420
	ortp_socket_t sock;
	sock=socket(AF_UNIX,SOCK_STREAM,0);
	sa.sun_family=AF_UNIX;
421 422 423
	strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
	unlink(pipename);/*in case we didn't finished properly previous time */
	ortp_free(pipename);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
	fchmod(sock,S_IRUSR|S_IWUSR);
	if (bind(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
		ortp_error("Failed to bind command unix socket: %s",strerror(errno));
		return -1;
	}
	listen(sock,1);
	return sock;
}

ortp_socket_t ortp_server_pipe_accept_client(ortp_socket_t server){
	struct sockaddr_un su;
	socklen_t ssize=sizeof(su);
	ortp_socket_t client_sock=accept(server,(struct sockaddr*)&su,&ssize);
	return client_sock;
}

int ortp_server_pipe_close_client(ortp_socket_t client){
	return close(client);
}

int ortp_server_pipe_close(ortp_socket_t spipe){
Simon Morlat's avatar
Simon Morlat committed
445 446 447 448 449 450 451 452
	struct sockaddr_un sa;
	socklen_t len=sizeof(sa);
	int err;
	/*this is to retrieve the name of the pipe, in order to unlink the file*/
	err=getsockname(spipe,(struct sockaddr*)&sa,&len);
	if (err==0){
		unlink(sa.sun_path);
	}else ortp_error("getsockname(): %s",strerror(errno));
453 454 455 456
	return close(spipe);
}

ortp_socket_t ortp_client_pipe_connect(const char *name){
457
	ortp_socket_t sock = -1;
458
	struct sockaddr_un sa;
459
	struct stat fstats;
460
	char *pipename=make_pipe_name(name);
461 462 463 464
	uid_t uid = getuid();

	// check that the creator of the pipe is us
	if( (stat(name, &fstats) == 0) && (fstats.st_uid != uid) ){
465
		ortp_error("UID of file %s (%lu) differs from ours (%lu)", pipename, (unsigned long)fstats.st_uid, (unsigned long)uid);
466 467 468 469
		return -1;
	}

	sock = socket(AF_UNIX,SOCK_STREAM,0);
470
	sa.sun_family=AF_UNIX;
471 472
	strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
	ortp_free(pipename);
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
	if (connect(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
		close(sock);
		return -1;
	}
	return sock;
}

int ortp_pipe_read(ortp_socket_t p, uint8_t *buf, int len){
	return read(p,buf,len);
}

int ortp_pipe_write(ortp_socket_t p, const uint8_t *buf, int len){
	return write(p,buf,len);
}

int ortp_client_pipe_close(ortp_socket_t sock){
	return close(sock);
}

Simon Morlat's avatar
Simon Morlat committed
492 493 494 495 496
#ifdef HAVE_SYS_SHM_H

void *ortp_shm_open(unsigned int keyid, int size, int create){
	key_t key=keyid;
	void *mem;
497 498
	int perms=S_IRUSR|S_IWUSR;
	int fd=shmget(key,size,create ? (IPC_CREAT | perms ) : perms);
Simon Morlat's avatar
Simon Morlat committed
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
	if (fd==-1){
		printf("shmget failed: %s\n",strerror(errno));
		return NULL;
	}
	mem=shmat(fd,NULL,0);
	if (mem==(void*)-1){
		printf("shmat() failed: %s", strerror(errno));
		return NULL;
	}
	return mem;
}

void ortp_shm_close(void *mem){
	shmdt(mem);
}

#endif
Jehan Monnier's avatar
Jehan Monnier committed
516

517
#elif defined(_WIN32) && !defined(_WIN32_WCE)
518 519 520 521 522 523 524

static char *make_pipe_name(const char *name){
	return ortp_strdup_printf("\\\\.\\pipe\\%s",name);
}

static HANDLE event=NULL;

525
/* portable named pipes */
526
ortp_pipe_t ortp_server_pipe_create(const char *name){
527
#ifdef ORTP_WINDOWS_DESKTOP
528 529 530 531 532 533 534 535 536 537
	ortp_pipe_t h;
	char *pipename=make_pipe_name(name);
	h=CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_MESSAGE|PIPE_WAIT,1,
						32768,32768,0,NULL);
	ortp_free(pipename);
	if (h==INVALID_HANDLE_VALUE){
		ortp_error("Fail to create named pipe %s",pipename);
	}
	if (event==NULL) event=CreateEvent(NULL,TRUE,FALSE,NULL);
	return h;
538 539 540
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return INVALID_HANDLE_VALUE;
Ghislain MARY's avatar
Ghislain MARY committed
541
#endif
542 543 544 545 546 547 548 549
}


/*this function is a bit complex because we need to wakeup someday
even if nobody connects to the pipe.
ortp_server_pipe_close() makes this function to exit.
*/
ortp_pipe_t ortp_server_pipe_accept_client(ortp_pipe_t server){
550
#ifdef ORTP_WINDOWS_DESKTOP
551 552
	OVERLAPPED ol;
	DWORD undef;
553
	HANDLE handles[2];
554
	memset(&ol,0,sizeof(ol));
555
	ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
556
	ConnectNamedPipe(server,&ol);
557 558 559
	handles[0]=ol.hEvent;
	handles[1]=event;
	WaitForMultipleObjects(2,handles,FALSE,INFINITE);
560
	if (GetOverlappedResult(server,&ol,&undef,FALSE)){
561
		CloseHandle(ol.hEvent);
562 563
		return server;
	}
564
	CloseHandle(ol.hEvent);
565
	return INVALID_HANDLE_VALUE;
566 567 568
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return INVALID_HANDLE_VALUE;
Ghislain MARY's avatar
Ghislain MARY committed
569
#endif
570
}
571

572
int ortp_server_pipe_close_client(ortp_pipe_t server){
573
#ifdef ORTP_WINDOWS_DESKTOP
574 575
	return DisconnectNamedPipe(server)==TRUE ? 0 : -1;
#else
Ghislain MARY's avatar
Ghislain MARY committed
576 577 578
	ortp_error("%s not supported!", __FUNCTION__);
	return -1;
#endif
579 580 581
}

int ortp_server_pipe_close(ortp_pipe_t spipe){
582
#ifdef ORTP_WINDOWS_DESKTOP
583 584 585
	SetEvent(event);
	//CancelIoEx(spipe,NULL); /*vista only*/
	return CloseHandle(spipe);
586 587 588
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return -1;
Ghislain MARY's avatar
Ghislain MARY committed
589
#endif
590 591 592
}

ortp_pipe_t ortp_client_pipe_connect(const char *name){
593
#ifdef ORTP_WINDOWS_DESKTOP
594
	char *pipename=make_pipe_name(name);
Jehan Monnier's avatar
Jehan Monnier committed
595
	ortp_pipe_t hpipe = CreateFile(
596 597 598 599 600 601 602 603
		 pipename,   // pipe name
		 GENERIC_READ |  // read and write access
		 GENERIC_WRITE,
		 0,              // no sharing
		 NULL,           // default security attributes
		 OPEN_EXISTING,  // opens existing pipe
		 0,              // default attributes
		 NULL);          // no template file
604 605
	ortp_free(pipename);
	return hpipe;
606 607 608
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return INVALID_HANDLE_VALUE;
Ghislain MARY's avatar
Ghislain MARY committed
609
#endif
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
}

int ortp_pipe_read(ortp_pipe_t p, uint8_t *buf, int len){
	DWORD ret=0;
	if (ReadFile(p,buf,len,&ret,NULL))
		return ret;
	/*ortp_error("Could not read from pipe: %s",strerror(GetLastError()));*/
	return -1;
}

int ortp_pipe_write(ortp_pipe_t p, const uint8_t *buf, int len){
	DWORD ret=0;
	if (WriteFile(p,buf,len,&ret,NULL))
		return ret;
	/*ortp_error("Could not write to pipe: %s",strerror(GetLastError()));*/
	return -1;
}


int ortp_client_pipe_close(ortp_pipe_t sock){
	return CloseHandle(sock);
}
632

633 634 635 636 637 638 639 640 641

typedef struct MapInfo{
	HANDLE h;
	void *mem;
}MapInfo;

static OList *maplist=NULL;

void *ortp_shm_open(unsigned int keyid, int size, int create){
642
#ifdef ORTP_WINDOWS_DESKTOP
643 644 645 646 647 648
	HANDLE h;
	char name[64];
	void *buf;

	snprintf(name,sizeof(name),"%x",keyid);
	if (create){
649 650
		h = CreateFileMapping(
			INVALID_HANDLE_VALUE,    // use paging file
651
			NULL,                    // default security
652
			PAGE_READWRITE,          // read/write access
653 654
			0,                       // maximum object size (high-order DWORD)
			size,                // maximum object size (low-order DWORD)
655 656
			name);                 // name of mapping object
	}else{
657 658
		h = OpenFileMapping(
			FILE_MAP_ALL_ACCESS,   // read/write access
659
			FALSE,                 // do not inherit the name
660
			name);               // name of mapping object
661 662 663 664 665
	}
	if (h==(HANDLE)-1) {
		ortp_error("Fail to open file mapping (create=%i)",create);
		return NULL;
	}
666 667
	buf = (LPTSTR) MapViewOfFile(h, // handle to map object
		FILE_MAP_ALL_ACCESS,  // read/write permission
668 669
		0,
		0,
670 671 672 673 674 675 676 677 678 679 680
		size);
	if (buf!=NULL){
		MapInfo *i=(MapInfo*)ortp_new(MapInfo,1);
		i->h=h;
		i->mem=buf;
		maplist=o_list_append(maplist,i);
	}else{
		CloseHandle(h);
		ortp_error("MapViewOfFile failed");
	}
	return buf;
681 682 683
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return NULL;
Ghislain MARY's avatar
Ghislain MARY committed
684
#endif
Simon Morlat's avatar
Simon Morlat committed
685 686 687
}

void ortp_shm_close(void *mem){
688
#ifdef ORTP_WINDOWS_DESKTOP
689 690 691 692 693 694 695 696 697 698 699 700
	OList *elem;
	for(elem=maplist;elem!=NULL;elem=elem->next){
		MapInfo *i=(MapInfo*)elem->data;
		if (i->mem==mem){
			CloseHandle(i->h);
			UnmapViewOfFile(mem);
			ortp_free(i);
			maplist=o_list_remove_link(maplist,elem);
			return;
		}
	}
	ortp_error("No shared memory at %p was found.",mem);
701 702
#else
	ortp_error("%s not supported!", __FUNCTION__);
Ghislain MARY's avatar
Ghislain MARY committed
703
#endif
Simon Morlat's avatar
Simon Morlat committed
704
}
Jehan Monnier's avatar
Jehan Monnier committed
705

706

707
#endif
708 709 710 711 712 713 714


#ifdef __MACH__
#include <sys/types.h>
#include <sys/timeb.h>
#endif

715
void _ortp_get_cur_time(ortpTimeSpec *ret, bool_t realtime){
716
#if defined(_WIN32_WCE) || defined(_WIN32)
717
#ifdef ORTP_WINDOWS_DESKTOP
718 719 720 721 722 723 724 725
	DWORD timemillis;
#	if defined(_WIN32_WCE)
	timemillis=GetTickCount();
#	else
	timemillis=timeGetTime();
#	endif
	ret->tv_sec=timemillis/1000;
	ret->tv_nsec=(timemillis%1000)*1000000LL;
726 727 728 729
#else
	ULONGLONG timemillis = GetTickCount64();
	ret->tv_sec = timemillis / 1000;
	ret->tv_nsec = (timemillis % 1000) * 1000000LL;
Ghislain MARY's avatar
Ghislain MARY committed
730
#endif
731 732 733 734 735 736 737 738 739 740 741 742 743
#elif defined(__MACH__) && defined(__GNUC__) && (__GNUC__ >= 3)
	struct timeval tv;
	gettimeofday(&tv, NULL);
	ret->tv_sec=tv.tv_sec;
	ret->tv_nsec=tv.tv_usec*1000LL;
#elif defined(__MACH__)
	struct timeb time_val;

	ftime (&time_val);
	ret->tv_sec = time_val.time;
	ret->tv_nsec = time_val.millitm * 1000000LL;
#else
	struct timespec ts;
744
	if (clock_gettime(realtime ? CLOCK_REALTIME : CLOCK_MONOTONIC,&ts)<0){
745 746 747 748 749 750
		ortp_fatal("clock_gettime() doesn't work: %s",strerror(errno));
	}
	ret->tv_sec=ts.tv_sec;
	ret->tv_nsec=ts.tv_nsec;
#endif
}
751

752
void ortp_get_cur_time(ortpTimeSpec *ret){
753
	_ortp_get_cur_time(ret, FALSE);
754 755 756
}


757 758 759 760 761 762
uint64_t ortp_get_cur_time_ms(void) {
	ortpTimeSpec ts;
	ortp_get_cur_time(&ts);
	return (ts.tv_sec * 1000LL) + ((ts.tv_nsec + 500000LL) / 1000000LL);
}

763
void ortp_sleep_ms(int ms){
764 765
#ifdef _WIN32
#ifdef ORTP_WINDOWS_DESKTOP
766 767 768 769 770 771 772 773 774
	Sleep(ms);
#else
	HANDLE sleepEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
	if (!sleepEvent) return;
	WaitForSingleObjectEx(sleepEvent, ms, FALSE);
	CloseHandle(sleepEvent);
#endif
#else
	struct timespec ts;
775 776
	ts.tv_sec=ms/1000;
	ts.tv_nsec=(ms%1000)*1000000LL;
777 778 779 780 781 782 783 784 785 786 787 788 789 790
	nanosleep(&ts,NULL);
#endif
}

void ortp_sleep_until(const ortpTimeSpec *ts){
#ifdef __linux
	struct timespec rq;
	rq.tv_sec=ts->tv_sec;
	rq.tv_nsec=ts->tv_nsec;
	while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &rq, NULL)==-1 && errno==EINTR){
	}
#else
	ortpTimeSpec current;
	ortpTimeSpec diff;
791
	_ortp_get_cur_time(&current, TRUE);
792 793 794 795 796 797
	diff.tv_sec=ts->tv_sec-current.tv_sec;
	diff.tv_nsec=ts->tv_nsec-current.tv_nsec;
	if (diff.tv_nsec<0){
		diff.tv_nsec+=1000000000LL;
		diff.tv_sec-=1;
	}
798
#ifdef _WIN32
799
		ortp_sleep_ms((int)((diff.tv_sec * 1000LL) + (diff.tv_nsec/1000000LL)));
800
#else
801 802 803 804 805 806 807 808
	{
		struct timespec dur,rem;
		dur.tv_sec=diff.tv_sec;
		dur.tv_nsec=diff.tv_nsec;
		while (nanosleep(&dur,&rem)==-1 && errno==EINTR){
			dur=rem;
		};
	}
809
#endif
810 811 812
#endif
}

813 814
#if defined(_WIN32) && !defined(_MSC_VER)
char* strtok_r(char *str, const char *delim, char **nextp){
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
	char *ret;

	if (str == NULL){
		str = *nextp;
	}
	str += strspn(str, delim);
	if (*str == '\0'){
		return NULL;
	}
	ret = str;
	str += strcspn(str, delim);
	if (*str){
		*str++ = '\0';
	}
	*nextp = str;
	return ret;
831 832
}
#endif
833 834


Simon Morlat's avatar
Simon Morlat committed
835 836 837
#if defined(_WIN32)

#if !defined(_MSC_VER)
838 839 840 841
#include <wincrypt.h>
static int ortp_wincrypto_random(unsigned int *rand_number){
	static HCRYPTPROV hProv=(HCRYPTPROV)-1;
	static int initd=0;
842

843 844 845 846 847 848 849 850 851
	if (!initd){
		if (!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
			ortp_error("ortp_wincrypto_random(): Could not acquire a windows crypto context");
			return -1;
		}
		initd=TRUE;
	}
	if (hProv==(HCRYPTPROV)-1)
		return -1;
852

853 854 855 856 857 858 859
	if (!CryptGenRandom(hProv,4,(BYTE*)rand_number)){
		ortp_error("ortp_wincrypto_random(): CryptGenRandom() failed.");
		return -1;
	}
	return 0;
}
#endif
Ghislain MARY's avatar
Ghislain MARY committed
860
#elif defined(__QNXNTO__) || ((defined(__linux) || defined(__APPLE__)) && !defined(HAVE_ARC4RANDOM))
861

Sylvain Berfini's avatar
Sylvain Berfini committed
862 863
static unsigned int ortp_urandom(void) {
	static int fd=-1;
Simon Morlat's avatar
Simon Morlat committed
864 865 866 867 868 869 870
	if (fd==-1) fd=open("/dev/urandom",O_RDONLY);
	if (fd!=-1){
		unsigned int tmp;
		if (read(fd,&tmp,4)!=4){
			ortp_error("Reading /dev/urandom failed.");
		}else return tmp;
	} else ortp_error("Could not open /dev/urandom");
Sylvain Berfini's avatar
Sylvain Berfini committed
871 872 873
	return (unsigned int) random();
}

Simon Morlat's avatar
Simon Morlat committed
874 875 876 877 878
#endif




879 880
unsigned int ortp_random(void){
#ifdef HAVE_ARC4RANDOM
Sylvain Berfini's avatar
Sylvain Berfini committed
881 882 883
#if defined(__QNXNTO__) // There is a false positive with blackberry build
	return ortp_urandom();
#else
884
	return arc4random();
Sylvain Berfini's avatar
Sylvain Berfini committed
885
#endif
886
#elif defined(__linux) || defined(__APPLE__)
Sylvain Berfini's avatar
Sylvain Berfini committed
887
	return ortp_urandom();
888
#elif defined(_WIN32)
889 890 891 892
	static int initd=0;
	unsigned int ret;
#ifdef _MSC_VER
	/*rand_s() is pretty nice and simple function but is not wrapped by mingw.*/
893

894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
	if (rand_s(&ret)==0){
		return ret;
	}
#else
	if (ortp_wincrypto_random(&ret)==0){
		return ret;
	}
#endif
	/* Windows's rand() is unsecure but is used as a fallback*/
	if (!initd) {
		struct timeval tv;
		ortp_gettimeofday(&tv,NULL);
		srand((unsigned int)tv.tv_sec+tv.tv_usec);
		initd=1;
		ortp_warning("ortp: Random generator is using rand(), this is unsecure !");
	}
	return rand()<<16 | rand();
#endif
}
Simon Morlat's avatar
Simon Morlat committed
913

914
bool_t ortp_is_multicast_addr(const struct sockaddr *addr) {
915

916 917 918 919 920 921 922 923
	switch (addr->sa_family) {
		case AF_INET:
			return IN_MULTICAST(ntohl(((struct sockaddr_in *) addr)->sin_addr.s_addr));
		case AF_INET6:
			return IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) addr)->sin6_addr));
		default:
			return FALSE;
	}
924

925
}