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

Commit d290bb7e authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add native vsock support to ADB."

parents 3c2c9d8d a05b64d4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1134,7 +1134,9 @@ bool handle_host_request(const char* service, TransportType type, const char* se
        std::string host;
        int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
        std::string error;
        if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) {
        if (address.starts_with("vsock:")) {
            serial = address;
        } else if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) {
            SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
                                                           address.c_str(), error.c_str()));
            return true;
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ void qemu_socket_thread(int port) {
        /* This could be an older version of the emulator, that doesn't
         * implement adb QEMUD service. Fall back to the old TCP way. */
        D("adb service is not available. Falling back to TCP socket.");
        std::thread(server_socket_thread, port).detach();
        std::thread(server_socket_thread, android::base::StringPrintf("tcp:%d", port)).detach();
        return;
    }

+116 −3
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ using android::base::StringPrintf;
#define ADB_WINDOWS 0
#endif

#if ADB_LINUX
#include <sys/socket.h>
#include "sysdeps/vm_sockets.h"
#endif

// Not static because it is used in commandline.c.
int gListenAll = 0;

@@ -174,6 +179,62 @@ bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std
            return true;
        }
        return false;
    } else if (address.starts_with("vsock:")) {
#if ADB_LINUX
        std::string spec_str(address);
        std::vector<std::string> fragments = android::base::Split(spec_str, ":");
        unsigned int port_value = port ? *port : 0;
        if (fragments.size() != 2 && fragments.size() != 3) {
            *error = android::base::StringPrintf("expected vsock:cid or vsock:port:cid in '%s'",
                                                 spec_str.c_str());
            errno = EINVAL;
            return false;
        }
        unsigned int cid = 0;
        if (!android::base::ParseUint(fragments[1], &cid)) {
            *error = android::base::StringPrintf("could not parse vsock cid in '%s'",
                                                 spec_str.c_str());
            errno = EINVAL;
            return false;
        }
        if (fragments.size() == 3 && !android::base::ParseUint(fragments[2], &port_value)) {
            *error = android::base::StringPrintf("could not parse vsock port in '%s'",
                                                 spec_str.c_str());
            errno = EINVAL;
            return false;
        }
        if (port_value == 0) {
            *error = android::base::StringPrintf("vsock port was not provided.");
            errno = EINVAL;
            return false;
        }
        fd->reset(socket(AF_VSOCK, SOCK_STREAM, 0));
        if (fd->get() == -1) {
            *error = "could not open vsock socket";
            return false;
        }
        sockaddr_vm addr{};
        addr.svm_family = AF_VSOCK;
        addr.svm_port = port_value;
        addr.svm_cid = cid;
        if (serial) {
            *serial = android::base::StringPrintf("vsock:%u:%d", cid, port_value);
        }
        if (connect(fd->get(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) {
            int error_num = errno;
            *error = android::base::StringPrintf("could not connect to vsock address '%s'",
                                                 spec_str.c_str());
            errno = error_num;
            return false;
        }
        if (port) {
            *port = port_value;
        }
        return true;
#else   // ADB_LINUX
        *error = "vsock is only supported on linux";
        return false;
#endif  // ADB_LINUX
    }

    for (const auto& it : kLocalSocketTypes) {
@@ -187,6 +248,9 @@ bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std

            fd->reset(network_local_client(&address[prefix.length()], it.second.socket_namespace,
                                           SOCK_STREAM, error));
            if (serial) {
                *serial = address;
            }
            return true;
        }
    }
@@ -196,7 +260,7 @@ bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std
    return false;
}

