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