diff options
| author | 2022-07-01 01:34:41 +0000 | |
|---|---|---|
| committer | 2022-07-01 01:34:41 +0000 | |
| commit | 7d93c6df2e5524bc997b22553062fd1c2983a43c (patch) | |
| tree | 36f9ce659d4f5f590169bb4420dae5633f8954f7 | |
| parent | 44f97a532b5b2b93618a9aa790cebcb16f83e5a9 (diff) | |
| parent | 992a405fd8d4025f5c5e7423530f398d459fff6b (diff) | |
Merge "libbinder: use socket operations in testSupportVsockLoopback"
| -rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 93 | 
1 files changed, 82 insertions, 11 deletions
| diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index c8b724b78f..3766278e3f 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -48,6 +48,7 @@  #include <poll.h>  #include <sys/prctl.h> +#include <sys/socket.h>  #include <unistd.h>  #include "../FdTrigger.h" @@ -1652,20 +1653,90 @@ TEST_P(BinderRpc, AidlDelegatorTest) {  static bool testSupportVsockLoopback() {      // We don't need to enable TLS to know if vsock is supported.      unsigned int vsockPort = allocateVsockPort(); -    sp<RpcServer> server = RpcServer::make(RpcTransportCtxFactoryRaw::make()); -    if (status_t status = server->setupVsockServer(vsockPort); status != OK) { -        if (status == -EAFNOSUPPORT) { -            return false; + +    android::base::unique_fd serverFd( +            TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); +    LOG_ALWAYS_FATAL_IF(serverFd == -1, "Could not create socket: %s", strerror(errno)); + +    sockaddr_vm serverAddr{ +            .svm_family = AF_VSOCK, +            .svm_port = vsockPort, +            .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, +                        strerror(errno)); + +    ret = TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/)); +    LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", vsockPort, +                        strerror(errno)); + +    // Try to connect to the server using the VMADDR_CID_LOCAL cid +    // to see if the kernel supports it. It's safe to use a blocking +    // connect because vsock sockets have a 2 second connection timeout, +    // and they return ETIMEDOUT after that. +    android::base::unique_fd connectFd( +            TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); +    LOG_ALWAYS_FATAL_IF(connectFd == -1, "Could not create socket for port %u: %s", vsockPort, +                        strerror(errno)); + +    bool success = false; +    sockaddr_vm connectAddr{ +            .svm_family = AF_VSOCK, +            .svm_port = vsockPort, +            .svm_cid = VMADDR_CID_LOCAL, +    }; +    ret = TEMP_FAILURE_RETRY(connect(connectFd.get(), reinterpret_cast<sockaddr*>(&connectAddr), +                                     sizeof(connectAddr))); +    if (ret != 0 && (errno == EAGAIN || errno == EINPROGRESS)) { +        android::base::unique_fd acceptFd; +        while (true) { +            pollfd pfd[]{ +                    {.fd = serverFd.get(), .events = POLLIN, .revents = 0}, +                    {.fd = connectFd.get(), .events = POLLOUT, .revents = 0}, +            }; +            ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1)); +            LOG_ALWAYS_FATAL_IF(ret < 0, "Error polling: %s", strerror(errno)); + +            if (pfd[0].revents & POLLIN) { +                sockaddr_vm acceptAddr; +                socklen_t acceptAddrLen = sizeof(acceptAddr); +                ret = TEMP_FAILURE_RETRY(accept4(serverFd.get(), +                                                 reinterpret_cast<sockaddr*>(&acceptAddr), +                                                 &acceptAddrLen, SOCK_CLOEXEC)); +                LOG_ALWAYS_FATAL_IF(ret < 0, "Could not accept4 socket: %s", strerror(errno)); +                LOG_ALWAYS_FATAL_IF(acceptAddrLen != static_cast<socklen_t>(sizeof(acceptAddr)), +                                    "Truncated address"); + +                // Store the fd in acceptFd so we keep the connection alive +                // while polling connectFd +                acceptFd.reset(ret); +            } + +            if (pfd[1].revents & POLLOUT) { +                // Connect either succeeded or timed out +                int connectErrno; +                socklen_t connectErrnoLen = sizeof(connectErrno); +                int ret = getsockopt(connectFd.get(), SOL_SOCKET, SO_ERROR, &connectErrno, +                                     &connectErrnoLen); +                LOG_ALWAYS_FATAL_IF(ret == -1, +                                    "Could not getsockopt() after connect() " +                                    "on non-blocking socket: %s.", +                                    strerror(errno)); + +                // We're done, this is all we wanted +                success = connectErrno == 0; +                break; +            }          } -        LOG_ALWAYS_FATAL("Could not setup vsock server: %s", statusToString(status).c_str()); +    } else { +        success = ret == 0;      } -    server->start(); -    sp<RpcSession> session = RpcSession::make(RpcTransportCtxFactoryRaw::make()); -    status_t status = session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort); -    while (!server->shutdown()) usleep(10000); -    ALOGE("Detected vsock loopback supported: %s", statusToString(status).c_str()); -    return status == OK; +    ALOGE("Detected vsock loopback supported: %s", success ? "yes" : "no"); + +    return success;  }  static std::vector<SocketType> testSocketTypes(bool hasPreconnected = true) { |