|
@@ -12,7 +12,9 @@
|
12
|
12
|
enum
|
13
|
13
|
{
|
14
|
14
|
kLocalNetFl = 0x01,
|
15
|
|
- kSockAddrNetFl = 0x02
|
|
15
|
+ kSockAddrNetFl = 0x02,
|
|
16
|
+ kRegNodeNetFl = 0x04,
|
|
17
|
+ kRecvNodeNetFl = 0x08
|
16
|
18
|
};
|
17
|
19
|
|
18
|
20
|
typedef enum
|
|
@@ -31,7 +33,8 @@ typedef enum
|
31
|
33
|
kHelloSelNetId,
|
32
|
34
|
kHelloAckSelNetId,
|
33
|
35
|
kEndpointSelNetId,
|
34
|
|
- kEndpointAckSelNetId
|
|
36
|
+ kEndpointAckSelNetId,
|
|
37
|
+ kDoneSelNetId
|
35
|
38
|
} cmRtNetSelId_t;
|
36
|
39
|
|
37
|
40
|
typedef struct cmRtNetEnd_str
|
|
@@ -50,7 +53,7 @@ typedef struct cmRtNetNode_str
|
50
|
53
|
cmUdpPort_t port;
|
51
|
54
|
unsigned flags;
|
52
|
55
|
cmRtNetNodeState_t state;
|
53
|
|
- unsigned epIdx;
|
|
56
|
+ unsigned epIdx; // tracks the next endpoint to send during sync-mode
|
54
|
57
|
cmTimeSpec_t lastSendTime;
|
55
|
58
|
cmRtNetEnd_t* ends;
|
56
|
59
|
struct cmRtNetNode_str* link;
|
|
@@ -65,6 +68,7 @@ typedef struct
|
65
|
68
|
cmRtNetNode_t* nodes;
|
66
|
69
|
cmRtNetNode_t* localNode;
|
67
|
70
|
bool syncModeFl;
|
|
71
|
+ bool masterFl;
|
68
|
72
|
unsigned udpRecvBufByteCnt;
|
69
|
73
|
unsigned udpTimeOutMs;
|
70
|
74
|
unsigned interSyncSendTimeMs;
|
|
@@ -189,7 +193,7 @@ cmRtNetRC_t _cmRtNetReleaseNode( cmRtNet_t* p, cmRtNetNode_t* np )
|
189
|
193
|
return cmErrMsg(&p->err,kNodeNotFoundNetRC,"Node to release not found.");
|
190
|
194
|
}
|
191
|
195
|
|
192
|
|
-cmRtNetRC_t _cmRtNetCreateNode( cmRtNet_t* p, const cmChar_t* label, const cmChar_t* addr, cmUdpPort_t port, const struct sockaddr_in* saddr )
|
|
196
|
+cmRtNetRC_t _cmRtNetCreateNode( cmRtNet_t* p, const cmChar_t* label, const cmChar_t* addr, cmUdpPort_t port, const struct sockaddr_in* saddr, unsigned flags )
|
193
|
197
|
{
|
194
|
198
|
cmRtNetRC_t rc = kOkNetRC;
|
195
|
199
|
cmRtNetNode_t* np;
|
|
@@ -209,7 +213,7 @@ cmRtNetRC_t _cmRtNetCreateNode( cmRtNet_t* p, const cmChar_t* label, const cmCha
|
209
|
213
|
np->label = cmMemAllocStr(label);
|
210
|
214
|
np->addr = addr==NULL ? NULL : cmMemAllocStr(addr);
|
211
|
215
|
np->port = port;
|
212
|
|
- np->flags = cmEnaFlag(np->flags,kLocalNetFl,localNodeFl);
|
|
216
|
+ np->flags = cmEnaFlag(flags,kLocalNetFl,localNodeFl);
|
213
|
217
|
np->link = p->nodes;
|
214
|
218
|
p->nodes = np;
|
215
|
219
|
|
|
@@ -323,7 +327,9 @@ cmRtNetRC_t _cmRtNetSendSyncMsg( cmRtNet_t* p, cmRtNetNode_t* np, cmRtNetSelId_t
|
323
|
327
|
|
324
|
328
|
// store this nodes current sync state
|
325
|
329
|
cmRtNetNodeState_t orgState = np->state;
|
326
|
|
- np->state = nextStId;
|
|
330
|
+
|
|
331
|
+ if( nextStId != kInvalidStNetId )
|
|
332
|
+ np->state = nextStId;
|
327
|
333
|
|
328
|
334
|
|
329
|
335
|
// send the msg
|
|
@@ -425,7 +431,7 @@ cmRtNetRC_t cmRtNetCreateNode( cmRtNetH_t h, const cmChar_t* nodeLabel, const cm
|
425
|
431
|
cmRtNetRC_t rc;
|
426
|
432
|
|
427
|
433
|
// create a node
|
428
|
|
- if((rc = _cmRtNetCreateNode(p,nodeLabel,ipAddr, port, NULL)) != kOkNetRC )
|
|
434
|
+ if((rc = _cmRtNetCreateNode(p,nodeLabel,ipAddr, port, NULL, kRegNodeNetFl)) != kOkNetRC )
|
429
|
435
|
return rc;
|
430
|
436
|
|
431
|
437
|
// if this is not the local node
|
|
@@ -476,7 +482,7 @@ cmRtNetRC_t cmRtNetBeginSyncMode( cmRtNetH_t h )
|
476
|
482
|
cmRtNet_t* p = _cmRtNetHandleToPtr(h);
|
477
|
483
|
|
478
|
484
|
p->syncModeFl = true;
|
479
|
|
-
|
|
485
|
+ p->masterFl = true;
|
480
|
486
|
return rc;
|
481
|
487
|
}
|
482
|
488
|
|
|
@@ -513,13 +519,17 @@ cmRtNetRC_t _cmRtNetRecvAck( cmRtNet_t* p, const struct sockaddr_in* fromAddr, c
|
513
|
519
|
|
514
|
520
|
if( np->state != expectedState )
|
515
|
521
|
{
|
516
|
|
- rc = cmErrMsg(&p->err,kNodeStateErrNetRC,"Node '%s' expected in state %i was in state %i.",kWaitHelloAckStNetId,np->state);
|
|
522
|
+ rc = cmErrMsg(&p->err,kNodeStateErrNetRC,"Node '%s' expected in state %i was in state %i.",cmStringNullGuard(np->label),kWaitHelloAckStNetId,np->state);
|
517
|
523
|
np->state = kErrorStNetId;
|
518
|
524
|
goto errLabel;
|
519
|
525
|
}
|
520
|
526
|
|
521
|
527
|
np->state = nextState;
|
522
|
528
|
|
|
529
|
+ // if we are about to send another endpoint - incr the endpoint index
|
|
530
|
+ if( nextState == kSendEndpointStNetId )
|
|
531
|
+ np->epIdx += 1;
|
|
532
|
+
|
523
|
533
|
errLabel:
|
524
|
534
|
return rc;
|
525
|
535
|
}
|
|
@@ -532,6 +542,8 @@ cmRtNetRC_t cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataB
|
532
|
542
|
cmRtNetNode_t* np = NULL;
|
533
|
543
|
cmRtNetSyncMsg_t m;
|
534
|
544
|
|
|
545
|
+ m.endPtLabel = NULL;
|
|
546
|
+
|
535
|
547
|
assert( cmRtNetIsSyncModeMsg(data,dataByteCnt));
|
536
|
548
|
|
537
|
549
|
if( _cmRtNetDeserializeSyncMsg(data,dataByteCnt,&m) != kOkNetRC )
|
|
@@ -558,11 +570,12 @@ cmRtNetRC_t cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataB
|
558
|
570
|
}
|
559
|
571
|
|
560
|
572
|
// create a node proxy to represent the remote node
|
561
|
|
- if(( rc = _cmRtNetCreateNode(p,m.endPtLabel,NULL,0,fromAddr)) != kOkNetRC )
|
|
573
|
+ if(( rc = _cmRtNetCreateNode(p,m.endPtLabel,NULL,0,fromAddr,kRecvNodeNetFl)) != kOkNetRC )
|
562
|
574
|
goto errLabel;
|
563
|
575
|
|
564
|
576
|
// send an ackknowledgement of the 'hello' msg
|
565
|
577
|
rc = _cmRtNetSendAck(p,kHelloAckSelNetId,fromAddr);
|
|
578
|
+
|
566
|
579
|
}
|
567
|
580
|
break;
|
568
|
581
|
|
|
@@ -573,7 +586,6 @@ cmRtNetRC_t cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataB
|
573
|
586
|
|
574
|
587
|
_cmRtNetRpt(p,"rcv endpoint\n");
|
575
|
588
|
|
576
|
|
-
|
577
|
589
|
// locate the remote node which sent the endpoint
|
578
|
590
|
if((np = _cmRtNetFindNodeFromSockAddr(p,fromAddr)) == NULL )
|
579
|
591
|
{
|
|
@@ -596,16 +608,29 @@ cmRtNetRC_t cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataB
|
596
|
608
|
}
|
597
|
609
|
break;
|
598
|
610
|
|
|
611
|
+ case kDoneSelNetId:
|
|
612
|
+ {
|
|
613
|
+ _cmRtNetRpt(p,"rcv done\n");
|
|
614
|
+
|
|
615
|
+ if( p->masterFl==false )
|
|
616
|
+ p->syncModeFl = true;
|
|
617
|
+ }
|
|
618
|
+ break;
|
|
619
|
+
|
599
|
620
|
case kHelloAckSelNetId: // master response
|
600
|
|
- assert( p->syncModeFl );
|
601
|
|
- _cmRtNetRpt(p,"rcv hello ack\n");
|
602
|
|
- rc = _cmRtNetRecvAck(p,fromAddr,kWaitHelloAckStNetId,kSendEndpointStNetId);
|
|
621
|
+ {
|
|
622
|
+ assert( p->syncModeFl );
|
|
623
|
+ _cmRtNetRpt(p,"rcv hello ack\n");
|
|
624
|
+ rc = _cmRtNetRecvAck(p,fromAddr,kWaitHelloAckStNetId,kSendEndpointStNetId);
|
|
625
|
+ }
|
603
|
626
|
break;
|
604
|
627
|
|
605
|
628
|
case kEndpointAckSelNetId: // master response
|
606
|
|
- assert( p->syncModeFl );
|
607
|
|
- _cmRtNetRpt(p,"rcv endpoint ack\n");
|
608
|
|
- rc = _cmRtNetRecvAck(p,fromAddr,kWaitEndpointAckStNetId,kSendEndpointStNetId);
|
|
629
|
+ {
|
|
630
|
+ assert( p->syncModeFl );
|
|
631
|
+ _cmRtNetRpt(p,"rcv endpoint ack\n");
|
|
632
|
+ rc = _cmRtNetRecvAck(p,fromAddr,kWaitEndpointAckStNetId,kSendEndpointStNetId);
|
|
633
|
+ }
|
609
|
634
|
break;
|
610
|
635
|
|
611
|
636
|
default:
|
|
@@ -613,6 +638,8 @@ cmRtNetRC_t cmRtNetSyncModeRecv( cmRtNetH_t h, const char* data, unsigned dataB
|
613
|
638
|
}
|
614
|
639
|
|
615
|
640
|
errLabel:
|
|
641
|
+
|
|
642
|
+ cmMemFree((cmChar_t*)m.endPtLabel);
|
616
|
643
|
return rc;
|
617
|
644
|
}
|
618
|
645
|
|
|
@@ -624,11 +651,15 @@ cmRtNetRC_t _cmRtNetSendNodeSync( cmRtNet_t* p, cmRtNetNode_t* np )
|
624
|
651
|
switch( np->state )
|
625
|
652
|
{
|
626
|
653
|
case kSendHelloStNetId:
|
627
|
|
- // send a 'hello' to this remote node
|
628
|
|
- if((rc = _cmRtNetSendSyncMsg(p,np,kHelloSelNetId,p->localNode->label, cmInvalidId, kWaitHelloAckStNetId )) != kOkNetRC )
|
629
|
|
- rc = cmErrMsg(&p->err,rc,"Send 'hello' to %s:%s:%i failed.",cmStringNullGuard(np->label),cmStringNullGuard(np->addr),np->port);
|
630
|
|
- else
|
631
|
|
- _cmRtNetRpt(p,"send hello\n");
|
|
654
|
+ {
|
|
655
|
+ np->epIdx = -1;
|
|
656
|
+
|
|
657
|
+ // send a 'hello' to this remote node
|
|
658
|
+ if((rc = _cmRtNetSendSyncMsg(p,np,kHelloSelNetId,p->localNode->label, cmInvalidId, kWaitHelloAckStNetId )) != kOkNetRC )
|
|
659
|
+ rc = cmErrMsg(&p->err,rc,"Send 'hello' to %s:%s:%i failed.",cmStringNullGuard(np->label),cmStringNullGuard(np->addr),np->port);
|
|
660
|
+ else
|
|
661
|
+ _cmRtNetRpt(p,"%s sent hello\n",cmStringNullGuard(np->label));
|
|
662
|
+ }
|
632
|
663
|
break;
|
633
|
664
|
|
634
|
665
|
case kSendEndpointStNetId:
|
|
@@ -637,14 +668,20 @@ cmRtNetRC_t _cmRtNetSendNodeSync( cmRtNet_t* p, cmRtNetNode_t* np )
|
637
|
668
|
|
638
|
669
|
// if all of the endpoints have been sent to this node ...
|
639
|
670
|
if((ep = _cmRtNetIndexToEndpoint(p,p->localNode,np->epIdx)) == NULL )
|
640
|
|
- np->state = kDoneStNetId; // ... we are done
|
|
671
|
+ {
|
|
672
|
+ // notify the remote node that all endpoints have been sent
|
|
673
|
+ if((rc = _cmRtNetSendSyncMsg(p,np,kDoneSelNetId,p->localNode->label,cmInvalidId, kDoneStNetId )) != kOkNetRC )
|
|
674
|
+ rc = cmErrMsg(&p->err,rc,"Send 'done' to %s:%s:%i failed.",cmStringNullGuard(np->label),cmStringNullGuard(np->addr),np->port);
|
|
675
|
+ else
|
|
676
|
+ _cmRtNetRpt(p,"Node %s done.\n",cmStringNullGuard(np->label));
|
|
677
|
+ }
|
641
|
678
|
else
|
642
|
679
|
{
|
643
|
680
|
// send an endpoint to this node
|
644
|
|
- if((rc = _cmRtNetSendSyncMsg(p,np,kHelloSelNetId,ep->endPtLabel, ep->endPtId, kWaitEndpointAckStNetId )) != kOkNetRC )
|
|
681
|
+ if((rc = _cmRtNetSendSyncMsg(p,np,kEndpointSelNetId,ep->endPtLabel, ep->endPtId, kWaitEndpointAckStNetId )) != kOkNetRC )
|
645
|
682
|
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);
|
646
|
683
|
else
|
647
|
|
- _cmRtNetRpt(p,"send endpoint\n");
|
|
684
|
+ _cmRtNetRpt(p,"%s sent endpoint %s\n",cmStringNullGuard(np->label),cmStringNullGuard(ep->endPtLabel));
|
648
|
685
|
|
649
|
686
|
}
|
650
|
687
|
}
|
|
@@ -688,14 +725,21 @@ cmRtNetRC_t cmRtNetSyncModeSend( cmRtNetH_t h )
|
688
|
725
|
unsigned activeCnt = 0;
|
689
|
726
|
cmRtNetNode_t* np = p->nodes;
|
690
|
727
|
for(; np != NULL; np=np->link )
|
691
|
|
- if( np != p->localNode && np->state != kDoneStNetId && np->state != kErrorStNetId )
|
|
728
|
+ {
|
|
729
|
+ bool fl = (p->masterFl && cmIsFlag(np->flags,kRegNodeNetFl)) || (p->masterFl==false && cmIsFlag(np->flags,kRecvNodeNetFl));
|
|
730
|
+
|
|
731
|
+ if( fl && np != p->localNode && np->state != kDoneStNetId && np->state != kErrorStNetId )
|
692
|
732
|
{
|
693
|
733
|
_cmRtNetSendNodeSync(p,np);
|
694
|
734
|
activeCnt += 1;
|
695
|
735
|
}
|
696
|
|
-
|
|
736
|
+ }
|
|
737
|
+
|
697
|
738
|
if( activeCnt == 0 )
|
|
739
|
+ {
|
698
|
740
|
p->syncModeFl = false;
|
|
741
|
+ _cmRtNetRpt(p,"sync mode complete.\n");
|
|
742
|
+ }
|
699
|
743
|
|
700
|
744
|
return rc;
|
701
|
745
|
}
|
|
@@ -853,6 +897,12 @@ void cmRtNetTest( cmCtx_t* ctx, bool mstrFl )
|
853
|
897
|
cmRptPrintf(&ctx->rpt,"%s q=quit\n", mstrFl ? "Master: " : "Slave: ");
|
854
|
898
|
while( (c=getchar()) != 'q' )
|
855
|
899
|
{
|
|
900
|
+ switch(c)
|
|
901
|
+ {
|
|
902
|
+ case 'r':
|
|
903
|
+ cmRtNetReport(p->netH);
|
|
904
|
+ break;
|
|
905
|
+ }
|
856
|
906
|
|
857
|
907
|
}
|
858
|
908
|
|