1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*00c7fec1SAndroid Build Coastguard Worker * All rights reserved.
4*00c7fec1SAndroid Build Coastguard Worker *
5*00c7fec1SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*00c7fec1SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
7*00c7fec1SAndroid Build Coastguard Worker * are met:
8*00c7fec1SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright
9*00c7fec1SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
10*00c7fec1SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright
11*00c7fec1SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in
12*00c7fec1SAndroid Build Coastguard Worker * the documentation and/or other materials provided with the
13*00c7fec1SAndroid Build Coastguard Worker * distribution.
14*00c7fec1SAndroid Build Coastguard Worker *
15*00c7fec1SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*00c7fec1SAndroid Build Coastguard Worker * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*00c7fec1SAndroid Build Coastguard Worker * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*00c7fec1SAndroid Build Coastguard Worker * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*00c7fec1SAndroid Build Coastguard Worker * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*00c7fec1SAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*00c7fec1SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*00c7fec1SAndroid Build Coastguard Worker * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*00c7fec1SAndroid Build Coastguard Worker * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*00c7fec1SAndroid Build Coastguard Worker * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*00c7fec1SAndroid Build Coastguard Worker * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*00c7fec1SAndroid Build Coastguard Worker * SUCH DAMAGE.
27*00c7fec1SAndroid Build Coastguard Worker */
28*00c7fec1SAndroid Build Coastguard Worker
29*00c7fec1SAndroid Build Coastguard Worker // This file implements the fastboot UDP protocol; see fastboot_protocol.txt for documentation.
30*00c7fec1SAndroid Build Coastguard Worker
31*00c7fec1SAndroid Build Coastguard Worker #include "udp.h"
32*00c7fec1SAndroid Build Coastguard Worker
33*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
34*00c7fec1SAndroid Build Coastguard Worker #include <stdio.h>
35*00c7fec1SAndroid Build Coastguard Worker
36*00c7fec1SAndroid Build Coastguard Worker #include <list>
37*00c7fec1SAndroid Build Coastguard Worker #include <memory>
38*00c7fec1SAndroid Build Coastguard Worker #include <vector>
39*00c7fec1SAndroid Build Coastguard Worker
40*00c7fec1SAndroid Build Coastguard Worker #include <android-base/macros.h>
41*00c7fec1SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
42*00c7fec1SAndroid Build Coastguard Worker
43*00c7fec1SAndroid Build Coastguard Worker #include "socket.h"
44*00c7fec1SAndroid Build Coastguard Worker
45*00c7fec1SAndroid Build Coastguard Worker namespace udp {
46*00c7fec1SAndroid Build Coastguard Worker
47*00c7fec1SAndroid Build Coastguard Worker using namespace internal;
48*00c7fec1SAndroid Build Coastguard Worker
49*00c7fec1SAndroid Build Coastguard Worker constexpr size_t kMinPacketSize = 512;
50*00c7fec1SAndroid Build Coastguard Worker constexpr size_t kHeaderSize = 4;
51*00c7fec1SAndroid Build Coastguard Worker
52*00c7fec1SAndroid Build Coastguard Worker enum Index {
53*00c7fec1SAndroid Build Coastguard Worker kIndexId = 0,
54*00c7fec1SAndroid Build Coastguard Worker kIndexFlags = 1,
55*00c7fec1SAndroid Build Coastguard Worker kIndexSeqH = 2,
56*00c7fec1SAndroid Build Coastguard Worker kIndexSeqL = 3,
57*00c7fec1SAndroid Build Coastguard Worker };
58*00c7fec1SAndroid Build Coastguard Worker
59*00c7fec1SAndroid Build Coastguard Worker // Extracts a big-endian uint16_t from a byte array.
ExtractUint16(const uint8_t * bytes)60*00c7fec1SAndroid Build Coastguard Worker static uint16_t ExtractUint16(const uint8_t* bytes) {
61*00c7fec1SAndroid Build Coastguard Worker return (static_cast<uint16_t>(bytes[0]) << 8) | bytes[1];
62*00c7fec1SAndroid Build Coastguard Worker }
63*00c7fec1SAndroid Build Coastguard Worker
64*00c7fec1SAndroid Build Coastguard Worker // Packet header handling.
65*00c7fec1SAndroid Build Coastguard Worker class Header {
66*00c7fec1SAndroid Build Coastguard Worker public:
67*00c7fec1SAndroid Build Coastguard Worker Header();
68*00c7fec1SAndroid Build Coastguard Worker ~Header() = default;
69*00c7fec1SAndroid Build Coastguard Worker
id() const70*00c7fec1SAndroid Build Coastguard Worker uint8_t id() const { return bytes_[kIndexId]; }
bytes() const71*00c7fec1SAndroid Build Coastguard Worker const uint8_t* bytes() const { return bytes_; }
72*00c7fec1SAndroid Build Coastguard Worker
73*00c7fec1SAndroid Build Coastguard Worker void Set(uint8_t id, uint16_t sequence, Flag flag);
74*00c7fec1SAndroid Build Coastguard Worker
75*00c7fec1SAndroid Build Coastguard Worker // Checks whether |response| is a match for this header.
76*00c7fec1SAndroid Build Coastguard Worker bool Matches(const uint8_t* response);
77*00c7fec1SAndroid Build Coastguard Worker
78*00c7fec1SAndroid Build Coastguard Worker private:
79*00c7fec1SAndroid Build Coastguard Worker uint8_t bytes_[kHeaderSize];
80*00c7fec1SAndroid Build Coastguard Worker };
81*00c7fec1SAndroid Build Coastguard Worker
Header()82*00c7fec1SAndroid Build Coastguard Worker Header::Header() {
83*00c7fec1SAndroid Build Coastguard Worker Set(kIdError, 0, kFlagNone);
84*00c7fec1SAndroid Build Coastguard Worker }
85*00c7fec1SAndroid Build Coastguard Worker
Set(uint8_t id,uint16_t sequence,Flag flag)86*00c7fec1SAndroid Build Coastguard Worker void Header::Set(uint8_t id, uint16_t sequence, Flag flag) {
87*00c7fec1SAndroid Build Coastguard Worker bytes_[kIndexId] = id;
88*00c7fec1SAndroid Build Coastguard Worker bytes_[kIndexFlags] = flag;
89*00c7fec1SAndroid Build Coastguard Worker bytes_[kIndexSeqH] = sequence >> 8;
90*00c7fec1SAndroid Build Coastguard Worker bytes_[kIndexSeqL] = sequence;
91*00c7fec1SAndroid Build Coastguard Worker }
92*00c7fec1SAndroid Build Coastguard Worker
Matches(const uint8_t * response)93*00c7fec1SAndroid Build Coastguard Worker bool Header::Matches(const uint8_t* response) {
94*00c7fec1SAndroid Build Coastguard Worker // Sequence numbers must be the same to match, but the response ID can either be the same
95*00c7fec1SAndroid Build Coastguard Worker // or an error response which is always accepted.
96*00c7fec1SAndroid Build Coastguard Worker return bytes_[kIndexSeqH] == response[kIndexSeqH] &&
97*00c7fec1SAndroid Build Coastguard Worker bytes_[kIndexSeqL] == response[kIndexSeqL] &&
98*00c7fec1SAndroid Build Coastguard Worker (bytes_[kIndexId] == response[kIndexId] || response[kIndexId] == kIdError);
99*00c7fec1SAndroid Build Coastguard Worker }
100*00c7fec1SAndroid Build Coastguard Worker
101*00c7fec1SAndroid Build Coastguard Worker // Implements the Transport interface to work with the fastboot engine.
102*00c7fec1SAndroid Build Coastguard Worker class UdpTransport : public Transport {
103*00c7fec1SAndroid Build Coastguard Worker public:
104*00c7fec1SAndroid Build Coastguard Worker // Factory function so we can return nullptr if initialization fails.
105*00c7fec1SAndroid Build Coastguard Worker static std::unique_ptr<UdpTransport> NewTransport(std::unique_ptr<Socket> socket,
106*00c7fec1SAndroid Build Coastguard Worker std::string* error);
107*00c7fec1SAndroid Build Coastguard Worker ~UdpTransport() override = default;
108*00c7fec1SAndroid Build Coastguard Worker
109*00c7fec1SAndroid Build Coastguard Worker ssize_t Read(void* data, size_t length) override;
110*00c7fec1SAndroid Build Coastguard Worker ssize_t Write(const void* data, size_t length) override;
111*00c7fec1SAndroid Build Coastguard Worker int Close() override;
112*00c7fec1SAndroid Build Coastguard Worker int Reset() override;
113*00c7fec1SAndroid Build Coastguard Worker
114*00c7fec1SAndroid Build Coastguard Worker private:
UdpTransport(std::unique_ptr<Socket> socket)115*00c7fec1SAndroid Build Coastguard Worker explicit UdpTransport(std::unique_ptr<Socket> socket) : socket_(std::move(socket)) {}
116*00c7fec1SAndroid Build Coastguard Worker
117*00c7fec1SAndroid Build Coastguard Worker // Performs the UDP initialization procedure. Returns true on success.
118*00c7fec1SAndroid Build Coastguard Worker bool InitializeProtocol(std::string* error);
119*00c7fec1SAndroid Build Coastguard Worker
120*00c7fec1SAndroid Build Coastguard Worker // Sends |length| bytes from |data| and waits for the response packet up to |attempts| times.
121*00c7fec1SAndroid Build Coastguard Worker // Continuation packets are handled automatically and any return data is written to |rx_data|.
122*00c7fec1SAndroid Build Coastguard Worker // Excess bytes that cannot fit in |rx_data| are dropped.
123*00c7fec1SAndroid Build Coastguard Worker // On success, returns the number of response data bytes received, which may be greater than
124*00c7fec1SAndroid Build Coastguard Worker // |rx_length|. On failure, returns -1 and fills |error| on failure.
125*00c7fec1SAndroid Build Coastguard Worker ssize_t SendData(Id id, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
126*00c7fec1SAndroid Build Coastguard Worker size_t rx_length, int attempts, std::string* error);
127*00c7fec1SAndroid Build Coastguard Worker
128*00c7fec1SAndroid Build Coastguard Worker // Helper for SendData(); sends a single packet and handles the response. |header| specifies
129*00c7fec1SAndroid Build Coastguard Worker // the initial outgoing packet information but may be modified by this function.
130*00c7fec1SAndroid Build Coastguard Worker ssize_t SendSinglePacketHelper(Header* header, const uint8_t* tx_data, size_t tx_length,
131*00c7fec1SAndroid Build Coastguard Worker uint8_t* rx_data, size_t rx_length, int attempts,
132*00c7fec1SAndroid Build Coastguard Worker std::string* error);
133*00c7fec1SAndroid Build Coastguard Worker
134*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<Socket> socket_;
135*00c7fec1SAndroid Build Coastguard Worker int sequence_ = -1;
136*00c7fec1SAndroid Build Coastguard Worker size_t max_data_length_ = kMinPacketSize - kHeaderSize;
137*00c7fec1SAndroid Build Coastguard Worker std::vector<uint8_t> rx_packet_;
138*00c7fec1SAndroid Build Coastguard Worker
139*00c7fec1SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(UdpTransport);
140*00c7fec1SAndroid Build Coastguard Worker };
141*00c7fec1SAndroid Build Coastguard Worker
NewTransport(std::unique_ptr<Socket> socket,std::string * error)142*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<UdpTransport> UdpTransport::NewTransport(std::unique_ptr<Socket> socket,
143*00c7fec1SAndroid Build Coastguard Worker std::string* error) {
144*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<UdpTransport> transport(new UdpTransport(std::move(socket)));
145*00c7fec1SAndroid Build Coastguard Worker
146*00c7fec1SAndroid Build Coastguard Worker if (!transport->InitializeProtocol(error)) {
147*00c7fec1SAndroid Build Coastguard Worker return nullptr;
148*00c7fec1SAndroid Build Coastguard Worker }
149*00c7fec1SAndroid Build Coastguard Worker
150*00c7fec1SAndroid Build Coastguard Worker return transport;
151*00c7fec1SAndroid Build Coastguard Worker }
152*00c7fec1SAndroid Build Coastguard Worker
InitializeProtocol(std::string * error)153*00c7fec1SAndroid Build Coastguard Worker bool UdpTransport::InitializeProtocol(std::string* error) {
154*00c7fec1SAndroid Build Coastguard Worker uint8_t rx_data[4];
155*00c7fec1SAndroid Build Coastguard Worker
156*00c7fec1SAndroid Build Coastguard Worker sequence_ = 0;
157*00c7fec1SAndroid Build Coastguard Worker rx_packet_.resize(kMinPacketSize);
158*00c7fec1SAndroid Build Coastguard Worker
159*00c7fec1SAndroid Build Coastguard Worker // First send the query packet to sync with the target. Only attempt this a small number of
160*00c7fec1SAndroid Build Coastguard Worker // times so we can fail out quickly if the target isn't available.
161*00c7fec1SAndroid Build Coastguard Worker ssize_t rx_bytes = SendData(kIdDeviceQuery, nullptr, 0, rx_data, sizeof(rx_data),
162*00c7fec1SAndroid Build Coastguard Worker kMaxConnectAttempts, error);
163*00c7fec1SAndroid Build Coastguard Worker if (rx_bytes == -1) {
164*00c7fec1SAndroid Build Coastguard Worker return false;
165*00c7fec1SAndroid Build Coastguard Worker } else if (rx_bytes < 2) {
166*00c7fec1SAndroid Build Coastguard Worker *error = "invalid query response from target";
167*00c7fec1SAndroid Build Coastguard Worker return false;
168*00c7fec1SAndroid Build Coastguard Worker }
169*00c7fec1SAndroid Build Coastguard Worker // The first two bytes contain the next expected sequence number.
170*00c7fec1SAndroid Build Coastguard Worker sequence_ = ExtractUint16(rx_data);
171*00c7fec1SAndroid Build Coastguard Worker
172*00c7fec1SAndroid Build Coastguard Worker // Now send the initialization packet with our version and maximum packet size.
173*00c7fec1SAndroid Build Coastguard Worker uint8_t init_data[] = {kProtocolVersion >> 8, kProtocolVersion & 0xFF,
174*00c7fec1SAndroid Build Coastguard Worker kHostMaxPacketSize >> 8, kHostMaxPacketSize & 0xFF};
175*00c7fec1SAndroid Build Coastguard Worker rx_bytes = SendData(kIdInitialization, init_data, sizeof(init_data), rx_data, sizeof(rx_data),
176*00c7fec1SAndroid Build Coastguard Worker kMaxTransmissionAttempts, error);
177*00c7fec1SAndroid Build Coastguard Worker if (rx_bytes == -1) {
178*00c7fec1SAndroid Build Coastguard Worker return false;
179*00c7fec1SAndroid Build Coastguard Worker } else if (rx_bytes < 4) {
180*00c7fec1SAndroid Build Coastguard Worker *error = "invalid initialization response from target";
181*00c7fec1SAndroid Build Coastguard Worker return false;
182*00c7fec1SAndroid Build Coastguard Worker }
183*00c7fec1SAndroid Build Coastguard Worker
184*00c7fec1SAndroid Build Coastguard Worker // The first two data bytes contain the version, the second two bytes contain the target max
185*00c7fec1SAndroid Build Coastguard Worker // supported packet size, which must be at least 512 bytes.
186*00c7fec1SAndroid Build Coastguard Worker uint16_t version = ExtractUint16(rx_data);
187*00c7fec1SAndroid Build Coastguard Worker if (version < kProtocolVersion) {
188*00c7fec1SAndroid Build Coastguard Worker *error = android::base::StringPrintf("target reported invalid protocol version %d",
189*00c7fec1SAndroid Build Coastguard Worker version);
190*00c7fec1SAndroid Build Coastguard Worker return false;
191*00c7fec1SAndroid Build Coastguard Worker }
192*00c7fec1SAndroid Build Coastguard Worker uint16_t packet_size = ExtractUint16(rx_data + 2);
193*00c7fec1SAndroid Build Coastguard Worker if (packet_size < kMinPacketSize) {
194*00c7fec1SAndroid Build Coastguard Worker *error = android::base::StringPrintf("target reported invalid packet size %d", packet_size);
195*00c7fec1SAndroid Build Coastguard Worker return false;
196*00c7fec1SAndroid Build Coastguard Worker }
197*00c7fec1SAndroid Build Coastguard Worker
198*00c7fec1SAndroid Build Coastguard Worker packet_size = std::min(kHostMaxPacketSize, packet_size);
199*00c7fec1SAndroid Build Coastguard Worker max_data_length_ = packet_size - kHeaderSize;
200*00c7fec1SAndroid Build Coastguard Worker rx_packet_.resize(packet_size);
201*00c7fec1SAndroid Build Coastguard Worker
202*00c7fec1SAndroid Build Coastguard Worker return true;
203*00c7fec1SAndroid Build Coastguard Worker }
204*00c7fec1SAndroid Build Coastguard Worker
205*00c7fec1SAndroid Build Coastguard Worker // SendData() is just responsible for chunking |data| into packets until it's all been sent.
206*00c7fec1SAndroid Build Coastguard Worker // Per-packet timeout/retransmission logic is done in SendSinglePacketHelper().
SendData(Id id,const uint8_t * tx_data,size_t tx_length,uint8_t * rx_data,size_t rx_length,int attempts,std::string * error)207*00c7fec1SAndroid Build Coastguard Worker ssize_t UdpTransport::SendData(Id id, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
208*00c7fec1SAndroid Build Coastguard Worker size_t rx_length, int attempts, std::string* error) {
209*00c7fec1SAndroid Build Coastguard Worker if (socket_ == nullptr) {
210*00c7fec1SAndroid Build Coastguard Worker *error = "socket is closed";
211*00c7fec1SAndroid Build Coastguard Worker return -1;
212*00c7fec1SAndroid Build Coastguard Worker }
213*00c7fec1SAndroid Build Coastguard Worker
214*00c7fec1SAndroid Build Coastguard Worker Header header;
215*00c7fec1SAndroid Build Coastguard Worker size_t packet_data_length;
216*00c7fec1SAndroid Build Coastguard Worker ssize_t ret = 0;
217*00c7fec1SAndroid Build Coastguard Worker // We often send header-only packets with no data as part of the protocol, so always send at
218*00c7fec1SAndroid Build Coastguard Worker // least once even if |length| == 0, then repeat until we've sent all of |data|.
219*00c7fec1SAndroid Build Coastguard Worker do {
220*00c7fec1SAndroid Build Coastguard Worker // Set the continuation flag and truncate packet data if needed.
221*00c7fec1SAndroid Build Coastguard Worker if (tx_length > max_data_length_) {
222*00c7fec1SAndroid Build Coastguard Worker packet_data_length = max_data_length_;
223*00c7fec1SAndroid Build Coastguard Worker header.Set(id, sequence_, kFlagContinuation);
224*00c7fec1SAndroid Build Coastguard Worker } else {
225*00c7fec1SAndroid Build Coastguard Worker packet_data_length = tx_length;
226*00c7fec1SAndroid Build Coastguard Worker header.Set(id, sequence_, kFlagNone);
227*00c7fec1SAndroid Build Coastguard Worker }
228*00c7fec1SAndroid Build Coastguard Worker
229*00c7fec1SAndroid Build Coastguard Worker ssize_t bytes = SendSinglePacketHelper(&header, tx_data, packet_data_length, rx_data,
230*00c7fec1SAndroid Build Coastguard Worker rx_length, attempts, error);
231*00c7fec1SAndroid Build Coastguard Worker
232*00c7fec1SAndroid Build Coastguard Worker // Advance our read and write buffers for the next packet. Keep going even if we run out
233*00c7fec1SAndroid Build Coastguard Worker // of receive buffer space so we can detect overflows.
234*00c7fec1SAndroid Build Coastguard Worker if (bytes == -1) {
235*00c7fec1SAndroid Build Coastguard Worker return -1;
236*00c7fec1SAndroid Build Coastguard Worker } else if (static_cast<size_t>(bytes) < rx_length) {
237*00c7fec1SAndroid Build Coastguard Worker rx_data += bytes;
238*00c7fec1SAndroid Build Coastguard Worker rx_length -= bytes;
239*00c7fec1SAndroid Build Coastguard Worker } else {
240*00c7fec1SAndroid Build Coastguard Worker rx_data = nullptr;
241*00c7fec1SAndroid Build Coastguard Worker rx_length = 0;
242*00c7fec1SAndroid Build Coastguard Worker }
243*00c7fec1SAndroid Build Coastguard Worker
244*00c7fec1SAndroid Build Coastguard Worker tx_length -= packet_data_length;
245*00c7fec1SAndroid Build Coastguard Worker tx_data += packet_data_length;
246*00c7fec1SAndroid Build Coastguard Worker
247*00c7fec1SAndroid Build Coastguard Worker ret += bytes;
248*00c7fec1SAndroid Build Coastguard Worker } while (tx_length > 0);
249*00c7fec1SAndroid Build Coastguard Worker
250*00c7fec1SAndroid Build Coastguard Worker return ret;
251*00c7fec1SAndroid Build Coastguard Worker }
252*00c7fec1SAndroid Build Coastguard Worker
SendSinglePacketHelper(Header * header,const uint8_t * tx_data,size_t tx_length,uint8_t * rx_data,size_t rx_length,const int attempts,std::string * error)253*00c7fec1SAndroid Build Coastguard Worker ssize_t UdpTransport::SendSinglePacketHelper(
254*00c7fec1SAndroid Build Coastguard Worker Header* header, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
255*00c7fec1SAndroid Build Coastguard Worker size_t rx_length, const int attempts, std::string* error) {
256*00c7fec1SAndroid Build Coastguard Worker ssize_t total_data_bytes = 0;
257*00c7fec1SAndroid Build Coastguard Worker error->clear();
258*00c7fec1SAndroid Build Coastguard Worker
259*00c7fec1SAndroid Build Coastguard Worker int attempts_left = attempts;
260*00c7fec1SAndroid Build Coastguard Worker while (attempts_left > 0) {
261*00c7fec1SAndroid Build Coastguard Worker if (!socket_->Send({{header->bytes(), kHeaderSize}, {tx_data, tx_length}})) {
262*00c7fec1SAndroid Build Coastguard Worker *error = Socket::GetErrorMessage();
263*00c7fec1SAndroid Build Coastguard Worker return -1;
264*00c7fec1SAndroid Build Coastguard Worker }
265*00c7fec1SAndroid Build Coastguard Worker
266*00c7fec1SAndroid Build Coastguard Worker // Keep receiving until we get a matching response or we timeout.
267*00c7fec1SAndroid Build Coastguard Worker ssize_t bytes = 0;
268*00c7fec1SAndroid Build Coastguard Worker do {
269*00c7fec1SAndroid Build Coastguard Worker bytes = socket_->Receive(rx_packet_.data(), rx_packet_.size(), kResponseTimeoutMs);
270*00c7fec1SAndroid Build Coastguard Worker if (bytes == -1) {
271*00c7fec1SAndroid Build Coastguard Worker if (socket_->ReceiveTimedOut()) {
272*00c7fec1SAndroid Build Coastguard Worker break;
273*00c7fec1SAndroid Build Coastguard Worker }
274*00c7fec1SAndroid Build Coastguard Worker *error = Socket::GetErrorMessage();
275*00c7fec1SAndroid Build Coastguard Worker return -1;
276*00c7fec1SAndroid Build Coastguard Worker } else if (bytes < static_cast<ssize_t>(kHeaderSize)) {
277*00c7fec1SAndroid Build Coastguard Worker *error = "protocol error: incomplete header";
278*00c7fec1SAndroid Build Coastguard Worker return -1;
279*00c7fec1SAndroid Build Coastguard Worker }
280*00c7fec1SAndroid Build Coastguard Worker } while (!header->Matches(rx_packet_.data()));
281*00c7fec1SAndroid Build Coastguard Worker
282*00c7fec1SAndroid Build Coastguard Worker if (socket_->ReceiveTimedOut()) {
283*00c7fec1SAndroid Build Coastguard Worker --attempts_left;
284*00c7fec1SAndroid Build Coastguard Worker continue;
285*00c7fec1SAndroid Build Coastguard Worker }
286*00c7fec1SAndroid Build Coastguard Worker ++sequence_;
287*00c7fec1SAndroid Build Coastguard Worker
288*00c7fec1SAndroid Build Coastguard Worker // Save to |error| or |rx_data| as appropriate.
289*00c7fec1SAndroid Build Coastguard Worker if (rx_packet_[kIndexId] == kIdError) {
290*00c7fec1SAndroid Build Coastguard Worker error->append(rx_packet_.data() + kHeaderSize, rx_packet_.data() + bytes);
291*00c7fec1SAndroid Build Coastguard Worker } else {
292*00c7fec1SAndroid Build Coastguard Worker total_data_bytes += bytes - kHeaderSize;
293*00c7fec1SAndroid Build Coastguard Worker size_t rx_data_bytes = std::min<size_t>(bytes - kHeaderSize, rx_length);
294*00c7fec1SAndroid Build Coastguard Worker if (rx_data_bytes > 0) {
295*00c7fec1SAndroid Build Coastguard Worker memcpy(rx_data, rx_packet_.data() + kHeaderSize, rx_data_bytes);
296*00c7fec1SAndroid Build Coastguard Worker rx_data += rx_data_bytes;
297*00c7fec1SAndroid Build Coastguard Worker rx_length -= rx_data_bytes;
298*00c7fec1SAndroid Build Coastguard Worker }
299*00c7fec1SAndroid Build Coastguard Worker }
300*00c7fec1SAndroid Build Coastguard Worker
301*00c7fec1SAndroid Build Coastguard Worker // If the response has a continuation flag we need to prompt for more data by sending
302*00c7fec1SAndroid Build Coastguard Worker // an empty packet.
303*00c7fec1SAndroid Build Coastguard Worker if (rx_packet_[kIndexFlags] & kFlagContinuation) {
304*00c7fec1SAndroid Build Coastguard Worker // We got a valid response so reset our attempt counter.
305*00c7fec1SAndroid Build Coastguard Worker attempts_left = attempts;
306*00c7fec1SAndroid Build Coastguard Worker header->Set(rx_packet_[kIndexId], sequence_, kFlagNone);
307*00c7fec1SAndroid Build Coastguard Worker tx_data = nullptr;
308*00c7fec1SAndroid Build Coastguard Worker tx_length = 0;
309*00c7fec1SAndroid Build Coastguard Worker continue;
310*00c7fec1SAndroid Build Coastguard Worker }
311*00c7fec1SAndroid Build Coastguard Worker
312*00c7fec1SAndroid Build Coastguard Worker break;
313*00c7fec1SAndroid Build Coastguard Worker }
314*00c7fec1SAndroid Build Coastguard Worker
315*00c7fec1SAndroid Build Coastguard Worker if (attempts_left <= 0) {
316*00c7fec1SAndroid Build Coastguard Worker *error = "no response from target";
317*00c7fec1SAndroid Build Coastguard Worker return -1;
318*00c7fec1SAndroid Build Coastguard Worker }
319*00c7fec1SAndroid Build Coastguard Worker
320*00c7fec1SAndroid Build Coastguard Worker if (rx_packet_[kIndexId] == kIdError) {
321*00c7fec1SAndroid Build Coastguard Worker *error = "target reported error: " + *error;
322*00c7fec1SAndroid Build Coastguard Worker return -1;
323*00c7fec1SAndroid Build Coastguard Worker }
324*00c7fec1SAndroid Build Coastguard Worker
325*00c7fec1SAndroid Build Coastguard Worker return total_data_bytes;
326*00c7fec1SAndroid Build Coastguard Worker }
327*00c7fec1SAndroid Build Coastguard Worker
Read(void * data,size_t length)328*00c7fec1SAndroid Build Coastguard Worker ssize_t UdpTransport::Read(void* data, size_t length) {
329*00c7fec1SAndroid Build Coastguard Worker // Read from the target by sending an empty packet.
330*00c7fec1SAndroid Build Coastguard Worker std::string error;
331*00c7fec1SAndroid Build Coastguard Worker ssize_t bytes = SendData(kIdFastboot, nullptr, 0, reinterpret_cast<uint8_t*>(data), length,
332*00c7fec1SAndroid Build Coastguard Worker kMaxTransmissionAttempts, &error);
333*00c7fec1SAndroid Build Coastguard Worker
334*00c7fec1SAndroid Build Coastguard Worker if (bytes == -1) {
335*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "UDP error: %s\n", error.c_str());
336*00c7fec1SAndroid Build Coastguard Worker return -1;
337*00c7fec1SAndroid Build Coastguard Worker } else if (static_cast<size_t>(bytes) > length) {
338*00c7fec1SAndroid Build Coastguard Worker // Fastboot protocol error: the target sent more data than our fastboot engine was prepared
339*00c7fec1SAndroid Build Coastguard Worker // to receive.
340*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "UDP error: receive overflow, target sent too much fastboot data\n");
341*00c7fec1SAndroid Build Coastguard Worker return -1;
342*00c7fec1SAndroid Build Coastguard Worker }
343*00c7fec1SAndroid Build Coastguard Worker
344*00c7fec1SAndroid Build Coastguard Worker return bytes;
345*00c7fec1SAndroid Build Coastguard Worker }
346*00c7fec1SAndroid Build Coastguard Worker
Write(const void * data,size_t length)347*00c7fec1SAndroid Build Coastguard Worker ssize_t UdpTransport::Write(const void* data, size_t length) {
348*00c7fec1SAndroid Build Coastguard Worker std::string error;
349*00c7fec1SAndroid Build Coastguard Worker ssize_t bytes = SendData(kIdFastboot, reinterpret_cast<const uint8_t*>(data), length, nullptr,
350*00c7fec1SAndroid Build Coastguard Worker 0, kMaxTransmissionAttempts, &error);
351*00c7fec1SAndroid Build Coastguard Worker
352*00c7fec1SAndroid Build Coastguard Worker if (bytes == -1) {
353*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "UDP error: %s\n", error.c_str());
354*00c7fec1SAndroid Build Coastguard Worker return -1;
355*00c7fec1SAndroid Build Coastguard Worker } else if (bytes > 0) {
356*00c7fec1SAndroid Build Coastguard Worker // UDP protocol error: only empty ACK packets are allowed when writing to a device.
357*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "UDP error: target sent fastboot data out-of-turn\n");
358*00c7fec1SAndroid Build Coastguard Worker return -1;
359*00c7fec1SAndroid Build Coastguard Worker }
360*00c7fec1SAndroid Build Coastguard Worker
361*00c7fec1SAndroid Build Coastguard Worker return length;
362*00c7fec1SAndroid Build Coastguard Worker }
363*00c7fec1SAndroid Build Coastguard Worker
Close()364*00c7fec1SAndroid Build Coastguard Worker int UdpTransport::Close() {
365*00c7fec1SAndroid Build Coastguard Worker if (socket_ == nullptr) {
366*00c7fec1SAndroid Build Coastguard Worker return 0;
367*00c7fec1SAndroid Build Coastguard Worker }
368*00c7fec1SAndroid Build Coastguard Worker
369*00c7fec1SAndroid Build Coastguard Worker int result = socket_->Close();
370*00c7fec1SAndroid Build Coastguard Worker socket_.reset();
371*00c7fec1SAndroid Build Coastguard Worker return result;
372*00c7fec1SAndroid Build Coastguard Worker }
373*00c7fec1SAndroid Build Coastguard Worker
Reset()374*00c7fec1SAndroid Build Coastguard Worker int UdpTransport::Reset() {
375*00c7fec1SAndroid Build Coastguard Worker return 0;
376*00c7fec1SAndroid Build Coastguard Worker }
377*00c7fec1SAndroid Build Coastguard Worker
Connect(const std::string & hostname,int port,std::string * error)378*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<Transport> Connect(const std::string& hostname, int port, std::string* error) {
379*00c7fec1SAndroid Build Coastguard Worker return internal::Connect(Socket::NewClient(Socket::Protocol::kUdp, hostname, port, error),
380*00c7fec1SAndroid Build Coastguard Worker error);
381*00c7fec1SAndroid Build Coastguard Worker }
382*00c7fec1SAndroid Build Coastguard Worker
383*00c7fec1SAndroid Build Coastguard Worker namespace internal {
384*00c7fec1SAndroid Build Coastguard Worker
Connect(std::unique_ptr<Socket> sock,std::string * error)385*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<Transport> Connect(std::unique_ptr<Socket> sock, std::string* error) {
386*00c7fec1SAndroid Build Coastguard Worker if (sock == nullptr) {
387*00c7fec1SAndroid Build Coastguard Worker // If Socket creation failed |error| is already set.
388*00c7fec1SAndroid Build Coastguard Worker return nullptr;
389*00c7fec1SAndroid Build Coastguard Worker }
390*00c7fec1SAndroid Build Coastguard Worker
391*00c7fec1SAndroid Build Coastguard Worker return UdpTransport::NewTransport(std::move(sock), error);
392*00c7fec1SAndroid Build Coastguard Worker }
393*00c7fec1SAndroid Build Coastguard Worker
394*00c7fec1SAndroid Build Coastguard Worker } // namespace internal
395*00c7fec1SAndroid Build Coastguard Worker
396*00c7fec1SAndroid Build Coastguard Worker } // namespace udp
397