blob: 2e574bcbe949a3dcaa74abe2d7064fd3dee7e17a [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"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000015#include "llvm/ADT/SmallVector.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/ADT/STLExtras.h"
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000018#include "llvm/Support/FileUtilities.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000019
20// Project includes
21#include "AdbClient.h"
22
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000023#include <limits.h>
24
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000025#include <algorithm>
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000026#include <fstream>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000027#include <sstream>
28
29using namespace lldb;
30using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000031using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000032
33namespace {
34
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000035const uint32_t kReadTimeout = 1000000; // 1 second
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000036const char * kOKAY = "OKAY";
37const char * kFAIL = "FAIL";
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000038const size_t kSyncPacketLen = 8;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000039
40} // namespace
41
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000042Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000043AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000044{
45 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000046 auto error = adb.GetDevices(connect_devices);
47 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000048 return error;
49
Chaoren Lin3ea689b2015-05-01 16:49:28 +000050 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000051 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000052 if (connect_devices.size() != 1)
53 return Error("Expected a single connected device, got instead %" PRIu64,
54 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000055
Chaoren Lin3ea689b2015-05-01 16:49:28 +000056 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000057 }
58 else
59 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000060 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
61 if (find_it == connect_devices.end())
62 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000063
Chaoren Lin3ea689b2015-05-01 16:49:28 +000064 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000065 }
66 return error;
67}
68
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000069AdbClient::AdbClient (const std::string &device_id)
70 : m_device_id (device_id)
71{
72}
73
74void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000075AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000076{
77 m_device_id = device_id;
78}
79
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000080const std::string&
81AdbClient::GetDeviceID() const
82{
83 return m_device_id;
84}
85
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000086Error
87AdbClient::Connect ()
88{
89 Error error;
90 m_conn.Connect ("connect://localhost:5037", &error);
91
92 return error;
93}
94
95Error
96AdbClient::GetDevices (DeviceIDList &device_list)
97{
98 device_list.clear ();
99
100 auto error = SendMessage ("host:devices");
101 if (error.Fail ())
102 return error;
103
104 error = ReadResponseStatus ();
105 if (error.Fail ())
106 return error;
107
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000108 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000109 error = ReadMessage (in_buffer);
110
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000111 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000112 llvm::SmallVector<llvm::StringRef, 4> devices;
113 response.split (devices, "\n", -1, false);
114
115 for (const auto device: devices)
116 device_list.push_back (device.split ('\t').first);
117
118 return error;
119}
120
121Error
122AdbClient::SetPortForwarding (const uint16_t port)
123{
124 char message[48];
125 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
126
127 const auto error = SendDeviceMessage (message);
128 if (error.Fail ())
129 return error;
130
131 return ReadResponseStatus ();
132}
133
134Error
135AdbClient::DeletePortForwarding (const uint16_t port)
136{
137 char message[32];
138 snprintf (message, sizeof (message), "killforward:tcp:%d", port);
139
140 const auto error = SendDeviceMessage (message);
141 if (error.Fail ())
142 return error;
143
144 return ReadResponseStatus ();
145}
146
147Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000148AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000149{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000150 Error error;
151 if (reconnect)
152 {
153 error = Connect ();
154 if (error.Fail ())
155 return error;
156 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000157
158 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000159 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000160
161 ConnectionStatus status;
162
163 m_conn.Write (length_buffer, 4, status, &error);
164 if (error.Fail ())
165 return error;
166
167 m_conn.Write (packet.c_str (), packet.size (), status, &error);
168 return error;
169}
170
171Error
172AdbClient::SendDeviceMessage (const std::string &packet)
173{
174 std::ostringstream msg;
175 msg << "host-serial:" << m_device_id << ":" << packet;
176 return SendMessage (msg.str ());
177}
178
179Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000180AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000181{
182 message.clear ();
183
184 char buffer[5];
185 buffer[4] = 0;
186
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000187 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000188 if (error.Fail ())
189 return error;
190
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000191 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000192 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000193
194 message.resize (packet_len, 0);
195 error = ReadAllBytes (&message[0], packet_len);
196 if (error.Fail ())
197 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000198
199 return error;
200}
201
202Error
203AdbClient::ReadResponseStatus()
204{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000205 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000206
207 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000208 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000209
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000210 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000211 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000212 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000213
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000214 if (strncmp (response_id, kOKAY, packet_len) != 0)
215 return GetResponseError (response_id);
216
217 return error;
218}
219
220Error
221AdbClient::GetResponseError (const char *response_id)
222{
223 if (strcmp (response_id, kFAIL) != 0)
224 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
225
226 std::vector<char> error_message;
227 auto error = ReadMessage (error_message);
228 if (error.Success ())
229 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
230
231 return error;
232}
233
234Error
235AdbClient::SwitchDeviceTransport ()
236{
237 std::ostringstream msg;
238 msg << "host:transport:" << m_device_id;
239
240 auto error = SendMessage (msg.str ());
241 if (error.Fail ())
242 return error;
243
244 return ReadResponseStatus ();
245}
246
247Error
248AdbClient::PullFile (const char *remote_file, const char *local_file)
249{
250 auto error = SwitchDeviceTransport ();
251 if (error.Fail ())
252 return Error ("Failed to switch to device transport: %s", error.AsCString ());
253
254 error = Sync ();
255 if (error.Fail ())
256 return Error ("Sync failed: %s", error.AsCString ());
257
258 llvm::FileRemover local_file_remover (local_file);
259
260 std::ofstream dst (local_file, std::ios::out | std::ios::binary);
261 if (!dst.is_open ())
262 return Error ("Unable to open local file %s", local_file);
263
264 error = SendSyncRequest ("RECV", strlen(remote_file), remote_file);
265 if (error.Fail ())
266 return error;
267
268 std::vector<char> chunk;
269 bool eof = false;
270 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000271 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000272 error = PullFileChunk (chunk, eof);
273 if (error.Fail ())
274 return Error ("Failed to read file chunk: %s", error.AsCString ());
275 if (!eof)
276 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000277 }
278
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000279 local_file_remover.releaseFile ();
280 return error;
281}
282
283Error
284AdbClient::Sync ()
285{
286 auto error = SendMessage ("sync:", false);
287 if (error.Fail ())
288 return error;
289
290 return ReadResponseStatus ();
291}
292
293Error
294AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
295{
296 buffer.clear ();
297
298 std::string response_id;
299 uint32_t data_len;
300 auto error = ReadSyncHeader (response_id, data_len);
301 if (error.Fail ())
302 return error;
303
304 if (response_id == "DATA")
305 {
306 buffer.resize (data_len, 0);
307 error = ReadAllBytes (&buffer[0], data_len);
308 if (error.Fail ())
309 buffer.clear ();
310 }
311 else if (response_id == "DONE")
312 eof = true;
313 else
314 error = GetResponseError (response_id.c_str ());
315
316 return error;
317}
318
319Error
320AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
321{
322 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
323 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
324 auto offset = encoder.PutData (0, request_id, strlen(request_id));
325 encoder.PutU32 (offset, data_len);
326
327 Error error;
328 ConnectionStatus status;
329 m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
330 if (error.Fail ())
331 return error;
332
333 m_conn.Write (data, data_len, status, &error);
334 return error;
335}
336
337Error
338AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
339{
340 char buffer[kSyncPacketLen];
341
342 auto error = ReadAllBytes (buffer, kSyncPacketLen);
343 if (error.Success ())
344 {
345 response_id.assign (&buffer[0], 4);
346 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
347 offset_t offset = 0;
348 data_len = extractor.GetU32 (&offset);
349 }
350
351 return error;
352}
353
354Error
355AdbClient::ReadAllBytes (void *buffer, size_t size)
356{
357 Error error;
358 ConnectionStatus status;
359 char *read_buffer = static_cast<char*>(buffer);
360
361 size_t tota_read_bytes = 0;
362 while (tota_read_bytes < size)
363 {
364 auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
365 if (error.Fail ())
366 return error;
367 tota_read_bytes += read_bytes;
368 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000369 return error;
370}