Squashed 'libs/CommService/' content from commit 7ccc0fc

git-subtree-dir: libs/CommService
git-subtree-split: 7ccc0fce88bbc5969df060058cf0fb57abe3bcf9
This commit is contained in:
Henry Winkel
2022-09-15 09:53:53 +02:00
commit cc67e4840f
799 changed files with 179487 additions and 0 deletions

View File

@@ -0,0 +1,385 @@
#pragma once
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @copyright 2022 MPLv2
*/
#include <chrono>
#include <cstdint>
#include <vector>
#include <cstring>
#include <BC/endianess.hpp>
#include <string>
#include <stdexcept>
#include <map>
/**
* @brief main namespace of libbattle-com++
*
* Main namespace of the libbattle-com++, everything concerning the library can be found
* in this namespace
*/
namespace BC
{
/**
* @brief Namespace for all BC wide DataTypes
*/
namespace DataTypes
{
/**
* @brief namespace for conversion functions for different datatypes
*/
namespace Convert
{
/*
* @brief template function to byte swap int/uint datatypes - used for endianess conversion
*
* @param v - pointer to a variable of some int/uint datatype - in place byte swapped
*/
template<typename T>
void swapBytes(T *v)
{
for (unsigned int i = 0; i < sizeof(T)/2; ++i)
{
std::swap(((char *)v)[i], ((char *)v)[sizeof(T)-1-i]);
}
}
/**
* @brief template for converting of simple datatypes to a byte_array, including endianness conversion to big endian
*
* @param variable - the variable to convert to a byte vector, needs to be int/uint datatype
*
* @return the std::vector<unsigned char>
*/
template<typename T>
std::vector<unsigned char> fromSimpleToByteArray(T &variable)
{
std::vector<unsigned char> bytes;
bytes.clear();
bytes.resize(sizeof(T));
#ifndef IS_BIG_ENDIAN
T convVariable = variable;
swapBytes(&convVariable);
std::memcpy(bytes.data(),reinterpret_cast<const unsigned char*>(&convVariable),sizeof(T));
#else
std::memcpy(bytes.data(),reinterpret_cast<const unsigned char*>(&variable),sizeof(T));
#endif
return bytes;
}
/**
* @brief function to convert a std::string to an std::vector<unsigned char>
*
* for converting the string, first the length of the string is converted as
* an uint32_t into the std::vector to be able to correctly parse the string
* in a larger vector.
*
* @param variable - the std::string to convert
*
* @return the std::vector<unsigned char>
*/
std::vector<unsigned char> fromStringToByteArray(const std::string &variable);
/**
* @brief function to convert a std::vector<unsigned char> to an std::string
*
* this is the partner function to fromStringToByteArray. It takes the
* first 4 byte of the vector as an uint32_t string length identifier and
* uses the following length chars as the string
*
* @param v - the vector to convert to a string
* @return the string read from the vector
* @throw std::invalid_argument: "vector too short for <X> chars"
*/
std::string fromByteArrayToString(std::vector<unsigned char> &v);
/**
* @brief function to convert a std::vector<unsigned char> to an simple datatype
*
* this is the partner function to fromSimpleToByteArray.
* it extracts the simple datatype like int, double, etc. from the vector and
* returns it
*
* @param v - the vector to convert to a simple datatype
* @return simple datatype
* @throw std::invalid_argument: "the bytevector is too small to fit the datatype"
*/
template<typename T>
T fromByteArrayToSimple(std::vector<unsigned char> &bytes)
{
T convVariable;
if(bytes.size() < sizeof(T))
{
throw(std::invalid_argument(std::string(__FILE__) + ":" + std::string(__PRETTY_FUNCTION__) + ":" + std::to_string(__LINE__) + ": the bytevector is too small to fit the datatype"));
}
std::memcpy(reinterpret_cast<unsigned char*>(&convVariable),bytes.data(),sizeof(T));
#ifndef IS_BIG_ENDIAN
swapBytes(&convVariable);
#endif
return std::move(convVariable);
}
/**
* @brief function to convert a container of a simple datatype to a std::vector<unsigned char>
*
* this is the partner function to fromByteArrayToSimpleContainer.
* the number of container elements is prepended to the std::vector and the simple datatype
* elements follow.
*
* @param data - the container of a simple datatype
*
* @return the std::vector<unsigned char>;
*/
template<class T>
std::vector<unsigned char> fromSimpleContainerToByteArray(T &data)
{
std::vector<unsigned char> bytes;
std::vector<unsigned char> convert;
uint32_t size=data.size();
bytes=BC::DataTypes::Convert::fromSimpleToByteArray(size);
for(auto it = data.begin(); it!=data.end(); ++it)
{
convert=BC::DataTypes::Convert::fromSimpleToByteArray(*it);
bytes.insert(std::end(bytes), std::begin(convert), std::end(convert));
}
return bytes;
}
/**
* @brief function to convert a std::vector<unsigned char> to a container of simple datatype elements
*
* this is the partner function to fromSimpleContainerToByteArray. It takes the
* first 4 byte of the vector as an uint32_t element count and parses the all the elements
* from the vector.
*
* @param v - the vector to convert to a container of simple datatype elements
*
* @return the container
*/
template<class T, typename S>
T fromByteArrayToSimpleContainer(std::vector<unsigned char> &v)
{
T data;
uint32_t size = BC::DataTypes::Convert::fromByteArrayToSimple<S>(v);
v.erase(v.begin(), v.begin()+sizeof(size));
for(uint32_t i=0; i<size; i++)
{
S convert = BC::DataTypes::Convert::fromByteArrayToSimple<S>(v);
v.erase(v.begin(), v.begin()+sizeof(convert));
data.push_back(convert);
}
return std::move(data);
}
/**
* @brief function to convert a container of strings to a std::vector<unsigned char>
*
* @param data - the container of std::string
*
* @return the std::vector<unsigned char>
*/
template<class T>
std::vector<unsigned char> fromStringContainerToByteArray(T &data)
{
std::vector<unsigned char> bytes;
std::vector<unsigned char> convert;
uint32_t size=data.size();
bytes=BC::DataTypes::Convert::fromSimpleToByteArray(size);
for(auto it = data.begin(); it!=data.end(); ++it)
{
convert=BC::DataTypes::Convert::fromStringToByteArray(*it);
bytes.insert(std::end(bytes), std::begin(convert), std::end(convert));
}
return bytes;
}
/**
* @brief function to convert a std::vector<unsigned char> to a container of strings
*
* @param data - the container of std::string
*
* @return the std::vector<unsigned char>
*/
template<class T>
T fromByteArrayToStringContainer(std::vector<unsigned char> &v)
{
T data;
uint32_t size = BC::DataTypes::Convert::fromByteArrayToSimple<uint32_t>(v);
v.erase(v.begin(), v.begin()+sizeof(size));
for(uint32_t i=0; i<size; i++)
{
std::string convert = BC::DataTypes::Convert::fromByteArrayToString(v);
data.push_back(convert);
}
return std::move(data);
}
} // namespace Convert
/// type of the clock used by BC
using BCClockType = std::chrono::system_clock;
/// type of all time attributes throughout BC BCClockType::period
using BCTimeType = uint64_t;
/// the period of the clock within BC, can be different from the actual used clock
using BCPeriod = std::chrono::nanoseconds;
/// variable type for device/endpoint ids within libcms++
using deviceIdType = uint32_t;
/// enumeration variable for identifying major device/endpoint types.
enum deviceMajorType : uint32_t
{
/// device/endpoint is a radar
RADAR,
/// device/endpoint is a sonar
SONAR,
/// device/endpoint is a lidar
LIDAR,
/// device/endpoint is a camera
CAMERA,
/// device/endpoint is a threat avaluation process/device/software
THREAT_EVALUATION_MANAGER,
/// device/endpoint is a FLOATS Receiver
FLOATS_RECEIVER,
/// device/endpoint is a display
DISPLAY,
/// device/endpoint is a history server
HISTORY_SERVER,
/// device/endpoint is a threat consolidation application
THREAT_CONSOLIDATION,
/// device/endpoint is an own track generator
OWN_TRACK_GENERATOR,
/// device/endpoint is a data fusion application
DATA_FUSION,
/// device/endpoint is an identification process application
ID_PROCESS,
/// device/endpoint type is unknown
UNKNOWN
};
/**
* @brief map converting from BC::DataTypes::deviceMajorType to string
*/
static std::map<BC::DataTypes::deviceMajorType, std::string>deviceMojorTypeMap =
{
{BC::DataTypes::deviceMajorType::UNKNOWN, "Unknown"},
{BC::DataTypes::deviceMajorType::DATA_FUSION, "Data Fusion"},
{BC::DataTypes::deviceMajorType::CAMERA, "Camera"},
{BC::DataTypes::deviceMajorType::DISPLAY, "Display"},
{BC::DataTypes::deviceMajorType::FLOATS_RECEIVER, "FLOATS Receiver"},
{BC::DataTypes::deviceMajorType::HISTORY_SERVER, "History Server"},
{BC::DataTypes::deviceMajorType::ID_PROCESS, "Identification Process"},
{BC::DataTypes::deviceMajorType::LIDAR, "Lidar"},
{BC::DataTypes::deviceMajorType::OWN_TRACK_GENERATOR, "Own Track Generator"},
{BC::DataTypes::deviceMajorType::RADAR, "Radar"},
{BC::DataTypes::deviceMajorType::SONAR, "Sonar"},
{BC::DataTypes::deviceMajorType::THREAT_EVALUATION_MANAGER, "Threat Evaluation"},
{BC::DataTypes::deviceMajorType::THREAT_CONSOLIDATION, "Threat Consolidation"}
};
} // namespace DataTypes
/**
* @brief function to get the current time in every BC implementation
*/
inline BC::DataTypes::BCTimeType getCurrentTime()
{
std::chrono::time_point<BC::DataTypes::BCClockType> now = BC::DataTypes::BCClockType::now();
return std::chrono::duration_cast<BC::DataTypes::BCPeriod>(now.time_since_epoch()).count();
}
/**
* @brief Class/Namespace for BC related constants
*/
class Constants
{
public:
/// the epoch starting date used throughout BC, used to abstract from the epoch used
/// in different operating systems and standards
static constexpr const char *cEpochDateTime = "1970-01-01 00:00";
///@name constants related to devices
///@{
/// constants identifying that we want to select/address all devices in the CMS, required for publish/subscribe
static const BC::DataTypes::deviceIdType allDevices = 0;
///@}
///@name PubSub Domain related constants
///@{
/// constant identifying the real world domain
static constexpr const char *cRealWorldDomain = "REALWORLD";
/// constant identifying the default simulation domain
static constexpr const char *cSimWorldDomain = "SIMULATION";
/// constant identifying the Management domain
static constexpr const char *cManagementDomain = "_MANAGEMENT_";
/// constant identifying all domains
static constexpr const char *cAllDomains = "_DOMAIN_ALL_";
///@}
///@name PubSub Topic related constants
///@{
/// constant identifying that the subscriber is interested in all topics
static constexpr const char *cAllTopics = "_TOPIC_ALL_";
/// constant identifying the PING topic, for pinging subscribers
static constexpr const char *cPingTopic = "_TOPIC_PING_";
/// constant identifying the PONG topic, for answering a PING
static constexpr const char *cPongTopic = "_TOPIC_PONG_";
/// constant identifying the HOTPLUG JOIN message topic
static constexpr const char *cHotplugJoin = "_HOTPLUG_JOIN_";
/// constant identifying the HOTPLUG LEAVE message topic
static constexpr const char *cHotplugLeave = "_HOTPLUG_LEAVE_";
/// constant identifying the PING message topic
static constexpr const char *cPing = "_PING_";
/// constant identifying the PONG message topic
static constexpr const char *cPong = "_PONG_";
};
} // namespace BC

