Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec9c528a authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk Committed by Android (Google) Code Review
Browse files

Merge "Implement Socket::receive<T> and refactor Socket::receiveAck"

parents 41589f07 71396052
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ bool setBitrate(std::string ifname, uint32_t bitrate) {
    }

    nl::Socket sock(NETLINK_ROUTE);
    return sock.send(req) && sock.receiveAck();
    return sock.send(req) && sock.receiveAck(req);
}

}  // namespace android::netdevice::can
+2 −2
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ bool add(std::string dev, std::string type) {
    }

    nl::Socket sock(NETLINK_ROUTE);
    return sock.send(req) && sock.receiveAck();
    return sock.send(req) && sock.receiveAck(req);
}

bool del(std::string dev) {
@@ -80,7 +80,7 @@ bool del(std::string dev) {
    req.addattr(IFLA_IFNAME, dev);

    nl::Socket sock(NETLINK_ROUTE);
    return sock.send(req) && sock.receiveAck();
    return sock.send(req) && sock.receiveAck(req);
}

std::optional<hwaddr_t> getHwAddr(const std::string& ifname) {
+1 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ bool add(const std::string& eth, const std::string& vlan, uint16_t id) {
    }

    nl::Socket sock(NETLINK_ROUTE);
    return sock.send(req) && sock.receiveAck();
    return sock.send(req) && sock.receiveAck(req);
}

}  // namespace android::netdevice::vlan
+27 −42
Original line number Diff line number Diff line
@@ -103,60 +103,45 @@ std::pair<std::optional<Buffer<nlmsghdr>>, sockaddr_nl> Socket::receiveFrom(size
    return {msg, sa};
}

/* TODO(161389935): Migrate receiveAck to use nlmsg<> internally. Possibly reuse
 * Socket::receive(). */
bool Socket::receiveAck() {
    if (mFailed) return false;

    char buf[8192];

    sockaddr_nl sa;
    iovec iov = {buf, sizeof(buf)};

    msghdr msg = {};
    msg.msg_name = &sa;
    msg.msg_namelen = sizeof(sa);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
bool Socket::receiveAck(uint32_t seq) {
    const auto nlerr = receive<nlmsgerr>({NLMSG_ERROR});
    if (!nlerr.has_value()) return false;

    const ssize_t status = recvmsg(mFd.get(), &msg, 0);
    if (status < 0) {
        PLOG(ERROR) << "Failed to receive Netlink message";
    if (nlerr->data.msg.nlmsg_seq != seq) {
        LOG(ERROR) << "Received ACK for a different message (" << nlerr->data.msg.nlmsg_seq
                   << ", expected " << seq << "). Multi-message tracking is not implemented.";
        return false;
    }
    size_t remainingLen = status;

    if (msg.msg_flags & MSG_TRUNC) {
        LOG(ERROR) << "Failed to receive Netlink message: truncated";
    if (nlerr->data.error == 0) return true;

    LOG(WARNING) << "Received Netlink error message: " << strerror(-nlerr->data.error);
    return false;
}

    for (auto nlmsg = reinterpret_cast<nlmsghdr*>(buf); NLMSG_OK(nlmsg, remainingLen);
         nlmsg = NLMSG_NEXT(nlmsg, remainingLen)) {
        if constexpr (kSuperVerbose) {
            LOG(VERBOSE) << "received Netlink response: "
                         << toString({nlmsg, nlmsg->nlmsg_len}, mProtocol);
        }
std::optional<Buffer<nlmsghdr>> Socket::receive(const std::set<nlmsgtype_t>& msgtypes,
                                                size_t maxSize) {
    while (!mFailed) {
        const auto msgBuf = receive(maxSize);
        if (!msgBuf.has_value()) return std::nullopt;

        // We're looking for error/ack message only, ignoring others.
        if (nlmsg->nlmsg_type != NLMSG_ERROR) {
            LOG(WARNING) << "Received unexpected Netlink message (ignored): " << nlmsg->nlmsg_type;
        for (const auto rawMsg : *msgBuf) {
            if (msgtypes.count(rawMsg->nlmsg_type) == 0) {
                LOG(WARNING) << "Received (and ignored) unexpected Netlink message of type "
                             << rawMsg->nlmsg_type;
                continue;
            }

        // Found error/ack message, return status.
        const auto nlerr = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(nlmsg));
        if (nlerr->error != 0) {
            LOG(ERROR) << "Received Netlink error message: " << strerror(-nlerr->error);
            return false;
            return rawMsg;
        }
        return true;
    }
    // Couldn't find any error/ack messages.
    return false;

    return std::nullopt;
}

std::optional<unsigned> Socket::getPid() {
    if (mFailed) return std::nullopt;

    sockaddr_nl sa = {};
    socklen_t sasize = sizeof(sa);
    if (getsockname(mFd.get(), reinterpret_cast<sockaddr*>(&sa), &sasize) < 0) {
+4 −1
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#include <libnl++/Attributes.h>
#include <libnl++/Buffer.h>

#include <set>

namespace android::nl {

/**
@@ -60,7 +62,8 @@ class Message {
     * \return Parsed message or nullopt, if the buffer data is invalid or message type
     *         doesn't match.
     */
    static std::optional<Message<T>> parse(Buffer<nlmsghdr> buf, std::set<nlmsgtype_t> msgtypes) {
    static std::optional<Message<T>> parse(Buffer<nlmsghdr> buf,
                                           const std::set<nlmsgtype_t>& msgtypes) {
        const auto& [nlOk, nlHeader] = buf.getFirst();  // we're doing it twice, but it's fine
        if (!nlOk) return std::nullopt;

Loading