731 lines
18 KiB
C
731 lines
18 KiB
C
#include "cmPrefix.h"
|
|
#include "cmGlobal.h"
|
|
#include "cmRpt.h"
|
|
#include "cmErr.h"
|
|
#include "cmCtx.h"
|
|
#include "cmMem.h"
|
|
#include "cmMallocDebug.h"
|
|
#include "cmUdpPort.h"
|
|
#include "cmJson.h"
|
|
#include "cmUdpNet.h"
|
|
#include "cmTime.h"
|
|
|
|
typedef struct cmUdpNode_str
|
|
{
|
|
cmChar_t* label;
|
|
unsigned id;
|
|
struct sockaddr_in addr;
|
|
cmUdpPort_t port;
|
|
struct cmUdpNode_str* link;
|
|
} cmUdpNode_t;
|
|
|
|
typedef struct
|
|
{
|
|
cmErr_t err;
|
|
cmUdpNetCallback_t cbFunc;
|
|
void* cbArg;
|
|
unsigned timeOutMs;
|
|
unsigned nodeId;
|
|
cmChar_t* nodeLabel;
|
|
cmUdpNode_t* list;
|
|
cmUdpH_t udpH;
|
|
} cmUdpNet_t;
|
|
|
|
cmUdpNetH_t cmUdpNetNullHandle = cmSTATIC_NULL_HANDLE;
|
|
|
|
cmUdpNet_t* _cmUnHandleToPtr( cmUdpNetH_t h )
|
|
{
|
|
cmUdpNet_t* p = (cmUdpNet_t*)h.h;
|
|
assert(p !=NULL );
|
|
return p;
|
|
}
|
|
|
|
cmUnRC_t _cmUdpNetFinal( cmUdpNet_t* p )
|
|
{
|
|
// release the node list
|
|
while( p->list != NULL)
|
|
{
|
|
cmUdpNode_t* np = p->list->link;
|
|
cmMemFree(p->list->label);
|
|
cmMemFree(p->list);
|
|
p->list = np;
|
|
}
|
|
|
|
cmMemFree(p->nodeLabel);
|
|
|
|
p->nodeLabel = NULL;
|
|
p->cbFunc = NULL;
|
|
p->cbArg = NULL;
|
|
p->nodeId = cmInvalidId;
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
cmUnRC_t _cmUdpNetFree( cmUdpNet_t* p )
|
|
{
|
|
cmUnRC_t rc;
|
|
if((rc = _cmUdpNetFinal(p)) != kOkUnRC )
|
|
return rc;
|
|
|
|
// release the UDP port
|
|
if( cmUdpFree(&p->udpH) != kOkUdpRC )
|
|
return cmErrMsg(&p->err,kUdpPortFailUnRC,"The UDP port release failed.");
|
|
|
|
cmMemFree(p);
|
|
return kOkUnRC;
|
|
}
|
|
|
|
|
|
cmUdpNode_t* _cmUnFindLabel( cmUdpNet_t* p, const cmChar_t* label )
|
|
{
|
|
cmUdpNode_t* np = p->list;
|
|
for(; np != NULL; np = np->link )
|
|
if( strcmp(np->label,label) == 0 )
|
|
return np;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
cmUdpNode_t* _cmUnFindId( cmUdpNet_t* p, unsigned id )
|
|
{
|
|
cmUdpNode_t* np = p->list;
|
|
for(; np != NULL; np = np->link )
|
|
if( np->id == id )
|
|
return np;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void _cmUdpNetCallback( void* cbArg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
|
|
{
|
|
cmUdpNet_t* p = (cmUdpNet_t*)cbArg;
|
|
|
|
if( p->cbFunc != NULL )
|
|
{
|
|
cmUdpNetH_t h;
|
|
cmUdpNode_t* np = p->list;
|
|
h.h = p;
|
|
|
|
// locate the source node in the node list to get the source node id
|
|
for(; np != NULL; np = np->link)
|
|
if( np->addr.sin_addr.s_addr == fromAddr->sin_addr.s_addr )
|
|
{
|
|
// forward the call to the networks callback function
|
|
p->cbFunc(p->cbArg,h,data,dataByteCnt,np->id);
|
|
break;
|
|
}
|
|
|
|
if( np == NULL )
|
|
cmErrMsg(&p->err,kNodeNotFoundUnRC,"A callback source node could not be identified.");
|
|
|
|
}
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetAlloc(cmCtx_t* ctx, cmUdpNetH_t* hp)
|
|
{
|
|
cmUnRC_t rc;
|
|
if((rc = cmUdpNetFree(hp)) != kOkUnRC )
|
|
return rc;
|
|
|
|
cmUdpNet_t* p = cmMemAllocZ(cmUdpNet_t,1);
|
|
|
|
cmErrSetup(&p->err,&ctx->rpt,"UDP Network");
|
|
|
|
if( cmUdpAlloc(ctx,&p->udpH) != kOkUdpRC )
|
|
return cmErrMsg(&p->err,kUdpPortFailUnRC,"UDP port allocation failed.");
|
|
|
|
p->nodeId = cmInvalidId;
|
|
hp->h = p;
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetAllocJson(
|
|
cmCtx_t* ctx,
|
|
cmUdpNetH_t* hp,
|
|
cmJsonH_t jsH,
|
|
cmUdpNetCallback_t cbFunc,
|
|
void* cbArg,
|
|
unsigned flags)
|
|
{
|
|
cmUnRC_t rc;
|
|
|
|
if((rc = cmUdpNetAlloc(ctx,hp)) != kOkUnRC )
|
|
return rc;
|
|
|
|
if((rc = cmUdpNetInitJson(*hp,jsH,cbFunc,cbArg)) != kOkUnRC )
|
|
{
|
|
if( cmIsFlag(flags,kNetOptionalUnFl) )
|
|
rc = kOkUnRC;
|
|
|
|
goto errLabel;
|
|
}
|
|
|
|
if((rc = cmUdpNetEnableListen(*hp,cmIsFlag(flags,kListenUnFl))) != kOkUnRC )
|
|
goto errLabel;
|
|
|
|
errLabel:
|
|
if( rc != kOkUnRC )
|
|
cmUdpNetFree(hp);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
cmUnRC_t cmUdpNetFree( cmUdpNetH_t* hp )
|
|
{
|
|
cmUnRC_t rc = kOkUnRC;
|
|
|
|
if( hp == NULL || cmUdpNetIsValid(*hp)==false )
|
|
return kOkUnRC;
|
|
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(*hp);
|
|
|
|
if((rc = _cmUdpNetFree(p)) != kOkUnRC )
|
|
return rc;
|
|
|
|
hp->h = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
cmUnRC_t cmUdpNetInit(
|
|
cmUdpNetH_t h,
|
|
const cmChar_t* nodeLabel,
|
|
unsigned nodeId,
|
|
cmUdpPort_t nodeSocketPort,
|
|
cmUdpNetCallback_t cbFunc,
|
|
void* cbArg,
|
|
unsigned recvBufByteCnt,
|
|
unsigned socketRecvTimeOutMs )
|
|
{
|
|
cmUnRC_t rc;
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
|
|
if((rc = _cmUdpNetFinal(p)) != kOkUnRC )
|
|
return rc;
|
|
|
|
// create the UDP port
|
|
if( cmUdpInit(p->udpH,nodeSocketPort,kBlockingUdpFl,_cmUdpNetCallback,p,NULL,0,recvBufByteCnt,socketRecvTimeOutMs) != kOkUdpRC )
|
|
{
|
|
rc = cmErrMsg(&p->err,kUdpPortFailUnRC,"The UDP port create failed.");
|
|
goto errLabel;
|
|
}
|
|
|
|
p->cbFunc = cbFunc;
|
|
p->cbArg = cbArg;
|
|
p->timeOutMs = socketRecvTimeOutMs;
|
|
p->nodeId = nodeId;
|
|
p->nodeLabel = cmMemAllocStr(nodeLabel);
|
|
p->list = NULL;
|
|
|
|
errLabel:
|
|
|
|
if( rc != kOkUnRC )
|
|
_cmUdpNetFinal(p);
|
|
|
|
return rc;
|
|
}
|
|
|
|
cmUnRC_t _cmUnParseMemberErr( cmUdpNet_t* p, cmJsRC_t jsRC, const cmChar_t* errLabel, const cmChar_t* objectLabel )
|
|
{
|
|
if( jsRC == kNodeNotFoundJsRC && errLabel != NULL )
|
|
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));
|
|
|
|
return cmErrMsg(&p->err,kJsonFailUnRC,"JSON parsing failed on the UDP network resource object '%s'.",cmStringNullGuard(objectLabel));
|
|
|
|
}
|
|
|
|
|
|
cmUnRC_t cmUdpNetInitJson(
|
|
cmUdpNetH_t h,
|
|
cmJsonH_t jsH,
|
|
cmUdpNetCallback_t cbFunc,
|
|
void* cbArg)
|
|
{
|
|
cmUnRC_t rc;
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmJsonNode_t* unp;
|
|
cmJsonNode_t* nap;
|
|
const cmChar_t* errLabelPtr = NULL;
|
|
cmJsRC_t jsRC;
|
|
unsigned port,recvBufByteCnt,timeOutMs;
|
|
const cmChar_t* localLabel;
|
|
const cmChar_t* topLabel = "udpnet";
|
|
unsigned nodeCnt = 0;
|
|
unsigned i;
|
|
|
|
typedef struct
|
|
{
|
|
const cmChar_t* label;
|
|
const cmChar_t* addr;
|
|
unsigned id;
|
|
} unNode_t;
|
|
|
|
unNode_t* a = NULL;
|
|
|
|
unNode_t* localPtr = NULL;
|
|
|
|
if((rc = _cmUdpNetFinal(p)) != kOkUnRC )
|
|
return rc;
|
|
|
|
if((unp = cmJsonFindValue(jsH,topLabel,NULL,kObjectTId )) == NULL )
|
|
{
|
|
return cmErrMsg(&p->err,kJsonFailUnRC,"The JSON 'udpnet' element was not found.");
|
|
}
|
|
if(( jsRC = cmJsonMemberValues( unp, &errLabelPtr,
|
|
"port", kIntTId, &port,
|
|
"recvBufByteCnt", kIntTId, &recvBufByteCnt,
|
|
"timeOutMs", kIntTId, &timeOutMs,
|
|
"local", kStringTId,&localLabel,
|
|
"nodeArray", kArrayTId, &nap,
|
|
NULL )) != kOkJsRC )
|
|
{
|
|
rc = _cmUnParseMemberErr(p, jsRC, errLabelPtr, topLabel );
|
|
goto errLabel;
|
|
}
|
|
|
|
|
|
// get a count of the number of nodes
|
|
if((nodeCnt = cmJsonChildCount(nap)) == 0 )
|
|
{
|
|
rc = cmErrMsg(&p->err,kJsonFailUnRC,"The JSON 'udpnet' node array appears to be empty.");
|
|
goto errLabel;
|
|
}
|
|
|
|
// allocate a temporary array to hold the node list
|
|
a = cmMemAllocZ(unNode_t,nodeCnt);
|
|
|
|
// for each remote node
|
|
for(i=0; i<nodeCnt; ++i)
|
|
{
|
|
const cmJsonNode_t* naep = cmJsonArrayElementC(nap,i);
|
|
|
|
// read the JSON recd
|
|
if(( jsRC = cmJsonMemberValues( naep, &errLabelPtr,
|
|
"label", kStringTId, &a[i].label,
|
|
"id", kIntTId, &a[i].id,
|
|
"addr", kStringTId, &a[i].addr,
|
|
NULL )) != kOkJsRC )
|
|
{
|
|
rc = _cmUnParseMemberErr(p, jsRC, errLabelPtr, "nodeArray" );
|
|
goto errLabel;
|
|
}
|
|
|
|
// track which node is the local node
|
|
if( strcmp(localLabel,a[i].label) == 0 )
|
|
localPtr = a + i;
|
|
}
|
|
|
|
// if no local node was located
|
|
if( localPtr == NULL )
|
|
{
|
|
rc = cmErrMsg(&p->err, kJsonFailUnRC,"The local node label '%s' was not found.",cmStringNullGuard(localLabel));
|
|
goto errLabel;
|
|
}
|
|
|
|
// initialize the network object
|
|
if((rc = cmUdpNetInit(h,localPtr->label, localPtr->id, port, cbFunc, cbArg, recvBufByteCnt, timeOutMs )) != kOkUnRC )
|
|
goto errLabel;
|
|
|
|
// register each remote node
|
|
for(i=0; i<nodeCnt; ++i)
|
|
if( a + i != localPtr )
|
|
if((rc = cmUdpNetRegisterRemote(h,a[i].label,a[i].id,a[i].addr,port)) != kOkUnRC )
|
|
goto errLabel;
|
|
|
|
errLabel:
|
|
cmMemFree(a);
|
|
|
|
if( rc != kOkUnRC )
|
|
_cmUdpNetFinal(p);
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool cmUdpNetIsInitialized( cmUdpNetH_t h )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
return p->nodeId != cmInvalidId;
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetFinal( cmUdpNetH_t h )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
return _cmUdpNetFinal(p);
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetEnableListen( cmUdpNetH_t h, bool enableFl )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
|
|
if( cmUdpEnableListen(p->udpH,enableFl) != kOkUdpRC )
|
|
return cmErrMsg(&p->err,kUdpPortFailUnRC,"UDP port listen %s failed.",enableFl?"enable":"disable");
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
bool cmUdpNetIsValid( cmUdpNetH_t h )
|
|
{ return h.h != NULL; }
|
|
|
|
unsigned cmUdpNetLocalNodeId( cmUdpNetH_t h )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
return p->nodeId;
|
|
}
|
|
|
|
const cmChar_t* cmUdpNetLocalNodeLabel( cmUdpNetH_t h )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
return p->nodeLabel;
|
|
}
|
|
|
|
unsigned cmUdpNetNodeLabelToId( cmUdpNetH_t h, const cmChar_t* label )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
|
|
// if the network was not initialized then nodeLabel == NULL
|
|
if( p->nodeLabel == NULL )
|
|
return cmInvalidId;
|
|
|
|
// if 'label' refers to the local node
|
|
if( strcmp(label,p->nodeLabel) == 0 )
|
|
return p->nodeId;
|
|
|
|
// otherwise search the remote node list
|
|
cmUdpNode_t* np = p->list;
|
|
for(; np != NULL; np = np->link )
|
|
if( strcmp(np->label,label) == 0 )
|
|
return np->id;
|
|
|
|
return cmInvalidId;
|
|
}
|
|
|
|
const cmChar_t* cmUdpNetNodeIdToLabel( cmUdpNetH_t h, unsigned id )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
|
|
// if 'id' refers to the local node
|
|
if( id == p->nodeId )
|
|
return p->nodeLabel;
|
|
|
|
// otherwise search the remote node list
|
|
cmUdpNode_t* np = p->list;
|
|
for(; np != NULL; np = np->link )
|
|
if( np->id == id )
|
|
return np->label;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
unsigned cmUdpNetNodeCount( cmUdpNetH_t h )
|
|
{
|
|
unsigned cnt = 0;
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmUdpNode_t* np = p->list;
|
|
for(; np != NULL; np = np->link )
|
|
++cnt;
|
|
|
|
return cnt;
|
|
}
|
|
|
|
unsigned cmUdpNetNodeId( cmUdpNetH_t h, unsigned nodeIdx )
|
|
{
|
|
unsigned cnt = 0;
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmUdpNode_t* np = p->list;
|
|
|
|
for(; np != NULL; np = np->link )
|
|
if( cnt == nodeIdx )
|
|
return np->id;
|
|
|
|
return cmInvalidId;
|
|
|
|
}
|
|
|
|
|
|
cmUnRC_t cmUdpNetRegisterRemote(
|
|
cmUdpNetH_t h,
|
|
const cmChar_t* remoteNodeLabel,
|
|
unsigned remoteNodeId,
|
|
const char* remoteNodeSockAddr,
|
|
cmUdpPort_t remoteNodePort )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
struct sockaddr_in addr;
|
|
|
|
if( remoteNodeLabel == NULL || strlen(remoteNodeLabel)==0 )
|
|
return cmErrMsg(&p->err,kInvalidNodeLabelUnRC,"The node label must contain a non-empty string.");
|
|
|
|
if( _cmUnFindLabel(p,remoteNodeLabel) != NULL )
|
|
return cmErrMsg(&p->err,kDuplicateNodeLabelUnRC,"The node label '%s' is already in use.",cmStringNullGuard(remoteNodeLabel));
|
|
|
|
if( _cmUnFindId(p,remoteNodeId) != NULL )
|
|
return cmErrMsg(&p->err,kDuplicateNodeIdUnRC,"The node id '%i' is already in use.",remoteNodeId);
|
|
|
|
if( cmUdpInitAddr(p->udpH, remoteNodeSockAddr, remoteNodePort, &addr ) != kOkUdpRC )
|
|
return cmErrMsg(&p->err,kInvalidNodeAddrUnRC,"The node address '%s' port:%i is not valid.",cmStringNullGuard(remoteNodeSockAddr),remoteNodePort);
|
|
|
|
cmUdpNode_t* np = cmMemAllocZ(cmUdpNode_t,1);
|
|
|
|
np->label = cmMemAllocStr(remoteNodeLabel);
|
|
np->id = remoteNodeId;
|
|
np->addr = addr;
|
|
np->port = remoteNodePort;
|
|
np->link = p->list;
|
|
p->list = np;
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetSendById( cmUdpNetH_t h, unsigned remoteNodeId, const void* data, unsigned dataByteCnt )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmUdpNode_t* np;
|
|
|
|
if((np = _cmUnFindId(p,remoteNodeId)) == NULL )
|
|
return cmErrMsg(&p->err,kNodeNotFoundUnRC,"The remote node (id=%i) was not found.",remoteNodeId);
|
|
|
|
if( cmUdpSendTo(p->udpH, data, dataByteCnt, &np->addr ) != kOkUdpRC )
|
|
return cmErrMsg(&p->err,kSendFailUnRC,"An attempt to send to a remote node with id=%i failed.",remoteNodeId);
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetSendByLabel( cmUdpNetH_t h, const cmChar_t* remoteNodeLabel, const void* data, unsigned dataByteCnt )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmUdpNode_t* np;
|
|
|
|
if((np = _cmUnFindLabel(p,remoteNodeLabel)) == NULL )
|
|
return cmErrMsg(&p->err,kNodeNotFoundUnRC,"The remote node (label=%s) was not found.",cmStringNullGuard(remoteNodeLabel));
|
|
|
|
if( cmUdpSendTo(p->udpH, data, dataByteCnt, &np->addr ) != kOkUdpRC )
|
|
return cmErrMsg(&p->err,kSendFailUnRC,"An attempt to send to the remote node labeled:%s failed.",cmStringNullGuard(remoteNodeLabel));
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetReceive( cmUdpNetH_t h, unsigned* msgCntPtr )
|
|
{
|
|
cmUnRC_t rc = kOkUnRC;
|
|
unsigned maxMsgCnt = 0;
|
|
unsigned msgCnt = 0;
|
|
|
|
if( msgCntPtr == NULL )
|
|
maxMsgCnt = cmInvalidCnt;
|
|
else
|
|
maxMsgCnt = *msgCntPtr;
|
|
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
if( cmUdpIsValid(p->udpH ) )
|
|
{
|
|
for(msgCnt=0; (maxMsgCnt==cmInvalidCnt || msgCnt<maxMsgCnt) && cmUdpAvailDataByteCount(p->udpH); ++msgCnt )
|
|
{
|
|
if( cmUdpGetAvailData(p->udpH,NULL,NULL,NULL) != kOkUdpRC )
|
|
{
|
|
rc = cmErrMsg(&p->err,kGetDataFailUnRC,"An attempt to get available message data failed.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( msgCntPtr != NULL )
|
|
*msgCntPtr = msgCnt;
|
|
|
|
return rc;
|
|
}
|
|
|
|
cmUnRC_t cmUdpNetPrintNodes( cmUdpNetH_t h, cmRpt_t* rpt )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmUdpNode_t* np = p->list;
|
|
unsigned i;
|
|
for(i=0; np != NULL; np = np->link, ++i )
|
|
cmRptPrintf(rpt,"%5i %5i %s\n",i,np->id,np->label);
|
|
|
|
return kOkUnRC;
|
|
}
|
|
|
|
void cmUdpNetReport( cmUdpNetH_t h, cmRpt_t* rpt )
|
|
{
|
|
cmUdpNet_t* p = _cmUnHandleToPtr(h);
|
|
cmUdpReport(p->udpH,rpt);
|
|
|
|
}
|
|
|
|
//=========================================================================================
|
|
typedef struct
|
|
{
|
|
cmTimeSpec_t t;
|
|
unsigned localNodeId;
|
|
cmUdpNetH_t h;
|
|
} _cmUdpNetTestMsg_t;
|
|
|
|
void _cmUdpNetTestCb( void* cbArg, cmUdpNetH_t h, const char* data, unsigned dataByteCnt, unsigned remoteNodeId )
|
|
{
|
|
cmRpt_t* rpt = (cmRpt_t*)cbArg;
|
|
cmRptPrintf(rpt,"recv - id:%i %s\n",remoteNodeId, data);
|
|
}
|
|
|
|
void _cmUdpNetTestCb2( void* cbArg, cmUdpNetH_t h, const char* data, unsigned dataByteCnt, unsigned remoteNodeId )
|
|
{
|
|
_cmUdpNetTestMsg_t* m = (_cmUdpNetTestMsg_t*)data;
|
|
cmRpt_t* rpt = (cmRpt_t*)cbArg;
|
|
|
|
assert( dataByteCnt == sizeof(_cmUdpNetTestMsg_t));
|
|
|
|
if( m->localNodeId == cmUdpNetLocalNodeId(h) )
|
|
{
|
|
cmTimeSpec_t t;
|
|
cmTimeGet(&t);
|
|
cmRptPrintf(rpt,"elapsed:%i\n", cmTimeElapsedMicros(&m->t,&t));
|
|
}
|
|
else
|
|
{
|
|
cmRptPrintf(rpt,"echo\n");
|
|
cmUdpNetSendById(h,m->localNodeId,&m,sizeof(*m));
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const cmChar_t* _cmUdpNetTestGetOpt( int argc, char* argv[], const char* opt )
|
|
{
|
|
unsigned i;
|
|
for(i=0; i<argc; ++i)
|
|
if( strcmp(argv[i],opt) == 0 )
|
|
return argv[i+1];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
cmRC_t cmUdpNetTest( cmCtx_t* ctx, int argc, char* argv[] )
|
|
{
|
|
cmUdpNetH_t h = cmUdpNetNullHandle;
|
|
cmJsonH_t jsH = cmJsonNullHandle;
|
|
cmErr_t err;
|
|
cmRC_t rc = cmOkRC;
|
|
unsigned i = 0;
|
|
const cmChar_t* jsonFn;
|
|
const cmChar_t* remoteNodeLabel;
|
|
unsigned strCharCnt = 31;
|
|
cmChar_t str[ strCharCnt + 1 ];
|
|
bool msgFl = false;
|
|
|
|
enum { kUdpNetTestErrRC = 1 };
|
|
|
|
cmErrSetup(&err,&ctx->rpt,"UDP Net Test");
|
|
|
|
// get the JSON file name
|
|
if(( jsonFn = _cmUdpNetTestGetOpt(argc,argv,"-j")) == NULL)
|
|
return cmErrMsg(&err,kUdpNetTestErrRC,"No JSON file name was given.");
|
|
|
|
// get the remote node label to send too
|
|
if(( remoteNodeLabel= _cmUdpNetTestGetOpt(argc,argv,"-n")) == NULL )
|
|
return cmErrMsg(&err,kUdpNetTestErrRC,"No remote node label was given.");
|
|
|
|
// create the JSON tree
|
|
if( cmJsonInitializeFromFile(&jsH, jsonFn, ctx ) != kOkJsRC )
|
|
{
|
|
rc = cmErrMsg(&err,kUdpNetTestErrRC,"JSON file init failed on '%s'.",cmStringNullGuard(jsonFn));
|
|
goto errLabel;
|
|
}
|
|
|
|
|
|
if( msgFl )
|
|
{
|
|
// alloc/init and put the network into listening mode
|
|
if( cmUdpNetAllocJson(ctx,&h,jsH,_cmUdpNetTestCb2,&ctx->rpt,kListenUnFl) != kOkUnRC )
|
|
{
|
|
rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP alloc/init/listen failed.");
|
|
goto errLabel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( cmUdpNetAlloc(ctx,&h) != kOkUnRC )
|
|
return cmErrMsg(&err,kUdpNetTestErrRC,"UDP alloc failed.");
|
|
|
|
if( cmUdpNetInitJson(h,jsH,_cmUdpNetTestCb,&ctx->rpt) != kOkUnRC )
|
|
{
|
|
rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP net init failed.");
|
|
goto errLabel;
|
|
}
|
|
|
|
if( cmUdpNetEnableListen(h,true) != kOkUnRC )
|
|
{
|
|
rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP listen enable failed.");
|
|
goto errLabel;
|
|
}
|
|
}
|
|
|
|
cmRptPrintf(&ctx->rpt,"s=send p=print r=report\n");
|
|
|
|
char c;
|
|
while((c=getchar()) != 'q')
|
|
{
|
|
bool promptFl = true;
|
|
|
|
switch(c)
|
|
{
|
|
case 's':
|
|
{
|
|
// form the emessage
|
|
snprintf(str,strCharCnt,"msg=%i",i);
|
|
|
|
// send a message to the remote node
|
|
if( !msgFl )
|
|
if( cmUdpNetSendByLabel(h,remoteNodeLabel,str,strlen(str)+1 ) != kOkUnRC )
|
|
cmErrMsg(&err,kUdpNetTestErrRC,"UDP net send failed.");
|
|
|
|
++i;
|
|
}
|
|
break;
|
|
|
|
case 't':
|
|
{
|
|
_cmUdpNetTestMsg_t m;
|
|
cmTimeGet(&m.t);
|
|
m.localNodeId = cmUdpNetLocalNodeId(h);
|
|
m.h = h;
|
|
|
|
// send a message to the remote node
|
|
if( msgFl )
|
|
if( cmUdpNetSendByLabel(h,remoteNodeLabel,&m,sizeof(m) ) != kOkUnRC )
|
|
cmErrMsg(&err,kUdpNetTestErrRC,"UDP net send failed.");
|
|
}
|
|
break;
|
|
|
|
case 'p':
|
|
cmUdpNetPrintNodes(h,&ctx->rpt);
|
|
break;
|
|
|
|
case 'r':
|
|
cmUdpNetReport(h,&ctx->rpt);
|
|
break;
|
|
|
|
default:
|
|
promptFl = false;
|
|
}
|
|
|
|
cmUdpNetReceive(h,NULL);
|
|
|
|
if( promptFl )
|
|
cmRptPrintf(&ctx->rpt,"%i> ",i);
|
|
}
|
|
|
|
errLabel:
|
|
|
|
if( cmUdpNetFree(&h) != kOkUnRC )
|
|
rc = cmErrMsg(&err,kUdpNetTestErrRC,"UDP free failed.");
|
|
|
|
if( cmJsonFinalize(&jsH) != kOkJsRC )
|
|
rc = cmErrMsg(&err,kUdpNetTestErrRC,"JSON final fail.");
|
|
|
|
return rc;
|
|
|
|
}
|