View File

@@ -0,0 +1,80 @@
#pragma once
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @copyright MPLv2
*/
#include <mutex>
#include <queue>
#include <memory>
#include <condition_variable>
#include <BC/Message.hpp>
namespace BC{
/**
* @class BasicMessageQueue
*
* This class encapsulates shared storage which is a queue and protect it
* with a mutex. In Addition there is a condition variable to notify other
* threads if there is new data in the queue.
*/
class BasicMessageQueue
{
private:
std::queue<std::unique_ptr<BC::Message>> q;
std::mutex mx;
std::condition_variable condVar;
public:
/**
* @brief default constructor for class BasicMessageQueue
*/
BasicMessageQueue();
/**
* @brief appends given message to queue
*
* The storage is protected by a mutex. Makes a notify_one call to inform
* in waiting thread that there is a new message in the queue.
*
* @param msg - incoming message
*/
void appendMessage( std::unique_ptr<BC::Message> msg );
/**
* @brief gets the fron message from the queue
*
* This method gets the front message in the queue and deletes it from the
* queue. The storage is protected by a mutex. If the queue is empty the
* function throws an exception.
*
* @result msg - returns the front message from the queue
* @throws length_error - if queue is empty this method throws length_error exception
*/
std::unique_ptr<BC::Message> getMessage();
/**
* @brief waits for new message to be added
*
* If the queue is empty this method waits for a notfication on the condition variable.
* It returns the front message and deletes it from the queue. This action is protected
* by a mutex.
*
* @result msg - returns the first/front message in the queue
* @throws length_error - if queue is empty this method throws length_error exception
*/
std::unique_ptr<BC::Message> waitForNewMessage();
/**
* @brief method size
*
* @result size - current size of the message queue
*/
unsigned int size();
}; //BasicMessageQueue
}; // namespace BC

