Loading adb/adb.c +99 −33 Original line number Diff line number Diff line Loading @@ -967,6 +967,99 @@ int adb_main(int is_daemon, int server_port) return 0; } #if ADB_HOST void connect_device(char* host, char* buffer, int buffer_size) { int port, fd; char* portstr = strchr(host, ':'); char buf[4096]; if (!portstr) { snprintf(buffer, buffer_size, "unable to parse %s as <host>:<port>", host); return; } if (find_transport(host)) { snprintf(buffer, buffer_size, "already connected to %s", host); 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); if (fd < 0) { snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port); return; } 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); } void connect_emulator(char* port_spec, char* buffer, int buffer_size) { char* port_separator = strchr(port_spec, ','); if (!port_separator) { snprintf(buffer, buffer_size, "unable to parse '%s' as <console port>,<adb port>", port_spec); return; } // Zero-terminate console port and make port_separator point to 2nd port. *port_separator++ = 0; int console_port = strtol(port_spec, NULL, 0); int adb_port = strtol(port_separator, NULL, 0); if (!(console_port > 0 && adb_port > 0)) { *(port_separator - 1) = ','; snprintf(buffer, buffer_size, "Invalid port numbers: Expected positive numbers, got '%s'", port_spec); return; } /* Check if the emulator is already known. * Note: There's a small but harmless race condition here: An emulator not * present just yet could be registered by another invocation right * after doing this check here. However, local_connect protects * against double-registration too. From here, a better error message * can be produced. In the case of the race condition, the very specific * error message won't be shown, but the data doesn't get corrupted. */ atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port); if (known_emulator != NULL) { snprintf(buffer, buffer_size, "Emulator on port %d already registered.", adb_port); return; } /* Check if more emulators can be registered. Similar unproblematic * race condition as above. */ int candidate_slot = get_available_local_transport_index(); if (candidate_slot < 0) { snprintf(buffer, buffer_size, "Cannot accept more emulators."); return; } /* Preconditions met, try to connect to the emulator. */ if (!local_connect_arbitrary_ports(console_port, adb_port)) { snprintf(buffer, buffer_size, "Connected to emulator on ports %d,%d", console_port, adb_port); } else { snprintf(buffer, buffer_size, "Could not connect to emulator on ports %d,%d", console_port, adb_port); } } #endif int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s) { atransport *transport = NULL; Loading Loading @@ -1024,43 +1117,16 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r return 0; } // add a new TCP transport // add a new TCP transport, device or emulator if (!strncmp(service, "connect:", 8)) { char buffer[4096]; int port, fd; char* host = service + 8; char* portstr = strchr(host, ':'); if (!portstr) { snprintf(buffer, sizeof(buffer), "unable to parse %s as <host>:<port>", host); goto done; } if (find_transport(host)) { snprintf(buffer, sizeof(buffer), "Already connected to %s", host); goto done; } // zero terminate host by overwriting the ':' *portstr++ = 0; if (sscanf(portstr, "%d", &port) == 0) { snprintf(buffer, sizeof(buffer), "bad port number %s", portstr); goto done; } fd = socket_network_client(host, port, SOCK_STREAM); if (fd < 0) { snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d", host, port); goto done; if (!strncmp(host, "emu:", 4)) { connect_emulator(host + 4, buffer, sizeof(buffer)); } else { connect_device(host, buffer, sizeof(buffer)); } 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, sizeof(buffer), "connected to %s:%d", host, port); done: // Send response for emulator and device snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); writex(reply_fd, buf, strlen(buf)); return 0; Loading adb/adb.h +8 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ struct atransport /* used to identify transports for clients */ char *serial; char *product; int adb_port; // Use for emulators (local transport) /* a list of adisconnect callbacks called when the transport is kicked */ int kicked; Loading Loading @@ -262,6 +263,9 @@ void run_transport_disconnects( atransport* t ); void kick_transport( atransport* t ); /* initialize a transport object's func pointers and state */ #if ADB_HOST int get_available_local_transport_index(); #endif int init_socket_transport(atransport *t, int s, int port, int local); void init_usb_transport(atransport *t, usb_handle *usb, int state); Loading @@ -280,6 +284,9 @@ void register_usb_transport(usb_handle *h, const char *serial, unsigned writeabl void unregister_usb_transport(usb_handle *usb); atransport *find_transport(const char *serial); #if ADB_HOST atransport* find_emulator_transport_by_adb_port(int adb_port); #endif int service_to_fd(const char *name); #if ADB_HOST Loading Loading @@ -368,6 +375,7 @@ typedef enum { void local_init(int port); int local_connect(int port); int local_connect_arbitrary_ports(int console_port, int adb_port); /* usb host/client interface */ void usb_init(); Loading adb/transport_local.c +72 −21 Original line number Diff line number Diff line Loading @@ -41,9 +41,9 @@ static inline void fix_endians(apacket *p) #endif #if ADB_HOST /* we keep a list of opened transports, transport 0 is bound to 5555, * transport 1 to 5557, .. transport n to 5555 + n*2. the list is used * to detect when we're trying to connect twice to a given local transport /* we keep a list of opened transports. The atransport struct knows to which * local transport it is connected. The list is used to detect when we're * trying to connect twice to a given local transport. */ #define ADB_LOCAL_TRANSPORT_MAX 16 Loading Loading @@ -102,7 +102,11 @@ static int remote_write(apacket *p, atransport *t) } int local_connect(int port) int local_connect(int port) { return local_connect_arbitrary_ports(port-1, port); } int local_connect_arbitrary_ports(int console_port, int adb_port) { char buf[64]; int fd = -1; Loading @@ -110,19 +114,19 @@ int local_connect(int port) #if ADB_HOST const char *host = getenv("ADBHOST"); if (host) { fd = socket_network_client(host, port, SOCK_STREAM); fd = socket_network_client(host, adb_port, SOCK_STREAM); } #endif if (fd < 0) { fd = socket_loopback_client(port, SOCK_STREAM); fd = socket_loopback_client(adb_port, SOCK_STREAM); } if (fd >= 0) { D("client: connected on remote on fd %d\n", fd); close_on_exec(fd); disable_tcp_nagle(fd); snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, port - 1); register_socket_transport(fd, buf, port, 1); snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port); register_socket_transport(fd, buf, adb_port, 1); return 0; } return -1; Loading Loading @@ -227,7 +231,50 @@ static void remote_close(atransport *t) adb_close(t->fd); } int init_socket_transport(atransport *t, int s, int port, int local) #if ADB_HOST /* Only call this function if you already hold local_transports_lock. */ atransport* find_emulator_transport_by_adb_port_locked(int adb_port) { int i; for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { if (local_transports[i] && local_transports[i]->adb_port == adb_port) { return local_transports[i]; } } return NULL; } atransport* find_emulator_transport_by_adb_port(int adb_port) { adb_mutex_lock( &local_transports_lock ); atransport* result = find_emulator_transport_by_adb_port_locked(adb_port); adb_mutex_unlock( &local_transports_lock ); return result; } /* Only call this function if you already hold local_transports_lock. */ int get_available_local_transport_index_locked() { int i; for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { if (local_transports[i] == NULL) { return i; } } return -1; } int get_available_local_transport_index() { adb_mutex_lock( &local_transports_lock ); int result = get_available_local_transport_index_locked(); adb_mutex_unlock( &local_transports_lock ); return result; } #endif int init_socket_transport(atransport *t, int s, int adb_port, int local) { int fail = 0; Loading @@ -239,25 +286,29 @@ int init_socket_transport(atransport *t, int s, int port, int local) t->sync_token = 1; t->connection_state = CS_OFFLINE; t->type = kTransportLocal; t->adb_port = 0; #if ADB_HOST if (HOST && local) { adb_mutex_lock( &local_transports_lock ); { int index = (port - DEFAULT_ADB_LOCAL_TRANSPORT_PORT)/2; if (!(port & 1) || index < 0 || index >= ADB_LOCAL_TRANSPORT_MAX) { D("bad local transport port number: %d\n", port); fail = -1; } else if (local_transports[index] != NULL) { t->adb_port = adb_port; atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port); int index = get_available_local_transport_index_locked(); if (existing_transport != NULL) { D("local transport for port %d already registered (%p)?\n", port, local_transports[index]); adb_port, existing_transport); fail = -1; } else } else if (index < 0) { // Too many emulators. D("cannot register more emulators. Maximum is %d\n", ADB_LOCAL_TRANSPORT_MAX); fail = -1; } else { local_transports[index] = t; } } adb_mutex_unlock( &local_transports_lock ); } #endif Loading Loading
adb/adb.c +99 −33 Original line number Diff line number Diff line Loading @@ -967,6 +967,99 @@ int adb_main(int is_daemon, int server_port) return 0; } #if ADB_HOST void connect_device(char* host, char* buffer, int buffer_size) { int port, fd; char* portstr = strchr(host, ':'); char buf[4096]; if (!portstr) { snprintf(buffer, buffer_size, "unable to parse %s as <host>:<port>", host); return; } if (find_transport(host)) { snprintf(buffer, buffer_size, "already connected to %s", host); 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); if (fd < 0) { snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port); return; } 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); } void connect_emulator(char* port_spec, char* buffer, int buffer_size) { char* port_separator = strchr(port_spec, ','); if (!port_separator) { snprintf(buffer, buffer_size, "unable to parse '%s' as <console port>,<adb port>", port_spec); return; } // Zero-terminate console port and make port_separator point to 2nd port. *port_separator++ = 0; int console_port = strtol(port_spec, NULL, 0); int adb_port = strtol(port_separator, NULL, 0); if (!(console_port > 0 && adb_port > 0)) { *(port_separator - 1) = ','; snprintf(buffer, buffer_size, "Invalid port numbers: Expected positive numbers, got '%s'", port_spec); return; } /* Check if the emulator is already known. * Note: There's a small but harmless race condition here: An emulator not * present just yet could be registered by another invocation right * after doing this check here. However, local_connect protects * against double-registration too. From here, a better error message * can be produced. In the case of the race condition, the very specific * error message won't be shown, but the data doesn't get corrupted. */ atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port); if (known_emulator != NULL) { snprintf(buffer, buffer_size, "Emulator on port %d already registered.", adb_port); return; } /* Check if more emulators can be registered. Similar unproblematic * race condition as above. */ int candidate_slot = get_available_local_transport_index(); if (candidate_slot < 0) { snprintf(buffer, buffer_size, "Cannot accept more emulators."); return; } /* Preconditions met, try to connect to the emulator. */ if (!local_connect_arbitrary_ports(console_port, adb_port)) { snprintf(buffer, buffer_size, "Connected to emulator on ports %d,%d", console_port, adb_port); } else { snprintf(buffer, buffer_size, "Could not connect to emulator on ports %d,%d", console_port, adb_port); } } #endif int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s) { atransport *transport = NULL; Loading Loading @@ -1024,43 +1117,16 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r return 0; } // add a new TCP transport // add a new TCP transport, device or emulator if (!strncmp(service, "connect:", 8)) { char buffer[4096]; int port, fd; char* host = service + 8; char* portstr = strchr(host, ':'); if (!portstr) { snprintf(buffer, sizeof(buffer), "unable to parse %s as <host>:<port>", host); goto done; } if (find_transport(host)) { snprintf(buffer, sizeof(buffer), "Already connected to %s", host); goto done; } // zero terminate host by overwriting the ':' *portstr++ = 0; if (sscanf(portstr, "%d", &port) == 0) { snprintf(buffer, sizeof(buffer), "bad port number %s", portstr); goto done; } fd = socket_network_client(host, port, SOCK_STREAM); if (fd < 0) { snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d", host, port); goto done; if (!strncmp(host, "emu:", 4)) { connect_emulator(host + 4, buffer, sizeof(buffer)); } else { connect_device(host, buffer, sizeof(buffer)); } 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, sizeof(buffer), "connected to %s:%d", host, port); done: // Send response for emulator and device snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); writex(reply_fd, buf, strlen(buf)); return 0; Loading
adb/adb.h +8 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ struct atransport /* used to identify transports for clients */ char *serial; char *product; int adb_port; // Use for emulators (local transport) /* a list of adisconnect callbacks called when the transport is kicked */ int kicked; Loading Loading @@ -262,6 +263,9 @@ void run_transport_disconnects( atransport* t ); void kick_transport( atransport* t ); /* initialize a transport object's func pointers and state */ #if ADB_HOST int get_available_local_transport_index(); #endif int init_socket_transport(atransport *t, int s, int port, int local); void init_usb_transport(atransport *t, usb_handle *usb, int state); Loading @@ -280,6 +284,9 @@ void register_usb_transport(usb_handle *h, const char *serial, unsigned writeabl void unregister_usb_transport(usb_handle *usb); atransport *find_transport(const char *serial); #if ADB_HOST atransport* find_emulator_transport_by_adb_port(int adb_port); #endif int service_to_fd(const char *name); #if ADB_HOST Loading Loading @@ -368,6 +375,7 @@ typedef enum { void local_init(int port); int local_connect(int port); int local_connect_arbitrary_ports(int console_port, int adb_port); /* usb host/client interface */ void usb_init(); Loading
adb/transport_local.c +72 −21 Original line number Diff line number Diff line Loading @@ -41,9 +41,9 @@ static inline void fix_endians(apacket *p) #endif #if ADB_HOST /* we keep a list of opened transports, transport 0 is bound to 5555, * transport 1 to 5557, .. transport n to 5555 + n*2. the list is used * to detect when we're trying to connect twice to a given local transport /* we keep a list of opened transports. The atransport struct knows to which * local transport it is connected. The list is used to detect when we're * trying to connect twice to a given local transport. */ #define ADB_LOCAL_TRANSPORT_MAX 16 Loading Loading @@ -102,7 +102,11 @@ static int remote_write(apacket *p, atransport *t) } int local_connect(int port) int local_connect(int port) { return local_connect_arbitrary_ports(port-1, port); } int local_connect_arbitrary_ports(int console_port, int adb_port) { char buf[64]; int fd = -1; Loading @@ -110,19 +114,19 @@ int local_connect(int port) #if ADB_HOST const char *host = getenv("ADBHOST"); if (host) { fd = socket_network_client(host, port, SOCK_STREAM); fd = socket_network_client(host, adb_port, SOCK_STREAM); } #endif if (fd < 0) { fd = socket_loopback_client(port, SOCK_STREAM); fd = socket_loopback_client(adb_port, SOCK_STREAM); } if (fd >= 0) { D("client: connected on remote on fd %d\n", fd); close_on_exec(fd); disable_tcp_nagle(fd); snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, port - 1); register_socket_transport(fd, buf, port, 1); snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port); register_socket_transport(fd, buf, adb_port, 1); return 0; } return -1; Loading Loading @@ -227,7 +231,50 @@ static void remote_close(atransport *t) adb_close(t->fd); } int init_socket_transport(atransport *t, int s, int port, int local) #if ADB_HOST /* Only call this function if you already hold local_transports_lock. */ atransport* find_emulator_transport_by_adb_port_locked(int adb_port) { int i; for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { if (local_transports[i] && local_transports[i]->adb_port == adb_port) { return local_transports[i]; } } return NULL; } atransport* find_emulator_transport_by_adb_port(int adb_port) { adb_mutex_lock( &local_transports_lock ); atransport* result = find_emulator_transport_by_adb_port_locked(adb_port); adb_mutex_unlock( &local_transports_lock ); return result; } /* Only call this function if you already hold local_transports_lock. */ int get_available_local_transport_index_locked() { int i; for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { if (local_transports[i] == NULL) { return i; } } return -1; } int get_available_local_transport_index() { adb_mutex_lock( &local_transports_lock ); int result = get_available_local_transport_index_locked(); adb_mutex_unlock( &local_transports_lock ); return result; } #endif int init_socket_transport(atransport *t, int s, int adb_port, int local) { int fail = 0; Loading @@ -239,25 +286,29 @@ int init_socket_transport(atransport *t, int s, int port, int local) t->sync_token = 1; t->connection_state = CS_OFFLINE; t->type = kTransportLocal; t->adb_port = 0; #if ADB_HOST if (HOST && local) { adb_mutex_lock( &local_transports_lock ); { int index = (port - DEFAULT_ADB_LOCAL_TRANSPORT_PORT)/2; if (!(port & 1) || index < 0 || index >= ADB_LOCAL_TRANSPORT_MAX) { D("bad local transport port number: %d\n", port); fail = -1; } else if (local_transports[index] != NULL) { t->adb_port = adb_port; atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port); int index = get_available_local_transport_index_locked(); if (existing_transport != NULL) { D("local transport for port %d already registered (%p)?\n", port, local_transports[index]); adb_port, existing_transport); fail = -1; } else } else if (index < 0) { // Too many emulators. D("cannot register more emulators. Maximum is %d\n", ADB_LOCAL_TRANSPORT_MAX); fail = -1; } else { local_transports[index] = t; } } adb_mutex_unlock( &local_transports_lock ); } #endif Loading