Core Library  1.7.0.0
Library containing core utilities and tools for threading, networking, logging, INI and CSV file management etc.
MessageUtils.h
Go to the documentation of this file.
1 
2 // This file is part of CoreLibrary containing useful reusable utility
3 // classes.
4 //
5 // Copyright (C) 2014 to present, Duncan Crutchley
6 // Contact <dac1976github@outlook.com>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Lesser General Public License as published
10 // by the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License and GNU Lesser General Public License
17 // for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // and GNU Lesser General Public License along with this program. If
21 // not, see <http://www.gnu.org/licenses/>.
22 
28 #ifndef MESSAGEUTILS
29 #define MESSAGEUTILS
30 
31 #include <iterator>
32 #include <algorithm>
33 #include <cstring>
34 #include <cassert>
35 #include "AsioDefines.h"
37 
39 namespace core_lib
40 {
42 namespace asio
43 {
45 namespace messages
46 {
47 
55 class CORE_LIBRARY_DLL_SHARED_API MessageHandler final
56 {
57 public:
58 #ifdef USE_DEFAULT_CONSTRUCTOR_
59 
61 #else
62 
63  MessageHandler() = default;
64 #endif
65 
77  MessageHandler(const defs::default_message_dispatcher_t& messageDispatcher,
78  const std::string& magicString,
79  size_t memPoolMsgCount = 0,
80  size_t defaultMsgSize = udp::DEFAULT_UDP_BUF_SIZE);
82  ~MessageHandler() = default;
84  MessageHandler(const MessageHandler&) = default;
86  MessageHandler& operator=(const MessageHandler&) = default;
87 
88 #ifdef USE_EXPLICIT_MOVE_
89 
92  MessageHandler& operator=(MessageHandler&& mh);
93 #else
94 
95  MessageHandler(MessageHandler&&) = default;
97  MessageHandler& operator=(MessageHandler&&) = default;
98 #endif
99 
103  size_t CheckBytesLeftToRead(const defs::char_buffer_t& message) const;
108  void MessageReceivedHandler(const defs::char_buffer_t& message) const;
109 
110 private:
115  static bool CheckMessage(const defs::char_buffer_t& message);
121  void InitialiseMsgPool(size_t memPoolMsgCount, size_t defaultMsgSize);
126  defs::default_received_message_ptr_t GetNewMessgeObject() const;
127 
128 private:
131 #ifdef USE_DEFAULT_CONSTRUCTOR_
132 
133  std::string m_magicString;
134 #else
135 
136  std::string m_magicString{static_cast<char const*>(defs::DEFAULT_MAGIC_STRING)};
137 #endif
138  mutable size_t m_msgPoolIndex{0};
139  std::vector<defs::default_received_message_ptr_t> m_msgPool;
140 };
141 
159 void CORE_LIBRARY_DLL_SHARED_API FillHeader(const std::string& magicString,
160  defs::eArchiveType archiveType, int32_t messageId,
161  const defs::connection_t& responseAddress,
162  uint32_t messageLength, defs::MessageHeader& header);
163 
170 template <typename A> struct ArchiveTypeToEnum
171 {
177  {
178  BOOST_THROW_EXCEPTION(std::invalid_argument("unknown archive type"));
180  }
181 };
182 
184 template <> struct ArchiveTypeToEnum<serialize::archives::out_bin_t>
185 {
191  {
193  }
194 };
195 
197 template <> struct ArchiveTypeToEnum<serialize::archives::out_port_bin_t>
198 {
204  {
206  }
207 };
208 
210 template <> struct ArchiveTypeToEnum<serialize::archives::out_raw_t>
211 {
217  {
219  }
220 };
221 
224 template <> struct ArchiveTypeToEnum<serialize::archives::out_protobuf_t>
225 {
231  {
233  }
234 };
235 
237 template <> struct ArchiveTypeToEnum<serialize::archives::out_json_t>
238 {
244  {
246  }
247 };
248 
250 template <> struct ArchiveTypeToEnum<serialize::archives::out_xml_t>
251 {
257  {
259  }
260 };
261 
268 class CORE_LIBRARY_DLL_SHARED_API MessageBuilder final
269 {
270 public:
271 #ifdef USE_DEFAULT_CONSTRUCTOR_
272 
273  MessageBuilder();
274 #else
275 
276  MessageBuilder() = default;
277 #endif
278 
282  explicit MessageBuilder(const std::string& magicString);
284  ~MessageBuilder() = default;
286  MessageBuilder(const MessageBuilder&) = default;
288  MessageBuilder& operator=(const MessageBuilder&) = default;
289 #ifdef USE_EXPLICIT_MOVE_
290 
293  MessageBuilder& operator=(MessageBuilder&& mb);
294 #else
295 
296  MessageBuilder(MessageBuilder&&) = default;
298  MessageBuilder& operator=(MessageBuilder&&) = default;
299 #endif
300 
310  defs::char_buffer_t const& Build(int32_t messageId,
311  const defs::connection_t& responseAddress) const;
320  defs::char_buffer_t const&
321  Build(const defs::char_buffer_t& message, int32_t messageId,
322  const defs::connection_t& responseAddress,
323  defs::eArchiveType archiveType = defs::eArchiveType::raw) const;
333  defs::char_buffer_t const&
334  Build(const void* message, size_t messageLength, int32_t messageId,
335  const defs::connection_t& responseAddress,
336  defs::eArchiveType archiveType = defs::eArchiveType::raw) const;
351  template <typename T, typename A>
352  defs::char_buffer_t const& Build(const T& message, int32_t messageId,
353  const defs::connection_t& responseAddress) const
354  {
355  // Serialise message.
356  serialize::ToCharVector<T, A>(message, m_serialisationBuffer);
357 
358  if (m_serialisationBuffer.empty())
359  {
360  BOOST_THROW_EXCEPTION(std::runtime_error("cannot serialize message"));
361  }
362 
363  // Resize message buffer.
364  auto totalLength = sizeof(defs::MessageHeader) + m_serialisationBuffer.size();
365  m_messageBuffer.resize(totalLength);
366 
367  // Fill header.
368  const defs::eArchiveType archiveType = ArchiveTypeToEnum<A>().Enumerate();
369  defs::MessageHeader* header =
370  reinterpret_cast<defs::MessageHeader*>(m_messageBuffer.data());
371  FillHeader(m_magicString,
372  archiveType,
373  messageId,
374  responseAddress,
375  static_cast<uint32_t>(m_serialisationBuffer.size()),
376  *header);
377 
378  auto writePosIter = std::next(m_messageBuffer.begin(), sizeof(defs::MessageHeader));
379  std::copy(m_serialisationBuffer.begin(), m_serialisationBuffer.end(), writePosIter);
380 
381  return m_messageBuffer;
382  }
383 
384 private:
385 #ifdef USE_DEFAULT_CONSTRUCTOR_
386 
387  std::string m_magicString;
388 #else
389 
390  std::string m_magicString{static_cast<char const*>(defs::DEFAULT_MAGIC_STRING)};
391 #endif
392  mutable defs::char_buffer_t m_messageBuffer;
393  mutable defs::char_buffer_t m_serialisationBuffer;
394 };
395 
410 template <typename MsgBldr>
411 defs::char_buffer_t const&
412 BuildMessage(int32_t messageId, const defs::connection_t& responseAddress,
413  const defs::connection_t& fallbackResponseAddress, const MsgBldr& messageBuilder)
414 {
415  auto responseConn =
416  (responseAddress == defs::NULL_CONNECTION) ? fallbackResponseAddress : responseAddress;
417  return messageBuilder.Build(messageId, responseConn);
418 }
434 template <typename MsgBldr>
435 defs::char_buffer_t const& BuildMessage(defs::char_buffer_t const& message, int32_t messageId,
436  const defs::connection_t& responseAddress,
437  const defs::connection_t& fallbackResponseAddress,
438  const MsgBldr& messageBuilder)
439 {
440  auto responseConn =
441  (responseAddress == defs::NULL_CONNECTION) ? fallbackResponseAddress : responseAddress;
442  return messageBuilder.Build(message, messageId, responseConn);
443 }
460 template <typename T, typename A, typename MsgBldr>
461 defs::char_buffer_t const&
462 BuildMessage(const T& message, int32_t messageId, const defs::connection_t& responseAddress,
463  const defs::connection_t& fallbackResponseAddress, const MsgBldr& messageBuilder)
464 {
465  auto responseConn =
466  (responseAddress == defs::NULL_CONNECTION) ? fallbackResponseAddress : responseAddress;
467  return messageBuilder.template Build<T, A>(message, messageId, responseConn);
468 }
469 
476 template <typename T>
477 T DeserializeMessage(const defs::char_buffer_t& messageBuffer, defs::eArchiveType archiveType)
478 {
479  assert((archiveType != defs::eArchiveType::raw) &&
480  (archiveType != defs::eArchiveType::protobuf));
481 
482  switch (archiveType)
483  {
485  return serialize::ToObject<T, serialize::archives::in_bin_t>(messageBuffer);
487  return serialize::ToObject<T, serialize::archives::in_port_bin_t>(messageBuffer);
489  // Do nothing.
490  break;
492  return serialize::ToObject<T, serialize::archives::in_json_t>(messageBuffer);
494  return serialize::ToObject<T, serialize::archives::in_xml_t>(messageBuffer);
496  // Do nothing;
497  break;
498  }
499 
500  return T();
501 }
502 
508 template <typename T> T DeserializeMessage(const defs::char_buffer_t& messageBuffer)
509 {
510  return serialize::ToObject<T, serialize::archives::in_raw_t>(messageBuffer);
511 }
512 
518 template <typename T> T DeserializeProtobuf(const defs::char_buffer_t& messageBuffer)
519 {
520  return serialize::ToObject<T, serialize::archives::in_protobuf_t>(messageBuffer);
521 }
522 
523 } // namespace messages
524 } // namespace asio
525 } // namespace core_lib
526 
527 #endif // MESSAGEUTILS
defs::default_message_dispatcher_t m_messageDispatcher
Message dispatcher function object.
Definition: MessageUtils.h:130
T DeserializeMessage(const defs::char_buffer_t &messageBuffer, defs::eArchiveType archiveType)
Templated message deserializer function for non-POD data.
Definition: MessageUtils.h:477
std::function< void(default_received_message_ptr_t)> default_message_dispatcher_t
Typedef to default message dispatcher function object.
Definition: AsioDefines.h:286
cereal::JSONOutputArchive out_json_t
Typedef to output json archive.
Definition: SerializeToVector.h:82
defs::char_buffer_t const & Build(const T &message, int32_t messageId, const defs::connection_t &responseAddress) const
Build message method for header + messaage body messages.
Definition: MessageUtils.h:352
Portable binary archive, requires Cereal serialization.
Raw data, only for POD objects.
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:243
File containing useful definitions.
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:176
Default message handler class.
Definition: MessageUtils.h:55
XML archive, requires Cereal serialization.
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:216
File containing utilities to serialize objects to byte vectors.
Binary archive, requires Cereal serialization.
JSON archive, requires Cereal serialization.
The core_lib namespace.
Definition: AsioDefines.h:59
std::shared_ptr< default_received_message_t > default_received_message_ptr_t
Typedef to default version of received message shared pointer.
Definition: AsioDefines.h:284
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:203
std::pair< std::string, uint16_t > connection_t
Typedef describing a network connection as (address, port).
Definition: AsioDefines.h:152
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:256
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:190
Default message header structure that is also POD.
Definition: AsioDefines.h:194
cereal::BinaryOutputArchive out_bin_t
Typedef to output binary archive.
Definition: SerializeToVector.h:78
void CORE_LIBRARY_DLL_SHARED_API FillHeader(const std::string &magicString, defs::eArchiveType archiveType, int32_t messageId, const defs::connection_t &responseAddress, uint32_t messageLength, defs::MessageHeader &header)
Header filler function.
Definition: MessageUtils.cpp:181
static defs::eArchiveType Enumerate()
Enumerate method.
Definition: MessageUtils.h:230
eArchiveType
Message serialization archive type enumeration.
Definition: AsioDefines.h:171
defs::char_buffer_t const & BuildMessage(int32_t messageId, const defs::connection_t &responseAddress, const defs::connection_t &fallbackResponseAddress, const MsgBldr &messageBuilder)
Message builder wrapper function for header only messages.
Definition: MessageUtils.h:412
T DeserializeProtobuf(const defs::char_buffer_t &messageBuffer)
Templated message deserializer function for Google protocol buffer data.
Definition: MessageUtils.h:518
const char DEFAULT_MAGIC_STRING[]
Constant defining default magc string as "_BEGIN_MESSAGE_".
Definition: AsioDefines.cpp:38
cereal::XMLOutputArchive out_xml_t
Typedef to output xml archive.
Definition: SerializeToVector.h:80
Default message builder class.
Definition: MessageUtils.h:268
cereal::PortableBinaryOutputArchive out_port_bin_t
Typedef to output portable binary archive.
Definition: SerializeToVector.h:76
protobuf_oarchive out_protobuf_t
Typedef to output using Google protocol buffers.
Definition: SerializeToVector.h:86
std::vector< char > char_buffer_t
Typedef to generic char buffer based on s std::vector<char>.
Definition: AsioDefines.h:239
raw_oarchive out_raw_t
Typedef to output raw archive.
Definition: SerializeToVector.h:84
const connection_t NULL_CONNECTION
Constant defining a null network connection as ("0.0.0.0", 0).
Archive type enumerator as a template class.
Definition: MessageUtils.h:170