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

Commit 3bcdaa28 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Recognize IPv6 addresses for "adb connect"."

parents 5208d551 3d5f60db
Loading
Loading
Loading
Loading
+19 −18
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include "adb_auth.h"
#include "adb_io.h"
#include "adb_listeners.h"
#include "adb_utils.h"
#include "transport.h"

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -896,28 +897,28 @@ int handle_host_request(const char* service, TransportType type,

    // remove TCP transport
    if (!strncmp(service, "disconnect:", 11)) {
        char buffer[4096];
        memset(buffer, 0, sizeof(buffer));
        const char* serial = service + 11;
        if (serial[0] == 0) {
        const std::string address(service + 11);
        if (address.empty()) {
            // disconnect from all TCP devices
            unregister_all_tcp_transports();
        } else {
            char hostbuf[100];
            // assume port 5555 if no port is specified
            if (!strchr(serial, ':')) {
                snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
                serial = hostbuf;
            }
            atransport* t = find_transport(serial);
            if (t) {
                unregister_transport(t);
            } else {
                snprintf(buffer, sizeof(buffer), "No such device %s", serial);
            }
            return SendOkay(reply_fd, "disconnected everything");
        }

        return SendOkay(reply_fd, buffer);
        std::string serial;
        std::string host;
        int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
        std::string error;
        if (!parse_host_and_port(address, &serial, &host, &port, &error)) {
            return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
                                                                  address.c_str(), error.c_str()));
        }
        atransport* t = find_transport(serial.c_str());
        if (t == nullptr) {
            return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'",
                                                                  serial.c_str()));
        }
        unregister_transport(t);
        return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str()));
    }

    // returns our value for ADB_SERVER_VERSION
