diff options
Diffstat (limited to 'libcutils/adb_networking.c')
-rw-r--r-- | libcutils/adb_networking.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/libcutils/adb_networking.c b/libcutils/adb_networking.c new file mode 100644 index 0000000..d819d44 --- /dev/null +++ b/libcutils/adb_networking.c @@ -0,0 +1,172 @@ +/* libs/utils/adb_networking.c +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define ADB_PORT 5037 + +#define _GNU_SOURCE /* for asprintf */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> + +#include <cutils/adb_networking.h> +#include <cutils/sockets.h> +#include <cutils/properties.h> + +#define ADB_RESPONSE_SIZE 4 + +/** + * Unfortunately, java.net.Socket wants to create it's filedescriptor early + * So, this function takes an fd that must be an unconnected + * PF_LOCAL SOCK_STREAM + */ +int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address) +{ + struct sockaddr_in local_addr; + socklen_t alen; + char *cmd; + char buf[ADB_RESPONSE_SIZE + 1]; + ssize_t count_read; + int ret; + int err; + /* for impl of inet_ntoa below*/ + union { + uint8_t b[4]; + uint32_t l; + } a; + + /* First, connect to adb */ + + memset(&local_addr, 0, sizeof(local_addr)); + local_addr.sin_family = AF_INET; + local_addr.sin_port = htons(ADB_PORT); + local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + do { + err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr)); + } while (err < 0 && errno == EINTR); + + if (err < 0) { + return -1; + } + + a.l = p_address->sin_addr.s_addr; + + // compose the command + asprintf(&cmd, "tcp:%u:%u.%u.%u.%u", + (unsigned int)ntohs(p_address->sin_port), + a.b[0],a.b[1],a.b[2],a.b[3]); + + // buf is now the ascii hex length of cmd + snprintf(buf, sizeof(buf), "%04X", strlen(cmd)); + + // write the 4-byte length + do { + err = write(fd, buf, 4); + } while (err < 0 && errno == EINTR); + + // write the command + do { + err = write(fd, cmd, strlen(cmd)); + } while (err < 0 && errno == EINTR); + + // read the result + do { + count_read = read(fd, buf, sizeof(buf) - 1); + } while (count_read < 0 && errno != EINTR); + + if (count_read == ADB_RESPONSE_SIZE + && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) { + ret = 0; + } else { + /* what errno here? <shrug? */ + errno = ENETUNREACH; + ret = -1; + } + + free(cmd); + + return ret; +} + +/** + * Fills in *p_out_addr and returns 0 on success + * Memset's *p_out_addr and returns -1 on fail + */ + +int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr) +{ + int fd; + char *cmd = NULL; + char buf[ADB_RESPONSE_SIZE + 1]; + int err; + ssize_t count_read; + + fd = socket_loopback_client(ADB_PORT, SOCK_STREAM); + + if (fd < 0) { + return -1; + } + + // compose the command + asprintf(&cmd, "dns:%s", name); + + // buf is now the ascii hex length of cmd + snprintf(buf, sizeof(buf), "%04X", strlen(cmd)); + + // write the 4-byte length + do { + err = write(fd, buf, 4); + } while (err < 0 && errno == EINTR); + + // write the command + do { + err = write(fd, cmd, strlen(cmd)); + } while (err < 0 && errno == EINTR); + + // read the result + do { + count_read = read(fd, buf, ADB_RESPONSE_SIZE); + } while (count_read < 0 && errno != EINTR); + + if (count_read != ADB_RESPONSE_SIZE + || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) { + goto error; + } + + // read the actual IP address + do { + count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr)); + } while (count_read < 0 && errno != EINTR); + + if (count_read != 4) { + goto error; + } + + free(cmd); + close(fd); + return 0; +error: + free(cmd); + close(fd); + memset(p_out_addr, 0, sizeof(struct in_addr)); + return -1; +} + |