Chromium Code Reviews| 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) { | |
|
vsevik
2013/03/11 11:47:14
HexEncode(&length, 2);
| |
| 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 AddRef(); // Balanced in *AndDie | |
| 41 } | |
| 42 | |
| 43 ADBClientSocket::~ADBClientSocket() { | |
| 44 } | |
| 45 | |
| 46 void ADBClientSocket::InnerQuery(int port, | |
| 47 const std::string& query, | |
| 48 const Callback& callback) { | |
| 49 if (query.length() > 0xFFFF) { | |
| 50 ReportErrorAndDie("Input message is too big"); | |
| 51 return; | |
| 52 } | |
| 53 callback_ = callback; | |
| 54 | |
| 55 net::IPAddressNumber ip_number; | |
| 56 if (!net::ParseIPLiteralToNumber("127.0.0.1", &ip_number)) { | |
| 57 ReportErrorAndDie("Could not connect to ADB"); | |
| 58 return; | |
| 59 } | |
| 60 | |
| 61 net::AddressList address_list = | |
| 62 net::AddressList::CreateFromIPAddress(ip_number, port); | |
| 63 socket_.reset(new net::TCPClientSocket(address_list, NULL, | |
| 64 net::NetLog::Source())); | |
| 65 std::string message = EncodeLength(query.length()) + query; | |
| 66 scoped_refptr<net::StringIOBuffer> request_buffer = | |
| 67 new net::StringIOBuffer(message); | |
| 68 int result = socket_->Connect(base::Bind( | |
| 69 &ADBClientSocket::OnConnectComplete, base::Unretained(this), | |
| 70 request_buffer)); | |
| 71 if (result != net::ERR_IO_PENDING) | |
| 72 ReportErrorAndDie("Could not connect to ADB"); | |
| 73 } | |
| 74 | |
| 75 void ADBClientSocket::OnConnectComplete( | |
| 76 scoped_refptr<net::StringIOBuffer> request_buffer, | |
| 77 int result) { | |
| 78 if (!CheckNetResultOrDie(result)) | |
| 79 return; | |
| 80 result = socket_->Write(request_buffer, request_buffer->size(), | |
| 81 base::Bind(&ADBClientSocket::OnWriteComplete, base::Unretained(this))); | |
| 82 if (result != net::ERR_IO_PENDING) | |
| 83 OnWriteComplete(result); | |
| 84 } | |
| 85 | |
| 86 void ADBClientSocket::OnWriteComplete(int result) { | |
| 87 if (!CheckNetResultOrDie(result)) | |
| 88 return; | |
| 89 scoped_refptr<net::IOBuffer> response_buffer = | |
| 90 new net::IOBuffer(kBufferSize); | |
| 91 result = socket_->Read(response_buffer, kBufferSize, | |
| 92 base::Bind(&ADBClientSocket::OnReadComplete, base::Unretained(this), | |
| 93 response_buffer)); | |
| 94 if (result != net::ERR_IO_PENDING) | |
| 95 OnReadComplete(response_buffer, result); | |
| 96 } | |
| 97 | |
| 98 void ADBClientSocket::OnReadComplete( | |
| 99 scoped_refptr<net::IOBuffer> response_buffer, | |
| 100 int result) { | |
| 101 if (!CheckNetResultOrDie(result)) | |
| 102 return; | |
| 103 | |
| 104 response_ += std::string(response_buffer->data(), result); | |
| 105 if (expected_response_length_ == -1) { | |
| 106 // Reading header | |
| 107 if (result < 8) { | |
| 108 ReportErrorAndDie("Response is too short: " + response_); | |
| 109 return; | |
| 110 } | |
| 111 | |
| 112 std::string status = response_.substr(0, 4); | |
| 113 if (status != "OKAY" && status != "FAIL") { | |
| 114 ReportInvalidResponseAndDie(); | |
| 115 return; | |
| 116 } | |
| 117 std::string payload_length = response_.substr(4, 4); | |
| 118 if (!base::HexStringToInt(response_.substr(4, 4), | |
| 119 &expected_response_length_)) { | |
| 120 ReportInvalidResponseAndDie(); | |
| 121 return; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 if (static_cast<int>(response_.length() - 8) == expected_response_length_) { | |
| 126 ReportSuccessAndDie(); | |
| 127 return; | |
| 128 } | |
| 129 | |
| 130 // Read tail | |
| 131 result = socket_->Read(response_buffer, kBufferSize, | |
| 132 base::Bind(&ADBClientSocket::OnReadComplete, base::Unretained(this), | |
| 133 response_buffer)); | |
| 134 if (result != net::ERR_IO_PENDING) | |
| 135 OnReadComplete(response_buffer, result); | |
| 136 } | |
| 137 | |
| 138 bool ADBClientSocket::CheckNetResultOrDie(int result) { | |
| 139 if (result >= 0) | |
| 140 return true; | |
| 141 ReportErrorAndDie(base::StringPrintf("Internal error %d", result)); | |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 void ADBClientSocket::ReportSuccessAndDie() { | |
| 146 callback_.Run(std::string(), response_.substr(8, response_.length() - 8)); | |
|
vsevik
2013/03/11 11:47:14
callback_.Run(std::string(), response_.substr(8));
| |
| 147 Release(); // Balanced in the constructor. | |
| 148 } | |
| 149 | |
| 150 void ADBClientSocket::ReportInvalidResponseAndDie() { | |
| 151 callback_.Run("Invalid response: " + response_, std::string()); | |
| 152 Release(); // Balanced in the constructor. | |
| 153 } | |
| 154 | |
| 155 void ADBClientSocket::ReportErrorAndDie(const std::string& error) { | |
| 156 callback_.Run(error, std::string()); | |
| 157 Release(); // Balanced in the constructor. | |
| 158 } | |
| OLD | NEW |