PUD: fix snprintf length confusion
[olsrd.git] / lib / pud / wireformat / include / OlsrdPudWireFormat / wireFormat.h
1 #ifndef _PUD_WIREFORMAT_H_
2 #define _PUD_WIREFORMAT_H_
3
4 #include "olsr_types.h"
5 #include "olsr_protocol.h"
6
7 #include <stddef.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <netinet/in.h>
11 #include <sys/socket.h>
12 #include <math.h>
13 #include <string.h>
14 #include <assert.h>
15 #include <OlsrdPudWireFormat/compiler.h>
16
17 /*
18  * Version
19  */
20
21 /** The version of the wire format */
22 #define PUD_WIRE_FORMAT_VERSION         2
23
24 /*
25  * Flags
26  */
27
28 /** Flags that the GPS information contains the nodeId */
29 #define PUD_FLAGS_ID                            0x80
30
31 /** Flags that the GPS information is originating from a gateway */
32 #define PUD_FLAGS_GATEWAY                       0x40
33
34 /*
35  * Time
36  */
37
38 /** The number of bits for the time field */
39 #define PUD_TIME_BITS                           17
40
41 /*
42  * Latitude
43  */
44
45 /** The number of bits for the latitude field */
46 #define PUD_LATITUDE_BITS                       28
47
48 /** The maximum size of the string representation of the latitude
49  * sign [0,90] [0,59] dot [0,59] [0,999] (including \0) */
50 #define PUD_TX_LATITUDE_DIGITS          (1 + 2 + 2 + 1 + 2 + 3 + 1)
51
52 /** The number of decimals of the latitude in the transmit sentence */
53 #define PUD_TX_LATITUDE_DECIMALS        "5"
54
55 /*
56  * Longitude
57  */
58
59 /** The number of bits for the longitude field */
60 #define PUD_LONGITUDE_BITS                      27
61
62 /** The maximum size of the string representation of the longitude
63  * sign [0,180] [0,59] dot [0,59] [0,999] (including \0) */
64 #define PUD_TX_LONGITUDE_DIGITS         (1 + 3 + 2 + 1 + 2 + 3 + 1)
65
66 /** The number of decimals of the longitude in the transmit sentence */
67 #define PUD_TX_LONGITUDE_DECIMALS       "5"
68
69 /*
70  * Altitude
71  */
72
73 /** The number of bits for the altitude field */
74 #define PUD_ALTITUDE_BITS                       16
75
76 /** The minimum altitude */
77 #define PUD_ALTITUDE_MIN                        (-400)
78
79 /** The maximum altitude */
80 #define PUD_ALTITUDE_MAX        (((1 << PUD_ALTITUDE_BITS) - 1) + PUD_ALTITUDE_MIN)
81
82 /** The maximum size of the string representation of the altitude (including \0) */
83 #define PUD_TX_ALTITUDE_DIGITS          (6 + 1)
84
85 /*
86  * Speed
87  */
88
89 /** The number of bits for the speed field */
90 #define PUD_SPEED_BITS                          12
91
92 /** The maximum speed value */
93 #define PUD_SPEED_MAX                           ((1 << PUD_SPEED_BITS) - 1)
94
95 /** The maximum size of the string representation of the speed (including \0) */
96 #define PUD_TX_SPEED_DIGITS                     (4 + 1)
97
98 /*
99  * Track
100  */
101
102 /** The number of bits for the track angle field */
103 #define PUD_TRACK_BITS                          9
104
105 /** The maximum size of the string representation of the track angle (including \0) */
106 #define PUD_TX_TRACK_DIGITS                     (3 + 1)
107
108 /*
109  * HDOP
110  */
111
112 /** The number of bits for the HDOP field */
113 #define PUD_HDOP_BITS                           11
114
115 /** The HDOP resolution (in m) */
116 #define PUD_HDOP_RESOLUTION                     (0.1)
117
118 /** The maximum HDOP value (in m) */
119 #define PUD_HDOP_MAX            (((1 << PUD_HDOP_BITS) - 1) * PUD_HDOP_RESOLUTION)
120
121 /** The maximum size of the string representation of the HDOP (including \0) */
122 #define PUD_TX_HDOP_DIGITS                      (5 + 1)
123
124 /** The number of decimals of the HDOP in the transmit sentence */
125 #define PUD_TX_HDOP_DECIMALS            "3"
126
127 /*
128  * Node ID Type
129  */
130
131 /** nodeIdType legal values */
132 typedef enum _NodeIdType {
133         /** the first id of the globally unique node type IDs */
134         PUD_NODEIDTYPE_GLOBAL_FIRST = 0,
135
136         /** MAC address, 48 bits, 6 bytes */
137         PUD_NODEIDTYPE_MAC = 0,
138
139         /** MSISDN number, 15 digits, 50 bits, 7 bytes */
140         PUD_NODEIDTYPE_MSISDN = 1,
141
142         /** TETRA number, 17 digits, 57 bits, 8 bytes */
143         PUD_NODEIDTYPE_TETRA = 2,
144
145         /** DNS name, variable length */
146         PUD_NODEIDTYPE_DNS = 3,
147
148         /** IPv4 address, 32 bits, 4 bytes */
149         PUD_NODEIDTYPE_IPV4 = 4,
150
151         /** gap 1 */
152         PUD_NODEIDTYPE_GAP1 = 5,
153
154         /** IPv6 address, 128 bits, 16 bytes */
155         PUD_NODEIDTYPE_IPV6 = 6,
156
157         /** AIS MMSI number, 9 digits, 30 bits, 4 bytes */
158         PUD_NODEIDTYPE_MMSI = 7,
159
160         /** URN number, 24 bits, 3 bytes */
161         PUD_NODEIDTYPE_URN = 8,
162
163         /** the last id of the globally unique node type IDs */
164         PUD_NODEIDTYPE_GLOBAL_LAST = PUD_NODEIDTYPE_URN,
165
166         /** the first id of the locally unique node type IDs */
167         PUD_NODEIDTYPE_LOCAL_FIRST = 192,
168
169         /** Brandweer number, 7 digits, 24 bits, 3 bytes */
170         PUD_NODEIDTYPE_192 = 192,
171
172         /** Ambulance number, 6 digits, 20 bits, 3 bytes */
173         PUD_NODEIDTYPE_193 = 193,
174
175         /** Number in the range [1, 8191], 4 digits, 13 bits, 2 bytes */
176         PUD_NODEIDTYPE_194 = 194,
177
178         /** the last id of the locally unique node type IDs */
179         PUD_NODEIDTYPE_LOCAL_LAST = PUD_NODEIDTYPE_194
180 } NodeIdType;
181
182 /** the number of nodeId bytes for PUD_NODEIDTYPE_MAC (IFHWADDRLEN) */
183 #define PUD_NODEIDTYPE_MAC_BYTES                6
184
185 /** the number of nodeId bytes for PUD_NODEIDTYPE_MSISDN */
186 #define PUD_NODEIDTYPE_MSISDN_BYTES             7
187 #define PUD_NODEIDTYPE_MSISDN_MIN               0LL
188 #define PUD_NODEIDTYPE_MSISDN_MAX               999999999999999LL
189
190 /** the number of nodeId bytes for PUD_NODEIDTYPE_TETRA */
191 #define PUD_NODEIDTYPE_TETRA_BYTES              8
192 #define PUD_NODEIDTYPE_TETRA_MIN                0LL
193 #define PUD_NODEIDTYPE_TETRA_MAX                99999999999999999LL
194
195 /** the number of nodeId bytes for PUD_NODEIDTYPE_MMSI */
196 #define PUD_NODEIDTYPE_MMSI_BYTES               4
197 #define PUD_NODEIDTYPE_MMSI_MIN                 0LL
198 #define PUD_NODEIDTYPE_MMSI_MAX                 999999999LL
199
200 /** the number of nodeId bytes for PUD_NODEIDTYPE_URN */
201 #define PUD_NODEIDTYPE_URN_BYTES                3
202 #define PUD_NODEIDTYPE_URN_MIN                  0LL
203 #define PUD_NODEIDTYPE_URN_MAX                  16777215LL
204
205 /** the number of nodeId bytes for PUD_NODEIDTYPE_192 */
206 #define PUD_NODEIDTYPE_192_BYTES                3
207 #define PUD_NODEIDTYPE_192_MIN                  0LL
208 #define PUD_NODEIDTYPE_192_MAX                  9999999LL
209
210 /** the number of nodeId bytes for PUD_NODEIDTYPE_193 */
211 #define PUD_NODEIDTYPE_193_BYTES                3
212 #define PUD_NODEIDTYPE_193_MIN                  0LL
213 #define PUD_NODEIDTYPE_193_MAX                  999999LL
214
215 /** the number of nodeId bytes for PUD_NODEIDTYPE_194 */
216 #define PUD_NODEIDTYPE_194_BYTES                2
217 #define PUD_NODEIDTYPE_194_MIN                  1LL
218 #define PUD_NODEIDTYPE_194_MAX                  8191LL
219
220 /** the number of nodeId bytes for PUD_NODEIDTYPE_IPV4 (sizeof(struct in_addr)) */
221 #define PUD_NODEIDTYPE_IPV4_BYTES               4
222
223 /** the number of nodeId bytes for PUD_NODEIDTYPE_IPV6 (sizeof(struct in6_addr)) */
224 #define PUD_NODEIDTYPE_IPV6_BYTES               16
225
226 /** The maximum size of the string representation of the nodeIdType (including \0) */
227 #define PUD_TX_NODEIDTYPE_DIGITS                (3 + 1)
228
229 /*
230  * Node ID
231  */
232
233 /** The maximum size of the string representation of the nodeId (including \0) */
234 #define PUD_TX_NODEID_BUFFERSIZE                1024
235
236 /**
237  The type that is used to store the nodeId as a binary representation along
238  with its length and setup status
239  */
240 typedef struct _nodeIdBinaryType {
241                 bool set;
242                 size_t length;
243                 union _buffer {
244                                 unsigned char mac[PUD_NODEIDTYPE_MAC_BYTES];
245                                 union olsr_ip_addr ip;
246                                 unsigned long long longValue;
247                                 unsigned char stringValue[PUD_TX_NODEID_BUFFERSIZE];
248                 } buffer;
249 } nodeIdBinaryType;
250
251 /*
252  * Wire Format Structures
253  */
254
255 /** Sub-format GPS information, 120 bits = 15 bytes */
256 typedef struct _GpsInfo {
257         uint32_t time :PUD_TIME_BITS; /**< the number of seconds since midnight, ALWAYS present */
258         uint32_t lat :PUD_LATITUDE_BITS; /**< latitude */
259         uint32_t lon :PUD_LONGITUDE_BITS; /**< longitude */
260         uint32_t alt :PUD_ALTITUDE_BITS; /**< altitude */
261         uint32_t speed :PUD_SPEED_BITS; /**< speed */
262         uint32_t track :PUD_TRACK_BITS; /**< track angle */
263         uint32_t hdop :PUD_HDOP_BITS; /**< HDOP */
264 }__attribute__((__packed__)) GpsInfo;
265
266 /** Sub-format Node information, 8 + variable bits = 1 + variable bytes */
267 typedef struct _NodeInfo {
268         uint8_t nodeIdType; /**< the nodeIdType */
269         unsigned char nodeId; /**< placeholder for variable length nodeId string */
270 }__attribute__((__packed__)) NodeInfo;
271
272 /** Complete format, 8+8+8+120+(8+variable) bits =  18+(1+variable) bytes*/
273 typedef struct _PudOlsrPositionUpdate {
274         uint8_t version; /**< the version of the sentence */
275         uint8_t validityTime; /**< the validity time of the sentence */
276         uint8_t smask; /**< mask signaling the contents of the sentence */
277         uint8_t flags; /**< mask signaling extra contents of the sentence */
278         GpsInfo gpsInfo; /**< the GPS information (MANDATORY) */
279         NodeInfo nodeInfo; /**< placeholder for node information (OPTIONAL) */
280 }__attribute__((__packed__)) PudOlsrPositionUpdate;
281
282 /** The size of the wire format, minus the size of the node information */
283 #define PUD_OLSRWIREFORMATSIZE (sizeof(PudOlsrPositionUpdate) - sizeof(NodeInfo))
284
285 /*
286  * Uplink
287  */
288
289 /** the types of the uplink messages */
290 typedef enum _UplinkMessageType {
291         POSITION = 0,
292         CLUSTERLEADER = 1
293 } UplinkMessageType;
294
295 /** cluster leader message, 10 bytes (IPv4), 34 bytes (IPv6) */
296 typedef struct _UplinkClusterLeader {
297         uint8_t version; /**< the version of the message */
298         uint8_t validityTime; /**< the validity time of the sentence */
299         union _leader {
300                 struct _v4 {
301                         struct in_addr originator;
302                         struct in_addr clusterLeader;
303                 } v4;
304                 struct _v6 {
305                         struct in6_addr originator;
306                         struct in6_addr clusterLeader;
307                 } v6;
308         } leader;
309 }__attribute__((__packed__)) UplinkClusterLeader;
310
311 /** TLV header for uplink messages, 4 bytes */
312 typedef struct _UplinkHeader {
313         uint8_t type; /**< stores a UplinkMessageType */
314         uint16_t length; /**< the length of the payload in txBuffer */
315         uint8_t ipv6 :1; /**< clear when IPv4, set when IPv6 */
316         uint8_t pad :7; /**< padding to align to 4 bytes */
317 }__attribute__((__packed__)) UplinkHeader;
318
319 /** uplink message */
320 typedef struct _UplinkMessage {
321         UplinkHeader header; /**< the uplink TLV header */
322         union _msg {
323                 /** an olsr message (position update) */
324                 union olsr_message olsrMessage;
325
326                 /** a cluster leader message */
327                 UplinkClusterLeader clusterLeader;
328         } msg;
329 }__attribute__((__packed__)) UplinkMessage;
330
331 /* ************************************************************************
332  * FUNCTIONS
333  * ************************************************************************ */
334
335 /*
336  * NodeIdType
337  */
338
339 static inline bool isValidNodeIdType(unsigned long long nodeIdType) {
340         return
341         (
342                 (
343                         (/* (nodeIdType >= PUD_NODEIDTYPE_GLOBAL_FIRST) && */ (nodeIdType <= PUD_NODEIDTYPE_GLOBAL_LAST)) ||
344                         (   (nodeIdType >= PUD_NODEIDTYPE_LOCAL_FIRST ) &&    (nodeIdType <= PUD_NODEIDTYPE_LOCAL_LAST ))
345                 )
346                 &&
347                 (
348                         (nodeIdType != PUD_NODEIDTYPE_GAP1)
349                 )
350         );
351 }
352
353 /*
354  * Validity Time
355  */
356
357 /** Determine the validity time in seconds from the OLSR wire format value */
358 #define PUD_VALIDITY_TIME_FROM_OLSR(msn, lsn) ((((lsn) + 16) * (1 << (msn))) - 16)
359
360 /**
361  Get the validity time from a message
362
363  @param validityTimeField
364  A pointer to the validity time field
365
366  @return
367  The validity time in seconds
368  */
369 static inline unsigned long getValidityTime(uint8_t * validityTimeField) {
370         return PUD_VALIDITY_TIME_FROM_OLSR(*validityTimeField >> 4, *validityTimeField % 16);
371 }
372
373 void setValidityTime(uint8_t * validityTimeField,
374                 unsigned long long validityTime);
375
376 /*
377  * UplinkHeader
378  */
379
380 /**
381  Get the type of the uplink message
382
383  @param uplinkHeader
384  A pointer to the uplink message
385  @return
386  The type of the uplink message
387  */
388 static inline uint8_t getUplinkMessageType(UplinkHeader * uplinkHeader) {
389         return uplinkHeader->type;
390 }
391
392 /**
393  Set the type of the uplink message
394
395  @param uplinkHeader
396  A pointer to the uplink message
397  @param type
398  The type of the uplink message
399  */
400 static inline void setUplinkMessageType(UplinkHeader * uplinkHeader,
401                 uint8_t type) {
402         uplinkHeader->type = type;
403 }
404
405 /**
406  Get the length of the uplink message
407
408  @param uplinkHeader
409  A pointer to the uplink message
410  @return
411  The length of the uplink message
412  */
413 static inline uint16_t getUplinkMessageLength(UplinkHeader * uplinkHeader) {
414         return ntohs(uplinkHeader->length);
415 }
416
417 /**
418  Set the length of the uplink message
419
420  @param uplinkHeader
421  A pointer to the uplink message
422  @param length
423  The length of the uplink message
424  */
425 static inline void setUplinkMessageLength(UplinkHeader * uplinkHeader,
426                 uint16_t length) {
427         uplinkHeader->length = ntohs(length);
428 }
429
430 /**
431  Get the IPv6 status of the uplink message
432
433  @param uplinkHeader
434  A pointer to the uplink message
435  @return
436  true when the uplink message is sent from an olsrd stack in IPv6 mode, false
437  otherwise
438  */
439 static inline bool getUplinkMessageIPv6(UplinkHeader * uplinkHeader) {
440         return (uplinkHeader->ipv6 == 1);
441 }
442
443 /**
444  Set the IPv6 status of the uplink message
445
446  @param uplinkHeader
447  A pointer to the uplink message
448  @param ipv6
449  The IPv6 status of the uplink message (true when the uplink message is sent
450  from olsrd stack in IPv6 mode, false otherwise)
451  */
452 static inline void setUplinkMessageIPv6(UplinkHeader * uplinkHeader,
453                 bool ipv6) {
454         uplinkHeader->ipv6 = ipv6 ? 1 : 0;
455 }
456
457 /**
458  Set the padding of the uplink message header
459
460  @param uplinkHeader
461  A pointer to the uplink message
462  @param pad
463  The padding of the uplink message header
464  */
465 static inline void setUplinkMessagePadding(UplinkHeader * uplinkHeader,
466                 uint8_t pad) {
467         uplinkHeader->pad = pad;
468 }
469
470 /*
471  * OLSR header
472  */
473
474
475 /**
476  Determine the size of an OLSR message
477
478  @param ipVersion
479  The IP version
480  @param olsrMessage
481  A pointer to the OLSR message
482  @return
483  The size of the OLSR message
484  */
485 static inline unsigned short getOlsrMessageSize(int ipVersion,
486                 union olsr_message * olsrMessage) {
487         if (ipVersion == AF_INET) {
488                 return ntohs(olsrMessage->v4.olsr_msgsize);
489         }
490
491         return ntohs(olsrMessage->v6.olsr_msgsize);
492 }
493
494 /**
495  Get the originator of an OLSR message
496
497  @param ipVersion
498  The IP version (AF_INET or AF_INET6)
499  @param olsrMessage
500  A pointer to the OLSR message
501  @return
502  A pointer to the originator address
503  */
504 static inline union olsr_ip_addr * getOlsrMessageOriginator(int ipVersion,
505                 union olsr_message * olsrMessage) {
506         if (ipVersion == AF_INET) {
507                 return (union olsr_ip_addr *) &olsrMessage->v4.originator;
508         }
509
510         return (union olsr_ip_addr *) &olsrMessage->v6.originator;
511 }
512
513 /**
514  Get the position update message in an OLSR message
515
516  @param ipVersion
517  The IP version (AF_INET or AF_INET6)
518  @param olsrMessage
519  A pointer to the OLSR message
520  @return
521  A pointer to the position update message
522  */
523 static inline PudOlsrPositionUpdate * getOlsrMessagePayload(int ipVersion,
524                 union olsr_message * olsrMessage) {
525         if (ipVersion == AF_INET) {
526                 return (PudOlsrPositionUpdate *) &olsrMessage->v4.message;
527         }
528
529         return (PudOlsrPositionUpdate *) &olsrMessage->v6.message;
530 }
531
532 /*
533  * PudOlsrPositionUpdate
534  */
535
536 /**
537  Get the version of the position update message
538
539  @param olsrGpsMessage
540  A pointer to the position update message
541  @return
542  The version of the position update message
543  */
544 static inline uint8_t getPositionUpdateVersion(
545                 PudOlsrPositionUpdate * olsrGpsMessage) {
546         return olsrGpsMessage->version;
547 }
548
549 /**
550  Set the version of the position update message
551
552  @param olsrGpsMessage
553  A pointer to the position update message
554  @param version
555  The version of the position update message
556  */
557 static inline void setPositionUpdateVersion(
558                 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t version) {
559         olsrGpsMessage->version = version;
560 }
561
562 /**
563  Get the smask of the position update message
564
565  @param olsrGpsMessage
566  A pointer to the position update message
567  @return
568  The smask of the position update message
569  */
570 static inline uint8_t getPositionUpdateSmask(
571                 PudOlsrPositionUpdate * olsrGpsMessage) {
572         return olsrGpsMessage->smask;
573 }
574
575 /**
576  Set the smask of the position update message
577
578  @param olsrGpsMessage
579  A pointer to the position update message
580  @param smask
581  The smask of the position update message
582  */
583 static inline void setPositionUpdateSmask(
584                 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t smask) {
585         olsrGpsMessage->smask = smask;
586 }
587
588 /**
589  Get the flags of the position update message
590
591  @param olsrGpsMessage
592  A pointer to the position update message
593  @return
594  The flags of the position update message
595  */
596 static inline uint8_t getPositionUpdateFlags(
597                 PudOlsrPositionUpdate * olsrGpsMessage) {
598         return olsrGpsMessage->flags;
599 }
600
601 /**
602  Set the flags of the position update message
603
604  @param olsrGpsMessage
605  A pointer to the position update message
606  @param flags
607  The flags of the position update message
608  */
609 static inline void setPositionUpdateFlags(
610                 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t flags) {
611         olsrGpsMessage->flags = flags;
612 }
613
614 /*
615  * GpsInfo
616  */
617
618 void getPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
619                 time_t baseDate, struct tm *nowStruct);
620
621 /**
622  Set the time of the position update message (the number of seconds after
623  midnight)
624
625  @param olsrGpsMessage
626  A pointer to the position update message
627  @param hour
628  The hours
629  @param min
630  The minutes
631  @param sec
632  The seconds
633  */
634 static inline void setPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
635                 int hour, int min, int sec) {
636         olsrGpsMessage->gpsInfo.time = ((hour * 60 * 60) + (min * 60) + sec);
637 }
638
639 /**
640  Get the latitude of the position update message
641
642  @param olsrGpsMessage
643  A pointer to the position update message
644
645  @return
646  The latitude converted to degrees: [-90, 90>
647  */
648 static inline double getPositionUpdateLatitude(
649                 PudOlsrPositionUpdate * olsrGpsMessage) {
650         uint32_t olsrLat = olsrGpsMessage->gpsInfo.lat;
651         double lat = (double) olsrLat;
652
653         /* lat is in [0, 2^LATITUDE_BITS> */
654
655         /* take half of the rounding error */
656         lat += 0.5;
657
658         lat /= (double) (1 << PUD_LATITUDE_BITS);
659         /* lat is now in [0, 1> */
660
661         lat -= 0.5;
662         /* lat is now in [-0.5, 0.5> */
663
664         lat *= 180.0;
665         /* lat is now in [-90, 90> */
666
667         return lat;
668 }
669
670 /**
671  Set the latitude of the position update message
672
673  @param olsrGpsMessage
674  A pointer to the position update message
675  @param latitude
676  The latitude in degrees: [-90, 90]
677  */
678 static inline void setPositionUpdateLatitude(
679                 PudOlsrPositionUpdate * olsrGpsMessage, double latitude) {
680         double lat = latitude;
681
682         /* lat is in [-90, 90] */
683         assert(lat >= -90.0);
684         assert(lat <= 90.0);
685
686         lat /= 180.0;
687         /* lat is now in [-0.5, 0.5] */
688
689         lat += 0.5;
690         /* lat is now in [0, 1] */
691
692         lat *= (double) (1 << PUD_LATITUDE_BITS);
693         /* lat is now in [0, LATITUDE_BITS] */
694
695         /* clip max */
696         if (unlikely(lat > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
697                 lat = (double) ((1 << PUD_LATITUDE_BITS) - 1);
698         }
699         /* lat is now in [0, 2^LATITUDE_BITS> */
700
701         olsrGpsMessage->gpsInfo.lat = lrint(lat);
702 }
703
704 /**
705  Get the longitude of the position update message
706
707  @param olsrGpsMessage
708  A pointer to the position update message
709
710  @return
711  The longitude converted to degrees: [-180, 180>
712  */
713 static inline double getPositionUpdateLongitude(
714                 PudOlsrPositionUpdate * olsrGpsMessage) {
715         uint32_t olsrLon = olsrGpsMessage->gpsInfo.lon;
716         double lon = (double) olsrLon;
717
718         /* lon is in [0, 2^LONGITUDE_BITS> */
719
720         /* take half of the rounding error */
721         lon += 0.5;
722
723         lon /= (1 << PUD_LONGITUDE_BITS);
724         /* lon is now in [0, 1> */
725
726         lon -= 0.5;
727         /* lon is now in [-0.5, 0.5> */
728
729         lon *= 360.0;
730         /* lon is now in [-180, 180> */
731
732         return lon;
733 }
734
735 /**
736  Set the longitude of the position update message
737
738  @param olsrGpsMessage
739  A pointer to the position update message
740  @param longitude
741  The longitude in degrees: [-90, 90]
742  */
743 static inline void setPositionUpdateLongitude(
744                 PudOlsrPositionUpdate * olsrGpsMessage, double longitude) {
745         double lon = longitude;
746
747         /* lon is in [-180, 180] */
748         assert(lon >= -180.0);
749         assert(lon <= 180.0);
750
751         lon /= 360.0;
752         /* lon is now in [-0.5, 0.5] */
753
754         lon += 0.5;
755         /* lon is now in [0, 1] */
756
757         lon *= (double) (1 << PUD_LONGITUDE_BITS);
758         /* lon is now in [0, LONGITUDE_BITS] */
759
760         /* clip max */
761         if (unlikely(lon > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
762                 lon = (double) ((1 << PUD_LATITUDE_BITS) - 1);
763         }
764
765         /* lon is now in [0, 2^LONGITUDE_BITS> */
766
767         olsrGpsMessage->gpsInfo.lon = lrint(lon);
768 }
769
770 /**
771  Get the altitude of the position update message
772
773  @param olsrGpsMessage
774  A pointer to the position update message
775
776  @return
777  The altitude in meters
778  */
779 static inline long getPositionUpdateAltitude(
780                 PudOlsrPositionUpdate * olsrGpsMessage) {
781         return ((long) olsrGpsMessage->gpsInfo.alt + PUD_ALTITUDE_MIN);
782 }
783
784 /**
785  Set the altitude of the position update message
786
787  @param olsrGpsMessage
788  A pointer to the position update message
789  @param altitude
790  The altitude in meters
791  */
792 static inline void setPositionUpdateAltitude(
793                 PudOlsrPositionUpdate * olsrGpsMessage, double altitude) {
794         double alt = altitude;
795
796         if (unlikely(alt > PUD_ALTITUDE_MAX)) {
797                 alt = PUD_ALTITUDE_MAX;
798         } else if (unlikely(alt < PUD_ALTITUDE_MIN)) {
799                 alt = PUD_ALTITUDE_MIN;
800         }
801
802         alt -= PUD_ALTITUDE_MIN;
803
804         olsrGpsMessage->gpsInfo.alt = lrint(alt);
805 }
806
807 /**
808  Get the speed of the position update message
809
810  @param olsrGpsMessage
811  A pointer to the position update message
812
813  @return
814  The speed in kph
815  */
816 static inline unsigned long getPositionUpdateSpeed(
817                 PudOlsrPositionUpdate * olsrGpsMessage) {
818         return olsrGpsMessage->gpsInfo.speed;
819 }
820
821 /**
822  Set the speed of the position update message
823
824  @param olsrGpsMessage
825  A pointer to the position update message
826  @param speed
827  The speed in kph
828  */
829 static inline void setPositionUpdateSpeed(
830                 PudOlsrPositionUpdate * olsrGpsMessage, double speed) {
831         double spd = speed;
832
833         if (unlikely(speed < 0)) {
834                 spd = 0;
835         } else if (unlikely(speed > PUD_SPEED_MAX)) {
836                 spd = PUD_SPEED_MAX;
837         }
838
839         olsrGpsMessage->gpsInfo.speed = lrint(spd);
840 }
841
842 /**
843  Get the track angle of the position update message
844
845  @param olsrGpsMessage
846  A pointer to the position update message
847
848  @return
849  The track angle in degrees
850  */
851 static inline unsigned long getPositionUpdateTrack(
852                 PudOlsrPositionUpdate * olsrGpsMessage) {
853         return olsrGpsMessage->gpsInfo.track;
854 }
855
856 /**
857  Set the track angle of the position update message
858
859  @param olsrGpsMessage
860  A pointer to the position update message
861  @param track
862  The track angle in degrees
863  */
864 static inline void setPositionUpdateTrack(
865                 PudOlsrPositionUpdate * olsrGpsMessage, double track) {
866         olsrGpsMessage->gpsInfo.track = lrint(track);
867 }
868
869 /**
870  Get the HDOP of the position update message
871
872  @param olsrGpsMessage
873  A pointer to the position update message
874
875  @return
876  The HDOP
877  */
878 static inline double getPositionUpdateHdop(
879                 PudOlsrPositionUpdate * olsrGpsMessage) {
880         return (olsrGpsMessage->gpsInfo.hdop * PUD_HDOP_RESOLUTION);
881 }
882
883 /**
884  Set the HDOP of the position update message
885
886  @param olsrGpsMessage
887  A pointer to the position update message
888  @param hdop
889  The HDOP
890  */
891 static inline void setPositionUpdateHdop(PudOlsrPositionUpdate * olsrGpsMessage,
892                 double hdop) {
893         double hdopInternal = hdop;
894
895         if (unlikely(hdopInternal > PUD_HDOP_MAX)) {
896                 hdopInternal = PUD_HDOP_MAX;
897         }
898
899         olsrGpsMessage->gpsInfo.hdop = lrint(hdopInternal / PUD_HDOP_RESOLUTION);
900 }
901
902 /*
903  * NodeInfo
904  */
905
906 /**
907  Get the nodeIdType of the position update message
908
909  @param ipVersion
910  The IP version (AF_INET or AF_INET6)
911  @param olsrGpsMessage
912  A pointer to the position update message
913
914  @return
915  The nodeIdType
916  */
917 static inline NodeIdType getPositionUpdateNodeIdType(int ipVersion,
918                 PudOlsrPositionUpdate * olsrGpsMessage) {
919         if (getPositionUpdateFlags(olsrGpsMessage) & PUD_FLAGS_ID) {
920                 return olsrGpsMessage->nodeInfo.nodeIdType;
921         }
922
923         return ((ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 : PUD_NODEIDTYPE_IPV6);
924 }
925
926 /**
927  Set the nodeIdType of the position update message
928
929  @param olsrGpsMessage
930  A pointer to the position update message
931  @param nodeIdType
932  The nodeIdType
933  */
934 static inline void setPositionUpdateNodeIdType(
935                 PudOlsrPositionUpdate * olsrGpsMessage, NodeIdType nodeIdType) {
936         olsrGpsMessage->nodeInfo.nodeIdType = nodeIdType;
937 }
938
939 void getPositionUpdateNodeId(int ipVersion, union olsr_message * olsrMessage,
940                 unsigned char ** nodeId, unsigned int * nodeIdSize);
941
942 /**
943  Set the nodeId of the position update message
944
945  @param olsrGpsMessage
946  A pointer to the position update message
947  @param nodeId
948  The nodeId
949  @param nodeIdSize
950  The number of bytes in nodeId
951  @param padWithNullByte
952  When true then an extra '\0' byte will be added at the end
953  */
954 static inline void setPositionUpdateNodeId(
955                 PudOlsrPositionUpdate * olsrGpsMessage, unsigned char * nodeId,
956                 unsigned int nodeIdSize, bool padWithNullByte) {
957         memcpy(&olsrGpsMessage->nodeInfo.nodeId, nodeId, nodeIdSize);
958         if (unlikely(padWithNullByte)) {
959                 (&olsrGpsMessage->nodeInfo.nodeId)[nodeIdSize] = '\0';
960         }
961 }
962
963 size_t setPositionUpdateNodeInfo(int ipVersion,
964                 PudOlsrPositionUpdate * olsrGpsMessage, unsigned int olsrMessageSize,
965                 NodeIdType nodeIdType, unsigned char * nodeId, size_t nodeIdLength);
966
967 /*
968  * UplinkClusterLeader
969  */
970
971 /**
972  Get the version of the cluster leader message
973
974  @param clusterLeaderMessage
975  A pointer to the cluster leader message
976  @return
977  The version of the cluster leader message
978  */
979 static inline uint8_t getClusterLeaderVersion(
980                 UplinkClusterLeader * clusterLeaderMessage) {
981         return clusterLeaderMessage->version;
982 }
983
984 /**
985  Set the version of the cluster leader message
986
987  @param clusterLeaderMessage
988  A pointer to the cluster leader message
989  @param version
990  The version of the cluster leader message
991  */
992 static inline void setClusterLeaderVersion(
993                 UplinkClusterLeader * clusterLeaderMessage, uint8_t version) {
994         clusterLeaderMessage->version = version;
995 }
996
997 /**
998  Get the originator of a cluster leader message
999
1000  @param ipVersion
1001  The IP version (AF_INET or AF_INET6)
1002  @param clusterLeaderMessage
1003  A pointer to the cluster leader message
1004  @return
1005  A pointer to the originator address
1006  */
1007 static inline union olsr_ip_addr * getClusterLeaderOriginator(int ipVersion,
1008                 UplinkClusterLeader * clusterLeaderMessage) {
1009         if (ipVersion == AF_INET) {
1010                 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v4.originator;
1011         }
1012
1013         return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v6.originator;
1014 }
1015
1016 /**
1017  Get the cluster leader of a cluster leader message
1018
1019  @param ipVersion
1020  The IP version (AF_INET or AF_INET6)
1021  @param clusterLeaderMessage
1022  A pointer to the cluster leader message
1023  @return
1024  A pointer to the clust leader address
1025  */
1026 static inline union olsr_ip_addr * getClusterLeaderClusterLeader(int ipVersion,
1027                 UplinkClusterLeader * clusterLeaderMessage) {
1028         if (ipVersion == AF_INET) {
1029                 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v4.clusterLeader;
1030         }
1031
1032         return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v6.clusterLeader;
1033 }
1034
1035 #endif /* _PUD_WIREFORMAT_H_ */