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

Commit 5200c667 authored by Spencer Low's avatar Spencer Low
Browse files

adb: win32: initial IPv6 support and improved Winsock error reporting



Call getaddrinfo() for connecting to IPv6 destinations.

Winsock APIs do not set errno. WSAGetLastError() returns Winsock errors
that are more numerous than BSD sockets, so it really doesn't make sense
to map those to BSD socket errors. Plus, even if we did that, the
Windows C Runtime (that mingw binaries use) has a strerror() that does
not recognize BSD socket error codes.

The solution is to wrap the various libcutils socket_* APIs with
sysdeps.h network_* APIs. For POSIX, the network_* APIs just call
strerror(). For Windows, they call SystemErrorCodeToString() (adapted
from Chromium).

Also in this change:

 - Various other code was modified to return errors in a std::string*
   argument, to be able to surface the error string to the end-user.

 - Improved error checking and use of D() to log Winsock errors for
   improved debuggability.

 - For sysdeps_win32.cpp, added unique_fh class that works like
   std::unique_ptr, for calling _fh_close().

 - Fix win32 adb_socketpair() setting of errno in error case.

 - Improve _socket_set_errno() D() logging to reduce confusion. Map
   a few extra error codes.

 - Move adb_shutdown() lower in sysdeps_win32.cpp so it can call
   _socket_set_errno().

 - Move network_connect() from adb_utils.cpp to sysdeps.h.

 - Merge socket_loopback_server() and socket_inaddr_any_server() into
   _network_server() since most of the code was identical.

Change-Id: I945f36870f320578b3a11ba093852ba6f7b93400
Signed-off-by: default avatarSpencer Low <CompareAndSwap@gmail.com>
parent 7b98bfcc
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -801,11 +801,13 @@ int handle_forward_request(const char* service, TransportType type, const char*
            return 1;
        }

        std::string error;
        InstallStatus r;
        if (kill_forward) {
            r = remove_listener(pieces[0].c_str(), transport);
        } else {
            r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind);
            r = install_listener(pieces[0], pieces[1].c_str(), transport,
                                 no_rebind, &error);
        }
        if (r == INSTALL_STATUS_OK) {
#if ADB_HOST
@@ -821,7 +823,8 @@ int handle_forward_request(const char* service, TransportType type, const char*
          case INSTALL_STATUS_OK: message = "success (!)"; break;
          case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
          case INSTALL_STATUS_CANNOT_BIND:
            message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
            message = android::base::StringPrintf("cannot bind to socket: %s",
                                                  error.c_str());
            break;
          case INSTALL_STATUS_CANNOT_REBIND:
            message = android::base::StringPrintf("cannot rebind existing socket");
+4 −3
Original line number Diff line number Diff line
@@ -153,8 +153,8 @@ int _adb_connect(const std::string& service, std::string* error) {
    }

    int fd;
    if (__adb_server_name) {
    std::string reason;
    if (__adb_server_name) {
        fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
        if (fd == -1) {
            *error = android::base::StringPrintf("can't connect to %s:%d: %s",
@@ -163,9 +163,10 @@ int _adb_connect(const std::string& service, std::string* error) {
            return -2;
        }
    } else {
        fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
        fd = network_loopback_client(__adb_server_port, SOCK_STREAM, &reason);
        if (fd == -1) {
            *error = perror_str("cannot connect to daemon");
            *error = android::base::StringPrintf("cannot connect to daemon: %s",
                                                 reason.c_str());
            return -2;
        }
    }
+14 −10
Original line number Diff line number Diff line
@@ -110,27 +110,30 @@ static void listener_disconnect(void* listener, atransport* t) {
    free_listener(reinterpret_cast<alistener*>(listener));
}

static int local_name_to_fd(const char* name) {
static int local_name_to_fd(const char* name, std::string* error) {
    if (!strncmp("tcp:", name, 4)) {
        int port = atoi(name + 4);
        if (gListenAll > 0) {
            return socket_inaddr_any_server(port, SOCK_STREAM);
            return network_inaddr_any_server(port, SOCK_STREAM, error);
        } else {
            return socket_loopback_server(port, SOCK_STREAM);
            return network_loopback_server(port, SOCK_STREAM, error);
        }
    }
#if !defined(_WIN32)  // No Unix-domain sockets on Windows.
    // It's nonsensical to support the "reserved" space on the adb host side
    if (!strncmp(name, "local:", 6)) {
        return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
        return network_local_server(name + 6,
                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
    } else if (!strncmp(name, "localabstract:", 14)) {
        return socket_local_server(name + 14, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
        return network_local_server(name + 14,
                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
    } else if (!strncmp(name, "localfilesystem:", 16)) {
        return socket_local_server(name + 16, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
        return network_local_server(name + 16,
                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM, error);
    }

#endif
    printf("unknown local portname '%s'\n", name);
    *error = android::base::StringPrintf("unknown local portname '%s'", name);
    return -1;
}

@@ -178,7 +181,8 @@ void remove_all_listeners(void)
InstallStatus install_listener(const std::string& local_name,
                                  const char *connect_to,
                                  atransport* transport,
                                  int no_rebind)
                                  int no_rebind,
                                  std::string* error)
{
    for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
        if (local_name == l->local_name) {
@@ -226,9 +230,9 @@ InstallStatus install_listener(const std::string& local_name,
        goto nomem;
    }

    listener->fd = local_name_to_fd(listener->local_name);
    listener->fd = local_name_to_fd(listener->local_name, error);
    if (listener->fd < 0) {
        printf("cannot bind '%s': %s\n", listener->local_name, strerror(errno));
        printf("cannot bind '%s': %s\n", listener->local_name, error->c_str());
        free(listener->local_name);
        free(listener->connect_to);
        free(listener);
+2 −1
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ enum InstallStatus {
InstallStatus install_listener(const std::string& local_name,
                               const char* connect_to,
                               atransport* transport,
                               int no_rebind);
                               int no_rebind,
                               std::string* error);

std::string format_listeners();

+0 −22
Original line number Diff line number Diff line
@@ -28,17 +28,10 @@
#include <base/logging.h>
#include <base/stringprintf.h>
#include <base/strings.h>
#include <cutils/sockets.h>

#include "adb_trace.h"
#include "sysdeps.h"

#if defined(_WIN32)
#include <ws2tcpip.h>
#else
#include <netdb.h>
#endif

bool getcwd(std::string* s) {
  char* cwd = getcwd(nullptr, 0);
  if (cwd != nullptr) *s = cwd;
@@ -178,18 +171,3 @@ bool parse_host_and_port(const std::string& address,
               << " (" << *canonical_address << ")";
    return true;
}

int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
    int getaddrinfo_error = 0;
    int fd = socket_network_client_timeout(host.c_str(), port, type, timeout, &getaddrinfo_error);
    if (fd != -1) {
        return fd;
    }
    if (getaddrinfo_error != 0) {
        // TODO: gai_strerror is not thread safe on Win32.
        *error = gai_strerror(getaddrinfo_error);
    } else {
        *error = strerror(errno);
    }
    return -1;
}
Loading