1 #include <OlsrdPudWireFormat/wireFormat.h>
2 #include <OlsrdPudWireFormat/compiler.h>
4 /* ************************************************************************
6 * ************************************************************************ */
8 static unsigned long long cachedValidityTimeMsn[16];
10 static bool cachedValidityTimeMsnValid = false;
13 Setup of cache of calculated most significant nibble results of the validity
14 time calculation to speed up run-time calculations. This method has to be
15 called once upon first use of ValidityTime functions.
17 static void setupCachedValidityTimeMsn(void) {
19 for (msn = 0; msn < 16; msn++) {
20 cachedValidityTimeMsn[msn] = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
22 cachedValidityTimeMsnValid = true;
25 /* ************************************************************************
27 * ************************************************************************ */
29 /** The size of the cached nodeId buffer */
30 #define PUD_CACHED_NODEID_BUFFER_SIZE 256
32 /** The cached nodeId buffer: contains a pre-processed version of the nodeId
33 in order to improve performance. It is currently used for nodeIdTypes
34 PUD_NODEIDTYPE_MSISDN, PUD_NODEIDTYPE_TETRA, PUD_NODEIDTYPE_MMSI,
35 PUD_NODEIDTYPE_URN, PUD_NODEIDTYPE_192, PUD_NODEIDTYPE_193
36 (so basically for numbers that will not change) */
37 static unsigned char cachedNodeIdBuffer[PUD_CACHED_NODEID_BUFFER_SIZE];
39 /** The number of bytes stored in cachedNodeIdBuffer */
40 static unsigned int cachedNodeIdBufferLength = 0;
43 Check a nodeId number for validity and if valid set it up in the
44 cachedNodeIdBuffer. The valid range for the number is [min, max].
47 The value to setup in the cache
49 The lower bound for a valid number
51 The upper bound for a valid number
53 The number of bytes used by the number in the wire format
56 - true when the number is valid
59 bool setupNodeIdNumberForOlsrCache(unsigned long long val,
60 unsigned long long min, unsigned long long max, unsigned int bytes) {
61 assert(bytes <= PUD_CACHED_NODEID_BUFFER_SIZE);
63 if ((val >= min) && (val <= max)) {
66 cachedNodeIdBuffer[i] = val & 0xff;
73 cachedNodeIdBufferLength = bytes;
81 Setup a nodeId buffer in the cachedNodeIdBuffer.
84 The value to setup in the cache
86 The number of bytes used by the number in the wire format
89 - true when the number is valid
92 bool setupNodeIdBinaryBufferForOlsrCache(void * val, size_t bytes) {
93 if (bytes >= PUD_CACHED_NODEID_BUFFER_SIZE) {
97 memcpy(cachedNodeIdBuffer, val, bytes);
98 cachedNodeIdBufferLength = bytes;
102 /* ************************************************************************
104 * ************************************************************************ */
106 /* inline getValidityTime */
109 Set the validity time of the position update message
111 @param validityTimeField
112 A pointer to the validity time field
114 The validity time in seconds
116 void setValidityTime(uint8_t * validityTimeField,
117 unsigned long long validityTime) {
118 unsigned int msn = 1;
119 unsigned long long lsn = 0;
120 unsigned long long upperBound;
122 if (!cachedValidityTimeMsnValid) {
123 setupCachedValidityTimeMsn();
125 upperBound = cachedValidityTimeMsn[msn];
126 while ((msn < 16) && (validityTime >= upperBound)) {
128 upperBound = cachedValidityTimeMsn[msn];
132 if (unlikely(validityTime >= upperBound)) {
135 unsigned long lowerBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
136 unsigned long resolution = (1 << msn);
137 lsn = ((validityTime - lowerBound + (resolution >> 1)) / resolution);
143 *validityTimeField = ((msn << 4) | lsn);
146 /* ************************************************************************
147 * UplinkPositionUpdate
148 * ************************************************************************ */
150 /* inline uint8_t getUplinkMessageType */
151 /* inline void setUplinkMessageType */
153 /* inline uint16_t getUplinkMessageLength */
154 /* inline void setUplinkMessageLength */
156 /* inline bool getUplinkMessageIPv6 */
157 /* inline void setUplinkMessageIPv6 */
159 /* inline void setUplinkMessagePadding */
161 /* ************************************************************************
163 * ************************************************************************ */
165 /* inline union olsr_ip_addr * getOlsrMessageOriginator */
167 /* inline PudOlsrPositionUpdate * getOlsrMessagePayload */
169 /* ************************************************************************
170 * PudOlsrPositionUpdate
171 * ************************************************************************ */
173 /* inline uint8_t getPositionUpdateVersion */
174 /* inline void setPositionUpdateVersion */
176 /* inline uint8_t getPositionUpdateSmask */
177 /* inline void setPositionUpdateSmask */
179 /* ************************************************************************
181 * ************************************************************************ */
183 /* inline void setPositionUpdateTime */
186 Convert the time of an OLSR message (the number of seconds after midnight) to
187 a time structure, based on midnight of the current day.
189 @param olsrGpsMessage
190 A pointer to the position update message
192 The base date from which to determine the time (number of seconds since Epoch,
195 A pointer to the time structure into which to put the converted time
197 void getPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
198 time_t baseDate, struct tm *nowStruct) {
199 uint32_t olsrTime = olsrGpsMessage->gpsInfo.time;
202 time_t now = baseDate;
203 gmtime_r(&now, nowStruct);
205 secNow = ((nowStruct->tm_hour * 60 * 60) + (nowStruct->tm_min * 60)
206 + nowStruct->tm_sec);
208 if (secNow <= (12 * 60 * 60)) {
209 /* we are now in the first 12h of the day */
210 if (unlikely(olsrTime > (secNow + (12 * 60 * 60)))) {
211 /* the message was sent more than 12h later in time:
212 the message was sent yesterday: adjust the date by -1 day */
213 now -= (24 * 60 * 60);
214 gmtime_r(&now, nowStruct);
217 /* we are now in the last 12h of the day */
218 if (unlikely(olsrTime < (secNow - (12 * 60 * 60)))) {
219 /* the message was sent more than 12h earlier in time:
220 the message was sent tomorrow: adjust the date by +1 day */
221 now += (24 * 60 * 60);
222 gmtime_r(&now, nowStruct);
226 nowStruct->tm_hour = ((olsrTime % (24 * 60 * 60)) / 3600);
227 nowStruct->tm_min = ((olsrTime % (60 * 60)) / 60);
228 nowStruct->tm_sec = (olsrTime % 60);
231 /* inline double getPositionUpdateLatitude */
232 /* inline void setPositionUpdateLatitude */
234 /* inline double getPositionUpdateLongitude */
235 /* inline void setPositionUpdateLongitude */
237 /* inline long getPositionUpdateAltitude */
238 /* inline void setPositionUpdateAltitude */
240 /* inline unsigned long getPositionUpdateSpeed */
241 /* inline void setPositionUpdateSpeed */
243 /* inline unsigned long getPositionUpdateTrack */
244 /* inline void setPositionUpdateTrack */
246 /* inline double getPositionUpdateHdop */
247 /* inline void setPositionUpdateHdop */
249 /* ************************************************************************
251 * ************************************************************************ */
253 /* inline NodeIdType getPositionUpdateNodeIdType */
254 /* inline void setPositionUpdateNodeIdType */
257 Get the nodeId and its size, accounting for nodeId presence
260 The IP version (AF_INET or AF_INET6)
262 A pointer to the OLSR message
264 A pointer to the location where a pointer to the nodeId (as contained in the
265 olsrMessage) can be stored
267 A pointer to the location where the number of bytes in the nodeId can be
270 void getPositionUpdateNodeId(int ipVersion, union olsr_message * olsrMessage,
271 unsigned char ** nodeId, unsigned int * nodeIdSize) {
272 PudOlsrPositionUpdate * olsrGpsMessage = getOlsrMessagePayload(ipVersion,
275 *nodeId = &olsrGpsMessage->nodeInfo.nodeId;
277 switch (getPositionUpdateNodeIdType(ipVersion, olsrGpsMessage)) {
278 case PUD_NODEIDTYPE_MAC: /* hardware address */
279 *nodeIdSize = PUD_NODEIDTYPE_MAC_BYTES;
282 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
283 *nodeIdSize = PUD_NODEIDTYPE_MSISDN_BYTES;
286 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
287 *nodeIdSize = PUD_NODEIDTYPE_TETRA_BYTES;
290 case PUD_NODEIDTYPE_DNS: /* DNS name */
291 *nodeIdSize = strlen((char *) *nodeId);
292 /* FIXME for no '\0' at the end, need to scan from the end until
293 * encountering a non-zero byte: end of string address and
294 * subtract the string start address */
297 case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
298 *nodeIdSize = PUD_NODEIDTYPE_MMSI_BYTES;
301 case PUD_NODEIDTYPE_URN: /* a URN number */
302 *nodeIdSize = PUD_NODEIDTYPE_URN_BYTES;
305 case PUD_NODEIDTYPE_192:
306 *nodeIdSize = PUD_NODEIDTYPE_192_BYTES;
309 case PUD_NODEIDTYPE_193:
310 *nodeIdSize = PUD_NODEIDTYPE_193_BYTES;
313 case PUD_NODEIDTYPE_194:
314 *nodeIdSize = PUD_NODEIDTYPE_194_BYTES;
317 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
318 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
319 default: /* unsupported */
321 *nodeId = (unsigned char *) getOlsrMessageOriginator(ipVersion,
324 (ipVersion == AF_INET) ?
325 PUD_NODEIDTYPE_IPV4_BYTES : PUD_NODEIDTYPE_IPV6_BYTES;
334 Convert the node information to the node information for an OLSR message and
335 put it in the PUD message in the OLSR message. Also updates the PUD message
339 The IP version (AF_INET or AF_INET6)
340 @param olsrGpsMessage
341 A pointer to the PUD message in the OLSR message
342 @param olsrMessageSize
343 The maximum number of bytes available for the olsrMessage
347 The (configured) nodeId
349 The number of bytes in the nodeId
352 The number of bytes written in the PUD message in the OLSR message (for ALL
353 the node information)
355 size_t setPositionUpdateNodeInfo(int ipVersion,
356 PudOlsrPositionUpdate * olsrGpsMessage, unsigned int olsrMessageSize,
357 NodeIdType nodeIdType, unsigned char * nodeId, size_t nodeIdLength) {
358 unsigned char * buffer;
359 unsigned int length = 0;
361 setPositionUpdateNodeIdType(olsrGpsMessage, nodeIdType);
362 switch (nodeIdType) {
363 case PUD_NODEIDTYPE_MAC: /* hardware address */
364 length = nodeIdLength;
365 setPositionUpdateNodeId(olsrGpsMessage, nodeId, nodeIdLength, false);
368 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
369 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
370 case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
371 case PUD_NODEIDTYPE_URN: /* a URN number */
372 case PUD_NODEIDTYPE_192:
373 case PUD_NODEIDTYPE_193:
374 case PUD_NODEIDTYPE_194:
375 buffer = &cachedNodeIdBuffer[0];
376 length = cachedNodeIdBufferLength;
377 setPositionUpdateNodeId(olsrGpsMessage, buffer, length, false);
380 case PUD_NODEIDTYPE_DNS: /* DNS name */
382 long charsAvailable = olsrMessageSize
383 - (PUD_OLSRWIREFORMATSIZE + sizeof(NodeInfo)
384 - sizeof(olsrGpsMessage->nodeInfo.nodeId)) - 1;
386 length = nodeIdLength + 1;
387 if (unlikely((long) length > charsAvailable)) {
388 length = charsAvailable;
391 setPositionUpdateNodeId(olsrGpsMessage, nodeId, length, true);
395 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
396 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
397 /* explicit return: no nodeId information in message */
400 default: /* unsupported */
401 /* fallback to IP address */
402 setPositionUpdateNodeIdType(olsrGpsMessage,
403 (ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 :
404 PUD_NODEIDTYPE_IPV6);
406 /* explicit return: no nodeId information in message */
410 setPositionUpdateFlags(olsrGpsMessage,
411 getPositionUpdateFlags(olsrGpsMessage) | PUD_FLAGS_ID);
412 return ((sizeof(NodeInfo)
413 - (sizeof(olsrGpsMessage->nodeInfo.nodeId) /* nodeId placeholder */))