View File

@@ -0,0 +1,150 @@
#pragma once
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @copyright MPLv2
*/
#include <BC/receiveable.hpp>
#include <BC/BasicMessageQueue.hpp>
#include <condition_variable>
#include <iostream>
#include <chrono>
namespace BC
{
/**
* @brief class BasicQueueReceiver
*
* Derived class from receiveable (libbattle-com++) to receive messages
* published in the battle-com network.
*
* This class is a basic component for applications that need to connect to a
* battle-com network, like e.g. the prototype CMS.
* The receiver will be moved to a thread by the service it is used from. If
* the receive method gets called and it is still busy with the previous
* message, the new message will get lost.
*
* Therefor messages that are received by this BasicQueueReceiver are pushed
* to a message queue (short receive method). From there the other components
* of the application can take the messages as needed. This implementation
* ensures that the receive method is short so no information get lost.
*/
class BasicQueueReceiver : public BC::receiveable
{
private:
/// threadsafe queue to store received messages
BC::BasicMessageQueue messages;
public:
/**
* @brief default constructor for class Receiver
*/
BasicQueueReceiver();
/**
* @brief tryGetMessage
*
* This method tries to get a message from the message queue.
* Calles getMessage from message queue. This method rethrows the exception
* that can be trown by called method.
*
* @result msg - raw pointer to new message from the network
* @throws length_error - if queue is empty this method throws length_error exception
*/
[[deprecated("Replaced by bool tryGetMessage(BC::Message **msg)")]]
BC::Message * tryGetMessage();
/**
* @brief tryGetMessage
*
* This method tries to get a message from the message queue.
* Calles getMessage from message queue. This method rethrows the exception
* that can be trown by called method.
*
* @TODO: change param msg to smart pointer (when switching from raw to smart pointer in this project)
*
* @result true - a message was get successfully
* @return false - there was no message in the queue, the pointer is invalid and equals nullptr
* @param msg - raw pointer to new message from the network that should be get from the queue
*/
[[deprecated("Replaced by function that uses unique_ptr")]]
bool tryGetMessage(BC::Message **msg);
/**
* @brief waitForNewMessage
*
* Calles waitForNewMessage method from corresponding message queue. After
* notification the new message will be returned.
* This method catches the exception: empty queue.
*
* @result msg - raw pointer to new message from the network
* @rethrow - rethrows an exception that is not empty queue exception
*/
[[deprecated("Replaced by function that uses unique_ptr")]]
BC::Message * waitForNewMessage();
/**
* @brief getMessage
*
* This method gets a message form the message queue if there is a message
* in the queue. If the message queue is empty this method throw an
* exception
*
* @result - unique pointer to received message
* @throws length_error - if queue is empty this method throws length_error exception
*/
std::unique_ptr<BC::Message> getMessage();
/**
* @brief waits given time in seconds for new message to be recieved
*
* This method tries to get one BC::Message from the receiver for a
* specific time. If no message can be taken after this time the class
* function returns a nullpointer.
*
* @param time - time duration in seconds the method tries to get a message from the queue
* @result - unique pointer to BC::Message from message queue
* @result nullptr - returns nullptr if message queue stays empty
*/
std::unique_ptr<BC::Message> waitSecondsForNewMessage(std::uint16_t time);
/**
* @brief waits given time in milliseconds for new message to be recieved
*
* This method tries to get one BC::Message from the receiver for a
* specific time. If no message can be taken after this time the class
* function returns a nullpointer.
*
* @param time - time duration in milliseconds the method tries to get a message from the queue
* @result - unique pointer to BC::Message from message queue
* @result nullptr - returns nullptr if message queue stays empty
*/
std::unique_ptr<BC::Message> waitMillisecondsForNewMessage(std::uint16_t time);
/**
* @brief gets number of messages in the queue
*
* This method returns the queue size which means the number of messages
* stored at the queue.
*
* @result size - size of message queue
*/
unsigned int getQueueSize();
/**
* @brief virtual function receive
*
* This function is called if there are new messages published.
* These messages are pushed to the message queue.
*
* @param m - raw pointer to the received message
*/
virtual void receive(BC::Message *m) override;
}; // class BasicQueueReceiver
}; // namespace BC

