00001 #include "mfextensions/Receivers/UDP_receiver.hh"
00002 #include "mfextensions/Receivers/ReceiverMacros.hh"
00003 #include <boost/tokenizer.hpp>
00004 #include <boost/regex.hpp>
00005 #include <sstream>
00006
00007 mfviewer::UDPReceiver::UDPReceiver(fhicl::ParameterSet pset) : MVReceiver(pset)
00008 , port_(pset.get<int>("port", 5140))
00009 , io_service_()
00010 , socket_(io_service_)
00011 , debug_(pset.get<bool>("debug_mode", false))
00012 {
00013
00014 boost::system::error_code ec;
00015 udp::endpoint listen_endpoint(boost::asio::ip::address::from_string("0.0.0.0"), port_);
00016 socket_.open(listen_endpoint.protocol());
00017 boost::asio::socket_base::reuse_address option(true);
00018 socket_.set_option(option, ec);
00019 if (ec)
00020 {
00021 std::cerr << "An error occurred setting reuse_address: " << ec.message() << std::endl;
00022 }
00023 socket_.bind(listen_endpoint, ec);
00024
00025 if (ec)
00026 {
00027 std::cerr << "An error occurred in bind(): " << ec.message() << std::endl;
00028 }
00029
00030 if (pset.get<bool>("multicast_enable", false))
00031 {
00032 std::string multicast_address_string = pset.get<std::string>("multicast_address", "227.128.12.27");
00033 auto multicast_address = boost::asio::ip::address::from_string(multicast_address_string);
00034 boost::asio::ip::multicast::join_group group_option(multicast_address);
00035 socket_.set_option(group_option, ec);
00036 if (ec)
00037 {
00038 std::cerr << "An error occurred joining the multicast group " << multicast_address_string
00039 << ": " << ec.message() << std::endl;
00040 }
00041
00042 boost::asio::ip::multicast::enable_loopback loopback_option(true);
00043 socket_.set_option(loopback_option, ec);
00044
00045 if (ec)
00046 {
00047 std::cerr << "An error occurred setting the multicast loopback option: " << ec.message() << std::endl;
00048 }
00049 }
00050 if (debug_) { std::cout << "UDPReceiver Constructor Done" << std::endl; }
00051 }
00052
00053 mfviewer::UDPReceiver::~UDPReceiver()
00054 {
00055 if (debug_) { std::cout << "Closing UDP Socket" << std::endl; }
00056 socket_.close();
00057 }
00058
00059 void mfviewer::UDPReceiver::run()
00060 {
00061 while (!stopRequested_)
00062 {
00063 if (socket_.available() <= 0)
00064 {
00065 usleep(10000);
00066 }
00067 else
00068 {
00069
00070 udp::endpoint remote_endpoint;
00071 boost::system::error_code ec;
00072 size_t packetSize = socket_.receive_from(boost::asio::buffer(buffer_), remote_endpoint, 0, ec);
00073 if (debug_) { std::cout << "Recieved message; validating...(packetSize=" << packetSize << ")" << std::endl; }
00074 std::string message(buffer_, buffer_ + packetSize);
00075 if (ec)
00076 {
00077 std::cerr << "Recieved error code: " << ec.message() << std::endl;
00078 }
00079 else if (packetSize > 0 && validate_packet(message))
00080 {
00081 if (debug_) { std::cout << "Valid UDP Message received! Sending to GUI!" << std::endl; }
00082 emit NewMessage(read_msg(message));
00083
00084 }
00085 }
00086 }
00087 std::cout << "UDPReceiver shutting down!" << std::endl;
00088 }
00089
00090 mf::MessageFacilityMsg mfviewer::UDPReceiver::read_msg(std::string input)
00091 {
00092 mf::MessageFacilityMsg msg;
00093 if (debug_) { std::cout << "Recieved MF/Syslog message with contents: " << input << std::endl; }
00094
00095 boost::char_separator<char> sep("|","",boost::keep_empty_tokens);
00096 typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
00097 tokenizer tokens(input, sep);
00098 tokenizer::iterator it = tokens.begin();
00099
00100
00101 boost::regex timestamp(".*?(\\d{2}-[^-]*-\\d{4}\\s\\d{2}:\\d{2}:\\d{2})");
00102 boost::smatch res;
00103 while (it != tokens.end() && !boost::regex_search(*it, res, timestamp))
00104 {
00105 ++it;
00106 }
00107
00108 if (it != tokens.end())
00109 {
00110 struct tm tm;
00111 time_t t;
00112 timeval tv;
00113 std::string value(res[1].first, res[1].second);
00114 strptime(value.c_str(), "%d-%b-%Y %H:%M:%S", &tm);
00115 tm.tm_isdst = -1;
00116 t = mktime(&tm);
00117 tv.tv_sec = t;
00118 tv.tv_usec = 0;
00119 msg.setTimestamp(tv);
00120
00121 int seqNum = 0;
00122 auto prevIt = it;
00123 try
00124 {
00125 if (++it != tokens.end()) { seqNum = std::stoi(*it); }
00126 }
00127 catch (std::invalid_argument e) { it = prevIt; }
00128 if (++it != tokens.end()) { msg.setHostname(*it); }
00129 if (++it != tokens.end()) { msg.setHostaddr(*it); }
00130 if (++it != tokens.end()) { msg.setSeverity(*it); }
00131 if (++it != tokens.end()) { msg.setCategory(*it); }
00132 if (++it != tokens.end()) { msg.setApplication(*it); }
00133 # if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
00134 if (++it != tokens.end()) { msg.setProcess(*it); }
00135 # endif
00136 prevIt = it;
00137 try
00138 {
00139 if (++it != tokens.end()) { msg.setPid(std::stol(*it)); }
00140 }
00141 catch (std::invalid_argument e) { it = prevIt; }
00142 if (++it != tokens.end()) { msg.setContext(*it); }
00143 if (++it != tokens.end()) { msg.setModule(*it); }
00144 std::ostringstream oss;
00145 bool first = true;
00146 while (++it != tokens.end())
00147 {
00148 if (!first) { oss << "|"; }
00149 else { first = false; }
00150 oss << *it;
00151 }
00152 if (debug_) { std::cout << "Message content: " << oss.str() << std::endl; }
00153 msg.setMessage(std::string("UDPMessage"), std::to_string(seqNum), oss.str());
00154 }
00155
00156 return msg;
00157 }
00158
00159 bool mfviewer::UDPReceiver::validate_packet(std::string input)
00160 {
00161
00162 if (input.find("MF") == std::string::npos)
00163 {
00164 std::cout << "Failed to find \"MF\" in message: " << input << std::endl;
00165 return false;
00166 }
00167 if (input.find("|") == std::string::npos)
00168 {
00169 std::cout << "Failed to find | separator character in message: " << input << std::endl;
00170 return false;
00171 }
00172 return true;
00173 }
00174
00175 #include "moc_UDP_receiver.cpp"
00176
00177 DEFINE_MFVIEWER_RECEIVER(mfviewer::UDPReceiver)