libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmUdpPort.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmThread.h"
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. #include <fcntl.h>
  13. #include <unistd.h> // close
  14. #include "cmUdpPort.h"
  15. #define cmUdp_SYS_ERR (-1)
  16. #define cmUdp_NULL_SOCK (-1)
  17. enum
  18. {
  19. kIsConnectedUdpFl = 0x01,
  20. kIsBlockingUdpFl = 0x02,
  21. kQueueingUdpFl = 0x04
  22. };
  23. typedef struct
  24. {
  25. cmErr_t err;
  26. int sockH;
  27. cmUdpCallback_t cbFunc;
  28. void* cbArg;
  29. unsigned timeOutMs;
  30. unsigned flags;
  31. cmThreadH_t thH;
  32. cmTs1p1cH_t qH;
  33. unsigned recvBufByteCnt;
  34. char* tempBuf;
  35. unsigned timeOutCnt;
  36. unsigned recvCnt;
  37. unsigned queCbCnt;
  38. unsigned errCnt;
  39. struct sockaddr_in sockaddr;
  40. cmChar_t ntopBuf[ INET_ADDRSTRLEN+1 ]; // use INET6_ADDRSTRLEN for IPv6
  41. cmChar_t hnameBuf[ HOST_NAME_MAX+1 ];
  42. } cmUdp_t;
  43. cmUdpH_t cmUdpNullHandle = cmSTATIC_NULL_HANDLE;
  44. #define _cmUdpClear_errno() errno = 0
  45. cmUdp_t* _cmUdpHandleToPtr( cmUdpH_t h )
  46. {
  47. cmUdp_t* p = (cmUdp_t*)h.h;
  48. assert(p != NULL);
  49. return p;
  50. }
  51. cmUdpRC_t _cmUdpFinal( cmUdp_t* p )
  52. {
  53. cmUdpRC_t rc = kOkUdpRC;
  54. if( cmThreadIsValid(p->thH) )
  55. if( cmThreadDestroy(&p->thH) != kOkThRC )
  56. return cmErrMsg(&p->err,kThreadFailUdpRC,"Listener thread destroy failed.");
  57. if( cmTs1p1cIsValid(p->qH) )
  58. if( cmTs1p1cDestroy(&p->qH) != kOkThRC )
  59. cmErrMsg(&p->err,kQueueFailUdpRC,"Receive data queue destroy failed.");
  60. cmMemPtrFree(&p->tempBuf);
  61. // close the socket
  62. if( p->sockH != cmUdp_NULL_SOCK )
  63. {
  64. _cmUdpClear_errno();
  65. if( close(p->sockH) != 0 )
  66. cmErrSysMsg(&p->err,kSockCloseFailUdpRC,errno,"The socket close failed." );
  67. p->sockH = cmUdp_NULL_SOCK;
  68. }
  69. return rc;
  70. }
  71. cmUdpRC_t _cmUdpFree( cmUdp_t* p )
  72. {
  73. cmUdpRC_t rc;
  74. if((rc = _cmUdpFinal(p)) != kOkUdpRC )
  75. return rc;
  76. cmMemFree(p);
  77. return rc;
  78. }
  79. cmUdpRC_t _cmUdpInitAddr( cmUdp_t* p, const char* addrStr, cmUdpPort_t portNumber, struct sockaddr_in* retAddrPtr )
  80. {
  81. memset(retAddrPtr,0,sizeof(struct sockaddr_in));
  82. if( addrStr == NULL )
  83. retAddrPtr->sin_addr.s_addr = htonl(INADDR_ANY);
  84. else
  85. {
  86. _cmUdpClear_errno();
  87. if(inet_pton(AF_INET,addrStr,&retAddrPtr->sin_addr) == 0 )
  88. //if(( retAddrPtr->sin_addr.s_addr = inet_addr(addrStr)) == INADDR_NONE )
  89. return cmErrSysMsg(&p->err,kPtoNFailUdpRC,errno, "The network address string '%s' could not be converted to a netword address structure.",cmStringNullGuard(addrStr) );
  90. }
  91. //retAddrPtr->sin_len = sizeof(struct sockaddr_in);
  92. retAddrPtr->sin_family = AF_INET;
  93. retAddrPtr->sin_port = htons(portNumber);
  94. return kOkUdpRC;
  95. }
  96. cmUdpRC_t _cmUdpConnect( cmUdp_t* p, const char* remoteAddr, cmUdpPort_t remotePort )
  97. {
  98. struct sockaddr_in addr;
  99. cmUdpRC_t rc;
  100. // create the remote address
  101. if((rc = _cmUdpInitAddr(p, remoteAddr, remotePort, &addr )) != kOkUdpRC )
  102. return rc;
  103. _cmUdpClear_errno();
  104. // ... and connect this socket to the remote address/port
  105. if( connect(p->sockH, (struct sockaddr*)&addr, sizeof(addr)) == cmUdp_SYS_ERR )
  106. return cmErrSysMsg(&p->err,kSockConnectFailUdpRC, errno, "Socket connect failed." );
  107. p->flags = cmSetFlag(p->flags,kIsConnectedUdpFl);
  108. return rc;
  109. }
  110. cmUdpRC_t cmUdpAlloc( cmCtx_t* ctx, cmUdpH_t* hp )
  111. {
  112. cmUdpRC_t rc;
  113. if((rc = cmUdpFree(hp)) != kOkUdpRC )
  114. return rc;
  115. cmUdp_t* p = cmMemAllocZ(cmUdp_t,1);
  116. cmErrSetup(&p->err,&ctx->rpt,"UDP Port");
  117. p->sockH = cmUdp_NULL_SOCK;
  118. hp->h = p;
  119. return rc;
  120. }
  121. cmUdpRC_t cmUdpFree( cmUdpH_t* hp )
  122. {
  123. cmUdpRC_t rc = kOkUdpRC;
  124. if( hp == NULL || cmUdpIsValid(*hp)==false)
  125. return rc;
  126. cmUdp_t* p = _cmUdpHandleToPtr(*hp);
  127. if((rc = _cmUdpFree(p)) != kOkUdpRC )
  128. return rc;
  129. hp->h = NULL;
  130. return rc;
  131. }
  132. cmUdpRC_t cmUdpInit(
  133. cmUdpH_t h,
  134. cmUdpPort_t port,
  135. unsigned flags,
  136. cmUdpCallback_t cbFunc,
  137. void* cbArg,
  138. const char* remoteAddr,
  139. cmUdpPort_t remotePort,
  140. unsigned recvBufByteCnt,
  141. unsigned timeOutMs )
  142. {
  143. cmUdpRC_t rc;
  144. cmUdp_t* p = _cmUdpHandleToPtr(h);
  145. if((rc = _cmUdpFinal(p)) != kOkUdpRC )
  146. return rc;
  147. _cmUdpClear_errno();
  148. // get a handle to the socket
  149. if(( p->sockH = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == cmUdp_SYS_ERR )
  150. return cmErrSysMsg(&p->err, kSockCreateFailUdpRC, errno, "Socket create failed." );
  151. // create the local address
  152. if((rc = _cmUdpInitAddr(p, NULL, port, &p->sockaddr )) != kOkUdpRC )
  153. goto errLabel;
  154. // bind the socket to a local address/port
  155. if( (bind( p->sockH, (struct sockaddr*)&p->sockaddr, sizeof(p->sockaddr))) == cmUdp_SYS_ERR )
  156. {
  157. rc = cmErrSysMsg(&p->err,kSockBindFailUdpRC,errno,"Socket bind failed." );
  158. goto errLabel;
  159. }
  160. // if a remote addr was given connect this socket to it
  161. if( remoteAddr != NULL )
  162. if((rc = _cmUdpConnect(p,remoteAddr,remotePort)) != kOkUdpRC )
  163. goto errLabel;
  164. // if this socket should block
  165. if( cmIsFlag(flags,kBlockingUdpFl) )
  166. {
  167. struct timeval timeOut;
  168. // set the socket time out
  169. timeOut.tv_sec = timeOutMs/1000;
  170. timeOut.tv_usec = (timeOutMs - (timeOut.tv_sec * 1000)) * 1000;
  171. if( setsockopt( p->sockH, SOL_SOCKET, SO_RCVTIMEO, &timeOut, sizeof(timeOut) ) == cmUdp_SYS_ERR )
  172. {
  173. rc = cmErrSysMsg(&p->err,kSockOptSetFailUdpRC,errno, "Attempt to set the socket timeout failed." );
  174. goto errLabel;
  175. }
  176. p->flags = cmSetFlag(p->flags,kIsBlockingUdpFl);
  177. }
  178. else
  179. {
  180. int opts;
  181. // get the socket options flags
  182. if( (opts = fcntl(p->sockH,F_GETFL)) < 0 )
  183. {
  184. rc = cmErrSysMsg(&p->err,kSockOptSetFailUdpRC,errno, "Attempt to get the socket options flags failed." );
  185. goto errLabel;
  186. }
  187. opts = (opts | O_NONBLOCK);
  188. // set the socket options flags
  189. if(fcntl(p->sockH,F_SETFL,opts) < 0)
  190. {
  191. rc = cmErrSysMsg(&p->err,kSockOptSetFailUdpRC,errno, "Attempt to set the socket to non-blocking failed." );
  192. goto errLabel;
  193. }
  194. }
  195. // if broadcast option was requested.
  196. if( cmIsFlag(flags,kBroadcastUdpFl) )
  197. {
  198. int bcastFl = 1;
  199. if( setsockopt( p->sockH, SOL_SOCKET, SO_BROADCAST, &bcastFl, sizeof(bcastFl) ) == cmUdp_SYS_ERR )
  200. {
  201. rc = cmErrSysMsg(&p->err,kSockOptSetFailUdpRC,errno, "Attempt to set the socket broadcast attribute failed." );
  202. goto errLabel;
  203. }
  204. }
  205. if( recvBufByteCnt != 0 )
  206. p->tempBuf = cmMemAlloc(char,recvBufByteCnt );
  207. p->timeOutMs = timeOutMs;
  208. p->cbFunc = cbFunc;
  209. p->cbArg = cbArg;
  210. p->recvBufByteCnt = recvBufByteCnt;
  211. p->timeOutCnt = 0;
  212. p->recvCnt = 0;
  213. p->queCbCnt = 0;
  214. p->errCnt = 0;
  215. if( cmIsFlag(flags,kNoQueueUdpFl) == false )
  216. p->flags = cmSetFlag(p->flags,kQueueingUdpFl);
  217. errLabel:
  218. if( rc != kOkUdpRC )
  219. _cmUdpFree(p);
  220. return rc;
  221. }
  222. cmUdpRC_t cmUdpFinal( cmUdpH_t h )
  223. {
  224. cmUdp_t* p = _cmUdpHandleToPtr(h);
  225. return _cmUdpFinal(p);
  226. }
  227. bool cmUdpIsValid( cmUdpH_t h )
  228. { return h.h != NULL; }
  229. const struct sockaddr_in* cmUdpLocalAddr( cmUdpH_t h )
  230. {
  231. cmUdp_t* p = _cmUdpHandleToPtr(h);
  232. return &p->sockaddr;
  233. }
  234. cmUdpRC_t cmUdpConnect( cmUdpH_t h, const char* remoteAddr, cmUdpPort_t remotePort )
  235. {
  236. cmUdp_t* p = _cmUdpHandleToPtr(h);
  237. return _cmUdpConnect(p,remoteAddr,remotePort);
  238. }
  239. cmUdpRC_t cmUdpSend( cmUdpH_t h, const char* data, unsigned dataByteCnt )
  240. {
  241. cmUdp_t* p = _cmUdpHandleToPtr(h);
  242. _cmUdpClear_errno();
  243. if( cmIsFlag(p->flags,kIsConnectedUdpFl) == false )
  244. return cmErrMsg(&p->err,kNotConnectedUdpRC,"cmUdpSend() only works with connected sockets.");
  245. if( send( p->sockH, data, dataByteCnt, 0 ) == cmUdp_SYS_ERR )
  246. return cmErrSysMsg(&p->err,kSockSendFailUdpRC,errno,"Send failed.");
  247. return kOkUdpRC;
  248. }
  249. cmUdpRC_t cmUdpSendTo( cmUdpH_t h, const char* data, unsigned dataByteCnt, const struct sockaddr_in* remoteAddr )
  250. {
  251. cmUdp_t* p = _cmUdpHandleToPtr(h);
  252. _cmUdpClear_errno();
  253. if( sendto(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)remoteAddr, sizeof(*remoteAddr)) == cmUdp_SYS_ERR )
  254. return cmErrSysMsg(&p->err,kSockSendFailUdpRC,errno,"SendTo failed.");
  255. return kOkUdpRC;
  256. }
  257. cmUdpRC_t cmUdpSend2( cmUdpH_t h, const char* data, unsigned dataByteCnt, const char* remoteAddr, cmUdpPort_t remotePort )
  258. {
  259. cmUdpRC_t rc;
  260. cmUdp_t* p = _cmUdpHandleToPtr(h);
  261. struct sockaddr_in addr;
  262. if((rc = _cmUdpInitAddr(p,remoteAddr,remotePort,&addr)) != kOkUdpRC )
  263. return rc;
  264. return cmUdpSendTo( h, data, dataByteCnt, &addr );
  265. }
  266. cmUdpRC_t cmUdpRecv( cmUdpH_t h, char* data, unsigned dataByteCnt, struct sockaddr_in* fromAddr, unsigned* recvByteCntPtr )
  267. {
  268. cmUdp_t* p = _cmUdpHandleToPtr(h);
  269. cmUdpRC_t rc = kOkUdpRC;
  270. ssize_t retVal = 0;
  271. socklen_t sizeOfRemoteAddr = fromAddr==NULL ? 0 : sizeof(struct sockaddr_in);
  272. _cmUdpClear_errno();
  273. if( recvByteCntPtr != NULL )
  274. *recvByteCntPtr = 0;
  275. if((retVal = recvfrom(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cmUdp_SYS_ERR )
  276. return cmErrSysMsg(&p->err,kSockRecvFailUdpRC,errno,"recvFrom() failed.");
  277. if( recvByteCntPtr != NULL )
  278. *recvByteCntPtr = retVal;
  279. return rc;
  280. }
  281. bool _cmUdpThreadCb(void* param)
  282. {
  283. cmUdp_t* p = (cmUdp_t*)param;
  284. fd_set rdSet;
  285. struct timeval timeOut;
  286. // setup the select() call
  287. FD_ZERO(&rdSet);
  288. FD_SET(p->sockH, &rdSet );
  289. timeOut.tv_sec = p->timeOutMs/1000;
  290. timeOut.tv_usec = (p->timeOutMs - (timeOut.tv_sec * 1000)) * 1000;
  291. // NOTE; select() takes the highest socket value plus one of all the sockets in all the sets.
  292. switch( select(p->sockH+1,&rdSet,NULL,NULL,&timeOut) )
  293. {
  294. case -1: // error
  295. if( errno != EINTR )
  296. cmErrSysMsg(&p->err,kSockSelectFailUdpRC,errno,"Select failed.");
  297. ++p->errCnt;
  298. break;
  299. case 0: // select() timed out
  300. ++p->timeOutCnt;
  301. break;
  302. case 1: // (> 0) count of ready descripters
  303. if( FD_ISSET(p->sockH,&rdSet) )
  304. {
  305. struct sockaddr_in remoteAddr;
  306. socklen_t addrByteCnt = sizeof(remoteAddr);
  307. ssize_t retByteCnt;
  308. _cmUdpClear_errno();
  309. ++p->recvCnt;
  310. // recv the incoming msg into p->tempBuf[]
  311. if(( retByteCnt = recvfrom( p->sockH, p->tempBuf, p->recvBufByteCnt, 0, (struct sockaddr*)&remoteAddr, &addrByteCnt )) == cmUdp_SYS_ERR )
  312. cmErrSysMsg(&p->err,kSockRecvFailUdpRC,errno,"recvfrom() failed.");
  313. else
  314. {
  315. // check for overflow
  316. if( retByteCnt == p->recvBufByteCnt )
  317. cmErrMsg(&p->err,kRecvBufOverflowUdpRC,"The receive buffer requires more than %i bytes.",p->recvBufByteCnt);
  318. else
  319. {
  320. // if queueing is enabled
  321. if( cmIsFlag(p->flags,kQueueingUdpFl ) )
  322. {
  323. // enqueue the msg - with the source address appended after the data
  324. const void* msgPtrArray[] = { p->tempBuf, &remoteAddr, p->tempBuf };
  325. unsigned msgByteCntArray[] = { retByteCnt, sizeof(remoteAddr) };
  326. if( cmTs1p1cEnqueueSegMsg( p->qH, msgPtrArray, msgByteCntArray, 2 ) != kOkThRC )
  327. cmErrMsg(&p->err,kQueueFailUdpRC,"A received msg containing %i bytes was not queued.",retByteCnt);
  328. }
  329. else // if queueing is not enabled - transmit the data directly via the callback
  330. if( p->cbFunc != NULL )
  331. {
  332. p->cbFunc(p->cbArg,p->tempBuf,retByteCnt,&remoteAddr);
  333. }
  334. }
  335. }
  336. }
  337. break;
  338. default:
  339. { assert(0); }
  340. } // switch
  341. return true;
  342. }
  343. cmRC_t _cmUdpQueueCb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
  344. {
  345. cmUdp_t* p = (cmUdp_t*)userCbPtr;
  346. if( p->cbFunc != NULL )
  347. {
  348. struct sockaddr_in addr;
  349. assert( msgByteCnt >= sizeof(addr));
  350. const char* dataPtr = (const char*)msgDataPtr;
  351. // the address of the data source is apppended to the data bytes.
  352. const char* addrPtr = dataPtr + msgByteCnt - sizeof(addr);
  353. memcpy(&addr,addrPtr,sizeof(addr));
  354. // make the receive callback
  355. p->cbFunc(p->cbArg,dataPtr,msgByteCnt-sizeof(addr),&addr);
  356. ++p->queCbCnt;
  357. }
  358. return cmOkRC;
  359. }
  360. cmUdpRC_t cmUdpEnableListen( cmUdpH_t h, bool enableFl )
  361. {
  362. cmUdp_t* p = _cmUdpHandleToPtr(h);
  363. if( cmThreadIsValid(p->thH) == false && enableFl == true)
  364. {
  365. if(cmThreadCreate(&p->thH,_cmUdpThreadCb,p,p->err.rpt) != kOkThRC )
  366. return cmErrMsg(&p->err,kThreadFailUdpRC,"Listener thread create failed.");
  367. if(cmTs1p1cCreate(&p->qH,p->recvBufByteCnt,_cmUdpQueueCb,p,p->err.rpt) != kOkThRC )
  368. return cmErrMsg(&p->err,kQueueFailUdpRC,"Listener data queue create failed.");
  369. }
  370. if( cmThreadIsValid(p->thH) )
  371. if( cmThreadPause( p->thH, enableFl ? 0 : kPauseThFl ) != kOkThRC )
  372. return cmErrMsg(&p->err,kThreadFailUdpRC,"The listener thread failed to %s.", enableFl ? "pause" : "un-pause" );
  373. return kOkUdpRC;
  374. }
  375. bool cmUdpIsQueueEnabled( cmUdpH_t h )
  376. {
  377. cmUdp_t* p = _cmUdpHandleToPtr(h);
  378. return cmIsFlag(p->flags,kQueueingUdpFl);
  379. }
  380. void cmUdpQueueEnable( cmUdpH_t h, bool enableFl )
  381. {
  382. cmUdp_t* p = _cmUdpHandleToPtr(h);
  383. p->flags = cmSetFlag(p->flags,kQueueingUdpFl);
  384. }
  385. unsigned cmUdpAvailDataByteCount( cmUdpH_t h )
  386. {
  387. cmUdp_t* p = _cmUdpHandleToPtr(h);
  388. return cmTs1p1cIsValid(p->qH) ? cmTs1p1cDequeueMsgByteCount( p->qH ) : 0;
  389. }
  390. cmUdpRC_t cmUdpGetAvailData( cmUdpH_t h, char* data, unsigned* dataByteCntPtr, struct sockaddr_in* fromAddr )
  391. {
  392. cmUdp_t* p = _cmUdpHandleToPtr(h);
  393. unsigned availByteCnt;
  394. // if a received msg is queued
  395. if( (availByteCnt = cmTs1p1cAvailByteCount(p->qH)) > 0 )
  396. {
  397. // all msg's must have at least a source address
  398. assert( availByteCnt >= sizeof(*fromAddr) );
  399. // get the size of the return buffer (or 0 if there is no return buffer)
  400. unsigned dataByteCnt = (data != NULL && dataByteCntPtr != NULL) ? *dataByteCntPtr : 0;
  401. if( dataByteCnt == 0 )
  402. data = NULL;
  403. // dequeue the msg - if data==NULL then the data will be returned by
  404. // a call to the callback function provided in cmUdpAlloc().
  405. if( cmTs1p1cDequeueMsg(p->qH, data, dataByteCnt ) != kOkThRC )
  406. return cmErrMsg(&p->err,kQueueFailUdpRC,"Data dequeue failed.");
  407. // if a return buffer was given
  408. if( data != NULL )
  409. {
  410. assert( dataByteCntPtr != NULL );
  411. // the source address is appended to the end of the data
  412. const char* addrPtr = data + availByteCnt - sizeof(*fromAddr);
  413. // copy out the source address
  414. if( fromAddr != NULL )
  415. memcpy(fromAddr,addrPtr,sizeof(*fromAddr));
  416. // subtract the address size from the total msg size
  417. *dataByteCntPtr = availByteCnt - sizeof(*fromAddr);
  418. }
  419. }
  420. return kOkUdpRC;
  421. }
  422. void cmUdpReport( cmUdpH_t h, cmRpt_t* rpt )
  423. {
  424. cmUdp_t* p = _cmUdpHandleToPtr(h);
  425. cmRptPrintf(rpt,"time-out:%i recv:%i queue cb:%i\n",p->timeOutCnt,p->recvCnt,p->queCbCnt);
  426. }
  427. cmUdpRC_t cmUdpInitAddr( cmUdpH_t h, const char* addrStr, cmUdpPort_t portNumber, struct sockaddr_in* retAddrPtr )
  428. {
  429. cmUdp_t* p = _cmUdpHandleToPtr(h);
  430. return _cmUdpInitAddr(p,addrStr,portNumber,retAddrPtr);
  431. }
  432. const cmChar_t* cmUdpAddrToString( cmUdpH_t h, const struct sockaddr_in* addr )
  433. {
  434. cmUdp_t* p = _cmUdpHandleToPtr(h);
  435. _cmUdpClear_errno();
  436. if( inet_ntop(AF_INET, &(addr->sin_addr), p->ntopBuf, INET_ADDRSTRLEN) == NULL)
  437. {
  438. cmErrSysMsg(&p->err,kNtoPFailUdpRC,errno, "Network address to string conversion failed." );
  439. return NULL;
  440. }
  441. p->ntopBuf[INET_ADDRSTRLEN]=0;
  442. return p->ntopBuf;
  443. }
  444. const cmChar_t* cmUdpHostName( cmUdpH_t h )
  445. {
  446. cmUdp_t* p = _cmUdpHandleToPtr(h);
  447. _cmUdpClear_errno();
  448. if( gethostname(p->hnameBuf,HOST_NAME_MAX) != 0 )
  449. {
  450. cmErrSysMsg(&p->err,kHostNameFailUdpRC,errno, "gethostname() failed." );
  451. return NULL;
  452. }
  453. p->hnameBuf[HOST_NAME_MAX] = 0;
  454. return p->hnameBuf;
  455. }