#pragma once #include "AftrConfig.h" #ifdef AFTR_CONFIG_USE_BOOST #include "NetMessengerMessageQueue.h" #include #include #include namespace Aftr { //SLN, this class is DEPRECATED and only left for older modules that may still use it... It will be removed in the future. // PREFER TO USE NetMessengerServerUDPConn or NetMessengerServerUDPConnT instead /// This can only send messages UP TO the maximum size of a UDP payload. No fragmentation occurs. If the payload /// is larger than UDP payload, a boost error (typically system: 1784) will result. class NetMessengerServerSessionUDP { public: //This constructor is used by the NetMessengerServerListener to establish a new session between an initiating //remote client and this server. NetMessengerServerSessionUDP( boost::asio::io_context& io_context, NetMessengerMessageQueue* servListenerRecvQueue ); //This constructor can be used by a user to establish a session to a remote NetMessengerServerListener (a remote //instance of the AftrBurner engine running. NetMessengerServerSessionUDP( const std::string& host, const std::string& port, boost::asio::io_context& io_context, NetMessengerMessageQueue* recvQueue ); ~NetMessengerServerSessionUDP(); boost::asio::ip::udp::socket& getSocket(); bool isStarted() { return this->IsStarted; } //Ownership is transferred to the NetMessengerServerSessionUDP, the message will be destroyed by this instance. bool enqueueMsgToSend( std::shared_ptr msg ); void start(); bool connectSessionToHost( const std::string& host, const std::string& port ); bool reConnectSessionToHost(); std::string toString() const; //When doing async sending and receiving, notifying the user of a send/recv error is not possible //as the time the user queues the request to send or recv. What we do instead, if an send or recv //error occurs, we set these values to non-null. The user can then check these flags to see if an //error has occurred and choose to take action at that point, such as by trying to reconnect to the //endpoint. //These two get Error msgs will return the latest error and THEN reset the error_code back to none. boost::system::error_code getLastSendError(); boost::system::error_code getLastRecvError(); private: bool isValidHeader( unsigned int headerCode ) const; //host and port are only used for the second constructor when the session is used to initiate a new connection (SYN) //versus serving as receiver of a new connection (the remote endpoint (SYN ACK)). std::string host{ "127.0.0.1" }; std::string port{ "12683" }; boost::asio::ip::udp::socket sock; static const unsigned int HEADER_LEN_BYTES = 8; ///< Header length of a message in bytes (32-bits) std::vector< char > recvBuff; std::array recvHeader{ 0 }; void onRecvHeader( const boost::system::error_code& error, size_t bytesReceived ); void onRecvBody( const boost::system::error_code& error, size_t bytesReceived ); //This method is only execute inside asio handler via this->strand executor. //This method adds msg to sendQueue. If no existing messages are being sent, it will //begin an writing within the strand's asio context. void enqueueMsgHandler( std::shared_ptr msg ); //This method is only execute inside asio handler via this->strand executor. //This method is called by enqueueMsgHandler only to begin writing queued messages within //the strand's asio context. This will repeatedly invoke until the send queue is empty. void sendMsgHandler(); void onSentMsg( char* binDat, const boost::system::error_code& error, size_t bytes_transferred ); bool IsStarted = false; ///< Initially set to false, gets set to True once this->start() has been invoked and async operations have begun unsigned int currHeaderCode = 0; ///< Set by onRecvHeader, read by onRecvBody, indicates NetMsg subclass to instantiate unsigned int currMsgLenBytes = 0; ///< Set by onRecvHeader, read by onRecvBody, indicates length of binary data for the current message //Thread safe queue of pending messages to send to endpoint associated with this session //Only thread safe when the user calls lock() prior to using it and unlock after using it. NetMessengerMessageQueueT< std::shared_ptr > sendQueue; /** Pointer to corresponding NetMessengerServerListener's queue, which holds all newly received (and fully instantiated) messages until the engine processes their callbacks (NetMsg::onMessageArrived()). The callback is invoked when then engine calls NetMessengerServer::onUpdate(), which is typically in the GLView::onUpdateWorld(). This recvQueue is NOT owned by this instance, do not delete. This queue is actually owned by the corresponding NetMessengerServerListener which spawned this session's existence. */ NetMessengerMessageQueue* recvQueue = nullptr; boost::asio::io_context::strand writeStrand; // A strand guarantees that no two handlers execute concurrently. boost::system::error_code lastSendError; boost::system::error_code lastRecvError; }; } //namespace Aftr #endif