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

Commit 1975aaa5 authored by Andrei Homescu's avatar Andrei Homescu
Browse files

libbinder: replace RpcTransport::peek() with pollRead()

peek uses MSG_PEEK internally which only works with sockets.
This refactors that function into a more specific pollRead()
which works for e.g. pipes and other files.

Bug: 224644083
Test: atest binderRpcTest
Change-Id: I340fa7ee7a7bb2077115fc28835bcadf67db03d9
parent 97c1356a
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -661,13 +661,10 @@ status_t RpcState::getAndExecuteCommand(const sp<RpcSession::RpcConnection>& con

status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection,
                                 const sp<RpcSession>& session, CommandType type) {
    uint8_t buf;
    while (true) {
        size_t num_bytes;
        status_t status = connection->rpcTransport->peek(&buf, sizeof(buf), &num_bytes);
        status_t status = connection->rpcTransport->pollRead();
        if (status == WOULD_BLOCK) break;
        if (status != OK) return status;
        if (!num_bytes) break;

        status = getAndExecuteCommand(connection, session, type);
        if (status != OK) return status;
+7 −4
Original line number Diff line number Diff line
@@ -32,19 +32,22 @@ namespace {
class RpcTransportRaw : public RpcTransport {
public:
    explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
    status_t peek(void* buf, size_t size, size_t* out_size) override {
        ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK));
    status_t pollRead(void) override {
        uint8_t buf;
        ssize_t ret = TEMP_FAILURE_RETRY(
                ::recv(mSocket.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
        if (ret < 0) {
            int savedErrno = errno;
            if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
                return WOULD_BLOCK;
            }

            LOG_RPC_DETAIL("RpcTransport peek(): %s", strerror(savedErrno));
            LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
            return -savedErrno;
        } else if (ret == 0) {
            return DEAD_OBJECT;
        }

        *out_size = static_cast<size_t>(ret);
        return OK;
    }

+4 −5
Original line number Diff line number Diff line
@@ -277,7 +277,7 @@ class RpcTransportTls : public RpcTransport {
public:
    RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
          : mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
    status_t peek(void* buf, size_t size, size_t* out_size) override;
    status_t pollRead(void) override;
    status_t interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
                                     const std::function<status_t()>& altPoll) override;
    status_t interruptableReadFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
@@ -289,9 +289,9 @@ private:
};

// Error code is errno.
status_t RpcTransportTls::peek(void* buf, size_t size, size_t* out_size) {
    size_t todo = std::min<size_t>(size, std::numeric_limits<int>::max());
    auto [ret, errorQueue] = mSsl.call(SSL_peek, buf, static_cast<int>(todo));
status_t RpcTransportTls::pollRead(void) {
    uint8_t buf;
    auto [ret, errorQueue] = mSsl.call(SSL_peek, &buf, sizeof(buf));
    if (ret < 0) {
        int err = mSsl.getError(ret);
        if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
@@ -304,7 +304,6 @@ status_t RpcTransportTls::peek(void* buf, size_t size, size_t* out_size) {
    }
    errorQueue.clear();
    LOG_TLS_DETAIL("TLS: Peeked %d bytes!", ret);
    *out_size = static_cast<size_t>(ret);
    return OK;
}

+9 −2
Original line number Diff line number Diff line
@@ -39,8 +39,15 @@ class RpcTransport {
public:
    virtual ~RpcTransport() = default;

    // replacement of ::recv(MSG_PEEK). Error code may not be set if TLS is enabled.
    [[nodiscard]] virtual status_t peek(void *buf, size_t size, size_t *out_size) = 0;
    /**
     * Poll the transport to check whether there is any data ready to read.
     *
     * Return:
     *   OK - There is data available on this transport
     *   WOULDBLOCK - No data is available
     *   error - any other error
     */
    [[nodiscard]] virtual status_t pollRead(void) = 0;

    /**
     * Read (or write), but allow to be interrupted by a trigger.