Merge changes from topic 'adb_cmd_socket'
* changes:
adb: allow use of arbitrary socket specs for command socket.
adb: extract the adb-specific unique_fd out into its own header.
adb: add helper to get the ~/.android directory.
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 3308950..056dbef 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -611,8 +611,7 @@
#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 @@
}
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 @@
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 {
diff --git a/adb/adb.h b/adb/adb.h
index 4a2da91..0b9fe5b 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -126,8 +126,8 @@
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_auth_host.cpp b/adb/adb_auth_host.cpp
index 4f4f382..8366549 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -246,21 +246,7 @@
}
static std::string get_user_key_path() {
- const std::string home = adb_get_homedir_path(true);
- LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
-
- const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
- OS_PATH_SEPARATOR);
-
- struct stat buf;
- if (stat(android_dir.c_str(), &buf) == -1) {
- if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
- PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
- return "";
- }
- }
-
- return android_dir + OS_PATH_SEPARATOR + "adbkey";
+ return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
}
static bool get_user_key() {
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index a27dd47..0b2fc1e 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_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 @@
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 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 9f9eb1f..d35d705 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -43,11 +43,9 @@
// 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/adb_unique_fd.h b/adb/adb_unique_fd.h
new file mode 100644
index 0000000..34c1bbc
--- /dev/null
+++ b/adb/adb_unique_fd.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+
+// Helper to automatically close an FD when it goes out of scope.
+struct AdbCloser {
+ static void Close(int fd);
+};
+
+using unique_fd = android::base::unique_fd_impl<AdbCloser>;
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 31ec8af..db39ef4 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -17,6 +17,7 @@
#define TRACE_TAG ADB
#include "adb_utils.h"
+#include "adb_unique_fd.h"
#include <libgen.h>
#include <stdlib.h>
@@ -25,6 +26,7 @@
#include <unistd.h>
#include <algorithm>
+#include <vector>
#include <android-base/logging.h>
#include <android-base/parseint.h>
@@ -41,6 +43,8 @@
# endif
# include "windows.h"
# include "shlobj.h"
+#else
+#include <pwd.h>
#endif
ADB_MUTEX_DEFINE(basename_lock);
@@ -263,14 +267,8 @@
return true;
}
-std::string adb_get_homedir_path(bool check_env_first) {
+std::string adb_get_homedir_path() {
#ifdef _WIN32
- if (check_env_first) {
- if (const char* const home = getenv("ANDROID_SDK_HOME")) {
- return home;
- }
- }
-
WCHAR path[MAX_PATH];
const HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path);
if (FAILED(hr)) {
@@ -286,6 +284,33 @@
if (const char* const home = getenv("HOME")) {
return home;
}
+
+ struct passwd pwent;
+ struct passwd* result;
+ int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ std::vector<char> buf(pwent_max);
+ int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
+ if (rc == 0 && result) {
+ return result->pw_dir;
+ }
+
+ LOG(FATAL) << "failed to get user home directory";
return {};
#endif
}
+
+std::string adb_get_android_dir_path() {
+ std::string user_dir = adb_get_homedir_path();
+ std::string android_dir = user_dir + OS_PATH_SEPARATOR + ".android";
+ struct stat buf;
+ if (stat(android_dir.c_str(), &buf) == -1) {
+ if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
+ PLOG(FATAL) << "Cannot mkdir '" << android_dir << "'";
+ }
+ }
+ return android_dir;
+}
+
+void AdbCloser::Close(int fd) {
+ adb_close(fd);
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index f6b4b26..16317e0 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -20,7 +20,6 @@
#include <string>
#include <android-base/macros.h>
-#include <android-base/unique_fd.h>
void close_stdin();
@@ -33,10 +32,10 @@
std::string adb_dirname(const std::string& path);
// Return the user's home directory.
-// |check_env_first| - if true, on Windows check the ANDROID_SDK_HOME
-// environment variable before trying the WinAPI call (useful when looking for
-// the .android directory)
-std::string adb_get_homedir_path(bool check_env_first);
+std::string adb_get_homedir_path();
+
+// Return the adb user directory.
+std::string adb_get_android_dir_path();
bool mkdirs(const std::string& path);
@@ -57,13 +56,4 @@
bool forward_targets_are_valid(const std::string& source, const std::string& dest,
std::string* error);
-// Helper to automatically close an FD when it goes out of scope.
-struct AdbCloser {
- static void Close(int fd) {
- adb_close(fd);
- }
-};
-
-using unique_fd = android::base::unique_fd_impl<AdbCloser>;
-
#endif
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 0c85fe5..571c227 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -88,7 +88,7 @@
}
#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 @@
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 c69fe19..77c5f96 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -51,6 +51,7 @@
#include "adb_auth.h"
#include "adb_client.h"
#include "adb_io.h"
+#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "bugreport.h"
#include "commandline.h"
@@ -100,6 +101,8 @@
" 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"
@@ -1453,18 +1456,9 @@
}
// 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;
@@ -1518,17 +1512,14 @@
} 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();
@@ -1538,34 +1529,58 @@
} 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) {
@@ -1573,9 +1588,9 @@
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/console.cpp b/adb/console.cpp
index e9b90a5..9563eac 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -32,7 +32,7 @@
static std::string adb_construct_auth_command() {
static const char auth_token_filename[] = ".emulator_console_auth_token";
- std::string auth_token_path = adb_get_homedir_path(false);
+ std::string auth_token_path = adb_get_homedir_path();
auth_token_path += OS_PATH_SEPARATOR;
auth_token_path += auth_token_filename;
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index 027821a..3135aa4 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -34,6 +34,7 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_unique_fd.h"
#include "adb_utils.h"
/* here's how these things work.
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index d83622c..01e206a 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -100,6 +100,7 @@
#include "adb.h"
#include "adb_io.h"
#include "adb_trace.h"
+#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "security_log_tags.h"
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index f8bbbb3..18e6e6d 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -131,6 +131,22 @@
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 69efb07..6302da5 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,