port.c 20.5 KB
Newer Older
aymeric's avatar
aymeric committed
1
/*
2
 * Copyright (c) 2010-2019 Belledonne Communications SARL.
3
 *
4
 * This file is part of oRTP.
5
 *
6 7 8 9
 * 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 3 of the License, or
 * (at your option) any later version.
10
 *
11 12 13 14 15 16 17
 * 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, see <http://www.gnu.org/licenses/>.
18
 */
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

#if	!defined(_WIN32) && !defined(_WIN32_WCE)
	/* Use UNIX inet_aton method */
#else
	int inet_aton (const char * cp, struct in_addr * addr)
	{
Simon Morlat's avatar
Simon Morlat committed
150 151 152 153 154
		int retval;

		retval = inet_pton (AF_INET, cp, addr);

		return retval == 1 ? 1 : 0;
aymeric's avatar
aymeric committed
155 156 157 158 159 160
	}
#endif

char *ortp_strndup(const char *str,int n){
	int min=MIN((int)strlen(str),n)+1;
	char *ret=(char*)ortp_malloc(min);
161
	strncpy(ret,str,min);
aymeric's avatar
aymeric committed
162 163 164 165 166 167 168 169 170 171 172 173 174
	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;
}

175
int __ortp_thread_create(ortp_thread_t *thread, pthread_attr_t *attr, void * (*routine)(void*), void *arg){
aymeric's avatar
aymeric committed
176 177 178 179 180 181 182 183 184 185 186
	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);
}

187 188 189 190
unsigned long __ortp_thread_self(void) {
	return (unsigned long)pthread_self();
}

aymeric's avatar
aymeric committed
191 192 193 194
#endif
#if	defined(_WIN32) || defined(_WIN32_WCE)

int WIN_mutex_init(ortp_mutex_t *mutex, void *attr)
Jehan Monnier's avatar
Jehan Monnier committed
195
{
196
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
197
	*mutex=CreateMutex(NULL, FALSE, NULL);
198 199
#else
	InitializeSRWLock(mutex);
Ghislain MARY's avatar
Ghislain MARY committed
200
#endif
aymeric's avatar
aymeric committed
201 202 203 204 205
	return 0;
}

int WIN_mutex_lock(ortp_mutex_t * hMutex)
{
206
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
207
	WaitForSingleObject(*hMutex, INFINITE); /* == WAIT_TIMEOUT; */
208 209
#else
	AcquireSRWLockExclusive(hMutex);
Ghislain MARY's avatar
Ghislain MARY committed
210
#endif
aymeric's avatar
aymeric committed
211 212 213 214 215
	return 0;
}

int WIN_mutex_unlock(ortp_mutex_t * hMutex)
{
216
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
217
	ReleaseMutex(*hMutex);
218 219
#else
	ReleaseSRWLockExclusive(hMutex);
Ghislain MARY's avatar
Ghislain MARY committed
220
#endif
aymeric's avatar
aymeric committed
221 222 223 224 225
	return 0;
}

int WIN_mutex_destroy(ortp_mutex_t * hMutex)
{
226
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
227
	CloseHandle(*hMutex);
Ghislain MARY's avatar
Ghislain MARY committed
228
#endif
aymeric's avatar
aymeric committed
229 230 231 232 233 234 235 236 237 238
	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;
239
	params->func(params->arg);
aymeric's avatar
aymeric committed
240
	ortp_free(data);
241
	return 0;
aymeric's avatar
aymeric committed
242 243 244 245 246 247 248 249 250
}

#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)
{
251 252 253
	thread_param_t *params=ortp_new(thread_param_t,1);
	params->func=func;
	params->arg=data;
254
	*th=(HANDLE)_beginthreadex( NULL, 0, thread_starter, params, 0, NULL);
aymeric's avatar
aymeric committed
255 256 257 258 259 260 261
	return 0;
}

int WIN_thread_join(ortp_thread_t thread_h, void **unused)
{
	if (thread_h!=NULL)
	{
262
		WaitForSingleObjectEx(thread_h, INFINITE, FALSE);
aymeric's avatar
aymeric committed
263 264 265 266 267
		CloseHandle(thread_h);
	}
	return 0;
}

268 269 270 271
unsigned long WIN_thread_self(void) {
	return (unsigned long)GetCurrentThreadId();
}

