1 //===-- 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
11 #include "lldb/Core/DataBuffer.h"
12 #include "lldb/Core/DataBufferHeap.h"
13 #include "lldb/Core/DataEncoder.h"
14 #include "lldb/Core/DataExtractor.h"
15 #include "lldb/Core/StreamString.h"
16 #include "lldb/Host/FileSpec.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/Support/FileUtilities.h"
21 
22 // Project includes
23 #include "AdbClient.h"
24 
25 #include <limits.h>
26 
27 #include <algorithm>
28 #include <fstream>
29 #include <sstream>
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 using namespace lldb_private::platform_android;
34 
35 namespace {
36 
37 const uint32_t kReadTimeout = 1000000; // 1 second
38 const char * kOKAY = "OKAY";
39 const char * kFAIL = "FAIL";
40 const char * kDATA = "DATA";
41 const char * kDONE = "DONE";
42 
43 const char * kSEND = "SEND";
44 const char * kRECV = "RECV";
45 const char * kSTAT = "STAT";
46 
47 const size_t kSyncPacketLen = 8;
48 // Maximum size of a filesync DATA packet.
49 const size_t kMaxPushData = 2*1024;
50 // Default mode for pushed files.
51 const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
52 
53 const char * kSocketNamespaceAbstract = "localabstract";
54 const char * kSocketNamespaceFileSystem = "localfilesystem";
55 
56 }  // namespace
57 
58 Error
59 AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
60 {
61     DeviceIDList connect_devices;
62     auto error = adb.GetDevices(connect_devices);
63     if (error.Fail())
64         return error;
65 
66     if (device_id.empty())
67     {
68         if (connect_devices.size() != 1)
69             return Error("Expected a single connected device, got instead %" PRIu64,
70                     static_cast<uint64_t>(connect_devices.size()));
71 
72         adb.SetDeviceID(connect_devices.front());
73     }
74     else
75     {
76         auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
77         if (find_it == connect_devices.end())
78             return Error("Device \"%s\" not found", device_id.c_str());
79 
80         adb.SetDeviceID(*find_it);
81     }
82     return error;
83 }
84 
85 AdbClient::AdbClient (const std::string &device_id)
86     : m_device_id (device_id)
87 {
88 }
89 
90 void
91 AdbClient::SetDeviceID (const std::string &device_id)
92 {
93     m_device_id = device_id;
94 }
95 
96 const std::string&
97 AdbClient::GetDeviceID() const
98 {
99     return m_device_id;
100 }
101 
102 Error
103 AdbClient::Connect ()
104 {
105     Error error;
106     m_conn.Connect ("connect://localhost:5037", &error);
107 
108     return error;
109 }
110 
111 Error
112 AdbClient::GetDevices (DeviceIDList &device_list)
113 {
114     device_list.clear ();
115 
116     auto error = SendMessage ("host:devices");
117     if (error.Fail ())
118         return error;
119 
120     error = ReadResponseStatus ();
121     if (error.Fail ())
122         return error;
123 
124     std::vector<char> in_buffer;
125     error = ReadMessage (in_buffer);
126 
127     llvm::StringRef response (&in_buffer[0], in_buffer.size ());
128     llvm::SmallVector<llvm::StringRef, 4> devices;
129     response.split (devices, "\n", -1, false);
130 
131     for (const auto device: devices)
132         device_list.push_back (device.split ('\t').first);
133 
134     return error;
135 }
136 
137 Error
138 AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
139 {
140     char message[48];
141     snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
142 
143     const auto error = SendDeviceMessage (message);
144     if (error.Fail ())
145         return error;
146 
147     return ReadResponseStatus ();
148 }
149 
150 Error
151 AdbClient::SetPortForwarding (const uint16_t local_port,
152                               const char* remote_socket_name,
153                               const UnixSocketNamespace socket_namespace)
154 {
155     char message[PATH_MAX];
156     const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
157         kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
158     snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
159               local_port,
160               sock_namespace_str,
161               remote_socket_name);
162 
163     const auto error = SendDeviceMessage (message);
164     if (error.Fail ())
165         return error;
166 
167     return ReadResponseStatus ();
168 }
169 
170 Error
171 AdbClient::DeletePortForwarding (const uint16_t local_port)
172 {
173     char message[32];
174     snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
175 
176     const auto error = SendDeviceMessage (message);
177     if (error.Fail ())
178         return error;
179 
180     return ReadResponseStatus ();
181 }
182 
183 Error
184 AdbClient::SendMessage (const std::string &packet, const bool reconnect)
185 {
186     Error error;
187     if (reconnect)
188     {
189         error = Connect ();
190         if (error.Fail ())
191             return error;
192     }
193 
194     char length_buffer[5];
195     snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
196 
197     ConnectionStatus status;
198 
199     m_conn.Write (length_buffer, 4, status, &error);
200     if (error.Fail ())
201         return error;
202 
203     m_conn.Write (packet.c_str (), packet.size (), status, &error);
204     return error;
205 }
206 
207 Error
208 AdbClient::SendDeviceMessage (const std::string &packet)
209 {
210     std::ostringstream msg;
211     msg << "host-serial:" << m_device_id << ":" << packet;
212     return SendMessage (msg.str ());
213 }
214 
215 Error
216 AdbClient::ReadMessage (std::vector<char> &message)
217 {
218     message.clear ();
219 
220     char buffer[5];
221     buffer[4] = 0;
222 
223     auto error = ReadAllBytes (buffer, 4);
224     if (error.Fail ())
225         return error;
226 
227     unsigned int packet_len = 0;
228     sscanf (buffer, "%x", &packet_len);
229 
230     message.resize (packet_len, 0);
231     error = ReadAllBytes (&message[0], packet_len);
232     if (error.Fail ())
233         message.clear ();
234 
235     return error;
236 }
237 
238 Error
239 AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
240 {
241     auto start = std::chrono::steady_clock::now();
242     message.clear();
243 
244     Error error;
245     lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
246     char buffer[1024];
247     while (error.Success() && status == lldb::eConnectionStatusSuccess)
248     {
249         auto end = std::chrono::steady_clock::now();
250         uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
251         if (elapsed_time >= timeout_ms)
252             return Error("Timed out");
253 
254         size_t n = m_conn.Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error);
255         if (n > 0)
256             message.insert(message.end(), &buffer[0], &buffer[n]);
257     }
258     return error;
259 }
260 
261 Error
262 AdbClient::ReadResponseStatus()
263 {
264     char response_id[5];
265 
266     static const size_t packet_len = 4;
267     response_id[packet_len] = 0;
268 
269     auto error = ReadAllBytes (response_id, packet_len);
270     if (error.Fail ())
271         return error;
272 
273     if (strncmp (response_id, kOKAY, packet_len) != 0)
274         return GetResponseError (response_id);
275 
276     return error;
277 }
278 
279 Error
280 AdbClient::GetResponseError (const char *response_id)
281 {
282     if (strcmp (response_id, kFAIL) != 0)
283         return Error ("Got unexpected response id from adb: \"%s\"", response_id);
284 
285     std::vector<char> error_message;
286     auto error = ReadMessage (error_message);
287     if (error.Success ())
288         error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
289 
290     return error;
291 }
292 
293 Error
294 AdbClient::SwitchDeviceTransport ()
295 {
296     std::ostringstream msg;
297     msg << "host:transport:" << m_device_id;
298 
299     auto error = SendMessage (msg.str ());
300     if (error.Fail ())
301         return error;
302 
303     return ReadResponseStatus ();
304 }
305 
306 Error
307 AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
308 {
309     auto error = StartSync ();
310     if (error.Fail ())
311         return error;
312 
313     const auto local_file_path = local_file.GetPath ();
314     llvm::FileRemover local_file_remover (local_file_path.c_str ());
315 
316     std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
317     if (!dst.is_open ())
318         return Error ("Unable to open local file %s", local_file_path.c_str());
319 
320     const auto remote_file_path = remote_file.GetPath (false);
321     error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
322     if (error.Fail ())
323         return error;
324 
325     std::vector<char> chunk;
326     bool eof = false;
327     while (!eof)
328     {
329         error = PullFileChunk (chunk, eof);
330         if (error.Fail ())
331             return error;
332         if (!eof)
333             dst.write (&chunk[0], chunk.size ());
334     }
335 
336     local_file_remover.releaseFile ();
337     return error;
338 }
339 
340 Error
341 AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
342 {
343     auto error = StartSync ();
344     if (error.Fail ())
345         return error;
346 
347     const auto local_file_path (local_file.GetPath ());
348     std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
349     if (!src.is_open ())
350         return Error ("Unable to open local file %s", local_file_path.c_str());
351 
352     std::stringstream file_description;
353     file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
354     std::string file_description_str = file_description.str();
355     error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
356     if (error.Fail ())
357         return error;
358 
359     char chunk[kMaxPushData];
360     while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
361     {
362         size_t chunk_size = src.gcount();
363         error = SendSyncRequest(kDATA, chunk_size, chunk);
364         if (error.Fail ())
365             return Error ("Failed to send file chunk: %s", error.AsCString ());
366     }
367     error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
368     if (error.Fail ())
369         return error;
370 
371     std::string response_id;
372     uint32_t data_len;
373     error = ReadSyncHeader (response_id, data_len);
374     if (error.Fail ())
375         return Error ("Failed to read DONE response: %s", error.AsCString ());
376     if (response_id == kFAIL)
377     {
378         std::string error_message (data_len, 0);
379         error = ReadAllBytes (&error_message[0], data_len);
380         if (error.Fail ())
381             return Error ("Failed to read DONE error message: %s", error.AsCString ());
382         return Error ("Failed to push file: %s", error_message.c_str ());
383     }
384     else if (response_id != kOKAY)
385         return Error ("Got unexpected DONE response: %s", response_id.c_str ());
386 
387     // If there was an error reading the source file, finish the adb file
388     // transfer first so that adb isn't expecting any more data.
389     if (src.bad())
390         return Error ("Failed read on %s", local_file_path.c_str());
391     return error;
392 }
393 
394 Error
395 AdbClient::StartSync ()
396 {
397     auto error = SwitchDeviceTransport ();
398     if (error.Fail ())
399         return Error ("Failed to switch to device transport: %s", error.AsCString ());
400 
401     error = Sync ();
402     if (error.Fail ())
403         return Error ("Sync failed: %s", error.AsCString ());
404 
405     return error;
406 }
407 
408 Error
409 AdbClient::Sync ()
410 {
411     auto error = SendMessage ("sync:", false);
412     if (error.Fail ())
413         return error;
414 
415     return ReadResponseStatus ();
416 }
417 
418 Error
419 AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
420 {
421     buffer.clear ();
422 
423     std::string response_id;
424     uint32_t data_len;
425     auto error = ReadSyncHeader (response_id, data_len);
426     if (error.Fail ())
427         return error;
428 
429     if (response_id == kDATA)
430     {
431         buffer.resize (data_len, 0);
432         error = ReadAllBytes (&buffer[0], data_len);
433         if (error.Fail ())
434             buffer.clear ();
435     }
436     else if (response_id == kDONE)
437     {
438         eof = true;
439     }
440     else if (response_id == kFAIL)
441     {
442         std::string error_message (data_len, 0);
443         error = ReadAllBytes (&error_message[0], data_len);
444         if (error.Fail ())
445             return Error ("Failed to read pull error message: %s", error.AsCString ());
446         return Error ("Failed to pull file: %s", error_message.c_str ());
447     }
448     else
449         return Error ("Pull failed with unknown response: %s", response_id.c_str ());
450 
451     return Error ();
452 }
453 
454 Error
455 AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
456 {
457     const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
458     DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
459     auto offset = encoder.PutData (0, request_id, strlen(request_id));
460     encoder.PutU32 (offset, data_len);
461 
462     Error error;
463     ConnectionStatus status;
464     m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
465     if (error.Fail ())
466         return error;
467 
468     if (data)
469         m_conn.Write (data, data_len, status, &error);
470     return error;
471 }
472 
473 Error
474 AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
475 {
476     char buffer[kSyncPacketLen];
477 
478     auto error = ReadAllBytes (buffer, kSyncPacketLen);
479     if (error.Success ())
480     {
481         response_id.assign (&buffer[0], 4);
482         DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
483         offset_t offset = 0;
484         data_len = extractor.GetU32 (&offset);
485     }
486 
487     return error;
488 }
489 
490 Error
491 AdbClient::ReadAllBytes (void *buffer, size_t size)
492 {
493     Error error;
494     ConnectionStatus status;
495     char *read_buffer = static_cast<char*>(buffer);
496 
497     size_t tota_read_bytes = 0;
498     while (tota_read_bytes < size)
499     {
500         auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
501         if (error.Fail ())
502             return error;
503         tota_read_bytes += read_bytes;
504     }
505     return error;
506 }
507 
508 Error
509 AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
510 {
511     auto error = StartSync ();
512     if (error.Fail ())
513         return error;
514 
515     const std::string remote_file_path (remote_file.GetPath (false));
516     error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
517     if (error.Fail ())
518         return Error ("Failed to send request: %s", error.AsCString ());
519 
520     static const size_t stat_len = strlen (kSTAT);
521     static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
522 
523     std::vector<char> buffer (response_len);
524     error = ReadAllBytes (&buffer[0], buffer.size ());
525     if (error.Fail ())
526         return Error ("Failed to read response: %s", error.AsCString ());
527 
528     DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
529     offset_t offset = 0;
530 
531     const void* command = extractor.GetData (&offset, stat_len);
532     if (!command)
533         return Error ("Failed to get response command");
534     const char* command_str = static_cast<const char*> (command);
535     if (strncmp (command_str, kSTAT, stat_len))
536         return Error ("Got invalid stat command: %s", command_str);
537 
538     mode = extractor.GetU32 (&offset);
539     size = extractor.GetU32 (&offset);
540     mtime = extractor.GetU32 (&offset);
541     return Error ();
542 }
543 
544 Error
545 AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
546 {
547     auto error = SwitchDeviceTransport ();
548     if (error.Fail ())
549         return Error ("Failed to switch to device transport: %s", error.AsCString ());
550 
551     StreamString adb_command;
552     adb_command.Printf("shell:%s", command);
553     error = SendMessage (adb_command.GetData(), false);
554     if (error.Fail ())
555         return error;
556 
557     error = ReadResponseStatus ();
558     if (error.Fail ())
559         return error;
560 
561     std::vector<char> in_buffer;
562     error = ReadMessageStream (in_buffer, timeout_ms);
563     if (error.Fail())
564         return error;
565 
566     if (output)
567         output->assign(in_buffer.begin(), in_buffer.end());
568     return error;
569 }
570