blob: fef8dcb4f213511cebef436c2fd385d4adb5b99c [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
32using namespace lldb;
33using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000034using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000035
36namespace {
37
Pavel Labath204ef662016-05-16 11:41:36 +000038const std::chrono::seconds kReadTimeout(8);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000039const char * kOKAY = "OKAY";
40const char * kFAIL = "FAIL";
Oleksiy Vyalov6002a312015-06-05 01:32:45 +000041const char * kDATA = "DATA";
42const char * kDONE = "DONE";
43
44const char * kSEND = "SEND";
45const char * kRECV = "RECV";
46const char * kSTAT = "STAT";
47
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000048const size_t kSyncPacketLen = 8;
Robert Flack62efb1f2015-05-27 02:18:50 +000049// Maximum size of a filesync DATA packet.
50const size_t kMaxPushData = 2*1024;
51// Default mode for pushed files.
52const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000053
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +000054const char * kSocketNamespaceAbstract = "localabstract";
55const char * kSocketNamespaceFileSystem = "localfilesystem";
56
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +000057Error
58ReadAllBytes (Connection &conn, void *buffer, size_t size)
59{
60 using namespace std::chrono;
61
62 Error error;
63 ConnectionStatus status;
64 char *read_buffer = static_cast<char*>(buffer);
65
66 auto now = steady_clock::now();
67 const auto deadline = now + kReadTimeout;
68 size_t total_read_bytes = 0;
69 while (total_read_bytes < size && now < deadline)
70 {
71 uint32_t timeout_usec = duration_cast<microseconds>(deadline - now).count();
72 auto read_bytes =
73 conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, timeout_usec, status, &error);
74 if (error.Fail ())
75 return error;
76 total_read_bytes += read_bytes;
77 if (status != eConnectionStatusSuccess)
78 break;
79 now = steady_clock::now();
80 }
81 if (total_read_bytes < size)
82 error = Error("Unable to read requested number of bytes. Connection status: %d.", status);
83 return error;
84}
85
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000086} // namespace
87
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000088Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000089AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000090{
91 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000092 auto error = adb.GetDevices(connect_devices);
93 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000094 return error;
95
Chaoren Lin3ea689b2015-05-01 16:49:28 +000096 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000097 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000098 if (connect_devices.size() != 1)
99 return Error("Expected a single connected device, got instead %" PRIu64,
100 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000101
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000102 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000103 }
104 else
105 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000106 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
107 if (find_it == connect_devices.end())
108 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000109
Chaoren Lin3ea689b2015-05-01 16:49:28 +0000110 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000111 }
112 return error;
113}
114
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000115AdbClient::AdbClient () {}
116
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000117AdbClient::AdbClient (const std::string &device_id)
118 : m_device_id (device_id)
119{
120}
121
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000122AdbClient::~AdbClient() {}
123
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000124void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000125AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000126{
127 m_device_id = device_id;
128}
129
Oleksiy Vyalov6f001062015-03-25 17:58:13 +0000130const std::string&
131AdbClient::GetDeviceID() const
132{
133 return m_device_id;
134}
135
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000136Error
137AdbClient::Connect ()
138{
139 Error error;
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000140 m_conn.reset (new ConnectionFileDescriptor);
141 m_conn->Connect ("connect://localhost:5037", &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000142
143 return error;
144}
145
146Error
147AdbClient::GetDevices (DeviceIDList &device_list)
148{
149 device_list.clear ();
150
151 auto error = SendMessage ("host:devices");
152 if (error.Fail ())
153 return error;
154
155 error = ReadResponseStatus ();
156 if (error.Fail ())
157 return error;
158
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000159 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000160 error = ReadMessage (in_buffer);
161
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000162 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000163 llvm::SmallVector<llvm::StringRef, 4> devices;
164 response.split (devices, "\n", -1, false);
165
166 for (const auto device: devices)
167 device_list.push_back (device.split ('\t').first);
168
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000169 // Force disconnect since ADB closes connection after host:devices
170 // response is sent.
171 m_conn.reset ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000172 return error;
173}
174
175Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000176AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000177{
178 char message[48];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000179 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000180
181 const auto error = SendDeviceMessage (message);
182 if (error.Fail ())
183 return error;
184
185 return ReadResponseStatus ();
186}
187
188Error
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000189AdbClient::SetPortForwarding (const uint16_t local_port,
190 const char* remote_socket_name,
191 const UnixSocketNamespace socket_namespace)
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000192{
193 char message[PATH_MAX];
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000194 const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
195 kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
196 snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
197 local_port,
198 sock_namespace_str,
199 remote_socket_name);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000200
201 const auto error = SendDeviceMessage (message);
202 if (error.Fail ())
203 return error;
204
205 return ReadResponseStatus ();
206}
207
208Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000209AdbClient::DeletePortForwarding (const uint16_t local_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000210{
211 char message[32];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000212 snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000213
214 const auto error = SendDeviceMessage (message);
215 if (error.Fail ())
216 return error;
217
218 return ReadResponseStatus ();
219}
220
221Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000222AdbClient::SendMessage (const std::string &packet)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000223{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000224 Error error;
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000225 if (!m_conn || !m_conn->IsConnected())
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000226 {
227 error = Connect ();
228 if (error.Fail ())
229 return error;
230 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000231
232 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000233 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000234
235 ConnectionStatus status;
236
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000237 m_conn->Write (length_buffer, 4, status, &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000238 if (error.Fail ())
239 return error;
240
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000241 m_conn->Write (packet.c_str (), packet.size (), status, &error);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000242 return error;
243}
244
245Error
246AdbClient::SendDeviceMessage (const std::string &packet)
247{
248 std::ostringstream msg;
249 msg << "host-serial:" << m_device_id << ":" << packet;
250 return SendMessage (msg.str ());
251}
252
253Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000254AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000255{
256 message.clear ();
257
258 char buffer[5];
259 buffer[4] = 0;
260
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000261 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000262 if (error.Fail ())
263 return error;
264
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000265 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000266 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000267
268 message.resize (packet_len, 0);
269 error = ReadAllBytes (&message[0], packet_len);
270 if (error.Fail ())
271 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000272
273 return error;
274}
275
276Error
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000277AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
278{
279 auto start = std::chrono::steady_clock::now();
280 message.clear();
281
282 Error error;
283 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
284 char buffer[1024];
285 while (error.Success() && status == lldb::eConnectionStatusSuccess)
286 {
287 auto end = std::chrono::steady_clock::now();
288 uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
289 if (elapsed_time >= timeout_ms)
290 return Error("Timed out");
291
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000292 size_t n = m_conn->Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error);
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000293 if (n > 0)
294 message.insert(message.end(), &buffer[0], &buffer[n]);
295 }
296 return error;
297}
298
299Error
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000300AdbClient::ReadResponseStatus()
301{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000302 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000303
304 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000305 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000306
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000307 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000308 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000309 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000310
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000311 if (strncmp (response_id, kOKAY, packet_len) != 0)
312 return GetResponseError (response_id);
313
314 return error;
315}
316
317Error
318AdbClient::GetResponseError (const char *response_id)
319{
320 if (strcmp (response_id, kFAIL) != 0)
321 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
322
323 std::vector<char> error_message;
324 auto error = ReadMessage (error_message);
325 if (error.Success ())
326 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
327
328 return error;
329}
330
331Error
332AdbClient::SwitchDeviceTransport ()
333{
334 std::ostringstream msg;
335 msg << "host:transport:" << m_device_id;
336
337 auto error = SendMessage (msg.str ());
338 if (error.Fail ())
339 return error;
340
341 return ReadResponseStatus ();
342}
343
344Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000345AdbClient::StartSync ()
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000346{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000347 auto error = SwitchDeviceTransport ();
348 if (error.Fail ())
349 return Error ("Failed to switch to device transport: %s", error.AsCString ());
350
351 error = Sync ();
352 if (error.Fail ())
353 return Error ("Sync failed: %s", error.AsCString ());
354
355 return error;
356}
357
358Error
359AdbClient::Sync ()
360{
361 auto error = SendMessage ("sync:");
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000362 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000363 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000364
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000365 return ReadResponseStatus ();
366}
367
368Error
369AdbClient::ReadAllBytes (void *buffer, size_t size)
370{
371 return ::ReadAllBytes (*m_conn, buffer, size);
372}
373
374Error
375AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
376{
377 StreamString adb_command;
378 adb_command.Printf("shell:%s", command);
379 auto error = SendMessage (adb_command.GetData());
380 if (error.Fail ())
381 return error;
382
383 error = ReadResponseStatus ();
384 if (error.Fail ())
385 return error;
386
387 std::vector<char> in_buffer;
388 error = ReadMessageStream (in_buffer, timeout_ms);
389 if (error.Fail())
390 return error;
391
392 if (output)
393 output->assign(in_buffer.begin(), in_buffer.end());
394 return error;
395}
396
397std::unique_ptr<AdbClient::SyncService>
398AdbClient::GetSyncService (Error &error)
399{
400 std::unique_ptr<SyncService> sync_service;
401 error = StartSync ();
402 if (error.Success ())
403 sync_service.reset (new SyncService(std::move(m_conn)));
404
405 return sync_service;
406}
407
408Error
409AdbClient::SyncService::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
410{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000411 const auto local_file_path = local_file.GetPath ();
412 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000413
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000414 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000415 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000416 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000417
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000418 const auto remote_file_path = remote_file.GetPath (false);
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000419 auto error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000420 if (error.Fail ())
421 return error;
422
423 std::vector<char> chunk;
424 bool eof = false;
425 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000426 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000427 error = PullFileChunk (chunk, eof);
428 if (error.Fail ())
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000429 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000430 if (!eof)
431 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000432 }
433
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000434 local_file_remover.releaseFile ();
435 return error;
436}
437
438Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000439AdbClient::SyncService::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000440{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000441 const auto local_file_path (local_file.GetPath ());
442 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000443 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000444 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000445
446 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000447 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000448 std::string file_description_str = file_description.str();
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000449 auto error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000450 if (error.Fail ())
451 return error;
452
453 char chunk[kMaxPushData];
454 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
455 {
456 size_t chunk_size = src.gcount();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000457 error = SendSyncRequest(kDATA, chunk_size, chunk);
Robert Flack62efb1f2015-05-27 02:18:50 +0000458 if (error.Fail ())
459 return Error ("Failed to send file chunk: %s", error.AsCString ());
460 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000461 error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000462 if (error.Fail ())
463 return error;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000464
465 std::string response_id;
Jason Molendad10f6aa2015-10-28 23:31:03 +0000466 uint32_t data_len;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000467 error = ReadSyncHeader (response_id, data_len);
468 if (error.Fail ())
469 return Error ("Failed to read DONE response: %s", error.AsCString ());
470 if (response_id == kFAIL)
471 {
472 std::string error_message (data_len, 0);
473 error = ReadAllBytes (&error_message[0], data_len);
474 if (error.Fail ())
475 return Error ("Failed to read DONE error message: %s", error.AsCString ());
476 return Error ("Failed to push file: %s", error_message.c_str ());
477 }
478 else if (response_id != kOKAY)
479 return Error ("Got unexpected DONE response: %s", response_id.c_str ());
480
Robert Flack62efb1f2015-05-27 02:18:50 +0000481 // If there was an error reading the source file, finish the adb file
482 // transfer first so that adb isn't expecting any more data.
483 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000484 return Error ("Failed read on %s", local_file_path.c_str());
485 return error;
486}
487
488Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000489AdbClient::SyncService::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000490{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000491 const std::string remote_file_path (remote_file.GetPath (false));
492 auto error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000493 if (error.Fail ())
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000494 return Error ("Failed to send request: %s", error.AsCString ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000495
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000496 static const size_t stat_len = strlen (kSTAT);
497 static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
498
499 std::vector<char> buffer (response_len);
500 error = ReadAllBytes (&buffer[0], buffer.size ());
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000501 if (error.Fail ())
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000502 return Error ("Failed to read response: %s", error.AsCString ());
503
504 DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
505 offset_t offset = 0;
506
507 const void* command = extractor.GetData (&offset, stat_len);
508 if (!command)
509 return Error ("Failed to get response command");
510 const char* command_str = static_cast<const char*> (command);
511 if (strncmp (command_str, kSTAT, stat_len))
512 return Error ("Got invalid stat command: %s", command_str);
513
514 mode = extractor.GetU32 (&offset);
515 size = extractor.GetU32 (&offset);
516 mtime = extractor.GetU32 (&offset);
517 return Error ();
518}
519
520AdbClient::SyncService::SyncService(std::unique_ptr<Connection> &&conn):
521m_conn(std::move(conn))
522{
523}
524
525AdbClient::SyncService::~SyncService () {}
526
527Error
528AdbClient::SyncService::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
529{
530 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
531 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
532 auto offset = encoder.PutData (0, request_id, strlen(request_id));
533 encoder.PutU32 (offset, data_len);
534
535 Error error;
536 ConnectionStatus status;
537 m_conn->Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
538 if (error.Fail ())
539 return error;
540
541 if (data)
542 m_conn->Write (data, data_len, status, &error);
543 return error;
544}
545
546Error
547AdbClient::SyncService::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
548{
549 char buffer[kSyncPacketLen];
550
551 auto error = ReadAllBytes (buffer, kSyncPacketLen);
552 if (error.Success ())
553 {
554 response_id.assign (&buffer[0], 4);
555 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
556 offset_t offset = 0;
557 data_len = extractor.GetU32 (&offset);
558 }
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000559
Robert Flack62efb1f2015-05-27 02:18:50 +0000560 return error;
561}
562
563Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000564AdbClient::SyncService::PullFileChunk (std::vector<char> &buffer, bool &eof)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000565{
566 buffer.clear ();
567
568 std::string response_id;
569 uint32_t data_len;
570 auto error = ReadSyncHeader (response_id, data_len);
571 if (error.Fail ())
572 return error;
573
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000574 if (response_id == kDATA)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000575 {
576 buffer.resize (data_len, 0);
577 error = ReadAllBytes (&buffer[0], data_len);
578 if (error.Fail ())
579 buffer.clear ();
580 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000581 else if (response_id == kDONE)
582 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000583 eof = true;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000584 }
585 else if (response_id == kFAIL)
586 {
587 std::string error_message (data_len, 0);
588 error = ReadAllBytes (&error_message[0], data_len);
589 if (error.Fail ())
590 return Error ("Failed to read pull error message: %s", error.AsCString ());
591 return Error ("Failed to pull file: %s", error_message.c_str ());
592 }
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000593 else
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000594 return Error ("Pull failed with unknown response: %s", response_id.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000595
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000596 return Error ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000597}
598
599Error
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000600AdbClient::SyncService::ReadAllBytes (void *buffer, size_t size)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000601{
Oleksiy Vyalov6e181cf2016-06-30 18:10:27 +0000602 return ::ReadAllBytes (*m_conn, buffer, size);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000603}
604