Loading adb/SERVICES.TXT +27 −0 Original line number Diff line number Diff line Loading @@ -117,7 +117,34 @@ host:<request> or even any one of the local services described below. <host-prefix>:forward:norebind:<local>;<remote> Same as <host-prefix>:forward:<local>;<remote> except that it will fail it there is already a forward connection from <local>. Used to implement 'adb forward --no-rebind <local> <remote>' <host-prefix>:killforward:<local> Remove any existing forward local connection from <local>. This is used to implement 'adb forward --remove <local>' <host-prefix>:killforward-all Remove all forward network connections. This is used to implement 'adb forward --remove-all'. <host-prefix>:list-forward List all existing forward connections from this server. This returns something that looks like the following: <hex4>: The length of the payload, as 4 hexadecimal chars. <payload>: A series of lines of the following format: <serial> " " <local> " " <remote> "\n" Where <serial> is a device serial number. <local> is the host-specific endpoint (e.g. tcp:9000). <remote> is the device-specific endpoint. Used to implement 'adb forward --list'. LOCAL SERVICES: Loading adb/adb.c +149 −28 Original line number Diff line number Diff line Loading @@ -722,24 +722,90 @@ int local_name_to_fd(const char *name) return -1; } static int remove_listener(const char *local_name, const char *connect_to, atransport* transport) // 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. static int format_listeners(char* buf, size_t buflen) { alistener* l; int result = 0; for (l = listener_list.next; l != &listener_list; l = l->next) { if (!strcmp(local_name, l->local_name) && !strcmp(connect_to, l->connect_to) && l->transport && l->transport == transport) { // 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; } } return result; } listener_disconnect(l, transport); static int remove_listener(const char *local_name, atransport* transport) { alistener *l; for (l = listener_list.next; l != &listener_list; l = l->next) { if (!strcmp(local_name, l->local_name)) { listener_disconnect(l, l->transport); return 0; } } return -1; } static int install_listener(const char *local_name, const char *connect_to, atransport* transport) static void remove_all_listeners(void) { alistener *l, *l_next; for (l = listener_list.next; l != &listener_list; l = l_next) { l_next = l->next; // Never remove smart sockets. if (l->connect_to[0] == '*') continue; listener_disconnect(l, l->transport); } } // error/status codes for install_listener. typedef enum { INSTALL_STATUS_OK = 0, INSTALL_STATUS_INTERNAL_ERROR = -1, INSTALL_STATUS_CANNOT_BIND = -2, INSTALL_STATUS_CANNOT_REBIND = -3, } install_status_t; static install_status_t install_listener(const char *local_name, const char *connect_to, atransport* transport, int no_rebind) { alistener *l; Loading @@ -751,12 +817,17 @@ static int install_listener(const char *local_name, const char *connect_to, atra /* can't repurpose a smartsocket */ if(l->connect_to[0] == '*') { return -1; return INSTALL_STATUS_INTERNAL_ERROR; } /* can't repurpose a listener if 'no_rebind' is true */ if (no_rebind) { return INSTALL_STATUS_CANNOT_REBIND; } cto = strdup(connect_to); if(cto == 0) { return -1; return INSTALL_STATUS_INTERNAL_ERROR; } //printf("rebinding '%s' to '%s'\n", local_name, connect_to); Loading @@ -767,7 +838,7 @@ static int install_listener(const char *local_name, const char *connect_to, atra l->transport = transport; add_transport_disconnect(l->transport, &l->disconnect); } return 0; return INSTALL_STATUS_OK; } } Loading Loading @@ -804,11 +875,11 @@ static int install_listener(const char *local_name, const char *connect_to, atra l->disconnect.func = listener_disconnect; add_transport_disconnect(transport, &l->disconnect); } return 0; return INSTALL_STATUS_OK; nomem: fatal("cannot allocate listener"); return 0; return INSTALL_STATUS_INTERNAL_ERROR; } #ifdef HAVE_WIN32_PROC Loading Loading @@ -1113,7 +1184,7 @@ int adb_main(int is_daemon, int server_port) char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL)) { if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } #else Loading Loading @@ -1180,7 +1251,7 @@ int adb_main(int is_daemon, int server_port) } else { char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL)) { if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } } Loading Loading @@ -1474,15 +1545,47 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } #endif // ADB_HOST if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) { if(!strcmp(service,"list-forward")) { // Create the list of forward redirections. char header[9]; 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); snprintf(header, sizeof header, "OKAY%04x", buffer_size); writex(reply_fd, header, 8); writex(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; } local = service + (createForward ? 8 : 12); remote = strchr(local,';'); if (createForward) { // Check forward: parameter format: '<local>;<remote>' if(remote == 0) { sendfailmsg(reply_fd, "malformed forward spec"); return 0; Loading @@ -1493,6 +1596,13 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r 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) { Loading @@ -1501,9 +1611,9 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if (createForward) { r = install_listener(local, remote, transport); r = install_listener(local, remote, transport, no_rebind); } else { r = remove_listener(local, remote, transport); r = remove_listener(local, transport); } if(r == 0) { /* 1st OKAY is connect, 2nd OKAY is status */ Loading @@ -1512,7 +1622,18 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if (createForward) { sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket"); 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"); } Loading adb/commandline.c +82 −5 Original line number Diff line number Diff line Loading @@ -112,6 +112,9 @@ void help() " adb shell <command> - run remote shell command\n" " adb emu <command> - run emulator console command\n" " adb logcat [ <filter-spec> ] - View device log\n" " adb forward --list - list all forward socket connections.\n" " the format is a list of lines with the following format:\n" " <serial> \" \" <local> \" \" <remote> \"\\n\"\n" " adb forward <local> <remote> - forward socket connections\n" " forward specs are one of: \n" " tcp:<port>\n" Loading @@ -120,6 +123,11 @@ void help() " localfilesystem:<unix domain socket name>\n" " dev:<character device name>\n" " jdwp:<process pid> (remote only)\n" " adb forward --no-rebind <local> <remote>\n" " - same as 'adb forward <local> <remote>' but fails\n" " 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 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 @@ -1223,16 +1231,85 @@ top: } if(!strcmp(argv[0], "forward")) { if(argc != 3) return usage(); char host_prefix[64]; char remove = 0; char remove_all = 0; char list = 0; char no_rebind = 0; // Parse options here. while (argc > 1 && argv[1][0] == '-') { if (!strcmp(argv[1], "--list")) list = 1; else if (!strcmp(argv[1], "--remove")) remove = 1; else if (!strcmp(argv[1], "--remove-all")) remove_all = 1; else if (!strcmp(argv[1], "--no-rebind")) no_rebind = 1; else { return usage(); } argc--; argv++; } // Ensure we can only use one option at a time. if (list + remove + remove_all + no_rebind > 1) { return usage(); } // Determine the <host-prefix> for this command. if (serial) { snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", serial); } else if (ttype == kTransportUsb) { snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host-usb"); } else if (ttype == kTransportLocal) { snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host-local"); } else { snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host"); } // Implement forward --list if (list) { if (argc != 1) return usage(); snprintf(buf, sizeof buf, "%s:list-forward", host_prefix); char* forwards = adb_query(buf); if (forwards == NULL) { fprintf(stderr, "error: %s\n", adb_error()); return 1; } printf("%s", forwards); free(forwards); return 0; } // Implement forward --remove-all else if (remove_all) { if (argc != 1) return usage(); snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix); } // Implement forward --remove <local> else if (remove) { if (argc != 2) return usage(); snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]); } // Or implement one of: // forward <local> <remote> // forward --no-rebind <local> <remote> else { if (argc != 3) return usage(); const char* command = no_rebind ? "forward:norebind:" : "forward"; snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]); } if(adb_command(buf)) { fprintf(stderr,"error: %s\n", adb_error()); return 1; Loading Loading
adb/SERVICES.TXT +27 −0 Original line number Diff line number Diff line Loading @@ -117,7 +117,34 @@ host:<request> or even any one of the local services described below. <host-prefix>:forward:norebind:<local>;<remote> Same as <host-prefix>:forward:<local>;<remote> except that it will fail it there is already a forward connection from <local>. Used to implement 'adb forward --no-rebind <local> <remote>' <host-prefix>:killforward:<local> Remove any existing forward local connection from <local>. This is used to implement 'adb forward --remove <local>' <host-prefix>:killforward-all Remove all forward network connections. This is used to implement 'adb forward --remove-all'. <host-prefix>:list-forward List all existing forward connections from this server. This returns something that looks like the following: <hex4>: The length of the payload, as 4 hexadecimal chars. <payload>: A series of lines of the following format: <serial> " " <local> " " <remote> "\n" Where <serial> is a device serial number. <local> is the host-specific endpoint (e.g. tcp:9000). <remote> is the device-specific endpoint. Used to implement 'adb forward --list'. LOCAL SERVICES: Loading
adb/adb.c +149 −28 Original line number Diff line number Diff line Loading @@ -722,24 +722,90 @@ int local_name_to_fd(const char *name) return -1; } static int remove_listener(const char *local_name, const char *connect_to, atransport* transport) // 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. static int format_listeners(char* buf, size_t buflen) { alistener* l; int result = 0; for (l = listener_list.next; l != &listener_list; l = l->next) { if (!strcmp(local_name, l->local_name) && !strcmp(connect_to, l->connect_to) && l->transport && l->transport == transport) { // 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; } } return result; } listener_disconnect(l, transport); static int remove_listener(const char *local_name, atransport* transport) { alistener *l; for (l = listener_list.next; l != &listener_list; l = l->next) { if (!strcmp(local_name, l->local_name)) { listener_disconnect(l, l->transport); return 0; } } return -1; } static int install_listener(const char *local_name, const char *connect_to, atransport* transport) static void remove_all_listeners(void) { alistener *l, *l_next; for (l = listener_list.next; l != &listener_list; l = l_next) { l_next = l->next; // Never remove smart sockets. if (l->connect_to[0] == '*') continue; listener_disconnect(l, l->transport); } } // error/status codes for install_listener. typedef enum { INSTALL_STATUS_OK = 0, INSTALL_STATUS_INTERNAL_ERROR = -1, INSTALL_STATUS_CANNOT_BIND = -2, INSTALL_STATUS_CANNOT_REBIND = -3, } install_status_t; static install_status_t install_listener(const char *local_name, const char *connect_to, atransport* transport, int no_rebind) { alistener *l; Loading @@ -751,12 +817,17 @@ static int install_listener(const char *local_name, const char *connect_to, atra /* can't repurpose a smartsocket */ if(l->connect_to[0] == '*') { return -1; return INSTALL_STATUS_INTERNAL_ERROR; } /* can't repurpose a listener if 'no_rebind' is true */ if (no_rebind) { return INSTALL_STATUS_CANNOT_REBIND; } cto = strdup(connect_to); if(cto == 0) { return -1; return INSTALL_STATUS_INTERNAL_ERROR; } //printf("rebinding '%s' to '%s'\n", local_name, connect_to); Loading @@ -767,7 +838,7 @@ static int install_listener(const char *local_name, const char *connect_to, atra l->transport = transport; add_transport_disconnect(l->transport, &l->disconnect); } return 0; return INSTALL_STATUS_OK; } } Loading Loading @@ -804,11 +875,11 @@ static int install_listener(const char *local_name, const char *connect_to, atra l->disconnect.func = listener_disconnect; add_transport_disconnect(transport, &l->disconnect); } return 0; return INSTALL_STATUS_OK; nomem: fatal("cannot allocate listener"); return 0; return INSTALL_STATUS_INTERNAL_ERROR; } #ifdef HAVE_WIN32_PROC Loading Loading @@ -1113,7 +1184,7 @@ int adb_main(int is_daemon, int server_port) char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL)) { if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } #else Loading Loading @@ -1180,7 +1251,7 @@ int adb_main(int is_daemon, int server_port) } else { char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL)) { if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } } Loading Loading @@ -1474,15 +1545,47 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } #endif // ADB_HOST if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) { if(!strcmp(service,"list-forward")) { // Create the list of forward redirections. char header[9]; 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); snprintf(header, sizeof header, "OKAY%04x", buffer_size); writex(reply_fd, header, 8); writex(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; } local = service + (createForward ? 8 : 12); remote = strchr(local,';'); if (createForward) { // Check forward: parameter format: '<local>;<remote>' if(remote == 0) { sendfailmsg(reply_fd, "malformed forward spec"); return 0; Loading @@ -1493,6 +1596,13 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r 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) { Loading @@ -1501,9 +1611,9 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if (createForward) { r = install_listener(local, remote, transport); r = install_listener(local, remote, transport, no_rebind); } else { r = remove_listener(local, remote, transport); r = remove_listener(local, transport); } if(r == 0) { /* 1st OKAY is connect, 2nd OKAY is status */ Loading @@ -1512,7 +1622,18 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if (createForward) { sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket"); 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"); } Loading
adb/commandline.c +82 −5 Original line number Diff line number Diff line Loading @@ -112,6 +112,9 @@ void help() " adb shell <command> - run remote shell command\n" " adb emu <command> - run emulator console command\n" " adb logcat [ <filter-spec> ] - View device log\n" " adb forward --list - list all forward socket connections.\n" " the format is a list of lines with the following format:\n" " <serial> \" \" <local> \" \" <remote> \"\\n\"\n" " adb forward <local> <remote> - forward socket connections\n" " forward specs are one of: \n" " tcp:<port>\n" Loading @@ -120,6 +123,11 @@ void help() " localfilesystem:<unix domain socket name>\n" " dev:<character device name>\n" " jdwp:<process pid> (remote only)\n" " adb forward --no-rebind <local> <remote>\n" " - same as 'adb forward <local> <remote>' but fails\n" " 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 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 @@ -1223,16 +1231,85 @@ top: } if(!strcmp(argv[0], "forward")) { if(argc != 3) return usage(); char host_prefix[64]; char remove = 0; char remove_all = 0; char list = 0; char no_rebind = 0; // Parse options here. while (argc > 1 && argv[1][0] == '-') { if (!strcmp(argv[1], "--list")) list = 1; else if (!strcmp(argv[1], "--remove")) remove = 1; else if (!strcmp(argv[1], "--remove-all")) remove_all = 1; else if (!strcmp(argv[1], "--no-rebind")) no_rebind = 1; else { return usage(); } argc--; argv++; } // Ensure we can only use one option at a time. if (list + remove + remove_all + no_rebind > 1) { return usage(); } // Determine the <host-prefix> for this command. if (serial) { snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", serial); } else if (ttype == kTransportUsb) { snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host-usb"); } else if (ttype == kTransportLocal) { snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host-local"); } else { snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]); snprintf(host_prefix, sizeof host_prefix, "host"); } // Implement forward --list if (list) { if (argc != 1) return usage(); snprintf(buf, sizeof buf, "%s:list-forward", host_prefix); char* forwards = adb_query(buf); if (forwards == NULL) { fprintf(stderr, "error: %s\n", adb_error()); return 1; } printf("%s", forwards); free(forwards); return 0; } // Implement forward --remove-all else if (remove_all) { if (argc != 1) return usage(); snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix); } // Implement forward --remove <local> else if (remove) { if (argc != 2) return usage(); snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]); } // Or implement one of: // forward <local> <remote> // forward --no-rebind <local> <remote> else { if (argc != 3) return usage(); const char* command = no_rebind ? "forward:norebind:" : "forward"; snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]); } if(adb_command(buf)) { fprintf(stderr,"error: %s\n", adb_error()); return 1; Loading