View File

@@ -0,0 +1,283 @@
#ifndef __LIBBC_BC_BASICSERVICE_HPP__
#define __LIBBC_BC_BASICSERVICE_HPP__
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the BasicService class
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2018-11-23
* @copyright 2018 no yet defined
*/
#include <thread>
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <chrono>
#include <list>
#include <atomic>
#include <map>
#include <BC/BC.hpp>
#include <BC/Message.hpp>
#include <BC/receiveable.hpp>
namespace BC {
/**
* @brief base class for all battle-com services
*
* This class is the interface for all battle-com services. It enforces all
* the required methods and provides essential data types.
*/
class BasicService
{
private:
/// the network id of the device using this service
BC::DataTypes::deviceIdType id;
/// The major type of the id of the device using this service
BC::DataTypes::deviceMajorType majorType;
/// The minor type of the device, like a string with vendor/device string
std::string minorType;
/// variable for holding the receive thread identifier
std::thread receiveThread;
/// variable indicating if the receiveThread should be stopped
std::atomic<bool> stopReceiveThread;
/// list holding all the subscribers of this service
std::map<std::string, std::map<std::string,std::vector<BC::receiveable *>>> subscribers;
/// mutex protecting the subscrivers list in a multithread context
std::mutex subscribersMutex;
/// show if the service is connected or not
std::atomic<bool> connected;
std::mutex mutex;
/// attribute identifying this service as a gateway and all packets should be forwarded
bool gateway = false;
/**
* @brief method called by the receive thread.
*
* This method is called inside the receiveThread
* It calls the derivedReceive method in an endless loop.
*/
void receive();
/**
* @brief method to process basic received messages
*
* example messages processed in this method are
* PING and Control messages.
*
* @param m - the message to process
*
* @return true - the message has been processed by the method
* @return false - the message has not been processes by the method
*/
bool basicProcess(const BC::Message *m);
protected:
/**
* @brief called by the connect method after basic initializing
*
* This method has to be implemented by every child class. It is responsible
* for connecting to the underlying transport layer protocol like UDP/TCP.
*
*/
virtual void derivedConnect()=0;
/**
* @brief called by the disconnect method before closing everything down
*
* This method has to be implemented by every child class. It is responsible
* for disconnecting from the underlying transport layer protocol like UDP/TCP.
*
*/
virtual void derivedDisconnect()=0;
/**
* @brief called from the receive thread to receive a message in a *neverending loop*
*
* This method has to be implemented by every child class. It is responsible
* for receiving data from the used transport layer protocol, like UDP/TCP .
*
* It has to be implemented that it receives one data frame. It is called repeatedly from
* the receive thread. It may block but eventually the method has to return control
* to the receive thread.
*
* The last action of this method has to be calling the process(std::vector<unsigned char> v) method
*/
virtual void derivedReceive()=0;
/**
* @brief process an received data vector, called from the derivedReceive method
*
* Method converts the vector to a CMS::PubSub::Message and calls
* the basicProcess and the process(CMS::PubSub::Message *m) method
*
* if the message is not processed by one of these methods it searches for subscribers
* to call
*
* @param v - the vector to process and convert to a CMS::PubSub::Message
*/
void process(std::vector<unsigned char> &v);
/**
* @brief called from the publish method inside the child class
*
* In this method the transmission of the message through the
* used transport layer is implemented.
*
* The BasicService is publishing a HOTPLUG JOIN after connecting and
* a HOTPLUG LEAVE message before disconnecting. The child class is
* responsible to add a CMS::PubSub::Payloads::HotPlugJoin payload to
* the first and a CMS::PubSub::Payloads::HotPlugLeave payload to the
* later in this method before transmitting it.
*
* @param m - the message to publish/transmit
*/
virtual void derivedPublish(BC::Message &m)=0;
/**
* @brief method to process certain messages inside the child class
*
* Method is called after converting the char vector to a CMS::PubSub::Message
* and calling basicProcess. The child class can process some required
* special messages in this method.
*
* @param m - the message to process
*
* @return true - the message has been processed by the method
* @return false - the message has not been processes by the method
*/
virtual bool process(const BC::Message *m)=0;
public:
/**
* @brief main constructor for the BasicService class
*
* This constructor just initializes the attributes to the given parameter values.
* receiveThread is initialized to a thread but without a call function.
* This is required to just initialize the class without starting a thread.
*/
BasicService(const BC::DataTypes::deviceIdType &myID, const BC::DataTypes::deviceMajorType &majorT,
const std::string &minorT) : id(myID), majorType(majorT), minorType(minorT), receiveThread(),
stopReceiveThread(false), connected(false)
{}
/**
* @brief destructor the the BasicService. if necessary stop the receiveThread
*
*/
virtual ~BasicService();
/**
* @brief set if we are a gateay or not
*
*/
void setGateway(const bool v){gateway=v;}
/**
* @brief check if we are a gateway or not
*
*/
bool isGateway() const {return gateway;}
/**
* @brief check if the service is already connected
*
*/
bool isConnected() const {return connected;}
/**
* @brief just return the id
*/
BC::DataTypes::deviceIdType getId() const {return id;}
/**
* @brief method to connect the service to the underlying network and start receiving
*
* this method also calls the derivedConnect method of the child class
*/
void connect();
/**
* @brief method to disconnect the service from the underlying network
*
* this method also calls the derivedDisconnect method of the child class
*/
void disconnect();
/**
* @brief method to publish a message through the service
*
* this method calls the derivedPublish method of the child class
*
* @param m - the message to publish
*/
void publish(BC::Message &m);
/**
* @brief subscribe a CMS::PubSub::receiveable class to the list of domains and the list of topics
*
* @param r - the class to subscribe
* @param domains the list of domains to subscribe to
* @param topics the list of topics to subscribe to
*/
void subscribe(BC::receiveable *r, std::list<std::string> domains, std::list<std::string> topics);
/**
* @brief subscribe a CMS::PubSub::receiveable class to the domain and the list of topics
*
* @param r - the class to subscribe
* @param domains the domain to subscribe to
* @param topics the list of topics to subscribe to
*/
void subscribe(BC::receiveable *r, std::string domain, std::list<std::string> topics);
/**
* @brief subscribe a CMS::PubSub::receiveable class to the list of domains and the topic
*
* @param r - the class to subscribe
* @param domains the list of domains to subscribe to
* @param topics the topic to subscribe to
*/
void subscribe(BC::receiveable *r, std::string domain, std::string topic);
/**
* @brief Return the id of the service in the network.
*
*/
BC::DataTypes::deviceIdType getID() const { return id;}
/**
* @brief Get the Major Type of the Service.
*
* @return BC::DataTypes::deviceMajorType
*/
BC::DataTypes::deviceMajorType getMajorType() const { return majorType;}
/**
* @brief Get the Minor Type of the Service.
*
* @return std::string
*/
std::string getMinorType() const { return minorType;}
};
}; // namespace BC
#endif

