Browse Source

cmRtNet.h/c: Iniital commit.

master
kevin 11 years ago
parent
commit
3289a05944
3 changed files with 847 additions and 2 deletions
  1. 2
    2
      Makefile.am
  2. 751
    0
      cmRtNet.c
  3. 94
    0
      cmRtNet.h

+ 2
- 2
Makefile.am View File

@@ -30,8 +30,8 @@ cmSRC += src/libcm/cmMidiFilePlay.c src/libcm/cmMidiPort.c src/libcm/cmMidiFile.
30 30
 cmHDR += src/libcm/cmAudioFile.h src/libcm/cmAudioFileMgr.h src/libcm/cmMsgProtocol.h src/libcm/cmAudioSys.h src/libcm/cmAudioPortFile.h src/libcm/cmAudioFileDev.h 
31 31
 cmSRC += src/libcm/cmAudioFile.c src/libcm/cmAudioFileMgr.c src/libcm/cmMsgProtocol.c src/libcm/cmAudioSys.c src/libcm/cmAudioPortFile.c src/libcm/cmAudioFileDev.c
32 32
 
33
-cmHDR += src/libcm/cmRtSys.h src/libcm/cmUiRtSysMstr.h src/libcm/cmRtSysMsg.h 
34
-cmHDR += src/libcm/cmRtSys.c src/libcm/cmUiRtSysMstr.c
33
+cmHDR += src/libcm/cmRtSys.h src/libcm/cmRtNet.h src/libcm/cmUiRtSysMstr.h src/libcm/cmRtSysMsg.h 
34
+cmSRC += src/libcm/cmRtSys.c src/libcm/cmRtNet.c src/libcm/cmUiRtSysMstr.c
35 35
 
36 36
 cmHDR += src/libcm/cmDevCfg.h src/libcm/cmUi.h src/libcm/cmUiDrvr.h 
37 37
 cmSRC += src/libcm/cmDevCfg.c src/libcm/cmUi.c src/libcm/cmUiDrvr.c

+ 751
- 0
cmRtNet.c View File

