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.
This commit is contained in:
Treehugger Robot 2016-09-02 01:03:12 +00:00 committed by Gerrit Code Review
commit 1f5a49f77a
15 changed files with 159 additions and 119 deletions

View file

@ -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 {

View file

@ -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

View file

@ -246,21 +246,7 @@ static bool read_keys(const std::string& path, bool allow_dir = true) {
}
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() {

View file

@ -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()

View file

@ -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>

26
adb/adb_unique_fd.h Normal file
View file

@ -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>;

View file

@ -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 @@ bool forward_targets_are_valid(const std::string& source, const std::string& des
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 @@ std::string adb_get_homedir_path(bool check_env_first) {
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);
}

View file

@ -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_basename(const std::string& path);
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 @@ extern int adb_close(int fd);
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

View file

@ -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());
}

View file

@ -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 @@ 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"
@ -1453,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;
@ -1518,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();
@ -1538,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) {
@ -1573,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");

View file

@ -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;

View file

@ -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.

View file

@ -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"

View file

@ -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;

View file

@ -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,