blob: 27e21695be80cc89efb6db55c7bacfc465b92e61 [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
253AdbClient::PullFile (const char *remote_file, const char *local_file)
254{
255 auto error = SwitchDeviceTransport ();
256 if (error.Fail ())
257 return Error ("Failed to switch to device transport: %s", error.AsCString ());
258
259 error = Sync ();
260 if (error.Fail ())
261 return Error ("Sync failed: %s", error.AsCString ());
262
263 llvm::FileRemover local_file_remover (local_file);
264
265 std::ofstream dst (local_file, std::ios::out | std::ios::binary);
266 if (!dst.is_open ())
267 return Error ("Unable to open local file %s", local_file);
268
269 error = SendSyncRequest ("RECV", strlen(remote_file), remote_file);
270 if (error.Fail ())
271 return error;
272
273 std::vector<char> chunk;
274 bool eof = false;
275 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000276 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000277 error = PullFileChunk (chunk, eof);
278 if (error.Fail ())
279 return Error ("Failed to read file chunk: %s", error.AsCString ());
280 if (!eof)
281 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000282 }
283
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000284 local_file_remover.releaseFile ();
285 return error;
286}
287
288Error
Robert Flack62efb1f2015-05-27 02:18:50 +0000289AdbClient::PushFile (const lldb_private::FileSpec& source, const lldb_private::FileSpec& destination)
290{
291 auto error = SwitchDeviceTransport ();
292 if (error.Fail ())
293 return Error ("Failed to switch to device transport: %s", error.AsCString ());
294
295 error = Sync ();
296 if (error.Fail ())
297 return Error ("Sync failed: %s", error.AsCString ());
298
299 std::ifstream src (source.GetPath().c_str(), std::ios::in | std::ios::binary);
300 if (!src.is_open ())
301 return Error ("Unable to open local file %s", source.GetPath().c_str());
302
303 std::stringstream file_description;
304 file_description << destination.GetPath(false).c_str() << "," << kDefaultMode;
305 std::string file_description_str = file_description.str();
306 error = SendSyncRequest ("SEND", file_description_str.length(), file_description_str.c_str());
307 if (error.Fail ())
308 return error;
309
310 char chunk[kMaxPushData];
311 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
312 {
313 size_t chunk_size = src.gcount();
314 error = SendSyncRequest("DATA", chunk_size, chunk);
315 if (error.Fail ())
316 return Error ("Failed to send file chunk: %s", error.AsCString ());
317 }
318 error = SendSyncRequest("DONE", source.GetModificationTime().seconds(), nullptr);
319 if (error.Fail ())
320 return error;
321 error = ReadResponseStatus();
322 // If there was an error reading the source file, finish the adb file
323 // transfer first so that adb isn't expecting any more data.
324 if (src.bad())
325 return Error ("Failed read on %s", source.GetPath().c_str());
326 return error;
327}
328
329Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000330AdbClient::Sync ()
331{
332 auto error = SendMessage ("sync:", false);
333 if (error.Fail ())
334 return error;
335
336 return ReadResponseStatus ();
337}
338
339Error
340AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
341{
342 buffer.clear ();
343
344 std::string response_id;
345 uint32_t data_len;
346 auto error = ReadSyncHeader (response_id, data_len);
347 if (error.Fail ())
348 return error;
349
350 if (response_id == "DATA")
351 {
352 buffer.resize (data_len, 0);
353 error = ReadAllBytes (&buffer[0], data_len);
354 if (error.Fail ())
355 buffer.clear ();
356 }
357 else if (response_id == "DONE")
358 eof = true;
359 else
360 error = GetResponseError (response_id.c_str ());
361
362 return error;
363}
364
365Error
366AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
367{
368 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
369 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
370 auto offset = encoder.PutData (0, request_id, strlen(request_id));
371 encoder.PutU32 (offset, data_len);
372
373 Error error;
374 ConnectionStatus status;
375 m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
376 if (error.Fail ())
377 return error;
378
Robert Flack62efb1f2015-05-27 02:18:50 +0000379 if (data)
380 m_conn.Write (data, data_len, status, &error);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000381 return error;
382}
383
384Error
385AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
386{
387 char buffer[kSyncPacketLen];
388
389 auto error = ReadAllBytes (buffer, kSyncPacketLen);
390 if (error.Success ())
391 {
392 response_id.assign (&buffer[0], 4);
393 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
394 offset_t offset = 0;
395 data_len = extractor.GetU32 (&offset);
396 }
397
398 return error;
399}
400
401Error
402AdbClient::ReadAllBytes (void *buffer, size_t size)
403{
404 Error error;
405 ConnectionStatus status;
406 char *read_buffer = static_cast<char*>(buffer);
407
408 size_t tota_read_bytes = 0;
409 while (tota_read_bytes < size)
410 {
411 auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
412 if (error.Fail ())
413 return error;
414 tota_read_bytes += read_bytes;
415 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000416 return error;
417}