View File

@@ -0,0 +1,134 @@
#ifndef __LIBBC_BC_MESSAGE_HPP__
#define __LIBBC_BC_MESSAGE_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief header file for the battle-com message class
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2018-11-23
* @copyright 2018 no yet defined
*/
#include <BC/BC.hpp>
#include <BC/transmittable.hpp>
#include <vector>
#include <memory>
namespace BC
{
/**
* @brief simple datatype to combine all information of a message distributed through the publish subscriber system of libbattle-com++
*/
class Message : public BC::transmittable
{
private:
/// vector representing the object to transmit
std::vector<unsigned char> data;
public:
/// the device id of the device/endpoint sending this Message
BC::DataTypes::deviceIdType sourceID;
/// the device id of the device/endpoint which should receive this Message BC::Constants::allDevices for broadcast
BC::DataTypes::deviceIdType destinationID = BC::Constants::allDevices;
/// the major type of the device/endpoint transmitting this message
BC::DataTypes::deviceMajorType srcMajorType;
/// the minor type of the device/endpoint transmitting this message
std::string srcMinorType;
/// the time this Message was transmitted by calling the publish method of the PubSubService
BC::DataTypes::BCTimeType transmissionTime;
/// the time this Message was received by calling the subscribed method
BC::DataTypes::BCTimeType receptionTime;
/// the domain this message resides in
std::string domain;
/// which topic does this message have ? helps identifying the transmitted datatype
std::string topic;
/**
* @brief set the data object to transmit through the battle-com service
*
* @prarma d - an object implementing the transmittable interface
*/
void setData(const BC::transmittable &d){data=d.toByteVector();}
/**
* @brief set the data object to transmit through the battle-com service
*
* @param d - the object already converted to a byte vector
*/
void setData(const std::vector<unsigned char> &d){data=d;}
/**
* @brief return the raw byte vector of the data object, required for data reception
*
* @return the std::vector<unsigned char>
*/
std::vector<unsigned char> getRawData() const {return data;}
Message() : sourceID(0), destinationID(0), srcMajorType(BC::DataTypes::UNKNOWN), srcMinorType(""),
transmissionTime(0), receptionTime(0), domain(""), topic(""){}
virtual ~Message()=default;
/**
* @brief Constructor for generationg a Message object from a received std::vector<unsiged char>
*
* @param v - the std::vector<unsigned char> representing a message object
*/
explicit Message(std::vector<unsigned char>);
/**
* @brief Copy constructor of the Message class
*
* creates a copy of the object, including copies of all data
*
* @param obj - the object from which to copy everything
*/
Message(const Message &obj);
/**
* @brief returns the size in bytes of the whole message
*
*/
const uint64_t size() const;
/**
* @brief converts the whole message information into a byte vector
*
* all information of the message class is converted into a byte vector for transmission
* through any kind of network.
*
* @param payload - returns the byte vector by call by reference
*/
std::vector<unsigned char> toByteVector() const override;
/**
* @brief fills the message class with information from the given byte vector
*
* the message is filled with all the information from the provided
* byte vector, except the data attribute. The byte vector identifying the
* data is returned to the caller. The caller has to call the appropriate
* factory to generate the right object
*
* @param payload - provides the byte vector representing the message
* @param data - returns the byte vector representing the data attribute by call by reference
*/
void fromByteVector(std::vector<unsigned char> &payload, std::vector<unsigned char> &data);
};
}; // namespace BC
#endif

