MADARA  3.2.3
MessageHeader.cpp
Go to the documentation of this file.
1 
2 #include <algorithm>
3 #include <time.h>
4 #include <sstream>
5 
7 #include "MessageHeader.h"
9 
11 : size (encoded_size ()),
12  type (0), updates (0), quality (0), clock (0),
13  timestamp (utility::get_time ()), ttl (0)
14 {
15  memcpy (madara_id, MADARA_IDENTIFIER, 7);
16  madara_id[7] = 0;
17 
18  originator[0] = 0;
19  domain[0] = 0;
20 }
21 
22 
24 {
25 }
26 
27 uint32_t
29 {
30  return sizeof (uint64_t) * 3 // size, clock, timestamp
33  + sizeof (uint32_t) * 3; // type, updates, quality
34 }
35 
36 uint32_t
38 {
39  return sizeof (uint64_t) * 3 // size, clock, timestamp
42  + sizeof (uint32_t) * 3; // type, updates, quality
43 }
44 
45 const char *
47  int64_t & buffer_remaining)
48 {
49  // Remove size field from the buffer and update accordingly
50  if ((size_t)buffer_remaining >= sizeof (size))
51  {
52  memcpy (&size, buffer, sizeof (size));
54  buffer += sizeof (size);
55  }
56  buffer_remaining -= sizeof (size);
57 
58  // Remove madara_id field from the buffer and update accordingly
59  if ((size_t)buffer_remaining >= sizeof (char) * MADARA_IDENTIFIER_LENGTH)
60  {
61  strncpy (madara_id, buffer, MADARA_IDENTIFIER_LENGTH);
62  buffer += sizeof (char) * MADARA_IDENTIFIER_LENGTH;
63  }
64  else
65  {
66  std::stringstream buffer;
67  buffer << "MessageHeader::read: ";
68  buffer << MADARA_IDENTIFIER_LENGTH << " byte id encoding cannot fit in ";
69  buffer << buffer_remaining << " byte buffer\n";
70 
71  throw exceptions::MemoryException (buffer.str ());
72  }
73 
74 
75  buffer_remaining -= sizeof (char) * MADARA_IDENTIFIER_LENGTH;
76 
77  // Remove domain field from the buffer and update accordingly
78  if ((size_t)buffer_remaining >= sizeof (char) * MADARA_DOMAIN_MAX_LENGTH)
79  {
80  strncpy (domain, buffer, MADARA_DOMAIN_MAX_LENGTH);
81  buffer += sizeof (char) * MADARA_DOMAIN_MAX_LENGTH;
82  }
83  else
84  {
85  std::stringstream buffer;
86  buffer << "MessageHeader::read: ";
87  buffer << MADARA_DOMAIN_MAX_LENGTH << " byte domain encoding cannot";
88  buffer << " fit in ";
89  buffer << buffer_remaining << " byte buffer\n";
90 
91  throw exceptions::MemoryException (buffer.str ());
92  }
93 
94  buffer_remaining -= sizeof (char) * MADARA_DOMAIN_MAX_LENGTH;
95 
96  // Remove originator from the buffer and update accordingly
97  if ((size_t)buffer_remaining >= sizeof (char) * MAX_ORIGINATOR_LENGTH)
98  {
99  strncpy (originator, buffer, MAX_ORIGINATOR_LENGTH);
100  buffer += sizeof (char) * MAX_ORIGINATOR_LENGTH;
101  }
102  else
103  {
104  std::stringstream buffer;
105  buffer << "MessageHeader::read: ";
106  buffer << MAX_ORIGINATOR_LENGTH << " byte originator encoding cannot";
107  buffer << " fit in ";
108  buffer << buffer_remaining << " byte buffer\n";
109 
110  throw exceptions::MemoryException (buffer.str ());
111  }
112  buffer_remaining -= sizeof (char) * MAX_ORIGINATOR_LENGTH;
113 
114  // Remove type field from the buffer and update accordingly
115  if ((size_t)buffer_remaining >= sizeof (type))
116  {
117  memcpy (&type, buffer, sizeof (type));
119  buffer += sizeof (type);
120  }
121  else
122  {
123  std::stringstream buffer;
124  buffer << "MessageHeader::read: ";
125  buffer << sizeof (type) << " byte type encoding cannot";
126  buffer << " fit in ";
127  buffer << buffer_remaining << " byte buffer\n";
128 
129  throw exceptions::MemoryException (buffer.str ());
130  }
131  buffer_remaining -= sizeof (type);
132 
133  // Remove updates field from the buffer and update accordingly
134  if ((size_t)buffer_remaining >= sizeof (updates))
135  {
136  memcpy (&updates, buffer, sizeof (updates));
138  buffer += sizeof (updates);
139  }
140  else
141  {
142  std::stringstream buffer;
143  buffer << "MessageHeader::read: ";
144  buffer << sizeof (updates) << " byte updates encoding cannot";
145  buffer << " fit in ";
146  buffer << buffer_remaining << " byte buffer\n";
147 
148  throw exceptions::MemoryException (buffer.str ());
149  }
150  buffer_remaining -= sizeof (updates);
151 
152  // Remove quality field from the buffer and update accordingly
153  if ((size_t)buffer_remaining >= sizeof (quality))
154  {
155  memcpy (&quality, buffer, sizeof (quality));
157  buffer += sizeof (quality);
158  }
159  else
160  {
161  std::stringstream buffer;
162  buffer << "MessageHeader::read: ";
163  buffer << sizeof (quality) << " byte quality encoding cannot";
164  buffer << " fit in ";
165  buffer << buffer_remaining << " byte buffer\n";
166 
167  throw exceptions::MemoryException (buffer.str ());
168  }
169  buffer_remaining -= sizeof (quality);
170 
171  // Remove clock field from the buffer and update accordingly
172  if ((size_t)buffer_remaining >= sizeof (clock))
173  {
174  memcpy (&clock, buffer, sizeof (clock));
176  buffer += sizeof (clock);
177  }
178  else
179  {
180  std::stringstream buffer;
181  buffer << "MessageHeader::read: ";
182  buffer << sizeof (clock) << " byte clock encoding cannot";
183  buffer << " fit in ";
184  buffer << buffer_remaining << " byte buffer\n";
185 
186  throw exceptions::MemoryException (buffer.str ());
187  }
188  buffer_remaining -= sizeof (clock);
189 
190  // Remove timestamp field from the buffer and update accordingly
191  if ((size_t)buffer_remaining >= sizeof (timestamp))
192  {
193  memcpy (&timestamp, buffer, sizeof (timestamp));
195  buffer += sizeof (timestamp);
196  }
197  else
198  {
199  std::stringstream buffer;
200  buffer << "MessageHeader::read: ";
201  buffer << sizeof (timestamp) << " byte timestamp encoding cannot";
202  buffer << " fit in ";
203  buffer << buffer_remaining << " byte buffer\n";
204 
205  throw exceptions::MemoryException (buffer.str ());
206  }
207  buffer_remaining -= sizeof (timestamp);
208 
209  // Remove the time to live field from the buffer
210  if (buffer_remaining >= 1)
211  {
212  memcpy (&ttl, buffer, 1);
213  buffer += 1;
214  }
215  buffer_remaining -= 1;
216 
217  return buffer;
218 }
219 
220 char *
222  int64_t & buffer_remaining)
223 {
224  // Write size field from the buffer and update accordingly
225  if ((size_t)buffer_remaining >= sizeof (size))
226  {
227  *(uint64_t *) buffer = madara::utility::endian_swap (size);
228  buffer += sizeof (size);
229  }
230  else
231  {
232  std::stringstream buffer;
233  buffer << "MessageHeader::write: ";
234  buffer << sizeof (size) << " byte size encoding cannot";
235  buffer << " fit in ";
236  buffer << buffer_remaining << " byte buffer\n";
237 
238  throw exceptions::MemoryException (buffer.str ());
239  }
240  buffer_remaining -= sizeof (size);
241 
242  // Write madara_id field from the buffer and update accordingly
243  if ((size_t)buffer_remaining >= sizeof (char) * MADARA_IDENTIFIER_LENGTH)
244  {
245  strncpy (buffer, madara_id, MADARA_IDENTIFIER_LENGTH);
246  buffer += sizeof (char) * MADARA_IDENTIFIER_LENGTH;
247  }
248  else
249  {
250  std::stringstream buffer;
251  buffer << "MessageHeader::write: ";
252  buffer << MADARA_IDENTIFIER_LENGTH << " byte id encoding cannot";
253  buffer << " fit in ";
254  buffer << buffer_remaining << " byte buffer\n";
255 
256  throw exceptions::MemoryException (buffer.str ());
257  }
258  buffer_remaining -= sizeof (char) * MADARA_IDENTIFIER_LENGTH;
259 
260  // Write domain field from the buffer and update accordingly
261  if ((size_t)buffer_remaining >= sizeof (char) * MADARA_DOMAIN_MAX_LENGTH)
262  {
263  strncpy (buffer, domain, MADARA_DOMAIN_MAX_LENGTH);
264  buffer += sizeof (char) * MADARA_DOMAIN_MAX_LENGTH;
265  }
266  else
267  {
268  std::stringstream buffer;
269  buffer << "MessageHeader::write: ";
270  buffer << MADARA_DOMAIN_MAX_LENGTH << " byte domain encoding cannot";
271  buffer << " fit in ";
272  buffer << buffer_remaining << " byte buffer\n";
273 
274  throw exceptions::MemoryException (buffer.str ());
275  }
276  buffer_remaining -= sizeof (char) * MADARA_DOMAIN_MAX_LENGTH;
277 
278  // Write originator from the buffer and update accordingly
279  if ((size_t)buffer_remaining >= sizeof (char) * MAX_ORIGINATOR_LENGTH)
280  {
281  strncpy (buffer, originator, MAX_ORIGINATOR_LENGTH);
282  buffer += sizeof (char) * MAX_ORIGINATOR_LENGTH;
283  }
284  else
285  {
286  std::stringstream buffer;
287  buffer << "MessageHeader::write: ";
288  buffer << MAX_ORIGINATOR_LENGTH << " byte originator encoding cannot";
289  buffer << " fit in ";
290  buffer << buffer_remaining << " byte buffer\n";
291 
292  throw exceptions::MemoryException (buffer.str ());
293  }
294  buffer_remaining -= sizeof (char) * MAX_ORIGINATOR_LENGTH;
295 
296  // Write type field from the buffer and update accordingly
297  if ((size_t)buffer_remaining >= sizeof (type))
298  {
299  *(uint32_t *) buffer = madara::utility::endian_swap (type);
300  buffer += sizeof (type);
301  }
302  else
303  {
304  std::stringstream buffer;
305  buffer << "MessageHeader::write: ";
306  buffer << sizeof (type) << " byte type encoding cannot";
307  buffer << " fit in ";
308  buffer << buffer_remaining << " byte buffer\n";
309 
310  throw exceptions::MemoryException (buffer.str ());
311  }
312  buffer_remaining -= sizeof (type);
313 
314  // Write updates field from the buffer and update accordingly
315  if ((size_t)buffer_remaining >= sizeof (updates))
316  {
317  *(uint32_t *) buffer = madara::utility::endian_swap (updates);
318  buffer += sizeof (updates);
319  }
320  else
321  {
322  std::stringstream buffer;
323  buffer << "MessageHeader::write: ";
324  buffer << sizeof (updates) << " byte updates encoding cannot";
325  buffer << " fit in ";
326  buffer << buffer_remaining << " byte buffer\n";
327 
328  throw exceptions::MemoryException (buffer.str ());
329  }
330  buffer_remaining -= sizeof (updates);
331 
332  // Write quality field from the buffer and update accordingly
333  if ((size_t)buffer_remaining >= sizeof (quality))
334  {
335  *(uint32_t *) buffer = madara::utility::endian_swap (quality);
336  buffer += sizeof (quality);
337  }
338  else
339  {
340  std::stringstream buffer;
341  buffer << "MessageHeader::write: ";
342  buffer << sizeof (quality) << " byte quality encoding cannot";
343  buffer << " fit in ";
344  buffer << buffer_remaining << " byte buffer\n";
345 
346  throw exceptions::MemoryException (buffer.str ());
347  }
348  buffer_remaining -= sizeof (quality);
349 
350  // Write clock field from the buffer and update accordingly
351  if ((size_t)buffer_remaining >= sizeof (clock))
352  {
353  *(uint64_t *) buffer = madara::utility::endian_swap (clock);
354  buffer += sizeof (clock);
355  }
356  else
357  {
358  std::stringstream buffer;
359  buffer << "MessageHeader::write: ";
360  buffer << sizeof (clock) << " byte clock encoding cannot";
361  buffer << " fit in ";
362  buffer << buffer_remaining << " byte buffer\n";
363 
364  throw exceptions::MemoryException (buffer.str ());
365  }
366  buffer_remaining -= sizeof (clock);
367 
368  // Write timestamp field from the buffer and update accordingly
369  if ((size_t)buffer_remaining >= sizeof (timestamp))
370  {
371  *(uint64_t *) buffer = madara::utility::endian_swap (timestamp);
372  buffer += sizeof (timestamp);
373  }
374  else
375  {
376  std::stringstream buffer;
377  buffer << "MessageHeader::write: ";
378  buffer << sizeof (timestamp) << " byte timestamp encoding cannot";
379  buffer << " fit in ";
380  buffer << buffer_remaining << " byte buffer\n";
381 
382  throw exceptions::MemoryException (buffer.str ());
383  }
384  buffer_remaining -= sizeof (timestamp);
385 
386  if (buffer_remaining >= 1)
387  {
388  memcpy (buffer, &ttl, 1);
389  buffer += 1;
390  }
391  buffer_remaining -= 1;
392 
393  return buffer;
394 }
395 
398 {
399  std::stringstream buffer;
400 
401  buffer << "140: size (8:" << size << "), ";
402  buffer << "encoding (8:" << madara_id << "), ";
403  buffer << "domain (32:" << domain << "), ";
404  buffer << "orig (64:" << originator << "), ";
405  buffer << "type (4:" << type << "), ";
406  buffer << "numupdates (4:" << updates << "), ";
407  buffer << "quality (4:" << quality << "), ";
408  buffer << "clock (8:" << clock << "), ";
409  buffer << "wallclock (8:" << timestamp << "), ";
410  buffer << "ttl (1:" << (int)ttl << "), ";
411 
412  return buffer.str ();
413 }
414 
415 uint64_t
417 {
418  return (madara::utility::endian_swap (*(uint64_t *)buffer));
419 }
420 
421 bool
423 {
424  return size == other.size &&
425  type == other.type &&
426  updates == other.updates &&
427  quality == other.quality &&
428  clock == other.clock &&
429  timestamp == other.timestamp &&
430  strncmp (madara_id, other.madara_id, MADARA_IDENTIFIER_LENGTH) == 0 &&
431  strncmp (domain, other.domain, MADARA_DOMAIN_MAX_LENGTH) == 0 &&
432  strncmp (originator, other.originator, MAX_ORIGINATOR_LENGTH) == 0;
433 }
virtual uint32_t encoded_size(void) const
Returns the size of the encoded MessageHeader class, which may be different from sizeof (MessageHeade...
char madara_id[8]
the identifier of this transport (MADARA_IDENTIFIER)
#define MADARA_IDENTIFIER
Definition: MessageHeader.h:22
virtual const char * read(const char *buffer, int64_t &buffer_remaining)
Reads a MessageHeader instance from a buffer and updates the amount of buffer room remaining...
uint32_t updates
the number of knowledge variable updates in the message
int64_t get_time(void)
Returns a time of day in nanoseconds If simtime feature is enabled, this may be simulation time inste...
Definition: Utility.inl:253
#define MAX_ORIGINATOR_LENGTH
Definition: MessageHeader.h:28
uint32_t type
the type of message
static uint32_t static_encoded_size(void)
Returns the size of the encoded MessageHeader class.
virtual std::string to_string(void)
Converts the relevant fields to a printable string.
static struct madara::knowledge::tags::string_t string
uint64_t endian_swap(uint64_t value)
Converts a host format uint64_t into big endian.
Definition: Utility.inl:115
uint64_t size
the size of this header plus the updates
static uint64_t get_size(const char *buffer)
Returns the size field of the header.
unsigned char ttl
time to live (number of rebroadcasts to perform after original send
uint64_t timestamp
the timestamp of the sender when the message was generated
An exception for general memory errors like out-of-memory.
char originator[64]
the originator of the message (host:port)
char domain[32]
the domain that this message is intended for
virtual ~MessageHeader()
Destructor.
Provides utility functions and classes for common tasks and needs.
Definition: IteratorImpl.h:14
#define MADARA_IDENTIFIER_LENGTH
Definition: MessageHeader.h:21
uint64_t clock
the clock of the sender when the message was generated
#define MADARA_DOMAIN_MAX_LENGTH
Definition: MessageHeader.h:23
Defines a robust message header which is the default for KaRL messages.
Definition: MessageHeader.h:57
virtual bool equals(const MessageHeader &other)
Compares the fields of this instance to another instance.
uint32_t quality
the quality of the message sender
virtual char * write(char *buffer, int64_t &buffer_remaining)
Writes a MessageHeader instance to a buffer and updates the amount of buffer room remaining...