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 "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/STLExtras.h"
14 
15 // Project includes
16 #include "AdbClient.h"
17 
18 #include <algorithm>
19 #include <sstream>
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace lldb_private::platform_android;
24 
25 namespace {
26 
27 const uint32_t kConnTimeout = 10000; // 10 ms
28 const char * kOKAY = "OKAY";
29 const char * kFAIL = "FAIL";
30 
31 }  // namespace
32 
33 Error
34 AdbClient::CreateByDeviceID (const char* device_id, AdbClient &adb)
35 {
36     DeviceIDList connect_devices;
37     auto error = adb.GetDevices (connect_devices);
38     if (error.Fail ())
39         return error;
40 
41     if (device_id)
42     {
43         auto find_it = std::find(connect_devices.begin (), connect_devices.end (), device_id);
44         if (find_it == connect_devices.end ())
45             return Error ("Device \"%s\" not found", device_id);
46 
47         adb.SetDeviceID (*find_it);
48     }
49     else
50     {
51         if (connect_devices.size () != 1)
52             return Error ("Expected a single connected device, got instead %zu", connect_devices.size ());
53 
54         adb.SetDeviceID (connect_devices.front ());
55     }
56     return error;
57 }
58 
59 AdbClient::AdbClient (const std::string &device_id)
60     : m_device_id (device_id)
61 {
62 }
63 
64 void
65 AdbClient::SetDeviceID (const std::string& device_id)
66 {
67     m_device_id = device_id;
68 }
69 
70 const std::string&
71 AdbClient::GetDeviceID() const
72 {
73     return m_device_id;
74 }
75 
76 Error
77 AdbClient::Connect ()
78 {
79     Error error;
80     m_conn.Connect ("connect://localhost:5037", &error);
81 
82     return error;
83 }
84 
85 Error
86 AdbClient::GetDevices (DeviceIDList &device_list)
87 {
88     device_list.clear ();
89 
90     auto error = SendMessage ("host:devices");
91     if (error.Fail ())
92         return error;
93 
94     error = ReadResponseStatus ();
95     if (error.Fail ())
96         return error;
97 
98     std::string in_buffer;
99     error = ReadMessage (in_buffer);
100 
101     llvm::StringRef response (in_buffer);
102     llvm::SmallVector<llvm::StringRef, 4> devices;
103     response.split (devices, "\n", -1, false);
104 
105     for (const auto device: devices)
106         device_list.push_back (device.split ('\t').first);
107 
108     return error;
109 }
110 
111 Error
112 AdbClient::SetPortForwarding (const uint16_t port)
113 {
114     char message[48];
115     snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
116 
117     const auto error = SendDeviceMessage (message);
118     if (error.Fail ())
119         return error;
120 
121     return ReadResponseStatus ();
122 }
123 
124 Error
125 AdbClient::DeletePortForwarding (const uint16_t port)
126 {
127     char message[32];
128     snprintf (message, sizeof (message), "killforward:tcp:%d", port);
129 
130     const auto error = SendDeviceMessage (message);
131     if (error.Fail ())
132         return error;
133 
134     return ReadResponseStatus ();
135 }
136 
137 Error
138 AdbClient::SendMessage (const std::string &packet)
139 {
140     auto error = Connect ();
141     if (error.Fail ())
142         return error;
143 
144     char length_buffer[5];
145     snprintf (length_buffer, sizeof (length_buffer), "%04zx", packet.size ());
146 
147     ConnectionStatus status;
148 
149     m_conn.Write (length_buffer, 4, status, &error);
150     if (error.Fail ())
151         return error;
152 
153     m_conn.Write (packet.c_str (), packet.size (), status, &error);
154     return error;
155 }
156 
157 Error
158 AdbClient::SendDeviceMessage (const std::string &packet)
159 {
160     std::ostringstream msg;
161     msg << "host-serial:" << m_device_id << ":" << packet;
162     return SendMessage (msg.str ());
163 }
164 
165 Error
166 AdbClient::ReadMessage (std::string &message)
167 {
168     message.clear ();
169 
170     char buffer[5];
171     buffer[4] = 0;
172 
173     Error error;
174     ConnectionStatus status;
175 
176     m_conn.Read (buffer, 4, kConnTimeout, status, &error);
177     if (error.Fail ())
178         return error;
179 
180     size_t packet_len = 0;
181     sscanf (buffer, "%zx", &packet_len);
182     std::string result (packet_len, 0);
183     m_conn.Read (&result[0], packet_len, kConnTimeout, status, &error);
184     if (error.Success ())
185         result.swap (message);
186 
187     return error;
188 }
189 
190 Error
191 AdbClient::ReadResponseStatus()
192 {
193     char buffer[5];
194 
195     static const size_t packet_len = 4;
196     buffer[packet_len] = 0;
197 
198     Error error;
199     ConnectionStatus status;
200 
201     m_conn.Read (buffer, packet_len, kConnTimeout, status, &error);
202     if (error.Fail ())
203       return error;
204 
205     if (strncmp (buffer, kOKAY, packet_len) != 0)
206     {
207         if (strncmp (buffer, kFAIL, packet_len) == 0)
208         {
209             std::string error_message;
210             error = ReadMessage (error_message);
211             if (error.Fail ())
212                 return error;
213             error.SetErrorString (error_message.c_str ());
214         }
215         else
216             error.SetErrorStringWithFormat ("\"%s\" expected from adb, received: \"%s\"", kOKAY, buffer);
217     }
218 
219     return error;
220 }
221