libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmUdpNet.c 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  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 "cmUdpPort.h"
  9. #include "cmJson.h"
  10. #include "cmUdpNet.h"
  11. #include "cmTime.h"
  12. typedef struct cmUdpNode_str
  13. {
  14. cmChar_t* label;
  15. unsigned id;
  16. struct sockaddr_in addr;
  17. cmUdpPort_t port;
  18. struct cmUdpNode_str* link;
  19. } cmUdpNode_t;
  20. typedef struct
  21. {
  22. cmErr_t err;
  23. cmUdpNetCallback_t cbFunc;
  24. void* cbArg;
  25. unsigned timeOutMs;
  26. unsigned nodeId;
  27. cmChar_t* nodeLabel;
  28. cmUdpNode_t* list;
  29. cmUdpH_t udpH;
  30. } cmUdpNet_t;
  31. cmUdpNetH_t cmUdpNetNullHandle = cmSTATIC_NULL_HANDLE;
  32. cmUdpNet_t* _cmUnHandleToPtr( cmUdpNetH_t h )
  33. {
  34. cmUdpNet_t* p = (cmUdpNet_t*)h.h;
  35. assert(p !=NULL );
  36. return p;
  37. }
  38. cmUnRC_t _cmUdpNetFinal( cmUdpNet_t* p )
  39. {
  40. // release the node list
  41. while( p->list != NULL)
  42. {
  43. cmUdpNode_t* np = p->list->link;
  44. cmMemFree(p->list->label);
  45. cmMemFree(p->list);
  46. p->list = np;
  47. }
  48. cmMemFree(p->nodeLabel);
  49. p->nodeLabel = NULL;
  50. p->cbFunc = NULL;
  51. p->cbArg = NULL;
  52. p->nodeId = cmInvalidId;
  53. return kOkUnRC;
  54. }
  55. cmUnRC_t _cmUdpNetFree( cmUdpNet_t* p )
  56. {
  57. cmUnRC_t rc;
  58. if((rc = _cmUdpNetFinal(p)) != kOkUnRC )
  59. return rc;
  60. // release the UDP port
  61. if( cmUdpFree(&p->udpH) != kOkUdpRC )
  62. return cmErrMsg(&p->err,kUdpPortFailUnRC,"The UDP port release failed.");
  63. cmMemFree(p);
  64. return kOkUnRC;
  65. }
  66. cmUdpNode_t* _cmUnFindLabel( cmUdpNet_t* p, const cmChar_t* label )
  67. {
  68. cmUdpNode_t* np = p->list;
  69. for(; np != NULL; np = np->link )
  70. if( strcmp(np->label,label) == 0 )
  71. return np;
  72. return NULL;
  73. }
  74. cmUdpNode_t* _cmUnFindId( cmUdpNet_t* p, unsigned id )
  75. {
  76. cmUdpNode_t* np = p->list;
  77. for(; np != NULL; np = np->link )
  78. if( np->id == id )
  79. return np;
  80. return NULL;
  81. }
  82. void _cmUdpNetCallback( void* cbArg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
  83. {
  84. cmUdpNet_t* p = (cmUdpNet_t*)cbArg;
  85. if( p->cbFunc != NULL )
  86. {
  87. cmUdpNetH_t h;
  88. cmUdpNode_t* np = p->list;
  89. h.h = p;
  90. // locate the source node in the node list to get the source node id
  91. for(; np != NULL; np = np->link)
  92. if( np->addr.sin_addr.s_addr == fromAddr->sin_addr.s_addr )
  93. {
  94. // forward the call to the networks callback function
  95. p->cbFunc(p->cbArg,h,data,dataByteCnt,np->id);
  96. break;
  97. }
  98. if( np == NULL )
  99. cmErrMsg(&p->err,kNodeNotFoundUnRC,"A callback source node could not be identified.");
  100. }
  101. }
  102. cmUnRC_t cmUdpNetAlloc(cmCtx_t* ctx, cmUdpNetH_t* hp)
  103. {
  104. cmUnRC_t rc;
  105. if((rc = cmUdpNetFree(hp)) != kOkUnRC )
  106. return rc;
  107. cmUdpNet_t* p = cmMemAllocZ(cmUdpNet_t,1);
  108. cmErrSetup(&p->err,&ctx->rpt,"UDP Network");
  109. if( cmUdpAlloc(ctx,&p->udpH) != kOkUdpRC )
  110. return cmErrMsg(&p->err,kUdpPortFailUnRC,"UDP port allocation failed.");
  111. p->nodeId = cmInvalidId;
  112. hp->h = p;
  113. return kOkUnRC;
  114. }
  115. cmUnRC_t cmUdpNetAllocJson(
  116. cmCtx_t* ctx,
  117. cmUdpNetH_t* hp,
  118. cmJsonH_t jsH,
  119. cmUdpNetCallback_t cbFunc,
  120. void* cbArg,
  121. unsigned flags)
  122. {
  123. cmUnRC_t rc;
  124. if((rc = cmUdpNetAlloc(ctx,hp)) != kOkUnRC )
  125. return rc;
  126. if((rc = cmUdpNetInitJson(*hp,jsH,cbFunc,cbArg)) != kOkUnRC )
  127. {
  128. if( cmIsFlag(flags,kNetOptionalUnFl) )
  129. rc = kOkUnRC;
  130. goto errLabel;
  131. }
  132. if((rc = cmUdpNetEnableListen(*hp,cmIsFlag(flags,kListenUnFl))) != kOkUnRC )
  133. goto errLabel;
  134. errLabel:
  135. if( rc != kOkUnRC )
  136. cmUdpNetFree(hp);
  137. return rc;
  138. }
  139. cmUnRC_t cmUdpNetFree( cmUdpNetH_t* hp )
  140. {
  141. cmUnRC_t rc = kOkUnRC;
  142. if( hp == NULL || cmUdpNetIsValid(*hp)==false )
  143. return kOkUnRC;
  144. cmUdpNet_t* p = _cmUnHandleToPtr(*hp);
  145. if((rc = _cmUdpNetFree(p)) != kOkUnRC )
  146. return rc;
  147. hp->h = NULL;
  148. return rc;
  149. }
  150. cmUnRC_t cmUdpNetInit(
  151. cmUdpNetH_t h,
  152. const cmChar_t* nodeLabel,
  153. unsigned nodeId,
  154. cmUdpPort_t nodeSocketPort,
  155. cmUdpNetCallback_t cbFunc,
  156. void* cbArg,
  157. unsigned recvBufByteCnt,
  158. unsigned socketRecvTimeOutMs )
  159. {
  160. cmUnRC_t rc;
  161. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  162. if((rc = _cmUdpNetFinal(p)) != kOkUnRC )
  163. return rc;
  164. // create the UDP port
  165. if( cmUdpInit(p->udpH,nodeSocketPort,kBlockingUdpFl,_cmUdpNetCallback,p,NULL,0,recvBufByteCnt,socketRecvTimeOutMs) != kOkUdpRC )
  166. {
  167. rc = cmErrMsg(&p->err,kUdpPortFailUnRC,"The UDP port create failed.");
  168. goto errLabel;
  169. }
  170. p->cbFunc = cbFunc;
  171. p->cbArg = cbArg;
  172. p->timeOutMs = socketRecvTimeOutMs;
  173. p->nodeId = nodeId;
  174. p->nodeLabel = cmMemAllocStr(nodeLabel);
  175. p->list = NULL;
  176. errLabel:
  177. if( rc != kOkUnRC )
  178. _cmUdpNetFinal(p);
  179. return rc;
  180. }
  181. cmUnRC_t _cmUnParseMemberErr( cmUdpNet_t* p, cmJsRC_t jsRC, const cmChar_t* errLabel, const cmChar_t* objectLabel )
  182. {
  183. if( jsRC == kNodeNotFoundJsRC && errLabel != NULL )
  184. return cmErrMsg(&p->err,kJsonFailUnRC,"The required field '%s'was not found in the UDP network resource tree in the object '%s'.",errLabel,cmStringNullGuard(objectLabel));
  185. return cmErrMsg(&p->err,kJsonFailUnRC,"JSON parsing failed on the UDP network resource object '%s'.",cmStringNullGuard(objectLabel));
  186. }
  187. cmUnRC_t cmUdpNetInitJson(
  188. cmUdpNetH_t h,
  189. cmJsonH_t jsH,
  190. cmUdpNetCallback_t cbFunc,
  191. void* cbArg)
  192. {
  193. cmUnRC_t rc;
  194. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  195. cmJsonNode_t* unp;
  196. cmJsonNode_t* nap;
  197. const cmChar_t* errLabelPtr = NULL;
  198. cmJsRC_t jsRC;
  199. unsigned port,recvBufByteCnt,timeOutMs;
  200. const cmChar_t* localLabel;
  201. const cmChar_t* topLabel = "udpnet";
  202. unsigned nodeCnt = 0;
  203. unsigned i;
  204. typedef struct
  205. {
  206. const cmChar_t* label;
  207. const cmChar_t* addr;
  208. unsigned id;
  209. } unNode_t;
  210. unNode_t* a = NULL;
  211. unNode_t* localPtr = NULL;
  212. if((rc = _cmUdpNetFinal(p)) != kOkUnRC )
  213. return rc;
  214. if((unp = cmJsonFindValue(jsH,topLabel,NULL,kObjectTId )) == NULL )
  215. {
  216. return cmErrMsg(&p->err,kJsonFailUnRC,"The JSON 'udpnet' element was not found.");
  217. }
  218. if(( jsRC = cmJsonMemberValues( unp, &errLabelPtr,
  219. "port", kIntTId, &port,
  220. "recvBufByteCnt", kIntTId, &recvBufByteCnt,
  221. "timeOutMs", kIntTId, &timeOutMs,
  222. "local", kStringTId,&localLabel,
  223. "nodeArray", kArrayTId, &nap,
  224. NULL )) != kOkJsRC )
  225. {
  226. rc = _cmUnParseMemberErr(p, jsRC, errLabelPtr, topLabel );
  227. goto errLabel;
  228. }
  229. // get a count of the number of nodes
  230. if((nodeCnt = cmJsonChildCount(nap)) == 0 )
  231. {
  232. rc = cmErrMsg(&p->err,kJsonFailUnRC,"The JSON 'udpnet' node array appears to be empty.");
  233. goto errLabel;
  234. }
  235. // allocate a temporary array to hold the node list
  236. a = cmMemAllocZ(unNode_t,nodeCnt);
  237. // for each remote node
  238. for(i=0; i<nodeCnt; ++i)
  239. {
  240. const cmJsonNode_t* naep = cmJsonArrayElementC(nap,i);
  241. // read the JSON recd
  242. if(( jsRC = cmJsonMemberValues( naep, &errLabelPtr,
  243. "label", kStringTId, &a[i].label,
  244. "id", kIntTId, &a[i].id,
  245. "addr", kStringTId, &a[i].addr,
  246. NULL )) != kOkJsRC )
  247. {
  248. rc = _cmUnParseMemberErr(p, jsRC, errLabelPtr, "nodeArray" );
  249. goto errLabel;
  250. }
  251. // track which node is the local node
  252. if( strcmp(localLabel,a[i].label) == 0 )
  253. localPtr = a + i;
  254. }
  255. // if no local node was located
  256. if( localPtr == NULL )
  257. {
  258. rc = cmErrMsg(&p->err, kJsonFailUnRC,"The local node label '%s' was not found.",cmStringNullGuard(localLabel));
  259. goto errLabel;
  260. }
  261. // initialize the network object
  262. if((rc = cmUdpNetInit(h,localPtr->label, localPtr->id, port, cbFunc, cbArg, recvBufByteCnt, timeOutMs )) != kOkUnRC )
  263. goto errLabel;
  264. // register each remote node
  265. for(i=0; i<nodeCnt; ++i)
  266. if( a + i != localPtr )
  267. if((rc = cmUdpNetRegisterRemote(h,a[i].label,a[i].id,a[i].addr,port)) != kOkUnRC )
  268. goto errLabel;
  269. errLabel:
  270. cmMemFree(a);
  271. if( rc != kOkUnRC )
  272. _cmUdpNetFinal(p);
  273. return rc;
  274. }
  275. bool cmUdpNetIsInitialized( cmUdpNetH_t h )
  276. {
  277. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  278. return p->nodeId != cmInvalidId;
  279. }
  280. cmUnRC_t cmUdpNetFinal( cmUdpNetH_t h )
  281. {
  282. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  283. return _cmUdpNetFinal(p);
  284. }
  285. cmUnRC_t cmUdpNetEnableListen( cmUdpNetH_t h, bool enableFl )
  286. {
  287. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  288. if( cmUdpEnableListen(p->udpH,enableFl) != kOkUdpRC )
  289. return cmErrMsg(&p->err,kUdpPortFailUnRC,"UDP port listen %s failed.",enableFl?"enable":"disable");
  290. return kOkUnRC;
  291. }
  292. bool cmUdpNetIsValid( cmUdpNetH_t h )
  293. { return h.h != NULL; }
  294. unsigned cmUdpNetLocalNodeId( cmUdpNetH_t h )
  295. {
  296. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  297. return p->nodeId;
  298. }
  299. const cmChar_t* cmUdpNetLocalNodeLabel( cmUdpNetH_t h )
  300. {
  301. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  302. return p->nodeLabel;
  303. }
  304. unsigned cmUdpNetNodeLabelToId( cmUdpNetH_t h, const cmChar_t* label )
  305. {
  306. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  307. // if the network was not initialized then nodeLabel == NULL
  308. if( p->nodeLabel == NULL )
  309. return cmInvalidId;
  310. // if 'label' refers to the local node
  311. if( strcmp(label,p->nodeLabel) == 0 )
  312. return p->nodeId;
  313. // otherwise search the remote node list
  314. cmUdpNode_t* np = p->list;
  315. for(; np != NULL; np = np->link )
  316. if( strcmp(np->label,label) == 0 )
  317. return np->id;
  318. return cmInvalidId;
  319. }
  320. const cmChar_t* cmUdpNetNodeIdToLabel( cmUdpNetH_t h, unsigned id )
  321. {
  322. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  323. // if 'id' refers to the local node
  324. if( id == p->nodeId )
  325. return p->nodeLabel;
  326. // otherwise search the remote node list
  327. cmUdpNode_t* np = p->list;
  328. for(; np != NULL; np = np->link )
  329. if( np->id == id )
  330. return np->label;
  331. return NULL;
  332. }
  333. unsigned cmUdpNetNodeCount( cmUdpNetH_t h )
  334. {
  335. unsigned cnt = 0;
  336. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  337. cmUdpNode_t* np = p->list;
  338. for(; np != NULL; np = np->link )
  339. ++cnt;
  340. return cnt;
  341. }
  342. unsigned cmUdpNetNodeId( cmUdpNetH_t h, unsigned nodeIdx )
  343. {
  344. unsigned cnt = 0;
  345. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  346. cmUdpNode_t* np = p->list;
  347. for(; np != NULL; np = np->link )
  348. if( cnt == nodeIdx )
  349. return np->id;
  350. return cmInvalidId;
  351. }
  352. cmUnRC_t cmUdpNetRegisterRemote(
  353. cmUdpNetH_t h,
  354. const cmChar_t* remoteNodeLabel,
  355. unsigned remoteNodeId,
  356. const char* remoteNodeSockAddr,
  357. cmUdpPort_t remoteNodePort )
  358. {
  359. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  360. struct sockaddr_in addr;
  361. if( remoteNodeLabel == NULL || strlen(remoteNodeLabel)==0 )
  362. return cmErrMsg(&p->err,kInvalidNodeLabelUnRC,"The node label must contain a non-empty string.");
  363. if( _cmUnFindLabel(p,remoteNodeLabel) != NULL )
  364. return cmErrMsg(&p->err,kDuplicateNodeLabelUnRC,"The node label '%s' is already in use.",cmStringNullGuard(remoteNodeLabel));
  365. if( _cmUnFindId(p,remoteNodeId) != NULL )
  366. return cmErrMsg(&p->err,kDuplicateNodeIdUnRC,"The node id '%i' is already in use.",remoteNodeId);
  367. if( cmUdpInitAddr(p->udpH, remoteNodeSockAddr, remoteNodePort, &addr ) != kOkUdpRC )
  368. return cmErrMsg(&p->err,kInvalidNodeAddrUnRC,"The node address '%s' port:%i is not valid.",cmStringNullGuard(remoteNodeSockAddr),remoteNodePort);
  369. cmUdpNode_t* np = cmMemAllocZ(cmUdpNode_t,1);
  370. np->label = cmMemAllocStr(remoteNodeLabel);
  371. np->id = remoteNodeId;
  372. np->addr = addr;
  373. np->port = remoteNodePort;
  374. np->link = p->list;
  375. p->list = np;
  376. return kOkUnRC;
  377. }
  378. cmUnRC_t cmUdpNetSendById( cmUdpNetH_t h, unsigned remoteNodeId, const void* data, unsigned dataByteCnt )
  379. {
  380. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  381. cmUdpNode_t* np;
  382. if((np = _cmUnFindId(p,remoteNodeId)) == NULL )
  383. return cmErrMsg(&p->err,kNodeNotFoundUnRC,"The remote node (id=%i) was not found.",remoteNodeId);
  384. if( cmUdpSendTo(p->udpH, data, dataByteCnt, &np->addr ) != kOkUdpRC )
  385. return cmErrMsg(&p->err,kSendFailUnRC,"An attempt to send to a remote node with id=%i failed.",remoteNodeId);
  386. return kOkUnRC;
  387. }
  388. cmUnRC_t cmUdpNetSendByLabel( cmUdpNetH_t h, const cmChar_t* remoteNodeLabel, const void* data, unsigned dataByteCnt )
  389. {
  390. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  391. cmUdpNode_t* np;
  392. if((np = _cmUnFindLabel(p,remoteNodeLabel)) == NULL )
  393. return cmErrMsg(&p->err,kNodeNotFoundUnRC,"The remote node (label=%s) was not found.",cmStringNullGuard(remoteNodeLabel));
  394. if( cmUdpSendTo(p->udpH, data, dataByteCnt, &np->addr ) != kOkUdpRC )
  395. return cmErrMsg(&p->err,kSendFailUnRC,"An attempt to send to the remote node labeled:%s failed.",cmStringNullGuard(remoteNodeLabel));
  396. return kOkUnRC;
  397. }
  398. cmUnRC_t cmUdpNetReceive( cmUdpNetH_t h, unsigned* msgCntPtr )
  399. {
  400. cmUnRC_t rc = kOkUnRC;
  401. unsigned maxMsgCnt = 0;
  402. unsigned msgCnt = 0;
  403. if( msgCntPtr == NULL )
  404. maxMsgCnt = cmInvalidCnt;
  405. else
  406. maxMsgCnt = *msgCntPtr;
  407. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  408. if( cmUdpIsValid(p->udpH ) )
  409. {
  410. for(msgCnt=0; (maxMsgCnt==cmInvalidCnt || msgCnt<maxMsgCnt) && cmUdpAvailDataByteCount(p->udpH); ++msgCnt )
  411. {
  412. if( cmUdpGetAvailData(p->udpH,NULL,NULL,NULL) != kOkUdpRC )
  413. {
  414. rc = cmErrMsg(&p->err,kGetDataFailUnRC,"An attempt to get available message data failed.");
  415. break;
  416. }
  417. }
  418. }
  419. if( msgCntPtr != NULL )
  420. *msgCntPtr = msgCnt;
  421. return rc;
  422. }
  423. cmUnRC_t cmUdpNetPrintNodes( cmUdpNetH_t h, cmRpt_t* rpt )
  424. {
  425. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  426. cmUdpNode_t* np = p->list;
  427. unsigned i;
  428. for(i=0; np != NULL; np = np->link, ++i )
  429. cmRptPrintf(rpt,"%5i %5i %s\n",i,np->id,np->label);
  430. return kOkUnRC;
  431. }
  432. void cmUdpNetReport( cmUdpNetH_t h, cmRpt_t* rpt )
  433. {
  434. cmUdpNet_t* p = _cmUnHandleToPtr(h);
  435. cmUdpReport(p->udpH,rpt);
  436. }
  437. //=========================================================================================
  438. typedef struct
  439. {
  440. cmTimeSpec_t t;
  441. unsigned localNodeId;
  442. cmUdpNetH_t h;
  443. } _cmUdpNetTestMsg_t;
  444. void _cmUdpNetTestCb( void* cbArg, cmUdpNetH_t h, const char* data, unsigned dataByteCnt, unsigned remoteNodeId )
  445. {
  446. cmRpt_t* rpt = (cmRpt_t*)cbArg;
  447. cmRptPrintf(rpt,"recv - id:%i %s\n",remoteNodeId, data);
  448. }
  449. void _cmUdpNetTestCb2( void* cbArg, cmUdpNetH_t h, const char* data, unsigned dataByteCnt, unsigned remoteNodeId )
  450. {
  451. _cmUdpNetTestMsg_t* m = (_cmUdpNetTestMsg_t*)data;
  452. cmRpt_t* rpt = (cmRpt_t*)cbArg;
  453. assert( dataByteCnt == sizeof(_cmUdpNetTestMsg_t));
  454. if( m->localNodeId == cmUdpNetLocalNodeId(h) )
  455. {
  456. cmTimeSpec_t t;
  457. cmTimeGet(&t);
  458. cmRptPrintf(rpt,"elapsed:%i\n", cmTimeElapsedMicros(&m->t,&t));
  459. }
  460. else
  461. {
  462. cmRptPrintf(rpt,"echo\n");
  463. cmUdpNetSendById(h,m->localNodeId,&m,sizeof(*m));
  464. }
  465. }
  466. const cmChar_t* _cmUdpNetTestGetOpt( int argc, const char* argv[], const char* opt )
  467. {
  468. unsigned i;
  469. for(i=0; i<argc; ++i)
  470. if( strcmp(argv[i],opt) == 0 )
  471. return argv[i+1];
  472. return NULL;
  473. }
  474. cmRC_t cmUdpNetTest( cmCtx_t* ctx, int argc, const char* argv[] )
  475. {
  476. cmUdpNetH_t h = cmUdpNetNullHandle;
  477. cmJsonH_t jsH = cmJsonNullHandle;
  478. cmErr_t err;
  479. cmRC_t rc = cmOkRC;
  480. unsigned i = 0;
  481. const cmChar_t* jsonFn;
  482. const cmChar_t* remoteNodeLabel;
  483. unsigned strCharCnt = 31;
  484. cmChar_t str[ strCharCnt + 1 ];
  485. bool msgFl = false;
  486. enum { kUdpNetTestErrRC = 1 };
  487. cmErrSetup(&err,&ctx->rpt,"UDP Net Test");
  488. // get the JSON file name
  489. if(( jsonFn = _cmUdpNetTestGetOpt(argc,argv,"-j")) == NULL)
  490. return cmErrMsg(&err,kUdpNetTestErrRC,"No JSON file name was given.");
  491. // get the remote node label to send too
  492. if(( remoteNodeLabel= _cmUdpNetTestGetOpt(argc,argv,"-n")) == NULL )
  493. return cmErrMsg(&err,kUdpNetTestErrRC,"No remote node label was given.");
  494. // create the JSON tree
  495. if( cmJsonInitializeFromFile(&jsH, jsonFn, ctx ) != kOkJsRC )
  496. {
  497. rc = cmErrMsg(&err,kUdpNetTestErrRC,"JSON file init failed on '%s'.",cmStringNullGuard(jsonFn));
  498. goto errLabel;
  499. }
  500. if( msgFl )
  501. {
  502. // alloc/init and put the network into listening mode
  503. if( cmUdpNetAllocJson(ctx,&h,jsH,_cmUdpNetTestCb2,&ctx->rpt,kListenUnFl) != kOkUnRC )
  504. {
  505. rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP alloc/init/listen failed.");
  506. goto errLabel;
  507. }
  508. }
  509. else
  510. {
  511. if( cmUdpNetAlloc(ctx,&h) != kOkUnRC )
  512. return cmErrMsg(&err,kUdpNetTestErrRC,"UDP alloc failed.");
  513. if( cmUdpNetInitJson(h,jsH,_cmUdpNetTestCb,&ctx->rpt) != kOkUnRC )
  514. {
  515. rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP net init failed.");
  516. goto errLabel;
  517. }
  518. if( cmUdpNetEnableListen(h,true) != kOkUnRC )
  519. {
  520. rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP listen enable failed.");
  521. goto errLabel;
  522. }
  523. }
  524. cmRptPrintf(&ctx->rpt,"s=send p=print r=report\n");
  525. char c;
  526. while((c=getchar()) != 'q')
  527. {
  528. bool promptFl = true;
  529. switch(c)
  530. {
  531. case 's':
  532. {
  533. // form the emessage
  534. snprintf(str,strCharCnt,"msg=%i",i);
  535. // send a message to the remote node
  536. if( !msgFl )
  537. if( cmUdpNetSendByLabel(h,remoteNodeLabel,str,strlen(str)+1 ) != kOkUnRC )
  538. cmErrMsg(&err,kUdpNetTestErrRC,"UDP net send failed.");
  539. ++i;
  540. }
  541. break;
  542. case 't':
  543. {
  544. _cmUdpNetTestMsg_t m;
  545. cmTimeGet(&m.t);
  546. m.localNodeId = cmUdpNetLocalNodeId(h);
  547. m.h = h;
  548. // send a message to the remote node
  549. if( msgFl )
  550. if( cmUdpNetSendByLabel(h,remoteNodeLabel,&m,sizeof(m) ) != kOkUnRC )
  551. cmErrMsg(&err,kUdpNetTestErrRC,"UDP net send failed.");
  552. }
  553. break;
  554. case 'p':
  555. cmUdpNetPrintNodes(h,&ctx->rpt);
  556. break;
  557. case 'r':
  558. cmUdpNetReport(h,&ctx->rpt);
  559. break;
  560. default:
  561. promptFl = false;
  562. }
  563. cmUdpNetReceive(h,NULL);
  564. if( promptFl )
  565. cmRptPrintf(&ctx->rpt,"%i> ",i);
  566. }
  567. errLabel:
  568. if( cmUdpNetFree(&h) != kOkUnRC )
  569. rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP free failed.");
  570. if( cmJsonFinalize(&jsH) != kOkJsRC )
  571. rc = cmErrMsg(&err,kUdpNetTestErrRC,"JSON final fail.");
  572. return rc;
  573. }