12ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell/*
22ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * Copyright (C) 2016 The Android Open Source Project
32ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * All rights reserved.
42ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *
52ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * Redistribution and use in source and binary forms, with or without
62ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * modification, are permitted provided that the following conditions
72ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * are met:
82ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *  * Redistributions of source code must retain the above copyright
92ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *    notice, this list of conditions and the following disclaimer.
102ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *  * Redistributions in binary form must reproduce the above copyright
112ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *    notice, this list of conditions and the following disclaimer in
122ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *    the documentation and/or other materials provided with the
132ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *    distribution.
142ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell *
152ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
182ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
192ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
202ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
212ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
222ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
232ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
242ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
252ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell * SUCH DAMAGE.
272ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell */
282ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
292ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell#include "tcp.h"
302ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
31aad72a533f97e8be5114e127fb681ee1596bdc89David Pursell#include <android-base/parseint.h>
322ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell#include <android-base/stringprintf.h>
332ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
342ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellnamespace tcp {
352ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
362ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic constexpr int kProtocolVersion = 1;
372ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic constexpr size_t kHandshakeLength = 4;
382ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic constexpr int kHandshakeTimeoutMs = 2000;
392ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
402ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// Extract the big-endian 8-byte message length into a 64-bit number.
412ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic uint64_t ExtractMessageLength(const void* buffer) {
422ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    uint64_t ret = 0;
432ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    for (int i = 0; i < 8; ++i) {
442ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        ret |= uint64_t{reinterpret_cast<const uint8_t*>(buffer)[i]} << (56 - i * 8);
452ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
462ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return ret;
472ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
482ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
492ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// Encode the 64-bit number into a big-endian 8-byte message length.
502ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic void EncodeMessageLength(uint64_t length, void* buffer) {
512ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    for (int i = 0; i < 8; ++i) {
522ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        reinterpret_cast<uint8_t*>(buffer)[i] = length >> (56 - i * 8);
532ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
542ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
552ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
562ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellclass TcpTransport : public Transport {
572ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell  public:
582ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    // Factory function so we can return nullptr if initialization fails.
592ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    static std::unique_ptr<TcpTransport> NewTransport(std::unique_ptr<Socket> socket,
602ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                                                      std::string* error);
612ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
622ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    ~TcpTransport() override = default;
632ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
642ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    ssize_t Read(void* data, size_t length) override;
652ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    ssize_t Write(const void* data, size_t length) override;
662ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    int Close() override;
672ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
682ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell  private:
691c563d96f000876d77b2d33fbfb03c241bc503e1Chih-Hung Hsieh    explicit TcpTransport(std::unique_ptr<Socket> sock) : socket_(std::move(sock)) {}
702ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
712ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    // Connects to the device and performs the initial handshake. Returns false and fills |error|
722ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    // on failure.
732ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    bool InitializeProtocol(std::string* error);
742ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
752ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    std::unique_ptr<Socket> socket_;
762ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    uint64_t message_bytes_left_ = 0;
772ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
782ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    DISALLOW_COPY_AND_ASSIGN(TcpTransport);
792ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell};
802ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
812ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstd::unique_ptr<TcpTransport> TcpTransport::NewTransport(std::unique_ptr<Socket> socket,
822ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                                                         std::string* error) {
832ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    std::unique_ptr<TcpTransport> transport(new TcpTransport(std::move(socket)));
842ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
852ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (!transport->InitializeProtocol(error)) {
862ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return nullptr;
872ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
882ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
892ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return transport;
902ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
912ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
922ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// These error strings are checked in tcp_test.cpp and should be kept in sync.
932ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellbool TcpTransport::InitializeProtocol(std::string* error) {
942ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    std::string handshake_message(android::base::StringPrintf("FB%02d", kProtocolVersion));
952ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
962ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (!socket_->Send(handshake_message.c_str(), kHandshakeLength)) {
972ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        *error = android::base::StringPrintf("Failed to send initialization message (%s)",
982ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                                             Socket::GetErrorMessage().c_str());
992ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return false;
1002ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1012ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
102aad72a533f97e8be5114e127fb681ee1596bdc89David Pursell    char buffer[kHandshakeLength + 1];
103aad72a533f97e8be5114e127fb681ee1596bdc89David Pursell    buffer[kHandshakeLength] = '\0';
1042ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (socket_->ReceiveAll(buffer, kHandshakeLength, kHandshakeTimeoutMs) != kHandshakeLength) {
1052ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        *error = android::base::StringPrintf(
1062ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                "No initialization message received (%s). Target may not support TCP fastboot",
1072ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                Socket::GetErrorMessage().c_str());
1082ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return false;
1092ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1102ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1112ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (memcmp(buffer, "FB", 2) != 0) {
1122ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        *error = "Unrecognized initialization message. Target may not support TCP fastboot";
1132ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return false;
1142ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1152ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
116aad72a533f97e8be5114e127fb681ee1596bdc89David Pursell    int version = 0;
117aad72a533f97e8be5114e127fb681ee1596bdc89David Pursell    if (!android::base::ParseInt(buffer + 2, &version) || version < kProtocolVersion) {
1182ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        *error = android::base::StringPrintf("Unknown TCP protocol version %s (host version %02d)",
119aad72a533f97e8be5114e127fb681ee1596bdc89David Pursell                                             buffer + 2, kProtocolVersion);
1202ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return false;
1212ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1222ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1232ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    error->clear();
1242ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return true;
1252ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
1262ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1272ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellssize_t TcpTransport::Read(void* data, size_t length) {
1282ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (socket_ == nullptr) {
1292ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return -1;
1302ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1312ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1322ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    // Unless we're mid-message, read the next 8-byte message length.
1332ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (message_bytes_left_ == 0) {
1342ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        char buffer[8];
1352ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        if (socket_->ReceiveAll(buffer, 8, 0) != 8) {
1362ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            Close();
1372ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            return -1;
1382ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
1392ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        message_bytes_left_ = ExtractMessageLength(buffer);
1402ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1412ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1422ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    // Now read the message (up to |length| bytes).
1432ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (length > message_bytes_left_) {
1442ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        length = message_bytes_left_;
1452ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1462ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    ssize_t bytes_read = socket_->ReceiveAll(data, length, 0);
1472ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (bytes_read == -1) {
1482ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        Close();
1492ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    } else {
1502ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        message_bytes_left_ -= bytes_read;
1512ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1522ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return bytes_read;
1532ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
1542ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1552ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellssize_t TcpTransport::Write(const void* data, size_t length) {
1562ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (socket_ == nullptr) {
1572ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return -1;
1582ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1592ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1602ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    // Use multi-buffer writes for better performance.
1612ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    char header[8];
1622ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    EncodeMessageLength(length, header);
1632ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (!socket_->Send(std::vector<cutils_socket_buffer_t>{{header, 8}, {data, length}})) {
1642ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        Close();
1652ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return -1;
1662ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1672ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1682ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return length;
1692ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
1702ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1712ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellint TcpTransport::Close() {
1722ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (socket_ == nullptr) {
1732ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return 0;
1742ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1752ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1762ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    int result = socket_->Close();
1772ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    socket_.reset();
1782ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return result;
1792ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
1802ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1812ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstd::unique_ptr<Transport> Connect(const std::string& hostname, int port, std::string* error) {
1822ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return internal::Connect(Socket::NewClient(Socket::Protocol::kTcp, hostname, port, error),
1832ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                             error);
1842ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
1852ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1862ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellnamespace internal {
1872ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1882ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstd::unique_ptr<Transport> Connect(std::unique_ptr<Socket> sock, std::string* error) {
1892ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (sock == nullptr) {
1902ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        // If Socket creation failed |error| is already set.
1912ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return nullptr;
1922ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
1932ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1942ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    return TcpTransport::NewTransport(std::move(sock), error);
1952ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}
1962ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1972ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}  // namespace internal
1982ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1992ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell}  // namespace tcp
200