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