@@ -0,0 +1,751 @@
1
+#include "cmGlobal.h"
2
+#include "cmRpt.h"
3
+#include "cmErr.h"
4
+#include "cmCtx.h"
5
+#include "cmMem.h"
6
+#include "cmMallocDebug.h"
7
+#include "cmUdpPort.h"
8
+#include "cmRtNet.h"
9
+#include "cmTime.h"
10
+#include "cmRtSysMsg.h"
11
+
12
+enum
13
+{
14
+  kLocalNetFl = 0x01,
15
+  kSockAddrNetFl = 0x02
16
+};
17
+
18
+typedef enum
19
+{
20
+  kSendHelloStNetId = 0,
21
+  kWaitHelloAckStNetId,
22
+  kSendEndpointStNetId,
23
+  kWaitEndpointAckStNetId,
24
+  kDoneStNetId,
25
+  kErrorStNetId,
26
+  kInvalidStNetId,
27
+} cmRtNetNodeState_t;
28
+
29
+typedef enum
30
+{
31
+  kHelloSelNetId,
32
+  kHelloAckSelNetId,
33
+  kEndpointSelNetId,
34
+  kEndpointAckSelNetId
35
+} cmRtNetSelId_t;
36
+
37
+typedef struct cmRtNetEnd_str
38
+{
39
+  cmChar_t*              endPtLabel;
40
+  unsigned               endPtId;
41
+  struct cmRtNetEnd_str* link;
42
+} cmRtNetEnd_t;
43
+
44
+
45
+typedef struct cmRtNetNode_str
46
+{
47
+  cmChar_t*               label;
48
+  struct sockaddr_in      sockaddr;
49
+  cmChar_t*               addr;
50
+  cmUdpPort_t             port;
51
+  unsigned                flags;
52
+  cmRtNetNodeState_t      state;
53
+  unsigned                epIdx;
54
+  cmTimeSpec_t            lastSendTime;
55
+  cmRtNetEnd_t*           ends;
56
+  struct cmRtNetNode_str* link;
57
+} cmRtNetNode_t;
58
+
59
+typedef struct
60
+{
61
+  cmErr_t         err;
62
+  cmUdpH_t        udpH;
63
+  cmUdpCallback_t cbFunc;
64
+  void*           cbArg;
65
+  cmRtNetNode_t*  nodes;
66
+  cmRtNetNode_t*  localNode;
67
+  bool            syncModeFl;
68
+  unsigned        udpRecvBufByteCnt;
69
+  unsigned        udpTimeOutMs;
70
+  unsigned        interSyncSendTimeMs;
71
+} cmRtNet_t;
72
+
73
+
74
+typedef struct
75
+{
76
+  cmRtSysMsgHdr_t hdr;
77
+  cmRtNetSelId_t    selId;
78
+  const cmChar_t* endPtLabel;
79
+  unsigned        endPtId;
80
+} cmRtNetSyncMsg_t;
81
+
82
+cmRtNetH_t cmRtNetNullHandle = cmSTATIC_NULL_HANDLE;
83
+
84
+cmRtNet_t* _cmRtNetHandleToPtr( cmRtNetH_t h )
85
+{
86
+  cmRtNet_t* p = (cmRtNet_t*)h.h;
87
+  assert( p != NULL );
88
+  return p;
89
+}
90
+
91
+void _cmRtNetVRpt( cmRtNet_t* p, const cmChar_t* fmt, va_list vl )
92
+{
93
+  cmRptVPrintf(p->err.rpt,fmt,vl);
94
+}
95
+
96
+void _cmRtNetRpt( cmRtNet_t* p, const cmChar_t* fmt, ... )
97
+{
98
+  va_list vl;
99
+  va_start(vl,fmt);
100
+  _cmRtNetVRpt(p,fmt,vl);
101
+  va_end(vl);
102
+}
103
+
104
+cmRtNetNode_t* _cmRtNetFindNode( cmRtNet_t* p, const cmChar_t* label )
105
+{
106
+  if( label == NULL )
107
+    return NULL;
108
+
109
+  cmRtNetNode_t* np = p->nodes;
110
+  for(; np!=NULL; np=np->link)
111
+    if( strcmp(label,np->label)==0)
112
+      return np;
113
+
114
+  return NULL;
115
+}
116
+
117
+cmRtNetNode_t* _cmRtNetFindNodeFromSockAddr( cmRtNet_t* p, const struct sockaddr_in* saddr )
118
+{
119
+  if( saddr == NULL )
120
+    return NULL;
121
+
122
+  cmRtNetNode_t* np = p->nodes;
123
+  for(; np!=NULL; np=np->link)
124
+    if( cmIsFlag(np->flags,kSockAddrNetFl) && np->sockaddr.sin_addr.s_addr == saddr->sin_addr.s_addr && np->sockaddr.sin_port == saddr->sin_port )
125
+      return np;
126
+  
127
+  return NULL;
128
+}
129
+
130
+void _cmRtNetFreeNode( cmRtNetNode_t* np )
131
+{
132
+  cmRtNetEnd_t* ep = np->ends;
133
+  while( ep != NULL )
134
+  {
135
+    cmRtNetEnd_t* nep = ep->link;
136
+    cmMemFree(ep->endPtLabel);
137
+    cmMemFree(ep);
138
+    ep = nep;
139
+  }
140
+
141
+  cmMemFree(np->label);
142
+  cmMemFree(np->addr);
143
+  cmMemFree(np);
144
+}
145
+
146
+void _cmRtNetReleaseNodes( cmRtNet_t* p )
147
+{
148
+  cmRtNetNode_t* np = p->nodes;
149
+  while( np != NULL )
150
+  {
151
+    cmRtNetNode_t* nnp = np->link;
152
+
153
+    _cmRtNetFreeNode(np);
154
+
155
+    np = nnp;
156
+  }
157
+  p->nodes = NULL;
158
+  p->localNode = NULL;
159
+}
160
+
161
+cmRtNetRC_t  _cmRtNetReleaseNode( cmRtNet_t* p, cmRtNetNode_t* np )
162
+{
163
+  // we should never release the local node via this function
164
+  assert( np != p->localNode );
165
+
166
+  cmRtNetNode_t* cnp = p->nodes;
167
+  cmRtNetNode_t* pnp = NULL;
168
+
169
+  while( cnp != NULL )
170
+  {
171
+    cmRtNetNode_t* nnp = cnp->link;
172
+    if( np == cnp )
173
+    {
174
+      if( pnp == NULL )
175
+        p->nodes = np->link;
176
+      else
177
+        pnp->link = np->link;
178
+
179
+      _cmRtNetFreeNode(np);
180
+
181
+      return kOkNetRC;
182
+    }
183
+
184
+    pnp = np;
185
+    cnp = nnp;
186
+  }
187
+
188
+  assert(0);
189
+  return cmErrMsg(&p->err,kNodeNotFoundNetRC,"Node to release not found.");
190
+}
191
+
192
+cmRtNetRC_t _cmRtNetCreateNode( cmRtNet_t* p, const cmChar_t* label, const cmChar_t* addr, cmUdpPort_t port, const struct sockaddr_in* saddr )
193
+{
194
+  cmRtNetNode_t* np;
195
+
196
+  if( label == NULL )
197
+    return cmErrMsg(&p->err,kInvalidLabelNetRC,"A null or blank node label was encountered.");
198
+
199
+  if((np = _cmRtNetFindNode(p,label)) != NULL )
200
+    return cmErrMsg(&p->err,kDuplLabelNetRC,"The node label '%s' is already in use.",cmStringNullGuard(label));
201
+
202
+  bool localNodeFl = addr==NULL && saddr==NULL;
203
+  
204
+  if( localNodeFl && p->localNode != NULL )
205
+    return cmErrMsg(&p->err,kDuplLocalNetRC,"The local node '%s' has already been set.",cmStringNullGuard(p->localNode->label));
206
+
207
+  np = cmMemAllocZ(cmRtNetNode_t,1);
208
+  np->label = cmMemAllocStr(label);
209
+  np->addr  = addr==NULL ? NULL : cmMemAllocStr(addr);
210
+  np->port  = port;
211
+  np->flags = cmEnaFlag(np->flags,kLocalNetFl,localNodeFl);
212
+  np->link  = p->nodes;
213
+  p->nodes  = np;
214
+
215
+  if( localNodeFl )
216
+    p->localNode = np;
217
+
218
+  if( saddr != NULL )
219
+  {
220
+    np->sockaddr = *saddr;
221
+    np->flags = cmSetFlag(np->flags,kSockAddrNetFl);
222
+  }
223
+
224
+  return kOkNetRC;
225
+}
226
+
227
+cmRtNetEnd_t* _cmRtNetFindNodeEnd(cmRtNetNode_t* np, const cmChar_t* endPtLabel )
228
+{
229
+  cmRtNetEnd_t* ep = np->ends;
230
+  for(; ep!=NULL; ep=ep->link)
231
+    if( strcmp(ep->endPtLabel,endPtLabel)==0 )
232
+      return ep;
233
+  return NULL;
234
+}
235
+
236
+cmRtNetEnd_t* _cmRtNetIndexToEndpoint( cmRtNet_t* p, cmRtNetNode_t* np, unsigned endIndex )
237
+{
238
+  cmRtNetEnd_t* ep = np->ends;
239
+  unsigned i;
240
+  for(i=0; ep!=NULL; ep=ep->link)
241
+  {
242
+    if( i == endIndex )
243
+      return ep;
244
+    ++i;
245
+  }
246
+
247
+  return NULL;
248
+}
249
+
250
+cmRtNetRC_t _cmRtNetCreateEndpoint( cmRtNet_t* p, cmRtNetNode_t* np, const cmChar_t* endPtLabel, unsigned endPtId )
251
+{
252
+  if( endPtLabel == NULL )
253
+    return cmErrMsg(&p->err,kInvalidLabelNetRC,"A null or blank node label was encountered.");
254
+
255
+  if( _cmRtNetFindNodeEnd( np, endPtLabel) != NULL)
256
+    return cmErrMsg(&p->err,kDuplEndNetRC,"A duplicate endpoint ('%s') was encountered on node '%s'.",endPtLabel,np->label);
257
+
258
+  cmRtNetRC_t   rc = kOkNetRC;
259
+  cmRtNetEnd_t* ep = cmMemAllocZ(cmRtNetEnd_t,1);
260
+
261
+  ep->endPtLabel = cmMemAllocStr(endPtLabel);
262
+  ep->endPtId    = endPtId;
263
+  ep->link      = np->ends;
264
+  np->ends      = ep;
265
+
266
+  return rc;
267
+}
268
+
269
+unsigned _cmRtNetSyncMsgSerialByteCount( const cmRtNetSyncMsg_t* m )
270
+{ return sizeof(cmRtNetSyncMsg_t) + m->endPtLabel==NULL ? 1 : strlen(m->endPtLabel) + 1; }
271
+
272
+cmRtNetRC_t _cmRtNetSerializeSyncMsg( cmRtNet_t* p, const cmRtNetSyncMsg_t* m, void* buf, unsigned n )
273
+{
274
+  unsigned bn = _cmRtNetSyncMsgSerialByteCount(m);
275
+  char*    b  = (char*)buf;
276
+
277
+  if( bn > n )
278
+    return cmErrMsg(&p->err,kBufToSmallNetRC,"Serialize buffer too small.");
279
+
280
+  memcpy(b,m,sizeof(*m));
281
+  strcpy(b + sizeof(*m),m->endPtLabel==NULL ? "" : m->endPtLabel);
282
+  return kOkNetRC;
283
+}
284
+
285
+cmRtNetRC_t _cmRtNetDeserializeSyncMsg( const void* buf, unsigned n, cmRtNetSyncMsg_t* m )
286
+{
287
+  assert( n > sizeof(*m));
288
+  memcpy(m,buf,sizeof(*m));
289
+  const cmRtNetSyncMsg_t* mp = (const cmRtNetSyncMsg_t*)buf;
290
+  const cmChar_t*   s  = (const cmChar_t*)(mp+1);
291
+  m->endPtLabel = cmMemAllocStr(s);
292
+  return kOkNetRC;
293
+}
294
+
295
+cmRtNetRC_t _cmRtNetSendSyncMsg( cmRtNet_t* p, cmRtNetNode_t* np, cmRtNetSelId_t selId, const cmChar_t* endPtLabel, unsigned endPtId, cmRtNetNodeState_t nextStId )
296
+{
297
+  cmRtNetSyncMsg_t m;
298
+  cmRtNetRC_t      rc = kOkNetRC;
299
+
300
+  m.hdr.rtSubIdx = cmInvalidIdx;
301
+  m.hdr.selId    = kNetSyncSelRtId;
302
+  m.selId        = selId;
303
+  m.endPtLabel    = endPtLabel;
304
+  m.endPtId       = endPtId;
305
+
306
+  // determine size of msg to send
307
+  unsigned n  = _cmRtNetSyncMsgSerialByteCount(&m);
308
+  cmChar_t buf[n];
309
+
310
+  // serialize msg into buf[]
311
+  if((rc = _cmRtNetSerializeSyncMsg(p,&m,buf,n)) != kOkNetRC )
312
+    return rc;
313
+
314
+  // store this nodes current sync state
315
+  cmRtNetNodeState_t orgState = np->state;
316
+  np->state = nextStId;
317
+
318
+  // send the msg
319
+  cmUdpRC_t udpRC;
320
+  if( cmIsFlag(np->flags,kSockAddrNetFl) )
321
+    udpRC = cmUdpSendTo(p->udpH, buf, n, &np->sockaddr );
322
+  else
323
+    udpRC = cmUdpSend2(p->udpH, buf, n, np->addr, np->port );
324
+
325
+  // check for send errors
326
+  if( udpRC != kOkUdpRC )
327
+  {
328
+    rc = cmErrMsg(&p->err,kUdpPortFailNetRC,"Sync msg. send on UDP port failed.");
329
+    np->state = orgState;  // restore node state so we can try again
330
+  }
331
+  else
332
+  {
333
+    // record the last send time
334
+    cmTimeGet(&np->lastSendTime);
335
+  }
336
+
337
+  return rc;
338
+}
339
+
340
+cmRtNetRC_t _cmRtNetFree( cmRtNet_t* p )
341
+{
342
+  cmRtNetRC_t rc = kOkNetRC;
343
+  
344
+  if( cmUdpFree(&p->udpH) != kOkUdpRC )
345
+    cmErrMsg(&p->err,kUdpPortFailNetRC,"UDP Port free failed.");
346
+
347
+  _cmRtNetReleaseNodes(p);
348
+
349
+  cmMemFree(p);
350
+  return rc;
351
+}
352
+
353
+
354
+cmRtNetRC_t cmRtNetAlloc( cmCtx_t* ctx, cmRtNetH_t* hp, cmUdpCallback_t cbFunc, void* cbArg )
355
+{
356
+  cmRtNetRC_t rc;
357
+  if((rc = cmRtNetFree(hp)) != kOkNetRC )
358
+    return rc;
359
+
360
+  cmRtNet_t* p = cmMemAllocZ(cmRtNet_t,1);
361
+  cmErrSetup(&p->err,&ctx->rpt,"cmRtNet");
362
+ 
363
+  // allocate the UDP port
364
+  if(cmUdpAlloc(ctx,&p->udpH) != kOkUdpRC )
365
+  {
366
+    cmErrMsg(&p->err,kUdpPortFailNetRC,"UDP Port allocate failed.");
367
+    goto errLabel;
368
+  }
369
+
370
+  p->udpTimeOutMs        = 50;
371
+  p->udpRecvBufByteCnt   = 8192;
372
+  p->interSyncSendTimeMs = 10;
373
+  p->cbFunc = cbFunc;
374
+  p->cbArg  = cbArg;
375
+
376
+  hp->h = p;
377
+
378
+ errLabel:
379
+  if(rc != kOkNetRC )
380
+    _cmRtNetFree(p);
381
+
382
+  return rc;
383
+}
384
+
385
+cmRtNetRC_t cmRtNetFree( cmRtNetH_t* hp )
386
+{
387
+  cmRtNetRC_t rc = kOkNetRC;
388
+
389
+  if( hp==NULL || cmRtNetIsValid(*hp)==false )
390
+    return rc;
391
+
392
+  cmRtNet_t* p = _cmRtNetHandleToPtr(*hp);
393
+
394
+  if((rc = _cmRtNetFree(p)) != kOkNetRC )
395
+    return rc;
396
+
397
+  hp->h = NULL;
398
+
399
+  return rc;
400
+}
401
+
402
+bool cmRtNetIsValid( cmRtNetH_t h )
403
+{ return h.h !=NULL; }
404
+
405
+cmUdpH_t  cmRtNetUdpPortHandle( cmRtNetH_t h )
406
+{
407
+  cmRtNet_t*  p = _cmRtNetHandleToPtr(h);
408
+  return p->udpH;
409
+}
410
+
411
+
412
+cmRtNetRC_t cmRtNetCreateNode( cmRtNetH_t h, const cmChar_t* nodeLabel, const cmChar_t* ipAddr, cmUdpPort_t port )
413
+{
414
+  cmRtNet_t*  p = _cmRtNetHandleToPtr(h);
415
+  cmRtNetRC_t rc;
416
+
417
+  // create a node
418
+  if((rc = _cmRtNetCreateNode(p,nodeLabel,ipAddr, port, NULL)) != kOkNetRC )
419
+    return rc;
420
+
421
+  // if this is not the local node
422
+  if( ipAddr != NULL )
423
+    return rc;
424
+
425
+  // if this is the local node then initialze the local socket
426
+  if( cmUdpInit(p->udpH,port,kNonBlockingUdpFl,p->cbFunc,p->cbArg,NULL,0,p->udpRecvBufByteCnt,p->udpTimeOutMs) != kOkUdpRC )
427
+  {
428
+    rc = cmErrMsg(&p->err,kUdpPortFailNetRC,"The UDP port initialization failed.");
429
+    goto errLabel;
430
+  }
431
+
432
+  // begin listening on the local port
433
+  if( cmUdpEnableListen(p->udpH, true ) != kOkUdpRC )
434
+  {
435
+    rc = cmErrMsg(&p->err,kUdpPortFailNetRC,"The UDP port failed to enter 'listen' mode.");
436
+    goto errLabel;
437
+  }
438
+
439
+
440
+ errLabel:
441
+  return rc;
442
+}
443
+
444
+cmRtNetRC_t cmRtNetRegisterEndPoint( cmRtNetH_t h, const cmChar_t* endPtLabel, unsigned endPtId )
445
+{
446
+  cmRtNet_t* p = _cmRtNetHandleToPtr(h);
447
+
448
+  if( p->localNode == NULL )
449
+    return cmErrMsg(&p->err,kLocalNodeNetRC,"Local endpoints may not be added if a local node has not been defined.");
450
+
451
+  return _cmRtNetCreateEndpoint(p, p->localNode,endPtLabel,endPtId );
452
+
453
+}
454
+
455
+cmRtNetRC_t cmRtNetClearAll( cmRtNetH_t h )
456
+{
457
+  cmRtNet_t* p = _cmRtNetHandleToPtr(h);
458
+  _cmRtNetReleaseNodes(p);
459
+  return kOkNetRC;
460
+}
461
+
462
+cmRtNetRC_t cmRtNetBeginSyncMode( cmRtNetH_t h )
463
+{
464
+  cmRtNetRC_t rc = kOkNetRC;
465
+  
466
+  cmRtNet_t* p = _cmRtNetHandleToPtr(h);
467
+
468
+  p->syncModeFl = true;
469
+  
470
+  return rc;
471
+}
472
+
473
+bool      cmRtNetIsInSyncMode(  cmRtNetH_t h )
474
+{
475
+  cmRtNet_t* p = _cmRtNetHandleToPtr(h);
476
+
477
+  return p->syncModeFl;
478
+}
479
+
480
+
481
+// Used by slaves to send the master an 'ack' msg.
482
+cmRtNetRC_t _cmRtNetSendAck( cmRtNet_t* p, cmRtNetSelId_t ackSelId, const struct sockaddr_in* saddr )
483
+{
484
+  cmRtNetNode_t* np;
485
+
486
+  if((np = _cmRtNetFindNodeFromSockAddr(p,saddr)) != NULL )
487
+    return cmErrMsg(&p->err,kNodeNotFoundNetRC,"The net node associated with an ack cmd was not found. Ack not sent.");
488
+
489
+  return _cmRtNetSendSyncMsg(p,np,ackSelId,NULL,cmInvalidId,kInvalidStNetId);
490
+}
491
+
492
+// Used by master to update state upon receipt of 'ack' msg
493
+cmRtNetRC_t _cmRtNetRecvAck( cmRtNet_t* p, const struct sockaddr_in* fromAddr, cmRtNetNodeState_t expectedState, cmRtNetNodeState_t nextState )
494
+{
495
+  cmRtNetNode_t* np;
496
+  cmRtNetRC_t rc = kOkNetRC;
497
+
498
+  if((np = _cmRtNetFindNodeFromSockAddr(p,fromAddr)) == NULL )
499
+  {
500
+    rc = cmErrMsg(&p->err,kNodeNotFoundNetRC,"The net node associated with a  ack receive was not found.");
501
+    goto errLabel;
502
+  }
503
+
504
+  if( np->state != expectedState )
505
+  {
506
+    rc = cmErrMsg(&p->err,kNodeStateErrNetRC,"Node '%s' expected in state %i was in state %i.",kWaitHelloAckStNetId,np->state);
507
+    np->state = kErrorStNetId;
508
+    goto errLabel;
509
+  }
510
+
511
+  np->state = nextState;
512
+
513
+ errLabel:
514
+  return rc;
515
+}
516
+
517
+
518
+cmRtNetRC_t  cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
519
+{
520
+  cmRtNet_t*       p  = _cmRtNetHandleToPtr(h);
521
+  cmRtNetRC_t      rc = kOkNetRC;
522
+  cmRtNetNode_t*   np = NULL;
523
+  cmRtNetSyncMsg_t m;
524
+
525
+  assert( p->syncModeFl );
526
+  
527
+  if( _cmRtNetDeserializeSyncMsg(data,dataByteCnt,&m) != kOkNetRC )
528
+  {
529
+    rc = cmErrMsg(&p->err,rc,"Net sync. receive failed due to deserialize fail.");
530
+    goto errLabel;
531
+  }
532
+
533
+  assert( m.hdr.selId == kNetSyncSelRtId );
534
+
535
+  switch( m.selId )
536
+  {
537
+    
538
+    case kHelloSelNetId: // slave response
539
+      {
540
+        _cmRtNetRpt(p,"rcv hello\n");
541
+
542
+        // attempt to locate the remote node which sent the endpoint 
543
+        if((np = _cmRtNetFindNodeFromSockAddr(p,fromAddr)) != NULL )
544
+        {
545
+          // delete the existing node because we are about to get new info. about it.
546
+          if((rc =  _cmRtNetReleaseNode(p,np )) != kOkNetRC )
547
+            goto errLabel;
548
+        }
549
+
550
+        //  create a node proxy to represent the remote node
551
+        if(( rc = _cmRtNetCreateNode(p,m.endPtLabel,NULL,0,fromAddr)) != kOkNetRC )
552
+          goto errLabel;
553
+
554
+        // send an ackknowledgement of the 'hello' msg
555
+        rc = _cmRtNetSendAck(p,kHelloAckSelNetId,fromAddr);
556
+      }
557
+      break;
558
+
559
+    
560
+    case kEndpointSelNetId: // slave response
561
+      {
562
+        cmRtNetEnd_t* ep;
563
+
564
+        _cmRtNetRpt(p,"rcv endpoint\n");
565
+
566
+
567
+        // locate the remote node which sent the endpoint
568
+        if((np = _cmRtNetFindNodeFromSockAddr(p,fromAddr)) == NULL )
569
+        {
570
+          rc = cmErrMsg(&p->err,kNodeNotFoundNetRC,"The net node associated with an endpoint receive was not found.");
571
+          goto errLabel;
572
+        }
573
+        
574
+        // attempt to find the end point 
575
+        if((ep = _cmRtNetFindNodeEnd(np,m.endPtLabel)) != NULL )
576
+          ep->endPtId = m.endPtId; // the endpoint was found update the endPtId
577
+        else
578
+        {
579
+          // create a local proxy for the endpoint
580
+          if((rc = _cmRtNetCreateEndpoint(p,np,m.endPtLabel,m.endPtId)) != kOkNetRC )
581
+            goto errLabel;
582
+        }
583
+
584
+        // ack. the endpoint msg
585
+        rc = _cmRtNetSendAck(p,kEndpointAckSelNetId,fromAddr);
586
+      }
587
+      break;
588
+
589
+    case kHelloAckSelNetId: // master response
590
+      _cmRtNetRpt(p,"rcv hello ack\n");
591
+      rc = _cmRtNetRecvAck(p,fromAddr,kWaitHelloAckStNetId,kSendEndpointStNetId);
592
+      break;
593
+
594
+    case kEndpointAckSelNetId: // master response
595
+      _cmRtNetRpt(p,"rcv endpoint ack\n");
596
+      rc = _cmRtNetRecvAck(p,fromAddr,kWaitEndpointAckStNetId,kSendEndpointStNetId);
597
+      break;
598
+
599
+    default:
600
+      break;
601
+  }
602
+
603
+ errLabel:
604
+  return rc;
605
+}
606
+
607
+
608
+cmRtNetRC_t _cmRtNetSendNodeSync( cmRtNet_t* p, cmRtNetNode_t* np )
609
+{
610
+  cmRtNetRC_t rc = kOkNetRC;
611
+
612
+  switch( np->state )
613
+  {
614
+    case kSendHelloStNetId:
615
+      // send a 'hello' to this remote node
616
+      if((rc = _cmRtNetSendSyncMsg(p,np,kHelloSelNetId,p->localNode->label, cmInvalidId, kWaitHelloAckStNetId )) != kOkNetRC )
617
+        rc = cmErrMsg(&p->err,rc,"Send 'hello' to %s:%s:%i failed.",cmStringNullGuard(np->label),cmStringNullGuard(np->addr),np->port);
618
+      else
619
+        _cmRtNetRpt(p,"send hello\n");
620
+      break;
621
+
622
+    case kSendEndpointStNetId:
623
+      {
624
+        cmRtNetEnd_t* ep;
625
+
626
+        // if all of the endpoints have been sent to this node ...
627
+        if((ep = _cmRtNetIndexToEndpoint(p,p->localNode,np->epIdx)) == NULL )
628
+          np->state = kDoneStNetId; // ... we are done
629
+        else
630
+        {
631
+          // send an endpoint to this node 
632
+          if((rc = _cmRtNetSendSyncMsg(p,np,kHelloSelNetId,ep->endPtLabel, ep->endPtId, kWaitEndpointAckStNetId )) != kOkNetRC )
633
+            rc = cmErrMsg(&p->err,rc,"Endpoint (%s index:%i) transmission to %s:%s:%i failed.",cmStringNullGuard(ep->endPtLabel),cmStringNullGuard(np->label),cmStringNullGuard(np->addr),np->port);
634
+          else
635
+            _cmRtNetRpt(p,"send endpoint\n");
636
+
637
+        }
638
+      }
639
+      break;
640
+
641
+    case kWaitHelloAckStNetId:
642
+    case kWaitEndpointAckStNetId:
643
+      {
644
+        cmTimeSpec_t t;
645
+        cmTimeGet(&t);
646
+        unsigned fiveSecs = 5000000;
647
+        if( cmTimeElapsedMicros(&np->lastSendTime,&t) > fiveSecs)
648
+        {
649
+          const cmChar_t* ackStr = np->state==kWaitHelloAckStNetId ? "hello" : "endpoint";
650
+          rc = cmErrMsg(&p->err,kTimeOutErrNetRC,"The node %s:%s:%i did not give a '%s' acknowledge.",cmStringNullGuard(np->label),cmStringNullGuard(np->addr),np->port,ackStr);         
651
+        }
652
+      }
653
+      break;
654
+
655
+    default:
656
+      break;
657
+  }
658
+      
659
+  // if an error occurred put the node into an error state
660
+  if( rc != kOkNetRC )
661
+    np->state = kErrorStNetId;
662
+      
663
+  return rc;
664
+}
665
+
666
+
667
+
668
+cmRtNetRC_t cmRtNetSyncModeSend( cmRtNetH_t h )
669
+{
670
+  cmRtNetRC_t rc = kOkNetRC;
671
+  cmRtNet_t*  p  = _cmRtNetHandleToPtr(h);
672
+
673
+  if( p->syncModeFl == false )
674
+    return rc;
675
+  
676
+  unsigned     activeCnt = 0;
677
+  cmRtNetNode_t* np        = p->nodes;
678
+  for(; np != NULL; np=np->link )
679
+    if( np != p->localNode && np->state != kDoneStNetId && np->state != kErrorStNetId )
680
+    {
681
+      _cmRtNetSendNodeSync(p,np);
682
+      activeCnt += 1;
683
+    }
684
+    
685
+  if( activeCnt == 0 )
686
+    p->syncModeFl = false;
687
+
688
+  return rc;
689
+}
690
+
691
+
692
+cmRtNetRC_t cmRtNetReceive( cmRtNetH_t h )
693
+{
694
+  cmRtNetRC_t rc = kOkNetRC;
695
+  cmRtNet_t*  p  = _cmRtNetHandleToPtr(h);
696
+
697
+  if( cmUdpGetAvailData(p->udpH, NULL, NULL, NULL ) != kOkUdpRC )
698
+  {
699
+    cmErrMsg(&p->err,kUdpPortFailNetRC,"UDP port query failed.");
700
+    goto errLabel;
701
+  }
702
+ errLabel:
703
+  return rc;
704
+}
705
+
706
+unsigned  cmRtNetEndPointIndex( cmRtNetH_t h, const cmChar_t* nodeLabel, const cmChar_t* endPtLabel )
707
+{
708
+  //cmRtNet_t* p = _cmRtNetHandleToPtr(h);
709
+  return cmInvalidIdx;
710
+}  
711
+
712
+cmRtNetRC_t cmRtNetSend( cmRtNetH_t h, unsigned endPointIndex, const void* msg, unsigned msgByteCnt )
713
+{
714
+  cmRtNetRC_t rc = kOkNetRC;
715
+  //cmRtNet_t* p = _cmRtNetHandleToPtr(h);
716
+  return rc;
717
+}
718
+
719
+void   cmRtNetReport( cmRtNetH_t h )
720
+{
721
+  cmRtNet_t* p = _cmRtNetHandleToPtr(h);
722
+  cmRpt_t* rpt = p->err.rpt;
723
+
724
+  cmRptPrintf(rpt,"Sync Mode:%s\n",p->syncModeFl ? "ON" : "OFF");
725
+
726
+  cmRtNetNode_t* np = p->nodes;
727
+  for(; np!=NULL; np=np->link)
728
+  {
729
+    cmRptPrintf(rpt,"Node: %s ",np->label);
730
+
731
+    if( np->addr != NULL )
732
+      cmRptPrintf(rpt,"%s ",np->addr );
733
+
734
+    if( cmIsFlag(np->flags,kLocalNetFl) )
735
+      cmRptPrintf(rpt,"LOCAL ");
736
+
737
+    if( cmIsFlag(np->flags,kSockAddrNetFl) )
738
+      cmRptPrintf(rpt,"%s ",cmStringNullGuard(cmUdpAddrToString(p->udpH,&np->sockaddr)));
739
+
740
+    if( np->port != cmInvalidId )
741
+      cmRptPrintf(rpt,"%i ",np->port );
742
+
743
+    cmRptPrintf(rpt,"\n");
744
+
745
+    cmRtNetEnd_t* ep = np->ends;
746
+    for(; ep!=NULL; ep=ep->link)
747
+    {
748
+      cmRptPrintf(rpt,"  endpt: %i %s\n",ep->endPtId,cmStringNullGuard(ep->endPtLabel));
749
+    }
750
+  }
751
+}

