giuliomoro@135
|
1 #include "ClockSync.h"
|
giuliomoro@135
|
2
|
giuliomoro@135
|
3 void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){
|
giuliomoro@135
|
4 virtualClock=&aVirtualClock;
|
giuliomoro@135
|
5 }
|
giuliomoro@135
|
6 void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
|
giuliomoro@135
|
7 setVirtualClock(aVirtualClock);
|
giuliomoro@135
|
8 slave=thisIsSlave;
|
giuliomoro@135
|
9 setPort(aPort);
|
giuliomoro@135
|
10 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1");
|
giuliomoro@135
|
11 isSlave() ? client.setServer("192.168.7.1") : client.setServer("192.168.7.2");
|
giuliomoro@135
|
12 bufferLength=kSyncMessageLength;
|
giuliomoro@135
|
13 T1=-1;
|
giuliomoro@135
|
14 T1p=-1;
|
giuliomoro@135
|
15 T2=-1;
|
giuliomoro@135
|
16 T2p=-1;
|
giuliomoro@135
|
17 receiveLoopSleepUs=10;
|
giuliomoro@135
|
18 receiveLoopTimeout=1e5;
|
giuliomoro@135
|
19 movingAverage.setLength(201);
|
giuliomoro@135
|
20 expectedClockSyncType=isSlave() ? kSync : kNone;
|
giuliomoro@135
|
21 }
|
giuliomoro@135
|
22 ClockSync::ClockSync(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
|
giuliomoro@135
|
23 init(thisIsSlave, aPort, aVirtualClock);
|
giuliomoro@135
|
24 }
|
giuliomoro@135
|
25 void* ClockSync::getBuffer(){
|
giuliomoro@135
|
26 return buffer;
|
giuliomoro@135
|
27 }
|
giuliomoro@135
|
28 bool ClockSync::isSlave(){
|
giuliomoro@135
|
29 return slave;
|
giuliomoro@135
|
30 }
|
giuliomoro@135
|
31 bool ClockSync::isMaster(){
|
giuliomoro@135
|
32 return !slave;
|
giuliomoro@135
|
33 }
|
giuliomoro@135
|
34 int ClockSync::getType(){
|
giuliomoro@135
|
35 return ((int*)buffer)[0];
|
giuliomoro@135
|
36 }
|
giuliomoro@135
|
37 myClock_t ClockSync::getTimestamp(){
|
giuliomoro@135
|
38 return *((myClock_t*)((char*)buffer+sizeof(int)));
|
giuliomoro@135
|
39 }
|
giuliomoro@135
|
40 void ClockSync::setType(int clockSyncType){
|
giuliomoro@135
|
41 ((int*)buffer)[0]=clockSyncType;
|
giuliomoro@135
|
42 }
|
giuliomoro@135
|
43 void ClockSync::setTimestamp(myClock_t timestamp){
|
giuliomoro@135
|
44 ((myClock_t*)((char*)buffer+sizeof(int)))[0]=timestamp;
|
giuliomoro@135
|
45 }
|
giuliomoro@135
|
46 void ClockSync::print(){
|
giuliomoro@135
|
47 //printf("type: %d, timestamp: %lld\n",*((int*)buffer),*((myClock_t*)(((int*)buffer)+1)));
|
giuliomoro@135
|
48 }
|
giuliomoro@135
|
49 void ClockSync::setPort(int aPort){
|
giuliomoro@135
|
50 if(aPort>0){
|
giuliomoro@135
|
51 int inPort=isSlave() ? aPort : aPort+1;
|
giuliomoro@135
|
52 int outPort=isSlave() ? aPort+1: aPort;
|
giuliomoro@135
|
53 server.bindToPort(inPort);
|
giuliomoro@135
|
54 client.setPort(outPort);
|
giuliomoro@135
|
55 //printf("Receiving on port %d\n", inPort);
|
giuliomoro@135
|
56 //printf("Sending to port %d\n", outPort);
|
giuliomoro@135
|
57 }
|
giuliomoro@135
|
58 }
|
giuliomoro@135
|
59 /**
|
giuliomoro@135
|
60 * sends a clockSync without blocking, checks results and returns the timestamp
|
giuliomoro@135
|
61 * immediately after the clockSync has been sent or -1 if there was an error or timeout expired.
|
giuliomoro@135
|
62 */
|
giuliomoro@135
|
63 myClock_t ClockSync::send(){
|
giuliomoro@135
|
64 // print();
|
giuliomoro@135
|
65 int ret;
|
giuliomoro@135
|
66 ret=client.waitUntilReady(false, 0);
|
giuliomoro@135
|
67 if(ret<=0){ //don't retry
|
giuliomoro@135
|
68 return -1;
|
giuliomoro@135
|
69 }
|
giuliomoro@135
|
70 ret=client.send(buffer, bufferLength);
|
giuliomoro@135
|
71 myClock_t timestamp=(myClock_t)virtualClock->getNow();
|
giuliomoro@135
|
72 if(ret<0){
|
giuliomoro@135
|
73 //if there was an error while sending, don't retry
|
giuliomoro@135
|
74 return -1;
|
giuliomoro@135
|
75 }
|
giuliomoro@135
|
76 return timestamp; //get the accurate time *after* you sent the sync clockSync
|
giuliomoro@135
|
77 }
|
giuliomoro@135
|
78 /**
|
giuliomoro@135
|
79 * receives a clockSync without blocking, checks results and returns the timestamp
|
giuliomoro@135
|
80 * immediately after the clockSync has been received, or -1 if there was an error
|
giuliomoro@135
|
81 * or 0 if timeout expired.
|
giuliomoro@135
|
82 */
|
giuliomoro@135
|
83 myClock_t ClockSync::receive(){
|
giuliomoro@135
|
84 int ret;
|
giuliomoro@135
|
85 ret=server.waitUntilReady(true, 0);
|
giuliomoro@135
|
86 if(ret<=0){ //don't retry
|
giuliomoro@135
|
87 return 0;
|
giuliomoro@135
|
88 }
|
giuliomoro@135
|
89 ret=server.read(buffer, bufferLength, false);
|
giuliomoro@135
|
90 myClock_t timestamp=(myClock_t)virtualClock->getNow();
|
giuliomoro@135
|
91 if(timestamp==0){
|
giuliomoro@135
|
92 //printf("The virtualClock period is <=0\n");
|
giuliomoro@135
|
93 return -3;
|
giuliomoro@135
|
94 }
|
giuliomoro@135
|
95 if(ret==-1){
|
giuliomoro@135
|
96 //if there was an error while receiving, don't retry
|
giuliomoro@135
|
97 return -1;
|
giuliomoro@135
|
98 }
|
giuliomoro@135
|
99 if(ret!=bufferLength){
|
giuliomoro@135
|
100 //printf("Received a clockSync of the wrong size: %d\n", ret);
|
giuliomoro@135
|
101 return -2;
|
giuliomoro@135
|
102 }
|
giuliomoro@135
|
103 // print();
|
giuliomoro@135
|
104 return timestamp; //get the accurate time *after* you sent the sync clockSync
|
giuliomoro@135
|
105 }
|
giuliomoro@135
|
106
|
giuliomoro@135
|
107 int ClockSync::masterSendSync(){
|
giuliomoro@135
|
108 //let's send a sync clockSync!
|
giuliomoro@135
|
109 //printf("Sending a sync clockSync\n");
|
giuliomoro@135
|
110 setType(kSync);
|
giuliomoro@135
|
111 setTimestamp(-1);//do not care about sending the timestamp, a more accurate one will be sent in the follow up
|
giuliomoro@135
|
112 localTimestamp=send();
|
giuliomoro@135
|
113 if(localTimestamp<0){
|
giuliomoro@135
|
114 //printf("Could not send sync clockSync\n");
|
giuliomoro@135
|
115 return -1; //error, don't retry, start over
|
giuliomoro@135
|
116 }
|
giuliomoro@135
|
117 //let's send a followUp
|
giuliomoro@135
|
118 //printf("sent a sync clockSync\n");
|
giuliomoro@135
|
119 setType(kFollowUp);
|
giuliomoro@135
|
120 setTimestamp(localTimestamp);
|
giuliomoro@135
|
121 if(localTimestamp<0){
|
giuliomoro@135
|
122 //printf("Could not send followup clockSync\n");
|
giuliomoro@135
|
123 return -2; //error, don't retry, start over
|
giuliomoro@135
|
124 }
|
giuliomoro@135
|
125 int ret=send();
|
giuliomoro@135
|
126 if(ret<0){
|
giuliomoro@135
|
127 //printf("Error while sending followup\n");
|
giuliomoro@135
|
128 return -3;
|
giuliomoro@135
|
129 }
|
giuliomoro@135
|
130 //printf("sent a followUp clockSync\n");
|
giuliomoro@135
|
131 expectedClockSyncType=kDelayReq;
|
giuliomoro@135
|
132 return 1;
|
giuliomoro@135
|
133 }
|
giuliomoro@135
|
134 #ifdef USE_JUCE
|
giuliomoro@135
|
135 #define NOTGSHOULDSTOP 1
|
giuliomoro@135
|
136 #else
|
giuliomoro@135
|
137 extern bool gShouldStop;
|
giuliomoro@135
|
138 #define NOTGSHOULDSTOP (!gShouldStop)
|
giuliomoro@135
|
139 #endif /* USE_JUCE */
|
giuliomoro@135
|
140 int ClockSync::receiveLoop(){
|
giuliomoro@135
|
141 int receiveLoopElapsed=0;
|
giuliomoro@135
|
142 while( NOTGSHOULDSTOP && (isSlave() || (receiveLoopElapsed<receiveLoopTimeout))){ //when slave, does not timeout!
|
giuliomoro@135
|
143 receiveLoopElapsed+=receiveLoopSleepUs;
|
giuliomoro@135
|
144 usleep(receiveLoopSleepUs); //how often to check for new clockSyncs;
|
giuliomoro@135
|
145 // //printf("waiting for clockSyncs\n");
|
giuliomoro@135
|
146 localTimestamp=receive();
|
giuliomoro@135
|
147 if(localTimestamp<=0){
|
giuliomoro@135
|
148 if(localTimestamp==0){
|
giuliomoro@135
|
149 // //printf("Socket not ready to be read: %lld\n", localTimestamp);
|
giuliomoro@135
|
150 }
|
giuliomoro@135
|
151 else if(localTimestamp==-1){
|
giuliomoro@135
|
152 //printf("Error while receiving: %lld\n", localTimestamp);
|
giuliomoro@135
|
153 }
|
giuliomoro@135
|
154 else if(localTimestamp==-2){
|
giuliomoro@135
|
155 // //printf("Wrong size of the received clockSync: %lld\n", localTimestamp);
|
giuliomoro@135
|
156 }
|
giuliomoro@135
|
157 continue ; //keep waiting
|
giuliomoro@135
|
158 }
|
giuliomoro@135
|
159 clockSyncType=getType();
|
giuliomoro@135
|
160 clockSyncTimestamp=getTimestamp();
|
giuliomoro@135
|
161 if(clockSyncType!=expectedClockSyncType){
|
giuliomoro@135
|
162 //printf("Wrong clockSync type: %d, expected: %d\n",clockSyncType, expectedClockSyncType);
|
giuliomoro@135
|
163 return -2; //start over
|
giuliomoro@135
|
164 }
|
giuliomoro@135
|
165 //printf("Received clockSync type: %d, clockSyncTimestamp: %lld\n", clockSyncType, clockSyncTimestamp);
|
giuliomoro@135
|
166 if(isSlave()==true){
|
giuliomoro@135
|
167 int ret=slaveHandleMessage();
|
giuliomoro@135
|
168 if(ret==1 && clockSyncType==kDelayResp){ //we are done, end of a cycle!
|
giuliomoro@135
|
169 return 1;
|
giuliomoro@135
|
170 } else if (ret!=1) {
|
giuliomoro@135
|
171 return -1; //
|
giuliomoro@135
|
172 } else {
|
giuliomoro@135
|
173 continue;
|
giuliomoro@135
|
174 }
|
giuliomoro@135
|
175 }
|
giuliomoro@135
|
176 if(isMaster()==true){ //this is master
|
giuliomoro@135
|
177 int ret=masterHandleMessage();
|
giuliomoro@135
|
178 if(ret==1 && clockSyncType==kDelayReq){ //we are done, end of a cycle!
|
giuliomoro@135
|
179 return 1;
|
giuliomoro@135
|
180 } else {
|
giuliomoro@135
|
181 return -2; //we are done but something was wrong
|
giuliomoro@135
|
182 }
|
giuliomoro@135
|
183 }
|
giuliomoro@135
|
184 }
|
giuliomoro@135
|
185 //printf("Receive loop timeout\n");
|
giuliomoro@135
|
186 return -1;
|
giuliomoro@135
|
187 }
|
giuliomoro@135
|
188
|
giuliomoro@135
|
189 int ClockSync::slaveHandleMessage(){
|
giuliomoro@135
|
190 switch(clockSyncType){
|
giuliomoro@135
|
191 case kSync: //the clockSync timestamp is meaningless, the localTimestamp is when kSync was received
|
giuliomoro@135
|
192 T1p=localTimestamp;
|
giuliomoro@135
|
193 expectedClockSyncType=kFollowUp;
|
giuliomoro@135
|
194 break;
|
giuliomoro@135
|
195 case kFollowUp: //the clockSyncTimestamp is the time when kSync was sent, the localTimestamp is meaningless
|
giuliomoro@135
|
196 T1=clockSyncTimestamp;
|
giuliomoro@135
|
197 //send delayReq
|
giuliomoro@135
|
198 setType(kDelayReq);
|
giuliomoro@135
|
199 setTimestamp(-1);
|
giuliomoro@135
|
200 T2=send();
|
giuliomoro@135
|
201 if(T2<0){
|
giuliomoro@135
|
202 //printf("Error while sending delayReq\n");
|
giuliomoro@135
|
203 return -1;
|
giuliomoro@135
|
204 }
|
giuliomoro@135
|
205 expectedClockSyncType=kDelayResp;
|
giuliomoro@135
|
206 break;
|
giuliomoro@135
|
207 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless
|
giuliomoro@135
|
208 T2p=clockSyncTimestamp;
|
giuliomoro@135
|
209 //TODO: evaluate things
|
giuliomoro@135
|
210 double offset=(T1p-T1-T2p+T2)/2.0d;
|
giuliomoro@135
|
211 printf("-----------OFFSET IS : %04.1f, average: %04.2f\n", offset, movingAverage.add(offset));
|
giuliomoro@135
|
212 expectedClockSyncType=kSync; //end of the cycle, wait for next sync.
|
giuliomoro@135
|
213 break;
|
giuliomoro@135
|
214 }
|
giuliomoro@135
|
215 default:
|
giuliomoro@135
|
216 //printf("Unexpected message type\n"); // we should never get here
|
giuliomoro@135
|
217 return -1;
|
giuliomoro@135
|
218 }
|
giuliomoro@135
|
219 return 1;
|
giuliomoro@135
|
220 }
|
giuliomoro@135
|
221
|
giuliomoro@135
|
222 int ClockSync::masterHandleMessage(){
|
giuliomoro@135
|
223 switch(clockSyncType){
|
giuliomoro@135
|
224 case kDelayReq:
|
giuliomoro@135
|
225 //TODO: do something with it
|
giuliomoro@135
|
226 //send kDelayResp
|
giuliomoro@135
|
227 setType(kDelayResp);
|
giuliomoro@135
|
228 setTimestamp(localTimestamp);
|
giuliomoro@135
|
229 send();
|
giuliomoro@135
|
230 expectedClockSyncType=kNone;
|
giuliomoro@135
|
231 break;
|
giuliomoro@135
|
232 }
|
giuliomoro@135
|
233 }
|
giuliomoro@135
|
234
|
giuliomoro@135
|
235 int ClockSync::sendReceiveLoop(){
|
giuliomoro@135
|
236 if(isSlave()==true){
|
giuliomoro@135
|
237 //printf("Waiting for a sync clockSync\n");
|
giuliomoro@135
|
238 } else { //if this is master
|
giuliomoro@135
|
239 usleep(100000); //this times (roughly) how often sync clockSyncs are being sent.
|
giuliomoro@135
|
240 int ret=masterSendSync();
|
giuliomoro@135
|
241 if(ret<=0)
|
giuliomoro@135
|
242 return -1;
|
giuliomoro@135
|
243 }
|
giuliomoro@135
|
244 int ret=receiveLoop();
|
giuliomoro@135
|
245 if(ret<=0)
|
giuliomoro@135
|
246 return -2;
|
giuliomoro@135
|
247 return 1;
|
giuliomoro@135
|
248 }
|
giuliomoro@135
|
249
|
giuliomoro@135
|
250
|