SockIt
|
#include <TcpServer.h>
Public Member Functions | |
TcpServer (int port, boost::asio::io_service &io_service) | |
TcpServer (int port, boost::asio::io_service &io_service, map< string, string > options) | |
virtual | ~TcpServer () |
virtual void | start_listening () |
virtual void | shutdown () |
virtual int | get_port () |
FB_JSAPI_EVENT (disconnect, 1,(const string &)) | |
FB_JSAPI_EVENT (connect, 0,()) | |
Protected Member Functions | |
void | receive_handler (const boost::system::error_code &error_code, std::size_t bytesTransferred, boost::shared_ptr< tcp::socket > connection, string host, int port) |
virtual void | fire_error_event (const string &message) |
virtual void | fire_disconnect_event (const string &message) |
virtual void | fire_data_event (const string data, boost::shared_ptr< tcp::socket > connection) |
virtual void | close () |
Private Member Functions | |
void | init () |
void | init_socket (boost::shared_ptr< tcp::socket > connection) |
TcpServer (const TcpServer &other) | |
void | accept_handler (const boost::system::error_code &error_code, boost::shared_ptr< tcp::socket > connection, string host, int port) |
Private Attributes | |
boost::shared_ptr< tcp::acceptor > | acceptor |
set< boost::shared_ptr < tcp::socket > > | connections |
This class represents a TCP server, which inherits basic TCP handling functionality from Tcp
, and defines additional functionality to bind to a port and accept incoming connections.
Definition at line 24 of file TcpServer.h.
TcpServer::TcpServer | ( | int | port, |
boost::asio::io_service & | io_service | ||
) |
Builds a TCP server to listen on the specified port, but does not start the server listening on it. Using this constructor uses IPv4, given an I/O service to use for asynchronous I/O.
port | The port on which the server should listen |
io_service | The I/O service to use for background I/O requests |
Definition at line 10 of file TcpServer.cpp.
References init().
: Tcp("SERVER", port, io_service) { init(); }
TcpServer::TcpServer | ( | int | port, |
boost::asio::io_service & | io_service, | ||
map< string, string > | options | ||
) |
Builds a TCP server to listen on the specified port, but does not start the server listening on it. Using this constructor creates a server using IPv6, given an I/O service to use for asynchronous I/O.
port | The port on which the server should listen |
io_service | The I/O service to use for background I/O requests |
options | A map of options specifying the behavior of the socket |
Definition at line 16 of file TcpServer.cpp.
References init(), and Tcp::parse_args().
: Tcp("SERVER", port, io_service) { parse_args(options); init(); }
TcpServer::~TcpServer | ( | ) | [virtual] |
Deconstructs this TCP server, by immediately ceasing to accept incoming connections, shutdown all necessary resources.
Definition at line 23 of file TcpServer.cpp.
References close().
{ close(); }
TcpServer::TcpServer | ( | const TcpServer & | other | ) | [private] |
Disallows copying a TCP server
void TcpServer::accept_handler | ( | const boost::system::error_code & | error_code, |
boost::shared_ptr< tcp::socket > | connection, | ||
string | host, | ||
int | port | ||
) | [private] |
Handler invoked when a new connection is made to this server. This handler tries to start receiving data from the new incoming connection if there was no error accepting the connection.
error_code | The error code encountered when trying to receive data, if any occurred. On success, this value is zero, and nonzero on error. |
connection | The new connection created by this accept, from which this function will attempt to receive data. |
host | The host from which this accept was attempted |
port | The port from which this accept was attempted |
Definition at line 218 of file TcpServer.cpp.
References Tcp::disconnect_errors, Logger::error(), Logger::info(), init_socket(), Tcp::receive_buffer, receive_handler(), start_listening(), Tcp::waiting_to_shutdown, and Logger::warn().
Referenced by start_listening().
{ // Log error & return if there is an error if (error_code) { // Check for disconnection errors std::set<boost::system::error_code>::iterator find_result = disconnect_errors.find(error_code); if (find_result != disconnect_errors.end()) { if (error_code == boost::asio::error::operation_aborted) { // If we're waiting to shutdown, this is part of the normal process if(waiting_to_shutdown) { Logger::info("TCP server stopped listening for new connections", port, host); } else { Logger::warn("TCP accept was aborted", port, host); } } else { string message("TCP accept failed, disconnected: '" + error_code.message() + "'"); Logger::warn(message, port, host); fire_disconnect(message); } return; } string message("Error accepting incoming connection: '" + error_code.message() + "'"); Logger::error(message, port, host); fire_error(message); return; } // Initialize the socket options before we start using it init_socket(connection); // Log that we've successfully accepted a new connection, and fire the 'onconnect' event string message("TCP server accepted new connection from " + connection->remote_endpoint().address().to_string() + " port " + boost::lexical_cast<string>(connection->remote_endpoint().port())); Logger::info(message, port, host); fire_connect(); if (connection.get()) connection->async_receive(boost::asio::buffer(receive_buffer), boost::bind(&TcpServer::receive_handler, this, _1, _2, connection, host, port)); // Start listening for new connections, if we're not waiting to close if (!waiting_to_shutdown) { start_listening(); } }
void TcpServer::close | ( | ) | [protected, virtual] |
Closes down this TCP server immediately, by immediately ceasing to accept incoming connections, shutdown all necessary resources.
Implements Tcp.
Definition at line 28 of file TcpServer.cpp.
References acceptor, connections, Tcp::host, Tcp::port, Tcp::waiting_to_shutdown, and Logger::warn().
Referenced by shutdown(), and ~TcpServer().
{ // Shutdown the IO service, cancel any transfers on the socket, and close the socket waiting_to_shutdown = true; set<boost::shared_ptr<tcp::socket> >::iterator it; for(it = connections.begin(); it != connections.end(); it++) { try { if((*it) && (*it).get() && (*it)->is_open()) { (*it)->close(); } } catch(boost::system::error_code &e) { Logger::warn("Error in TcpServer deconstructor: " + e.message(), port, host); } catch(std::exception &er) { Logger::warn("Error in TcpServer deconstructor: " + std::string(er.what()), port, host); } catch(...) { Logger::warn("Error occured that could not be caught"); } } connections.clear(); if (acceptor && acceptor->is_open()) { acceptor->close(); } else { // Don't fire an error, otherwise the plugin will crash string message("Could not cleanly shut down acceptor in TCP server, desctructing anyways"); Logger::warn(message, port, host); } }
TcpServer::FB_JSAPI_EVENT | ( | disconnect | , |
1 | , | ||
(const string &) | |||
) |
The javascript event fired on a disconnect-type network error. This is fired on the following boost
errors:
boost::asio::error::connection_reset
boost::asio::error::eof
boost::asio::error::connection_aborted
boost::asio::error::operation_aborted
TcpServer::FB_JSAPI_EVENT | ( | connect | , |
0 | , | ||
() | |||
) |
The javascript event fired once a client has connected to its remote endpoint, or once a server has accepted a connection successfully (but has not yet receieved data), in this class, the former.
void TcpServer::fire_data_event | ( | const string | data, |
boost::shared_ptr< tcp::socket > | connection | ||
) | [protected, virtual] |
Helper to fire data event to javascript.
data | The data received |
connection | The connection on which to reply to the data |
Implements Tcp.
Definition at line 299 of file TcpServer.cpp.
{
fire_data(boost::make_shared<TcpEvent>(this, connection, data));
}
void TcpServer::fire_disconnect_event | ( | const string & | message | ) | [protected, virtual] |
Helper to fire an disconnect error event to javascript.
message | The error message |
Implements Tcp.
Definition at line 294 of file TcpServer.cpp.
{ fire_disconnect(message); }
void TcpServer::fire_error_event | ( | const string & | message | ) | [protected, virtual] |
Helper to fire an error event to javascript.
message | The error message |
Implements Tcp.
Definition at line 289 of file TcpServer.cpp.
{ fire_error(message); }
int TcpServer::get_port | ( | void | ) | [virtual] |
Returns the port on which this server listens
Implements Server.
Definition at line 284 of file TcpServer.cpp.
References Tcp::port.
{ return port; }
void TcpServer::init | ( | ) | [private] |
Helper function to initialize the acceptor. If this was not successfully initialized, fail
is true.
Definition at line 71 of file TcpServer.cpp.
References acceptor, Logger::error(), Tcp::failed, Tcp::host, Tcp::io_service, Tcp::port, and Tcp::using_ipv6.
Referenced by TcpServer().
{ // Bind the acceptor to the correct port & set the options on this acceptor try { if (using_ipv6 && *using_ipv6) { acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(io_service, tcp::endpoint(tcp::v6(), port))); } else { acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(io_service, tcp::endpoint(tcp::v4(), port))); } } catch (boost::system::system_error &e) { // Catch this error, and fail gracefully string message(string("Caught error initializing TCP server: '") + e.what() + "'"); Logger::error(message, port, host); // Stop this server from ever doing anything again failed = true; } // Check that acceptor was created successfully if (!acceptor.get()) { // Fail gracefully and stop this server from ever doing anything again string message("Failed to initialized TCP server acceptor"); Logger::error(message, port, host); failed = true; } }
void TcpServer::init_socket | ( | boost::shared_ptr< tcp::socket > | connection | ) | [private] |
Initialize the properties of this socket
Definition at line 105 of file TcpServer.cpp.
References Tcp::do_not_route, Tcp::keep_alive, Tcp::keep_alive_timeout, Tcp::no_delay, and Tcp::set_tcp_keepalive().
Referenced by accept_handler().
{ // Set the socket options for this client's TCP socket if (do_not_route) { boost::asio::socket_base::do_not_route option(*do_not_route); connection->set_option(option); } // Toggle keep alive (enabled/disabled) if (keep_alive) { boost::asio::socket_base::keep_alive option(*keep_alive); connection->set_option(option); } if (no_delay) { boost::asio::ip::tcp::no_delay option(*no_delay); connection->set_option(option); } if (keep_alive_timeout) { // Set the TCP keep-alive timeout - ignores return value set_tcp_keepalive(connection); } }
void TcpServer::receive_handler | ( | const boost::system::error_code & | error_code, |
std::size_t | bytesTransferred, | ||
boost::shared_ptr< tcp::socket > | connection, | ||
string | host, | ||
int | port | ||
) | [protected, virtual] |
Inherited from Tcp. Handler invoked when the data has been sent (or sending terminated in error).
Reimplemented from Tcp.
Definition at line 275 of file TcpServer.cpp.
References connections.
Referenced by accept_handler().
{ Tcp::receive_handler(error_code, bytesTransferred, connection, host, port); if(connection && connection.get() && !connection->is_open()) connections.erase(connection); }
void TcpServer::shutdown | ( | ) | [virtual] |
Gracefully shutdown this TCP server, waiting until all sends have completed before freeing all resources for this TCP server and shutting down any open connections. This function is exposed the javascript API.
Implements NetworkObject.
Definition at line 199 of file TcpServer.cpp.
References Tcp::active_jobs, close(), Logger::error(), Tcp::failed, Tcp::host, Tcp::port, and Tcp::waiting_to_shutdown.
{ if(!failed) { waiting_to_shutdown = true; if (active_jobs == 0) { fire_close(); close(); } } else { // Log & fire an error string message("Trying to shutdown the TCP server, but the server has permanently failed!"); Logger::error(message, port, host); } }
void TcpServer::start_listening | ( | ) | [virtual] |
Called to start the the server listening for the first time, fires the 'open' event, and is exposed to the javascript. This should only be called once, and starts the server listening for incoming connections.
Implements Server.
Definition at line 164 of file TcpServer.cpp.
References accept_handler(), acceptor, connections, Logger::error(), Tcp::failed, Tcp::host, Logger::info(), Tcp::io_service, Tcp::port, and socket_deallocate().
Referenced by accept_handler().
{ if(failed) { // Log & fire an error string message("Trying to start the server listening, but the server has permanently failed!"); Logger::error(message, port, host); } // Log listening Logger::info("TCP server about to start listening for incoming connections on port " + boost::lexical_cast<string>(port), port, host); // Prepare to accept a new connection and asynchronously accept new incoming connections boost::shared_ptr < tcp::socket > connection(new tcp::socket(io_service), socket_deallocate); connections.insert(connection); // Try to accept any new connection if(acceptor.get()) { acceptor->async_accept(*connection, boost::bind(&TcpServer::accept_handler, this, _1, connection, host, port)); } else { // Fail gracefully and stop this server from ever doing anything again string message("TCP server failed to accept, acceptor invalid"); Logger::error(message, port, host); failed = true; return; } // Callback acknowledging that the server has opened fire_open(); }
boost::shared_ptr<tcp::acceptor> TcpServer::acceptor [private] |
The acceptor for incoming connections for this server
Definition at line 159 of file TcpServer.h.
Referenced by close(), init(), and start_listening().
set<boost::shared_ptr<tcp::socket> > TcpServer::connections [private] |
A set of established connections.
Definition at line 162 of file TcpServer.h.
Referenced by close(), receive_handler(), and start_listening().