More adb buffer fixes.
This patch factors out a lot of the basic protocol code: sending OKAY, sending FAIL, and sending a length-prefixed string. ADB_TRACE has been non-optional for a long time, so let's just remove the #ifs. Also actually build the device tracker test tool (and remove its duplicate). Bug: http://b/20666660 Change-Id: I6c7d59f18707bdc62ca69dea45547617f9f31fc6
This commit is contained in:
parent
bacac0f7db
commit
e67f1f87d9
22 changed files with 310 additions and 603 deletions
|
@ -124,6 +124,21 @@ endif
|
|||
|
||||
include $(BUILD_HOST_NATIVE_TEST)
|
||||
|
||||
# adb device tracker (used by ddms) test tool
|
||||
# =========================================================
|
||||
|
||||
ifeq ($(HOST_OS),linux)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CLANG := $(adb_host_clang)
|
||||
LOCAL_MODULE := adb_device_tracker_test
|
||||
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
|
||||
LOCAL_SRC_FILES := test_track_devices.cpp
|
||||
LOCAL_SHARED_LIBRARIES := liblog libbase
|
||||
LOCAL_STATIC_LIBRARIES := libadb libcrypto_static libcutils
|
||||
LOCAL_LDLIBS += -lrt -ldl -lpthread
|
||||
include $(BUILD_HOST_EXECUTABLE)
|
||||
endif
|
||||
|
||||
# adb host tool
|
||||
# =========================================================
|
||||
include $(CLEAR_VARS)
|
||||
|
|
123
adb/adb.cpp
123
adb/adb.cpp
|
@ -48,9 +48,7 @@
|
|||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#if ADB_TRACE
|
||||
ADB_MUTEX_DEFINE( D_lock );
|
||||
#endif
|
||||
|
||||
int HOST = 0;
|
||||
|
||||
|
@ -322,28 +320,6 @@ static size_t fill_connect_data(char *buf, size_t bufsize)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if !ADB_HOST
|
||||
static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
|
||||
char header[5];
|
||||
if (msglen > 0xffff)
|
||||
msglen = 0xffff;
|
||||
snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
|
||||
WriteFdExactly(fd, header, 4);
|
||||
WriteFdExactly(fd, msg, msglen);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ADB_HOST
|
||||
static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
|
||||
char header[9];
|
||||
if (msglen > 0xffff)
|
||||
msglen = 0xffff;
|
||||
snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
|
||||
WriteFdExactly(fd, header, 8);
|
||||
WriteFdExactly(fd, msg, msglen);
|
||||
}
|
||||
#endif // ADB_HOST
|
||||
|
||||
void send_connect(atransport *t)
|
||||
{
|
||||
D("Calling send_connect \n");
|
||||
|
@ -356,32 +332,6 @@ void send_connect(atransport *t)
|
|||
send_packet(cp, t);
|
||||
}
|
||||
|
||||
#if ADB_HOST
|
||||
static const char* connection_state_name(atransport *t)
|
||||
{
|
||||
if (t == NULL) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
switch(t->connection_state) {
|
||||
case CS_BOOTLOADER:
|
||||
return "bootloader";
|
||||
case CS_DEVICE:
|
||||
return "device";
|
||||
case CS_RECOVERY:
|
||||
return "recovery";
|
||||
case CS_SIDELOAD:
|
||||
return "sideload";
|
||||
case CS_OFFLINE:
|
||||
return "offline";
|
||||
case CS_UNAUTHORIZED:
|
||||
return "unauthorized";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
#endif // ADB_HOST
|
||||
|
||||
// qual_overwrite is used to overwrite a qualifier string. dst is a
|
||||
// pointer to a char pointer. It is assumed that if *dst is non-NULL, it
|
||||
// was malloc'ed and needs to freed. *dst will be set to a dup of src.
|
||||
|
@ -752,20 +702,11 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
|
|||
{
|
||||
if (!strcmp(service, "list-forward")) {
|
||||
// Create the list of forward redirections.
|
||||
int buffer_size = format_listeners(NULL, 0);
|
||||
// Add one byte for the trailing zero.
|
||||
char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
|
||||
if (buffer == nullptr) {
|
||||
sendfailmsg(reply_fd, "not enough memory");
|
||||
return 1;
|
||||
}
|
||||
(void) format_listeners(buffer, buffer_size + 1);
|
||||
std::string listeners = format_listeners();
|
||||
#if ADB_HOST
|
||||
send_msg_with_okay(reply_fd, buffer, buffer_size);
|
||||
#else
|
||||
send_msg_with_header(reply_fd, buffer, buffer_size);
|
||||
SendOkay(reply_fd);
|
||||
#endif
|
||||
free(buffer);
|
||||
SendProtocolString(reply_fd, listeners);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -773,9 +714,9 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
|
|||
remove_all_listeners();
|
||||
#if ADB_HOST
|
||||
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
|
||||
adb_write(reply_fd, "OKAY", 4);
|
||||
SendOkay(reply_fd);
|
||||
#endif
|
||||
adb_write(reply_fd, "OKAY", 4);
|
||||
SendOkay(reply_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -800,19 +741,19 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
|
|||
if (createForward) {
|
||||
// Check forward: parameter format: '<local>;<remote>'
|
||||
if(remote == 0) {
|
||||
sendfailmsg(reply_fd, "malformed forward spec");
|
||||
SendFail(reply_fd, "malformed forward spec");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*remote++ = 0;
|
||||
if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
|
||||
sendfailmsg(reply_fd, "malformed forward spec");
|
||||
SendFail(reply_fd, "malformed forward spec");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
// Check killforward: parameter format: '<local>'
|
||||
if (local[0] == 0) {
|
||||
sendfailmsg(reply_fd, "malformed forward spec");
|
||||
SendFail(reply_fd, "malformed forward spec");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -820,7 +761,7 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
|
|||
std::string error_msg;
|
||||
transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
|
||||
if (!transport) {
|
||||
sendfailmsg(reply_fd, error_msg.c_str());
|
||||
SendFail(reply_fd, error_msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -833,9 +774,9 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
|
|||
if (r == INSTALL_STATUS_OK) {
|
||||
#if ADB_HOST
|
||||
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
|
||||
WriteFdExactly(reply_fd, "OKAY", 4);
|
||||
SendOkay(reply_fd);
|
||||
#endif
|
||||
WriteFdExactly(reply_fd, "OKAY", 4);
|
||||
SendOkay(reply_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -851,7 +792,7 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
|
|||
break;
|
||||
case INSTALL_STATUS_LISTENER_NOT_FOUND: message = "listener not found"; break;
|
||||
}
|
||||
sendfailmsg(reply_fd, message.c_str());
|
||||
SendFail(reply_fd, message);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -862,7 +803,7 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
|
|||
if(!strcmp(service, "kill")) {
|
||||
fprintf(stderr,"adb server killed by remote request\n");
|
||||
fflush(stdout);
|
||||
adb_write(reply_fd, "OKAY", 4);
|
||||
SendOkay(reply_fd);
|
||||
usb_cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
@ -892,25 +833,25 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
|
|||
|
||||
if (transport) {
|
||||
s->transport = transport;
|
||||
adb_write(reply_fd, "OKAY", 4);
|
||||
SendOkay(reply_fd);
|
||||
} else {
|
||||
sendfailmsg(reply_fd, error_msg.c_str());
|
||||
SendFail(reply_fd, error_msg);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// return a list of all connected devices
|
||||
if (!strncmp(service, "devices", 7)) {
|
||||
char buffer[4096];
|
||||
int use_long = !strcmp(service+7, "-l");
|
||||
if (use_long || service[7] == 0) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
D("Getting device list \n");
|
||||
list_transports(buffer, sizeof(buffer), use_long);
|
||||
D("Wrote device list \n");
|
||||
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
|
||||
bool long_listing = (strcmp(service+7, "-l") == 0);
|
||||
if (long_listing || service[7] == 0) {
|
||||
D("Getting device list...\n");
|
||||
std::string device_list = list_transports(long_listing);
|
||||
D("Sending device list...\n");
|
||||
SendOkay(reply_fd);
|
||||
SendProtocolString(reply_fd, device_list);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remove TCP transport
|
||||
|
@ -937,15 +878,15 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
|
|||
}
|
||||
}
|
||||
|
||||
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
|
||||
SendOkay(reply_fd);
|
||||
SendProtocolString(reply_fd, buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns our value for ADB_SERVER_VERSION
|
||||
if (!strcmp(service, "version")) {
|
||||
char version[12];
|
||||
snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
|
||||
send_msg_with_okay(reply_fd, version, strlen(version));
|
||||
SendOkay(reply_fd);
|
||||
SendProtocolString(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -955,7 +896,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
|
|||
if (transport && transport->serial) {
|
||||
out = transport->serial;
|
||||
}
|
||||
send_msg_with_okay(reply_fd, out, strlen(out));
|
||||
SendOkay(reply_fd);
|
||||
SendProtocolString(reply_fd, out);
|
||||
return 0;
|
||||
}
|
||||
if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
|
||||
|
@ -964,7 +906,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
|
|||
if (transport && transport->devpath) {
|
||||
out = transport->devpath;
|
||||
}
|
||||
send_msg_with_okay(reply_fd, out, strlen(out));
|
||||
SendOkay(reply_fd);
|
||||
SendProtocolString(reply_fd, out);
|
||||
return 0;
|
||||
}
|
||||
// indicates a new emulator instance has started
|
||||
|
@ -977,8 +920,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
|
|||
|
||||
if(!strncmp(service,"get-state",strlen("get-state"))) {
|
||||
transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
|
||||
const char *state = connection_state_name(transport);
|
||||
send_msg_with_okay(reply_fd, state, strlen(state));
|
||||
SendOkay(reply_fd);
|
||||
SendProtocolString(reply_fd, transport->connection_state_name());
|
||||
return 0;
|
||||
}
|
||||
#endif // ADB_HOST
|
||||
|
|
|
@ -209,6 +209,8 @@ struct atransport
|
|||
unsigned char token[TOKEN_SIZE];
|
||||
fdevent auth_fde;
|
||||
unsigned failed_auth_attempts;
|
||||
|
||||
const char* connection_state_name() const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -369,7 +371,6 @@ enum subproc_mode {
|
|||
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
|
||||
#endif
|
||||
|
||||
int sendfailmsg(int fd, const char *reason);
|
||||
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
|
||||
|
||||
void handle_online(atransport *t);
|
||||
|
|
|
@ -56,7 +56,7 @@ static bool ReadProtocolString(int fd, std::string* s, std::string* error) {
|
|||
buf[4] = 0;
|
||||
|
||||
unsigned long len = strtoul(buf, 0, 16);
|
||||
s->resize(len + 1, '\0'); // Ensure NUL-termination.
|
||||
s->resize(len, '\0');
|
||||
if (!ReadFdExactly(fd, &(*s)[0], len)) {
|
||||
*error = perror_str("protocol fault (couldn't read status message)");
|
||||
return false;
|
||||
|
@ -136,9 +136,7 @@ static int switch_socket_transport(int fd, std::string* error) {
|
|||
service += transport_type;
|
||||
}
|
||||
|
||||
char tmp[5];
|
||||
snprintf(tmp, sizeof(tmp), "%04zx", service.size());
|
||||
if (!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service.c_str(), service.size())) {
|
||||
if (!SendProtocolString(fd, service)) {
|
||||
*error = perror_str("write failure during connection");
|
||||
adb_close(fd);
|
||||
return -1;
|
||||
|
@ -199,9 +197,7 @@ int _adb_connect(const std::string& service, std::string* error) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
char tmp[5];
|
||||
snprintf(tmp, sizeof(tmp), "%04zx", service.size());
|
||||
if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, &service[0], service.size())) {
|
||||
if(!SendProtocolString(fd, service)) {
|
||||
*error = perror_str("write failure during connection");
|
||||
adb_close(fd);
|
||||
return -1;
|
||||
|
|
|
@ -22,14 +22,31 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "adb_trace.h"
|
||||
#include "transport.h"
|
||||
#include "adb_utils.h"
|
||||
|
||||
bool SendProtocolString(int fd, const std::string& s) {
|
||||
int length = s.size();
|
||||
if (length > 0xffff) {
|
||||
length = 0xffff;
|
||||
}
|
||||
|
||||
char buf[5];
|
||||
snprintf(buf, sizeof(buf), "%04x", length);
|
||||
return WriteFdExactly(fd, buf, 4) && WriteFdExactly(fd, s);
|
||||
}
|
||||
|
||||
bool SendOkay(int fd) {
|
||||
return WriteFdExactly(fd, "OKAY", 4);
|
||||
}
|
||||
|
||||
bool SendFail(int fd, const std::string& reason) {
|
||||
return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason);
|
||||
}
|
||||
|
||||
bool ReadFdExactly(int fd, void* buf, size_t len) {
|
||||
char* p = reinterpret_cast<char*>(buf);
|
||||
|
||||
#if ADB_TRACE
|
||||
size_t len0 = len;
|
||||
#endif
|
||||
|
||||
D("readx: fd=%d wanted=%zu\n", fd, len);
|
||||
while (len > 0) {
|
||||
|
@ -47,12 +64,10 @@ bool ReadFdExactly(int fd, void* buf, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
#if ADB_TRACE
|
||||
D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
|
||||
if (ADB_TRACING) {
|
||||
dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -61,12 +76,10 @@ bool WriteFdExactly(int fd, const void* buf, size_t len) {
|
|||
const char* p = reinterpret_cast<const char*>(buf);
|
||||
int r;
|
||||
|
||||
#if ADB_TRACE
|
||||
D("writex: fd=%d len=%d: ", fd, (int)len);
|
||||
if (ADB_TRACING) {
|
||||
dump_hex(reinterpret_cast<const unsigned char*>(buf), len);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (len > 0) {
|
||||
r = adb_write(fd, p, len);
|
||||
|
@ -90,6 +103,14 @@ bool WriteFdExactly(int fd, const void* buf, size_t len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WriteFdExactly(int fd, const char* str) {
|
||||
return WriteFdExactly(fd, str, strlen(str));
|
||||
}
|
||||
|
||||
bool WriteFdExactly(int fd, const std::string& str) {
|
||||
return WriteFdExactly(fd, str.c_str(), str.size());
|
||||
}
|
||||
|
||||
bool WriteStringFully(int fd, const char* str) {
|
||||
return WriteFdExactly(fd, str, strlen(str));
|
||||
}
|
||||
|
|
20
adb/adb_io.h
20
adb/adb_io.h
|
@ -17,9 +17,19 @@
|
|||
#ifndef ADB_IO_H
|
||||
#define ADB_IO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
// Sends the protocol "OKAY" message.
|
||||
bool SendOkay(int fd);
|
||||
|
||||
// Sends the protocol "FAIL" message, with the given failure reason.
|
||||
bool SendFail(int fd, const std::string& reason);
|
||||
|
||||
// Writes a protocol-format string; a four hex digit length followed by the string data.
|
||||
bool SendProtocolString(int fd, const std::string& s);
|
||||
|
||||
/*
|
||||
* Reads exactly len bytes from fd into buf.
|
||||
*
|
||||
|
@ -37,9 +47,13 @@ bool ReadFdExactly(int fd, void *buf, size_t len);
|
|||
* completed. If the other end of the fd (such as in a socket, pipe, or fifo),
|
||||
* is closed, errno will be set to 0.
|
||||
*/
|
||||
bool WriteFdExactly(int fd, const void *buf, size_t len);
|
||||
bool WriteFdExactly(int fd, const void* buf, size_t len);
|
||||
|
||||
/* Same as WriteFdExactly, but with an implicit len = strlen(buf). */
|
||||
/* Same as above, but with an implicit len = strlen(buf). */
|
||||
bool WriteFdExactly(int fd, const char* s);
|
||||
bool WriteFdExactly(int fd, const std::string& s);
|
||||
|
||||
// TODO: move minadb off this and remove it.
|
||||
bool WriteStringFully(int fd, const char* str);
|
||||
|
||||
#endif /* ADB_IO_H */
|
||||
|
|
|
@ -139,13 +139,13 @@ TEST(io, WriteFdExactly_ENOSPC) {
|
|||
ASSERT_EQ(ENOSPC, errno);
|
||||
}
|
||||
|
||||
TEST(io, WriteStringFully) {
|
||||
TEST(io, WriteFdExactly_string) {
|
||||
const char str[] = "Foobar";
|
||||
TemporaryFile tf;
|
||||
ASSERT_NE(-1, tf.fd);
|
||||
|
||||
// Test writing a partial string to the file.
|
||||
ASSERT_TRUE(WriteStringFully(tf.fd, str)) << strerror(errno);
|
||||
ASSERT_TRUE(WriteFdExactly(tf.fd, str)) << strerror(errno);
|
||||
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
|
||||
|
||||
std::string s;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
@ -143,49 +145,17 @@ int local_name_to_fd(const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Write a single line describing a listener to a user-provided buffer.
|
||||
// Appends a trailing zero, even in case of truncation, but the function
|
||||
// returns the full line length.
|
||||
// If |buffer| is NULL, does not write but returns required size.
|
||||
static int format_listener(alistener* l, char* buffer, size_t buffer_len) {
|
||||
// Format is simply:
|
||||
//
|
||||
// <device-serial> " " <local-name> " " <remote-name> "\n"
|
||||
//
|
||||
int local_len = strlen(l->local_name);
|
||||
int connect_len = strlen(l->connect_to);
|
||||
int serial_len = strlen(l->transport->serial);
|
||||
|
||||
if (buffer != NULL) {
|
||||
snprintf(buffer, buffer_len, "%s %s %s\n",
|
||||
l->transport->serial, l->local_name, l->connect_to);
|
||||
}
|
||||
// NOTE: snprintf() on Windows returns -1 in case of truncation, so
|
||||
// return the computed line length instead.
|
||||
return local_len + connect_len + serial_len + 3;
|
||||
}
|
||||
|
||||
// Write the list of current listeners (network redirections) into a
|
||||
// user-provided buffer. Appends a trailing zero, even in case of
|
||||
// trunctaion, but return the full size in bytes.
|
||||
// If |buffer| is NULL, does not write but returns required size.
|
||||
int format_listeners(char* buf, size_t buflen)
|
||||
{
|
||||
alistener* l;
|
||||
int result = 0;
|
||||
for (l = listener_list.next; l != &listener_list; l = l->next) {
|
||||
// Write the list of current listeners (network redirections) into a string.
|
||||
std::string format_listeners() {
|
||||
std::string result;
|
||||
for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
|
||||
// Ignore special listeners like those for *smartsocket*
|
||||
if (l->connect_to[0] == '*')
|
||||
continue;
|
||||
int len = format_listener(l, buf, buflen);
|
||||
// Ensure there is space for the trailing zero.
|
||||
result += len;
|
||||
if (buf != NULL) {
|
||||
buf += len;
|
||||
buflen -= len;
|
||||
if (buflen <= 0)
|
||||
break;
|
||||
if (l->connect_to[0] == '*') {
|
||||
continue;
|
||||
}
|
||||
// <device-serial> " " <local-name> " " <remote-name> "\n"
|
||||
android::base::StringAppendF(&result, "%s %s %s\n",
|
||||
l->transport->serial, l->local_name, l->connect_to);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "adb.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// error/status codes for install_listener.
|
||||
enum install_status_t {
|
||||
INSTALL_STATUS_OK = 0,
|
||||
|
@ -39,7 +41,7 @@ install_status_t install_listener(const char *local_name,
|
|||
atransport* transport,
|
||||
int no_rebind);
|
||||
|
||||
int format_listeners(char* buf, size_t buflen);
|
||||
std::string format_listeners();
|
||||
|
||||
install_status_t remove_listener(const char* local_name, atransport* transport);
|
||||
void remove_all_listeners(void);
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
|
||||
#define ADB_TRACE 1
|
||||
|
||||
/* IMPORTANT: if you change the following list, don't
|
||||
* forget to update the corresponding 'tags' table in
|
||||
* the adb_trace_init() function implemented in adb.c
|
||||
|
@ -45,8 +42,6 @@ enum AdbTrace {
|
|||
TRACE_FDEVENT,
|
||||
} ;
|
||||
|
||||
#if ADB_TRACE
|
||||
|
||||
#if !ADB_HOST
|
||||
/*
|
||||
* When running inside the emulator, guest's adbd can connect to 'adb-debug'
|
||||
|
@ -97,19 +92,6 @@ void adb_trace_init(void);
|
|||
errno = save_errno; \
|
||||
} \
|
||||
} while (0)
|
||||
# define DD(...) \
|
||||
do { \
|
||||
int save_errno = errno; \
|
||||
adb_mutex_lock(&D_lock); \
|
||||
fprintf(stderr, "%16s: %5d:%5lu | ", \
|
||||
__FUNCTION__, \
|
||||
getpid(), adb_thread_id()); \
|
||||
errno = save_errno; \
|
||||
fprintf(stderr, __VA_ARGS__ ); \
|
||||
fflush(stderr); \
|
||||
adb_mutex_unlock(&D_lock); \
|
||||
errno = save_errno; \
|
||||
} while (0)
|
||||
#else
|
||||
# define D(...) \
|
||||
do { \
|
||||
|
@ -129,19 +111,6 @@ void adb_trace_init(void);
|
|||
__VA_ARGS__ ); \
|
||||
} \
|
||||
} while (0)
|
||||
# define DD(...) \
|
||||
do { \
|
||||
__android_log_print( \
|
||||
ANDROID_LOG_INFO, \
|
||||
__FUNCTION__, \
|
||||
__VA_ARGS__ ); \
|
||||
} while (0)
|
||||
#endif /* ADB_HOST */
|
||||
#else
|
||||
# define D(...) ((void)0)
|
||||
# define DR(...) ((void)0)
|
||||
# define DD(...) ((void)0)
|
||||
# define ADB_TRACING 0
|
||||
#endif /* ADB_TRACE */
|
||||
|
||||
#endif /* __ADB_TRACE_H */
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define TRACE_TAG TRACE_ADB
|
||||
|
||||
#include "adb_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -21,6 +23,11 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
|
||||
#include "adb_trace.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
bool getcwd(std::string* s) {
|
||||
|
@ -50,3 +57,25 @@ std::string escape_arg(const std::string& s) {
|
|||
result.push_back('\'');
|
||||
return result;
|
||||
}
|
||||
|
||||
void dump_hex(const void* data, size_t byte_count) {
|
||||
byte_count = std::min(byte_count, size_t(16));
|
||||
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
|
||||
|
||||
std::string line;
|
||||
for (size_t i = 0; i < byte_count; ++i) {
|
||||
android::base::StringAppendF(&line, "%02x", p[i]);
|
||||
}
|
||||
line.push_back(' ');
|
||||
|
||||
for (size_t i = 0; i < byte_count; ++i) {
|
||||
int c = p[i];
|
||||
if (c < 32 || c > 127) {
|
||||
c = '.';
|
||||
}
|
||||
line.push_back(c);
|
||||
}
|
||||
|
||||
DR("%s\n", line.c_str());
|
||||
}
|
||||
|
|
|
@ -24,4 +24,6 @@ bool directory_exists(const std::string& path);
|
|||
|
||||
std::string escape_arg(const std::string& s);
|
||||
|
||||
void dump_hex(const void* ptr, size_t byte_count);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -490,17 +490,8 @@ static int adb_download_buffer(const char *service, const char *fn, const void*
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
// TODO: should this be adb_status?
|
||||
char buf[5];
|
||||
if(!ReadFdExactly(fd, buf, 4)){
|
||||
fprintf(stderr,"* error reading response *\n");
|
||||
adb_close(fd);
|
||||
return -1;
|
||||
}
|
||||
if(memcmp(buf, "OKAY", 4)) {
|
||||
buf[4] = 0;
|
||||
fprintf(stderr,"* error response '%s' *\n", buf);
|
||||
adb_close(fd);
|
||||
if (!adb_status(fd, &error)) {
|
||||
fprintf(stderr,"* error response '%s' *\n", error.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ static bool remount_partition(int fd, const char* partition, int* ro) {
|
|||
if (remount(partition, ro)) {
|
||||
char buf[200];
|
||||
snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno));
|
||||
WriteStringFully(fd, buf);
|
||||
WriteFdExactly(fd, buf);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -102,7 +102,7 @@ void remount_service(int fd, void* cookie) {
|
|||
char prop_buf[PROPERTY_VALUE_MAX];
|
||||
|
||||
if (getuid() != 0) {
|
||||
WriteStringFully(fd, "Not running as root. Try \"adb root\" first.\n");
|
||||
WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
|
||||
adb_close(fd);
|
||||
return;
|
||||
}
|
||||
|
@ -128,12 +128,11 @@ void remount_service(int fd, void* cookie) {
|
|||
both ? " and " : "",
|
||||
vendor_verified ? "vendor" : "",
|
||||
both ? "s" : "");
|
||||
WriteStringFully(fd, buffer);
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"Use \"adb disable-verity\" to disable verity.\n"
|
||||
"If you do not, remount may succeed, however, you will still "
|
||||
"not be able to write to these volumes.\n");
|
||||
WriteStringFully(fd, buffer);
|
||||
WriteFdExactly(fd, buffer);
|
||||
WriteFdExactly(fd,
|
||||
"Use \"adb disable-verity\" to disable verity.\n"
|
||||
"If you do not, remount may succeed, however, you will still "
|
||||
"not be able to write to these volumes.\n");
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
@ -141,7 +140,7 @@ void remount_service(int fd, void* cookie) {
|
|||
success &= remount_partition(fd, "/vendor", &vendor_ro);
|
||||
success &= remount_partition(fd, "/oem", &oem_ro);
|
||||
|
||||
WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n");
|
||||
WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n");
|
||||
|
||||
adb_close(fd);
|
||||
}
|
||||
|
|
139
adb/services.cpp
139
adb/services.cpp
|
@ -31,10 +31,11 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <base/file.h>
|
||||
#include <base/stringprintf.h>
|
||||
#include <base/strings.h>
|
||||
|
||||
#if !ADB_HOST
|
||||
#include "base/file.h"
|
||||
#include "cutils/android_reboot.h"
|
||||
#include "cutils/properties.h"
|
||||
#endif
|
||||
|
@ -147,8 +148,7 @@ static bool reboot_service_impl(int fd, const char* arg) {
|
|||
// in the command file.
|
||||
if (strcmp(reboot_arg, "sideload") == 0) {
|
||||
if (getuid() != 0) {
|
||||
snprintf(buf, sizeof(buf), "'adb root' is required for 'adb reboot sideload'.\n");
|
||||
WriteStringFully(fd, buf);
|
||||
WriteFdExactly(fd, "'adb root' is required for 'adb reboot sideload'.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -175,14 +175,14 @@ static bool reboot_service_impl(int fd, const char* arg) {
|
|||
int ret = snprintf(property_val, sizeof(property_val), "reboot,%s", reboot_arg);
|
||||
if (ret >= static_cast<int>(sizeof(property_val))) {
|
||||
snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
|
||||
WriteStringFully(fd, buf);
|
||||
WriteFdExactly(fd, buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = property_set(ANDROID_RB_PROPERTY, property_val);
|
||||
if (ret < 0) {
|
||||
snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
|
||||
WriteStringFully(fd, buf);
|
||||
WriteFdExactly(fd, buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ void reverse_service(int fd, void* arg)
|
|||
const char* command = reinterpret_cast<const char*>(arg);
|
||||
|
||||
if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
|
||||
sendfailmsg(fd, "not a reverse forwarding command");
|
||||
SendFail(fd, "not a reverse forwarding command");
|
||||
}
|
||||
free(arg);
|
||||
adb_close(fd);
|
||||
|
@ -551,9 +551,9 @@ static void wait_for_state(int fd, void* cookie)
|
|||
std::string error_msg = "unknown error";
|
||||
atransport* t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &error_msg);
|
||||
if (t != 0) {
|
||||
WriteFdExactly(fd, "OKAY", 4);
|
||||
SendOkay(fd);
|
||||
} else {
|
||||
sendfailmsg(fd, error_msg.c_str());
|
||||
SendFail(fd, error_msg);
|
||||
}
|
||||
|
||||
if (sinfo->serial)
|
||||
|
@ -563,35 +563,31 @@ static void wait_for_state(int fd, void* cookie)
|
|||
D("wait_for_state is done\n");
|
||||
}
|
||||
|
||||
static void connect_device(char* host, char* buffer, int buffer_size)
|
||||
{
|
||||
int port, fd;
|
||||
char* portstr = strchr(host, ':');
|
||||
char hostbuf[100];
|
||||
char serial[100];
|
||||
int ret;
|
||||
|
||||
strncpy(hostbuf, host, sizeof(hostbuf) - 1);
|
||||
if (portstr) {
|
||||
if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
|
||||
snprintf(buffer, buffer_size, "bad host name %s", host);
|
||||
return;
|
||||
}
|
||||
// zero terminate the host at the point we found the colon
|
||||
hostbuf[portstr - host] = 0;
|
||||
if (sscanf(portstr + 1, "%d", &port) != 1) {
|
||||
snprintf(buffer, buffer_size, "bad port number %s", portstr);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
|
||||
static void connect_device(const std::string& host, std::string* response) {
|
||||
if (host.empty()) {
|
||||
*response = "empty host name";
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
|
||||
std::vector<std::string> pieces = android::base::Split(host, ":");
|
||||
const std::string& hostname = pieces[0];
|
||||
|
||||
fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
|
||||
int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
|
||||
if (pieces.size() > 1) {
|
||||
if (sscanf(pieces[1].c_str(), "%d", &port) != 1) {
|
||||
*response = android::base::StringPrintf("bad port number %s", pieces[1].c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// This may look like we're putting 'host' back together,
|
||||
// but we're actually inserting the default port if necessary.
|
||||
std::string serial = android::base::StringPrintf("%s:%d", hostname.c_str(), port);
|
||||
|
||||
int fd = socket_network_client_timeout(hostname.c_str(), port, SOCK_STREAM, 10);
|
||||
if (fd < 0) {
|
||||
snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
|
||||
*response = android::base::StringPrintf("unable to connect to %s:%d",
|
||||
hostname.c_str(), port);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -599,85 +595,74 @@ static void connect_device(char* host, char* buffer, int buffer_size)
|
|||
close_on_exec(fd);
|
||||
disable_tcp_nagle(fd);
|
||||
|
||||
ret = register_socket_transport(fd, serial, port, 0);
|
||||
int ret = register_socket_transport(fd, serial.c_str(), port, 0);
|
||||
if (ret < 0) {
|
||||
adb_close(fd);
|
||||
snprintf(buffer, buffer_size, "already connected to %s", serial);
|
||||
*response = android::base::StringPrintf("already connected to %s", serial.c_str());
|
||||
} else {
|
||||
snprintf(buffer, buffer_size, "connected to %s", serial);
|
||||
*response = android::base::StringPrintf("connected to %s", serial.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void connect_emulator(char* port_spec, char* buffer, int buffer_size)
|
||||
{
|
||||
char* port_separator = strchr(port_spec, ',');
|
||||
if (!port_separator) {
|
||||
snprintf(buffer, buffer_size,
|
||||
"unable to parse '%s' as <console port>,<adb port>",
|
||||
port_spec);
|
||||
void connect_emulator(const std::string& port_spec, std::string* response) {
|
||||
std::vector<std::string> pieces = android::base::Split(port_spec, ",");
|
||||
if (pieces.size() != 2) {
|
||||
*response = android::base::StringPrintf("unable to parse '%s' as <console port>,<adb port>",
|
||||
port_spec.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Zero-terminate console port and make port_separator point to 2nd port.
|
||||
*port_separator++ = 0;
|
||||
int console_port = strtol(port_spec, NULL, 0);
|
||||
int adb_port = strtol(port_separator, NULL, 0);
|
||||
if (!(console_port > 0 && adb_port > 0)) {
|
||||
*(port_separator - 1) = ',';
|
||||
snprintf(buffer, buffer_size,
|
||||
"Invalid port numbers: Expected positive numbers, got '%s'",
|
||||
port_spec);
|
||||
int console_port = strtol(pieces[0].c_str(), NULL, 0);
|
||||
int adb_port = strtol(pieces[1].c_str(), NULL, 0);
|
||||
if (console_port <= 0 || adb_port <= 0) {
|
||||
*response = android::base::StringPrintf("Invalid port numbers: %s", port_spec.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the emulator is already known.
|
||||
* Note: There's a small but harmless race condition here: An emulator not
|
||||
* present just yet could be registered by another invocation right
|
||||
* after doing this check here. However, local_connect protects
|
||||
* against double-registration too. From here, a better error message
|
||||
* can be produced. In the case of the race condition, the very specific
|
||||
* error message won't be shown, but the data doesn't get corrupted. */
|
||||
// Check if the emulator is already known.
|
||||
// Note: There's a small but harmless race condition here: An emulator not
|
||||
// present just yet could be registered by another invocation right
|
||||
// after doing this check here. However, local_connect protects
|
||||
// against double-registration too. From here, a better error message
|
||||
// can be produced. In the case of the race condition, the very specific
|
||||
// error message won't be shown, but the data doesn't get corrupted.
|
||||
atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
|
||||
if (known_emulator != NULL) {
|
||||
snprintf(buffer, buffer_size,
|
||||
"Emulator on port %d already registered.", adb_port);
|
||||
if (known_emulator != nullptr) {
|
||||
*response = android::base::StringPrintf("Emulator already registered on port %d", adb_port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if more emulators can be registered. Similar unproblematic
|
||||
* race condition as above. */
|
||||
// Check if more emulators can be registered. Similar unproblematic
|
||||
// race condition as above.
|
||||
int candidate_slot = get_available_local_transport_index();
|
||||
if (candidate_slot < 0) {
|
||||
snprintf(buffer, buffer_size, "Cannot accept more emulators.");
|
||||
*response = "Cannot accept more emulators";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Preconditions met, try to connect to the emulator. */
|
||||
// Preconditions met, try to connect to the emulator.
|
||||
if (!local_connect_arbitrary_ports(console_port, adb_port)) {
|
||||
snprintf(buffer, buffer_size,
|
||||
"Connected to emulator on ports %d,%d", console_port, adb_port);
|
||||
*response = android::base::StringPrintf("Connected to emulator on ports %d,%d",
|
||||
console_port, adb_port);
|
||||
} else {
|
||||
snprintf(buffer, buffer_size,
|
||||
"Could not connect to emulator on ports %d,%d",
|
||||
console_port, adb_port);
|
||||
*response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d",
|
||||
console_port, adb_port);
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_service(int fd, void* cookie)
|
||||
{
|
||||
char buf[4096];
|
||||
char resp[4096];
|
||||
char *host = reinterpret_cast<char*>(cookie);
|
||||
|
||||
std::string response;
|
||||
if (!strncmp(host, "emu:", 4)) {
|
||||
connect_emulator(host + 4, buf, sizeof(buf));
|
||||
connect_emulator(host + 4, &response);
|
||||
} else {
|
||||
connect_device(host, buf, sizeof(buf));
|
||||
connect_device(host, &response);
|
||||
}
|
||||
|
||||
// Send response for emulator and device
|
||||
snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
|
||||
WriteFdExactly(fd, resp, strlen(resp));
|
||||
SendProtocolString(fd, response);
|
||||
adb_close(fd);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
|
|
@ -37,23 +37,6 @@ ADB_MUTEX_DEFINE( socket_list_lock );
|
|||
|
||||
static void local_socket_close_locked(asocket *s);
|
||||
|
||||
int sendfailmsg(int fd, const char *reason)
|
||||
{
|
||||
char buf[9];
|
||||
int len;
|
||||
len = strlen(reason);
|
||||
if (len > 0xffff) {
|
||||
len = 0xffff;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof buf, "FAIL%04x", len);
|
||||
if (!WriteFdExactly(fd, buf, 8)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return WriteFdExactly(fd, reason, len) ? 0 : -1;
|
||||
}
|
||||
|
||||
static unsigned local_socket_next_id = 1;
|
||||
|
||||
static asocket local_socket_list = {
|
||||
|
@ -608,7 +591,7 @@ static void local_socket_ready_notify(asocket *s)
|
|||
s->ready = local_socket_ready;
|
||||
s->shutdown = NULL;
|
||||
s->close = local_socket_close;
|
||||
adb_write(s->fd, "OKAY", 4);
|
||||
SendOkay(s->fd);
|
||||
s->ready(s);
|
||||
}
|
||||
|
||||
|
@ -620,11 +603,11 @@ static void local_socket_close_notify(asocket *s)
|
|||
s->ready = local_socket_ready;
|
||||
s->shutdown = NULL;
|
||||
s->close = local_socket_close;
|
||||
sendfailmsg(s->fd, "closed");
|
||||
SendFail(s->fd, "closed");
|
||||
s->close(s);
|
||||
}
|
||||
|
||||
unsigned unhex(unsigned char *s, int len)
|
||||
static unsigned unhex(unsigned char *s, int len)
|
||||
{
|
||||
unsigned n = 0, c;
|
||||
|
||||
|
@ -654,6 +637,8 @@ unsigned unhex(unsigned char *s, int len)
|
|||
return n;
|
||||
}
|
||||
|
||||
#if ADB_HOST
|
||||
|
||||
#define PREFIX(str) { str, sizeof(str) - 1 }
|
||||
static const struct prefix_struct {
|
||||
const char *str;
|
||||
|
@ -670,7 +655,7 @@ static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0]));
|
|||
skipping over the 'serial' parameter in the ADB protocol,
|
||||
where parameter string may be a host:port string containing
|
||||
the protocol delimiter (colon). */
|
||||
char *skip_host_serial(char *service) {
|
||||
static char *skip_host_serial(char *service) {
|
||||
char *first_colon, *serial_end;
|
||||
int i;
|
||||
|
||||
|
@ -698,6 +683,8 @@ char *skip_host_serial(char *service) {
|
|||
return serial_end;
|
||||
}
|
||||
|
||||
#endif // ADB_HOST
|
||||
|
||||
static int smart_socket_enqueue(asocket *s, apacket *p)
|
||||
{
|
||||
unsigned len;
|
||||
|
@ -799,7 +786,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
|
|||
s2 = create_host_service_socket(service, serial);
|
||||
if(s2 == 0) {
|
||||
D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
|
||||
sendfailmsg(s->peer->fd, "unknown host service");
|
||||
SendFail(s->peer->fd, "unknown host service");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -810,7 +797,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
|
|||
** connection, and close this smart socket now
|
||||
** that its work is done.
|
||||
*/
|
||||
adb_write(s->peer->fd, "OKAY", 4);
|
||||
SendOkay(s->peer->fd);
|
||||
|
||||
s->peer->ready = local_socket_ready;
|
||||
s->peer->shutdown = NULL;
|
||||
|
@ -831,7 +818,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
|
|||
s->transport = acquire_one_transport(CS_ANY, kTransportAny, NULL, &error_msg);
|
||||
|
||||
if (s->transport == NULL) {
|
||||
sendfailmsg(s->peer->fd, error_msg.c_str());
|
||||
SendFail(s->peer->fd, error_msg);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -841,7 +828,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
|
|||
/* if there's no remote we fail the connection
|
||||
** right here and terminate it
|
||||
*/
|
||||
sendfailmsg(s->peer->fd, "device offline (x)");
|
||||
SendFail(s->peer->fd, "device offline (x)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// TODO: replace this with a shell/python script.
|
||||
|
||||
/* a simple test program, connects to ADB server, and opens a track-devices session */
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -6,6 +8,8 @@
|
|||
#include <errno.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <base/file.h>
|
||||
|
||||
static void
|
||||
panic( const char* msg )
|
||||
{
|
||||
|
@ -13,82 +17,49 @@ panic( const char* msg )
|
|||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
unix_write( int fd, const char* buf, int len )
|
||||
{
|
||||
int result = 0;
|
||||
while (len > 0) {
|
||||
int len2 = write(fd, buf, len);
|
||||
if (len2 < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
result += len2;
|
||||
len -= len2;
|
||||
buf += len2;
|
||||
int main(int argc, char* argv[]) {
|
||||
const char* request = "host:track-devices";
|
||||
|
||||
if (argv[1] && strcmp(argv[1], "--jdwp") == 0) {
|
||||
request = "track-jdwp";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
unix_read( int fd, char* buf, int len )
|
||||
{
|
||||
int result = 0;
|
||||
while (len > 0) {
|
||||
int len2 = read(fd, buf, len);
|
||||
if (len2 < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
result += len2;
|
||||
len -= len2;
|
||||
buf += len2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main( void )
|
||||
{
|
||||
int ret, s;
|
||||
int ret;
|
||||
struct sockaddr_in server;
|
||||
char buffer[1024];
|
||||
const char* request = "host:track-devices";
|
||||
int len;
|
||||
|
||||
memset( &server, 0, sizeof(server) );
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(5037);
|
||||
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
s = socket( PF_INET, SOCK_STREAM, 0 );
|
||||
int s = socket( PF_INET, SOCK_STREAM, 0 );
|
||||
ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
|
||||
if (ret < 0) panic( "could not connect to server" );
|
||||
|
||||
/* send the request */
|
||||
len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
|
||||
if (unix_write(s, buffer, len) < 0)
|
||||
int len = snprintf(buffer, sizeof(buffer), "%04zx%s", strlen(request), request);
|
||||
if (!android::base::WriteFully(s, buffer, len))
|
||||
panic( "could not send request" );
|
||||
|
||||
/* read the OKAY answer */
|
||||
if (unix_read(s, buffer, 4) != 4)
|
||||
if (!android::base::ReadFully(s, buffer, 4))
|
||||
panic( "could not read request" );
|
||||
|
||||
printf( "server answer: %.*s\n", 4, buffer );
|
||||
|
||||
/* now loop */
|
||||
for (;;) {
|
||||
while (true) {
|
||||
char head[5] = "0000";
|
||||
|
||||
if (unix_read(s, head, 4) < 0)
|
||||
if (!android::base::ReadFully(s, head, 4))
|
||||
panic("could not read length");
|
||||
|
||||
if ( sscanf( head, "%04x", &len ) != 1 )
|
||||
int len;
|
||||
if (sscanf(head, "%04x", &len) != 1 )
|
||||
panic("could not decode length");
|
||||
|
||||
if (unix_read(s, buffer, len) != len)
|
||||
if (!android::base::ReadFully(s, buffer, len))
|
||||
panic("could not read data");
|
||||
|
||||
printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/* a simple test program, connects to ADB server, and opens a track-devices session */
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <memory.h>
|
||||
|
||||
static void
|
||||
panic( const char* msg )
|
||||
{
|
||||
fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
unix_write( int fd, const char* buf, int len )
|
||||
{
|
||||
int result = 0;
|
||||
while (len > 0) {
|
||||
int len2 = write(fd, buf, len);
|
||||
if (len2 < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
result += len2;
|
||||
len -= len2;
|
||||
buf += len2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
unix_read( int fd, char* buf, int len )
|
||||
{
|
||||
int result = 0;
|
||||
while (len > 0) {
|
||||
int len2 = read(fd, buf, len);
|
||||
if (len2 < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
result += len2;
|
||||
len -= len2;
|
||||
buf += len2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main( void )
|
||||
{
|
||||
int ret, s;
|
||||
struct sockaddr_in server;
|
||||
char buffer[1024];
|
||||
const char* request = "track-jdwp";
|
||||
int len;
|
||||
|
||||
memset( &server, 0, sizeof(server) );
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(5037);
|
||||
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
s = socket( PF_INET, SOCK_STREAM, 0 );
|
||||
ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
|
||||
if (ret < 0) panic( "could not connect to server" );
|
||||
|
||||
/* send the request */
|
||||
len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
|
||||
if (unix_write(s, buffer, len) < 0)
|
||||
panic( "could not send request" );
|
||||
|
||||
/* read the OKAY answer */
|
||||
if (unix_read(s, buffer, 4) != 4)
|
||||
panic( "could not read request" );
|
||||
|
||||
printf( "server answer: %.*s\n", 4, buffer );
|
||||
|
||||
/* now loop */
|
||||
for (;;) {
|
||||
char head[5] = "0000";
|
||||
|
||||
if (unix_read(s, head, 4) < 0)
|
||||
panic("could not read length");
|
||||
|
||||
if ( sscanf( head, "%04x", &len ) != 1 )
|
||||
panic("could not decode length");
|
||||
|
||||
if (unix_read(s, buffer, len) != len)
|
||||
panic("could not read data");
|
||||
|
||||
printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
|
||||
}
|
||||
close(s);
|
||||
}
|
|
@ -26,7 +26,10 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "adb_utils.h"
|
||||
|
||||
static void transport_unref(atransport *t);
|
||||
|
||||
|
@ -42,34 +45,6 @@ static atransport pending_list = {
|
|||
|
||||
ADB_MUTEX_DEFINE( transport_lock );
|
||||
|
||||
#if ADB_TRACE
|
||||
#define MAX_DUMP_HEX_LEN 16
|
||||
void dump_hex(const unsigned char* ptr, size_t len)
|
||||
{
|
||||
int nn, len2 = len;
|
||||
// Build a string instead of logging each character.
|
||||
// MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
|
||||
char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
|
||||
|
||||
if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
|
||||
|
||||
for (nn = 0; nn < len2; nn++) {
|
||||
sprintf(pb, "%02x", ptr[nn]);
|
||||
pb += 2;
|
||||
}
|
||||
sprintf(pb++, " ");
|
||||
|
||||
for (nn = 0; nn < len2; nn++) {
|
||||
int c = ptr[nn];
|
||||
if (c < 32 || c > 127)
|
||||
c = '.';
|
||||
*pb++ = c;
|
||||
}
|
||||
*pb++ = '\0';
|
||||
DR("%s\n", buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kick_transport(atransport* t)
|
||||
{
|
||||
if (t && !t->kicked)
|
||||
|
@ -117,10 +92,7 @@ void run_transport_disconnects(atransport* t)
|
|||
}
|
||||
}
|
||||
|
||||
#if ADB_TRACE
|
||||
static void
|
||||
dump_packet(const char* name, const char* func, apacket* p)
|
||||
{
|
||||
static void dump_packet(const char* name, const char* func, apacket* p) {
|
||||
unsigned command = p->msg.command;
|
||||
int len = p->msg.data_length;
|
||||
char cmd[9];
|
||||
|
@ -155,7 +127,6 @@ dump_packet(const char* name, const char* func, apacket* p)
|
|||
name, func, cmd, arg0, arg1, len);
|
||||
dump_hex(p->data, len);
|
||||
}
|
||||
#endif /* ADB_TRACE */
|
||||
|
||||
static int
|
||||
read_packet(int fd, const char* name, apacket** ppacket)
|
||||
|
@ -180,11 +151,9 @@ read_packet(int fd, const char* name, apacket** ppacket)
|
|||
}
|
||||
}
|
||||
|
||||
#if ADB_TRACE
|
||||
if (ADB_TRACING) {
|
||||
dump_packet(name, "from remote", *ppacket);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -199,11 +168,9 @@ write_packet(int fd, const char* name, apacket** ppacket)
|
|||
name = buff;
|
||||
}
|
||||
|
||||
#if ADB_TRACE
|
||||
if (ADB_TRACING) {
|
||||
dump_packet(name, "to remote", *ppacket);
|
||||
}
|
||||
#endif
|
||||
len = sizeof(ppacket);
|
||||
while(len > 0) {
|
||||
r = adb_write(fd, p, len);
|
||||
|
@ -389,17 +356,6 @@ static fdevent transport_registration_fde;
|
|||
|
||||
|
||||
#if ADB_HOST
|
||||
static int list_transports_msg(char* buffer, size_t bufferlen)
|
||||
{
|
||||
char head[5];
|
||||
int len;
|
||||
|
||||
len = list_transports(buffer+4, bufferlen-4, 0);
|
||||
snprintf(head, sizeof(head), "%04x", len);
|
||||
memcpy(buffer, head, 4);
|
||||
len += 4;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* this adds support required by the 'track-devices' service.
|
||||
* this is used to send the content of "list_transport" to any
|
||||
|
@ -457,39 +413,29 @@ device_tracker_enqueue( asocket* socket, apacket* p )
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
device_tracker_send( device_tracker* tracker,
|
||||
const char* buffer,
|
||||
int len )
|
||||
{
|
||||
apacket* p = get_apacket();
|
||||
asocket* peer = tracker->socket.peer;
|
||||
static int device_tracker_send(device_tracker* tracker, const std::string& string) {
|
||||
apacket* p = get_apacket();
|
||||
asocket* peer = tracker->socket.peer;
|
||||
|
||||
memcpy(p->data, buffer, len);
|
||||
p->len = len;
|
||||
return peer->enqueue( peer, p );
|
||||
snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
|
||||
memcpy(&p->data[4], string.data(), string.size());
|
||||
p->len = 4 + string.size();
|
||||
return peer->enqueue(peer, p);
|
||||
}
|
||||
|
||||
static void device_tracker_ready(asocket* socket) {
|
||||
device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
|
||||
|
||||
static void
|
||||
device_tracker_ready( asocket* socket )
|
||||
{
|
||||
device_tracker* tracker = (device_tracker*) socket;
|
||||
|
||||
/* we want to send the device list when the tracker connects
|
||||
* for the first time, even if no update occured */
|
||||
// We want to send the device list when the tracker connects
|
||||
// for the first time, even if no update occurred.
|
||||
if (tracker->update_needed > 0) {
|
||||
char buffer[1024];
|
||||
int len;
|
||||
|
||||
tracker->update_needed = 0;
|
||||
|
||||
len = list_transports_msg(buffer, sizeof(buffer));
|
||||
device_tracker_send(tracker, buffer, len);
|
||||
std::string transports = list_transports(false);
|
||||
device_tracker_send(tracker, transports);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
asocket*
|
||||
create_device_tracker(void)
|
||||
{
|
||||
|
@ -510,27 +456,25 @@ create_device_tracker(void)
|
|||
}
|
||||
|
||||
|
||||
/* call this function each time the transport list has changed */
|
||||
void update_transports(void) {
|
||||
char buffer[1024];
|
||||
int len;
|
||||
device_tracker* tracker;
|
||||
// Call this function each time the transport list has changed.
|
||||
void update_transports() {
|
||||
std::string transports = list_transports(false);
|
||||
|
||||
len = list_transports_msg(buffer, sizeof(buffer));
|
||||
|
||||
tracker = device_tracker_list;
|
||||
while (tracker != NULL) {
|
||||
device_tracker* next = tracker->next;
|
||||
/* note: this may destroy the tracker if the connection is closed */
|
||||
device_tracker_send(tracker, buffer, len);
|
||||
device_tracker* tracker = device_tracker_list;
|
||||
while (tracker != nullptr) {
|
||||
device_tracker* next = tracker->next;
|
||||
// This may destroy the tracker if the connection is closed.
|
||||
device_tracker_send(tracker, transports);
|
||||
tracker = next;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void update_transports(void)
|
||||
{
|
||||
// nothing to do on the device side
|
||||
|
||||
void update_transports() {
|
||||
// Nothing to do on the device side.
|
||||
}
|
||||
|
||||
#endif // ADB_HOST
|
||||
|
||||
struct tmsg
|
||||
|
@ -895,100 +839,71 @@ retry:
|
|||
return result;
|
||||
}
|
||||
|
||||
#if ADB_HOST
|
||||
static const char *statename(atransport *t)
|
||||
{
|
||||
switch(t->connection_state){
|
||||
const char* atransport::connection_state_name() const {
|
||||
switch (connection_state) {
|
||||
case CS_OFFLINE: return "offline";
|
||||
case CS_BOOTLOADER: return "bootloader";
|
||||
case CS_DEVICE: return "device";
|
||||
case CS_HOST: return "host";
|
||||
case CS_RECOVERY: return "recovery";
|
||||
case CS_SIDELOAD: return "sideload";
|
||||
case CS_NOPERM: return "no permissions";
|
||||
case CS_SIDELOAD: return "sideload";
|
||||
case CS_UNAUTHORIZED: return "unauthorized";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void add_qual(char **buf, size_t *buf_size,
|
||||
const char *prefix, const char *qual, bool sanitize_qual)
|
||||
{
|
||||
if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
|
||||
#if ADB_HOST
|
||||
|
||||
static void append_transport_info(std::string* result, const char* key, const char* value, bool sanitize) {
|
||||
if (value == nullptr || *value == '\0') {
|
||||
return;
|
||||
|
||||
int prefix_len;
|
||||
size_t len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
|
||||
|
||||
if (sanitize_qual) {
|
||||
for (char* cp = *buf + prefix_len; cp < *buf + len; cp++) {
|
||||
if (!isalnum(*cp))
|
||||
*cp = '_';
|
||||
}
|
||||
}
|
||||
|
||||
*buf_size -= len;
|
||||
*buf += len;
|
||||
*result += ' ';
|
||||
*result += key;
|
||||
|
||||
for (const char* p = value; *p; ++p) {
|
||||
result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
|
||||
}
|
||||
}
|
||||
|
||||
static size_t format_transport(atransport *t, char *buf, size_t bufsize,
|
||||
int long_listing)
|
||||
{
|
||||
static void append_transport(atransport* t, std::string* result, bool long_listing) {
|
||||
const char* serial = t->serial;
|
||||
if (!serial || !serial[0])
|
||||
if (!serial || !serial[0]) {
|
||||
serial = "????????????";
|
||||
}
|
||||
|
||||
if (!long_listing) {
|
||||
return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t));
|
||||
*result += serial;
|
||||
*result += '\t';
|
||||
*result += t->connection_state_name();
|
||||
} else {
|
||||
size_t len, remaining = bufsize;
|
||||
android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
|
||||
|
||||
len = snprintf(buf, remaining, "%-22s %s", serial, statename(t));
|
||||
remaining -= len;
|
||||
buf += len;
|
||||
|
||||
add_qual(&buf, &remaining, " ", t->devpath, false);
|
||||
add_qual(&buf, &remaining, " product:", t->product, false);
|
||||
add_qual(&buf, &remaining, " model:", t->model, true);
|
||||
add_qual(&buf, &remaining, " device:", t->device, false);
|
||||
|
||||
len = snprintf(buf, remaining, "\n");
|
||||
remaining -= len;
|
||||
|
||||
return bufsize - remaining;
|
||||
append_transport_info(result, "", t->devpath, false);
|
||||
append_transport_info(result, "product:", t->product, false);
|
||||
append_transport_info(result, "model:", t->model, true);
|
||||
append_transport_info(result, "device:", t->device, false);
|
||||
}
|
||||
*result += '\n';
|
||||
}
|
||||
|
||||
int list_transports(char *buf, size_t bufsize, int long_listing)
|
||||
{
|
||||
char* p = buf;
|
||||
char* end = buf + bufsize;
|
||||
int len;
|
||||
atransport *t;
|
||||
|
||||
/* XXX OVERRUN PROBLEMS XXX */
|
||||
std::string list_transports(bool long_listing) {
|
||||
std::string result;
|
||||
adb_mutex_lock(&transport_lock);
|
||||
for(t = transport_list.next; t != &transport_list; t = t->next) {
|
||||
len = format_transport(t, p, end - p, long_listing);
|
||||
if (p + len >= end) {
|
||||
/* discard last line if buffer is too short */
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
|
||||
append_transport(t, &result, long_listing);
|
||||
}
|
||||
p[0] = 0;
|
||||
adb_mutex_unlock(&transport_lock);
|
||||
return p - buf;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* hack for osx */
|
||||
void close_usb_devices()
|
||||
{
|
||||
atransport *t;
|
||||
|
||||
adb_mutex_lock(&transport_lock);
|
||||
for(t = transport_list.next; t != &transport_list; t = t->next) {
|
||||
for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
|
||||
if ( !t->kicked ) {
|
||||
t->kicked = 1;
|
||||
t->kick(t);
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
|
||||
#include "adb.h"
|
||||
|
||||
#if ADB_TRACE
|
||||
void dump_hex(const unsigned char* ptr, size_t len);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Obtain a transport from the available transports.
|
||||
* If state is != CS_ANY, only transports in that state are considered.
|
||||
|
@ -45,7 +41,7 @@ void update_transports(void);
|
|||
** get_device_transport does an acquire on your behalf before returning
|
||||
*/
|
||||
void init_transport_registration(void);
|
||||
int list_transports(char* buf, size_t bufsize, int long_listing);
|
||||
std::string list_transports(bool long_listing);
|
||||
atransport* find_transport(const char* serial);
|
||||
|
||||
void register_usb_transport(usb_handle* h, const char* serial,
|
||||
|
|
Loading…
Reference in a new issue