libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmUdpPort.c 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  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( recvBufByteCnt != 0 )
  196. p->tempBuf = cmMemAlloc(char,recvBufByteCnt );
  197. p->timeOutMs = timeOutMs;
  198. p->cbFunc = cbFunc;
  199. p->cbArg = cbArg;
  200. p->recvBufByteCnt = recvBufByteCnt;
  201. p->timeOutCnt = 0;
  202. p->recvCnt = 0;
  203. p->queCbCnt = 0;
  204. p->errCnt = 0;
  205. if( cmIsFlag(flags,kNoQueueUdpFl) == false )
  206. p->flags = cmSetFlag(p->flags,kQueueingUdpFl);
  207. errLabel:
  208. if( rc != kOkUdpRC )
  209. _cmUdpFree(p);
  210. return rc;
  211. }
  212. cmUdpRC_t cmUdpFinal( cmUdpH_t h )
  213. {
  214. cmUdp_t* p = _cmUdpHandleToPtr(h);
  215. return _cmUdpFinal(p);
  216. }
  217. bool cmUdpIsValid( cmUdpH_t h )
  218. { return h.h != NULL; }
  219. const struct sockaddr_in* cmUdpLocalAddr( cmUdpH_t h )
  220. {
  221. cmUdp_t* p = _cmUdpHandleToPtr(h);
  222. return &p->sockaddr;
  223. }
  224. cmUdpRC_t cmUdpConnect( cmUdpH_t h, const char* remoteAddr, cmUdpPort_t remotePort )
  225. {
  226. cmUdp_t* p = _cmUdpHandleToPtr(h);
  227. return _cmUdpConnect(p,remoteAddr,remotePort);
  228. }
  229. cmUdpRC_t cmUdpSend( cmUdpH_t h, const char* data, unsigned dataByteCnt )
  230. {
  231. cmUdp_t* p = _cmUdpHandleToPtr(h);
  232. _cmUdpClear_errno();
  233. if( cmIsFlag(p->flags,kIsConnectedUdpFl) == false )
  234. return cmErrMsg(&p->err,kNotConnectedUdpRC,"cmUdpSend() only works with connected sockets.");
  235. if( send( p->sockH, data, dataByteCnt, 0 ) == cmUdp_SYS_ERR )
  236. return cmErrSysMsg(&p->err,kSockSendFailUdpRC,errno,"Send failed.");
  237. return kOkUdpRC;
  238. }
  239. cmUdpRC_t cmUdpSendTo( cmUdpH_t h, const char* data, unsigned dataByteCnt, const struct sockaddr_in* remoteAddr )
  240. {
  241. cmUdp_t* p = _cmUdpHandleToPtr(h);
  242. _cmUdpClear_errno();
  243. if( sendto(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)remoteAddr, sizeof(*remoteAddr)) == cmUdp_SYS_ERR )
  244. return cmErrSysMsg(&p->err,kSockSendFailUdpRC,errno,"SendTo failed.");
  245. return kOkUdpRC;
  246. }
  247. cmUdpRC_t cmUdpSend2( cmUdpH_t h, const char* data, unsigned dataByteCnt, const char* remoteAddr, cmUdpPort_t remotePort )
  248. {
  249. cmUdpRC_t rc;
  250. cmUdp_t* p = _cmUdpHandleToPtr(h);
  251. struct sockaddr_in addr;
  252. if((rc = _cmUdpInitAddr(p,remoteAddr,remotePort,&addr)) != kOkUdpRC )
  253. return rc;
  254. return cmUdpSendTo( h, data, dataByteCnt, &addr );
  255. }
  256. cmUdpRC_t cmUdpRecv( cmUdpH_t h, char* data, unsigned dataByteCnt, struct sockaddr_in* fromAddr, unsigned* recvByteCntPtr )
  257. {
  258. cmUdp_t* p = _cmUdpHandleToPtr(h);
  259. cmUdpRC_t rc = kOkUdpRC;
  260. ssize_t retVal = 0;
  261. socklen_t sizeOfRemoteAddr = fromAddr==NULL ? 0 : sizeof(struct sockaddr_in);
  262. _cmUdpClear_errno();
  263. if( recvByteCntPtr != NULL )
  264. *recvByteCntPtr = 0;
  265. if((retVal = recvfrom(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cmUdp_SYS_ERR )
  266. return cmErrSysMsg(&p->err,kSockRecvFailUdpRC,errno,"recvFrom() failed.");
  267. if( recvByteCntPtr != NULL )
  268. *recvByteCntPtr = retVal;
  269. return rc;
  270. }
  271. bool _cmUdpThreadCb(void* param)
  272. {
  273. cmUdp_t* p = (cmUdp_t*)param;
  274. fd_set rdSet;
  275. struct timeval timeOut;
  276. // setup the select() call
  277. FD_ZERO(&rdSet);
  278. FD_SET(p->sockH, &rdSet );
  279. timeOut.tv_sec = p->timeOutMs/1000;
  280. timeOut.tv_usec = (p->timeOutMs - (timeOut.tv_sec * 1000)) * 1000;
  281. // NOTE; select() takes the highest socket value plus one of all the sockets in all the sets.
  282. switch( select(p->sockH+1,&rdSet,NULL,NULL,&timeOut) )
  283. {
  284. case -1: // error
  285. if( errno != EINTR )
  286. cmErrSysMsg(&p->err,kSockSelectFailUdpRC,errno,"Select failed.");
  287. ++p->errCnt;
  288. break;
  289. case 0: // select() timed out
  290. ++p->timeOutCnt;
  291. break;
  292. case 1: // (> 0) count of ready descripters
  293. if( FD_ISSET(p->sockH,&rdSet) )
  294. {
  295. struct sockaddr_in remoteAddr;
  296. socklen_t addrByteCnt = sizeof(remoteAddr);
  297. ssize_t retByteCnt;
  298. _cmUdpClear_errno();
  299. ++p->recvCnt;
  300. // recv the incoming msg into p->tempBuf[]
  301. if(( retByteCnt = recvfrom( p->sockH, p->tempBuf, p->recvBufByteCnt, 0, (struct sockaddr*)&remoteAddr, &addrByteCnt )) == cmUdp_SYS_ERR )
  302. cmErrSysMsg(&p->err,kSockRecvFailUdpRC,errno,"recvfrom() failed.");
  303. else
  304. {
  305. // check for overflow
  306. if( retByteCnt == p->recvBufByteCnt )
  307. cmErrMsg(&p->err,kRecvBufOverflowUdpRC,"The receive buffer requires more than %i bytes.",p->recvBufByteCnt);
  308. else
  309. {
  310. // if queueing is enabled
  311. if( cmIsFlag(p->flags,kQueueingUdpFl ) )
  312. {
  313. // enqueue the msg - with the source address appended after the data
  314. const void* msgPtrArray[] = { p->tempBuf, &remoteAddr, p->tempBuf };
  315. unsigned msgByteCntArray[] = { retByteCnt, sizeof(remoteAddr) };
  316. if( cmTs1p1cEnqueueSegMsg( p->qH, msgPtrArray, msgByteCntArray, 2 ) != kOkThRC )
  317. cmErrMsg(&p->err,kQueueFailUdpRC,"A received msg containing %i bytes was not queued.",retByteCnt);
  318. }
  319. else // if queueing is not enabled - transmit the data directly via the callback
  320. if( p->cbFunc != NULL )
  321. {
  322. p->cbFunc(p->cbArg,p->tempBuf,retByteCnt,&remoteAddr);
  323. }
  324. }
  325. }
  326. }
  327. break;
  328. default:
  329. { assert(0); }
  330. } // switch
  331. return true;
  332. }
  333. cmRC_t _cmUdpQueueCb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
  334. {
  335. cmUdp_t* p = (cmUdp_t*)userCbPtr;
  336. if( p->cbFunc != NULL )
  337. {
  338. struct sockaddr_in addr;
  339. assert( msgByteCnt >= sizeof(addr));
  340. const char* dataPtr = (const char*)msgDataPtr;
  341. // the address of the data source is apppended to the data bytes.
  342. const char* addrPtr = dataPtr + msgByteCnt - sizeof(addr);
  343. memcpy(&addr,addrPtr,sizeof(addr));
  344. // make the receive callback
  345. p->cbFunc(p->cbArg,dataPtr,msgByteCnt-sizeof(addr),&addr);
  346. ++p->queCbCnt;
  347. }
  348. return cmOkRC;
  349. }
  350. cmUdpRC_t cmUdpEnableListen( cmUdpH_t h, bool enableFl )
  351. {
  352. cmUdp_t* p = _cmUdpHandleToPtr(h);
  353. if( cmThreadIsValid(p->thH) == false && enableFl == true)
  354. {
  355. if(cmThreadCreate(&p->thH,_cmUdpThreadCb,p,p->err.rpt) != kOkThRC )
  356. return cmErrMsg(&p->err,kThreadFailUdpRC,"Listener thread create failed.");
  357. if(cmTs1p1cCreate(&p->qH,p->recvBufByteCnt,_cmUdpQueueCb,p,p->err.rpt) != kOkThRC )
  358. return cmErrMsg(&p->err,kQueueFailUdpRC,"Listener data queue create failed.");
  359. }
  360. if( cmThreadIsValid(p->thH) )
  361. if( cmThreadPause( p->thH, enableFl ? 0 : kPauseThFl ) != kOkThRC )
  362. return cmErrMsg(&p->err,kThreadFailUdpRC,"The listener thread failed to %s.", enableFl ? "pause" : "un-pause" );
  363. return kOkUdpRC;
  364. }
  365. bool cmUdpIsQueueEnabled( cmUdpH_t h )
  366. {
  367. cmUdp_t* p = _cmUdpHandleToPtr(h);
  368. return cmIsFlag(p->flags,kQueueingUdpFl);
  369. }
  370. void cmUdpQueueEnable( cmUdpH_t h, bool enableFl )
  371. {
  372. cmUdp_t* p = _cmUdpHandleToPtr(h);
  373. p->flags = cmSetFlag(p->flags,kQueueingUdpFl);
  374. }
  375. unsigned cmUdpAvailDataByteCount( cmUdpH_t h )
  376. {
  377. cmUdp_t* p = _cmUdpHandleToPtr(h);
  378. return cmTs1p1cIsValid(p->qH) ? cmTs1p1cDequeueMsgByteCount( p->qH ) : 0;
  379. }
  380. cmUdpRC_t cmUdpGetAvailData( cmUdpH_t h, char* data, unsigned* dataByteCntPtr, struct sockaddr_in* fromAddr )
  381. {
  382. cmUdp_t* p = _cmUdpHandleToPtr(h);
  383. unsigned availByteCnt;
  384. // if a received msg is queued
  385. if( (availByteCnt = cmTs1p1cAvailByteCount(p->qH)) > 0 )
  386. {
  387. // all msg's must have at least a source address
  388. assert( availByteCnt >= sizeof(*fromAddr) );
  389. // get the size of the return buffer (or 0 if there is no return buffer)
  390. unsigned dataByteCnt = (data != NULL && dataByteCntPtr != NULL) ? *dataByteCntPtr : 0;
  391. if( dataByteCnt == 0 )
  392. data = NULL;
  393. // dequeue the msg - if data==NULL then the data will be returned by
  394. // a call to the callback function provided in cmUdpAlloc().
  395. if( cmTs1p1cDequeueMsg(p->qH, data, dataByteCnt ) != kOkThRC )
  396. return cmErrMsg(&p->err,kQueueFailUdpRC,"Data dequeue failed.");
  397. // if a return buffer was given
  398. if( data != NULL )
  399. {
  400. assert( dataByteCntPtr != NULL );
  401. // the source address is appended to the end of the data
  402. const char* addrPtr = data + availByteCnt - sizeof(*fromAddr);
  403. // copy out the source address
  404. if( fromAddr != NULL )
  405. memcpy(fromAddr,addrPtr,sizeof(*fromAddr));
  406. // subtract the address size from the total msg size
  407. *dataByteCntPtr = availByteCnt - sizeof(*fromAddr);
  408. }
  409. }
  410. return kOkUdpRC;
  411. }
  412. void cmUdpReport( cmUdpH_t h, cmRpt_t* rpt )
  413. {
  414. cmUdp_t* p = _cmUdpHandleToPtr(h);
  415. cmRptPrintf(rpt,"time-out:%i recv:%i queue cb:%i\n",p->timeOutCnt,p->recvCnt,p->queCbCnt);
  416. }
  417. cmUdpRC_t cmUdpInitAddr( cmUdpH_t h, const char* addrStr, cmUdpPort_t portNumber, struct sockaddr_in* retAddrPtr )
  418. {
  419. cmUdp_t* p = _cmUdpHandleToPtr(h);
  420. return _cmUdpInitAddr(p,addrStr,portNumber,retAddrPtr);
  421. }
  422. const cmChar_t* cmUdpAddrToString( cmUdpH_t h, const struct sockaddr_in* addr )
  423. {
  424. cmUdp_t* p = _cmUdpHandleToPtr(h);
  425. _cmUdpClear_errno();
  426. if( inet_ntop(AF_INET, &(addr->sin_addr), p->ntopBuf, INET_ADDRSTRLEN) == NULL)
  427. {
  428. cmErrSysMsg(&p->err,kNtoPFailUdpRC,errno, "Network address to string conversion failed." );
  429. return NULL;
  430. }
  431. p->ntopBuf[INET_ADDRSTRLEN]=0;
  432. return p->ntopBuf;
  433. }
  434. const cmChar_t* cmUdpHostName( cmUdpH_t h )
  435. {
  436. cmUdp_t* p = _cmUdpHandleToPtr(h);
  437. _cmUdpClear_errno();
  438. if( gethostname(p->hnameBuf,HOST_NAME_MAX) != 0 )
  439. {
  440. cmErrSysMsg(&p->err,kHostNameFailUdpRC,errno, "gethostname() failed." );
  441. return NULL;
  442. }
  443. p->hnameBuf[HOST_NAME_MAX] = 0;
  444. return p->hnameBuf;
  445. }