blob: 2d73abdfa99f8934ab08f18844eeb894ebb588fd [file] [log] [blame]
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +00001//===-- AdbClient.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Other libraries and framework includes
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000011#include "lldb/Core/DataBuffer.h"
12#include "lldb/Core/DataBufferHeap.h"
13#include "lldb/Core/DataEncoder.h"
14#include "lldb/Core/DataExtractor.h"
Robert Flack62efb1f2015-05-27 02:18:50 +000015#include "lldb/Host/FileSpec.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000016#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/STLExtras.h"
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000019#include "llvm/Support/FileUtilities.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000020
21// Project includes
22#include "AdbClient.h"
23
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000024#include <limits.h>
25
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000026#include <algorithm>
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000027#include <fstream>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000028#include <sstream>
29
30using namespace lldb;
31using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000032using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000033
34namespace {
35
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000036const uint32_t kReadTimeout = 1000000; // 1 second
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000037const char * kOKAY = "OKAY";
38const char * kFAIL = "FAIL";
Oleksiy Vyalov6002a312015-06-05 01:32:45 +000039const char * kDATA = "DATA";
40const char * kDONE = "DONE";
41
42const char * kSEND = "SEND";
43const char * kRECV = "RECV";
44const char * kSTAT = "STAT";
45
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000046const size_t kSyncPacketLen = 8;
Robert Flack62efb1f2015-05-27 02:18:50 +000047// Maximum size of a filesync DATA packet.
48const size_t kMaxPushData = 2*1024;
49// Default mode for pushed files.
50const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000051
52} // namespace
53
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000054Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000055AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000056{
57 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000058 auto error = adb.GetDevices(connect_devices);
59 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000060 return error;
61
Chaoren Lin3ea689b2015-05-01 16:49:28 +000062 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000063 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000064 if (connect_devices.size() != 1)
65 return Error("Expected a single connected device, got instead %" PRIu64,
66 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000067
Chaoren Lin3ea689b2015-05-01 16:49:28 +000068 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000069 }
70 else
71 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000072 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
73 if (find_it == connect_devices.end())
74 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000075
Chaoren Lin3ea689b2015-05-01 16:49:28 +000076 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000077 }
78 return error;
79}
80
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000081AdbClient::AdbClient (const std::string &device_id)
82 : m_device_id (device_id)
83{
84}
85
86void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000087AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000088{
89 m_device_id = device_id;
90}
91
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000092const std::string&
93AdbClient::GetDeviceID() const
94{
95 return m_device_id;
96}
97
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000098Error
99AdbClient::Connect ()
100{
101 Error error;
102 m_conn.Connect ("connect://localhost:5037", &error);
103
104 return error;
105}
106
107Error
108AdbClient::GetDevices (DeviceIDList &device_list)
109{
110 device_list.clear ();
111
112 auto error = SendMessage ("host:devices");
113 if (error.Fail ())
114 return error;
115
116 error = ReadResponseStatus ();
117 if (error.Fail ())
118 return error;
119
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000120 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000121 error = ReadMessage (in_buffer);
122
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000123 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000124 llvm::SmallVector<llvm::StringRef, 4> devices;
125 response.split (devices, "\n", -1, false);
126
127 for (const auto device: devices)
128 device_list.push_back (device.split ('\t').first);
129
130 return error;
131}
132
133Error
134AdbClient::SetPortForwarding (const uint16_t port)
135{
136 char message[48];
137 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
138
139 const auto error = SendDeviceMessage (message);
140 if (error.Fail ())
141 return error;
142
143 return ReadResponseStatus ();
144}
145
146Error
147AdbClient::DeletePortForwarding (const uint16_t port)
148{
149 char message[32];
150 snprintf (message, sizeof (message), "killforward:tcp:%d", port);
151
152 const auto error = SendDeviceMessage (message);
153 if (error.Fail ())
154 return error;
155
156 return ReadResponseStatus ();
157}
158
159Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000160AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000161{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000162 Error error;
163 if (reconnect)
164 {
165 error = Connect ();
166 if (error.Fail ())
167 return error;
168 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000169
170 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000171 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000172
173 ConnectionStatus status;
174
175 m_conn.Write (length_buffer, 4, status, &error);
176 if (error.Fail ())
177 return error;
178
179 m_conn.Write (packet.c_str (), packet.size (), status, &error);
180 return error;
181}
182
183Error
184AdbClient::SendDeviceMessage (const std::string &packet)
185{
186 std::ostringstream msg;
187 msg << "host-serial:" << m_device_id << ":" << packet;
188 return SendMessage (msg.str ());
189}
190
191Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000192AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000193{
194 message.clear ();
195
196 char buffer[5];
197 buffer[4] = 0;
198
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000199 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000200 if (error.Fail ())
201 return error;
202
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000203 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000204 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000205
206 message.resize (packet_len, 0);
207 error = ReadAllBytes (&message[0], packet_len);
208 if (error.Fail ())
209 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000210
211 return error;
212}
213
214Error
215AdbClient::ReadResponseStatus()
216{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000217 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000218
219 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000220 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000221
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000222 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000223 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000224 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000225
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000226 if (strncmp (response_id, kOKAY, packet_len) != 0)
227 return GetResponseError (response_id);
228
229 return error;
230}
231
232Error
233AdbClient::GetResponseError (const char *response_id)
234{
235 if (strcmp (response_id, kFAIL) != 0)
236 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
237
238 std::vector<char> error_message;
239 auto error = ReadMessage (error_message);
240 if (error.Success ())
241 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
242
243 return error;
244}
245
246Error
247AdbClient::SwitchDeviceTransport ()
248{
249 std::ostringstream msg;
250 msg << "host:transport:" << m_device_id;
251
252 auto error = SendMessage (msg.str ());
253 if (error.Fail ())
254 return error;
255
256 return ReadResponseStatus ();
257}
258
259Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000260AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000261{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000262 auto error = StartSync ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000263 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000264 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000265
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000266 const auto local_file_path = local_file.GetPath ();
267 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000268
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000269 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000270 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000271 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000272
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000273 const auto remote_file_path = remote_file.GetPath (false);
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000274 error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000275 if (error.Fail ())
276 return error;
277
278 std::vector<char> chunk;
279 bool eof = false;
280 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000281 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000282 error = PullFileChunk (chunk, eof);
283 if (error.Fail ())
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000284 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000285 if (!eof)
286 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000287 }
288
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000289 local_file_remover.releaseFile ();
290 return error;
291}
292
293Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000294AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000295{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000296 auto error = StartSync ();
Robert Flack62efb1f2015-05-27 02:18:50 +0000297 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000298 return error;
Robert Flack62efb1f2015-05-27 02:18:50 +0000299
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000300 const auto local_file_path (local_file.GetPath ());
301 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000302 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000303 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000304
305 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000306 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000307 std::string file_description_str = file_description.str();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000308 error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000309 if (error.Fail ())
310 return error;
311
312 char chunk[kMaxPushData];
313 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
314 {
315 size_t chunk_size = src.gcount();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000316 error = SendSyncRequest(kDATA, chunk_size, chunk);
Robert Flack62efb1f2015-05-27 02:18:50 +0000317 if (error.Fail ())
318 return Error ("Failed to send file chunk: %s", error.AsCString ());
319 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000320 error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000321 if (error.Fail ())
322 return error;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000323
324 std::string response_id;
325 uint32_t data_len;
326 error = ReadSyncHeader (response_id, data_len);
327 if (error.Fail ())
328 return Error ("Failed to read DONE response: %s", error.AsCString ());
329 if (response_id == kFAIL)
330 {
331 std::string error_message (data_len, 0);
332 error = ReadAllBytes (&error_message[0], data_len);
333 if (error.Fail ())
334 return Error ("Failed to read DONE error message: %s", error.AsCString ());
335 return Error ("Failed to push file: %s", error_message.c_str ());
336 }
337 else if (response_id != kOKAY)
338 return Error ("Got unexpected DONE response: %s", response_id.c_str ());
339
Robert Flack62efb1f2015-05-27 02:18:50 +0000340 // If there was an error reading the source file, finish the adb file
341 // transfer first so that adb isn't expecting any more data.
342 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000343 return Error ("Failed read on %s", local_file_path.c_str());
344 return error;
345}
346
347Error
348AdbClient::StartSync ()
349{
350 auto error = SwitchDeviceTransport ();
351 if (error.Fail ())
352 return Error ("Failed to switch to device transport: %s", error.AsCString ());
353
354 error = Sync ();
355 if (error.Fail ())
356 return Error ("Sync failed: %s", error.AsCString ());
357
Robert Flack62efb1f2015-05-27 02:18:50 +0000358 return error;
359}
360
361Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000362AdbClient::Sync ()
363{
364 auto error = SendMessage ("sync:", false);
365 if (error.Fail ())
366 return error;
367
368 return ReadResponseStatus ();
369}
370
371Error
372AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
373{
374 buffer.clear ();
375
376 std::string response_id;
377 uint32_t data_len;
378 auto error = ReadSyncHeader (response_id, data_len);
379 if (error.Fail ())
380 return error;
381
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000382 if (response_id == kDATA)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000383 {
384 buffer.resize (data_len, 0);
385 error = ReadAllBytes (&buffer[0], data_len);
386 if (error.Fail ())
387 buffer.clear ();
388 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000389 else if (response_id == kDONE)
390 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000391 eof = true;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000392 }
393 else if (response_id == kFAIL)
394 {
395 std::string error_message (data_len, 0);
396 error = ReadAllBytes (&error_message[0], data_len);
397 if (error.Fail ())
398 return Error ("Failed to read pull error message: %s", error.AsCString ());
399 return Error ("Failed to pull file: %s", error_message.c_str ());
400 }
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000401 else
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000402 return Error ("Pull failed with unknown response: %s", response_id.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000403
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000404 return Error ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000405}
406
407Error
408AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
409{
410 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
411 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
412 auto offset = encoder.PutData (0, request_id, strlen(request_id));
413 encoder.PutU32 (offset, data_len);
414
415 Error error;
416 ConnectionStatus status;
417 m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
418 if (error.Fail ())
419 return error;
420
Robert Flack62efb1f2015-05-27 02:18:50 +0000421 if (data)
422 m_conn.Write (data, data_len, status, &error);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000423 return error;
424}
425
426Error
427AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
428{
429 char buffer[kSyncPacketLen];
430
431 auto error = ReadAllBytes (buffer, kSyncPacketLen);
432 if (error.Success ())
433 {
434 response_id.assign (&buffer[0], 4);
435 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
436 offset_t offset = 0;
437 data_len = extractor.GetU32 (&offset);
438 }
439
440 return error;
441}
442
443Error
444AdbClient::ReadAllBytes (void *buffer, size_t size)
445{
446 Error error;
447 ConnectionStatus status;
448 char *read_buffer = static_cast<char*>(buffer);
449
450 size_t tota_read_bytes = 0;
451 while (tota_read_bytes < size)
452 {
453 auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
454 if (error.Fail ())
455 return error;
456 tota_read_bytes += read_bytes;
457 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000458 return error;
459}
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000460
461Error
462AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
463{
464 auto error = StartSync ();
465 if (error.Fail ())
466 return error;
467
468 const std::string remote_file_path (remote_file.GetPath (false));
469 error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
470 if (error.Fail ())
471 return Error ("Failed to send request: %s", error.AsCString ());
472
473 static const size_t stat_len = strlen (kSTAT);
474 static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
475
476 std::vector<char> buffer (response_len);
477 error = ReadAllBytes (&buffer[0], buffer.size ());
478 if (error.Fail ())
479 return Error ("Failed to read response: %s", error.AsCString ());
480
481 DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
482 offset_t offset = 0;
483
484 const void* command = extractor.GetData (&offset, stat_len);
485 if (!command)
486 return Error ("Failed to get response command");
487 const char* command_str = static_cast<const char*> (command);
488 if (strncmp (command_str, kSTAT, stat_len))
489 return Error ("Got invalid stat command: %s", command_str);
490
491 mode = extractor.GetU32 (&offset);
492 size = extractor.GetU32 (&offset);
493 mtime = extractor.GetU32 (&offset);
494 return Error ();
495}