in Netlink.cpp [380:478]
void Netlink::handle_msg(uint16_t msg_type, uint16_t msg_flags, uint32_t msg_seq, const void* payload_data, size_t payload_len) {
reply_fn_t* fn_ptr = nullptr;
bool done = false;
std::shared_ptr<ReplyRec> reply;
if (msg_seq != 0) {
// The seq is non-zero so this message should be a reply to a request
// look for the reply_fn associates with this seq #
std::lock_guard<std::mutex> _lock(_run_mutex);
auto itr = _replies.find(msg_seq);
if (itr != _replies.end()) {
reply = itr->second;
fn_ptr = &reply->_fn;
done = reply->_done;
reply->_req_age = std::chrono::steady_clock::now();
_known_seq[msg_seq] = reply->_req_age;
} else {
// No ReplyRec found for the seq #
done = true;
// Only print a warning if the seq # is not known
if (_known_seq.count(msg_seq) == 0) {
Logger::Warn("Received unexpected NETLINK packet (Type: %d, Flags: 0x%X, Seq: %d, Size: %ld",
msg_type, msg_flags, msg_seq, payload_len);
}
}
} else {
if (_default_msg_handler_fn) {
fn_ptr = &_default_msg_handler_fn;
} else {
done = true;
Logger::Warn(
"Received NETLINK packet With Seq 0 and no default handler is defined (Type: %d, Flags: 0x%X, Size: %ld",
msg_type, msg_flags, payload_len);
}
}
// If the request hasn't been marked done, has a valid reply_fn associated, and the message is not of type NLMSG_ERRROR or NLMSG_DONE
// then call the reply_fn
if (!done && fn_ptr != nullptr && *fn_ptr && msg_type != NLMSG_ERROR && msg_type != NLMSG_DONE) {
try {
if (!(*fn_ptr)(msg_type, msg_flags, payload_data, payload_len) && msg_seq > 0) {
// The reply_fn returned false, so mark the request as complete.
std::lock_guard<std::mutex> _lock(_run_mutex);
if (reply) {
reply->_done = true;
reply->_promise.set_value(0);
}
return;
}
} catch (const std::exception &ex) {
if (msg_seq > 0) {
// The reply_fn threw an exception, try to propagate the exception through the request promise
std::lock_guard<std::mutex> _lock(_run_mutex);
if (reply) {
try {
reply->_promise.set_exception(std::current_exception());
reply->_done = true;
} catch (const std::exception &ex) {
Logger::Error(
"Unexpected exception while trying to set exception in NETLINK msg reply promise: %s",
ex.what());
}
_replies.erase(msg_seq);
}
}
return;
}
}
if (msg_seq != 0) {
if (msg_type == NLMSG_ERROR) {
auto err = reinterpret_cast<const nlmsgerr *>(payload_data);
std::lock_guard<std::mutex> _lock(_run_mutex);
// If the request failed, or the request succeeded but no response is expected then set the value to err->error
// If !fn then no response is expected and the return value is err->error (typically == 0)
if (err->error != 0 || fn_ptr == nullptr || !(*fn_ptr)) {
if (reply) {
if (!reply->_done) {
reply->_done = true;
reply->_promise.set_value(err->error);
}
_replies.erase(msg_seq);
}
_known_seq.erase(msg_seq);
}
} else if ((msg_flags & NLM_F_MULTI) == 0 || msg_type == NLMSG_DONE) {
std::lock_guard<std::mutex> _lock(_run_mutex);
if (reply) {
if (!reply->_done) {
reply->_promise.set_value(0);
reply->_done = true;
}
_replies.erase(msg_seq);
}
_known_seq.erase(msg_seq);
}
}
}