View File

@@ -0,0 +1,63 @@
#ifndef __LIBBC_BC_PAYLOADS_HOTPLUGJOIN_HPP__
#define __LIBBC_BC_PAYLOADS_HOTPLUGJOIN_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the BC::Payloads::HotPlugJoin payload
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-02-03
* @copyright 2019 no yet defined
*/
#include <BC/BC.hpp>
#include <BC/transmittable.hpp>
#include <cstdint>
#include <vector>
namespace BC
{
namespace Payloads
{
/**
* @brief class representing the payload of a HotPlugJoin message
*
* the HotPlugJoin messages is transmitted by every PubSub Service after connection
* has been established to the underlying network/transport layer.
* It provides information about the type of service, the id and the underlying
* network/transport layer addresses.
*
*/
class HotPlugJoin : public BC::transmittable
{
public:
HotPlugJoin()=default;
/**
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
*/
explicit HotPlugJoin(std::vector<unsigned char> v);
/// the address of the underlying network layer used to join the network
unsigned char networkLayerAddress[16];
/// the address of the underlying transport layer used to join the network
uint32_t transportLayerAddress;
/**
* @brief converts the information of the class (the attributes) to a byte vector
*
* @param byteVector - returns a std::vector of bytes representing the class
*/
std::vector<unsigned char> toByteVector() const override;
};
}; //namespace Payloads
}; //namespace BC
#endif