+1 −2
Original line number Diff line number Diff line
@@ -277,8 +277,7 @@ bool adb_query(const std::string& service, std::string* result, std::string* err
    D("adb_query: %s\n", service.c_str());
    int fd = adb_connect(service, error);
    if (fd < 0) {
        fprintf(stderr,"error: %s\n", error->c_str());
        return 0;
        return false;
    }

    result->clear();
+55 −0
Original line number Diff line number Diff line
@@ -25,7 +25,9 @@

#include <algorithm>

#include <base/logging.h>
#include <base/stringprintf.h>
#include <base/strings.h>

#include "adb_trace.h"
#include "sysdeps.h"
@@ -103,3 +105,56 @@ void dump_hex(const void* data, size_t byte_count) {

    DR("%s\n", line.c_str());
}

bool parse_host_and_port(const std::string& address,
                         std::string* canonical_address,
                         std::string* host, int* port,
                         std::string* error) {
    host->clear();

    bool ipv6 = true;
    bool saw_port = false;
    size_t colons = std::count(address.begin(), address.end(), ':');
    size_t dots = std::count(address.begin(), address.end(), '.');
    std::string port_str;
    if (address[0] == '[') {
      // [::1]:123
      if (address.rfind("]:") == std::string::npos) {
        *error = android::base::StringPrintf("bad IPv6 address '%s'", address.c_str());
        return false;
      }
      *host = address.substr(1, (address.find("]:") - 1));
      port_str = address.substr(address.rfind("]:") + 2);
      saw_port = true;
    } else if (dots == 0 && colons >= 2 && colons <= 7) {
      // ::1
      *host = address;
    } else if (colons <= 1) {
      // 1.2.3.4 or some.accidental.domain.com
      ipv6 = false;
      std::vector<std::string> pieces = android::base::Split(address, ":");
      *host = pieces[0];
      if (pieces.size() > 1) {
        port_str = pieces[1];
        saw_port = true;
      }
    }

    if (host->empty()) {
      *error = android::base::StringPrintf("no host in '%s'", address.c_str());
      return false;
    }

    if (saw_port) {
      if (sscanf(port_str.c_str(), "%d", port) != 1 || *port <= 0 || *port > 65535) {
        *error = android::base::StringPrintf("bad port number '%s' in '%s'",
                                             port_str.c_str(), address.c_str());
        return false;
      }
    }

    *canonical_address = android::base::StringPrintf(ipv6 ? "[%s]:%d" : "%s:%d", host->c_str(), *port);
    LOG(DEBUG) << "parsed " << address << " as " << *host << " and " << *port
               << " (" << *canonical_address << ")";
    return true;
}
+11 −0
Original line number Diff line number Diff line
@@ -28,4 +28,15 @@ std::string escape_arg(const std::string& s);

void dump_hex(const void* ptr, size_t byte_count);

// Parses 'address' into 'host' and 'port'.
// If no port is given, takes the default from *port.
// 'canonical_address' then becomes "host:port" or "[host]:port" as appropriate.
// Note that no real checking is done that 'host' or 'port' is valid; that's
// left to getaddrinfo(3).
// Returns false on failure and sets *error to an appropriate message.
bool parse_host_and_port(const std::string& address,
                         std::string* canonical_address,
                         std::string* host, int* port,
                         std::string* error);

#endif
+82 −0
Original line number Diff line number Diff line
@@ -50,3 +50,85 @@ TEST(adb_utils, escape_arg) {
  ASSERT_EQ(R"('abc(')", escape_arg("abc("));
  ASSERT_EQ(R"('abc)')", escape_arg("abc)"));
}

TEST(adb_utils, parse_host_and_port) {
  std::string canonical_address;
  std::string host;
  int port;
  std::string error;

  // Name, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("www.google.com", &canonical_address, &host, &port, &error));
  ASSERT_EQ("www.google.com:123", canonical_address);
  ASSERT_EQ("www.google.com", host);
  ASSERT_EQ(123, port);

  // Name, explicit port.
  ASSERT_TRUE(parse_host_and_port("www.google.com:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("www.google.com:666", canonical_address);
  ASSERT_EQ("www.google.com", host);
  ASSERT_EQ(666, port);

  // IPv4, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("1.2.3.4", &canonical_address, &host, &port, &error));
  ASSERT_EQ("1.2.3.4:123", canonical_address);
  ASSERT_EQ("1.2.3.4", host);
  ASSERT_EQ(123, port);

  // IPv4, explicit port.
  ASSERT_TRUE(parse_host_and_port("1.2.3.4:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("1.2.3.4:666", canonical_address);
  ASSERT_EQ("1.2.3.4", host);
  ASSERT_EQ(666, port);

  // Simple IPv6, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("::1", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[::1]:123", canonical_address);
  ASSERT_EQ("::1", host);
  ASSERT_EQ(123, port);

  // Simple IPv6, explicit port.
  ASSERT_TRUE(parse_host_and_port("[::1]:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[::1]:666", canonical_address);
  ASSERT_EQ("::1", host);
  ASSERT_EQ(666, port);

  // Hairy IPv6, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("fe80::200:5aee:feaa:20a2", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[fe80::200:5aee:feaa:20a2]:123", canonical_address);
  ASSERT_EQ("fe80::200:5aee:feaa:20a2", host);
  ASSERT_EQ(123, port);

  // Simple IPv6, explicit port.
  ASSERT_TRUE(parse_host_and_port("[fe80::200:5aee:feaa:20a2]:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[fe80::200:5aee:feaa:20a2]:666", canonical_address);
  ASSERT_EQ("fe80::200:5aee:feaa:20a2", host);
  ASSERT_EQ(666, port);

  // Invalid IPv4.
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4::", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:hello", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port(":123", &canonical_address, &host, &port, &error));

  // Invalid IPv6.
  EXPECT_FALSE(parse_host_and_port(":1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("::::::::1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]::", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:hello", &canonical_address, &host, &port, &error));

  // Invalid ports.
  EXPECT_FALSE(parse_host_and_port("[::1]:-1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:0", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:65536", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:-1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:0", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:65536", &canonical_address, &host, &port, &error));
}
Loading