Files
SimControl/libs/libbattle-com/include/BC/BasicService.hpp
Henry Winkel cc67e4840f Squashed 'libs/CommService/' content from commit 7ccc0fc
git-subtree-dir: libs/CommService
git-subtree-split: 7ccc0fce88bbc5969df060058cf0fb57abe3bcf9
2022-09-15 09:53:53 +02:00

284 lines
9.1 KiB
C++

#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