Loading adb/SERVICES.TXT +17 −0 Original line number Diff line number Diff line Loading @@ -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'. adb/adb.c +129 −92 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1428,6 +1439,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; Loading Loading @@ -1548,97 +1673,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); Loading adb/adb.h +2 −0 Original line number Diff line number Diff line Loading @@ -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, Loading adb/commandline.c +29 −9 Original line number Diff line number Diff line Loading @@ -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] [-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" Loading Loading @@ -1299,8 +1312,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; Loading Loading @@ -1329,6 +1345,9 @@ top: } // Determine the <host-prefix> for this command. if (reverse) { snprintf(host_prefix, sizeof host_prefix, "reverse"); } else { if (serial) { snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", serial); Loading @@ -1339,6 +1358,7 @@ top: } else { snprintf(host_prefix, sizeof host_prefix, "host"); } } // Implement forward --list if (list) { Loading adb/services.c +21 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,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) Loading Loading @@ -398,6 +409,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) { Loading Loading
adb/SERVICES.TXT +17 −0 Original line number Diff line number Diff line Loading @@ -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'.
adb/adb.c +129 −92 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1428,6 +1439,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; Loading Loading @@ -1548,97 +1673,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); Loading
adb/adb.h +2 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
adb/commandline.c +29 −9 Original line number Diff line number Diff line Loading @@ -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] [-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" Loading Loading @@ -1299,8 +1312,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; Loading Loading @@ -1329,6 +1345,9 @@ top: } // Determine the <host-prefix> for this command. if (reverse) { snprintf(host_prefix, sizeof host_prefix, "reverse"); } else { if (serial) { snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", serial); Loading @@ -1339,6 +1358,7 @@ top: } else { snprintf(host_prefix, sizeof host_prefix, "host"); } } // Implement forward --list if (list) { Loading
adb/services.c +21 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,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) Loading Loading @@ -398,6 +409,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) { Loading