00001 #define TRACE_NAME "UDP_Receiver"
00002
00003 #include "mfextensions/Receivers/UDP_receiver.hh"
00004 #include "mfextensions/Receivers/ReceiverMacros.hh"
00005 #include "mfextensions/Receivers/detail/TCPConnect.hh"
00006 #include "messagefacility/Utilities/ELseverityLevel.h"
00007 #include <boost/tokenizer.hpp>
00008 #include <boost/regex.hpp>
00009 #include <sstream>
00010 #include <sys/poll.h>
00011
00012 mfviewer::UDPReceiver::UDPReceiver(fhicl::ParameterSet pset) : MVReceiver(pset)
00013 , message_port_(pset.get<int>("port", 5140))
00014 , message_addr_(pset.get<std::string>("message_address", "227.128.12.27"))
00015 , multicast_enable_(pset.get<bool>("multicast_enable", false))
00016 , multicast_out_addr_(pset.get<std::string>("multicast_interface_ip", "0.0.0.0"))
00017 , message_socket_(-1)
00018 {
00019 TLOG(TLVL_TRACE) << "UDPReceiver Constructor";
00020 }
00021
00022
00023 void mfviewer::UDPReceiver::setupMessageListener_()
00024 {
00025 TLOG(TLVL_INFO) << "Setting up message listen socket, address=" << message_addr_ << ":" << message_port_;
00026 message_socket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00027 if (message_socket_ < 0)
00028 {
00029 TLOG(TLVL_ERROR) << "Error creating socket for receiving messages! err=" << strerror(errno);
00030 exit(1);
00031 }
00032
00033 struct sockaddr_in si_me_request;
00034
00035 int yes = 1;
00036 if (setsockopt(message_socket_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
00037 {
00038 TLOG(TLVL_ERROR) << "Unable to enable port reuse on message socket, err=" << strerror(errno);
00039 exit(1);
00040 }
00041 memset(&si_me_request, 0, sizeof(si_me_request));
00042 si_me_request.sin_family = AF_INET;
00043 si_me_request.sin_port = htons(message_port_);
00044 si_me_request.sin_addr.s_addr = htonl(INADDR_ANY);
00045 if (bind(message_socket_, (struct sockaddr *)&si_me_request, sizeof(si_me_request)) == -1)
00046 {
00047 TLOG(TLVL_ERROR) << "Cannot bind message socket to port " << message_port_ << ", err=" << strerror(errno);
00048 exit(1);
00049 }
00050
00051 if (message_addr_ != "localhost" && multicast_enable_)
00052 {
00053 struct ip_mreq mreq;
00054 int sts = ResolveHost(message_addr_.c_str(), mreq.imr_multiaddr);
00055 if (sts == -1)
00056 {
00057 TLOG(TLVL_ERROR) << "Unable to resolve multicast message address, err=" << strerror(errno);
00058 exit(1);
00059 }
00060 sts = GetInterfaceForNetwork(multicast_out_addr_.c_str(), mreq.imr_interface);
00061 if (sts == -1)
00062 {
00063 TLOG(TLVL_ERROR) << "Unable to resolve hostname for " << multicast_out_addr_;
00064 exit(1);
00065 }
00066 if (setsockopt(message_socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
00067 {
00068 TLOG(TLVL_ERROR) << "Unable to join multicast group, err=" << strerror(errno);
00069 exit(1);
00070 }
00071 }
00072 TLOG(TLVL_INFO) << "Done setting up message receive socket";
00073 }
00074
00075
00076 mfviewer::UDPReceiver::~UDPReceiver()
00077 {
00078 TLOG(TLVL_DEBUG) << "Closing message receive socket";
00079 close(message_socket_);
00080 message_socket_ = -1;
00081 }
00082
00083 void mfviewer::UDPReceiver::run()
00084 {
00085 while (!stopRequested_)
00086 {
00087 if (message_socket_ == -1) setupMessageListener_();
00088
00089 int ms_to_wait = 10;
00090 struct pollfd ufds[1];
00091 ufds[0].fd = message_socket_;
00092 ufds[0].events = POLLIN | POLLPRI | POLLERR;
00093 int rv = poll(ufds, 1, ms_to_wait);
00094
00095
00096 if (rv <= 0 || (ufds[0].revents != POLLIN && ufds[0].revents != POLLPRI))
00097 {
00098 if (rv == 1 && (ufds[0].revents & (POLLNVAL | POLLERR | POLLHUP)))
00099 {
00100 close(message_socket_);
00101 message_socket_ = -1;
00102 }
00103 if (stopRequested_)
00104 {
00105 break;
00106 }
00107 continue;
00108 }
00109
00110 char buffer[TRACE_STREAMER_MSGMAX + 1];
00111 auto packetSize = read(message_socket_, &buffer, TRACE_STREAMER_MSGMAX);
00112 if (packetSize < 0)
00113 {
00114 TLOG(TLVL_ERROR) << "Error receiving message, errno=" << errno << " (" << strerror(errno) << ")";
00115 }
00116 else
00117 {
00118 TLOG(TLVL_TRACE) << "Recieved message; validating...(packetSize=" << packetSize << ")";
00119 std::string message(buffer, buffer + packetSize);
00120 if (validate_packet(message))
00121 {
00122 TLOG(TLVL_TRACE) << "Valid UDP Message received! Sending to GUI!";
00123 emit NewMessage(read_msg(message));
00124 }
00125 }
00126 }
00127 TLOG(TLVL_INFO) << "UDPReceiver shutting down!";
00128 }
00129
00130 qt_mf_msg mfviewer::UDPReceiver::read_msg(std::string input)
00131 {
00132 std::string hostname, category, application, message, hostaddr, file, line, module, eventID;
00133 mf::ELseverityLevel sev;
00134 timeval tv;
00135 int pid = 0;
00136 int seqNum = 0;
00137
00138 TLOG(TLVL_TRACE) << "Recieved MF/Syslog message with contents: " << input;
00139
00140 boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
00141 typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
00142 tokenizer tokens(input, sep);
00143 tokenizer::iterator it = tokens.begin();
00144
00145
00146 boost::regex timestamp(".*?(\\d{2}-[^-]*-\\d{4}\\s\\d{2}:\\d{2}:\\d{2})");
00147 boost::smatch res;
00148 while (it != tokens.end() && !boost::regex_search(*it, res, timestamp))
00149 {
00150 ++it;
00151 }
00152
00153 if (it != tokens.end())
00154 {
00155 struct tm tm;
00156 time_t t;
00157 std::string value(res[1].first, res[1].second);
00158 strptime(value.c_str(), "%d-%b-%Y %H:%M:%S", &tm);
00159 tm.tm_isdst = -1;
00160 t = mktime(&tm);
00161 tv.tv_sec = t;
00162 tv.tv_usec = 0;
00163
00164 auto prevIt = it;
00165 try
00166 {
00167 if (++it != tokens.end()) { seqNum = std::stoi(*it); }
00168 }
00169 catch (std::invalid_argument e) { it = prevIt; }
00170 if (++it != tokens.end()) { hostname = *it; }
00171 if (++it != tokens.end()) { hostaddr = *it; }
00172 if (++it != tokens.end()) { sev = mf::ELseverityLevel(*it); }
00173 if (++it != tokens.end()) { category = *it; }
00174 if (++it != tokens.end()) { application = *it; }
00175 prevIt = it;
00176 try
00177 {
00178 if (++it != tokens.end()) { pid = std::stol(*it); }
00179 }
00180 catch (std::invalid_argument e) { it = prevIt; }
00181 if (++it != tokens.end()) { eventID = *it; }
00182 if (++it != tokens.end()) { module = *it; }
00183 #if MESSAGEFACILITY_HEX_VERSION >= 0x20201 // Sender and receiver version must match!
00184 if (++it != tokens.end()) { file = *it; }
00185 if (++it != tokens.end()) { line = *it; }
00186 #endif
00187 std::ostringstream oss;
00188 bool first = true;
00189 while (++it != tokens.end())
00190 {
00191 if (!first) { oss << "|"; }
00192 else { first = false; }
00193 oss << *it;
00194 }
00195 TLOG(TLVL_TRACE) << "Message content: " << oss.str();
00196 message = oss.str();
00197 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // Sender and receiver version must match!
00198 boost::regex fileLine("^\\s*([^:]*\\.[^:]{1,3}):(\\d+)(.*)");
00199 if (boost::regex_search(message, res, fileLine))
00200 {
00201 file = std::string(res[1].first, res[1].second);
00202 line = std::string(res[2].first, res[2].second);
00203 std::string messagetmp = std::string(res[3].first, res[3].second);
00204 message = messagetmp;
00205 }
00206 #endif
00207 }
00208
00209 qt_mf_msg msg(hostname, category, application, pid, tv);
00210 msg.setSeverity(sev);
00211 msg.setMessage("UDPMessage", seqNum, message);
00212 msg.setHostAddr(hostaddr);
00213 msg.setFileName(file);
00214 msg.setLineNumber(line);
00215 msg.setModule(module);
00216 msg.setEventID(eventID);
00217 msg.updateText();
00218
00219 return msg;
00220 }
00221
00222 bool mfviewer::UDPReceiver::validate_packet(std::string input)
00223 {
00224
00225 if (input.find("MF") == std::string::npos)
00226 {
00227 TLOG(TLVL_WARNING) << "Failed to find \"MF\" in message: " << input;
00228 return false;
00229 }
00230 if (input.find("|") == std::string::npos)
00231 {
00232 TLOG(TLVL_WARNING) << "Failed to find | separator character in message: " << input;
00233 return false;
00234 }
00235 return true;
00236 }
00237
00238 #include "moc_UDP_receiver.cpp"
00239
00240 DEFINE_MFVIEWER_RECEIVER(mfviewer::UDPReceiver)