15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/common/adb_connection.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <arpa/inet.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/common/net.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tools {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloseSocket(int fd) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fd >= 0) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int old_errno = errno;
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    close(fd);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errno = old_errno;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ConnectAdbHostSocket(const char* forward_to) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ADB port forward request format: HHHHtcp:port:address.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HHHH is the hexidecimal length of the "tcp:port:address" part.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kBufferMaxLength = 30;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kLengthOfLength = 4;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kAddressMaxLength = kBufferMaxLength - kLengthOfLength;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kAddressPrefix[] = { 't', 'c', 'p', ':' };
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t address_length = arraysize(kAddressPrefix) + strlen(forward_to);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address_length > kBufferMaxLength - kLengthOfLength) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Forward to address is too long: " << forward_to;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char request[kBufferMaxLength];
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(request + kLengthOfLength, kAddressPrefix, arraysize(kAddressPrefix));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(request + kLengthOfLength + arraysize(kAddressPrefix),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         forward_to, strlen(forward_to));
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char length_buffer[kLengthOfLength + 1];
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snprintf(length_buffer, arraysize(length_buffer), "%04X",
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           static_cast<int>(address_length));
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(request, length_buffer, kLengthOfLength);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int host_socket = socket(AF_INET, SOCK_STREAM, 0);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_socket < 0) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create adb socket: " << strerror(errno);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DisableNagle(host_socket);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kAdbPort = 5037;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sockaddr_in addr;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&addr, 0, sizeof(addr));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.sin_family = AF_INET;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.sin_port = htons(kAdbPort);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HANDLE_EINTR(connect(host_socket, reinterpret_cast<sockaddr*>(&addr),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sizeof(addr))) < 0) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to connect adb socket: " << strerror(errno);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSocket(host_socket);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_remaining = address_length + kLengthOfLength;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_sent = 0;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (bytes_remaining > 0) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = HANDLE_EINTR(send(host_socket, request + bytes_sent,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bytes_remaining, 0));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret < 0) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to send request: " << strerror(errno);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseSocket(host_socket);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_sent += ret;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_remaining -= ret;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kAdbStatusLength = 4;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char response[kBufferMaxLength];
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_length = HANDLE_EINTR(recv(host_socket, response,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          kBufferMaxLength, 0));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_length < kAdbStatusLength ||
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strncmp("OKAY", response, kAdbStatusLength) != 0) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Bad response from ADB: length: " << response_length
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " data: " << DumpBinary(response, response_length);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSocket(host_socket);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return host_socket;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace tools
108