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