diff --git a/adb/adb.c b/adb/adb.c index dd40eefe9..95dc001d4 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -972,25 +972,32 @@ void connect_device(char* host, char* buffer, int buffer_size) { int port, fd; char* portstr = strchr(host, ':'); - char buf[4096]; + char hostbuf[100]; + char serial[100]; - if (!portstr) { - snprintf(buffer, buffer_size, "unable to parse %s as :", host); - return; + strncpy(hostbuf, host, sizeof(hostbuf) - 1); + if (portstr) { + if (portstr - host >= 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) == 0) { + snprintf(buffer, buffer_size, "bad port number %s", portstr); + return; + } + } else { + port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; } - if (find_transport(host)) { - snprintf(buffer, buffer_size, "already connected to %s", host); + + snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port); + if (find_transport(serial)) { + snprintf(buffer, buffer_size, "already connected to %s", serial); return; } - // zero terminate host by overwriting the ':' - *portstr++ = 0; - if (sscanf(portstr, "%d", &port) == 0) { - snprintf(buffer, buffer_size, "bad port number %s", portstr); - return; - } - - fd = socket_network_client(host, port, SOCK_STREAM); + fd = socket_network_client(hostbuf, port, SOCK_STREAM); if (fd < 0) { snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port); return; @@ -999,9 +1006,8 @@ void connect_device(char* host, char* buffer, int buffer_size) D("client: connected on remote on fd %d\n", fd); close_on_exec(fd); disable_tcp_nagle(fd); - snprintf(buf, sizeof buf, "%s:%d", host, port); - register_socket_transport(fd, buf, port, 0); - snprintf(buffer, buffer_size, "connected to %s:%d", host, port); + register_socket_transport(fd, serial, port, 0); + snprintf(buffer, buffer_size, "connected to %s", serial); } void connect_emulator(char* port_spec, char* buffer, int buffer_size) @@ -1137,12 +1143,23 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r char buffer[4096]; memset(buffer, 0, sizeof(buffer)); char* serial = service + 11; - atransport *t = find_transport(serial); - - if (t) { - unregister_transport(t); + if (serial[0] == 0) { + // disconnect from all TCP devices + unregister_all_tcp_transports(); } else { - snprintf(buffer, sizeof(buffer), "No such device %s", serial); + char hostbuf[100]; + // assume port 5555 if no port is specified + if (!strchr(serial, ':')) { + snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial); + serial = hostbuf; + } + atransport *t = find_transport(serial); + + if (t) { + unregister_transport(t); + } else { + snprintf(buffer, sizeof(buffer), "No such device %s", serial); + } } snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); diff --git a/adb/adb.h b/adb/adb.h index 292e41592..3d2a77bba 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -275,8 +275,9 @@ void close_usb_devices(); /* cause new transports to be init'd and added to the list */ void register_socket_transport(int s, const char *serial, int port, int local); -/* this should only be used for the "adb disconnect" command */ +/* these should only be used for the "adb disconnect" command */ void unregister_transport(atransport *t); +void unregister_all_tcp_transports(); void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable); diff --git a/adb/commandline.c b/adb/commandline.c index 4d7d357f4..dcba83b77 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -100,8 +100,12 @@ void help() " environment variable is used, which must\n" " be an absolute path.\n" " devices - list all connected devices\n" - " connect : - connect to a device via TCP/IP\n" - " disconnect : - disconnect from a TCP/IP device\n" + " connect [:] - connect to a device via TCP/IP\n" + " Port 5555 is used by default if no port number is specified.\n" + " disconnect [[:]] - disconnect from a TCP/IP device.\n" + " Port 5555 is used by default if no port number is specified.\n" + " Using this ocmmand with no additional arguments\n" + " will disconnect from all connected TCP/IP devices.\n" "\n" "device commands:\n" " adb push - copy file/dir to device\n" @@ -794,13 +798,33 @@ top: } } - if(!strcmp(argv[0], "connect") || !strcmp(argv[0], "disconnect")) { + if(!strcmp(argv[0], "connect")) { char *tmp; if (argc != 2) { - fprintf(stderr, "Usage: adb %s :\n", argv[0]); + fprintf(stderr, "Usage: adb connect [:]\n"); return 1; } - snprintf(buf, sizeof buf, "host:%s:%s", argv[0], argv[1]); + snprintf(buf, sizeof buf, "host:connect:%s", argv[1]); + tmp = adb_query(buf); + if(tmp) { + printf("%s\n", tmp); + return 0; + } else { + return 1; + } + } + + if(!strcmp(argv[0], "disconnect")) { + char *tmp; + if (argc > 2) { + fprintf(stderr, "Usage: adb disconnect [[:]]\n"); + return 1; + } + if (argc == 2) { + snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]); + } else { + snprintf(buf, sizeof buf, "host:disconnect:"); + } tmp = adb_query(buf); if(tmp) { printf("%s\n", tmp); diff --git a/adb/transport.c b/adb/transport.c index c2877d239..62bdfdb74 100644 --- a/adb/transport.c +++ b/adb/transport.c @@ -671,21 +671,26 @@ static void remove_transport(atransport *transport) } +static void transport_unref_locked(atransport *t) +{ + t->ref_count--; + D("transport: %p R- (ref=%d)\n", t, t->ref_count); + if (t->ref_count == 0) { + D("transport: %p kicking and closing\n", t); + if (!t->kicked) { + t->kicked = 1; + t->kick(t); + } + t->close(t); + remove_transport(t); + } +} + static void transport_unref(atransport *t) { if (t) { adb_mutex_lock(&transport_lock); - t->ref_count--; - D("transport: %p R- (ref=%d)\n", t, t->ref_count); - if (t->ref_count == 0) { - D("transport: %p kicking and closing\n", t); - if (!t->kicked) { - t->kicked = 1; - t->kick(t); - } - t->close(t); - remove_transport(t); - } + transport_unref_locked(t); adb_mutex_unlock(&transport_lock); } } @@ -894,6 +899,29 @@ void unregister_transport(atransport *t) transport_unref(t); } +// unregisters all non-emulator TCP transports +void unregister_all_tcp_transports() +{ + atransport *t, *next; + adb_mutex_lock(&transport_lock); + for (t = transport_list.next; t != &transport_list; t = next) { + next = t->next; + if (t->type == kTransportLocal && t->adb_port == 0) { + t->next->prev = t->prev; + t->prev->next = next; + // we cannot call kick_transport when holding transport_lock + if (!t->kicked) + { + t->kicked = 1; + t->kick(t); + } + transport_unref_locked(t); + } + } + + adb_mutex_unlock(&transport_lock); +} + #endif void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)