SockIt
|
#include <UdpClient.h>
Public Member Functions | |
UdpClient (const string &host, int port, boost::asio::io_service &io_service) | |
UdpClient (const string &host, int port, boost::asio::io_service &io_service, map< string, string > options) | |
virtual | ~UdpClient () |
virtual void | send (const string &data) |
virtual void | send_bytes (const vector< byte > &bytes) |
virtual void | shutdown () |
virtual int | get_port () |
virtual string | get_host () |
Protected Member Functions | |
void | init_socket () |
virtual void | fire_error_event (const string &message) |
virtual void | fire_data_event (const string data, boost::shared_ptr< udp::socket > socket, boost::shared_ptr< udp::endpoint > endpoint) |
virtual void | close () |
Private Member Functions | |
UdpClient (const UdpClient &other) | |
virtual void | listen () |
void | resolve_handler (const boost::system::error_code &err, udp::resolver::iterator endpoint_iterator) |
void | flush () |
Private Attributes | |
boost::shared_ptr< udp::resolver > | resolver |
boost::shared_ptr< udp::socket > | socket |
boost::mutex | queue_mtx |
std::queue< string > | msgs_not_sent |
bool | resolved_endpoint |
Definition at line 22 of file UdpClient.h.
UdpClient::UdpClient | ( | const string & | host, |
int | port, | ||
boost::asio::io_service & | io_service | ||
) |
Asynchronously resolves the host and port number after creation. The client will not be able to send messages until after the resolve handler has run to completion.
host | The host to connect to |
port | The port the host is listening on |
io_service | The I/O service to be used for asynchronous I/O requests |
Definition at line 16 of file UdpClient.cpp.
References Logger::error(), Udp::failed, resolver, and socket.
: Udp(host, port, ioService), resolver(new udp::resolver(io_service)), socket(new udp::socket(io_service)), resolved_endpoint(false) { // Check that the connection and resolver are valid, and fail gracefully if they are not if (!resolver.get() || !socket.get()) { failed = true; string message("Failed to initialize UDP client, failed to initialize properly"); Logger::error(message, port, host); fire_error(message); return; } }
UdpClient::UdpClient | ( | const string & | host, |
int | port, | ||
boost::asio::io_service & | io_service, | ||
map< string, string > | options | ||
) |
Asynchronously resolves the host and port number after creation. The client will not be able to send messages until after the resolve handler has run to completion.
host | The host to connect to |
port | The port the host is listening on |
io_service | The I/O service to be used for asynchronous I/O requests |
options | A map of additional options to configure this UDP client |
Definition at line 30 of file UdpClient.cpp.
References Logger::error(), Udp::failed, Udp::parse_args(), resolver, and socket.
: Udp(host, port, ioService), resolver(new udp::resolver(io_service)), socket(new udp::socket(io_service)), resolved_endpoint(false) { // Check that the connection and resolver are valid, and fail gracefully if they are not if (!resolver.get() || !socket.get()) { failed = true; string message("Failed to initialize UDP client, failed to initialize properly"); Logger::error(message, port, host); fire_error(message); return; } parse_args(options); }
UdpClient::~UdpClient | ( | ) | [virtual] |
Deconstructs a UDP client, immediately calling close
to shutdown this client's socket and stop listening for responses.
Definition at line 92 of file UdpClient.cpp.
References close().
{ close(); }
UdpClient::UdpClient | ( | const UdpClient & | other | ) | [private] |
Disallows copying a UDP client
void UdpClient::close | ( | ) | [protected, virtual] |
Immediately cancels any pending operations and closes this client's socket.
Implements Udp.
Definition at line 97 of file UdpClient.cpp.
References Udp::should_close, and socket.
Referenced by shutdown(), and ~UdpClient().
{ should_close = true; if (socket->is_open()) { socket->close(); } }
void UdpClient::fire_data_event | ( | const string | data, |
boost::shared_ptr< udp::socket > | socket, | ||
boost::shared_ptr< udp::endpoint > | endpoint | ||
) | [protected, virtual] |
Helper to fire data event to javascript.
data | The data received |
socket | The socket on which to reply to this data |
endpoint | The connected endpoint to the remote host |
Implements Udp.
Definition at line 281 of file UdpClient.cpp.
References Udp::should_close.
{ if (should_close) return; fire_data(boost::make_shared<UdpEvent>(this, socket, endpoint, data)); }
void UdpClient::fire_error_event | ( | const string & | message | ) | [protected, virtual] |
Helper to fire an error event to javascript.
message | The error message |
Implements Udp.
Definition at line 273 of file UdpClient.cpp.
References Udp::should_close.
{ if (should_close) return; fire_error(message); }
void UdpClient::flush | ( | ) | [private] |
Flush all pending messages.
Definition at line 238 of file UdpClient.cpp.
References msgs_not_sent, queue_mtx, and send().
Referenced by resolve_handler(), and send().
{ queue_mtx.lock(); while (!msgs_not_sent.empty()) { string msg = msgs_not_sent.front(); msgs_not_sent.pop(); queue_mtx.unlock(); send(msg); queue_mtx.lock(); } queue_mtx.unlock(); }
string UdpClient::get_host | ( | void | ) | [virtual] |
Returns the host to which this client connects
Implements Client.
Definition at line 263 of file UdpClient.cpp.
References Udp::host.
{ return host; }
int UdpClient::get_port | ( | void | ) | [virtual] |
Returns the port of the remote host on which this client connects
Implements Client.
Definition at line 268 of file UdpClient.cpp.
References Udp::port.
{ return port; }
void UdpClient::init_socket | ( | ) | [protected] |
Initializes the socket according to the passed in options (if any).
Definition at line 46 of file UdpClient.cpp.
References Udp::BUFFER_SIZE, Udp::do_not_route, Logger::error(), Udp::host, Logger::info(), Udp::log_options(), Udp::multicast, Udp::multicast_ttl, Udp::port, Udp::reuse_address, socket, and Udp::using_ipv6.
Referenced by resolve_handler().
{ Logger::info( "Initializing UDP client to host '" + boost::lexical_cast<string>(host) + "' on port " + boost::lexical_cast<string>(port), port, host); log_options(); if (using_ipv6 && *using_ipv6) socket->open(udp::v6()); else socket->open(udp::v4()); if (!socket->is_open()) { string message("Failed to open UDP client socket"); Logger::error(message, port, host); fire_error(message); } // synchronize the buffer size of the socket with this class's buffer size boost::asio::socket_base::receive_buffer_size buf_size_option(BUFFER_SIZE); socket->set_option(buf_size_option); // set multicast ttl and out going interface if (multicast && *multicast) { if (multicast_ttl) { boost::asio::ip::multicast::hops option(*multicast_ttl); socket->set_option(option); } } if (do_not_route) { boost::asio::socket_base::do_not_route option(*do_not_route); socket->set_option(option); } if (reuse_address) { boost::asio::socket_base::reuse_address option(*reuse_address); socket->set_option(option); } }
void UdpClient::listen | ( | void | ) | [private, virtual] |
Helper function that will listen for incoming data on the UDP connection for the client, specifically responses to data already sent.
Implements Udp.
Definition at line 254 of file UdpClient.cpp.
References Udp::host, Udp::port, Udp::receive_buffer, Udp::receive_handler(), Udp::remote_endpoint, socket, and Logger::warn().
Referenced by send().
{ if (remote_endpoint && remote_endpoint.get()) socket->async_receive_from(boost::asio::buffer(receive_buffer), *remote_endpoint, boost::bind(&UdpClient::receive_handler, this, _1, _2, socket, remote_endpoint, host, port)); else Logger::warn("remote endpoint is null", port, host); }
void UdpClient::resolve_handler | ( | const boost::system::error_code & | err, |
udp::resolver::iterator | endpoint_iterator | ||
) | [private] |
I/O handler invoked when the remote host is resolved. This handler attempts to asynchronously establish a UDP connection with the remote host.
err | The error code encountered when trying to receive data, if any occurred. On success, this value is zero, and nonzero on error. |
endpoint_iterator | Allows the client to iterate through resolvers to retry the connection if it initially fails to connect. |
Definition at line 200 of file UdpClient.cpp.
References Logger::error(), flush(), Udp::host, Logger::info(), init_socket(), Udp::port, Udp::remote_endpoint, resolved_endpoint, resolver, and socket.
Referenced by send().
{ if (err) { udp::resolver::iterator end; if (endpoint_iterator != end && err == boost::asio::error::host_not_found) { // If we haven't tried resolving using all resolvers, try with another udp::resolver::query query(host, boost::lexical_cast<string>(port)); resolver->async_resolve(query, boost::bind(&UdpClient::resolve_handler, this, _1, endpoint_iterator++)); } else { // We have tried and cannot recover, fail permanently string message("Error: resolving host " + host + ":" + boost::lexical_cast<string>(port) + " error was " + err.message()); Logger::error(message, port, host); fire_error(message); return; } } fire_resolve(); Logger::info("udpclient: resolved, going to send", port, host); // We succeeded resolving the endpoint, continue remote_endpoint = boost::make_shared<udp::endpoint>(*endpoint_iterator); if (!socket->is_open()) init_socket(); // This endpoint has now been initialized resolved_endpoint = true; flush(); }
void UdpClient::send | ( | const string & | data | ) | [virtual] |
Asynchronously sends data to the remote host to which this client is connected.
data | The data to send across the wire |
Implements Client.
Definition at line 137 of file UdpClient.cpp.
References Logger::error(), Udp::failed, flush(), Udp::host, Logger::info(), listen(), msgs_not_sent, Udp::pending_sends, Udp::pending_sends_mutex, Udp::port, queue_mtx, Udp::remote_endpoint, resolve_handler(), resolved_endpoint, resolver, Udp::send_handler(), Udp::should_close, socket, and Udp::using_ipv6.
Referenced by flush(), and send_bytes().
{ if (failed) { // Log & fire an error string message("Trying to send from a UDP client that has permanently failed!"); Logger::error(message, port, host); return; } if (should_close) return; Logger::info("udpclient: sending a msg of size: " + boost::lexical_cast<std::string>(msg.size()) + " which is: " + msg, port, host); pending_sends_mutex.lock(); pending_sends++; pending_sends_mutex.unlock(); if (!resolved_endpoint) { Logger::info("udpclient: resolving " + host + ":" + boost::lexical_cast<string>(port), port, host); queue_mtx.lock(); msgs_not_sent.push(msg); queue_mtx.unlock(); // Create a query to resolve this host & port if (using_ipv6 && *using_ipv6) { // Asynchronously resolve the remote host, and once the host is resolved, create a connection udp::resolver::query query(udp::v6(), host, boost::lexical_cast<string>(port), boost::asio::ip::resolver_query_base::numeric_service); resolver->async_resolve(query, boost::bind(&UdpClient::resolve_handler, this, _1, _2)); } else { // Asynchronously resolve the remote host, and once the host is resolved, create a connection udp::resolver::query query(udp::v4(), host, boost::lexical_cast<string>(port), boost::asio::ip::resolver_query_base::numeric_service); resolver->async_resolve(query, boost::bind(&UdpClient::resolve_handler, this, _1, _2)); } } else { flush(); // any pending messages? send them. Logger::info("udpclient: attempting to send " + boost::lexical_cast<string>(msg.size()) + " bytes of data: " + msg, port, host); // send the message if (socket->is_open() && remote_endpoint.get()) { socket->async_send_to(boost::asio::buffer(msg.data(), msg.size()), *remote_endpoint, boost::bind(&UdpClient::send_handler, this, _1, _2, msg, host, port)); Logger::info("udpclient: (async) send called", port, host); if (!should_close) listen(); // listen for responses } } }
void UdpClient::send_bytes | ( | const vector< byte > & | bytes | ) | [virtual] |
Asynchronously sends bytes to the remote host to which this client is connected.
bytes | The data to send across the wire |
Implements Client.
Definition at line 125 of file UdpClient.cpp.
References UdpEvent::data, and send().
{ string data; for (int i = 0; i < bytes.size(); i++) { data.push_back((unsigned char) bytes[i]); } send(data); }
void UdpClient::shutdown | ( | ) | [virtual] |
Gracefully shutdown this UDP client, waiting until all sends have completed before freeing all resources for this UDP client and shutting down any open connections. This function is exposed the javascript API.
Implements NetworkObject.
Definition at line 107 of file UdpClient.cpp.
References close(), Udp::failed, Udp::pending_sends, Udp::pending_sends_mutex, and Udp::should_close.
{ if (!failed) { should_close = true; pending_sends_mutex.lock(); int pending_sends_now = pending_sends; pending_sends_mutex.unlock(); if (pending_sends_now == 0) { fire_close(); close(); } } }
std::queue<string> UdpClient::msgs_not_sent [private] |
Messages waiting to be sent, since the host hasn't been resolved yet.
Definition at line 159 of file UdpClient.h.
boost::mutex UdpClient::queue_mtx [private] |
Mutex for the message queue.
Definition at line 154 of file UdpClient.h.
bool UdpClient::resolved_endpoint [private] |
A flag representing whether the remote host for this UDP client has already been resolved.
Definition at line 164 of file UdpClient.h.
Referenced by resolve_handler(), and send().
boost::shared_ptr<udp::resolver> UdpClient::resolver [private] |
Resolver object provided by boost
to resolve the remote hostname and port
Definition at line 144 of file UdpClient.h.
Referenced by resolve_handler(), send(), and UdpClient().
boost::shared_ptr<udp::socket> UdpClient::socket [private] |
A shared reference to the socket used to connect to the remote host
Definition at line 149 of file UdpClient.h.
Referenced by close(), init_socket(), listen(), resolve_handler(), send(), and UdpClient().