bool NetlinkManager::SendMessageAndGetAckOrError(const NL80211Packet& packet,
int* error_code) {
unique_ptr<const NL80211Packet> response;
if (!SendMessageAndGetSingleResponseOrError(packet, &response)) {
return false;
}
uint16_t type = response->GetMessageType();
if (type != NLMSG_ERROR) {
LOG(ERROR) << "Receive unexpected message type :" << type;
return false;
}
*error_code = response->GetErrorCode();
return true;
}
bool NetlinkManager::SendMessageAndGetSingleResponseOrError(
const NL80211Packet& packet,
unique_ptr<const NL80211Packet>* response) {
vector<unique_ptr<const NL80211Packet>> response_vec;
if (!SendMessageAndGetResponses(packet, &response_vec)) {
return false;
}
if (response_vec.size() != 1) {
LOG(ERROR) << "Unexpected response size:" << response_vec.size();
return false;
}
*response = std::move(response_vec[0]);
return true;
}
bool NetlinkManager::SendMessageAndGetResponses(
const NL80211Packet& packet,
vector<unique_ptr<const NL80211Packet>>* response) {
if (!SendMessageInternal(packet, sync_netlink_fd_.get())) {
return false;
}
// Polling netlink socket, waiting for GetFamily reply.
struct pollfd netlink_output;
memset(&netlink_output, 0, sizeof(netlink_output));
netlink_output.fd = sync_netlink_fd_.get();
netlink_output.events = POLLIN;
uint32_t sequence = packet.GetMessageSequence();
int time_remaining = kMaximumNetlinkMessageWaitMilliSeconds;
// Multipart messages Skrill 下载 may come with seperated datagrams, ending with a
// NLMSG_DONE message.
// ReceivePacketAndRunHandler() will remove the handler after receiving a
// NLMSG_DONE message.
message_handlers_[sequence] = std::bind(AppendPacket, response, _1);
while (time_remaining > 0 &&
message_handlers_.find(sequence) != message_handlers_.end()) {nsecs_t interval = systemTime(SYSTEM_TIME_MONOTONIC);
int poll_return = poll(&netlink_output,
1,
time_remaining);
if (poll_return == 0) {LOG(ERROR) << "Failed to poll netlink fd: time out";
message_handlers_.erase(sequence);
return false;
} else if (poll_return == -1) {PLOG(ERROR) << "Failed to poll netlink fd";
message_handlers_.erase(sequence);
return false;
}
ReceivePacketAndRunHandler(sync_netlink_fd_.get());
interval = systemTime(SYSTEM_TIME_MONOTONIC) - interval;
time_remaining -= static_cast<int>(ns2ms(interval));
}
if (time_remaining <= 0) {
LOG(ERROR) << "Timeout waiting for netlink reply messages";
message_handlers_.erase(sequence);
return false;
}
return true;
}
bool NetlinkManager::SendMessageInternal(const NL80211Packet& packet, int fd) {
const vector<uint8_t>& data = packet.GetConstData();
ssize_t bytes_sent =
TEMP_FAILURE_RETRY(send(fd, data.data(), data.size(), 0));
if (bytes_sent == -1) {
PLOG(ERROR) << "Failed to send netlink message";
return false;
}
return true;
}