blob: a136226aace5d5f3b1e4a1b946879fda99fa2a0f [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 Vyalov6e181cf2016-06-30 18:10:27 +000011#include "AdbClient.h"
12
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000013#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/STLExtras.h"
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000016#include "llvm/Support/FileUtilities.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000017
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +000018#include "lldb/Core/DataBuffer.h"
19#include "lldb/Core/DataBufferHeap.h"
20#include "lldb/Core/DataEncoder.h"
21#include "lldb/Core/DataExtractor.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Host/ConnectionFileDescriptor.h"
24#include "lldb/Host/FileSpec.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000025
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000026#include <limits.h>
27
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000028#include <algorithm>
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000029#include <fstream>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000030#include <sstream>
31
Adrian McCarthy1341d4c2016-06-30 20:55:50 +000032// On Windows, transitive dependencies pull in <Windows.h>, which defines a
33// macro that clashes with a method name.
34#ifdef SendMessage
35#undef SendMessage
36#endif
37
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000038using namespace lldb;
39using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000040using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000041
42namespace {
43
Pavel Labath204ef662016-05-16 11:41:36 +000044const std::chrono::seconds kReadTimeout(8);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000045const char * kOKAY = "OKAY";
46const char * kFAIL = "FAIL";
Oleksiy Vyalov6002a312015-06-05 01:32:45 +000047const char * kDATA = "DATA";
48const char * kDONE = "DONE";
49
50const char * kSEND = "SEND";
51const char * kRECV = "RECV";
52const char * kSTAT = "STAT";
53
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000054const size_t kSyncPacketLen = 8;
Robert Flack62efb1f2015-05-27 02:18:50 +000055// Maximum size of a filesync DATA packet.
56const size_t kMaxPushData = 2*1024;
57// Default mode for pushed files.
58const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000059
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +000060const char * kSocketNamespaceAbstract = "localabstract";
61const char * kSocketNamespaceFileSystem = "localfilesystem";
62
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +000063Error
64ReadAllBytes (Connection &conn, void *buffer, size_t size)
65{
66 using namespace std::chrono;
67
68 Error error;
69 ConnectionStatus status;
70 char *read_buffer = static_cast<char*>(buffer);
71
72 auto now = steady_clock::now();
73 const auto deadline = now + kReadTimeout;
74 size_t total_read_bytes = 0;
75 while (total_read_bytes < size && now < deadline)
76 {
77 uint32_t timeout_usec = duration_cast<microseconds>(deadline - now).count();
78 auto read_bytes =
79 conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, timeout_usec, status, &error);
80 if (error.Fail ())
81 return error;
82 total_read_bytes += read_bytes;
83 if (status != eConnectionStatusSuccess)
84 break;
85 now = steady_clock::now();
86 }
87 if (total_read_bytes < size)
88 error = Error("Unable to read requested number of bytes. Connection status: %d.", status);
89 return error;
90}
91
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000092} // namespace
93
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000094Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000095AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000096{
97 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000098 auto error = adb.GetDevices(connect_devices);
99 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000100 return error;
101
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000102 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000103 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000104 if (connect_devices.size() != 1)
105 return Error("Expected a single connected device, got instead %" PRIu64,
106 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000107
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000108 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000109 }
110 else
111 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000112 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
113 if (find_it == connect_devices.end())
114 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000115
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000116 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000117 }
118 return error;
119}
120
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000121AdbClient::AdbClient () {}
122
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000123AdbClient::AdbClient (const std::string &device_id)
124 : m_device_id (device_id)
125{
126}
127
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000128AdbClient::~AdbClient() {}
129
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000130void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000131AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000132{
133 m_device_id = device_id;
134}
135
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000136const std::string&
137AdbClient::GetDeviceID() const
138{
139 return m_device_id;
140}
141
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000142Error
143AdbClient::Connect ()
144{
145 Error error;
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000146 m_conn.reset (new ConnectionFileDescriptor);
147 m_conn->Connect ("connect://localhost:5037", &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000148
149 return error;
150}
151
152Error
153AdbClient::GetDevices (DeviceIDList &device_list)
154{
155 device_list.clear ();
156
157 auto error = SendMessage ("host:devices");
158 if (error.Fail ())
159 return error;
160
161 error = ReadResponseStatus ();
162 if (error.Fail ())
163 return error;
164
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000165 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000166 error = ReadMessage (in_buffer);
167
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000168 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000169 llvm::SmallVector<llvm::StringRef, 4> devices;
170 response.split (devices, "\n", -1, false);
171
172 for (const auto device: devices)
173 device_list.push_back (device.split ('\t').first);
174
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000175 // Force disconnect since ADB closes connection after host:devices
176 // response is sent.
177 m_conn.reset ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000178 return error;
179}
180
181Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000182AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000183{
184 char message[48];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000185 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000186
187 const auto error = SendDeviceMessage (message);
188 if (error.Fail ())
189 return error;
190
191 return ReadResponseStatus ();
192}
193
194Error
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000195AdbClient::SetPortForwarding (const uint16_t local_port,
196 const char* remote_socket_name,
197 const UnixSocketNamespace socket_namespace)
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000198{
199 char message[PATH_MAX];
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000200 const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
201 kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
202 snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
203 local_port,
204 sock_namespace_str,
205 remote_socket_name);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000206
207 const auto error = SendDeviceMessage (message);
208 if (error.Fail ())
209 return error;
210
211 return ReadResponseStatus ();
212}
213
214Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000215AdbClient::DeletePortForwarding (const uint16_t local_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000216{
217 char message[32];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000218 snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000219
220 const auto error = SendDeviceMessage (message);
221 if (error.Fail ())
222 return error;
223
224 return ReadResponseStatus ();
225}
226
227Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000228AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000229{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000230 Error error;
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000231 if (!m_conn || reconnect)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000232 {
233 error = Connect ();
234 if (error.Fail ())
235 return error;
236 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000237
238 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000239 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000240
241 ConnectionStatus status;
242
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000243 m_conn->Write (length_buffer, 4, status, &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000244 if (error.Fail ())
245 return error;
246
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000247 m_conn->Write (packet.c_str (), packet.size (), status, &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000248 return error;
249}
250
251Error
252AdbClient::SendDeviceMessage (const std::string &packet)
253{
254 std::ostringstream msg;
255 msg << "host-serial:" << m_device_id << ":" << packet;
256 return SendMessage (msg.str ());
257}
258
259Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000260AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000261{
262 message.clear ();
263
264 char buffer[5];
265 buffer[4] = 0;
266
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000267 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000268 if (error.Fail ())
269 return error;
270
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000271 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000272 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000273
274 message.resize (packet_len, 0);
275 error = ReadAllBytes (&message[0], packet_len);
276 if (error.Fail ())
277 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000278
279 return error;
280}
281
282Error
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000283AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
284{
285 auto start = std::chrono::steady_clock::now();
286 message.clear();
287
288 Error error;
289 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
290 char buffer[1024];
291 while (error.Success() && status == lldb::eConnectionStatusSuccess)
292 {
293 auto end = std::chrono::steady_clock::now();
294 uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
295 if (elapsed_time >= timeout_ms)
296 return Error("Timed out");
297
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000298 size_t n = m_conn->Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error);
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000299 if (n > 0)
300 message.insert(message.end(), &buffer[0], &buffer[n]);
301 }
302 return error;
303}
304
305Error
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000306AdbClient::ReadResponseStatus()
307{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000308 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000309
310 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000311 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000312
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000313 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000314 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000315 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000316
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000317 if (strncmp (response_id, kOKAY, packet_len) != 0)
318 return GetResponseError (response_id);
319
320 return error;
321}
322
323Error
324AdbClient::GetResponseError (const char *response_id)
325{
326 if (strcmp (response_id, kFAIL) != 0)
327 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
328
329 std::vector<char> error_message;
330 auto error = ReadMessage (error_message);
331 if (error.Success ())
332 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
333
334 return error;
335}
336
337Error
338AdbClient::SwitchDeviceTransport ()
339{
340 std::ostringstream msg;
341 msg << "host:transport:" << m_device_id;
342
343 auto error = SendMessage (msg.str ());
344 if (error.Fail ())
345 return error;
346
347 return ReadResponseStatus ();
348}
349
350Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000351AdbClient::StartSync ()
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000352{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000353 auto error = SwitchDeviceTransport ();
354 if (error.Fail ())
355 return Error ("Failed to switch to device transport: %s", error.AsCString ());
356
357 error = Sync ();
358 if (error.Fail ())
359 return Error ("Sync failed: %s", error.AsCString ());
360
361 return error;
362}
363
364Error
365AdbClient::Sync ()
366{
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000367 auto error = SendMessage ("sync:", false);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000368 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000369 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000370
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000371 return ReadResponseStatus ();
372}
373
374Error
375AdbClient::ReadAllBytes (void *buffer, size_t size)
376{
377 return ::ReadAllBytes (*m_conn, buffer, size);
378}
379
380Error
381AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
382{
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000383 auto error = SwitchDeviceTransport ();
384 if (error.Fail ())
385 return Error ("Failed to switch to device transport: %s", error.AsCString ());
386
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000387 StreamString adb_command;
388 adb_command.Printf("shell:%s", command);
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000389 error = SendMessage (adb_command.GetData(), false);
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000390 if (error.Fail ())
391 return error;
392
393 error = ReadResponseStatus ();
394 if (error.Fail ())
395 return error;
396
397 std::vector<char> in_buffer;
398 error = ReadMessageStream (in_buffer, timeout_ms);
399 if (error.Fail())
400 return error;
401
402 if (output)
403 output->assign(in_buffer.begin(), in_buffer.end());
404 return error;
405}
406
407std::unique_ptr<AdbClient::SyncService>
408AdbClient::GetSyncService (Error &error)
409{
410 std::unique_ptr<SyncService> sync_service;
411 error = StartSync ();
412 if (error.Success ())
413 sync_service.reset (new SyncService(std::move(m_conn)));
414
415 return sync_service;
416}
417
418Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000419AdbClient::SyncService::internalPullFile (const FileSpec &remote_file, const FileSpec &local_file)
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000420{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000421 const auto local_file_path = local_file.GetPath ();
422 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000423
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000424 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000425 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000426 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000427
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000428 const auto remote_file_path = remote_file.GetPath (false);
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000429 auto error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000430 if (error.Fail ())
431 return error;
432
433 std::vector<char> chunk;
434 bool eof = false;
435 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000436 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000437 error = PullFileChunk (chunk, eof);
438 if (error.Fail ())
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000439 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000440 if (!eof)
441 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000442 }
443
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000444 local_file_remover.releaseFile ();
445 return error;
446}
447
448Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000449AdbClient::SyncService::internalPushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000450{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000451 const auto local_file_path (local_file.GetPath ());
452 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000453 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000454 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000455
456 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000457 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000458 std::string file_description_str = file_description.str();
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000459 auto error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000460 if (error.Fail ())
461 return error;
462
463 char chunk[kMaxPushData];
464 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
465 {
466 size_t chunk_size = src.gcount();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000467 error = SendSyncRequest(kDATA, chunk_size, chunk);
Robert Flack62efb1f2015-05-27 02:18:50 +0000468 if (error.Fail ())
469 return Error ("Failed to send file chunk: %s", error.AsCString ());
470 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000471 error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000472 if (error.Fail ())
473 return error;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000474
475 std::string response_id;
Jason Molendad10f6aa2015-10-28 23:31:03 +0000476 uint32_t data_len;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000477 error = ReadSyncHeader (response_id, data_len);
478 if (error.Fail ())
479 return Error ("Failed to read DONE response: %s", error.AsCString ());
480 if (response_id == kFAIL)
481 {
482 std::string error_message (data_len, 0);
483 error = ReadAllBytes (&error_message[0], data_len);
484 if (error.Fail ())
485 return Error ("Failed to read DONE error message: %s", error.AsCString ());
486 return Error ("Failed to push file: %s", error_message.c_str ());
487 }
488 else if (response_id != kOKAY)
489 return Error ("Got unexpected DONE response: %s", response_id.c_str ());
490
Robert Flack62efb1f2015-05-27 02:18:50 +0000491 // If there was an error reading the source file, finish the adb file
492 // transfer first so that adb isn't expecting any more data.
493 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000494 return Error ("Failed read on %s", local_file_path.c_str());
495 return error;
496}
497
498Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000499AdbClient::SyncService::internalStat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000500{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000501 const std::string remote_file_path (remote_file.GetPath (false));
502 auto error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000503 if (error.Fail ())
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000504 return Error ("Failed to send request: %s", error.AsCString ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000505
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000506 static const size_t stat_len = strlen (kSTAT);
507 static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
508
509 std::vector<char> buffer (response_len);
510 error = ReadAllBytes (&buffer[0], buffer.size ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000511 if (error.Fail ())
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000512 return Error ("Failed to read response: %s", error.AsCString ());
513
514 DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
515 offset_t offset = 0;
516
517 const void* command = extractor.GetData (&offset, stat_len);
518 if (!command)
519 return Error ("Failed to get response command");
520 const char* command_str = static_cast<const char*> (command);
521 if (strncmp (command_str, kSTAT, stat_len))
522 return Error ("Got invalid stat command: %s", command_str);
523
524 mode = extractor.GetU32 (&offset);
525 size = extractor.GetU32 (&offset);
526 mtime = extractor.GetU32 (&offset);
527 return Error ();
528}
529
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000530Error
531AdbClient::SyncService::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
532{
533 return executeCommand ([this, &remote_file, &local_file]() {
534 return internalPullFile (remote_file, local_file);
535 });
536}
537
538Error
539AdbClient::SyncService::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
540{
541 return executeCommand ([this, &local_file, &remote_file]() {
542 return internalPushFile (local_file, remote_file);
543 });
544}
545
546Error
547AdbClient::SyncService::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
548{
549 return executeCommand ([this, &remote_file, &mode, &size, &mtime]() {
550 return internalStat (remote_file, mode, size, mtime);
551 });
552}
553
554bool
555AdbClient::SyncService::IsConnected () const
556{
557 return m_conn && m_conn->IsConnected ();
558}
559
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000560AdbClient::SyncService::SyncService(std::unique_ptr<Connection> &&conn):
561m_conn(std::move(conn))
562{
563}
564
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000565Error
566AdbClient::SyncService::executeCommand (const std::function<Error()> &cmd)
567{
568 if (!m_conn)
569 return Error ("SyncService is disconnected");
570
571 const auto error = cmd ();
572 if (error.Fail ())
573 m_conn.reset ();
574
575 return error;
576}
577
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000578AdbClient::SyncService::~SyncService () {}
579
580Error
581AdbClient::SyncService::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
582{
583 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
584 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
585 auto offset = encoder.PutData (0, request_id, strlen(request_id));
586 encoder.PutU32 (offset, data_len);
587
588 Error error;
589 ConnectionStatus status;
590 m_conn->Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
591 if (error.Fail ())
592 return error;
593
594 if (data)
595 m_conn->Write (data, data_len, status, &error);
596 return error;
597}
598
599Error
600AdbClient::SyncService::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
601{
602 char buffer[kSyncPacketLen];
603
604 auto error = ReadAllBytes (buffer, kSyncPacketLen);
605 if (error.Success ())
606 {
607 response_id.assign (&buffer[0], 4);
608 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
609 offset_t offset = 0;
610 data_len = extractor.GetU32 (&offset);
611 }
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000612
Robert Flack62efb1f2015-05-27 02:18:50 +0000613 return error;
614}
615
616Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000617AdbClient::SyncService::PullFileChunk (std::vector<char> &buffer, bool &eof)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000618{
619 buffer.clear ();
620
621 std::string response_id;
622 uint32_t data_len;
623 auto error = ReadSyncHeader (response_id, data_len);
624 if (error.Fail ())
625 return error;
626
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000627 if (response_id == kDATA)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000628 {
629 buffer.resize (data_len, 0);
630 error = ReadAllBytes (&buffer[0], data_len);
631 if (error.Fail ())
632 buffer.clear ();
633 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000634 else if (response_id == kDONE)
635 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000636 eof = true;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000637 }
638 else if (response_id == kFAIL)
639 {
640 std::string error_message (data_len, 0);
641 error = ReadAllBytes (&error_message[0], data_len);
642 if (error.Fail ())
643 return Error ("Failed to read pull error message: %s", error.AsCString ());
644 return Error ("Failed to pull file: %s", error_message.c_str ());
645 }
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000646 else
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000647 return Error ("Pull failed with unknown response: %s", response_id.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000648
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000649 return Error ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000650}
651
652Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000653AdbClient::SyncService::ReadAllBytes (void *buffer, size_t size)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000654{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000655 return ::ReadAllBytes (*m_conn, buffer, size);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000656}
657