View File

@@ -0,0 +1,63 @@
#ifndef __LIBBC_BC_PAYLOADS_HOTPLUGLEAVE_HPP__
#define __LIBBC_BC_PAYLOADS_HOTPLUGLEAVE_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the BC::Payloads::HotPlugLeave payload
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-02-05
* @copyright 2019 no yet defined
*/
#include <BC/BC.hpp>
#include <BC/transmittable.hpp>
#include <cstdint>
#include <vector>
namespace BC
{
namespace Payloads
{
/**
* @brief class representing the payload of a HotPlugLeave message
*
* the HotPlugLeave messages is transmitted by every PubSub Service before disconnecting
* from the network.
* It provides information about the type of service, the id and the underlying
* network/transport layer addresses.
*
*/
class HotPlugLeave : public BC::transmittable
{
public:
HotPlugLeave()=default;
/**
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
*/
explicit HotPlugLeave(std::vector<unsigned char> v);
/// the address of the underlying network layer used to join the network
unsigned char networkLayerAddress[16];
/// the address of the underlying transport layer used to join the network
uint32_t transportLayerAddress;
/**
* @brief converts the information of the class (the attributes) to a byte vector
*
* @param byteVector - returns a std::vector of bytes representing the class
*/
std::vector<unsigned char> toByteVector() const override;
};
}; //namespace Payloads
}; //namespace BC
#endif

View File

@@ -0,0 +1,63 @@
#ifndef __LIBBC_BC_PAYLOADS_PING_HPP__
#define __LIBBC_BC_PAYLOADS_PING_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the BC::Payloads::Ping payload
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-02-06
* @copyright 2019 no yet defined
*/
#include <BC/BC.hpp>
#include <BC/transmittable.hpp>
#include <cstdint>
#include <vector>
#include <random>
namespace BC
{
namespace Payloads
{
/**
* @brief class representing the payload of a Ping message
*
* the Ping messages is transmitted can be published to all or individual nodes.
* these nodes will answer with a Pong message
*
*/
class Ping : public BC::transmittable
{
public:
Ping();
/**
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
*/
explicit Ping(std::vector<unsigned char> v);
/// message id uniqly identifying one ping message
uint64_t messageID;
/// the sequence number of the ping
uint64_t sequenceNr;
/// the local clock ticks
uint64_t pingTime;
/**
* @brief converts the information of the class (the attributes) to a byte vector
*
* @param byteVector - returns a std::vector of bytes representing the class
*/
std::vector<unsigned char> toByteVector() const override;
};
}; //namespace Payloads
}; //namespace BC
#endif

View File

@@ -0,0 +1,60 @@
#ifndef __LIBBC_BC_PAYLOADS_PONG_HPP__
#define __LIBBC_BC_PAYLOADS_PONG_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the BC::Payloads::Pong payload
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-02-06
* @copyright 2019 no yet defined
*/
#include <BC/BC.hpp>
#include <BC/transmittable.hpp>
#include <cstdint>
#include <vector>
namespace BC
{
namespace Payloads
{
/**
* @brief class representing the payload of a Pong message
*
* the Pong messages is the reply to a ping message.
*
*/
class Pong : public BC::transmittable
{
public:
Pong()=default;
/**
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
*/
explicit Pong(std::vector<unsigned char> v);
/// message id uniqly identifying one ping message
uint64_t pingMessageID;
/// ping transmission time
BC::DataTypes::BCTimeType pingTransmissionTime;
/// the sequence number of the ping
uint64_t sequenceNr;
/**
* @brief converts the information of the class (the attributes) to a byte vector
*
* @param byteVector - returns a std::vector of bytes representing the class
*/
std::vector<unsigned char> toByteVector() const override;
};
}; //namespace Payloads
}; //namespace BC
#endif

View File

