summaryrefslogtreecommitdiffstats
path: root/adb
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2014-05-27 16:43:45 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-05-27 16:43:45 +0000
commit7291ac60822c8b84e423de4f4abec6663d0e8f50 (patch)
tree763063e561c78d54b6b55c0243f354df803ee7d5 /adb
parentef386b3fb01b7458f2dcf11c9be7bd099f0ea2ed (diff)
parent972677557bd2c3a0678a945765783e85c7ec7b9c (diff)
downloadcore-7291ac60822c8b84e423de4f4abec6663d0e8f50.tar.gz
core-7291ac60822c8b84e423de4f4abec6663d0e8f50.tar.bz2
core-7291ac60822c8b84e423de4f4abec6663d0e8f50.zip
am 97267755: am c3358875: am 6e7343b8: Merge "adb: implement "adb reverse <local> <remote>""
* commit '972677557bd2c3a0678a945765783e85c7ec7b9c': adb: implement "adb reverse <local> <remote>"
Diffstat (limited to 'adb')
-rw-r--r--adb/SERVICES.TXT17
-rw-r--r--adb/adb.c221
-rw-r--r--adb/adb.h2
-rw-r--r--adb/commandline.c38
-rw-r--r--adb/services.c21
5 files changed, 198 insertions, 101 deletions
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
index 7f85dc343..63000f293 100644
--- a/adb/SERVICES.TXT
+++ b/adb/SERVICES.TXT
@@ -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'.
diff --git a/adb/adb.c b/adb/adb.c
index 018dd3c45..6d3a71bb8 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -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);
diff --git a/adb/adb.h b/adb/adb.h
index 6f5c93c3e..2504f9926 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -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,
diff --git a/adb/commandline.c b/adb/commandline.c
index a3eaf43c2..70bf641d0 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -137,6 +137,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"
@@ -1308,8 +1321,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;
@@ -1338,15 +1354,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
diff --git a/adb/services.c b/adb/services.c
index e25a232c8..7b809da94 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -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) {