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