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