int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port) {
int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_port) {
    if (spec.starts_with("tcp:")) {
        std::string hostname;
        int port;
@@ -215,10 +279,59 @@ int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_
            return -1;
        }

        if (result >= 0 && port == 0 && resolved_tcp_port) {
            *resolved_tcp_port = adb_socket_get_local_port(result);
        if (result >= 0 && resolved_port) {
            *resolved_port = adb_socket_get_local_port(result);
        }
        return result;
    } else if (spec.starts_with("vsock:")) {
#if ADB_LINUX
        std::string spec_str(spec);
        std::vector<std::string> fragments = android::base::Split(spec_str, ":");
        if (fragments.size() != 2) {
            *error = "given vsock server socket string was invalid";
            return -1;
        }
        int port;
        if (!android::base::ParseInt(fragments[1], &port)) {
            *error = "could not parse vsock port";
            errno = EINVAL;
            return -1;
        } else if (port < 0) {
            *error = "vsock port was negative.";
            errno = EINVAL;
            return -1;
        }
        unique_fd serverfd(socket(AF_VSOCK, SOCK_STREAM, 0));
        if (serverfd == -1) {
            int error_num = errno;
            *error = android::base::StringPrintf("could not create vsock server: '%s'",
                                                 strerror(error_num));
            errno = error_num;
            return -1;
        }
        sockaddr_vm addr{};
        addr.svm_family = AF_VSOCK;
        addr.svm_port = port == 0 ? VMADDR_PORT_ANY : port;
        addr.svm_cid = VMADDR_CID_ANY;
        socklen_t addr_len = sizeof(addr);
        if (bind(serverfd, reinterpret_cast<struct sockaddr*>(&addr), addr_len)) {
            return -1;
        }
        if (listen(serverfd, 4)) {
            return -1;
        }
        if (serverfd >= 0 && resolved_port) {
            if (getsockname(serverfd, reinterpret_cast<sockaddr*>(&addr), &addr_len) == 0) {
                *resolved_port = addr.svm_port;
            } else {
                return -1;
            }
        }
        return serverfd.release();
#else   // ADB_LINUX
        *error = "vsock is only supported on linux";
        return -1;
#endif  // ADB_LINUX
    }

    for (const auto& it : kLocalSocketTypes) {
+8 −0
Original line number Diff line number Diff line
@@ -609,6 +609,14 @@ bool parse_host_service(std::string_view* out_serial, std::string_view* out_comm
            return false;
        }
    }
    if (command.starts_with("vsock:")) {
        // vsock serials are vsock:cid:port, which have an extra colon compared to tcp.
        size_t next_colon = command.find(':');
        if (next_colon == std::string::npos) {
            return false;
        }
        consume(next_colon + 1);
    }

    bool found_address = false;
    if (command[0] == '[') {
+49 −0
Original line number Diff line number Diff line
#if __BIONIC__
#include <linux/vm_sockets.h>
#else
/****************************************************************************
 ****************************************************************************
 ***
 ***   This header was automatically generated from a Linux kernel header
 ***   of the same name, to make information necessary for userspace to
 ***   call into the kernel available to libc.  It contains only constants,
 ***   structures, and macros generated from the original header, and thus,
 ***   contains no copyrightable information.
 ***
 ***   Copied and modified from bionic/libc/kernel/uapi/linux/vm_sockets.h
 ***
 ****************************************************************************
 ****************************************************************************/
#ifndef _UAPI_VM_SOCKETS_H
#define _UAPI_VM_SOCKETS_H
#include <linux/socket.h>
#define SO_VM_SOCKETS_BUFFER_SIZE 0
#define SO_VM_SOCKETS_BUFFER_MIN_SIZE 1
#define SO_VM_SOCKETS_BUFFER_MAX_SIZE 2
#define SO_VM_SOCKETS_PEER_HOST_VM_ID 3
#define SO_VM_SOCKETS_TRUSTED 5
#define SO_VM_SOCKETS_CONNECT_TIMEOUT 6
#define SO_VM_SOCKETS_NONBLOCK_TXRX 7
#define VMADDR_CID_ANY -1U
#define VMADDR_PORT_ANY -1U
#define VMADDR_CID_HYPERVISOR 0
#define VMADDR_CID_RESERVED 1
#define VMADDR_CID_HOST 2
#define VM_SOCKETS_INVALID_VERSION -1U
#define VM_SOCKETS_VERSION_EPOCH(_v) (((_v)&0xFF000000) >> 24)
#define VM_SOCKETS_VERSION_MAJOR(_v) (((_v)&0x00FF0000) >> 16)
#define VM_SOCKETS_VERSION_MINOR(_v) (((_v)&0x0000FFFF))
struct sockaddr_vm {
    __kernel_sa_family_t svm_family;
    unsigned short svm_reserved1;
    unsigned int svm_port;
    unsigned int svm_cid;
    unsigned char svm_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - sizeof(unsigned short) -
                           sizeof(unsigned int) - sizeof(unsigned int)];
};
#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
#ifndef AF_VSOCK
#define AF_VSOCK 40
#endif
#endif
#endif
Loading