18#ifndef TRINITYCORE_SOCKET_H
19#define TRINITYCORE_SOCKET_H
25#include <boost/asio/io_context.hpp>
26#include <boost/asio/ip/tcp.hpp>
32using boost::asio::ip::tcp;
34#define READ_BLOCK_SIZE 4096
35#ifdef BOOST_ASIO_HAS_IOCP
36#define TC_SOCKET_USE_IOCP
41using IoContextTcpSocket = boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::executor_type>;
49template <
typename Callable>
52template <
typename SocketType>
63template <
typename SocketType>
108template<
class Stream = IoContextTcpSocket>
109class Socket :
public std::enable_shared_from_this<Socket<Stream>>
112 template<
typename... Args>
118 template<
typename... Args>
131 boost::system::error_code error;
142#ifndef TC_SOCKET_USE_IOCP
163 template <SocketReadCallback Callback>
172 [self = this->shared_from_this(), callback = std::forward<Callback>(callback)](boost::system::error_code
const& error,
size_t transferredBytes)
mutable
174 if (self->ReadHandlerInternal(error, transferredBytes))
175 if (callback() == SocketReadCallbackResult::KeepReading)
176 self->AsyncRead(std::forward<Callback>(callback));
184#ifdef TC_SOCKET_USE_IOCP
196 boost::system::error_code shutdownError;
197 _socket.shutdown(boost::asio::socket_base::shutdown_send, shutdownError);
200 shutdownError.value(), shutdownError.message());
234#ifdef TC_SOCKET_USE_IOCP
237 [self = this->shared_from_this()](boost::system::error_code
const& error, std::size_t transferedBytes)
239 self->WriteHandler(error, transferedBytes);
242 _socket.async_wait(boost::asio::socket_base::wait_type::wait_write,
243 [self = this->shared_from_this()](boost::system::error_code
const& error)
245 self->WriteHandlerWrapper(error);
254 boost::system::error_code err;
255 _socket.set_option(tcp::no_delay(enable), err);
257 TC_LOG_DEBUG(
"network",
"Socket::SetNoDelay: failed to set_option(boost::asio::ip::tcp::no_delay) for {} - {} ({})",
274#ifdef TC_SOCKET_USE_IOCP
276 void WriteHandler(boost::system::error_code error, std::size_t transferedBytes)
281 _writeQueue.front().ReadCompleted(transferedBytes);
311 boost::system::error_code error;
312 std::size_t bytesSent =
_socket.write_some(boost::asio::buffer(queuedMessage.
GetReadPointer(), bytesToSend), error);
316 if (error == boost::asio::error::would_block || error == boost::asio::error::try_again)
324 else if (bytesSent == 0)
331 else if (bytesSent < bytesToSend)
#define TC_LOG_DEBUG(filterType__,...)
size_type GetRemainingSpace() const
void ReadCompleted(size_type bytes)
void WriteCompleted(size_type bytes)
size_type GetActiveSize() const
uint8 * GetWritePointer()
uint16 GetRemotePort() const
static constexpr uint8 OpenState_Closed
std::atomic< uint8 > _openState
Socket(Socket const &other)=delete
bool ReadHandlerInternal(boost::system::error_code const &error, size_t transferredBytes)
void SetNoDelay(bool enable)
Socket(IoContextTcpSocket &&socket, Args &&... args)
std::queue< MessageBuffer > _writeQueue
virtual SocketReadCallbackResult ReadHandler()
Socket & operator=(Socket const &other)=delete
Stream & underlying_stream()
boost::asio::ip::address const & GetRemoteIpAddress() const
static constexpr uint8 OpenState_Closing
Transition to Closed state after sending all queued data.
static constexpr uint8 OpenState_Open
boost::asio::ip::address _remoteAddress
Socket(boost::asio::io_context &context, Args &&... args)
void AsyncRead(Callback &&callback)
void QueuePacket(MessageBuffer &&buffer)
void DelayedCloseSocket()
Marks the socket for closing after write buffer becomes empty.
MessageBuffer _readBuffer
void WriteHandlerWrapper(boost::system::error_code const &)
Socket(Socket &&other)=delete
Socket & operator=(Socket &&other)=delete
MessageBuffer & GetReadBuffer()
boost::asio::basic_stream_socket< boost::asio::ip::tcp, boost::asio::io_context::executor_type > IoContextTcpSocket
SocketReadCallbackResult operator()() const
InvokeReadHandlerCallback< SocketType > ReadCallback
ReadConnectionInitializer(SocketType *socket)
std::shared_ptr< SocketConnectionInitializer > next