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