aymeric's avatar
aymeric committed
272 273
int WIN_cond_init(ortp_cond_t *cond, void *attr)
{
274
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
275
	*cond=CreateEvent(NULL, FALSE, FALSE, NULL);
276 277
#else
	InitializeConditionVariable(cond);
Ghislain MARY's avatar
Ghislain MARY committed
278
#endif
aymeric's avatar
aymeric committed
279 280 281 282 283
	return 0;
}

int WIN_cond_wait(ortp_cond_t* hCond, ortp_mutex_t * hMutex)
{
284
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
285
	//gulp: this is not very atomic ! bug here ?
Jehan Monnier's avatar
Jehan Monnier committed
286
	WIN_mutex_unlock(hMutex);
aymeric's avatar
aymeric committed
287 288
	WaitForSingleObject(*hCond, INFINITE);
	WIN_mutex_lock(hMutex);
289 290
#else
	SleepConditionVariableSRW(hCond, hMutex, INFINITE, 0);
Ghislain MARY's avatar
Ghislain MARY committed
291
#endif
aymeric's avatar
aymeric committed
292 293 294 295 296
	return 0;
}

int WIN_cond_signal(ortp_cond_t * hCond)
{
297
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
298
	SetEvent(*hCond);
299 300
#else
	WakeConditionVariable(hCond);
Ghislain MARY's avatar
Ghislain MARY committed
301
#endif
aymeric's avatar
aymeric committed
302 303 304 305 306 307 308 309 310 311 312
	return 0;
}

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

int WIN_cond_destroy(ortp_cond_t * hCond)
{
313
#ifdef ORTP_WINDOWS_DESKTOP
aymeric's avatar
aymeric committed
314
	CloseHandle(*hCond);
Ghislain MARY's avatar
Ghislain MARY committed
315
#endif
aymeric's avatar
aymeric committed
316 317 318 319 320 321
	return 0;
}

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

Jehan Monnier's avatar
Jehan Monnier committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
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
337 338 339 340 341 342 343 344 345 346 347
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

348
int ortp_gettimeofday (struct timeval *tv, void* tz)
Jehan Monnier's avatar
Jehan Monnier committed
349 350 351 352 353 354
{
	union
	{
		__int64 ns100; /*time since 1 Jan 1601 in 100ns units */
		FILETIME fileTime;
	} now;
aymeric's avatar
aymeric committed
355

Jehan Monnier's avatar
Jehan Monnier committed
356 357 358 359 360
	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
361 362 363 364 365 366 367 368 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

#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

395
#ifndef _WIN32
396 397 398 399 400 401

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

402 403 404 405
static char *make_pipe_name(const char *name){
	return ortp_strdup_printf("/tmp/%s",name);
}

406 407 408
/* portable named pipes */
ortp_socket_t ortp_server_pipe_create(const char *name){
	struct sockaddr_un sa;
409
	char *pipename=make_pipe_name(name);
410 411 412
	ortp_socket_t sock;
	sock=socket(AF_UNIX,SOCK_STREAM,0);
	sa.sun_family=AF_UNIX;
413 414 415
	strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
	unlink(pipename);/*in case we didn't finished properly previous time */
	ortp_free(pipename);
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
	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
437 438 439 440 441 442 443 444
	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));
445 446 447 448
	return close(spipe);
}

