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...
 
MessageBuffer & GetReadBuffer ()
 

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: