am c3358875: am 6e7343b8: Merge "adb: implement "adb reverse <local> <remote>""

* commit 'c3358875169b920847a72428f4e8b8f09f7bdf05':
  adb: implement "adb reverse <local> <remote>"
This commit is contained in:
David 'Digit' Turner 2014-05-27 16:36:30 +00:00 committed by Android Git Automerger
commit 972677557b
5 changed files with 198 additions and 101 deletions

View File

@ -240,3 +240,20 @@ sync:
This starts the file synchronisation service, used to implement "adb push"
and "adb pull". Since this service is pretty complex, it will be detailed
in a companion document named SYNC.TXT
reverse:<forward-command>
This implements the 'adb reverse' feature, i.e. the ability to reverse
socket connections from a device to the host. <forward-command> is one
of the forwarding commands that are described above, as in:
list-forward
forward:<local>;<remote>
forward:norebind:<local>;<remote>
killforward-all
killforward:<local>
Note that in this case, <local> corresponds to the socket on the device
and <remote> corresponds to the socket on the host.
The output of reverse:list-forward is the same as host:list-forward
except that <serial> will be just 'host'.

221
adb/adb.c
View File

@ -318,7 +318,18 @@ static size_t fill_connect_data(char *buf, size_t bufsize)
#endif
}
static void send_msg_with_okay(int fd, char* msg, size_t msglen) {
#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);
writex(fd, header, 4);
writex(fd, msg, msglen);
}
#endif
static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
char header[9];
if (msglen > 0xffff)
msglen = 0xffff;
@ -1427,6 +1438,120 @@ int adb_main(int is_daemon, int server_port)
return 0;
}
// Try to handle a network forwarding request.
// This returns 1 on success, 0 on failure, and -1 to indicate this is not
// a forwarding-related request.
int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
{
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 = malloc(buffer_size + 1);
if (buffer == NULL) {
sendfailmsg(reply_fd, "not enough memory");
return 1;
}
(void) format_listeners(buffer, buffer_size + 1);
#if ADB_HOST
send_msg_with_okay(reply_fd, buffer, buffer_size);
#else
send_msg_with_header(reply_fd, buffer, buffer_size);
#endif
free(buffer);
return 1;
}
if (!strcmp(service, "killforward-all")) {
remove_all_listeners();
#if ADB_HOST
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
adb_write(reply_fd, "OKAY", 4);
#endif
adb_write(reply_fd, "OKAY", 4);
return 1;
}
if (!strncmp(service, "forward:",8) ||
!strncmp(service, "killforward:",12)) {
char *local, *remote, *err;
int r;
atransport *transport;
int createForward = strncmp(service, "kill", 4);
int no_rebind = 0;
local = strchr(service, ':') + 1;
// Handle forward:norebind:<local>... here
if (createForward && !strncmp(local, "norebind:", 9)) {
no_rebind = 1;
local = strchr(local, ':') + 1;
}
remote = strchr(local,';');
if (createForward) {
// Check forward: parameter format: '<local>;<remote>'
if(remote == 0) {
sendfailmsg(reply_fd, "malformed forward spec");
return 1;
}
*remote++ = 0;
if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
sendfailmsg(reply_fd, "malformed forward spec");
return 1;
}
} else {
// Check killforward: parameter format: '<local>'
if (local[0] == 0) {
sendfailmsg(reply_fd, "malformed forward spec");
return 1;
}
}
transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
if (!transport) {
sendfailmsg(reply_fd, err);
return 1;
}
if (createForward) {
r = install_listener(local, remote, transport, no_rebind);
} else {
r = remove_listener(local, transport);
}
if(r == 0) {
#if ADB_HOST
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
writex(reply_fd, "OKAY", 4);
#endif
writex(reply_fd, "OKAY", 4);
return 1;
}
if (createForward) {
const char* message;
switch (r) {
case INSTALL_STATUS_CANNOT_BIND:
message = "cannot bind to socket";
break;
case INSTALL_STATUS_CANNOT_REBIND:
message = "cannot rebind existing socket";
break;
default:
message = "internal error";
}
sendfailmsg(reply_fd, message);
} else {
sendfailmsg(reply_fd, "cannot remove listener");
}
return 1;
}
return 0;
}
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
{
atransport *transport = NULL;
@ -1547,97 +1672,9 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
}
#endif // ADB_HOST
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 = malloc(buffer_size+1);
(void) format_listeners(buffer, buffer_size+1);
send_msg_with_okay(reply_fd, buffer, buffer_size);
free(buffer);
return 0;
}
if (!strcmp(service,"killforward-all")) {
remove_all_listeners();
adb_write(reply_fd, "OKAYOKAY", 8);
return 0;
}
if(!strncmp(service,"forward:",8) ||
!strncmp(service,"killforward:",12)) {
char *local, *remote, *err;
int r;
atransport *transport;
int createForward = strncmp(service,"kill",4);
int no_rebind = 0;
local = strchr(service, ':') + 1;
// Handle forward:norebind:<local>... here
if (createForward && !strncmp(local, "norebind:", 9)) {
no_rebind = 1;
local = strchr(local, ':') + 1;
}
remote = strchr(local,';');
if (createForward) {
// Check forward: parameter format: '<local>;<remote>'
if(remote == 0) {
sendfailmsg(reply_fd, "malformed forward spec");
return 0;
}
*remote++ = 0;
if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
sendfailmsg(reply_fd, "malformed forward spec");
return 0;
}
} else {
// Check killforward: parameter format: '<local>'
if (local[0] == 0) {
sendfailmsg(reply_fd, "malformed forward spec");
return 0;
}
}
transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
if (!transport) {
sendfailmsg(reply_fd, err);
return 0;
}
if (createForward) {
r = install_listener(local, remote, transport, no_rebind);
} else {
r = remove_listener(local, transport);
}
if(r == 0) {
/* 1st OKAY is connect, 2nd OKAY is status */
writex(reply_fd, "OKAYOKAY", 8);
return 0;
}
if (createForward) {
const char* message;
switch (r) {
case INSTALL_STATUS_CANNOT_BIND:
message = "cannot bind to socket";
break;
case INSTALL_STATUS_CANNOT_REBIND:
message = "cannot rebind existing socket";
break;
default:
message = "internal error";
}
sendfailmsg(reply_fd, message);
} else {
sendfailmsg(reply_fd, "cannot remove listener");
}
return 0;
}
int ret = handle_forward_request(service, ttype, serial, reply_fd);
if (ret >= 0)
return ret - 1;
if(!strncmp(service,"get-state",strlen("get-state"))) {
transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);

