1 #define TRACE_NAME "UDP_Receiver"
3 #include "mfextensions/Receivers/UDP_receiver.hh"
6 #include "messagefacility/Utilities/ELseverityLevel.h"
7 #include "mfextensions/Receivers/ReceiverMacros.hh"
12 , message_port_(pset.get<int>(
"port", 5140))
13 , message_addr_(pset.get<std::string>(
"message_address",
"227.128.12.27"))
14 , multicast_enable_(pset.get<bool>(
"multicast_enable", false))
15 , multicast_out_addr_(pset.get<std::string>(
"multicast_interface_ip",
"0.0.0.0"))
18 TLOG(TLVL_TRACE) <<
"UDPReceiver Constructor";
21 void mfviewer::UDPReceiver::setupMessageListener_()
23 TLOG(TLVL_INFO) <<
"Setting up message listen socket, address=" << message_addr_ <<
":" << message_port_;
24 message_socket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
25 if (message_socket_ < 0)
27 TLOG(TLVL_ERROR) <<
"Error creating socket for receiving messages! err=" << strerror(errno);
31 struct sockaddr_in si_me_request;
34 if (setsockopt(message_socket_, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(yes)) < 0)
36 TLOG(TLVL_ERROR) <<
"Unable to enable port reuse on message socket, err=" << strerror(errno);
39 memset(&si_me_request, 0,
sizeof(si_me_request));
40 si_me_request.sin_family = AF_INET;
41 si_me_request.sin_port = htons(message_port_);
42 si_me_request.sin_addr.s_addr = htonl(INADDR_ANY);
43 if (bind(message_socket_, reinterpret_cast<struct sockaddr*>(&si_me_request),
sizeof(si_me_request)) == -1)
45 TLOG(TLVL_ERROR) <<
"Cannot bind message socket to port " << message_port_ <<
", err=" << strerror(errno);
49 if (message_addr_ !=
"localhost" && multicast_enable_)
52 int sts =
ResolveHost(message_addr_.c_str(), mreq.imr_multiaddr);
55 TLOG(TLVL_ERROR) <<
"Unable to resolve multicast message address, err=" << strerror(errno);
61 TLOG(TLVL_ERROR) <<
"Unable to resolve hostname for " << multicast_out_addr_;
64 if (setsockopt(message_socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0)
66 TLOG(TLVL_ERROR) <<
"Unable to join multicast group, err=" << strerror(errno);
70 TLOG(TLVL_INFO) <<
"Done setting up message receive socket";
75 TLOG(TLVL_DEBUG) <<
"Closing message receive socket";
76 close(message_socket_);
82 while (!stopRequested_)
84 if (message_socket_ == -1) setupMessageListener_();
87 struct pollfd ufds[1];
88 ufds[0].fd = message_socket_;
89 ufds[0].events = POLLIN | POLLPRI | POLLERR;
90 int rv = poll(ufds, 1, ms_to_wait);
93 if (rv <= 0 || (ufds[0].revents != POLLIN && ufds[0].revents != POLLPRI))
95 if (rv == 1 && (ufds[0].revents & (POLLNVAL | POLLERR | POLLHUP)))
97 close(message_socket_);
107 char buffer[TRACE_STREAMER_MSGMAX + 1];
108 auto packetSize = read(message_socket_, &buffer, TRACE_STREAMER_MSGMAX);
111 TLOG(TLVL_ERROR) <<
"Error receiving message, errno=" << errno <<
" (" << strerror(errno) <<
")";
115 TLOG(TLVL_TRACE) <<
"Recieved message; validating...(packetSize=" << packetSize <<
")";
116 std::string message(buffer, buffer + packetSize);
117 if (validate_packet(message))
119 TLOG(TLVL_TRACE) <<
"Valid UDP Message received! Sending to GUI!";
120 emit NewMessage(read_msg(message));
124 TLOG(TLVL_INFO) <<
"UDPReceiver shutting down!";
127 std::list<std::string> mfviewer::UDPReceiver::tokenize_(std::string
const& input)
130 std::list<std::string> output;
132 while (pos != std::string::npos && pos < input.size())
134 auto newpos = input.find(
'|', pos);
135 if (newpos != std::string::npos)
137 output.emplace_back(input, pos, newpos - pos);
143 output.emplace_back(input, pos);
153 std::string hostname, category, application, message, hostaddr, file, line, module, eventID;
154 mf::ELseverityLevel sev;
159 TLOG(TLVL_TRACE) <<
"Recieved MF/Syslog message with contents: " << input;
161 auto tokens = tokenize_(input);
162 auto it = tokens.begin();
164 if (it != tokens.end())
166 bool timestamp_found =
false;
169 while (it != tokens.end() && !timestamp_found)
171 std::string thisString = *it;
172 while (!thisString.empty() && !timestamp_found)
174 auto pos = thisString.find_first_of(
"0123456789");
175 if (pos != std::string::npos)
177 thisString = thisString.erase(0, pos);
180 if (strptime(thisString.c_str(),
"%d-%b-%Y %H:%M:%S", &tm) !=
nullptr)
182 timestamp_found =
true;
186 if (!thisString.empty() )
187 thisString = thisString.erase(0, 1);
201 if (it != tokens.end() && ++it != tokens.end() )
203 seqNum = std::stoi(*it);
206 catch (
const std::invalid_argument& e)
210 if (it != tokens.end() && ++it != tokens.end() )
214 if (it != tokens.end() && ++it != tokens.end() )
218 if (it != tokens.end() && ++it != tokens.end() )
220 sev = mf::ELseverityLevel(*it);
222 if (it != tokens.end() && ++it != tokens.end() )
226 if (it != tokens.end() && ++it != tokens.end() )
233 if (it != tokens.end() && ++it != tokens.end() )
235 pid = std::stol(*it);
238 catch (
const std::invalid_argument& e)
242 if (it != tokens.end() && ++it != tokens.end() )
246 if (it != tokens.end() && ++it != tokens.end() )
250 if (it != tokens.end() && ++it != tokens.end() )
254 if (it != tokens.end() && ++it != tokens.end() )
258 std::ostringstream oss;
260 while (it != tokens.end() && ++it != tokens.end() )
272 TLOG(TLVL_TRACE) <<
"Message content: " << oss.str();
276 auto msg = std::make_shared<qt_mf_msg>(hostname, category, application, pid, tv);
277 msg->setSeverity(sev);
278 msg->setMessage(
"UDPMessage", seqNum, message);
279 msg->setHostAddr(hostaddr);
280 msg->setFileName(file);
281 msg->setLineNumber(line);
282 msg->setModule(module);
283 msg->setEventID(eventID);
292 if (input.find(
"MF") == std::string::npos)
294 TLOG(TLVL_WARNING) <<
"Failed to find \"MF\" in message: " << input;
297 if (input.find(
"|") == std::string::npos)
299 TLOG(TLVL_WARNING) <<
"Failed to find | separator character in message: " << input;
305 #include "moc_UDP_receiver.cpp"
void run() override
Receiver method. Receive messages and emit NewMessage signal
int ResolveHost(char const *host_in, in_addr &addr)
Convert a string hostname to a in_addr suitable for socket communication.
Receive messages through a UDP socket. Expects the syslog format provided by UDP_mfPlugin (ELUDP) ...
UDPReceiver(fhicl::ParameterSet const &pset)
UDPReceiver Constructor
int GetInterfaceForNetwork(char const *host_in, in_addr &addr)
Convert an IP address to the network address of the interface sharing the subnet mask.
static bool validate_packet(std::string const &input)
Run simple validation tests on message
msg_ptr_t read_msg(std::string const &input)
Parse incoming message
virtual ~UDPReceiver()
Destructor – Close socket
A MVReceiver class listens for messages and raises a signal when one arrives