ortp_socket_t ortp_client_pipe_connect(const char *name){
449
	ortp_socket_t sock = -1;
450
	struct sockaddr_un sa;
451
	struct stat fstats;
452
	char *pipename=make_pipe_name(name);
453 454 455 456
	uid_t uid = getuid();

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

	sock = socket(AF_UNIX,SOCK_STREAM,0);
462
	sa.sun_family=AF_UNIX;
463 464
	strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
	ortp_free(pipename);
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
	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
484 485 486 487 488
#ifdef HAVE_SYS_SHM_H

void *ortp_shm_open(unsigned int keyid, int size, int create){
	key_t key=keyid;
	void *mem;
489 490
	int perms=S_IRUSR|S_IWUSR;
	int fd=shmget(key,size,create ? (IPC_CREAT | perms ) : perms);
Simon Morlat's avatar
Simon Morlat committed
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
	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
508

509
#elif defined(_WIN32) && !defined(_WIN32_WCE)
510 511 512 513 514 515 516

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

static HANDLE event=NULL;

517
/* portable named pipes */
518
ortp_pipe_t ortp_server_pipe_create(const char *name){
519
#ifdef ORTP_WINDOWS_DESKTOP
520 521 522 523 524 525 526 527 528 529
	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;
530 531 532
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return INVALID_HANDLE_VALUE;
Ghislain MARY's avatar
Ghislain MARY committed
533
#endif
534 535 536 537 538 539 540 541
}


/*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){
542
#ifdef ORTP_WINDOWS_DESKTOP
543 544
	OVERLAPPED ol;
	DWORD undef;
545
	HANDLE handles[2];
546
	memset(&ol,0,sizeof(ol));
547
	ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
548
	ConnectNamedPipe(server,&ol);
549 550 551
	handles[0]=ol.hEvent;
	handles[1]=event;
	WaitForMultipleObjects(2,handles,FALSE,INFINITE);
552
	if (GetOverlappedResult(server,&ol,&undef,FALSE)){
553
		CloseHandle(ol.hEvent);
554 555
		return server;
	}
556
	CloseHandle(ol.hEvent);
557
	return INVALID_HANDLE_VALUE;
558 559 560
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return INVALID_HANDLE_VALUE;
Ghislain MARY's avatar
Ghislain MARY committed
561
#endif
562
}
563

564
int ortp_server_pipe_close_client(ortp_pipe_t server){
565
#ifdef ORTP_WINDOWS_DESKTOP
566 567
	return DisconnectNamedPipe(server)==TRUE ? 0 : -1;
#else
Ghislain MARY's avatar
Ghislain MARY committed
568 569 570
	ortp_error("%s not supported!", __FUNCTION__);
	return -1;
#endif
571 572 573
}

int ortp_server_pipe_close(ortp_pipe_t spipe){
574
#ifdef ORTP_WINDOWS_DESKTOP
575 576 577
	SetEvent(event);
	//CancelIoEx(spipe,NULL); /*vista only*/
	return CloseHandle(spipe);
578 579 580
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return -1;
Ghislain MARY's avatar
Ghislain MARY committed
581
#endif
582 583 584
}

ortp_pipe_t ortp_client_pipe_connect(const char *name){
585
#ifdef ORTP_WINDOWS_DESKTOP
586
	char *pipename=make_pipe_name(name);
Jehan Monnier's avatar
Jehan Monnier committed
587
	ortp_pipe_t hpipe = CreateFile(
588 589 590 591 592 593 594 595
		 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
596 597
	ortp_free(pipename);
	return hpipe;
598 599 600
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return INVALID_HANDLE_VALUE;
Ghislain MARY's avatar
Ghislain MARY committed
601
#endif
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
}

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);
}
624

625 626 627 628 629 630 631 632 633

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

static OList *maplist=NULL;

void *ortp_shm_open(unsigned int keyid, int size, int create){
634
#ifdef ORTP_WINDOWS_DESKTOP
635 636 637 638 639 640
	HANDLE h;
	char name[64];
	void *buf;

	snprintf(name,sizeof(name),"%x",keyid);
	if (create){
641 642
		h = CreateFileMapping(
			INVALID_HANDLE_VALUE,    // use paging file
643
			NULL,                    // default security
644
			PAGE_READWRITE,          // read/write access
645 646
			0,                       // maximum object size (high-order DWORD)
			size,                // maximum object size (low-order DWORD)
647 648
			name);                 // name of mapping object
	}else{
649 650
		h = OpenFileMapping(
			FILE_MAP_ALL_ACCESS,   // read/write access
651
			FALSE,                 // do not inherit the name
652
			name);               // name of mapping object
653 654 655 656 657
	}
	if (h==(HANDLE)-1) {
		ortp_error("Fail to open file mapping (create=%i)",create);
		return NULL;
	}
658 659
	buf = (LPTSTR) MapViewOfFile(h, // handle to map object
		FILE_MAP_ALL_ACCESS,  // read/write permission
660 661
		0,
		0,
662 663 664 665 666 667 668 669 670 671 672
		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;
673 674 675
#else
	ortp_error("%s not supported!", __FUNCTION__);
	return NULL;
Ghislain MARY's avatar
Ghislain MARY committed
676
#endif
Simon Morlat's avatar
Simon Morlat committed
677 678 679
}

void ortp_shm_close(void *mem){
680
#ifdef ORTP_WINDOWS_DESKTOP
681 682 683 684 685 686 687 688 689 690 691 692
	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);
693 694
#else
	ortp_error("%s not supported!", __FUNCTION__);
Ghislain MARY's avatar
Ghislain MARY committed
695
#endif
Simon Morlat's avatar
Simon Morlat committed
696
}
Jehan Monnier's avatar
Jehan Monnier committed
697

