SockIt
|
#include <Tcp.h>
Public Member Functions | |
Tcp (string host, int port, boost::asio::io_service &io_service) | |
virtual | ~Tcp () |
Protected Member Functions | |
bool | set_tcp_keepalive (boost::shared_ptr< tcp::socket > socket) |
string | bool_option_to_string (optional< bool > &arg, string iftrue, string iffalse) |
template<class T > | |
string | option_to_string (optional< T > &arg) |
void | parse_string_bool_arg (map< string, string > &options, string arg, optional< bool > &arg_value) |
void | parse_string_int_arg (map< string, string > &options, string arg, optional< int > &arg_value) |
void | parse_args (map< string, string > options) |
void | log_options () |
virtual void | close ()=0 |
virtual void | send_handler (const boost::system::error_code &error_code, std::size_t bytes_transferred, string data, string host, int port, boost::shared_ptr< tcp::socket > connection) |
virtual void | receive_handler (const boost::system::error_code &error_code, std::size_t bytes_transferred, boost::shared_ptr< tcp::socket > connection, string host, int port) |
virtual void | fire_error_event (const string &message)=0 |
virtual void | fire_disconnect_event (const string &message)=0 |
virtual void | fire_data_event (const string data, boost::shared_ptr< tcp::socket > connection)=0 |
Protected Attributes | |
boost::array< char, BUFFER_SIZE > | receive_buffer |
boost::asio::io_service & | io_service |
bool | waiting_to_shutdown |
optional< bool > | using_ipv6 |
optional< bool > | no_delay |
optional< bool > | do_not_route |
optional< bool > | keep_alive |
optional< int > | keep_alive_timeout |
int | active_jobs |
boost::mutex | active_jobs_mutex |
string | host |
int | port |
std::set < boost::system::error_code > | disconnect_errors |
bool | failed |
Static Protected Attributes | |
static const int | BUFFER_SIZE = 4096 |
static const int | MAX_DATA_SIZE = 65536 |
Friends | |
class | TcpEvent |
Interface to abstract out the client-server model for use in the Event
. Contains common handlers used by both TCP servers and clients.
Tcp::Tcp | ( | string | host, |
int | port, | ||
boost::asio::io_service & | io_service | ||
) |
Builds a generic TCP object, and registers the 'shutdown' method on the API.
host | The hostname for this TCP object. For clients, this represents the remote host's hostname, and for servers, defaults to 'localhost'. |
port | The port for this TCP object, which for clients, represents the port of the remote host to which to connect, and for servers, represents the port to which to bind and listen for incoming connections. |
io_service | The I/O service used for asynchronous I/O requests |
Definition at line 10 of file Tcp.cpp.
References disconnect_errors.
: host(host), port(port), waiting_to_shutdown(false), active_jobs(0), io_service(ioService), using_ipv6(false), failed(false) { // Collect the set of errors classified as 'disconnect' type errors disconnect_errors.insert(boost::asio::error::connection_reset); disconnect_errors.insert(boost::asio::error::eof); disconnect_errors.insert(boost::asio::error::connection_aborted); disconnect_errors.insert(boost::asio::error::operation_aborted); }
virtual Tcp::~Tcp | ( | ) | [inline, virtual] |
string Tcp::bool_option_to_string | ( | optional< bool > & | arg, |
string | iftrue, | ||
string | iffalse | ||
) | [inline, protected] |
Helper for logging options passed in.
arg | optional bool option |
iftrue | if the arg has been set to true, return this |
iffalse | if the arg hasn't been set, or is set to false, return this |
Definition at line 159 of file Tcp.cpp.
Referenced by log_options().
{ if (arg && *arg) return iftrue; return iffalse; }
virtual void Tcp::close | ( | ) | [protected, pure virtual] |
Closes down this TCP object immediately, by immediately ceasing to accept incoming connections, shutdown all necessary resources.
Implemented in TcpClient, and TcpServer.
Referenced by send_handler().
virtual void Tcp::fire_data_event | ( | const string | data, |
boost::shared_ptr< tcp::socket > | connection | ||
) | [protected, pure virtual] |
Helper to fire data event to javascript.
data | The data received |
connection | The connection on which attempted to receive data. |
Implemented in TcpClient, and TcpServer.
Referenced by receive_handler().
virtual void Tcp::fire_disconnect_event | ( | const string & | message | ) | [protected, pure virtual] |
Helper to fire an disconnect error event to javascript.
message | The error message |
Implemented in TcpClient, and TcpServer.
Referenced by receive_handler(), and send_handler().
virtual void Tcp::fire_error_event | ( | const string & | message | ) | [protected, pure virtual] |
Helper to fire an error event to javascript.
message | The error message |
Implemented in TcpClient, and TcpServer.
Referenced by receive_handler(), and send_handler().
void Tcp::log_options | ( | ) | [protected] |
Write to the log the options used to create this connection.
Definition at line 229 of file Tcp.cpp.
References bool_option_to_string(), do_not_route, host, Logger::info(), keep_alive, keep_alive_timeout, no_delay, port, and using_ipv6.
Referenced by TcpClient::init(), and parse_args().
{ string options("These arguments were passed in: "); options.append(bool_option_to_string(using_ipv6, "ipv6, ", "ipv4, ")); options.append(bool_option_to_string(do_not_route, "no routing, ", "use routing, ")); options.append(bool_option_to_string(no_delay, "no delay, ", "allow delay, ")); options.append(bool_option_to_string(keep_alive, "keep alive", "don't keep alive")); options.append(", keep alive timeout is "); options.append(option_to_string<int> (keep_alive_timeout)); Logger::info(options, port, host); }
string Tcp::option_to_string | ( | optional< T > & | arg | ) | [inline, protected] |
void Tcp::parse_args | ( | map< string, string > | options | ) | [protected] |
Parses any options (like whether or use IPv6 or IPv4) from the options. Supported options currently include:
ipv6 if true, use ipv6. otherwise use ipv4. keep alive allow the socket to send keep-alives. do not route option to force TCP to use local interfaces only, prevents routing no delay option to disable Nagle algorithm for possibly improved performance
options | A map of options to values. |
Definition at line 197 of file Tcp.cpp.
References do_not_route, keep_alive, keep_alive_timeout, log_options(), no_delay, parse_string_bool_arg(), parse_string_int_arg(), and using_ipv6.
Referenced by TcpClient::TcpClient(), and TcpServer::TcpServer().
{ map<string, string>::iterator it; map<string, string> transformed_options; string t("true"); string f("false"); // transform the entire map to lower case for (it = options.begin(); it != options.end(); it++) { string k = it->first; string v = it->second; std::transform(k.begin(), k.end(), k.begin(), ::tolower); std::transform(v.begin(), v.end(), v.begin(), ::tolower); k.erase(std::remove_if(k.begin(), k.end(), ::isspace), k.end()); v.erase(std::remove_if(v.begin(), v.end(), ::isspace), v.end()); transformed_options.insert(std::pair<string, string>(k, v)); } parse_string_bool_arg(transformed_options, "ipv6", using_ipv6); parse_string_bool_arg(transformed_options, "donotroute", do_not_route); parse_string_bool_arg(transformed_options, "keepalive", keep_alive); parse_string_bool_arg(transformed_options, "nodelay", no_delay); parse_string_int_arg(transformed_options, "keepalivetimeout", keep_alive_timeout); log_options(); }
void Tcp::parse_string_bool_arg | ( | map< string, string > & | options, |
string | arg, | ||
optional< bool > & | arg_value | ||
) | [inline, protected] |
Helper for parsing boolean arguments
options | A map of strings to string representing the options passed in and their values |
arg | The specific option to check for |
arg_value | This will hold the value of the argument, if found. |
Definition at line 174 of file Tcp.cpp.
Referenced by parse_args().
{ map<string, string>::iterator it; if ((it = options.find(arg)) != options.end()) { if (it->second == std::string("true")) arg_value.reset(true); if (it->second == std::string("false")) arg_value.reset(false); } }
void Tcp::parse_string_int_arg | ( | map< string, string > & | options, |
string | arg, | ||
optional< int > & | arg_value | ||
) | [inline, protected] |
Helper for parsing integer arguments
options | A map of strings to string representing the options passed in and their values |
arg | The specific option to check for |
arg_value | This will hold the value of the argument, if found. |
Definition at line 187 of file Tcp.cpp.
Referenced by parse_args().
{
map<string, string>::iterator it;
if ((it = options.find(arg)) != options.end())
{
arg_value.reset(boost::lexical_cast<int>(it->second));
}
}
void Tcp::receive_handler | ( | const boost::system::error_code & | error_code, |
std::size_t | bytes_transferred, | ||
boost::shared_ptr< tcp::socket > | connection, | ||
string | host, | ||
int | port | ||
) | [protected, virtual] |
Handler invoked when some data has been received.
error_code | The error code encountered when trying to receive data, if any occurred. On success, this value is zero, and nonzero on error. |
bytes_transferred | The number of bytes successfully received over the connection. |
connection | The connection on which attempted to receive data. |
host | The hostname for this TCP object |
port | The port for this TCP object |
Reimplemented in TcpServer.
Definition at line 88 of file Tcp.cpp.
References disconnect_errors, Logger::error(), fire_data_event(), fire_disconnect_event(), fire_error_event(), Logger::info(), receive_buffer, and Logger::warn().
Referenced by TcpClient::connect_handler().
{ // Check for errors if (error_code) { // Check for disconnection errors if (disconnect_errors.find(error_code) != disconnect_errors.end()) { if (error_code == boost::asio::error::operation_aborted) { Logger::info("TCP send failed, aborted", port, host); return; } else { string message("TCP receive failed, disconnected, error message: '" + error_code.message() + "'"); Logger::info(message, port, host); fire_disconnect_event(message); return; } } // Otherwise, this is a more serious error, fail and log the error string message( "TCP receive failed, error message: '" + error_code.message() + "', value '" + boost::lexical_cast<string>( error_code.value()) + "'"); Logger::error(message, port, host); fire_error_event(message); // Shutdown the socket we're receiving from if (connection.get() && connection->is_open()) { try { connection->shutdown(connection->shutdown_receive); } catch (...) { Logger::warn("TCP receive failed, shutdown improperly, proceeding anyway", port, host); } } return; } // Pull out the data we received, and fire a data received event string data = string(receive_buffer.c_array(), bytes_transferred); // Log success string message( "Successfully received all " + boost::lexical_cast<string>(bytes_transferred) + " bytes of " + boost::lexical_cast<string>( bytes_transferred) + " total bytes. Data: '" + data + "'"); Logger::info(message, port, host); try { fire_data_event(data, connection); } catch (const boost::bad_weak_ptr &p) { Logger::error("Event is going out of scope", port, host); } // Try to receive more data if (connection.get()) connection->async_receive(boost::asio::buffer(receive_buffer), boost::bind(&Tcp::receive_handler, this, _1, _2, connection, host, port)); }
void Tcp::send_handler | ( | const boost::system::error_code & | error_code, |
std::size_t | bytes_transferred, | ||
string | data, | ||
string | host, | ||
int | port, | ||
boost::shared_ptr< tcp::socket > | connection | ||
) | [protected, virtual] |
Handler invoked when the data has been sent (or sending terminated in error).
error_code | The error code encountered when trying to send data, if any occurred. On success, this value is zero, and nonzero on error. |
bytes_transferred | The number of bytes successfully sent over the connection. |
data | The data to be sent. |
host | The hostname for this TCP object |
port | The port for this TCP object |
connection | The connection this data was sent on |
Definition at line 20 of file Tcp.cpp.
References active_jobs, active_jobs_mutex, close(), disconnect_errors, Logger::error(), fire_disconnect_event(), fire_error_event(), Logger::info(), waiting_to_shutdown, and Logger::warn().
Referenced by TcpClient::flush(), TcpEvent::send(), and TcpClient::send().
{ // Check the error code 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) { Logger::info("TCP send failed, aborted", port, host); } else { string message("TCP send failed, disconnected, error message: '" + error_code.message() + "'"); Logger::info(message, port, host); fire_disconnect_event(message); } return; } string message( "TCP send failed, error message '" + error_code.message() + "', error code '" + boost::lexical_cast<string>( error_code.value()) + "' was encountered"); Logger::error(message, port, host); fire_error_event(message); return; } if (bytes_transferred != data.size()) { // Get the rest of the message, and try resending it string rest_of_buffer(((char*) data.data()) + bytes_transferred, data.size() - bytes_transferred); active_jobs_mutex.lock(); active_jobs++; active_jobs_mutex.unlock(); connection->async_send(boost::asio::buffer(rest_of_buffer.data(), rest_of_buffer.size()), boost::bind(&Tcp::send_handler, this, _1, _2, rest_of_buffer, host, port, connection)); // Log that we had to do this // We could not send all of the message, fire an error and log it string message( string("TCP send failed, only ") + boost::lexical_cast<string>(bytes_transferred) + " of " + boost::lexical_cast<string>( data.size()) + " total bytes were sent"); Logger::warn(message, port, host); return; } else { string message("TCP send succeeded, sent " + boost::lexical_cast<string>(bytes_transferred) + " bytes, data is: " + data); Logger::info(message, port, host); } // Check to see if this is for the last send to complete, and if we're waiting to shutdown active_jobs_mutex.lock(); active_jobs--; active_jobs_mutex.unlock(); int current_jobs = active_jobs; if (waiting_to_shutdown && current_jobs == 0) { close(); } }
bool Tcp::set_tcp_keepalive | ( | boost::shared_ptr< tcp::socket > | socket | ) | [protected] |
Helper for setting tcp keep alive options (varies from platform to platform).
socket | The boost socket to set the tcp keep alive options on |
Definition at line 243 of file Tcp.cpp.
References Logger::error(), host, keep_alive_timeout, and port.
Referenced by TcpServer::init_socket(), and TcpClient::init_socket().
{ #ifdef __UNIX__ // For *n*x systems int native_fd = socket->native(); int timeout = *keep_alive_timeout; int intvl = 1; int probes = 10; int on = 1; int ret_keepalive = setsockopt(native_fd, SOL_SOCKET, SO_KEEPALIVE, (void*) &on, sizeof(int)); int ret_keepidle = setsockopt(native_fd, SOL_TCP, TCP_KEEPIDLE, (void*) &timeout, sizeof(int)); int ret_keepintvl = setsockopt(native_fd, SOL_TCP, TCP_KEEPINTVL, (void*) &intvl, sizeof(int)); int ret_keepinit = setsockopt(native_fd, SOL_TCP, TCP_KEEPCNT, (void*) &probes, sizeof(int)); if(ret_keepalive || ret_keepidle || ret_keepintvl || ret_keepinit) { string message("Failed to enable keep alive on TCP client socket!"); Logger::error(message, port, host); return false; } #elif defined(__OSX__) int native_fd = socket->native(); int timeout = *keep_alive_timeout; int intvl = 1; int on = 1; // Set the timeout before the first keep alive message int ret_sokeepalive = setsockopt(native_fd, SOL_SOCKET, SO_KEEPALIVE, (void*) &on, sizeof(int)); int ret_tcpkeepalive = setsockopt(native_fd, IPPROTO_TCP, TCP_KEEPALIVE, (void*) &timeout, sizeof(int)); int ret_tcpkeepintvl = setsockopt(native_fd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, (void*) &intvl, sizeof(int)); if(ret_sokeepalive || ret_tcpkeepalive || ret_tcpkeepintvl) { string message("Failed to enable keep alive on TCP client socket!"); Logger::error(message, port, host); return false; } #else // Partially supported on windows struct tcp_keepalive keepalive_options; keepalive_options.onoff = 1; keepalive_options.keepalivetime = *keep_alive_timeout * 1000; keepalive_options.keepaliveinterval = 2000; BOOL keepalive_val = true; SOCKET native = socket->native(); DWORD bytes_returned; int ret_keepalive = setsockopt(native, SOL_SOCKET, SO_KEEPALIVE, (const char *) &keepalive_val, sizeof(keepalive_val)); int ret_iotcl = WSAIoctl(native, SIO_KEEPALIVE_VALS, (LPVOID) & keepalive_options, (DWORD) sizeof(keepalive_options), NULL, 0, (LPDWORD) & bytes_returned, NULL, NULL); if (ret_keepalive || ret_iotcl) { string message("Failed to set keep alive timeout on TCP client socket!"); Logger::error(message, port, host); return false; } #endif return true; }
int Tcp::active_jobs [protected] |
The current count of active jobs on the socket
Definition at line 254 of file Tcp.h.
Referenced by TcpEvent::send(), TcpClient::send(), send_handler(), TcpServer::shutdown(), and TcpClient::shutdown().
boost::mutex Tcp::active_jobs_mutex [protected] |
A mutex around the current count of active jobs on the socket
Definition at line 259 of file Tcp.h.
Referenced by TcpClient::send(), send_handler(), and TcpClient::shutdown().
const int Tcp::BUFFER_SIZE = 4096 [static, protected] |
std::set<boost::system::error_code> Tcp::disconnect_errors [protected] |
The set of boost::system::error_code
errors considered to be 'disconnection' errors.
Definition at line 276 of file Tcp.h.
Referenced by TcpServer::accept_handler(), TcpClient::connect_handler(), receive_handler(), TcpClient::resolve_handler(), send_handler(), and Tcp().
optional<bool> Tcp::do_not_route [protected] |
Option to force TCP to use local interfaces only, prevents routing
Definition at line 239 of file Tcp.h.
Referenced by TcpServer::init_socket(), TcpClient::init_socket(), log_options(), and parse_args().
bool Tcp::failed [protected] |
A flag that is set to true whenever this TCP client or server encounters an unrecoverable error and cannot continue.
Definition at line 281 of file Tcp.h.
Referenced by TcpServer::init(), TcpClient::init(), TcpClient::resolve_handler(), TcpEvent::send(), TcpClient::send(), TcpServer::shutdown(), TcpClient::shutdown(), TcpServer::start_listening(), and TcpClient::TcpClient().
string Tcp::host [protected] |
The hostname for this TCP object ('localhost' for servers, or the hostname of the remote host for clients)
Definition at line 264 of file Tcp.h.
Referenced by TcpServer::close(), TcpClient::close(), TcpClient::connect_handler(), TcpClient::flush(), TcpClient::get_host(), TcpServer::init(), TcpClient::init(), log_options(), TcpClient::resolve_handler(), TcpClient::send(), set_tcp_keepalive(), TcpServer::shutdown(), TcpClient::shutdown(), and TcpServer::start_listening().
boost::asio::io_service& Tcp::io_service [protected] |
The I/O service for perform nonblocking actions
Definition at line 219 of file Tcp.h.
Referenced by TcpServer::init(), and TcpServer::start_listening().
optional<bool> Tcp::keep_alive [protected] |
Allow the socket to send keep-alives
Definition at line 244 of file Tcp.h.
Referenced by TcpServer::init_socket(), TcpClient::init_socket(), log_options(), and parse_args().
optional<int> Tcp::keep_alive_timeout [protected] |
Allow setting the socket's keep-alive timeout
Definition at line 249 of file Tcp.h.
Referenced by TcpServer::init_socket(), TcpClient::init_socket(), log_options(), parse_args(), and set_tcp_keepalive().
const int Tcp::MAX_DATA_SIZE = 65536 [static, protected] |
optional<bool> Tcp::no_delay [protected] |
Option to disable Nagle algorithm for possibly improved performance
Definition at line 234 of file Tcp.h.
Referenced by TcpServer::init_socket(), TcpClient::init_socket(), log_options(), and parse_args().
int Tcp::port [protected] |
The port (the port bound to by servers, port on which to connect to the remote host for clients)
Definition at line 269 of file Tcp.h.
Referenced by TcpServer::close(), TcpClient::close(), TcpClient::connect_handler(), TcpClient::flush(), TcpServer::get_port(), TcpClient::get_port(), TcpServer::init(), TcpClient::init(), log_options(), TcpClient::resolve_handler(), TcpClient::send(), set_tcp_keepalive(), TcpServer::shutdown(), TcpClient::shutdown(), and TcpServer::start_listening().
boost::array<char, BUFFER_SIZE> Tcp::receive_buffer [protected] |
A buffer for receiving data from the remote host.
Definition at line 214 of file Tcp.h.
Referenced by TcpServer::accept_handler(), TcpClient::connect_handler(), and receive_handler().
optional<bool> Tcp::using_ipv6 [protected] |
Flag to say whether or not this TCP object uses IPv6
Definition at line 229 of file Tcp.h.
Referenced by TcpServer::init(), TcpClient::init(), log_options(), parse_args(), and TcpClient::resolve_handler().
bool Tcp::waiting_to_shutdown [protected] |
A flag to say whether or not this server is waiting to shutdown
Definition at line 224 of file Tcp.h.
Referenced by TcpServer::accept_handler(), TcpServer::close(), TcpClient::close(), send_handler(), TcpServer::shutdown(), and TcpClient::shutdown().