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

Commit 022db680 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

RpcServer: let system allocate vsock ports

This greatly improves stability with concurrent test execution

Bug: 285204695
Test: atest --host binder_sdk_test
Change-Id: Ib7b76df693288033e55fa27786bf6efb21d0ebf0
parent 1d46f583
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -71,8 +71,23 @@ status_t RpcServer::setupUnixDomainServer(const char* path) {
    return setupSocketServer(UnixSocketAddress(path));
}

status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) {
    return setupSocketServer(VsockSocketAddress(bindCid, port));
status_t RpcServer::setupVsockServer(unsigned bindCid, unsigned port, unsigned* assignedPort) {
    auto status = setupSocketServer(VsockSocketAddress(bindCid, port));
    if (status != OK) return status;

    if (assignedPort == nullptr) return OK;
    sockaddr_vm addr;
    socklen_t len = sizeof(addr);
    if (0 != getsockname(mServer.fd.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
        status = -errno;
        ALOGE("setupVsockServer: Failed to getsockname: %s", strerror(-status));
        return status;
    }

    LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu",
                        static_cast<size_t>(len), sizeof(addr));
    *assignedPort = addr.svm_port;
    return OK;
}

status_t RpcServer::setupInetServer(const char* address, unsigned int port,
+5 −2
Original line number Diff line number Diff line
@@ -85,9 +85,12 @@ public:

    /**
     * Creates an RPC server binding to the given CID at the given port.
     *
     * Set |port| to VMADDR_PORT_ANY to pick an ephemeral port. In this case, |assignedPort|
     * will be set to the picked port number, if it is not null.
     */
    [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned int bindCid,
                                                               unsigned int port);
    [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned bindCid, unsigned port,
                                                               unsigned* assignedPort = nullptr);

    /**
     * Creates an RPC server at the current port using IPv4.
+0 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ parcelable BinderRpcTestServerConfig {
    int socketType;
    int rpcSecurity;
    int serverVersion;
    int vsockPort;
    int socketFd; // Inherited from the parent process.
    @utf8InCpp String addr;
}
+15 −17
Original line number Diff line number Diff line
@@ -141,11 +141,6 @@ static std::string allocateSocketAddress() {
    return ret;
};

static unsigned int allocateVsockPort() {
    static unsigned int vsockPort = 34567;
    return vsockPort++;
}

static unique_fd initUnixSocket(std::string addr) {
    auto socket_addr = UnixSocketAddress(addr.c_str());
    unique_fd fd(TEMP_FAILURE_RETRY(socket(socket_addr.addr()->sa_family, SOCK_STREAM, AF_UNIX)));
@@ -300,7 +295,6 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
    serverConfig.socketType = static_cast<int32_t>(socketType);
    serverConfig.rpcSecurity = static_cast<int32_t>(rpcSecurity);
    serverConfig.serverVersion = serverVersion;
    serverConfig.vsockPort = allocateVsockPort();
    serverConfig.addr = addr;
    serverConfig.socketFd = socketFd.get();
    for (auto mode : options.serverSupportedFileDescriptorTransportModes) {
@@ -379,7 +373,7 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
                        unique_fd(dup(bootstrapClientFd.get())));
                break;
            case SocketType::VSOCK:
                status = session->setupVsockClient(VMADDR_CID_LOCAL, serverConfig.vsockPort);
                status = session->setupVsockClient(VMADDR_CID_LOCAL, serverInfo.port);
                break;
            case SocketType::INET:
                status = session->setupInetClient("127.0.0.1", serverInfo.port);
@@ -1152,8 +1146,6 @@ INSTANTIATE_TEST_SUITE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderR
#else // BINDER_RPC_TO_TRUSTY_TEST
bool testSupportVsockLoopback() {
    // We don't need to enable TLS to know if vsock is supported.
    unsigned int vsockPort = allocateVsockPort();

    unique_fd serverFd(
            TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));

@@ -1165,16 +1157,21 @@ bool testSupportVsockLoopback() {

    sockaddr_vm serverAddr{
            .svm_family = AF_VSOCK,
            .svm_port = vsockPort,
            .svm_port = VMADDR_PORT_ANY,
            .svm_cid = VMADDR_CID_ANY,
    };
    int ret = TEMP_FAILURE_RETRY(
            bind(serverFd.get(), reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr)));
    LOG_ALWAYS_FATAL_IF(0 != ret, "Could not bind socket to port %u: %s", vsockPort,
    LOG_ALWAYS_FATAL_IF(0 != ret, "Could not bind socket to port VMADDR_PORT_ANY: %s",
                        strerror(errno));

    socklen_t len = sizeof(serverAddr);
    ret = getsockname(serverFd.get(), reinterpret_cast<sockaddr*>(&serverAddr), &len);
    LOG_ALWAYS_FATAL_IF(0 != ret, "Failed to getsockname: %s", strerror(errno));
    LOG_ALWAYS_FATAL_IF(len < sizeof(serverAddr), "getsockname didn't read the full addr struct");

    ret = TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/));
    LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", vsockPort,
    LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", serverAddr.svm_port,
                        strerror(errno));

    // Try to connect to the server using the VMADDR_CID_LOCAL cid
@@ -1183,13 +1180,13 @@ bool testSupportVsockLoopback() {
    // and they return ETIMEDOUT after that.
    unique_fd connectFd(
            TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
    LOG_ALWAYS_FATAL_IF(!connectFd.ok(), "Could not create socket for port %u: %s", vsockPort,
                        strerror(errno));
    LOG_ALWAYS_FATAL_IF(!connectFd.ok(), "Could not create socket for port %u: %s",
                        serverAddr.svm_port, strerror(errno));

    bool success = false;
    sockaddr_vm connectAddr{
            .svm_family = AF_VSOCK,
            .svm_port = vsockPort,
            .svm_port = serverAddr.svm_port,
            .svm_cid = VMADDR_CID_LOCAL,
    };
    ret = TEMP_FAILURE_RETRY(connect(connectFd.get(), reinterpret_cast<sockaddr*>(&connectAddr),
@@ -1538,8 +1535,9 @@ public:
                    };
                } break;
                case SocketType::VSOCK: {
                    auto port = allocateVsockPort();
                    auto status = rpcServer->setupVsockServer(VMADDR_CID_LOCAL, port);
                    unsigned port;
                    auto status =
                            rpcServer->setupVsockServer(VMADDR_CID_LOCAL, VMADDR_PORT_ANY, &port);
                    if (status != OK) {
                        return AssertionFailure() << "setupVsockServer: " << statusToString(status);
                    }
+2 −2
Original line number Diff line number Diff line
@@ -143,8 +143,8 @@ int main(int argc, char* argv[]) {
            break;
        case SocketType::VSOCK:
            LOG_ALWAYS_FATAL_IF(OK !=
                                        server->setupVsockServer(VMADDR_CID_LOCAL,
                                                                 serverConfig.vsockPort),
                                        server->setupVsockServer(VMADDR_CID_LOCAL, VMADDR_PORT_ANY,
                                                                 &outPort),
                                "Need `sudo modprobe vsock_loopback`?");
            break;
        case SocketType::INET: {