diff options
| -rw-r--r-- | adb/adb.c | 114 | ||||
| -rw-r--r-- | adb/adb.h | 2 | ||||
| -rw-r--r-- | adb/services.c | 123 | ||||
| -rw-r--r-- | adb/transport.c | 53 | 
4 files changed, 170 insertions, 122 deletions
| @@ -1387,105 +1387,6 @@ 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 hostbuf[100]; -    char serial[100]; - -    strncpy(hostbuf, host, sizeof(hostbuf) - 1); -    if (portstr) { -        if (portstr - host >= (ptrdiff_t)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; -    } - -    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port); -    if (find_transport(serial)) { -        snprintf(buffer, buffer_size, "already connected to %s", serial); -        return; -    } - -    fd = socket_network_client(hostbuf, 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); -    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) -{ -    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; @@ -1546,21 +1447,6 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r          }      } -    // add a new TCP transport, device or emulator -    if (!strncmp(service, "connect:", 8)) { -        char buffer[4096]; -        char* host = service + 8; -        if (!strncmp(host, "emu:", 4)) { -            connect_emulator(host + 4, buffer, sizeof(buffer)); -        } else { -            connect_device(host, buffer, sizeof(buffer)); -        } -        // 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; -    } -      // remove TCP transport      if (!strncmp(service, "disconnect:", 11)) {          char buffer[4096]; @@ -289,7 +289,7 @@ void init_usb_transport(atransport *t, usb_handle *usb, int state);  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); +int register_socket_transport(int s, const char *serial, int port, int local);  /* these should only be used for the "adb disconnect" command */  void unregister_transport(atransport *t); diff --git a/adb/services.c b/adb/services.c index 619199f..d2d428a 100644 --- a/adb/services.c +++ b/adb/services.c @@ -14,6 +14,7 @@   * limitations under the License.   */ +#include <stddef.h>  #include <stdlib.h>  #include <stdio.h>  #include <unistd.h> @@ -429,6 +430,124 @@ static void wait_for_state(int fd, void* cookie)      adb_close(fd);      D("wait_for_state is done\n");  } + +static void connect_device(char* host, char* buffer, int buffer_size) +{ +    int port, fd; +    char* portstr = strchr(host, ':'); +    char hostbuf[100]; +    char serial[100]; +    int ret; + +    strncpy(hostbuf, host, sizeof(hostbuf) - 1); +    if (portstr) { +        if (portstr - host >= (ptrdiff_t)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; +    } + +    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port); + +    fd = socket_network_client(hostbuf, 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); + +    ret = register_socket_transport(fd, serial, port, 0); +    if (ret < 0) { +        adb_close(fd); +        snprintf(buffer, buffer_size, "already connected to %s", serial); +    } else { +        snprintf(buffer, buffer_size, "connected to %s", serial); +    } +} + +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); +    } +} + +static void connect_service(int fd, void* cookie) +{ +    char buf[4096]; +    char resp[4096]; +    char *host = cookie; + +    if (!strncmp(host, "emu:", 4)) { +        connect_emulator(host + 4, buf, sizeof(buf)); +    } else { +        connect_device(host, buf, sizeof(buf)); +    } + +    // Send response for emulator and device +    snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf); +    writex(fd, resp, strlen(resp)); +    adb_close(fd); +}  #endif  #if ADB_HOST @@ -462,6 +581,10 @@ asocket*  host_service_to_socket(const char*  name, const char *serial)          int fd = create_service_thread(wait_for_state, sinfo);          return create_local_socket(fd); +    } else if (!strncmp(name, "connect:", 8)) { +        const char *host = name + 8; +        int fd = create_service_thread(connect_service, (void *)host); +        return create_local_socket(fd);      }      return NULL;  } diff --git a/adb/transport.c b/adb/transport.c index b4abb66..224fe55 100644 --- a/adb/transport.c +++ b/adb/transport.c @@ -32,6 +32,11 @@ static atransport transport_list = {      .prev = &transport_list,  }; +static atransport pending_list = { +    .next = &pending_list, +    .prev = &pending_list, +}; +  ADB_MUTEX_DEFINE( transport_lock );  #if ADB_TRACE @@ -645,8 +650,11 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)          }      } -        /* put us on the master device list */      adb_mutex_lock(&transport_lock); +    /* remove from pending list */ +    t->next->prev = t->prev; +    t->prev->next = t->next; +    /* put us on the master device list */      t->next = &transport_list;      t->prev = transport_list.prev;      t->next->prev = t; @@ -989,9 +997,10 @@ void close_usb_devices()  }  #endif // ADB_HOST -void register_socket_transport(int s, const char *serial, int port, int local) +int register_socket_transport(int s, const char *serial, int port, int local)  {      atransport *t = calloc(1, sizeof(atransport)); +    atransport *n;      char buff[32];      if (!serial) { @@ -999,15 +1008,37 @@ void register_socket_transport(int s, const char *serial, int port, int local)          serial = buff;      }      D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port); -    if ( init_socket_transport(t, s, port, local) < 0 ) { -        adb_close(s); +    if (init_socket_transport(t, s, port, local) < 0) {          free(t); -        return; +        return -1;      } -    if(serial) { -        t->serial = strdup(serial); + +    adb_mutex_lock(&transport_lock); +    for (n = pending_list.next; n != &pending_list; n = n->next) { +        if (n->serial && !strcmp(serial, n->serial)) { +            adb_mutex_unlock(&transport_lock); +            free(t); +            return -1; +        } +    } + +    for (n = transport_list.next; n != &transport_list; n = n->next) { +        if (n->serial && !strcmp(serial, n->serial)) { +            adb_mutex_unlock(&transport_lock); +            free(t); +            return -1; +        }      } + +    t->next = &pending_list; +    t->prev = pending_list.prev; +    t->next->prev = t; +    t->prev->next = t; +    t->serial = strdup(serial); +    adb_mutex_unlock(&transport_lock); +      register_transport(t); +    return 0;  }  #if ADB_HOST @@ -1077,6 +1108,14 @@ void register_usb_transport(usb_handle *usb, const char *serial, const char *dev      if(devpath) {          t->devpath = strdup(devpath);      } + +    adb_mutex_lock(&transport_lock); +    t->next = &pending_list; +    t->prev = pending_list.prev; +    t->next->prev = t; +    t->prev->next = t; +    adb_mutex_unlock(&transport_lock); +      register_transport(t);  } | 
