TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Socket< T, Stream > Class Template Referenceabstract

#include <Socket.h>

Public Member Functions

 Socket (tcp::socket &&socket)
 
virtual ~Socket ()
 
virtual void Start ()=0
 
virtual bool Update ()
 
boost::asio::ip::address GetRemoteIpAddress () const
 
uint16 GetRemotePort () const
 
void AsyncRead ()
 
void AsyncReadWithCallback (void(T::*callback)(boost::system::error_code, std::size_t))
 
void QueuePacket (MessageBuffer &&buffer)
 
bool IsOpen () const
 
void CloseSocket ()
 
void DelayedCloseSocket ()
 Marks the socket for closing after write buffer becomes empty. More...
 
MessageBufferGetReadBuffer ()
 

Protected Member Functions

virtual void OnClose ()
 
virtual void ReadHandler ()=0
 
bool AsyncProcessQueue ()
 
void SetNoDelay (bool enable)
 
Stream & underlying_stream ()
 

Private Member Functions

void ReadHandlerInternal (boost::system::error_code error, size_t transferredBytes)
 
void WriteHandlerWrapper (boost::system::error_code, std::size_t)
 
bool HandleQueue ()
 

Private Attributes

Stream _socket
 
boost::asio::ip::address _remoteAddress
 
uint16 _remotePort
 
MessageBuffer _readBuffer
 
std::queue< MessageBuffer_writeQueue
 
std::atomic< bool_closed
 
std::atomic< bool_closing
 
bool _isWritingAsync
 

Detailed Description

template<class T, class Stream = tcp::socket>
class Socket< T, Stream >

Base async socket implementation

Template Parameters
Tderived class type (CRTP)
Streamstream type used for operations on socket Stream must implement the following methods:

void close(boost::system::error_code& error);

void shutdown(boost::asio::socket_base::shutdown_type what, boost::system::error_code& shutdownError);

template<typename MutableBufferSequence, typename ReadHandlerType> void async_read_some(MutableBufferSequence const& buffers, ReadHandlerType&& handler);

template<typename ConstBufferSequence, typename WriteHandlerType> void async_write_some(ConstBufferSequence const& buffers, WriteHandlerType&& handler);

template<typename ConstBufferSequence> std::size_t write_some(ConstBufferSequence const& buffers, boost::system::error_code& error);

template<typename SettableSocketOption> void set_option(SettableSocketOption const& option, boost::system::error_code& error);

tcp::socket::endpoint_type remote_endpoint() const;

Constructor & Destructor Documentation

template<class T, class Stream = tcp::socket>
Socket< T, Stream >::Socket ( tcp::socket &&  socket)
inlineexplicit
68  : _socket(std::move(socket)), _remoteAddress(_socket.remote_endpoint().address()),
69  _remotePort(_socket.remote_endpoint().port()), _readBuffer(), _closed(false), _closing(false), _isWritingAsync(false)
70  {
72  }
boost::asio::ip::address _remoteAddress
Definition: Socket.h:285
bool _isWritingAsync
Definition: Socket.h:294
MessageBuffer _readBuffer
Definition: Socket.h:288
uint16 _remotePort
Definition: Socket.h:286
#define READ_BLOCK_SIZE
Definition: Socket.h:32
void Resize(size_type bytes)
Definition: MessageBuffer.h:51
std::atomic< bool > _closing
Definition: Socket.h:292
Stream _socket
Definition: Socket.h:283
std::atomic< bool > _closed
Definition: Socket.h:291
template<class T, class Stream = tcp::socket>
virtual Socket< T, Stream >::~Socket ( )
inlinevirtual
75  {
76  _closed = true;
77  boost::system::error_code error;
78  _socket.close(error);
79  }
Stream _socket
Definition: Socket.h:283
std::atomic< bool > _closed
Definition: Socket.h:291

Member Function Documentation

