#pragma once #include #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>& 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& 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