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 Setup a nodeId number in the cachedNodeIdBuffer.
46 The value to setup in the cache
48 The number of bytes used by the number in the wire format
51 - true when the number is valid
54 bool setupNodeIdNumberForOlsrCache(unsigned long long val, unsigned int bytes) {
57 if (bytes > PUD_CACHED_NODEID_BUFFER_SIZE) {
62 cachedNodeIdBuffer[i] = val & 0xff;
69 cachedNodeIdBufferLength = bytes;
74 Setup a nodeId buffer in the cachedNodeIdBuffer.
77 The value to setup in the cache
79 The number of bytes used by the number in the wire format
82 - true when the number is valid
85 bool setupNodeIdBinaryBufferForOlsrCache(void * val, size_t bytes) {
86 if (bytes >= PUD_CACHED_NODEID_BUFFER_SIZE) {
90 memcpy(cachedNodeIdBuffer, val, bytes);
91 cachedNodeIdBufferLength = bytes;
95 /* ************************************************************************
97 * ************************************************************************ */
99 /* inline getValidityTime */
102 Set the validity time of the position update message
104 @param validityTimeField
105 A pointer to the validity time field
107 The validity time in seconds
109 void setValidityTime(uint8_t * validityTimeField,
110 unsigned long long validityTime) {
111 unsigned int msn = 1;
112 unsigned long long lsn = 0;
113 unsigned long long upperBound;
115 if (!cachedValidityTimeMsnValid) {
116 setupCachedValidityTimeMsn();
118 upperBound = cachedValidityTimeMsn[msn];
119 while ((msn < 16) && (validityTime >= upperBound)) {
121 upperBound = cachedValidityTimeMsn[msn];
125 if (unlikely(validityTime >= upperBound)) {
128 unsigned long lowerBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
129 unsigned long resolution = (1 << msn);
130 lsn = ((validityTime - lowerBound + (resolution >> 1)) / resolution);
136 *validityTimeField = ((msn << 4) | lsn);
139 /* ************************************************************************
140 * UplinkPositionUpdate
141 * ************************************************************************ */
143 /* inline uint8_t getUplinkMessageType */
144 /* inline void setUplinkMessageType */
146 /* inline uint16_t getUplinkMessageLength */
147 /* inline void setUplinkMessageLength */
149 /* inline bool getUplinkMessageIPv6 */
150 /* inline void setUplinkMessageIPv6 */
152 /* inline void setUplinkMessagePadding */
154 /* ************************************************************************
156 * ************************************************************************ */
158 /* inline union olsr_ip_addr * getOlsrMessageOriginator */
160 /* inline PudOlsrPositionUpdate * getOlsrMessagePayload */
162 /* ************************************************************************
163 * PudOlsrPositionUpdate
164 * ************************************************************************ */
166 /* inline uint8_t getPositionUpdateVersion */
167 /* inline void setPositionUpdateVersion */
169 /* inline uint8_t getPositionUpdateSmask */
170 /* inline void setPositionUpdateSmask */
172 /* ************************************************************************
174 * ************************************************************************ */
176 /* inline void setPositionUpdateTime */
179 Convert the time of an OLSR message (the number of seconds after midnight) to
180 a time structure, based on midnight of the current day.
182 @param olsrGpsMessage
183 A pointer to the position update message
185 The base date from which to determine the time (number of seconds since Epoch,
188 A pointer to the time structure into which to put the converted time
190 void getPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
191 time_t baseDate, struct tm *nowStruct) {
192 uint32_t olsrTime = olsrGpsMessage->gpsInfo.time;
195 time_t now = baseDate;
196 gmtime_r(&now, nowStruct);
198 secNow = ((nowStruct->tm_hour * 60 * 60) + (nowStruct->tm_min * 60)
199 + nowStruct->tm_sec);
201 if (secNow <= (12 * 60 * 60)) {
202 /* we are now in the first 12h of the day */
203 if (unlikely(olsrTime > (secNow + (12 * 60 * 60)))) {
204 /* the message was sent more than 12h later in time:
205 the message was sent yesterday: adjust the date by -1 day */
206 now -= (24 * 60 * 60);
207 gmtime_r(&now, nowStruct);
210 /* we are now in the last 12h of the day */
211 if (unlikely(olsrTime < (secNow - (12 * 60 * 60)))) {
212 /* the message was sent more than 12h earlier in time:
213 the message was sent tomorrow: adjust the date by +1 day */
214 now += (24 * 60 * 60);
215 gmtime_r(&now, nowStruct);
219 nowStruct->tm_hour = ((olsrTime % (24 * 60 * 60)) / 3600);
220 nowStruct->tm_min = ((olsrTime % (60 * 60)) / 60);
221 nowStruct->tm_sec = (olsrTime % 60);
224 /* inline double getPositionUpdateLatitude */
225 /* inline void setPositionUpdateLatitude */
227 /* inline double getPositionUpdateLongitude */
228 /* inline void setPositionUpdateLongitude */
230 /* inline long getPositionUpdateAltitude */
231 /* inline void setPositionUpdateAltitude */
233 /* inline unsigned long getPositionUpdateSpeed */
234 /* inline void setPositionUpdateSpeed */
236 /* inline unsigned long getPositionUpdateTrack */
237 /* inline void setPositionUpdateTrack */
239 /* inline double getPositionUpdateHdop */
240 /* inline void setPositionUpdateHdop */
242 /* ************************************************************************
244 * ************************************************************************ */
246 /* inline NodeIdType getPositionUpdateNodeIdType */
247 /* inline void setPositionUpdateNodeIdType */
250 Get the nodeId and its size, accounting for nodeId presence
253 The IP version (AF_INET or AF_INET6)
255 A pointer to the OLSR message
257 A pointer to the location where a pointer to the nodeId (as contained in the
258 olsrMessage) can be stored
260 A pointer to the location where the number of bytes in the nodeId can be
263 void getPositionUpdateNodeId(int ipVersion, union olsr_message * olsrMessage,
264 unsigned char ** nodeId, unsigned int * nodeIdSize) {
265 PudOlsrPositionUpdate * olsrGpsMessage = getOlsrMessagePayload(ipVersion,
268 *nodeId = &olsrGpsMessage->nodeInfo.nodeId;
270 switch (getPositionUpdateNodeIdType(ipVersion, olsrGpsMessage)) {
271 case PUD_NODEIDTYPE_MAC: /* hardware address */
272 *nodeIdSize = PUD_NODEIDTYPE_MAC_BYTES;
275 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
276 *nodeIdSize = PUD_NODEIDTYPE_MSISDN_BYTES;
279 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
280 *nodeIdSize = PUD_NODEIDTYPE_TETRA_BYTES;
283 case PUD_NODEIDTYPE_DNS: /* DNS name */
284 *nodeIdSize = strlen((char *) *nodeId);
285 /* FIXME for no '\0' at the end, need to scan from the end until
286 * encountering a non-zero byte: end of string address and
287 * subtract the string start address */
290 case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
291 *nodeIdSize = PUD_NODEIDTYPE_MMSI_BYTES;
294 case PUD_NODEIDTYPE_URN: /* a URN number */
295 *nodeIdSize = PUD_NODEIDTYPE_URN_BYTES;
298 case PUD_NODEIDTYPE_192:
299 *nodeIdSize = PUD_NODEIDTYPE_192_BYTES;
302 case PUD_NODEIDTYPE_193:
303 *nodeIdSize = PUD_NODEIDTYPE_193_BYTES;
306 case PUD_NODEIDTYPE_194:
307 *nodeIdSize = PUD_NODEIDTYPE_194_BYTES;
310 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
311 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
312 default: /* unsupported */
314 *nodeId = (unsigned char *) getOlsrMessageOriginator(ipVersion,
317 (ipVersion == AF_INET) ?
318 PUD_NODEIDTYPE_IPV4_BYTES : PUD_NODEIDTYPE_IPV6_BYTES;
327 Convert the node information to the node information for an OLSR message and
328 put it in the PUD message in the OLSR message. Also updates the PUD message
332 The IP version (AF_INET or AF_INET6)
333 @param olsrGpsMessage
334 A pointer to the PUD message in the OLSR message
335 @param olsrMessageSize
336 The maximum number of bytes available for the olsrMessage
340 The (configured) nodeId
342 The number of bytes in the nodeId
345 The number of bytes written in the PUD message in the OLSR message (for ALL
346 the node information)
348 size_t setPositionUpdateNodeInfo(int ipVersion,
349 PudOlsrPositionUpdate * olsrGpsMessage, unsigned int olsrMessageSize,
350 NodeIdType nodeIdType, unsigned char * nodeId, size_t nodeIdLength) {
351 unsigned char * buffer;
352 unsigned int length = 0;
354 setPositionUpdateNodeIdType(olsrGpsMessage, nodeIdType);
355 switch (nodeIdType) {
356 case PUD_NODEIDTYPE_MAC: /* hardware address */
357 length = nodeIdLength;
358 setPositionUpdateNodeId(olsrGpsMessage, nodeId, nodeIdLength, false);
361 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
362 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
363 case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
364 case PUD_NODEIDTYPE_URN: /* a URN number */
365 case PUD_NODEIDTYPE_192:
366 case PUD_NODEIDTYPE_193:
367 case PUD_NODEIDTYPE_194:
368 buffer = &cachedNodeIdBuffer[0];
369 length = cachedNodeIdBufferLength;
370 setPositionUpdateNodeId(olsrGpsMessage, buffer, length, false);
373 case PUD_NODEIDTYPE_DNS: /* DNS name */
375 long charsAvailable = olsrMessageSize
376 - (PUD_OLSRWIREFORMATSIZE + sizeof(NodeInfo)
377 - sizeof(olsrGpsMessage->nodeInfo.nodeId)) - 1;
379 length = nodeIdLength + 1;
380 if (unlikely((long) length > charsAvailable)) {
381 length = charsAvailable;
384 setPositionUpdateNodeId(olsrGpsMessage, nodeId, length, true);
388 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
389 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
390 /* explicit return: no nodeId information in message */
393 default: /* unsupported */
394 /* fallback to IP address */
395 setPositionUpdateNodeIdType(olsrGpsMessage,
396 (ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 :
397 PUD_NODEIDTYPE_IPV6);
399 /* explicit return: no nodeId information in message */
403 setPositionUpdateFlags(olsrGpsMessage,
404 getPositionUpdateFlags(olsrGpsMessage) | PUD_FLAGS_ID);
405 return ((sizeof(NodeInfo)
406 - (sizeof(olsrGpsMessage->nodeInfo.nodeId) /* nodeId placeholder */))