This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,25 @@
#pragma once
#include <ov_common_defines.h>
#if defined Communication_Shared
# if defined TARGET_OS_Windows
# define Communication_API_Export __declspec(dllexport)
# define Communication_API_Import __declspec(dllimport)
# elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
# define Communication_API_Export __attribute__((visibility("default")))
# define Communication_API_Import __attribute__((visibility("default")))
# else
# define Communication_API_Export
# define Communication_API_Import
# endif
#else
# define Communication_API_Export
# define Communication_API_Import
#endif
#if defined Communication_Exports
# define Communication_API Communication_API_Export
#else
# define Communication_API Communication_API_Import
#endif
@@ -0,0 +1,323 @@
#pragma once
#include <socket/IConnection.h>
#include "defines.h"
#include "ovCMessagingProtocol.h"
namespace Communication {
/**
* \brief The purpose of this class is to provide a communication protocol to exchange EBML between a client and a server.
*/
class Communication_API CMessaging
{
public:
/**
* \brief Library error codes
*/
enum ELibraryError
{
NoError = 0,
Socket_NotConnected = 1,
Socket_FailedToConnect = 2,
Socket_ReceiveBufferFail = 3,
Socket_SendBufferFail = 4,
Socket_NoIncomingClientConnection = 6,
Socket_NotReadyToSend = 7,
Socket_NoDataReceived = 8,
Socket_FailedCloseClientConnection = 10,
Socket_FailedToCloseConnection = 11,
Socket_FailedConnectClient = 12,
Socket_ClientAlreadyConnected = 13,
Deserialize_BufferTooSmall = 30,
Deserialize_Header = 31,
Deserialize_ProtocolVersionMessage = 32,
Deserialize_BoxDescriptionMessage = 33,
Deserialize_EBMLMessage = 34,
Deserialize_EndMessage = 35,
Deserialize_ErrorMessage = 36,
Deserialize_LogMessage = 37,
Deserialize_AuthenticationMessage = 38,
Deserialize_MessageTypeNotSupported = 39,
BoxDescriptionAlreadyReceived = 60,
BoxDescriptionNotReceived = 61,
BadAuthenticationReceived = 70,
NoAuthenticationReceived = 71,
ThreadJoinFailed = 80
};
CMessaging();
virtual ~CMessaging();
/**
* \brief Get the code of the last error produced by the API
*
* \retval Error code
*/
ELibraryError getLastError() const;
/**
* \brief Give a short description of an error.
*
* \param error the error code
*
* \return Description of the error.
*/
static std::string getErrorString(ELibraryError error);
/**
* \brief Check that the socket is connected.
*
* \retval True if the socket is connected.
* \retval False if the socket is not connected.
*/
bool isConnected() const;
/**
* \brief Check that the synchronization is in error state.
*
* \retval True if the synchronization is in error state.
* \retval False if the synchronization is ok.
*/
bool isInErrorState() const;
/**
* \brief Set the connection ID to a new value
* \param connectionID The connection Id to set
*/
void setConnectionID(const std::string& connectionID) const;
/**
* \brief Check that a End message was received.
*
* \retval True if the end message from the client is received.
* \retval False if the end message from the client is not received.
*/
virtual bool isEndReceived();
/**
* \brief Get the time.
*/
virtual uint64_t getTime();
protected:
/**
* \brief Push a message to the send buffer.
* The message will be really sent in the socket in the next synchronization.
*
* \param message The message to send.
*
* \retval True if it succeeds.
* \retval False if library is in error state.
*/
bool pushMessage(const Message& message) const;
/**
* \brief Set the last error code.
*
* \param libraryError The error
*
* \sa getLastError
*/
void setLastError(ELibraryError libraryError) const;
/**
* \brief Provide the connection to the base class to communicate.
*
* \param connection The connection
*/
void setConnection(Socket::IConnection* connection) const;
/**
* \brief Start a thread that will push the outgoing data, pull and process the incoming data.
* This sync will be stopped in cases:
* - An error raised
* - stopSyncing() function was called.
*
* \retval True if it succeeds.
* \retval False if an error occured.
*
* \sa stopSyncing
*/
bool startSyncing();
/**
* \brief Request to stop the sync and stop the thread.
*
* \retval True if it succeeds.
* \retval False if an error occured.
*
* \sa startSyncing
*/
bool stopSyncing() const;
/**
* @brief Get the oldest authentication message
* @param id[out] Identifier of the message
* @param connectionID[out] Connection Id
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popAuthentication(uint64_t& id, std::string& connectionID);
/**
* @brief Get the oldest box description message
* @param id[out] Identifier of the message
* @param boxDescription[out] Descriptor of the box
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popBoxDescriptions(uint64_t& id, BoxDescriptionMessage& boxDescription);
/**
* @brief popCommunicationProtocolVersion
* @param id[out] Identifier of the message
* @param majorVersion[out] major version of the protocol
* @param minorVersion[out] minor version of the protocol
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popCommunicationProtocolVersion(uint64_t& id, uint8_t& majorVersion, uint8_t& minorVersion);
/**
* @brief Pop the oldest EBML message from the queue
* @param id[out] Identifier of the message
* @param index[out] Input index to which the EBML should be directed
* @param startTime[out] Start time of the buffer
* @param endTime[out] End time of the buffer
* @param ebml[out] The encoded EBML buffer
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popEBML(uint64_t& id, size_t& index, uint64_t& startTime, uint64_t& endTime, std::shared_ptr<const std::vector<uint8_t>>& ebml);
/**
* @brief Pop the oldest log message from the queue
* @param id[out] Identifier of the message
* @param type[out] Log level of the message
* @param message[out] Message text
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popLog(uint64_t& id, ELogLevel& type, std::string& message);
/**
* @brief Pop the oldest error message from the queue
* @param id[out] Identifier of the message
* @param type[out] Error code
* @param guiltyId[out] If of the sent message that caused this error
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popError(uint64_t& id, EError& type, uint64_t& guiltyId);
/**
* @brief Get the oldes End message
* @param id[out] Identifier of the message
* @return true if a message was popped, false if the queue is empty
*/
virtual bool popEnd(uint64_t& id);
/**
* @brief Reset the library state. Stop sending and receiving buffers, disconnect
* and empty all buffers.
*/
void reset() const;
/**
* \brief Checks if a sync message was received and reset it if it was.
*
* This method should be used in a busy loop to check if the other
* party has finished processing all of the data.
*
* From the external program standpoint this method will return true
* when the box has finished sending all of the data that has to be
* processed in one bulk.
*
* From the box standpoint, this means that the external program has
* finished processing and sending all of the data that the box has
* sent.
*
* \retval True if a sync message is received.
* \retval False if no sync message was received.
*/
virtual bool waitForSyncMessage();
private:
/**
* \brief Receive all the available data from the socket and insert it in the rcv buffer.
*
* \retval True if it succeeds.
* \retval False if an error occured.
* Library errors: TODO
*
* \sa push
*/
bool pull() const;
/**
* \brief Send all the data to the socket.
*
* \retval True if it succeeds.
* \retval False if an error occured.
* Library errors:
* - Socket_NotConnected
*
*
* \sa push
*/
bool push() const;
/**
* \brief Process incoming data, unpack it and put messages in queues.
* It use processBuffer.
*
* \retval True if it succeeds.
* \retval False if an error occured.
* Library errors: Error from processBuffer
*
* \sa processBuffer
*/
bool processIncomingMessages() const;
/**
* \brief Process buffer, pack it and put messages in queues.
*
* \param buffer Buffer with the incoming serialized data.
* \param[out] byteRead Number of bytes read and processed.
*
* \retval True if it succeeds.
* \retval False if an error occured.
* Library errors:
* - Deserialize_Header
* - Deserialize_AuthenticationMessage
* - Deserialize_ProtocolVersionMessage
* - Deserialize_BoxDescriptionMessage
* - Deserialize_EBMLMessage
* - Deserialize_LogMessage
* - Deserialize_ErrorMessage
* - Deserialize_MessageTypeNotSupported
*
* \sa processIncomingMessages
*/
bool processBuffer(const std::vector<uint8_t>& buffer, size_t& byteRead) const;
/**
* \brief Sync fucntion that is used in a thread to pull, push and process the incoming data.
*
* \retval True if it succeeds.
* \retval False if an error occured.
* Library errors: Errors from processIncomingMessages(), push() or pull()
*
* \sa pull
* \sa push
* \sa processIncomingMessages
*/
void sync() const;
public:
static const uint8_t s_CommunicationProtocol_MajorVersion = 1;
static const uint8_t s_CommunicationProtocol_MinorVersion = 1;
protected:
struct SMessagingImpl;
SMessagingImpl* impl = nullptr;
};
} // namespace Communication
@@ -0,0 +1,218 @@
#pragma once
#include "defines.h"
#include "ovCMessaging.h"
#include "socket/IConnectionClient.h"
namespace Communication {
class Communication_API MessagingClient : public CMessaging
{
public:
/**
* \brief Default constructor.
*/
MessagingClient();
/**
* \brief Destructor.
*/
~MessagingClient() override;
/**
* \brief Connect to a server.
*
* \param uri URI of the server.
* \param port The port.
*
* \retval True if it succeeds.
* \retval False there is no available error.
* Library errors:
* - FailedToConnect
* - NotConnected
* - NotReadyToSend
*
* \sa close
*/
bool connect(const std::string& uri, const size_t port);
/**
* \brief Closes the connection to the server.
*
* \retval True if it succeeds.
* \retval False there is no available error.
* Library errors:
* - NotConnected
* - FailedToCloseConnection
*
* \sa getLastError
*/
bool close() const;
/**
* \brief Return the number of box information's parameters available.
*
* \return The number of parameters available.
*
* \sa getParameter
*/
size_t getParameterCount() const;
/**
* \brief Return the number of box information's input available.
*
* \return The number of input available.
*
* \sa getInput
*/
size_t getInputCount() const;
/**
* \brief Return the number of output of the box information, available.
*
* \return The number of output available.
*
* \sa getOutput
*/
size_t getOutputCount() const;
/**
* \brief Get parameter information.
*
* \param i The index.
* \param[out] id The id
* \param[out] type The type (corresponding to the OpenViBE CIdentifier)
* \param[out] name Name
* \param[out] value Value (to convert accordinf to the type)
*
* \retval True if it succeeds.
* \retval False if the index is out of range.
*/
bool getParameter(size_t i, uint64_t& id, uint64_t& type, std::string& name, std::string& value) const;
/**
* \brief Get input information.
*
* \param i The index.
* \param[out] id The id
* \param[out] type The type (corresponding to the OpenViBE CIdentifier)
* \param[out] name Name
*
* \retval True if it succeeds.
* \retval False if the index is out of range.
*
* \sa getInputCount
*/
bool getInput(size_t i, uint64_t& id, uint64_t& type, std::string& name) const;
/**
* \brief Get input information.
*
* \param i The index.
* \param[out] id The id
* \param[out] type The type (corresponding to the OpenViBE CIdentifier)
* \param[out] name Name
*
* \retval True if it succeeds.
* \retval False if the index is out of range.
*
* \sa getOutputCount
*/
bool getOutput(size_t i, uint64_t& id, uint64_t& type, std::string& name) const;
/**
* \brief Get the oldest error message, if available.
*
* \param packetId
* \param[out] type The error's type.
* \param[out] guiltyId Identifier of the guilty message
*
* \retval True if it succeeds.
* \retval False there is no available error.
*/
bool popError(uint64_t& packetId, EError& type, uint64_t& guiltyId) override;
/**
* \brief Get the oldest EBML message, if available.
*
* \param packetId
* \param[out] index Box input index.
* \param[out] startTime The start time.
* \param[out] endTime The end time.
* \param[out] ebml The EBML vector.
*
* \retval True if it succeeds.
* \retval False there is no available error.
*/
bool popEBML(uint64_t& packetId, size_t& index, uint64_t& startTime, uint64_t& endTime, std::shared_ptr<const std::vector<uint8_t>>& ebml) override;
/**
* \brief Push a log message to the server.
*
* \param logLevel The log level.
* \param log The log string message.
*
* \retval True if it succeeds.
* \retval False there is no available error.
* Library errors:
* - NotConnected
* - NotReadyToSend
*
* \sa getLastError
*/
bool pushLog(ELogLevel logLevel, const std::string& log) const;
/**
* \brief Pushes an ebml.
*
* \param index Index of the box output.
* \param startTime The start time.
* \param endTime The endtime.
* \param ebml The ebml vector.
*
* \retval True if it succeeds.
* \retval False there is no available error.
* Library errors:
* - NotConnected
* - NotReadyToSend
*
* \sa getLastError
*/
bool pushEBML(size_t index, uint64_t startTime, uint64_t endTime, const std::shared_ptr<const std::vector<uint8_t>>& ebml) const;
/**
* \brief Push Sync message to the server.
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool pushSync() const;
/**
* \brief Check if a sync message is received.
*
* \retval True if a sync message is received.
* \retval False if no sync message was received.
*/
bool waitForSyncMessage() override;
private:
/**
* \brief Pushes an authentication message).
*
* \param connectionID The connection identifier.
*
* \retval True if it succeeds.
* \retval False there is no available error.
* Library errors:
* - NotConnected
* - NotReadyToSend
*/
bool pushAuthentication(const std::string& connectionID) const;
Socket::IConnectionClient* m_Client = nullptr;
bool m_BoxDescriptionReceived = false;
};
} // namespace Communication
@@ -0,0 +1,424 @@
#pragma once
#include "defines.h"
#include <cstdint>
#include <vector>
#include <memory>
#include <string>
#include <limits>
namespace Communication {
/**
* \brief Log level used by the client to log information in the server side
*/
enum ELogLevel : uint8_t
{
LogLevel_Info = 1,
LogLevel_Warning = 2,
LogLevel_Error = 3,
LogLevel_Fatal = 4,
LogLevel_Max = 5,
LogLevel_Unknown = 0xFF
};
/**
* \brief Values that represent errors.
*/
enum EError : uint16_t
{
Error_AuthenticationFail = 1,
Error_AuthenticationRequested = 2,
Error_InvalidOutputIndex = 3,
Error_BadCommunicationProtocol = 4,
Error_InvalidEBML = 5,
Error_InvalidLogLevel = 6,
Error_InvalidMessageType = 7,
Error_BadMessage = 8,
Error_Max = 9,
Error_Unknown = 0xFF
};
/**
* \brief Message type
*/
enum EMessageType : uint8_t
{
MessageType_Authentication = 0,
MessageType_ProtocolVersion = 1,
MessageType_BoxInformation = 2,
MessageType_EBML = 3,
MessageType_Log = 4,
MessageType_End = 5,
MessageType_Error = 6,
MessageType_Time = 7,
MessageType_Sync = 8,
MessageType_Max = 9,
MessageType_Unknown = 0xFF,
};
/**
* \brief A packet part is a part of a packet compound by an Header and a Message.
*/
class Communication_API CPacketPart
{
public:
virtual ~CPacketPart() {}
/**
* \brief Provide array of bytes that represent the object.
*
* \return A vector with the serialized information of the message that respect the communication protocol.
*
* \sa fromBytes
*/
virtual std::vector<uint8_t> toBytes() const = 0;
/**
* \brief Transform bytes vector into an object.
*
* \param buffer The buffer.
* \param [in,out] bufferIndex Zero-based index of the buffer.
*
* \retval True if it succeeds
* \retval False if it fails.
*
* \sa toBytes
*/
virtual bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) = 0;
/**
* \brief Query if this object is valid.
*
* \retval True if it is valid.
* \retval False if it is invalid.
*/
bool isValid() const { return m_isValid; }
protected:
bool m_isValid = false;
};
/**
* \brief A message is the second part of a packet after the header.
*/
class Message : public CPacketPart
{
public:
virtual EMessageType getMessageType() const = 0;
};
/**
* \brief A header is associated to a message. It give information about the message, like the type and the size.
*/
class Header final : CPacketPart
{
public:
Header();
Header(EMessageType type, uint64_t id, size_t size);
std::vector<uint8_t> toBytes() const override;
void setId(const uint64_t id) { m_id = id; }
uint64_t getId() const { return m_id; }
EMessageType getType() const { return m_type; }
size_t getSize() const { return m_size; }
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
private:
EMessageType m_type;
uint64_t m_id = 0;
size_t m_size = 0;
static const size_t TYPE_SIZE = sizeof(EMessageType);
static const size_t ID_SIZE = sizeof(uint64_t);
static const size_t SIZE_SIZE = sizeof(size_t);
static const size_t TYPE_INDEX = 0;
static const size_t ID_INDEX = TYPE_INDEX + TYPE_SIZE;
static const size_t SIZE_INDEX = ID_INDEX + ID_SIZE;
static const size_t MINIMUM_SIZE = TYPE_SIZE + ID_SIZE + SIZE_SIZE;
};
/**
* \brief Represent an Authentication message.
*/
class AuthenticationMessage final : public Message
{
public:
AuthenticationMessage() { m_isValid = false; }
AuthenticationMessage(const std::string& connectionID) : m_connectionID(connectionID) { m_isValid = true; }
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override { return MessageType_Authentication; }
std::string getConnectionID() const { return m_connectionID; }
private:
static const size_t SIZE_SIZE = sizeof(size_t);
static const size_t SIZE_INDEX = 0;
static const size_t CONNECTION_ID_INDEX = SIZE_INDEX + SIZE_SIZE;
static const size_t MINIMUM_SIZE = SIZE_SIZE;
std::string m_connectionID;
};
/**
* \brief This message is used to inform the server or the client about the current communication protocol version used.
*/
class CommunicationProtocolVersionMessage final : public Message
{
public:
CommunicationProtocolVersionMessage() { m_isValid = false; }
CommunicationProtocolVersionMessage(const uint8_t majorVersion, const uint8_t minorVersion) : m_minorVersion(minorVersion), m_majorVersion(majorVersion)
{
m_isValid = true;
}
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override { return MessageType_ProtocolVersion; }
uint8_t getMajorVersion() const { return m_majorVersion; }
uint8_t getMinorVersion() const { return m_minorVersion; }
private:
uint8_t m_minorVersion = 0;
uint8_t m_majorVersion = 0;
static const size_t MAJOR_SIZE = sizeof(uint8_t);
static const size_t MINOR_SIZE = sizeof(uint8_t);
static const size_t MAJOR_INDEX = 0;
static const size_t MINOR_INDEX = MAJOR_INDEX + MAJOR_SIZE;
static const size_t MINIMUM_SIZE = MAJOR_SIZE + MINOR_SIZE;
};
/**
* \brief InputOutput class describes the input or output of a box.
*/
class InputOutput final : public CPacketPart
{
public:
InputOutput();
InputOutput(uint64_t id, size_t type, const std::string& name);
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
uint64_t getId() const { return m_id; }
size_t getType() const { return m_type; }
std::string getName() const { return m_name; }
private:
uint64_t m_id = 0;
size_t m_type = 0;
std::string m_name;
static const size_t ID_SIZE = sizeof(uint64_t);
static const size_t TYPE_SIZE = sizeof(size_t);
static const size_t NAME_SIZE_SIZE = sizeof(size_t);
static const size_t ID_INDEX = 0;
static const size_t TYPE_INDEX = ID_INDEX + ID_SIZE;
static const size_t NAME_SIZE_INDEX = TYPE_INDEX + TYPE_SIZE;
static const size_t NAME_INDEX = NAME_SIZE_INDEX + NAME_SIZE_SIZE;
static const size_t MINIMUM_SIZE = ID_SIZE + TYPE_SIZE + NAME_SIZE_SIZE;
};
class Parameter final : public CPacketPart
{
public:
Parameter();
Parameter(uint64_t id, size_t type, const std::string& name, const std::string& value);
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
uint64_t getId() const { return m_id; }
size_t getType() const { return m_type; }
std::string getName() const { return m_name; }
std::string getValue() const { return m_value; }
private:
uint64_t m_id = 0;
size_t m_type = 0;
std::string m_name;
std::string m_value;
static const size_t ID_SIZE = sizeof(uint64_t);
static const size_t TYPE_SIZE = sizeof(size_t);
static const size_t NAME_SIZE_SIZE = sizeof(size_t);
static const size_t VALUE_SIZE_SIZE = sizeof(size_t);
static const size_t ID_INDEX = 0;
static const size_t TYPE_INDEX = ID_INDEX + ID_SIZE;
static const size_t NAME_SIZE_INDEX = TYPE_INDEX + TYPE_SIZE;
static const size_t VALUE_SIZE_INDEX = NAME_SIZE_INDEX + NAME_SIZE_SIZE;
static const size_t NAME_INDEX = VALUE_SIZE_INDEX + VALUE_SIZE_SIZE;
static const size_t MINIMUM_SIZE = ID_SIZE + TYPE_SIZE + NAME_SIZE_SIZE + VALUE_SIZE_SIZE;
};
/**
* \brief This message contains information about the box used in the NeuroRT pipeline.
* This message is sent by the server and received by the client.
*/
class BoxDescriptionMessage final : public Message
{
public:
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override;
bool addInput(uint64_t id, size_t type, const std::string& name);
bool addOutput(uint64_t id, size_t type, const std::string& name);
bool addParameter(uint64_t id, size_t type, const std::string& name, const std::string& value);
const std::vector<InputOutput>* getInputs() const { return &m_inputs; }
const std::vector<InputOutput>* getOutputs() const { return &m_outputs; }
const std::vector<Parameter>* getParameters() const { return &m_parameters; }
private:
std::vector<InputOutput> m_inputs;
std::vector<InputOutput> m_outputs;
std::vector<Parameter> m_parameters;
static const size_t N_INPUT_SIZE = sizeof(size_t);
static const size_t N_OUTPUT_SIZE = sizeof(size_t);
static const size_t N_PARAMETER_SIZE = sizeof(size_t);
static const size_t N_INPUT_INDEX = 0;
static const size_t N_OUTPUT_INDEX = N_INPUT_INDEX + N_INPUT_SIZE;
static const size_t N_PARAMETER_INDEX = N_OUTPUT_INDEX + N_OUTPUT_SIZE;
static const size_t MINIMUM_SIZE = N_INPUT_SIZE + N_OUTPUT_SIZE + N_PARAMETER_SIZE;
};
/**
* \brief Log message is a way to communicate information from the client to the server.
*/
class LogMessage final : public Message
{
public:
LogMessage();
LogMessage(ELogLevel type, const std::string& message);
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override { return MessageType_Log; }
ELogLevel getType() const { return m_type; }
std::string getMessage() const { return m_message; }
private:
ELogLevel m_type;
std::string m_message;
static const size_t TYPE_SIZE = sizeof(ELogLevel);
static const size_t SIZE_SIZE = sizeof(size_t);
static const size_t TYPE_INDEX = 0;
static const size_t SIZE_INDEX = TYPE_INDEX + TYPE_SIZE;
static const size_t NAME_INDEX = SIZE_INDEX + SIZE_SIZE;
static const size_t MINIMUM_SIZE = TYPE_SIZE + SIZE_SIZE;
};
/**
* \brief EBML message is used to send EBML data.
*/
class EBMLMessage final : public Message
{
public:
EBMLMessage();
EBMLMessage(size_t index, uint64_t startTime, uint64_t endTime, const std::shared_ptr<const std::vector<uint8_t>>& ebml);
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override { return MessageType_EBML; }
size_t getIndex() const { return m_ioIdx; }
uint64_t getStartTime() const { return m_startTime; }
uint64_t getEndTime() const { return m_endTime; }
std::shared_ptr<const std::vector<uint8_t>> getEBML() const { return m_EBML; }
private:
size_t m_ioIdx = 0;
uint64_t m_startTime = 0;
uint64_t m_endTime = 0;
std::shared_ptr<const std::vector<uint8_t>> m_EBML;
static const size_t IO_INDEX_SIZE = sizeof(size_t);
static const size_t START_TIME_SIZE = sizeof(uint64_t);
static const size_t END_TIME_SIZE = sizeof(uint64_t);
static const size_t SIZE_SIZE = sizeof(size_t);
static const size_t IO_INDEX_INDEX = 0;
static const size_t START_TIME_INDEX = IO_INDEX_INDEX + IO_INDEX_SIZE;
static const size_t END_TIME_INDEX = START_TIME_INDEX + START_TIME_SIZE;
static const size_t SIZE_INDEX = END_TIME_INDEX + END_TIME_SIZE;
static const size_t EBML_INDEX = SIZE_INDEX + SIZE_SIZE;
static const size_t MINIMUM_SIZE = IO_INDEX_SIZE + START_TIME_SIZE + END_TIME_SIZE + SIZE_SIZE;
};
/**
* \brief Error message is used to alert the client that the server raise an error due to a message by the client.
*/
class ErrorMessage final : public Message
{
public:
ErrorMessage() : m_type(Error_Unknown), m_guiltyId(std::numeric_limits<decltype(m_guiltyId)>::max()) {}
ErrorMessage(const EError error, const uint64_t guiltyId) : m_type(error), m_guiltyId(guiltyId) {}
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override { return MessageType_Error; }
EError getType() const { return m_type; }
uint64_t getGuiltyId() const { return m_guiltyId; }
private:
EError m_type;
uint64_t m_guiltyId = 0;
static const size_t TYPE_SIZE = sizeof(EError);
static const size_t GUILTY_ID_SIZE = sizeof(uint64_t);
static const size_t TYPE_INDEX = 0;
static const size_t GUILTY_ID_INDEX = TYPE_INDEX + TYPE_SIZE;
static const size_t MINIMUM_SIZE = GUILTY_ID_SIZE + TYPE_SIZE;
};
/**
* \brief End message can be sent by the server or/and by the client to inform that the processing is stopped and the connection will be closed.
*/
class EndMessage final : public Message
{
public:
EndMessage() {}
std::vector<uint8_t> toBytes() const override { return std::vector<uint8_t>(); }
bool fromBytes(const std::vector<uint8_t>& /*buffer*/, size_t& /*index*/) override { return false; }
EMessageType getMessageType() const override { return MessageType_End; }
};
/**
* \brief Time messages are only sent by the server to inform the client about the current time of the pipeline.
*/
class TimeMessage final : public Message
{
public:
TimeMessage(const uint64_t time = 0) : m_time(time) {}
std::vector<uint8_t> toBytes() const override;
bool fromBytes(const std::vector<uint8_t>& buffer, size_t& bufferIndex) override;
EMessageType getMessageType() const override { return MessageType_Time; }
uint64_t getTime() const { return m_time; }
private:
uint64_t m_time = 0;
static const size_t TIME_SIZE = sizeof(uint64_t);
static const size_t TIME_INDEX = 0;
static const size_t MINIMUM_SIZE = TIME_SIZE;
};
/**
* \brief Sync message can be sent by the server or/and by the client to inform that it's waiting the other part.
*/
class SyncMessage final : public Message
{
public:
SyncMessage() {}
std::vector<uint8_t> toBytes() const override { return std::vector<uint8_t>(); }
bool fromBytes(const std::vector<uint8_t>& /*buffer*/, size_t& /*index*/) override { return false; }
EMessageType getMessageType() const override { return MessageType_Sync; }
};
} // namespace Communication
@@ -0,0 +1,185 @@
#pragma once
#include "defines.h"
#include "ovCMessaging.h"
#include "socket/IConnectionServer.h"
namespace Communication {
class Communication_API MessagingServer : public CMessaging
{
public:
/**
* \brief Default constructor.
*/
MessagingServer() : CMessaging(), m_Server(Socket::createConnectionServer()) {}
/**
* \brief Destructor.
*/
~MessagingServer() override;
/**
* \brief Start listening on the given port.
*
* \param port The port.
*
* \retval True if listenning
* \retval False if not.
*
* \sa close
*/
bool listen(const size_t port) const { return m_Server->listen(port); }
/**
* \brief Close the connection
* *
* \retval True if it succeeds
* \retval False if it fails.
*/
bool close();
/**
* \brief Accepts one incoming connection.
*
* \retval True if it succeeds.
* \retval False if it fails.
*/
bool accept();
/**
* \brief Returns the port on the one the server is listening.
* This is useful if you set the port to '0'.
* \param port [out]: port on the one the server is listening
*/
bool getSocketPort(size_t& port) const { return m_Server->getSocketPort(port); }
/**
* \brief Adds a parameter in the Box Information.
*
* \param id The parameter's identifier.
* \param type The parameter's type. Use OpenViBE::CIdentifier.
* \param name The parameter's name.
* \param value The parameter's value. A string.
*
* \retval True if it succeeds.
* \retval False if an output with the given id already exists.
*
* \sa addInput
* \sa addOutput
*/
bool addParameter(uint64_t id, size_t type, const std::string& name, const std::string& value) const;
/**
* \brief Adds an input in the box Information.
*
* \param id The input's identifier.
* \param type The input's type. Use OpenViBE::CIdentifier.
* \param name The input's name.
*
* \retval True if it succeeds.
* \retval False if an output with the given id already exists.
*
* \sa addParameter
* \sa addOutput
*/
bool addInput(uint64_t id, size_t type, const std::string& name) const;
/**
* \brief Adds an output in the box information.
*
* \param id The output's identifier.
* \param type The output's type. Use OpenViBE::CIdentifier.
* \param name The output's name.
*
* \retval True if it succeeds.
* \retval False if an output with the given id already exists.
*
* \sa addParameter
* \sa addInput
*/
bool addOutput(uint64_t id, size_t type, const std::string& name) const;
/**
* \brief Get the log message received from the client.
*
* \param[out] packetId Packet id
* \param[out] type Level of the log
* \param[out] message Log message
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool popLog(uint64_t& packetId, ELogLevel& type, std::string& message) override;
/**
* \brief Get the EBML data received from the client.
*
* \param[out] packetId Packet id
* \param[out] index Output index
* \param[out] startTime Chunk time in OpenViBE 32:32 format
* \param[out] endTime Chunk time in OpenViBE 32:32 format
* \param[out] ebml EBML data
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool popEBML(uint64_t& packetId, size_t& index, uint64_t& startTime, uint64_t& endTime, std::shared_ptr<const std::vector<uint8_t>>& ebml) override;
/**
* \brief Push Error message to the client
*
* \param error Error code
* \param guiltyId Id of the received message that raised the error.
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool pushError(EError error, uint64_t guiltyId) const;
/**
* \brief Push EBML message to the client
*
* \param index Index of the input.
* \param startTime Chunk time in OpenViBE 32:32 format
* \param endTime Chunk time in OpenViBE 32:32 format
* \param ebml EBML data
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool pushEBML(size_t index, uint64_t startTime, uint64_t endTime, const std::shared_ptr<const std::vector<uint8_t>>& ebml) const;
/**
* \brief Push Time message to the client
*
* \param time Time in OpenViBE 32:32 format
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool pushTime(uint64_t time) { return this->pushMessage(TimeMessage(time)); }
/**
* \brief Push Sync message to the client
*
* \retval True if it succeeds.
* \retval False if the library is in error state.
*/
bool pushSync() { return this->pushMessage(SyncMessage()); }
/**
* \brief Check if a sync message is received.
*
* \retval True if a sync message is received.
* \retval False if no sync message was received.
*/
bool waitForSyncMessage() override { return CMessaging::waitForSyncMessage(); }
private:
Socket::IConnectionServer* m_Server = nullptr; //< Server connection
Socket::IConnection* m_Client = nullptr;
};
} // namespace Communication