+ 94
- 0
cmRtNet.h View File

@@ -0,0 +1,94 @@
1
+#ifndef cmNet_h
2
+#define cmNet_h
3
+
4
+#ifdef __cplusplus
5
+extern "C" {
6
+#endif
7
+
8
+  enum
9
+  {
10
+    kOkNetRC = cmOkRC,
11
+    kUdpPortFailNetRC,
12
+    kInvalidLabelNetRC,
13
+    kDuplLabelNetRC,
14
+    kDuplLocalNetRC,
15
+    kDuplEndNetRC,
16
+    kThreadFailNetRC,
17
+    kBufToSmallNetRC,
18
+    kNodeNotFoundNetRC,
19
+    kNodeStateErrNetRC,
20
+    kTimeOutErrNetRC,
21
+    kLocalNodeNetRC,
22
+  };
23
+
24
+  typedef cmRC_t     cmRtNetRC_t;
25
+  typedef cmHandle_t cmRtNetH_t;
26
+
27
+
28
+  extern cmRtNetH_t cmRtNetNullHandle;
29
+
30
+  // 'cbFunc' will be called within the context of cmRtNetReceive() to receive
31
+  // incoming network messages.
32
+  cmRtNetRC_t cmRtNetAlloc( cmCtx_t* ctx, cmRtNetH_t* hp, cmUdpCallback_t cbFunc, void* cbArg );
33
+  cmRtNetRC_t cmRtNetFree( cmRtNetH_t* hp );
34
+
35
+  bool      cmRtNetIsValid( cmRtNetH_t h );
36
+
37
+
38
+  // Create a network node.
39
+  // The 'nodeLabel' refers to a network device cfg. (see cmDevCfg).
40
+  // Set 'ipAddr' to NULL if this is the local node.
41
+  // During sync mode this node will attempt to sync with all
42
+  // nodes in the node list.
43
+  cmRtNetRC_t cmRtNetCreateNode( cmRtNetH_t h, const cmChar_t* nodeLabel, const cmChar_t* ipAddr, cmUdpPort_t ipPort );
44
+
45
+  // Register the local endpoints.
46
+  // Remote nodes will be able to send messages to these endpoints by
47
+  // referring to (nodeLabel/endPtLabel)
48
+  cmRtNetRC_t cmRtNetRegisterEndPoint( cmRtNetH_t h, const cmChar_t* endPtLabel, unsigned endPtId );
49
+
50
+  // Delete all nodes and endpoints.
51
+  cmRtNetRC_t cmRtNetClearAll( cmRtNetH_t h );
52
+
53
+
54
+  // Go into 'sync' node.
55
+  // When a node enters sync mode it systematically transmits all of it's local endpoint 
56
+  // information to each registered remote node.  Prior to entering sync mode a node 
57
+  // must therefore have been setup with a list of remote nodes (via cmRtNetCreateNode()) 
58
+  // and a list of local endpoints (cmRtNetRegisterEndpoint()). 
59
+  // During sync mode a node sends it's local endpoint list to each registered remote node.
60
+  // When a remote node receives an endpoint it updates it's own remote node/endpoint 
61
+  // list.
62
+  cmRtNetRC_t cmRtNetBeginSyncMode( cmRtNetH_t h );
63
+  bool      cmRtNetIsInSyncMode(  cmRtNetH_t h );
64
+
65
+  // When the network message recieve function (See cmRtNetAlloc() 'cbFunc') 
66
+  // receives a message with the cmRtSysMsgHdr_t.selId == kNetSyncSelRtId
67
+  // it should call this function to update the current sync state of the
68
+  // cmRtNet.
69
+  cmRtNetRC_t  cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr );
70
+
71
+  
72
+  // When in the network is in sync mode (cmRtNetIsSync()==true) 
73
+  // the client system must poll this function to update the networks sync state.
74
+  cmRtNetRC_t cmRtNetSyncModeSend( cmRtNetH_t h );
75
+
76
+  // This function must be polled to receive incoming network messages
77
+  // via the callback funcion 'cbFunc' as passed to cmRtNetAlloc()
78
+  cmRtNetRC_t cmRtNetReceive( cmRtNetH_t h );
79
+
80
+  unsigned  cmRtNetEndPointIndex( cmRtNetH_t h, const cmChar_t* nodeLabel, const cmChar_t* endPtLabel );
81
+  
82
+
83
+  cmRtNetRC_t cmRtNetSend( cmRtNetH_t h, unsigned endPointIndex, const void* msg, unsigned msgByteCnt );
84
+
85
+  void      cmRtNetReport( cmRtNetH_t h );
86
+    
87
+  
88
+
89
+#ifdef __cplusplus
90
+}
91
+#endif
92
+
93
+
94
+#endif

Loading…
Cancel
Save