blob: e7c03df29b32eb32a8eab11a322c30e995cf1d29 [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
Luke Drummond3db04912016-07-07 18:02:44 +000028#include <cstdlib>
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000029#include <algorithm>
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000030#include <fstream>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000031#include <sstream>
32
Adrian McCarthy1341d4c2016-06-30 20:55:50 +000033// On Windows, transitive dependencies pull in <Windows.h>, which defines a
34// macro that clashes with a method name.
35#ifdef SendMessage
36#undef SendMessage
37#endif
38
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000039using namespace lldb;
40using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000041using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000042
43namespace {
44
Pavel Labath204ef662016-05-16 11:41:36 +000045const std::chrono::seconds kReadTimeout(8);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000046const char * kOKAY = "OKAY";
47const char * kFAIL = "FAIL";
Oleksiy Vyalov6002a312015-06-05 01:32:45 +000048const char * kDATA = "DATA";
49const char * kDONE = "DONE";
50
51const char * kSEND = "SEND";
52const char * kRECV = "RECV";
53const char * kSTAT = "STAT";
54
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000055const size_t kSyncPacketLen = 8;
Robert Flack62efb1f2015-05-27 02:18:50 +000056// Maximum size of a filesync DATA packet.
57const size_t kMaxPushData = 2*1024;
58// Default mode for pushed files.
59const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000060
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +000061const char * kSocketNamespaceAbstract = "localabstract";
62const char * kSocketNamespaceFileSystem = "localfilesystem";
63
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +000064Error
65ReadAllBytes (Connection &conn, void *buffer, size_t size)
66{
67 using namespace std::chrono;
68
69 Error error;
70 ConnectionStatus status;
71 char *read_buffer = static_cast<char*>(buffer);
72
73 auto now = steady_clock::now();
74 const auto deadline = now + kReadTimeout;
75 size_t total_read_bytes = 0;
76 while (total_read_bytes < size && now < deadline)
77 {
78 uint32_t timeout_usec = duration_cast<microseconds>(deadline - now).count();
79 auto read_bytes =
80 conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, timeout_usec, status, &error);
81 if (error.Fail ())
82 return error;
83 total_read_bytes += read_bytes;
84 if (status != eConnectionStatusSuccess)
85 break;
86 now = steady_clock::now();
87 }
88 if (total_read_bytes < size)
89 error = Error("Unable to read requested number of bytes. Connection status: %d.", status);
90 return error;
91}
92
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000093} // namespace
94
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000095Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000096AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000097{
98 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000099 auto error = adb.GetDevices(connect_devices);
100 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000101 return error;
102
Luke Drummond3db04912016-07-07 18:02:44 +0000103 std::string android_serial;
104 if (!device_id.empty())
105 android_serial = device_id;
106 else if (const char *env_serial = std::getenv("ANDROID_SERIAL"))
107 android_serial = env_serial;
108
109 if (android_serial.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000110 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000111 if (connect_devices.size() != 1)
Luke Drummond3db04912016-07-07 18:02:44 +0000112 return Error("Expected a single connected device, got instead %zu - try setting 'ANDROID_SERIAL'",
113 connect_devices.size());
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000114 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000115 }
116 else
117 {
Luke Drummond3db04912016-07-07 18:02:44 +0000118 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), android_serial);
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000119 if (find_it == connect_devices.end())
Luke Drummond3db04912016-07-07 18:02:44 +0000120 return Error("Device \"%s\" not found", android_serial.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000121
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000122 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000123 }
124 return error;
125}
126
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000127AdbClient::AdbClient () {}
128
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000129AdbClient::AdbClient (const std::string &device_id)
130 : m_device_id (device_id)
131{
132}
133
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000134AdbClient::~AdbClient() {}
135
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000136void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000137AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000138{
139 m_device_id = device_id;
140}
141
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000142const std::string&
143AdbClient::GetDeviceID() const
144{
145 return m_device_id;
146}
147
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000148Error
149AdbClient::Connect ()
150{
151 Error error;
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000152 m_conn.reset (new ConnectionFileDescriptor);
153 m_conn->Connect ("connect://localhost:5037", &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000154
155 return error;
156}
157
158Error
159AdbClient::GetDevices (DeviceIDList &device_list)
160{
161 device_list.clear ();
162
163 auto error = SendMessage ("host:devices");
164 if (error.Fail ())
165 return error;
166
167 error = ReadResponseStatus ();
168 if (error.Fail ())
169 return error;
170
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000171 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000172 error = ReadMessage (in_buffer);
173
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000174 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000175 llvm::SmallVector<llvm::StringRef, 4> devices;
176 response.split (devices, "\n", -1, false);
177
178 for (const auto device: devices)
179 device_list.push_back (device.split ('\t').first);
180
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000181 // Force disconnect since ADB closes connection after host:devices
182 // response is sent.
183 m_conn.reset ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000184 return error;
185}
186
187Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000188AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000189{
190 char message[48];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000191 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000192
193 const auto error = SendDeviceMessage (message);
194 if (error.Fail ())
195 return error;
196
197 return ReadResponseStatus ();
198}
199
200Error
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000201AdbClient::SetPortForwarding (const uint16_t local_port,
202 const char* remote_socket_name,
203 const UnixSocketNamespace socket_namespace)
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000204{
205 char message[PATH_MAX];
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000206 const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
207 kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
208 snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
209 local_port,
210 sock_namespace_str,
211 remote_socket_name);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000212
213 const auto error = SendDeviceMessage (message);
214 if (error.Fail ())
215 return error;
216
217 return ReadResponseStatus ();
218}
219
220Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000221AdbClient::DeletePortForwarding (const uint16_t local_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000222{
223 char message[32];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000224 snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000225
226 const auto error = SendDeviceMessage (message);
227 if (error.Fail ())
228 return error;
229
230 return ReadResponseStatus ();
231}
232
233Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000234AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000235{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000236 Error error;
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000237 if (!m_conn || reconnect)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000238 {
239 error = Connect ();
240 if (error.Fail ())
241 return error;
242 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000243
244 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000245 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000246
247 ConnectionStatus status;
248
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000249 m_conn->Write (length_buffer, 4, status, &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000250 if (error.Fail ())
251 return error;
252
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000253 m_conn->Write (packet.c_str (), packet.size (), status, &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000254 return error;
255}
256
257Error
258AdbClient::SendDeviceMessage (const std::string &packet)
259{
260 std::ostringstream msg;
261 msg << "host-serial:" << m_device_id << ":" << packet;
262 return SendMessage (msg.str ());
263}
264
265Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000266AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000267{
268 message.clear ();
269
270 char buffer[5];
271 buffer[4] = 0;
272
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000273 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000274 if (error.Fail ())
275 return error;
276
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000277 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000278 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000279
280 message.resize (packet_len, 0);
281 error = ReadAllBytes (&message[0], packet_len);
282 if (error.Fail ())
283 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000284
285 return error;
286}
287
288Error
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000289AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
290{
291 auto start = std::chrono::steady_clock::now();
292 message.clear();
293
294 Error error;
295 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
296 char buffer[1024];
297 while (error.Success() && status == lldb::eConnectionStatusSuccess)
298 {
299 auto end = std::chrono::steady_clock::now();
300 uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
301 if (elapsed_time >= timeout_ms)
302 return Error("Timed out");
303
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000304 size_t n = m_conn->Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error);
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000305 if (n > 0)
306 message.insert(message.end(), &buffer[0], &buffer[n]);
307 }
308 return error;
309}
310
311Error
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000312AdbClient::ReadResponseStatus()
313{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000314 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000315
316 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000317 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000318
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000319 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000320 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000321 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000322
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000323 if (strncmp (response_id, kOKAY, packet_len) != 0)
324 return GetResponseError (response_id);
325
326 return error;
327}
328
329Error
330AdbClient::GetResponseError (const char *response_id)
331{
332 if (strcmp (response_id, kFAIL) != 0)
333 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
334
335 std::vector<char> error_message;
336 auto error = ReadMessage (error_message);
337 if (error.Success ())
338 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
339
340 return error;
341}
342
343Error
344AdbClient::SwitchDeviceTransport ()
345{
346 std::ostringstream msg;
347 msg << "host:transport:" << m_device_id;
348
349 auto error = SendMessage (msg.str ());
350 if (error.Fail ())
351 return error;
352
353 return ReadResponseStatus ();
354}
355
356Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000357AdbClient::StartSync ()
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000358{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000359 auto error = SwitchDeviceTransport ();
360 if (error.Fail ())
361 return Error ("Failed to switch to device transport: %s", error.AsCString ());
362
363 error = Sync ();
364 if (error.Fail ())
365 return Error ("Sync failed: %s", error.AsCString ());
366
367 return error;
368}
369
370Error
371AdbClient::Sync ()
372{
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000373 auto error = SendMessage ("sync:", false);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000374 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000375 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000376
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000377 return ReadResponseStatus ();
378}
379
380Error
381AdbClient::ReadAllBytes (void *buffer, size_t size)
382{
383 return ::ReadAllBytes (*m_conn, buffer, size);
384}
385
386Error
387AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
388{
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000389 auto error = SwitchDeviceTransport ();
390 if (error.Fail ())
391 return Error ("Failed to switch to device transport: %s", error.AsCString ());
392
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000393 StreamString adb_command;
394 adb_command.Printf("shell:%s", command);
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000395 error = SendMessage (adb_command.GetData(), false);
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000396 if (error.Fail ())
397 return error;
398
399 error = ReadResponseStatus ();
400 if (error.Fail ())
401 return error;
402
403 std::vector<char> in_buffer;
404 error = ReadMessageStream (in_buffer, timeout_ms);
405 if (error.Fail())
406 return error;
407
408 if (output)
409 output->assign(in_buffer.begin(), in_buffer.end());
410 return error;
411}
412
413std::unique_ptr<AdbClient::SyncService>
414AdbClient::GetSyncService (Error &error)
415{
416 std::unique_ptr<SyncService> sync_service;
417 error = StartSync ();
418 if (error.Success ())
419 sync_service.reset (new SyncService(std::move(m_conn)));
420
421 return sync_service;
422}
423
424Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000425AdbClient::SyncService::internalPullFile (const FileSpec &remote_file, const FileSpec &local_file)
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000426{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000427 const auto local_file_path = local_file.GetPath ();
428 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000429
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000430 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000431 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000432 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000433
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000434 const auto remote_file_path = remote_file.GetPath (false);
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000435 auto error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000436 if (error.Fail ())
437 return error;
438
439 std::vector<char> chunk;
440 bool eof = false;
441 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000442 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000443 error = PullFileChunk (chunk, eof);
444 if (error.Fail ())
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000445 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000446 if (!eof)
447 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000448 }
449
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000450 local_file_remover.releaseFile ();
451 return error;
452}
453
454Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000455AdbClient::SyncService::internalPushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000456{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000457 const auto local_file_path (local_file.GetPath ());
458 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000459 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000460 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000461
462 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000463 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000464 std::string file_description_str = file_description.str();
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000465 auto error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000466 if (error.Fail ())
467 return error;
468
469 char chunk[kMaxPushData];
470 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
471 {
472 size_t chunk_size = src.gcount();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000473 error = SendSyncRequest(kDATA, chunk_size, chunk);
Robert Flack62efb1f2015-05-27 02:18:50 +0000474 if (error.Fail ())
475 return Error ("Failed to send file chunk: %s", error.AsCString ());
476 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000477 error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000478 if (error.Fail ())
479 return error;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000480
481 std::string response_id;
Jason Molendad10f6aa2015-10-28 23:31:03 +0000482 uint32_t data_len;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000483 error = ReadSyncHeader (response_id, data_len);
484 if (error.Fail ())
485 return Error ("Failed to read DONE response: %s", error.AsCString ());
486 if (response_id == kFAIL)
487 {
488 std::string error_message (data_len, 0);
489 error = ReadAllBytes (&error_message[0], data_len);
490 if (error.Fail ())
491 return Error ("Failed to read DONE error message: %s", error.AsCString ());
492 return Error ("Failed to push file: %s", error_message.c_str ());
493 }
494 else if (response_id != kOKAY)
495 return Error ("Got unexpected DONE response: %s", response_id.c_str ());
496
Robert Flack62efb1f2015-05-27 02:18:50 +0000497 // If there was an error reading the source file, finish the adb file
498 // transfer first so that adb isn't expecting any more data.
499 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000500 return Error ("Failed read on %s", local_file_path.c_str());
501 return error;
502}
503
504Error
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000505AdbClient::SyncService::internalStat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000506{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000507 const std::string remote_file_path (remote_file.GetPath (false));
508 auto error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000509 if (error.Fail ())
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000510 return Error ("Failed to send request: %s", error.AsCString ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000511
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000512 static const size_t stat_len = strlen (kSTAT);
513 static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
514
515 std::vector<char> buffer (response_len);
516 error = ReadAllBytes (&buffer[0], buffer.size ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000517 if (error.Fail ())
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000518 return Error ("Failed to read response: %s", error.AsCString ());
519
520 DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
521 offset_t offset = 0;
522
523 const void* command = extractor.GetData (&offset, stat_len);
524 if (!command)
525 return Error ("Failed to get response command");
526 const char* command_str = static_cast<const char*> (command);
527 if (strncmp (command_str, kSTAT, stat_len))
528 return Error ("Got invalid stat command: %s", command_str);
529
530 mode = extractor.GetU32 (&offset);
531 size = extractor.GetU32 (&offset);
532 mtime = extractor.GetU32 (&offset);
533 return Error ();
534}
535
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000536Error
537AdbClient::SyncService::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
538{
539 return executeCommand ([this, &remote_file, &local_file]() {
540 return internalPullFile (remote_file, local_file);
541 });
542}
543
544Error
545AdbClient::SyncService::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
546{
547 return executeCommand ([this, &local_file, &remote_file]() {
548 return internalPushFile (local_file, remote_file);
549 });
550}
551
552Error
553AdbClient::SyncService::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
554{
555 return executeCommand ([this, &remote_file, &mode, &size, &mtime]() {
556 return internalStat (remote_file, mode, size, mtime);
557 });
558}
559
560bool
561AdbClient::SyncService::IsConnected () const
562{
563 return m_conn && m_conn->IsConnected ();
564}
565
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000566AdbClient::SyncService::SyncService(std::unique_ptr<Connection> &&conn):
567m_conn(std::move(conn))
568{
569}
570
Oleksiy Vyalovd6a143f2016-07-06 17:02:42 +0000571Error
572AdbClient::SyncService::executeCommand (const std::function<Error()> &cmd)
573{
574 if (!m_conn)
575 return Error ("SyncService is disconnected");
576
577 const auto error = cmd ();
578 if (error.Fail ())
579 m_conn.reset ();
580
581 return error;
582}
583
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000584AdbClient::SyncService::~SyncService () {}
585
586Error
587AdbClient::SyncService::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
588{
589 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
590 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
591 auto offset = encoder.PutData (0, request_id, strlen(request_id));
592 encoder.PutU32 (offset, data_len);
593
594 Error error;
595 ConnectionStatus status;
596 m_conn->Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
597 if (error.Fail ())
598 return error;
599
600 if (data)
601 m_conn->Write (data, data_len, status, &error);
602 return error;
603}
604
605Error
606AdbClient::SyncService::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
607{
608 char buffer[kSyncPacketLen];
609
610 auto error = ReadAllBytes (buffer, kSyncPacketLen);
611 if (error.Success ())
612 {
613 response_id.assign (&buffer[0], 4);
614 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
615 offset_t offset = 0;
616 data_len = extractor.GetU32 (&offset);
617 }
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000618
Robert Flack62efb1f2015-05-27 02:18:50 +0000619 return error;
620}
621
622Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000623AdbClient::SyncService::PullFileChunk (std::vector<char> &buffer, bool &eof)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000624{
625 buffer.clear ();
626
627 std::string response_id;
628 uint32_t data_len;
629 auto error = ReadSyncHeader (response_id, data_len);
630 if (error.Fail ())
631 return error;
632
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000633 if (response_id == kDATA)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000634 {
635 buffer.resize (data_len, 0);
636 error = ReadAllBytes (&buffer[0], data_len);
637 if (error.Fail ())
638 buffer.clear ();
639 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000640 else if (response_id == kDONE)
641 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000642 eof = true;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000643 }
644 else if (response_id == kFAIL)
645 {
646 std::string error_message (data_len, 0);
647 error = ReadAllBytes (&error_message[0], data_len);
648 if (error.Fail ())
649 return Error ("Failed to read pull error message: %s", error.AsCString ());
650 return Error ("Failed to pull file: %s", error_message.c_str ());
651 }
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000652 else
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000653 return Error ("Pull failed with unknown response: %s", response_id.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000654
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000655 return Error ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000656}
657
658Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000659AdbClient::SyncService::ReadAllBytes (void *buffer, size_t size)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000660{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000661 return ::ReadAllBytes (*m_conn, buffer, size);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000662}
663