@@ -0,0 +1,137 @@
#ifndef __LIBBC_BC_SIMPLESERVICE_UDP_HPP__
#define __LIBBC_BC_SIMPLESERVICE_UDP_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the simpleservice udp class
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-02-01
* @copyright 2019 no yet defined
*/
#include <thread>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <list>
#include <mutex>
#include <condition_variable>
#include <BC/BC.hpp>
#include <BC/BasicService.hpp>
#include <BC/Message.hpp>
namespace BC {
class SimpleServiceUDPremoteClient
{
public:
unsigned short port;
BC::DataTypes::deviceIdType id;
};
/**
* @brief SimpleServiceUDP uses simple UDP broadcasts for distributing messages
*
* The SimpleServiceUDP is an implementation of a PubSub Service. It extends the BasicService
* and uses UDP broadcasts to distribute data. The constructor of the class
*
* This Service is only useful for debugging purposes running your network in a local LAN.
*/
class SimpleServiceUDP : public BC::BasicService
{
private:
/// the IP Address to send messages to
std::string dstIp;
/// the local source IP Address
std::string srcIp;
/// the udp port on which to broadcast and receive messages
unsigned short broadcastPort = 0;
/// the port we are listing on for messages, should normally be broadcastPort, but...
unsigned short localPort = 0;
/// the network socket to work on
int inetSocket = -1;
/// vector of local client ports we forward messages to
std::vector<SimpleServiceUDPremoteClient> clients;
/// mutex for exclusive access to the clients vector
std::mutex mutexClients;
protected:
/**
* @brief called from the parent class when the connect method is called
*
* Method is responsible for setting up the connection to the underlying
* transport layer protocol
*
*/
void derivedConnect() override;
/**
* @brief called from the parent class when the disconnect method is called
*
* Method is responsible for tearing down the connection to the underlying
* transport layer protocol
*
*/
void derivedDisconnect() override;
/**
* @brief called from the parent class in the receive thread
*
* Method is responsible for receiving data frames from the transport layer
*
* @see BasicService::receive
*/
void derivedReceive() override;
/**
* @brief called from the parent class after constructing a correct CMS::PubSub::Message
*
* Method is responsible for processing Service specific messages
*
* @param m - the received message
*
* @return true|false true = message has been processed, false = message has not been processed
*/
bool process(const BC::Message *m) override;
/**
* @brief called from the parent class to actually publish the message
*
* @param m - the messahe to publish
*/
void derivedPublish(BC::Message &m) override;
public:
/**
* @brief constructor for the SimpleServiceUDP class
*
* Constructor initializes the class
*
* @param myID - the id of the device connected to the network
* @param majorT - the majorType of device
* @param minorT - the minorType of the device
* @param port - the UDP port on which to transmit and receive broadcast messages
* @param dst - the broadcast IP address to send messages to
* @param src - the local IP Address we listen on, has to be on the same network of the broadcast address
*/
SimpleServiceUDP(const BC::DataTypes::deviceIdType &myID, const BC::DataTypes::deviceMajorType &majorT,
const std::string &minorT, const unsigned short &port, const std::string &dst,
const std::string &src) : BasicService(myID,majorT,minorT),
dstIp(dst), srcIp(src), broadcastPort(port){}
};
}; // namespace BC
#endif

View File

@@ -0,0 +1,13 @@
#ifndef __LIBBC_BC_ENDIANESS_HPP__
#define __LIBBC_BC_ENDIANESS_HPP__
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/*
* if we have big or little endian
*/
#cmakedefine IS_BIG_ENDIAN @IS_BIG_ENDIAN@
#endif

View File

@@ -0,0 +1,40 @@
#ifndef __LIBBC_BC_RECEIVEABLE_HPP__
#define __LIBBC_BC_RECEIVEABLE_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the receiveable interface
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-01-08
* @copyright 2019 no yet defined
*/
#include <BC/Message.hpp>
namespace BC {
/**
* @brief interface for a class which is able to receive messages via a battle-com service
*
*/
class receiveable
{
public:
/**
* @brief method called by the battle-com service after registering this class via the subscribe method
*
* Please make sure this method is finished as fast as possible. New messages can only be
* processes by the battle-com service after this method has finished!!!!
*
* @param m - pointer to the message received by the service, this class has to make
* sure that the message is deleted/freed after usage
*/
virtual void receive(BC::Message *m)=0;
};
}; // namespace BC
#endif

View File

@@ -0,0 +1,44 @@
#ifndef __LIBBC_BC_TRANSMITTABLE_HPP__
#define __LIBBC_BC_TRANSMITTABLE_HPP__
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/**
* @file
* @brief main header file for the transmittable interface
* @author Dominik Meyer <dmeyer@hsu-hh.de>
* @date 2019-01-08
* @copyright 2019 no yet defined
*/
#include <vector>
#include <functional>
namespace BC
{
/**
* @brief abstract class providing the interface for classes being transmittable through a network
*
* the developer has to make sure that the correct endianess is used in the toByteVector function
* and in the Factory for each Class
*/
class transmittable
{
public:
/**
* @brief converts the information of the class (the attributes) to a byte vector
*
* @param byteVector - returns a std::vector of bytes representing the class
*/
virtual std::vector<unsigned char> toByteVector() const = 0;
};
}; //namespace BC
#endif