SockIt

Udp.cpp

Go to the documentation of this file.
00001 /*
00002  * Udp.cpp
00003  *
00004  *  Created on: Jun 8, 2011
00005  *      Author: jtedesco
00006  */
00007 
00008 #include "Udp.h"
00009 
00010 Udp::Udp(string host, int port, boost::asio::io_service & io_service) :
00011     host(host), port(port), pending_sends(0), should_close(false), io_service(io_service), failed(false)
00012 {
00013     remote_endpoint = boost::shared_ptr<udp::endpoint>(new udp::endpoint());
00014 }
00015 
00016 void Udp::send_handler(const boost::system::error_code &error_code, size_t bytes_transferred, string data, string host, int port)
00017 {
00018     if (error_code)
00019     {
00020         if (error_code == boost::asio::error::operation_aborted)
00021         {
00022             Logger::info("UDP send failed, aborted", port, host);
00023         }
00024         else
00025         {
00026             string message(
00027                     "UDP send failed, error message: '" + error_code.message() + "', error code '" + boost::lexical_cast<string>(
00028                             error_code.value()) + "' was encountered");
00029             Logger::error(message, port, host);
00030             fire_error_event(message);
00031         }
00032         return;
00033     }
00034 
00035     // Did not successfully send all the data, don't try and resend the rest (this is UDP)
00036     if (bytes_transferred != data.size())
00037     {
00038         string message(
00039                 string("UDP send failed, data was not successfully sent, only ") + boost::lexical_cast<string>(bytes_transferred) + " of "
00040                         + boost::lexical_cast<string>(message.size()) + " total bytes were sent");
00041         Logger::error(message, port, host);
00042         fire_error_event(message);
00043 
00044         return;
00045     }
00046 
00047     string message("UDP send succeeded, sent " + boost::lexical_cast<string>(bytes_transferred) + " bytes, message is: " + data);
00048     Logger::info(message, port, host);
00049 
00050     pending_sends_mutex.lock();
00051     pending_sends--; // just handled sending
00052     int pending_sends_now = pending_sends;
00053     pending_sends_mutex.unlock();
00054 
00055     if (pending_sends_now == 0 && should_close)
00056         close();
00057 }
00058 
00059 void Udp::receive_handler(const boost::system::error_code &error_code, std::size_t bytes_transferred,
00060         boost::shared_ptr<udp::socket> socket, boost::shared_ptr<udp::endpoint> endpoint, string host, int port)
00061 {
00062     // Check for errors
00063     if (error_code)
00064     {
00065         if (error_code == boost::asio::error::operation_aborted)
00066         {
00067             Logger::info("UDP receive failed, aborted", port, host);
00068         }
00069         else
00070         {
00071             string message(
00072                     "UDP receive failed, error message: '" + error_code.message() + "', code: '" + boost::lexical_cast<string>(
00073                             error_code.value()) + "'");
00074             Logger::error(message, port, host);
00075             fire_error_event(message);
00076         }
00077 
00078         return;
00079     }
00080 
00081     // Get the data && fire a data event
00082     string data(receive_buffer.c_array(), bytes_transferred);
00083     fire_data_event(data, socket, endpoint);
00084 
00085     // Pull out the data we received, and fire a data received event
00086     Logger::info("UDP receive succeeded, received " + boost::lexical_cast<string>(bytes_transferred) + " bytes, data is: " + data, port,
00087             host);
00088 
00089     // Listen for more messages if we're not trying to close down this UDP object
00090     if (!should_close)
00091         listen();
00092 }
00093 
00094 void inline Udp::parse_string_bool_arg(map<string, string> &options, string arg, optional<bool> &arg_value)
00095 {
00096     map<string, string>::iterator it;
00097 
00098     if ((it = options.find(arg)) != options.end())
00099     {
00100         if (it->second == std::string("true"))
00101             arg_value.reset(true);
00102         if (it->second == std::string("false"))
00103             arg_value.reset(false);
00104     }
00105 }
00106 
00107 void Udp::parse_args(map<string, string> options)
00108 {
00109     map<string, string>::iterator it;
00110     map<string, string> transformed_options;
00111 
00112     string t("true");
00113     string f("false");
00114 
00115     // transform the entire map to lower case
00116     for (it = options.begin(); it != options.end(); it++)
00117     {
00118         string k = it->first;
00119         string v = it->second;
00120 
00121         std::transform(k.begin(), k.end(), k.begin(), ::tolower);
00122         std::transform(v.begin(), v.end(), v.begin(), ::tolower);
00123 
00124         k.erase(std::remove_if(k.begin(), k.end(), ::isspace), k.end());
00125         v.erase(std::remove_if(v.begin(), v.end(), ::isspace), v.end());
00126 
00127         transformed_options.insert(std::pair<string, string>(k, v));
00128     }
00129 
00130     /* Lets just pretend you didn't see any of this */
00131     parse_string_bool_arg(transformed_options, "ipv6", using_ipv6);
00132     parse_string_bool_arg(transformed_options, "multicast", multicast);
00133     parse_string_bool_arg(transformed_options, "donotroute", do_not_route);
00134     parse_string_bool_arg(transformed_options, "reuseaddress", reuse_address);
00135 
00136     if ((it = transformed_options.find("multicastgroup")) != transformed_options.end())
00137         multicast_group.reset(it->second);
00138 
00139     if ((it = transformed_options.find("multicastttl")) != transformed_options.end())
00140         multicast_ttl.reset(boost::lexical_cast<int>(it->second));
00141 }
00142 
00143 inline string Udp::bool_option_to_string(optional<bool> &arg, string iftrue, string iffalse)
00144 {
00145     if (arg && *arg)
00146         return iftrue;
00147     return iffalse;
00148 }
00149 
00150 template<class T>
00151 inline string Udp::option_to_string(optional<T> &arg)
00152 {
00153     if (arg)
00154         return boost::lexical_cast<string>(*arg);
00155     return string("unset");
00156 }
00157 
00158 void Udp::log_options()
00159 {
00160     string options("These arguments were passed in: ");
00161 
00162     options.append(bool_option_to_string(using_ipv6, "ipv6, ", "ipv4, "));
00163     options.append(bool_option_to_string(multicast, "multicast enabled, ", "multicast disabled, "));
00164     options.append(bool_option_to_string(do_not_route, "no routing, ", "use routing, "));
00165     options.append(bool_option_to_string(reuse_address, "reuse address, ", "don't reuse address, "));
00166 
00167     options.append("multicast group: ");
00168     options.append(option_to_string<string> (multicast_group));
00169 
00170     options.append(", multicast ttl: ");
00171     options.append(option_to_string<int> (multicast_ttl));
00172 
00173     Logger::info(options, port, host);
00174 }
 All Classes Files Functions Variables Typedefs Friends Defines