PageRenderTime 27ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/ortp-0.20.0/src/port.c

#
C | 623 lines | 491 code | 93 blank | 39 comment | 35 complexity | 0a584eacaa205ddc15e62b88226a9d7e MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
  3. Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #if defined(WIN32) || defined(_WIN32_WCE)
  17. #include "ortp-config-win32.h"
  18. #elif HAVE_CONFIG_H
  19. #include "ortp-config.h"
  20. #endif
  21. #include "ortp/port.h"
  22. #include "ortp/ortp.h"
  23. #include "utils.h"
  24. #if defined(_WIN32) && !defined(_WIN32_WCE)
  25. #include <process.h>
  26. #endif
  27. #ifdef HAVE_SYS_SHM_H
  28. #include <sys/shm.h>
  29. #endif
  30. static void *ortp_libc_malloc(size_t sz){
  31. return malloc(sz);
  32. }
  33. static void *ortp_libc_realloc(void *ptr, size_t sz){
  34. return realloc(ptr,sz);
  35. }
  36. static void ortp_libc_free(void*ptr){
  37. free(ptr);
  38. }
  39. static bool_t allocator_used=FALSE;
  40. static OrtpMemoryFunctions ortp_allocator={
  41. ortp_libc_malloc,
  42. ortp_libc_realloc,
  43. ortp_libc_free
  44. };
  45. void ortp_set_memory_functions(OrtpMemoryFunctions *functions){
  46. if (allocator_used){
  47. ortp_fatal("ortp_set_memory_functions() must be called before "
  48. "first use of ortp_malloc or ortp_realloc");
  49. return;
  50. }
  51. ortp_allocator=*functions;
  52. }
  53. void* ortp_malloc(size_t sz){
  54. allocator_used=TRUE;
  55. return ortp_allocator.malloc_fun(sz);
  56. }
  57. void* ortp_realloc(void *ptr, size_t sz){
  58. allocator_used=TRUE;
  59. return ortp_allocator.realloc_fun(ptr,sz);
  60. }
  61. void ortp_free(void* ptr){
  62. ortp_allocator.free_fun(ptr);
  63. }
  64. void * ortp_malloc0(size_t size){
  65. void *ptr=ortp_malloc(size);
  66. memset(ptr,0,size);
  67. return ptr;
  68. }
  69. char * ortp_strdup(const char *tmp){
  70. size_t sz;
  71. char *ret;
  72. if (tmp==NULL)
  73. return NULL;
  74. sz=strlen(tmp)+1;
  75. ret=(char*)ortp_malloc(sz);
  76. strcpy(ret,tmp);
  77. ret[sz-1]='\0';
  78. return ret;
  79. }
  80. /*
  81. * this method is an utility method that calls fnctl() on UNIX or
  82. * ioctlsocket on Win32.
  83. * int retrun the result of the system method
  84. */
  85. int set_non_blocking_socket (ortp_socket_t sock)
  86. {
  87. #if !defined(_WIN32) && !defined(_WIN32_WCE)
  88. return fcntl (sock, F_SETFL, O_NONBLOCK);
  89. #else
  90. unsigned long nonBlock = 1;
  91. return ioctlsocket(sock, FIONBIO , &nonBlock);
  92. #endif
  93. }
  94. /*
  95. * this method is an utility method that calls close() on UNIX or
  96. * closesocket on Win32.
  97. * int retrun the result of the system method
  98. */
  99. int close_socket(ortp_socket_t sock){
  100. #if !defined(_WIN32) && !defined(_WIN32_WCE)
  101. return close (sock);
  102. #else
  103. return closesocket(sock);
  104. #endif
  105. }
  106. #if defined (_WIN32_WCE) || defined(_MSC_VER)
  107. int ortp_file_exist(const char *pathname) {
  108. FILE* fd;
  109. if (pathname==NULL) return -1;
  110. fd=fopen(pathname,"r");
  111. if (fd==NULL) {
  112. return -1;
  113. } else {
  114. fclose(fd);
  115. return 0;
  116. }
  117. }
  118. #else
  119. int ortp_file_exist(const char *pathname) {
  120. return access(pathname,F_OK);
  121. }
  122. #endif /*_WIN32_WCE*/
  123. #if !defined(_WIN32) && !defined(_WIN32_WCE)
  124. /* Use UNIX inet_aton method */
  125. #else
  126. int inet_aton (const char * cp, struct in_addr * addr)
  127. {
  128. unsigned long retval;
  129. retval = inet_addr (cp);
  130. if (retval == INADDR_NONE)
  131. {
  132. return -1;
  133. }
  134. else
  135. {
  136. addr->S_un.S_addr = retval;
  137. return 1;
  138. }
  139. }
  140. #endif
  141. char *ortp_strndup(const char *str,int n){
  142. int min=MIN((int)strlen(str),n)+1;
  143. char *ret=(char*)ortp_malloc(min);
  144. strncpy(ret,str,min);
  145. ret[min-1]='\0';
  146. return ret;
  147. }
  148. #if !defined(_WIN32) && !defined(_WIN32_WCE)
  149. int __ortp_thread_join(ortp_thread_t thread, void **ptr){
  150. int err=pthread_join(thread,ptr);
  151. if (err!=0) {
  152. ortp_error("pthread_join error: %s",strerror(err));
  153. }
  154. return err;
  155. }
  156. int __ortp_thread_create(pthread_t *thread, pthread_attr_t *attr, void * (*routine)(void*), void *arg){
  157. pthread_attr_t my_attr;
  158. pthread_attr_init(&my_attr);
  159. if (attr)
  160. my_attr = *attr;
  161. #ifdef ORTP_DEFAULT_THREAD_STACK_SIZE
  162. if (ORTP_DEFAULT_THREAD_STACK_SIZE!=0)
  163. pthread_attr_setstacksize(&my_attr, ORTP_DEFAULT_THREAD_STACK_SIZE);
  164. #endif
  165. return pthread_create(thread, &my_attr, routine, arg);
  166. }
  167. #endif
  168. #if defined(_WIN32) || defined(_WIN32_WCE)
  169. int WIN_mutex_init(ortp_mutex_t *mutex, void *attr)
  170. {
  171. *mutex=CreateMutex(NULL, FALSE, NULL);
  172. return 0;
  173. }
  174. int WIN_mutex_lock(ortp_mutex_t * hMutex)
  175. {
  176. WaitForSingleObject(*hMutex, INFINITE); /* == WAIT_TIMEOUT; */
  177. return 0;
  178. }
  179. int WIN_mutex_unlock(ortp_mutex_t * hMutex)
  180. {
  181. ReleaseMutex(*hMutex);
  182. return 0;
  183. }
  184. int WIN_mutex_destroy(ortp_mutex_t * hMutex)
  185. {
  186. CloseHandle(*hMutex);
  187. return 0;
  188. }
  189. typedef struct thread_param{
  190. void * (*func)(void *);
  191. void * arg;
  192. }thread_param_t;
  193. static unsigned WINAPI thread_starter(void *data){
  194. thread_param_t *params=(thread_param_t*)data;
  195. void *ret=params->func(params->arg);
  196. ortp_free(data);
  197. return (DWORD)ret;
  198. }
  199. #if defined _WIN32_WCE
  200. # define _beginthreadex CreateThread
  201. # define _endthreadex ExitThread
  202. #endif
  203. int WIN_thread_create(ortp_thread_t *th, void *attr, void * (*func)(void *), void *data)
  204. {
  205. thread_param_t *params=ortp_new(thread_param_t,1);
  206. params->func=func;
  207. params->arg=data;
  208. *th=(HANDLE)_beginthreadex( NULL, 0, thread_starter, params, 0, NULL);
  209. return 0;
  210. }
  211. int WIN_thread_join(ortp_thread_t thread_h, void **unused)
  212. {
  213. if (thread_h!=NULL)
  214. {
  215. WaitForSingleObject(thread_h, INFINITE);
  216. CloseHandle(thread_h);
  217. }
  218. return 0;
  219. }
  220. int WIN_cond_init(ortp_cond_t *cond, void *attr)
  221. {
  222. *cond=CreateEvent(NULL, FALSE, FALSE, NULL);
  223. return 0;
  224. }
  225. int WIN_cond_wait(ortp_cond_t* hCond, ortp_mutex_t * hMutex)
  226. {
  227. //gulp: this is not very atomic ! bug here ?
  228. WIN_mutex_unlock(hMutex);
  229. WaitForSingleObject(*hCond, INFINITE);
  230. WIN_mutex_lock(hMutex);
  231. return 0;
  232. }
  233. int WIN_cond_signal(ortp_cond_t * hCond)
  234. {
  235. SetEvent(*hCond);
  236. return 0;
  237. }
  238. int WIN_cond_broadcast(ortp_cond_t * hCond)
  239. {
  240. WIN_cond_signal(hCond);
  241. return 0;
  242. }
  243. int WIN_cond_destroy(ortp_cond_t * hCond)
  244. {
  245. CloseHandle(*hCond);
  246. return 0;
  247. }
  248. #if defined(_WIN32_WCE)
  249. #include <time.h>
  250. const char * ortp_strerror(DWORD value) {
  251. static TCHAR msgBuf[256];
  252. FormatMessage(
  253. FORMAT_MESSAGE_FROM_SYSTEM |
  254. FORMAT_MESSAGE_IGNORE_INSERTS,
  255. NULL,
  256. value,
  257. 0, // Default language
  258. (LPTSTR) &msgBuf,
  259. 0,
  260. NULL
  261. );
  262. return (const char *)msgBuf;
  263. }
  264. int
  265. gettimeofday (struct timeval *tv, void *tz)
  266. {
  267. DWORD timemillis = GetTickCount();
  268. tv->tv_sec = timemillis/1000;
  269. tv->tv_usec = (timemillis - (tv->tv_sec*1000)) * 1000;
  270. return 0;
  271. }
  272. #else
  273. int gettimeofday (struct timeval *tv, void* tz)
  274. {
  275. union
  276. {
  277. __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
  278. FILETIME fileTime;
  279. } now;
  280. GetSystemTimeAsFileTime (&now.fileTime);
  281. tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
  282. tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL);
  283. return (0);
  284. }
  285. #endif
  286. const char *getWinSocketError(int error)
  287. {
  288. static char buf[80];
  289. switch (error)
  290. {
  291. case WSANOTINITIALISED: return "Windows sockets not initialized : call WSAStartup";
  292. case WSAEADDRINUSE: return "Local Address already in use";
  293. case WSAEADDRNOTAVAIL: return "The specified address is not a valid address for this machine";
  294. case WSAEINVAL: return "The socket is already bound to an address.";
  295. case WSAENOBUFS: return "Not enough buffers available, too many connections.";
  296. case WSAENOTSOCK: return "The descriptor is not a socket.";
  297. case WSAECONNRESET: return "Connection reset by peer";
  298. default :
  299. sprintf(buf, "Error code : %d", error);
  300. return buf;
  301. break;
  302. }
  303. return buf;
  304. }
  305. #ifdef _WORKAROUND_MINGW32_BUGS
  306. char * WSAAPI gai_strerror(int errnum){
  307. return (char*)getWinSocketError(errnum);
  308. }
  309. #endif
  310. #endif
  311. #ifndef WIN32
  312. #include <sys/socket.h>
  313. #include <netdb.h>
  314. #include <sys/un.h>
  315. #include <sys/stat.h>
  316. static char *make_pipe_name(const char *name){
  317. return ortp_strdup_printf("/tmp/%s",name);
  318. }
  319. /* portable named pipes */
  320. ortp_socket_t ortp_server_pipe_create(const char *name){
  321. struct sockaddr_un sa;
  322. char *pipename=make_pipe_name(name);
  323. ortp_socket_t sock;
  324. sock=socket(AF_UNIX,SOCK_STREAM,0);
  325. sa.sun_family=AF_UNIX;
  326. strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
  327. unlink(pipename);/*in case we didn't finished properly previous time */
  328. ortp_free(pipename);
  329. fchmod(sock,S_IRUSR|S_IWUSR);
  330. if (bind(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
  331. ortp_error("Failed to bind command unix socket: %s",strerror(errno));
  332. return -1;
  333. }
  334. listen(sock,1);
  335. return sock;
  336. }
  337. ortp_socket_t ortp_server_pipe_accept_client(ortp_socket_t server){
  338. struct sockaddr_un su;
  339. socklen_t ssize=sizeof(su);
  340. ortp_socket_t client_sock=accept(server,(struct sockaddr*)&su,&ssize);
  341. return client_sock;
  342. }
  343. int ortp_server_pipe_close_client(ortp_socket_t client){
  344. return close(client);
  345. }
  346. int ortp_server_pipe_close(ortp_socket_t spipe){
  347. return close(spipe);
  348. }
  349. ortp_socket_t ortp_client_pipe_connect(const char *name){
  350. struct sockaddr_un sa;
  351. char *pipename=make_pipe_name(name);
  352. ortp_socket_t sock=socket(AF_UNIX,SOCK_STREAM,0);
  353. sa.sun_family=AF_UNIX;
  354. strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
  355. ortp_free(pipename);
  356. if (connect(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
  357. close(sock);
  358. return -1;
  359. }
  360. return sock;
  361. }
  362. int ortp_pipe_read(ortp_socket_t p, uint8_t *buf, int len){
  363. return read(p,buf,len);
  364. }
  365. int ortp_pipe_write(ortp_socket_t p, const uint8_t *buf, int len){
  366. return write(p,buf,len);
  367. }
  368. int ortp_client_pipe_close(ortp_socket_t sock){
  369. return close(sock);
  370. }
  371. #ifdef HAVE_SYS_SHM_H
  372. void *ortp_shm_open(unsigned int keyid, int size, int create){
  373. key_t key=keyid;
  374. void *mem;
  375. int fd=shmget(key,size,create ? (IPC_CREAT | 0666) : 0666);
  376. if (fd==-1){
  377. printf("shmget failed: %s\n",strerror(errno));
  378. return NULL;
  379. }
  380. mem=shmat(fd,NULL,0);
  381. if (mem==(void*)-1){
  382. printf("shmat() failed: %s", strerror(errno));
  383. return NULL;
  384. }
  385. return mem;
  386. }
  387. void ortp_shm_close(void *mem){
  388. shmdt(mem);
  389. }
  390. #endif
  391. #elif defined(WIN32) && !defined(_WIN32_WCE)
  392. static char *make_pipe_name(const char *name){
  393. return ortp_strdup_printf("\\\\.\\pipe\\%s",name);
  394. }
  395. static HANDLE event=NULL;
  396. /* portable named pipes */
  397. ortp_pipe_t ortp_server_pipe_create(const char *name){
  398. ortp_pipe_t h;
  399. char *pipename=make_pipe_name(name);
  400. h=CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_MESSAGE|PIPE_WAIT,1,
  401. 32768,32768,0,NULL);
  402. ortp_free(pipename);
  403. if (h==INVALID_HANDLE_VALUE){
  404. ortp_error("Fail to create named pipe %s",pipename);
  405. }
  406. if (event==NULL) event=CreateEvent(NULL,TRUE,FALSE,NULL);
  407. return h;
  408. }
  409. /*this function is a bit complex because we need to wakeup someday
  410. even if nobody connects to the pipe.
  411. ortp_server_pipe_close() makes this function to exit.
  412. */
  413. ortp_pipe_t ortp_server_pipe_accept_client(ortp_pipe_t server){
  414. OVERLAPPED ol;
  415. DWORD undef;
  416. HANDLE handles[2];
  417. memset(&ol,0,sizeof(ol));
  418. ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  419. ConnectNamedPipe(server,&ol);
  420. handles[0]=ol.hEvent;
  421. handles[1]=event;
  422. WaitForMultipleObjects(2,handles,FALSE,INFINITE);
  423. if (GetOverlappedResult(server,&ol,&undef,FALSE)){
  424. CloseHandle(ol.hEvent);
  425. return server;
  426. }
  427. CloseHandle(ol.hEvent);
  428. return INVALID_HANDLE_VALUE;
  429. }
  430. int ortp_server_pipe_close_client(ortp_pipe_t server){
  431. return DisconnectNamedPipe(server)==TRUE ? 0 : -1;
  432. }
  433. int ortp_server_pipe_close(ortp_pipe_t spipe){
  434. SetEvent(event);
  435. //CancelIoEx(spipe,NULL); /*vista only*/
  436. return CloseHandle(spipe);
  437. }
  438. ortp_pipe_t ortp_client_pipe_connect(const char *name){
  439. char *pipename=make_pipe_name(name);
  440. ortp_pipe_t hpipe = CreateFile(
  441. pipename, // pipe name
  442. GENERIC_READ | // read and write access
  443. GENERIC_WRITE,
  444. 0, // no sharing
  445. NULL, // default security attributes
  446. OPEN_EXISTING, // opens existing pipe
  447. 0, // default attributes
  448. NULL); // no template file
  449. ortp_free(pipename);
  450. return hpipe;
  451. }
  452. int ortp_pipe_read(ortp_pipe_t p, uint8_t *buf, int len){
  453. DWORD ret=0;
  454. if (ReadFile(p,buf,len,&ret,NULL))
  455. return ret;
  456. /*ortp_error("Could not read from pipe: %s",strerror(GetLastError()));*/
  457. return -1;
  458. }
  459. int ortp_pipe_write(ortp_pipe_t p, const uint8_t *buf, int len){
  460. DWORD ret=0;
  461. if (WriteFile(p,buf,len,&ret,NULL))
  462. return ret;
  463. /*ortp_error("Could not write to pipe: %s",strerror(GetLastError()));*/
  464. return -1;
  465. }
  466. int ortp_client_pipe_close(ortp_pipe_t sock){
  467. return CloseHandle(sock);
  468. }
  469. typedef struct MapInfo{
  470. HANDLE h;
  471. void *mem;
  472. }MapInfo;
  473. static OList *maplist=NULL;
  474. void *ortp_shm_open(unsigned int keyid, int size, int create){
  475. HANDLE h;
  476. char name[64];
  477. void *buf;
  478. snprintf(name,sizeof(name),"%x",keyid);
  479. if (create){
  480. h = CreateFileMapping(
  481. INVALID_HANDLE_VALUE, // use paging file
  482. NULL, // default security
  483. PAGE_READWRITE, // read/write access
  484. 0, // maximum object size (high-order DWORD)
  485. size, // maximum object size (low-order DWORD)
  486. name); // name of mapping object
  487. }else{
  488. h = OpenFileMapping(
  489. FILE_MAP_ALL_ACCESS, // read/write access
  490. FALSE, // do not inherit the name
  491. name); // name of mapping object
  492. }
  493. if (h==(HANDLE)-1) {
  494. ortp_error("Fail to open file mapping (create=%i)",create);
  495. return NULL;
  496. }
  497. buf = (LPTSTR) MapViewOfFile(h, // handle to map object
  498. FILE_MAP_ALL_ACCESS, // read/write permission
  499. 0,
  500. 0,
  501. size);
  502. if (buf!=NULL){
  503. MapInfo *i=(MapInfo*)ortp_new(MapInfo,1);
  504. i->h=h;
  505. i->mem=buf;
  506. maplist=o_list_append(maplist,i);
  507. }else{
  508. CloseHandle(h);
  509. ortp_error("MapViewOfFile failed");
  510. }
  511. return buf;
  512. }
  513. void ortp_shm_close(void *mem){
  514. OList *elem;
  515. for(elem=maplist;elem!=NULL;elem=elem->next){
  516. MapInfo *i=(MapInfo*)elem->data;
  517. if (i->mem==mem){
  518. CloseHandle(i->h);
  519. UnmapViewOfFile(mem);
  520. ortp_free(i);
  521. maplist=o_list_remove_link(maplist,elem);
  522. return;
  523. }
  524. }
  525. ortp_error("No shared memory at %p was found.",mem);
  526. }
  527. #endif