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 |