View File

@ -323,6 +323,8 @@ asocket* create_jdwp_tracker_service_socket();
int create_jdwp_connection_fd(int jdwp_pid);
#endif
int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd);
#if !ADB_HOST
typedef enum {
BACKUP,

View File

@ -136,6 +136,19 @@ void help()
" if <local> is already forwarded\n"
" adb forward --remove <local> - remove a specific forward socket connection\n"
" adb forward --remove-all - remove all forward socket connections\n"
" adb reverse --list - list all reverse socket connections from device\n"
" adb reverse <remote> <local> - reverse socket connections\n"
" reverse specs are one of:\n"
" tcp:<port>\n"
" localabstract:<unix domain socket name>\n"
" localreserved:<unix domain socket name>\n"
" localfilesystem:<unix domain socket name>\n"
" adb reverse --norebind <remote> <local>\n"
" - same as 'adb reverse <remote> <local>' but fails\n"
" if <remote> is already reversed.\n"
" adb reverse --remove <remote>\n"
" - remove a specific reversed socket connection\n"
" adb reverse --remove-all - remove all reversed socket connections from device\n"
" adb jdwp - list PIDs of processes hosting a JDWP transport\n"
" adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
" - push this package file to the device and install it\n"
@ -1300,8 +1313,11 @@ top:
return 0;
}
if(!strcmp(argv[0], "forward")) {
if(!strcmp(argv[0], "forward") ||
!strcmp(argv[0], "reverse"))
{
char host_prefix[64];
char reverse = (char) !strcmp(argv[0], "reverse");
char remove = 0;
char remove_all = 0;
char list = 0;
@ -1330,15 +1346,19 @@ top:
}
// Determine the <host-prefix> for this command.
if (serial) {
snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
serial);
} else if (ttype == kTransportUsb) {
snprintf(host_prefix, sizeof host_prefix, "host-usb");
} else if (ttype == kTransportLocal) {
snprintf(host_prefix, sizeof host_prefix, "host-local");
if (reverse) {
snprintf(host_prefix, sizeof host_prefix, "reverse");
} else {
snprintf(host_prefix, sizeof host_prefix, "host");
if (serial) {
snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
serial);
} else if (ttype == kTransportUsb) {
snprintf(host_prefix, sizeof host_prefix, "host-usb");
} else if (ttype == kTransportLocal) {
snprintf(host_prefix, sizeof host_prefix, "host-local");
} else {
snprintf(host_prefix, sizeof host_prefix, "host");
}
}
// Implement forward --list

View File

@ -141,6 +141,17 @@ cleanup:
adb_close(fd);
}
void reverse_service(int fd, void* arg)
{
const char* command = arg;
if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
sendfailmsg(fd, "not a reverse forwarding command");
}
free(arg);
adb_close(fd);
}
#endif
static int create_service_thread(void (*func)(int, void *), void *cookie)
@ -385,6 +396,16 @@ int service_to_fd(const char *name)
ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
} else if(!strncmp(name, "usb:", 4)) {
ret = create_service_thread(restart_usb_service, NULL);
} else if (!strncmp(name, "reverse:", 8)) {
char* cookie = strdup(name + 8);
if (cookie == NULL) {
ret = -1;
} else {
ret = create_service_thread(reverse_service, cookie);
if (ret < 0) {
free(cookie);
}
}
#endif
}
if (ret >= 0) {