#pragma once #include namespace sp { namespace io { class TcpListener; class SocketError : public std::exception { private: std::string m_Error; public: SocketError(std::string&& a_Msg) : m_Error(std::move(a_Msg)) {} virtual const char* what() const noexcept override { return m_Error.c_str(); } }; class TcpSocket : public sp::IoInterface { public: using SocketHandle = int; /** * \enum Status * \brief Describes the state of a socket */ enum class Status { /** The socket is connected */ Connected, /** The socket is not connected */ Disconnected, /** Something bad happened */ Error, }; TcpSocket(); TcpSocket(const std::string& a_Host, std::uint16_t a_Port); TcpSocket(TcpSocket&& a_Other); TcpSocket& operator=(TcpSocket&& a_Other); virtual ~TcpSocket(); virtual DataBuffer Read(std::size_t a_Amount) override; virtual void Write(const sp::DataBuffer& a_Data) override; /** * \brief Allows to set the socket in non blocking/blocking mode * \param a_Block If set to true, every call to Read will wait until the socket receives something * \return true if the operation was successful */ bool SetBlocking(bool a_Block); /** * \brief Getter of the m_Status member * \return The TcpSocket::Status of this socket */ Status GetStatus() const; /** * \brief Disconnects the socket from the remote * \note Does nothing if the socket is not connected. \n * This function is also called by the destructor. */ void Disconnect(); private: SocketHandle m_Handle; Status m_Status; void Connect(const std::string& a_Host, std::uint16_t a_Port); friend class TcpListener; }; } // namespace io } // namespace sp