| rev |
line source |
|
msach@0
|
1 /*
|
|
msach@0
|
2 * For a detailed description see header file.
|
|
msach@0
|
3 */
|
|
msach@0
|
4
|
|
msach@4
|
5 #include <string.h>
|
|
msach@4
|
6
|
|
msach@0
|
7 #include "LossyCom.h"
|
|
msach@0
|
8 #include "VMS_Implementations/VMS_impl/vmalloc.h"
|
|
msach@0
|
9
|
|
msach@0
|
10 /*
|
|
msach@5
|
11 * Initializes the central exchange structure and sets all trigger counter to 0
|
|
msach@0
|
12 * Allocates memory to fit the number of endpoints.
|
|
msach@0
|
13 * Returns NULL if an error occurs.
|
|
msach@0
|
14 */
|
|
msach@0
|
15 lossyCom__exchange_t* lossyCom__initialize(uint16_t numEndpoints)
|
|
msach@0
|
16 {
|
|
msach@5
|
17 lossyCom__exchange_t* centralExchange;
|
|
msach@0
|
18
|
|
msach@5
|
19 centralExchange = VMS_WL__malloc(sizeof(lossyCom__exchange_t));
|
|
msach@5
|
20 if(centralExchange == NULL)
|
|
msach@0
|
21 return NULL;
|
|
msach@0
|
22
|
|
msach@5
|
23 centralExchange->broadcastTriggerCounter = 0;
|
|
msach@5
|
24 centralExchange->numEndpoints = numEndpoints;
|
|
msach@5
|
25 centralExchange->outboxArray = VMS_WL__malloc(sizeof(lossyCom__msg_t)*numEndpoints);
|
|
msach@5
|
26 if(centralExchange->outboxArray == NULL){
|
|
msach@5
|
27 VMS_WL__free(centralExchange);
|
|
msach@0
|
28 return NULL;
|
|
msach@0
|
29 }
|
|
msach@0
|
30
|
|
msach@5
|
31 centralExchange->p2pTriggerCounters = VMS_WL__malloc(sizeof(uint16_t)*numEndpoints);
|
|
msach@5
|
32 if(centralExchange->p2pTriggerCounters == NULL){
|
|
msach@5
|
33 VMS_WL__free(centralExchange->outboxArray);
|
|
msach@5
|
34 VMS_WL__free(centralExchange);
|
|
msach@4
|
35 return NULL;
|
|
msach@4
|
36 }
|
|
msach@4
|
37
|
|
msach@4
|
38 //reset all point 2 point trigger counter
|
|
msach@5
|
39 memset((void*)centralExchange->p2pTriggerCounters, 0, sizeof(uint16_t)*numEndpoints);
|
|
msach@4
|
40
|
|
msach@5
|
41 return centralExchange;
|
|
msach@0
|
42 }
|
|
msach@0
|
43
|
|
msach@1
|
44 /*
|
|
msach@1
|
45 * Connects the local endpoint to the central exchange structure.
|
|
msach@5
|
46 * This registers a message handler that handles all incoming messages.
|
|
msach@1
|
47 * Also an endpointID is set this ID has to be between 0 and total number of
|
|
msach@5
|
48 * endpoints-1 and unique.
|
|
msach@1
|
49 */
|
|
msach@0
|
50 void lossyCom__initialize_endpoint(lossyCom__endpoint_t* localEndpoint,
|
|
msach@0
|
51 lossyCom__exchange_t* centralExchange,
|
|
msach@0
|
52 lossyCom__endpointID_t endpointID,
|
|
msach@1
|
53 lossyCom__msgHandler msgHandler,
|
|
msach@1
|
54 void* msgHandlerData)
|
|
msach@0
|
55 {
|
|
msach@4
|
56 localEndpoint->lastReceivedBroadcastTrigger = 0;
|
|
msach@0
|
57 localEndpoint->endpointID = endpointID;
|
|
msach@1
|
58 localEndpoint->centralExchange = centralExchange;
|
|
msach@1
|
59 localEndpoint->msgHandler = msgHandler;
|
|
msach@1
|
60 localEndpoint->msgHandlerData = msgHandlerData;
|
|
msach@0
|
61 }
|
|
msach@0
|
62
|
|
msach@5
|
63 /*
|
|
msach@5
|
64 * Prepare a lossyCom__msg_t in the correct format that contains the trigger
|
|
msach@5
|
65 * value, the receiver endpoint ID and the message body
|
|
msach@5
|
66 */
|
|
msach@4
|
67 inline lossyCom__msg_t prepareMsg(uint16_t triggerValue,
|
|
msach@4
|
68 lossyCom__endpointID_t receiverEndpointID,
|
|
msach@5
|
69 lossyCom__msgBody_t msgBody)
|
|
msach@4
|
70 {
|
|
msach@4
|
71 lossyCom__msg_t msgDraft;
|
|
msach@4
|
72
|
|
msach@5
|
73 msgDraft = (0 | msgBody);
|
|
msach@4
|
74 msgDraft |= ((lossyCom__msg_t)receiverEndpointID << ENDPOINT_ID_SHIFT);
|
|
msach@4
|
75 msgDraft |= ((lossyCom__msg_t)triggerValue << TRIGGER_SHIFT);
|
|
msach@4
|
76
|
|
msach@4
|
77 return msgDraft;
|
|
msach@4
|
78 }
|
|
msach@4
|
79
|
|
msach@1
|
80 /*
|
|
msach@1
|
81 * This broadcasts a message to all connected receivers
|
|
msach@1
|
82 */
|
|
msach@4
|
83 void lossyCom__broadcastMsg(lossyCom__endpoint_t* localEndpoint,
|
|
msach@4
|
84 lossyCom__msgBody_t msgBody)
|
|
msach@0
|
85 {
|
|
msach@4
|
86 lossyCom__exchange_t* centralExchange = localEndpoint->centralExchange;
|
|
msach@4
|
87 uint16_t increasedTrigger;
|
|
msach@4
|
88 lossyCom__msg_t msg;
|
|
msach@4
|
89
|
|
msach@5
|
90 increasedTrigger = centralExchange->broadcastTriggerCounter +1;
|
|
msach@4
|
91
|
|
msach@4
|
92 //build message
|
|
msach@4
|
93 msg = prepareMsg(increasedTrigger, BROADCAST_ID, msgBody);
|
|
msach@4
|
94
|
|
msach@4
|
95 //write msg to central exchange
|
|
msach@4
|
96 centralExchange->outboxArray[localEndpoint->endpointID] = msg;
|
|
msach@4
|
97
|
|
msach@4
|
98 //update broadcast trigger counter
|
|
msach@5
|
99 centralExchange->broadcastTriggerCounter = increasedTrigger;
|
|
msach@0
|
100 }
|
|
msach@0
|
101
|
|
msach@1
|
102 /*
|
|
msach@1
|
103 * This sends a message another endpoint. Again it is not guaranteed that the
|
|
msach@1
|
104 * message is received. But in most cases it will.
|
|
msach@1
|
105 */
|
|
msach@4
|
106 void lossyCom__sendMsg(lossyCom__endpoint_t* localEndpoint,
|
|
msach@0
|
107 lossyCom__endpointID_t receiverEndpointID,
|
|
msach@4
|
108 lossyCom__msgBody_t msgBody)
|
|
msach@0
|
109 {
|
|
msach@4
|
110 lossyCom__exchange_t* centralExchange = localEndpoint->centralExchange;
|
|
msach@4
|
111 lossyCom__msg_t msg;
|
|
msach@4
|
112 uint16_t increasedTrigger;
|
|
msach@0
|
113
|
|
msach@4
|
114 increasedTrigger =
|
|
msach@5
|
115 centralExchange->p2pTriggerCounters[receiverEndpointID] +1;
|
|
msach@0
|
116
|
|
msach@4
|
117 //build message
|
|
msach@4
|
118 msg = prepareMsg(increasedTrigger, receiverEndpointID, msgBody);
|
|
msach@0
|
119
|
|
msach@0
|
120 //write msg to central exchange
|
|
msach@4
|
121 centralExchange->outboxArray[localEndpoint->endpointID] = msg;
|
|
msach@0
|
122
|
|
msach@4
|
123 //write back increased trigger counter
|
|
msach@5
|
124 centralExchange->p2pTriggerCounters[receiverEndpointID] = increasedTrigger;
|
|
msach@0
|
125 }
|
|
msach@0
|
126
|
|
msach@4
|
127 int inline isUnreceivedMsg(uint16_t msgTrigger,
|
|
msach@4
|
128 uint16_t lastReceivedTrigger,
|
|
msach@4
|
129 uint16_t triggerSnapshot)
|
|
msach@0
|
130 {
|
|
msach@4
|
131 if(msgTrigger > lastReceivedTrigger ||
|
|
msach@4
|
132 msgTrigger <= triggerSnapshot)
|
|
msach@4
|
133 {
|
|
msach@4
|
134 // check if the message is new (msg trigger > archived trigger)
|
|
msach@4
|
135 // and already valid (msgTrigger <= currentTriggerCopy)
|
|
msach@4
|
136 if((msgTrigger > lastReceivedTrigger &&
|
|
msach@4
|
137 msgTrigger <= triggerSnapshot) ||
|
|
msach@4
|
138 ((int64_t) triggerSnapshot- // check for triggerCounterOverflow
|
|
msach@4
|
139 (int64_t)lastReceivedTrigger < -MAX_TRIGGER/2))
|
|
msach@4
|
140 {
|
|
msach@4
|
141 return TRUE;
|
|
msach@4
|
142 }
|
|
msach@4
|
143 }
|
|
msach@4
|
144 return FALSE;
|
|
msach@4
|
145 }
|
|
msach@4
|
146
|
|
msach@4
|
147 void lossyCom__receiveMsg(lossyCom__endpoint_t* localEndpoint)
|
|
msach@4
|
148 {
|
|
msach@4
|
149 uint16_t broadcastTriggerSnapshot, p2pTriggerSnapshot;
|
|
msach@4
|
150 lossyCom__exchange_t* centralExchange;
|
|
msach@0
|
151 lossyCom__endpointID_t senderEndpointID;
|
|
msach@4
|
152 lossyCom__endpointID_t receiverEndpointID;
|
|
msach@0
|
153 lossyCom__msg_t msgCopy;
|
|
msach@0
|
154 uint16_t msgTrigger;
|
|
msach@0
|
155 lossyCom__msgBody_t msgBody;
|
|
msach@0
|
156
|
|
msach@4
|
157 centralExchange = localEndpoint->centralExchange;
|
|
msach@4
|
158 //save trigger counter to know find valid messages
|
|
msach@5
|
159 broadcastTriggerSnapshot = centralExchange->broadcastTriggerCounter;
|
|
msach@4
|
160 p2pTriggerSnapshot =
|
|
msach@5
|
161 centralExchange->p2pTriggerCounters[localEndpoint->endpointID];
|
|
msach@1
|
162
|
|
msach@0
|
163 //new message arrived if trigger counter is higher than the last time read
|
|
msach@4
|
164 if( broadcastTriggerSnapshot > localEndpoint->lastReceivedBroadcastTrigger ||
|
|
msach@4
|
165 p2pTriggerSnapshot > localEndpoint->lastReceivedp2pTrigger)
|
|
msach@0
|
166 {
|
|
msach@4
|
167 senderEndpointID = 0;
|
|
msach@4
|
168 //search outboxes for new messages
|
|
msach@4
|
169 while(senderEndpointID < centralExchange->numEndpoints)
|
|
msach@0
|
170 {
|
|
msach@4
|
171 //ignore own outbox
|
|
msach@2
|
172 if(senderEndpointID != localEndpoint->endpointID)
|
|
msach@0
|
173 {
|
|
msach@4
|
174 msgCopy = centralExchange->outboxArray[senderEndpointID];
|
|
msach@2
|
175 msgTrigger = 0xFFFF & (msgCopy >> TRIGGER_SHIFT);
|
|
msach@4
|
176 receiverEndpointID = 0xFFFF & (msgCopy >> ENDPOINT_ID_SHIFT);
|
|
msach@3
|
177
|
|
msach@4
|
178 if(receiverEndpointID == BROADCAST_ID){//receive broadcast message
|
|
msach@4
|
179 if(isUnreceivedMsg(msgTrigger,
|
|
msach@4
|
180 localEndpoint->lastReceivedBroadcastTrigger,
|
|
msach@4
|
181 broadcastTriggerSnapshot))
|
|
msach@2
|
182 {
|
|
msach@3
|
183 //let the message handler parse the message
|
|
msach@4
|
184 msgBody = 0xFFFFFFFF & msgCopy;
|
|
msach@3
|
185 //only receive broadcast and p2p for own receiverID
|
|
msach@4
|
186
|
|
msach@4
|
187 (*(localEndpoint->msgHandler))(senderEndpointID,
|
|
msach@4
|
188 msgBody,
|
|
msach@4
|
189 localEndpoint->msgHandlerData);
|
|
msach@4
|
190 }
|
|
msach@4
|
191 }else{//point 2 point message
|
|
msach@4
|
192 if(receiverEndpointID == localEndpoint->endpointID &&
|
|
msach@4
|
193 isUnreceivedMsg(msgTrigger,
|
|
msach@4
|
194 localEndpoint->lastReceivedp2pTrigger,
|
|
msach@4
|
195 p2pTriggerSnapshot))
|
|
msach@4
|
196 {
|
|
msach@4
|
197 //let the message handler parse the message
|
|
msach@4
|
198 msgBody = 0xFFFFFFFF & msgCopy;
|
|
msach@4
|
199 //only receive broadcast and p2p for own receiverID
|
|
msach@4
|
200
|
|
msach@4
|
201 (*(localEndpoint->msgHandler))(senderEndpointID,
|
|
msach@4
|
202 msgBody,
|
|
msach@4
|
203 localEndpoint->msgHandlerData);
|
|
msach@4
|
204 }
|
|
msach@2
|
205 }
|
|
msach@0
|
206 }
|
|
msach@2
|
207 senderEndpointID++;
|
|
msach@4
|
208 }//search outbox loop
|
|
msach@0
|
209 }
|
|
msach@2
|
210 //save last TriggerCounter of last parsed Msg
|
|
msach@4
|
211 localEndpoint->lastReceivedBroadcastTrigger = broadcastTriggerSnapshot;
|
|
msach@4
|
212 localEndpoint->lastReceivedp2pTrigger = p2pTriggerSnapshot;
|
|
msach@0
|
213 } |