698

699
#endif
700 701 702 703 704 705 706


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

707
void _ortp_get_cur_time(ortpTimeSpec *ret, bool_t realtime){
708
#if defined(_WIN32_WCE) || defined(_WIN32)
709
#ifdef ORTP_WINDOWS_DESKTOP
710 711 712 713 714 715 716 717
	DWORD timemillis;
#	if defined(_WIN32_WCE)
	timemillis=GetTickCount();
#	else
	timemillis=timeGetTime();
#	endif
	ret->tv_sec=timemillis/1000;
	ret->tv_nsec=(timemillis%1000)*1000000LL;
718 719 720 721
#else
	ULONGLONG timemillis = GetTickCount64();
	ret->tv_sec = timemillis / 1000;
	ret->tv_nsec = (timemillis % 1000) * 1000000LL;
Ghislain MARY's avatar
Ghislain MARY committed
722
#endif
723 724 725 726 727 728 729 730 731 732 733 734 735
#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;
736
	if (clock_gettime(realtime ? CLOCK_REALTIME : CLOCK_MONOTONIC,&ts)<0){
737 738 739 740 741 742
		ortp_fatal("clock_gettime() doesn't work: %s",strerror(errno));
	}
	ret->tv_sec=ts.tv_sec;
	ret->tv_nsec=ts.tv_nsec;
#endif
}
743

744
void ortp_get_cur_time(ortpTimeSpec *ret){
745
	_ortp_get_cur_time(ret, FALSE);
746 747 748
}


749 750 751 752 753 754
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);
}

755
void ortp_sleep_ms(int ms){
756 757
#ifdef _WIN32
#ifdef ORTP_WINDOWS_DESKTOP
758 759 760 761 762 763 764 765 766
	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;
767 768
	ts.tv_sec=ms/1000;
	ts.tv_nsec=(ms%1000)*1000000LL;
769 770 771 772 773 774 775 776 777 778 779 780 781 782
	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;
783
	_ortp_get_cur_time(&current, TRUE);
784 785 786 787 788 789
	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;
	}
790
#ifdef _WIN32
791
		ortp_sleep_ms((int)((diff.tv_sec * 1000LL) + (diff.tv_nsec/1000000LL)));
792
#else
793 794 795 796 797 798 799 800
	{
		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;
		};
	}
801
#endif
802 803 804
#endif
}

805 806
#if defined(_WIN32) && !defined(_MSC_VER)
char* strtok_r(char *str, const char *delim, char **nextp){
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
	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;
823 824
}
#endif
825 826


Simon Morlat's avatar
Simon Morlat committed
827 828 829
#if defined(_WIN32)

#if !defined(_MSC_VER)
830 831 832 833
#include <wincrypt.h>
static int ortp_wincrypto_random(unsigned int *rand_number){
	static HCRYPTPROV hProv=(HCRYPTPROV)-1;
	static int initd=0;
834

835 836 837 838 839 840 841 842 843
	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;
844

845 846 847 848 849 850 851
	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
852
#elif defined(__QNXNTO__) || ((defined(__linux) || defined(__APPLE__)) && !defined(HAVE_ARC4RANDOM))
853

Sylvain Berfini's avatar
Sylvain Berfini committed
854 855
static unsigned int ortp_urandom(void) {
	static int fd=-1;
Simon Morlat's avatar
Simon Morlat committed
856 857 858 859 860 861 862
	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
863 864 865
	return (unsigned int) random();
}

Simon Morlat's avatar
Simon Morlat committed
866 867 868 869 870
#endif




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

886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
	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
905

906
bool_t ortp_is_multicast_addr(const struct sockaddr *addr) {
907

908 909 910 911 912 913 914 915
	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;
	}
916

917
}