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