template<class T, class Stream = tcp::socket>
bool Socket< T, Stream >::AsyncProcessQueue ( )
inlineprotected
167  {
168  if (_isWritingAsync)
169  return false;
170 
171  _isWritingAsync = true;
172 
173 #ifdef TC_SOCKET_USE_IOCP
174  MessageBuffer& buffer = _writeQueue.front();
175  _socket.async_write_some(boost::asio::buffer(buffer.GetReadPointer(), buffer.GetActiveSize()), std::bind(&Socket<T, Stream>::WriteHandler,
176  this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
177 #else
178  _socket.async_write_some(boost::asio::null_buffers(), std::bind(&Socket<T, Stream>::WriteHandlerWrapper,
179  this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
180 #endif
181 
182  return false;
183  }
Definition: Socket.h:65
bool _isWritingAsync
Definition: Socket.h:294
size_type GetActiveSize() const
Definition: MessageBuffer.h:66
std::queue< MessageBuffer > _writeQueue
Definition: Socket.h:289
Stream _socket
Definition: Socket.h:283
uint8 * GetReadPointer()
Definition: MessageBuffer.h:58
Definition: MessageBuffer.h:24

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::AsyncRead ( )
inline
110  {
111  if (!IsOpen())
112  return;
113 
116  _socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), _readBuffer.GetRemainingSpace()),
117  std::bind(&Socket<T, Stream>::ReadHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
118  }
Definition: Socket.h:65
size_type GetRemainingSpace() const
Definition: MessageBuffer.h:68
MessageBuffer _readBuffer
Definition: Socket.h:288
uint8 * GetWritePointer()
Definition: MessageBuffer.h:60
bool IsOpen() const
Definition: Socket.h:140
void EnsureFreeSpace()
Definition: MessageBuffer.h:85
Stream _socket
Definition: Socket.h:283
void Normalize()
Definition: MessageBuffer.h:73
template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::AsyncReadWithCallback ( void(T::*)(boost::system::error_code, std::size_t)  callback)
inline
121  {
122  if (!IsOpen())
123  return;
124 
127  _socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), _readBuffer.GetRemainingSpace()),
128  std::bind(callback, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
129  }
size_type GetRemainingSpace() const
Definition: MessageBuffer.h:68
MessageBuffer _readBuffer
Definition: Socket.h:288
uint8 * GetWritePointer()
Definition: MessageBuffer.h:60
bool IsOpen() const
Definition: Socket.h:140
void EnsureFreeSpace()
Definition: MessageBuffer.h:85
Stream _socket
Definition: Socket.h:283
void Normalize()
Definition: MessageBuffer.h:73
template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::CloseSocket ( )
inline
143  {
144  if (_closed.exchange(true))
145  return;
146 
147  boost::system::error_code shutdownError;
148  _socket.shutdown(boost::asio::socket_base::shutdown_send, shutdownError);
149  if (shutdownError)
150  TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when shutting down socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(),
151  shutdownError.value(), shutdownError.message().c_str());
152 
153  OnClose();
154  }
boost::asio::ip::address GetRemoteIpAddress() const
Definition: Socket.h:99
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:198
Stream _socket
Definition: Socket.h:283
virtual void OnClose()
Definition: Socket.h:162
std::atomic< bool > _closed
Definition: Socket.h:291

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::DelayedCloseSocket ( )
inline

Marks the socket for closing after write buffer becomes empty.

157 { _closing = true; }
std::atomic< bool > _closing
Definition: Socket.h:292
template<class T, class Stream = tcp::socket>
MessageBuffer& Socket< T, Stream >::GetReadBuffer ( )
inline
159 { return _readBuffer; }
MessageBuffer _readBuffer
Definition: Socket.h:288
template<class T, class Stream = tcp::socket>
boost::asio::ip::address Socket< T, Stream >::GetRemoteIpAddress ( ) const
inline
100  {
101  return _remoteAddress;
102  }
boost::asio::ip::address _remoteAddress
Definition: Socket.h:285

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
uint16 Socket< T, Stream >::GetRemotePort ( ) const
inline
105  {
106  return _remotePort;
107  }
uint16 _remotePort
Definition: Socket.h:286
template<class T, class Stream = tcp::socket>
bool Socket< T, Stream >::HandleQueue ( )
inlineprivate
241  {
242  if (_writeQueue.empty())
243  return false;
244 
245  MessageBuffer& queuedMessage = _writeQueue.front();
246 
247  std::size_t bytesToSend = queuedMessage.GetActiveSize();
248 
249  boost::system::error_code error;
250  std::size_t bytesSent = _socket.write_some(boost::asio::buffer(queuedMessage.GetReadPointer(), bytesToSend), error);
251 
252  if (error)
253  {
254  if (error == boost::asio::error::would_block || error == boost::asio::error::try_again)
255  return AsyncProcessQueue();
256 
257  _writeQueue.pop();
258  if (_closing && _writeQueue.empty())
259  CloseSocket();
260  return false;
261  }
262  else if (bytesSent == 0)
263  {
264  _writeQueue.pop();
265  if (_closing && _writeQueue.empty())
266  CloseSocket();
267  return false;
268  }
269  else if (bytesSent < bytesToSend) // now n > 0
270  {
271  queuedMessage.ReadCompleted(bytesSent);
272  return AsyncProcessQueue();
273  }
274 
275  _writeQueue.pop();
276  if (_closing && _writeQueue.empty())
277  CloseSocket();
278  return !_writeQueue.empty();
279  }
bool AsyncProcessQueue()
Definition: Socket.h:166
void ReadCompleted(size_type bytes)
Definition: MessageBuffer.h:62
size_type GetActiveSize() const
Definition: MessageBuffer.h:66
std::atomic< bool > _closing
Definition: Socket.h:292
std::queue< MessageBuffer > _writeQueue
Definition: Socket.h:289
Stream _socket
Definition: Socket.h:283
uint8 * GetReadPointer()
Definition: MessageBuffer.h:58
void CloseSocket()
Definition: Socket.h:142
Definition: MessageBuffer.h:24

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
bool Socket< T, Stream >::IsOpen ( ) const
inline
140 { return !_closed && !_closing; }
std::atomic< bool > _closing
Definition: Socket.h:292
std::atomic< bool > _closed
Definition: Socket.h:291

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
virtual void Socket< T, Stream >::OnClose ( )
inlineprotectedvirtual

Reimplemented in WorldSocket.

162 { }

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::QueuePacket ( MessageBuffer &&  buffer)
inline
132  {
133  _writeQueue.push(std::move(buffer));
134 
135 #ifdef TC_SOCKET_USE_IOCP
137 #endif
138  }
bool AsyncProcessQueue()
Definition: Socket.h:166
std::queue< MessageBuffer > _writeQueue
Definition: Socket.h:289
template<class T, class Stream = tcp::socket>
virtual void Socket< T, Stream >::ReadHandler ( )
protectedpure virtual

Implemented in Battlenet::Session, and WorldSocket.

+ Here is the caller graph for this function:

template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::ReadHandlerInternal ( boost::system::error_code  error,
size_t  transferredBytes 
)
inlineprivate
201  {
202  if (error)
203  {
204  CloseSocket();
205  return;
206  }
207 
208  _readBuffer.WriteCompleted(transferredBytes);
209  ReadHandler();
210  }
MessageBuffer _readBuffer
Definition: Socket.h:288
void WriteCompleted(size_type bytes)
Definition: MessageBuffer.h:64
virtual void ReadHandler()=0
void CloseSocket()
Definition: Socket.h:142
template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::SetNoDelay ( bool  enable)
inlineprotected
186  {
187  boost::system::error_code err;
188  _socket.set_option(tcp::no_delay(enable), err);
189  if (err)
190  TC_LOG_DEBUG("network", "Socket::SetNoDelay: failed to set_option(boost::asio::ip::tcp::no_delay) for %s - %d (%s)",
191  GetRemoteIpAddress().to_string().c_str(), err.value(), err.message().c_str());
192  }
boost::asio::ip::address GetRemoteIpAddress() const
Definition: Socket.h:99
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:198
Stream _socket
Definition: Socket.h:283
template<class T, class Stream = tcp::socket>
virtual void Socket< T, Stream >::Start ( )
pure virtual

Implemented in Battlenet::Session, and WorldSocket.

template<class T, class Stream = tcp::socket>
Stream& Socket< T, Stream >::underlying_stream ( )
inlineprotected
195  {
196  return _socket;
197  }
Stream _socket
Definition: Socket.h:283
template<class T, class Stream = tcp::socket>
virtual bool Socket< T, Stream >::Update ( )
inlinevirtual

Reimplemented in Battlenet::Session, and WorldSocket.

84  {
85  if (_closed)
86  return false;
87 
88 #ifndef TC_SOCKET_USE_IOCP
89  if (_isWritingAsync || (_writeQueue.empty() && !_closing))
90  return true;
91 
92  for (; HandleQueue();)
93  ;
94 #endif
95 
96  return true;
97  }
bool _isWritingAsync
Definition: Socket.h:294
bool HandleQueue()
Definition: Socket.h:240
std::atomic< bool > _closing
Definition: Socket.h:292
std::queue< MessageBuffer > _writeQueue
Definition: Socket.h:289
std::atomic< bool > _closed
Definition: Socket.h:291
template<class T, class Stream = tcp::socket>
void Socket< T, Stream >::WriteHandlerWrapper ( boost::system::error_code  ,
std::size_t   
)
inlineprivate
235  {
236  _isWritingAsync = false;
237  HandleQueue();
238  }
bool _isWritingAsync
Definition: Socket.h:294
bool HandleQueue()
Definition: Socket.h:240

Member Data Documentation

template<class T, class Stream = tcp::socket>
std::atomic<bool> Socket< T, Stream >::_closed
private
template<class T, class Stream = tcp::socket>
std::atomic<bool> Socket< T, Stream >::_closing
private
template<class T, class Stream = tcp::socket>
bool Socket< T, Stream >::_isWritingAsync
private
template<class T, class Stream = tcp::socket>
MessageBuffer Socket< T, Stream >::_readBuffer
private
template<class T, class Stream = tcp::socket>
boost::asio::ip::address Socket< T, Stream >::_remoteAddress
private
template<class T, class Stream = tcp::socket>
uint16 Socket< T, Stream >::_remotePort
private
template<class T, class Stream = tcp::socket>
Stream Socket< T, Stream >::_socket
private
template<class T, class Stream = tcp::socket>
std::queue<MessageBuffer> Socket< T, Stream >::_writeQueue
private

The documentation for this class was generated from the following file: