SockIt
|
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 }