diff options
author | Josh Gao <jmgao@google.com> | 2016-08-25 16:00:22 -0700 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2016-09-01 15:49:06 -0700 |
commit | 9c869b58a8cf4f7c3bc88931fbd27d3f5187b2db (patch) | |
tree | 4016ec3aa65e79122025d8bdf4f3185c2b6aaf1a | |
parent | 924d35a8d5f82e2d2f7e4dcedaa60791306b5fb5 (diff) | |
download | core-9c869b58a8cf4f7c3bc88931fbd27d3f5187b2db.tar.gz core-9c869b58a8cf4f7c3bc88931fbd27d3f5187b2db.tar.bz2 core-9c869b58a8cf4f7c3bc88931fbd27d3f5187b2db.zip |
adb: allow use of arbitrary socket specs for command socket.
Bug: http://b/30445394
Change-Id: I474ede35ec3c56ad86da503c9703f83ef5e80862
-rw-r--r-- | adb/adb.cpp | 13 | ||||
-rw-r--r-- | adb/adb.h | 4 | ||||
-rw-r--r-- | adb/adb_client.cpp | 45 | ||||
-rw-r--r-- | adb/adb_client.h | 8 | ||||
-rw-r--r-- | adb/client/main.cpp | 5 | ||||
-rw-r--r-- | adb/commandline.cpp | 82 | ||||
-rw-r--r-- | adb/socket_spec.cpp | 16 | ||||
-rw-r--r-- | adb/socket_spec.h | 1 |
8 files changed, 92 insertions, 82 deletions
diff --git a/adb/adb.cpp b/adb/adb.cpp index 3308950e2..056dbef4d 100644 --- a/adb/adb.cpp +++ b/adb/adb.cpp @@ -611,8 +611,7 @@ static unsigned __stdcall _redirect_stderr_thread(HANDLE h) { #endif -int launch_server(int server_port) -{ +int launch_server(const std::string& socket_spec) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ @@ -715,9 +714,8 @@ int launch_server(int server_port) } WCHAR args[64]; - snwprintf(args, arraysize(args), - L"adb -P %d fork-server server --reply-fd %d", server_port, - ack_write_as_int); + snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d", + socket_spec.c_str(), ack_write_as_int); PROCESS_INFORMATION pinfo; ZeroMemory(&pinfo, sizeof(pinfo)); @@ -862,12 +860,11 @@ int launch_server(int server_port) adb_close(fd[0]); - char str_port[30]; - snprintf(str_port, sizeof(str_port), "%d", server_port); char reply_fd[30]; snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]); // child process - int result = execl(path.c_str(), "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL); + int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server", + "--reply-fd", reply_fd, NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { @@ -126,8 +126,8 @@ void fatal_errno(const char* fmt, ...) __attribute__((noreturn, format(__printf_ void handle_packet(apacket *p, atransport *t); -int launch_server(int server_port); -int adb_server_main(int is_daemon, int server_port, int ack_reply_fd); +int launch_server(const std::string& socket_spec); +int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd); /* initialize a transport object's func pointers and state */ #if ADB_HOST diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp index a27dd4750..0b2fc1e6f 100644 --- a/adb/adb_client.cpp +++ b/adb/adb_client.cpp @@ -37,12 +37,12 @@ #include "adb_io.h" #include "adb_utils.h" +#include "socket_spec.h" static TransportType __adb_transport = kTransportAny; static const char* __adb_serial = NULL; -static int __adb_server_port = DEFAULT_ADB_PORT; -static const char* __adb_server_name = NULL; +static const char* __adb_server_socket_spec; void adb_set_transport(TransportType type, const char* serial) { @@ -59,14 +59,11 @@ void adb_get_transport(TransportType* type, const char** serial) { } } -void adb_set_tcp_specifics(int server_port) -{ - __adb_server_port = server_port; -} - -void adb_set_tcp_name(const char* hostname) -{ - __adb_server_name = hostname; +void adb_set_socket_spec(const char* socket_spec) { + if (!__adb_server_socket_spec) { + LOG(FATAL) << "attempted to reinitialize adb_server_socket_spec"; + } + __adb_server_socket_spec = socket_spec; } static int switch_socket_transport(int fd, std::string* error) { @@ -139,23 +136,12 @@ int _adb_connect(const std::string& service, std::string* error) { return -1; } - int fd; 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", - __adb_server_name, __adb_server_port, - reason.c_str()); - return -2; - } - } else { - fd = network_loopback_client(__adb_server_port, SOCK_STREAM, &reason); - if (fd == -1) { - *error = android::base::StringPrintf("cannot connect to daemon: %s", - reason.c_str()); - return -2; - } + int fd = socket_spec_connect(__adb_server_socket_spec, &reason); + if (fd < 0) { + *error = android::base::StringPrintf("cannot connect to daemon at %s: %s", + __adb_server_socket_spec, reason.c_str()); + return -2; } if ((memcmp(&service[0],"host",4) != 0 || service == "host:reconnect") && @@ -185,15 +171,14 @@ int adb_connect(const std::string& service, std::string* error) { int fd = _adb_connect("host:version", error); D("adb_connect: service %s", service.c_str()); - if (fd == -2 && __adb_server_name) { + if (fd == -2 && !is_local_socket_spec(__adb_server_socket_spec)) { fprintf(stderr,"** Cannot start server on remote host\n"); // error is the original network connection error return fd; } else if (fd == -2) { - fprintf(stdout,"* daemon not running. starting it now on port %d *\n", - __adb_server_port); + fprintf(stdout, "* daemon not running. starting it now at %s *\n", __adb_server_socket_spec); start_server: - if (launch_server(__adb_server_port)) { + if (launch_server(__adb_server_socket_spec)) { fprintf(stderr,"* failed to start daemon *\n"); // launch_server() has already printed detailed error info, so just // return a generic error string about the overall adb_connect() diff --git a/adb/adb_client.h b/adb/adb_client.h index 9f9eb1f5e..d35d70585 100644 --- a/adb/adb_client.h +++ b/adb/adb_client.h @@ -43,11 +43,9 @@ void adb_set_transport(TransportType type, const char* _Nullable serial); // Get the preferred transport to connect to. void adb_get_transport(TransportType* _Nullable type, const char* _Nullable* _Nullable serial); -// Set TCP specifics of the transport to use. -void adb_set_tcp_specifics(int server_port); - -// Set TCP Hostname of the transport to use. -void adb_set_tcp_name(const char* _Nullable hostname); +// Set the socket specification for the adb server. +// This function can only be called once, and the argument must live to the end of the process. +void adb_set_socket_spec(const char* _Nonnull socket_spec); // Send commands to the current emulator instance. Will fail if there is not // exactly one emulator connected (or if you use -s <serial> with a <serial> diff --git a/adb/client/main.cpp b/adb/client/main.cpp index 0c85fe59a..571c227a6 100644 --- a/adb/client/main.cpp +++ b/adb/client/main.cpp @@ -88,7 +88,7 @@ static BOOL WINAPI ctrlc_handler(DWORD type) { } #endif -int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) { +int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) { #if defined(_WIN32) // adb start-server starts us up with stdout and stderr hooked up to // anonymous pipes. When the C Runtime sees this, it makes stderr and @@ -113,8 +113,7 @@ int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) { local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); std::string error; - std::string local_name = android::base::StringPrintf("tcp:%d", server_port); - if (install_listener(local_name, "*smartsocket*", nullptr, 0, nullptr, &error)) { + if (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error)) { fatal("could not install *smartsocket* listener: %s", error.c_str()); } diff --git a/adb/commandline.cpp b/adb/commandline.cpp index 20d40fd72..77c5f96b5 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -101,6 +101,8 @@ static void help() { " be an absolute path.\n" " -H - Name of adb server host (default: localhost)\n" " -P - Port of adb server (default: 5037)\n" + " -L <socket> - listen on socket specifier for the adb server\n" + " (default: tcp:localhost:5037)\n" " devices [-l] - list all connected devices\n" " ('-l' will also list device qualifiers)\n" " connect <host>[:<port>] - connect to a device via TCP/IP\n" @@ -1454,18 +1456,9 @@ int adb_commandline(int argc, const char **argv) { } // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint - /* Validate and assign the server port */ - const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT"); - int server_port = DEFAULT_ADB_PORT; - if (server_port_str && strlen(server_port_str) > 0) { - server_port = strtol(server_port_str, nullptr, 0); - if (server_port <= 0 || server_port > 65535) { - fprintf(stderr, - "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65536. Got \"%s\"\n", - server_port_str); - return usage(); - } - } + const char* server_host_str = nullptr; + const char* server_port_str = nullptr; + const char* server_socket_str = nullptr; // We need to check for -d and -e before we look at $ANDROID_SERIAL. const char* serial = nullptr; @@ -1519,17 +1512,14 @@ int adb_commandline(int argc, const char **argv) { } else if (!strcmp(argv[0],"-a")) { gListenAll = 1; } else if (!strncmp(argv[0], "-H", 2)) { - const char *hostname = NULL; if (argv[0][2] == '\0') { if (argc < 2) return usage(); - hostname = argv[1]; + server_host_str = argv[1]; argc--; argv++; } else { - hostname = argv[0] + 2; + server_host_str = argv[0] + 2; } - adb_set_tcp_name(hostname); - } else if (!strncmp(argv[0], "-P", 2)) { if (argv[0][2] == '\0') { if (argc < 2) return usage(); @@ -1539,34 +1529,58 @@ int adb_commandline(int argc, const char **argv) { } else { server_port_str = argv[0] + 2; } - if (strlen(server_port_str) > 0) { - server_port = (int) strtol(server_port_str, NULL, 0); - if (server_port <= 0 || server_port > 65535) { - fprintf(stderr, - "adb: port number must be a positive number less than 65536. Got \"%s\"\n", - server_port_str); - return usage(); - } - } else { - fprintf(stderr, - "adb: port number must be a positive number less than 65536. Got empty string.\n"); - return usage(); - } + } else if (!strcmp(argv[0], "-L")) { + if (argc < 2) return usage(); + server_socket_str = argv[1]; + argc--; + argv++; } else { - /* out of recognized modifiers and flags */ + /* out of recognized modifiers and flags */ break; } argc--; argv++; } + if ((server_host_str || server_port_str) && server_socket_str) { + fprintf(stderr, "adb: -L is incompatible with -H or -P\n"); + exit(1); + } + + // If -L, -H, or -P are specified, ignore environment variables. + // Otherwise, prefer ADB_SERVER_SOCKET over ANDROID_ADB_SERVER_ADDRESS/PORT. + if (!(server_host_str || server_port_str || server_socket_str)) { + server_socket_str = server_socket_str ? server_socket_str : getenv("ADB_SERVER_SOCKET"); + } + + if (!server_socket_str) { + // tcp:1234 and tcp:localhost:1234 are different with -a, so don't default to localhost + server_host_str = server_host_str ? server_host_str : getenv("ANDROID_ADB_SERVER_ADDRESS"); + + long server_port = DEFAULT_ADB_PORT; + server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT"); + + int rc; + char* temp; + if (server_host_str) { + rc = asprintf(&temp, "tcp:%s:%ld", server_host_str, server_port); + } else { + rc = asprintf(&temp, "tcp:%ld", server_port); + } + if (rc < 0) { + fatal("failed to allocate server socket specification"); + } + server_socket_str = temp; + } + + adb_set_socket_spec(server_socket_str); + // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL. if (transport_type == kTransportAny && serial == nullptr) { serial = getenv("ANDROID_SERIAL"); } adb_set_transport(transport_type, serial); - adb_set_tcp_specifics(server_port); if (is_server) { if (no_daemon || is_daemon) { @@ -1574,9 +1588,9 @@ int adb_commandline(int argc, const char **argv) { fprintf(stderr, "reply fd for adb server to client communication not specified.\n"); return usage(); } - r = adb_server_main(is_daemon, server_port, ack_reply_fd); + r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd); } else { - r = launch_server(server_port); + r = launch_server(server_socket_str); } if (r) { fprintf(stderr,"* could not start server *\n"); diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp index f8bbbb325..18e6e6d88 100644 --- a/adb/socket_spec.cpp +++ b/adb/socket_spec.cpp @@ -131,6 +131,22 @@ bool is_socket_spec(const std::string& spec) { return StartsWith(spec, "tcp:"); } +bool is_local_socket_spec(const std::string& spec) { + for (const auto& it : kLocalSocketTypes) { + std::string prefix = it.first + ":"; + if (StartsWith(spec, prefix.c_str())) { + return true; + } + } + + std::string error; + std::string hostname; + if (!parse_tcp_spec(spec, &hostname, nullptr, &error)) { + return false; + } + return tcp_host_is_local(hostname); +} + int socket_spec_connect(const std::string& spec, std::string* error) { if (StartsWith(spec, "tcp:")) { std::string hostname; diff --git a/adb/socket_spec.h b/adb/socket_spec.h index 69efb07c2..6302da5a2 100644 --- a/adb/socket_spec.h +++ b/adb/socket_spec.h @@ -20,6 +20,7 @@ // Returns true if the argument starts with a plausible socket prefix. bool is_socket_spec(const std::string& spec); +bool is_local_socket_spec(const std::string& spec); int socket_spec_connect(const std::string& spec, std::string* error); int socket_spec_listen(const std::string& spec, std::string* error, |