15a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell/*
25a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * Copyright (C) 2015 The Android Open Source Project
35a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * All rights reserved.
45a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *
55a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * Redistribution and use in source and binary forms, with or without
65a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * modification, are permitted provided that the following conditions
75a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * are met:
85a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *  * Redistributions of source code must retain the above copyright
95a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *    notice, this list of conditions and the following disclaimer.
105a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *  * Redistributions in binary form must reproduce the above copyright
115a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *    notice, this list of conditions and the following disclaimer in
125a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *    the documentation and/or other materials provided with the
135a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *    distribution.
145a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell *
155a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
165a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
175a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
185a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
195a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
205a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
215a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
225a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
235a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
245a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
255a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell * SUCH DAMAGE.
275a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell */
285a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
295a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell// This file implements the fastboot UDP protocol; see fastboot_protocol.txt for documentation.
305a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
315a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include "udp.h"
325a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
335a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <errno.h>
345a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <stdio.h>
355a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
365a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <list>
375a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <memory>
385a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <vector>
395a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
405a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <android-base/macros.h>
415a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include <android-base/stringprintf.h>
425a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
435a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include "socket.h"
445a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
455a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellnamespace udp {
465a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
475a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellusing namespace internal;
485a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
495a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellconstexpr size_t kMinPacketSize = 512;
505a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellconstexpr size_t kHeaderSize = 4;
515a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
525a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellenum Index {
535a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    kIndexId = 0,
545a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    kIndexFlags = 1,
555a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    kIndexSeqH = 2,
565a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    kIndexSeqL = 3,
575a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell};
585a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
595a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell// Extracts a big-endian uint16_t from a byte array.
605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellstatic uint16_t ExtractUint16(const uint8_t* bytes) {
615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return (static_cast<uint16_t>(bytes[0]) << 8) | bytes[1];
625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
645a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell// Packet header handling.
655a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellclass Header {
665a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell  public:
675a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    Header();
685a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ~Header() = default;
695a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
705a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    uint8_t id() const { return bytes_[kIndexId]; }
715a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    const uint8_t* bytes() const { return bytes_; }
725a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
735a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    void Set(uint8_t id, uint16_t sequence, Flag flag);
745a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
755a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Checks whether |response| is a match for this header.
765a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    bool Matches(const uint8_t* response);
775a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
785a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell  private:
795a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    uint8_t bytes_[kHeaderSize];
805a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell};
815a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
825a0ec81e97f45edb9cc86e9e551864ee6d7ee210David PursellHeader::Header() {
835a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    Set(kIdError, 0, kFlagNone);
845a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
855a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
865a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellvoid Header::Set(uint8_t id, uint16_t sequence, Flag flag) {
875a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    bytes_[kIndexId] = id;
885a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    bytes_[kIndexFlags] = flag;
895a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    bytes_[kIndexSeqH] = sequence >> 8;
905a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    bytes_[kIndexSeqL] = sequence;
915a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
925a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
935a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellbool Header::Matches(const uint8_t* response) {
945a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Sequence numbers must be the same to match, but the response ID can either be the same
955a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // or an error response which is always accepted.
965a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return bytes_[kIndexSeqH] == response[kIndexSeqH] &&
975a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell           bytes_[kIndexSeqL] == response[kIndexSeqL] &&
985a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell           (bytes_[kIndexId] == response[kIndexId] || response[kIndexId] == kIdError);
995a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
1005a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1015a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell// Implements the Transport interface to work with the fastboot engine.
1025a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellclass UdpTransport : public Transport {
1035a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell  public:
1045a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Factory function so we can return nullptr if initialization fails.
1055a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    static std::unique_ptr<UdpTransport> NewTransport(std::unique_ptr<Socket> socket,
1065a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                                      std::string* error);
1075a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ~UdpTransport() override = default;
1085a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1095a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t Read(void* data, size_t length) override;
1105a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t Write(const void* data, size_t length) override;
1115a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    int Close() override;
1125a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1135a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell  private:
1145a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    UdpTransport(std::unique_ptr<Socket> socket) : socket_(std::move(socket)) {}
1155a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1165a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Performs the UDP initialization procedure. Returns true on success.
1175a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    bool InitializeProtocol(std::string* error);
1185a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1195a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Sends |length| bytes from |data| and waits for the response packet up to |attempts| times.
1205a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Continuation packets are handled automatically and any return data is written to |rx_data|.
1215a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Excess bytes that cannot fit in |rx_data| are dropped.
1225a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // On success, returns the number of response data bytes received, which may be greater than
1235a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // |rx_length|. On failure, returns -1 and fills |error| on failure.
1245a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t SendData(Id id, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
1255a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                     size_t rx_length, int attempts, std::string* error);
1265a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1275a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Helper for SendData(); sends a single packet and handles the response. |header| specifies
1285a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // the initial outgoing packet information but may be modified by this function.
1295a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t SendSinglePacketHelper(Header* header, const uint8_t* tx_data, size_t tx_length,
1305a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                   uint8_t* rx_data, size_t rx_length, int attempts,
1315a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                   std::string* error);
1325a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1335a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    std::unique_ptr<Socket> socket_;
1345a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    int sequence_ = -1;
1355a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    size_t max_data_length_ = kMinPacketSize - kHeaderSize;
1365a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    std::vector<uint8_t> rx_packet_;
1375a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1385a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    DISALLOW_COPY_AND_ASSIGN(UdpTransport);
1395a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell};
1405a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1415a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellstd::unique_ptr<UdpTransport> UdpTransport::NewTransport(std::unique_ptr<Socket> socket,
1425a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                                         std::string* error) {
1435a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    std::unique_ptr<UdpTransport> transport(new UdpTransport(std::move(socket)));
1445a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1455a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (!transport->InitializeProtocol(error)) {
1465a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return nullptr;
1475a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
1485a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1495a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return transport;
1505a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
1515a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1525a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellbool UdpTransport::InitializeProtocol(std::string* error) {
1535a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    uint8_t rx_data[4];
1545a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1555a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    sequence_ = 0;
1565a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    rx_packet_.resize(kMinPacketSize);
1575a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1585a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // First send the query packet to sync with the target. Only attempt this a small number of
1595a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // times so we can fail out quickly if the target isn't available.
1605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t rx_bytes = SendData(kIdDeviceQuery, nullptr, 0, rx_data, sizeof(rx_data),
1615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                kMaxConnectAttempts, error);
1625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (rx_bytes == -1) {
1635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return false;
1645a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    } else if (rx_bytes < 2) {
1655a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = "invalid query response from target";
1665a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return false;
1675a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
1685a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // The first two bytes contain the next expected sequence number.
1695a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    sequence_ = ExtractUint16(rx_data);
1705a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1715a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Now send the initialization packet with our version and maximum packet size.
1725a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    uint8_t init_data[] = {kProtocolVersion >> 8, kProtocolVersion & 0xFF,
1735a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                           kHostMaxPacketSize >> 8, kHostMaxPacketSize & 0xFF};
1745a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    rx_bytes = SendData(kIdInitialization, init_data, sizeof(init_data), rx_data, sizeof(rx_data),
1755a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                        kMaxTransmissionAttempts, error);
1765a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (rx_bytes == -1) {
1775a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return false;
1785a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    } else if (rx_bytes < 4) {
1795a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = "invalid initialization response from target";
1805a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return false;
1815a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
1825a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1835a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // The first two data bytes contain the version, the second two bytes contain the target max
1845a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // supported packet size, which must be at least 512 bytes.
1855a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    uint16_t version = ExtractUint16(rx_data);
1865a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (version < kProtocolVersion) {
1875a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = android::base::StringPrintf("target reported invalid protocol version %d",
1885a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                             version);
1895a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return false;
1905a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
1915a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    uint16_t packet_size = ExtractUint16(rx_data + 2);
1925a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (packet_size < kMinPacketSize) {
1935a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = android::base::StringPrintf("target reported invalid packet size %d", packet_size);
1945a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return false;
1955a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
1965a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
1975a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    packet_size = std::min(kHostMaxPacketSize, packet_size);
1985a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    max_data_length_ = packet_size - kHeaderSize;
1995a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    rx_packet_.resize(packet_size);
2005a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2015a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return true;
2025a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
2035a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2045a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell// SendData() is just responsible for chunking |data| into packets until it's all been sent.
2055a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell// Per-packet timeout/retransmission logic is done in SendSinglePacketHelper().
2065a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellssize_t UdpTransport::SendData(Id id, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
2075a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                               size_t rx_length, int attempts, std::string* error) {
2085a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (socket_ == nullptr) {
2095a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = "socket is closed";
2105a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
2115a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
2125a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2135a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    Header header;
2145a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    size_t packet_data_length;
2155a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t ret = 0;
2165a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // We often send header-only packets with no data as part of the protocol, so always send at
2175a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // least once even if |length| == 0, then repeat until we've sent all of |data|.
2185a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    do {
2195a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // Set the continuation flag and truncate packet data if needed.
2205a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (tx_length > max_data_length_) {
2215a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            packet_data_length = max_data_length_;
2225a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            header.Set(id, sequence_, kFlagContinuation);
2235a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } else {
2245a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            packet_data_length = tx_length;
2255a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            header.Set(id, sequence_, kFlagNone);
2265a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2275a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2285a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        ssize_t bytes = SendSinglePacketHelper(&header, tx_data, packet_data_length, rx_data,
2295a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                                               rx_length, attempts, error);
2305a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2315a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // Advance our read and write buffers for the next packet. Keep going even if we run out
2325a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // of receive buffer space so we can detect overflows.
2335a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (bytes == -1) {
2345a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            return -1;
2355a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } else if (static_cast<size_t>(bytes) < rx_length) {
2365a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            rx_data += bytes;
2375a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            rx_length -= bytes;
2385a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } else {
2395a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            rx_data = nullptr;
2405a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            rx_length = 0;
2415a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2425a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2435a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        tx_length -= packet_data_length;
2445a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        tx_data += packet_data_length;
2455a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2465a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        ret += bytes;
2475a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    } while (tx_length > 0);
2485a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2495a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return ret;
2505a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
2515a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2525a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellssize_t UdpTransport::SendSinglePacketHelper(
2535a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        Header* header, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
2545a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        size_t rx_length, const int attempts, std::string* error) {
2555a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t total_data_bytes = 0;
2565a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    error->clear();
2575a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2585a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    int attempts_left = attempts;
2595a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    while (attempts_left > 0) {
2605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (!socket_->Send({{header->bytes(), kHeaderSize}, {tx_data, tx_length}})) {
2615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            *error = Socket::GetErrorMessage();
2625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            return -1;
2635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2645a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2655a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // Keep receiving until we get a matching response or we timeout.
2665a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        ssize_t bytes = 0;
2675a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        do {
2685a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            bytes = socket_->Receive(rx_packet_.data(), rx_packet_.size(), kResponseTimeoutMs);
2695a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            if (bytes == -1) {
2705a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                if (socket_->ReceiveTimedOut()) {
2715a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                    break;
2725a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                }
2735a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                *error = Socket::GetErrorMessage();
2745a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                return -1;
2755a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            } else if (bytes < static_cast<ssize_t>(kHeaderSize)) {
2765a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                *error = "protocol error: incomplete header";
2775a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                return -1;
2785a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            }
2795a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } while (!header->Matches(rx_packet_.data()));
2805a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2815a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (socket_->ReceiveTimedOut()) {
2825a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            --attempts_left;
2835a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            continue;
2845a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2855a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        ++sequence_;
2865a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2875a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // Save to |error| or |rx_data| as appropriate.
2885a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (rx_packet_[kIndexId] == kIdError) {
2895a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            error->append(rx_packet_.data() + kHeaderSize, rx_packet_.data() + bytes);
2905a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } else {
2915a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            total_data_bytes += bytes - kHeaderSize;
2925a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            size_t rx_data_bytes = std::min<size_t>(bytes - kHeaderSize, rx_length);
2935a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            if (rx_data_bytes > 0) {
2945a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                memcpy(rx_data, rx_packet_.data() + kHeaderSize, rx_data_bytes);
2955a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                rx_data += rx_data_bytes;
2965a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                rx_length -= rx_data_bytes;
2975a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            }
2985a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2995a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3005a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // If the response has a continuation flag we need to prompt for more data by sending
3015a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // an empty packet.
3025a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (rx_packet_[kIndexFlags] & kFlagContinuation) {
3035a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            // We got a valid response so reset our attempt counter.
3045a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            attempts_left = attempts;
3055a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            header->Set(rx_packet_[kIndexId], sequence_, kFlagNone);
3065a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            tx_data = nullptr;
3075a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            tx_length = 0;
3085a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            continue;
3095a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
3105a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3115a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        break;
3125a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3135a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3145a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (attempts_left <= 0) {
3155a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = "no response from target";
3165a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
3175a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3185a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3195a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (rx_packet_[kIndexId] == kIdError) {
3205a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        *error = "target reported error: " + *error;
3215a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
3225a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3235a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3245a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return total_data_bytes;
3255a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
3265a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3275a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellssize_t UdpTransport::Read(void* data, size_t length) {
3285a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    // Read from the target by sending an empty packet.
3295a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    std::string error;
3305a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t bytes = SendData(kIdFastboot, nullptr, 0, reinterpret_cast<uint8_t*>(data), length,
3315a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                             kMaxTransmissionAttempts, &error);
3325a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3335a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (bytes == -1) {
3345a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        fprintf(stderr, "UDP error: %s\n", error.c_str());
3355a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
3365a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    } else if (static_cast<size_t>(bytes) > length) {
3375a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // Fastboot protocol error: the target sent more data than our fastboot engine was prepared
3385a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // to receive.
3395a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        fprintf(stderr, "UDP error: receive overflow, target sent too much fastboot data\n");
3405a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
3415a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3425a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3435a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return bytes;
3445a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
3455a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3465a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellssize_t UdpTransport::Write(const void* data, size_t length) {
3475a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    std::string error;
3485a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    ssize_t bytes = SendData(kIdFastboot, reinterpret_cast<const uint8_t*>(data), length, nullptr,
3495a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                             0, kMaxTransmissionAttempts, &error);
3505a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3515a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (bytes == -1) {
3525a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        fprintf(stderr, "UDP error: %s\n", error.c_str());
3535a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
3545a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    } else if (bytes > 0) {
3555a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // UDP protocol error: only empty ACK packets are allowed when writing to a device.
3565a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        fprintf(stderr, "UDP error: target sent fastboot data out-of-turn\n");
3575a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return -1;
3585a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3595a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return length;
3615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
3625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellint UdpTransport::Close() {
3645a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (socket_ == nullptr) {
3655a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return 0;
3665a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3675a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3685a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    int result = socket_->Close();
3695a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    socket_.reset();
3705a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return result;
3715a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
3725a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3735a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellstd::unique_ptr<Transport> Connect(const std::string& hostname, int port, std::string* error) {
3745a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return internal::Connect(Socket::NewClient(Socket::Protocol::kUdp, hostname, port, error),
3755a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                             error);
3765a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
3775a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3785a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellnamespace internal {
3795a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3805a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursellstd::unique_ptr<Transport> Connect(std::unique_ptr<Socket> sock, std::string* error) {
3815a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (sock == nullptr) {
3825a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        // If Socket creation failed |error| is already set.
3835a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        return nullptr;
3845a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    }
3855a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3865a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    return UdpTransport::NewTransport(std::move(sock), error);
3875a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}
3885a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3895a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}  // namespace internal
3905a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
3915a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell}  // namespace udp
392