blob: 3c154463c7babb38c92165368f2b7f3b52938f17 [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 Vyalov09e9079d2015-05-18 23:44:06 +000039const size_t kSyncPacketLen = 8;
Robert Flack62efb1f2015-05-27 02:18:50 +000040// Maximum size of a filesync DATA packet.
41const size_t kMaxPushData = 2*1024;
42// Default mode for pushed files.
43const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000044
45} // namespace
46
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000047Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000048AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000049{
50 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000051 auto error = adb.GetDevices(connect_devices);
52 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000053 return error;
54
Chaoren Lin3ea689b2015-05-01 16:49:28 +000055 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000056 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000057 if (connect_devices.size() != 1)
58 return Error("Expected a single connected device, got instead %" PRIu64,
59 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000060
Chaoren Lin3ea689b2015-05-01 16:49:28 +000061 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000062 }
63 else
64 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000065 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
66 if (find_it == connect_devices.end())
67 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000068
Chaoren Lin3ea689b2015-05-01 16:49:28 +000069 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000070 }
71 return error;
72}
73
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000074AdbClient::AdbClient (const std::string &device_id)
75 : m_device_id (device_id)
76{
77}
78
79void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000080AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000081{
82 m_device_id = device_id;
83}
84
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000085const std::string&
86AdbClient::GetDeviceID() const
87{
88 return m_device_id;
89}
90
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000091Error
92AdbClient::Connect ()
93{
94 Error error;
95 m_conn.Connect ("connect://localhost:5037", &error);
96
97 return error;
98}
99
100Error
101AdbClient::GetDevices (DeviceIDList &device_list)
102{
103 device_list.clear ();
104
105 auto error = SendMessage ("host:devices");
106 if (error.Fail ())
107 return error;
108
109 error = ReadResponseStatus ();
110 if (error.Fail ())
111 return error;
112
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000113 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000114 error = ReadMessage (in_buffer);
115
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000116 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000117 llvm::SmallVector<llvm::StringRef, 4> devices;
118 response.split (devices, "\n", -1, false);
119
120 for (const auto device: devices)
121 device_list.push_back (device.split ('\t').first);
122
123 return error;
124}
125
126Error
127AdbClient::SetPortForwarding (const uint16_t port)
128{
129 char message[48];
130 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
131
132 const auto error = SendDeviceMessage (message);
133 if (error.Fail ())
134 return error;
135
136 return ReadResponseStatus ();
137}
138
139Error
140AdbClient::DeletePortForwarding (const uint16_t port)
141{
142 char message[32];
143 snprintf (message, sizeof (message), "killforward:tcp:%d", port);
144
145 const auto error = SendDeviceMessage (message);
146 if (error.Fail ())
147 return error;
148
149 return ReadResponseStatus ();
150}
151
152Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000153AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000154{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000155 Error error;
156 if (reconnect)
157 {
158 error = Connect ();
159 if (error.Fail ())
160 return error;
161 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000162
163 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000164 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000165
166 ConnectionStatus status;
167
168 m_conn.Write (length_buffer, 4, status, &error);
169 if (error.Fail ())
170 return error;
171
172 m_conn.Write (packet.c_str (), packet.size (), status, &error);
173 return error;
174}
175
176Error
177AdbClient::SendDeviceMessage (const std::string &packet)
178{
179 std::ostringstream msg;
180 msg << "host-serial:" << m_device_id << ":" << packet;
181 return SendMessage (msg.str ());
182}
183
184Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000185AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000186{
187 message.clear ();
188
189 char buffer[5];
190 buffer[4] = 0;
191
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000192 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000193 if (error.Fail ())
194 return error;
195
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000196 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000197 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000198
199 message.resize (packet_len, 0);
200 error = ReadAllBytes (&message[0], packet_len);
201 if (error.Fail ())
202 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000203
204 return error;
205}
206
207Error
208AdbClient::ReadResponseStatus()
209{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000210 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000211
212 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000213 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000214
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000215 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000216 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000217 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000218
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000219 if (strncmp (response_id, kOKAY, packet_len) != 0)
220 return GetResponseError (response_id);
221
222 return error;
223}
224
225Error
226AdbClient::GetResponseError (const char *response_id)
227{
228 if (strcmp (response_id, kFAIL) != 0)
229 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
230
231 std::vector<char> error_message;
232 auto error = ReadMessage (error_message);
233 if (error.Success ())
234 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
235
236 return error;
237}
238
239Error
240AdbClient::SwitchDeviceTransport ()
241{
242 std::ostringstream msg;
243 msg << "host:transport:" << m_device_id;
244
245 auto error = SendMessage (msg.str ());
246 if (error.Fail ())
247 return error;
248
249 return ReadResponseStatus ();
250}
251
252Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000253AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000254{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000255 auto error = StartSync ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000256 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000257 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000258
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000259 const auto local_file_path = local_file.GetPath ();
260 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000261
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000262 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000263 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000264 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000265
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000266 const auto remote_file_path = remote_file.GetPath (false);
267 error = SendSyncRequest ("RECV", remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000268 if (error.Fail ())
269 return error;
270
271 std::vector<char> chunk;
272 bool eof = false;
273 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000274 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000275 error = PullFileChunk (chunk, eof);
276 if (error.Fail ())
277 return Error ("Failed to read file chunk: %s", error.AsCString ());
278 if (!eof)
279 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000280 }
281
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000282 local_file_remover.releaseFile ();
283 return error;
284}
285
286Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000287AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000288{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000289 auto error = StartSync ();
Robert Flack62efb1f2015-05-27 02:18:50 +0000290 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000291 return error;
Robert Flack62efb1f2015-05-27 02:18:50 +0000292
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000293 const auto local_file_path (local_file.GetPath ());
294 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000295 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000296 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000297
298 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000299 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000300 std::string file_description_str = file_description.str();
301 error = SendSyncRequest ("SEND", file_description_str.length(), file_description_str.c_str());
302 if (error.Fail ())
303 return error;
304
305 char chunk[kMaxPushData];
306 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
307 {
308 size_t chunk_size = src.gcount();
309 error = SendSyncRequest("DATA", chunk_size, chunk);
310 if (error.Fail ())
311 return Error ("Failed to send file chunk: %s", error.AsCString ());
312 }
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000313 error = SendSyncRequest("DONE", local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000314 if (error.Fail ())
315 return error;
316 error = ReadResponseStatus();
317 // If there was an error reading the source file, finish the adb file
318 // transfer first so that adb isn't expecting any more data.
319 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000320 return Error ("Failed read on %s", local_file_path.c_str());
321 return error;
322}
323
324Error
325AdbClient::StartSync ()
326{
327 auto error = SwitchDeviceTransport ();
328 if (error.Fail ())
329 return Error ("Failed to switch to device transport: %s", error.AsCString ());
330
331 error = Sync ();
332 if (error.Fail ())
333 return Error ("Sync failed: %s", error.AsCString ());
334
Robert Flack62efb1f2015-05-27 02:18:50 +0000335 return error;
336}
337
338Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000339AdbClient::Sync ()
340{
341 auto error = SendMessage ("sync:", false);
342 if (error.Fail ())
343 return error;
344
345 return ReadResponseStatus ();
346}
347
348Error
349AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
350{
351 buffer.clear ();
352
353 std::string response_id;
354 uint32_t data_len;
355 auto error = ReadSyncHeader (response_id, data_len);
356 if (error.Fail ())
357 return error;
358
359 if (response_id == "DATA")
360 {
361 buffer.resize (data_len, 0);
362 error = ReadAllBytes (&buffer[0], data_len);
363 if (error.Fail ())
364 buffer.clear ();
365 }
366 else if (response_id == "DONE")
367 eof = true;
368 else
369 error = GetResponseError (response_id.c_str ());
370
371 return error;
372}
373
374Error
375AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
376{
377 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
378 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
379 auto offset = encoder.PutData (0, request_id, strlen(request_id));
380 encoder.PutU32 (offset, data_len);
381
382 Error error;
383 ConnectionStatus status;
384 m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
385 if (error.Fail ())
386 return error;
387
Robert Flack62efb1f2015-05-27 02:18:50 +0000388 if (data)
389 m_conn.Write (data, data_len, status, &error);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000390 return error;
391}
392
393Error
394AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
395{
396 char buffer[kSyncPacketLen];
397
398 auto error = ReadAllBytes (buffer, kSyncPacketLen);
399 if (error.Success ())
400 {
401 response_id.assign (&buffer[0], 4);
402 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
403 offset_t offset = 0;
404 data_len = extractor.GetU32 (&offset);
405 }
406
407 return error;
408}
409
410Error
411AdbClient::ReadAllBytes (void *buffer, size_t size)
412{
413 Error error;
414 ConnectionStatus status;
415 char *read_buffer = static_cast<char*>(buffer);
416
417 size_t tota_read_bytes = 0;
418 while (tota_read_bytes < size)
419 {
420 auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
421 if (error.Fail ())
422 return error;
423 tota_read_bytes += read_bytes;
424 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000425 return error;
426}