OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/devtools/adb_client_socket.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" |
| 9 #include "base/stringprintf.h" |
| 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "net/base/net_errors.h" |
| 12 |
| 13 namespace { |
| 14 |
| 15 const int kBufferSize = 16 * 1024; |
| 16 |
| 17 std::string EncodeLength(size_t length) { |
| 18 static const char kHexChars[] = "0123456789ABCDEF"; |
| 19 |
| 20 std::string result(4, '\0'); |
| 21 char b = reinterpret_cast<const char*>(&length)[1]; |
| 22 result[0] = kHexChars[(b >> 4) & 0xf]; |
| 23 result[1] = kHexChars[b & 0xf]; |
| 24 b = reinterpret_cast<const char*>(&length)[0]; |
| 25 result[2] = kHexChars[(b >> 4) & 0xf]; |
| 26 result[3] = kHexChars[b & 0xf]; |
| 27 return result; |
| 28 } |
| 29 |
| 30 } // namespace |
| 31 |
| 32 // static |
| 33 void ADBClientSocket::Query(int port, |
| 34 const std::string& query, |
| 35 const Callback& callback) { |
| 36 (new ADBClientSocket())->InnerQuery(port, query, callback); |
| 37 } |
| 38 |
| 39 ADBClientSocket::ADBClientSocket() : expected_response_length_(-1) { |
| 40 } |
| 41 |
| 42 ADBClientSocket::~ADBClientSocket() { |
| 43 } |
| 44 |
| 45 void ADBClientSocket::InnerQuery(int port, |
| 46 const std::string& query, |
| 47 const Callback& callback) { |
| 48 if (query.length() > 0xFFFF) { |
| 49 ReportErrorAndDie("Input message is too big"); |
| 50 return; |
| 51 } |
| 52 callback_ = callback; |
| 53 |
| 54 net::IPAddressNumber ip_number; |
| 55 if (!net::ParseIPLiteralToNumber("127.0.0.1", &ip_number)) { |
| 56 ReportErrorAndDie("Could not connect to ADB"); |
| 57 return; |
| 58 } |
| 59 |
| 60 net::AddressList address_list = |
| 61 net::AddressList::CreateFromIPAddress(ip_number, port); |
| 62 socket_.reset(new net::TCPClientSocket(address_list, NULL, |
| 63 net::NetLog::Source())); |
| 64 std::string message = EncodeLength(query.length()) + query; |
| 65 scoped_refptr<net::StringIOBuffer> request_buffer = |
| 66 new net::StringIOBuffer(message); |
| 67 int result = socket_->Connect(base::Bind(&ADBClientSocket::OnConnectComplete, |
| 68 base::Unretained(this), |
| 69 request_buffer)); |
| 70 if (result != net::ERR_IO_PENDING) |
| 71 ReportErrorAndDie("Could not connect to ADB"); |
| 72 } |
| 73 |
| 74 void ADBClientSocket::OnConnectComplete( |
| 75 scoped_refptr<net::StringIOBuffer> request_buffer, |
| 76 int result) { |
| 77 if (!CheckNetResultOrDie(result)) |
| 78 return; |
| 79 result = socket_->Write(request_buffer, request_buffer->size(), |
| 80 base::Bind(&ADBClientSocket::OnWriteComplete, base::Unretained(this))); |
| 81 if (result != net::ERR_IO_PENDING) |
| 82 OnWriteComplete(result); |
| 83 } |
| 84 |
| 85 void ADBClientSocket::OnWriteComplete(int result) { |
| 86 if (!CheckNetResultOrDie(result)) |
| 87 return; |
| 88 scoped_refptr<net::IOBuffer> response_buffer = |
| 89 new net::IOBuffer(kBufferSize); |
| 90 result = socket_->Read(response_buffer, kBufferSize, |
| 91 base::Bind(&ADBClientSocket::OnReadComplete, base::Unretained(this), |
| 92 response_buffer)); |
| 93 if (result != net::ERR_IO_PENDING) |
| 94 OnReadComplete(response_buffer, result); |
| 95 } |
| 96 |
| 97 void ADBClientSocket::OnReadComplete( |
| 98 scoped_refptr<net::IOBuffer> response_buffer, |
| 99 int result) { |
| 100 if (!CheckNetResultOrDie(result)) |
| 101 return; |
| 102 |
| 103 response_ += std::string(response_buffer->data(), result); |
| 104 if (expected_response_length_ == -1) { |
| 105 // Reading header |
| 106 if (result < 8) { |
| 107 ReportErrorAndDie("Response is too short: " + response_); |
| 108 return; |
| 109 } |
| 110 |
| 111 std::string status = response_.substr(0, 4); |
| 112 if (status != "OKAY" && status != "FAIL") { |
| 113 ReportInvalidResponseAndDie(); |
| 114 return; |
| 115 } |
| 116 std::string payload_length = response_.substr(4, 4); |
| 117 if (!base::HexStringToInt(response_.substr(4, 4), |
| 118 &expected_response_length_)) { |
| 119 ReportInvalidResponseAndDie(); |
| 120 return; |
| 121 } |
| 122 } |
| 123 |
| 124 if (static_cast<int>(response_.length() - 8) == expected_response_length_) { |
| 125 ReportSuccessAndDie(); |
| 126 return; |
| 127 } |
| 128 |
| 129 // Read tail |
| 130 result = socket_->Read(response_buffer, kBufferSize, |
| 131 base::Bind(&ADBClientSocket::OnReadComplete, base::Unretained(this), |
| 132 response_buffer)); |
| 133 if (result != net::ERR_IO_PENDING) |
| 134 OnReadComplete(response_buffer, result); |
| 135 } |
| 136 |
| 137 bool ADBClientSocket::CheckNetResultOrDie(int result) { |
| 138 if (result >= 0) |
| 139 return true; |
| 140 ReportErrorAndDie(base::StringPrintf("Internal error %d", result)); |
| 141 return false; |
| 142 } |
| 143 |
| 144 void ADBClientSocket::ReportSuccessAndDie() { |
| 145 callback_.Run(std::string(), response_.substr(8)); |
| 146 Destroy(); |
| 147 } |
| 148 |
| 149 void ADBClientSocket::ReportInvalidResponseAndDie() { |
| 150 callback_.Run("Invalid response: " + response_, std::string()); |
| 151 Destroy(); |
| 152 } |
| 153 |
| 154 void ADBClientSocket::ReportErrorAndDie(const std::string& error) { |
| 155 callback_.Run(error, std::string()); |
| 156 Destroy(); |
| 157 } |
| 158 |
| 159 void ADBClientSocket::Destroy() { |
| 160 delete this; |
| 161 } |
OLD | NEW |