OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/socket/socks5_client_socket.h" | 5 #include "net/socket/socks5_client_socket.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 DCHECK(transport_.get()); | 68 DCHECK(transport_.get()); |
69 DCHECK(transport_->socket()); | 69 DCHECK(transport_->socket()); |
70 DCHECK(transport_->socket()->IsConnected()); | 70 DCHECK(transport_->socket()->IsConnected()); |
71 DCHECK_EQ(STATE_NONE, next_state_); | 71 DCHECK_EQ(STATE_NONE, next_state_); |
72 DCHECK(!user_callback_); | 72 DCHECK(!user_callback_); |
73 | 73 |
74 // If already connected, then just return OK. | 74 // If already connected, then just return OK. |
75 if (completed_handshake_) | 75 if (completed_handshake_) |
76 return OK; | 76 return OK; |
77 | 77 |
78 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT); | 78 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); |
79 | 79 |
80 next_state_ = STATE_GREET_WRITE; | 80 next_state_ = STATE_GREET_WRITE; |
81 buffer_.clear(); | 81 buffer_.clear(); |
82 | 82 |
83 int rv = DoLoop(OK); | 83 int rv = DoLoop(OK); |
84 if (rv == ERR_IO_PENDING) { | 84 if (rv == ERR_IO_PENDING) { |
85 user_callback_ = callback; | 85 user_callback_ = callback; |
86 } else { | 86 } else { |
87 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT); | 87 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); |
88 } | 88 } |
89 return rv; | 89 return rv; |
90 } | 90 } |
91 | 91 |
92 void SOCKS5ClientSocket::Disconnect() { | 92 void SOCKS5ClientSocket::Disconnect() { |
93 completed_handshake_ = false; | 93 completed_handshake_ = false; |
94 transport_->socket()->Disconnect(); | 94 transport_->socket()->Disconnect(); |
95 | 95 |
96 // Reset other states to make sure they aren't mistakenly used later. | 96 // Reset other states to make sure they aren't mistakenly used later. |
97 // These are the states initialized by Connect(). | 97 // These are the states initialized by Connect(). |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 // clear user_callback_ up front. | 145 // clear user_callback_ up front. |
146 CompletionCallback* c = user_callback_; | 146 CompletionCallback* c = user_callback_; |
147 user_callback_ = NULL; | 147 user_callback_ = NULL; |
148 c->Run(result); | 148 c->Run(result); |
149 } | 149 } |
150 | 150 |
151 void SOCKS5ClientSocket::OnIOComplete(int result) { | 151 void SOCKS5ClientSocket::OnIOComplete(int result) { |
152 DCHECK_NE(STATE_NONE, next_state_); | 152 DCHECK_NE(STATE_NONE, next_state_); |
153 int rv = DoLoop(result); | 153 int rv = DoLoop(result); |
154 if (rv != ERR_IO_PENDING) { | 154 if (rv != ERR_IO_PENDING) { |
155 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT); | 155 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); |
156 DoCallback(rv); | 156 DoCallback(rv); |
157 } | 157 } |
158 } | 158 } |
159 | 159 |
160 int SOCKS5ClientSocket::DoLoop(int last_io_result) { | 160 int SOCKS5ClientSocket::DoLoop(int last_io_result) { |
161 DCHECK_NE(next_state_, STATE_NONE); | 161 DCHECK_NE(next_state_, STATE_NONE); |
162 int rv = last_io_result; | 162 int rv = last_io_result; |
163 do { | 163 do { |
164 State state = next_state_; | 164 State state = next_state_; |
165 next_state_ = STATE_NONE; | 165 next_state_ = STATE_NONE; |
166 switch (state) { | 166 switch (state) { |
167 case STATE_GREET_WRITE: | 167 case STATE_GREET_WRITE: |
168 DCHECK_EQ(OK, rv); | 168 DCHECK_EQ(OK, rv); |
169 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE); | 169 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE, NULL); |
170 rv = DoGreetWrite(); | 170 rv = DoGreetWrite(); |
171 break; | 171 break; |
172 case STATE_GREET_WRITE_COMPLETE: | 172 case STATE_GREET_WRITE_COMPLETE: |
173 rv = DoGreetWriteComplete(rv); | 173 rv = DoGreetWriteComplete(rv); |
174 net_log_.EndEvent(NetLog::TYPE_SOCKS5_GREET_WRITE); | 174 net_log_.EndEvent(NetLog::TYPE_SOCKS5_GREET_WRITE, NULL); |
175 break; | 175 break; |
176 case STATE_GREET_READ: | 176 case STATE_GREET_READ: |
177 DCHECK_EQ(OK, rv); | 177 DCHECK_EQ(OK, rv); |
178 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ); | 178 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ, NULL); |
179 rv = DoGreetRead(); | 179 rv = DoGreetRead(); |
180 break; | 180 break; |
181 case STATE_GREET_READ_COMPLETE: | 181 case STATE_GREET_READ_COMPLETE: |
182 rv = DoGreetReadComplete(rv); | 182 rv = DoGreetReadComplete(rv); |
183 net_log_.EndEvent(NetLog::TYPE_SOCKS5_GREET_READ); | 183 net_log_.EndEvent(NetLog::TYPE_SOCKS5_GREET_READ, NULL); |
184 break; | 184 break; |
185 case STATE_HANDSHAKE_WRITE: | 185 case STATE_HANDSHAKE_WRITE: |
186 DCHECK_EQ(OK, rv); | 186 DCHECK_EQ(OK, rv); |
187 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); | 187 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, NULL); |
188 rv = DoHandshakeWrite(); | 188 rv = DoHandshakeWrite(); |
189 break; | 189 break; |
190 case STATE_HANDSHAKE_WRITE_COMPLETE: | 190 case STATE_HANDSHAKE_WRITE_COMPLETE: |
191 rv = DoHandshakeWriteComplete(rv); | 191 rv = DoHandshakeWriteComplete(rv); |
192 net_log_.EndEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); | 192 net_log_.EndEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, NULL); |
193 break; | 193 break; |
194 case STATE_HANDSHAKE_READ: | 194 case STATE_HANDSHAKE_READ: |
195 DCHECK_EQ(OK, rv); | 195 DCHECK_EQ(OK, rv); |
196 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); | 196 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, NULL); |
197 rv = DoHandshakeRead(); | 197 rv = DoHandshakeRead(); |
198 break; | 198 break; |
199 case STATE_HANDSHAKE_READ_COMPLETE: | 199 case STATE_HANDSHAKE_READ_COMPLETE: |
200 rv = DoHandshakeReadComplete(rv); | 200 rv = DoHandshakeReadComplete(rv); |
201 net_log_.EndEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); | 201 net_log_.EndEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, NULL); |
202 break; | 202 break; |
203 default: | 203 default: |
204 NOTREACHED() << "bad state"; | 204 NOTREACHED() << "bad state"; |
205 rv = ERR_UNEXPECTED; | 205 rv = ERR_UNEXPECTED; |
206 break; | 206 break; |
207 } | 207 } |
208 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 208 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
209 return rv; | 209 return rv; |
210 } | 210 } |
211 | 211 |
212 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 212 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
213 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; | 213 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; |
214 | 214 |
215 int SOCKS5ClientSocket::DoGreetWrite() { | 215 int SOCKS5ClientSocket::DoGreetWrite() { |
216 // Since we only have 1 byte to send the hostname length in, if the | 216 // Since we only have 1 byte to send the hostname length in, if the |
217 // URL has a hostname longer than 255 characters we can't send it. | 217 // URL has a hostname longer than 255 characters we can't send it. |
218 if (0xFF < host_request_info_.hostname().size()) { | 218 if (0xFF < host_request_info_.hostname().size()) { |
219 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); | 219 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG, NULL); |
220 return ERR_SOCKS_CONNECTION_FAILED; | 220 return ERR_SOCKS_CONNECTION_FAILED; |
221 } | 221 } |
222 | 222 |
223 if (buffer_.empty()) { | 223 if (buffer_.empty()) { |
224 buffer_ = std::string(kSOCKS5GreetWriteData, | 224 buffer_ = std::string(kSOCKS5GreetWriteData, |
225 arraysize(kSOCKS5GreetWriteData)); | 225 arraysize(kSOCKS5GreetWriteData)); |
226 bytes_sent_ = 0; | 226 bytes_sent_ = 0; |
227 } | 227 } |
228 | 228 |
229 next_state_ = STATE_GREET_WRITE_COMPLETE; | 229 next_state_ = STATE_GREET_WRITE_COMPLETE; |
(...skipping 26 matching lines...) Expand all Loading... |
256 handshake_buf_ = new IOBuffer(handshake_buf_len); | 256 handshake_buf_ = new IOBuffer(handshake_buf_len); |
257 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 257 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
258 &io_callback_); | 258 &io_callback_); |
259 } | 259 } |
260 | 260 |
261 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { | 261 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { |
262 if (result < 0) | 262 if (result < 0) |
263 return result; | 263 return result; |
264 | 264 |
265 if (result == 0) { | 265 if (result == 0) { |
266 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); | 266 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING, |
| 267 NULL); |
267 return ERR_SOCKS_CONNECTION_FAILED; | 268 return ERR_SOCKS_CONNECTION_FAILED; |
268 } | 269 } |
269 | 270 |
270 bytes_received_ += result; | 271 bytes_received_ += result; |
271 buffer_.append(handshake_buf_->data(), result); | 272 buffer_.append(handshake_buf_->data(), result); |
272 if (bytes_received_ < kGreetReadHeaderSize) { | 273 if (bytes_received_ < kGreetReadHeaderSize) { |
273 next_state_ = STATE_GREET_READ; | 274 next_state_ = STATE_GREET_READ; |
274 return OK; | 275 return OK; |
275 } | 276 } |
276 | 277 |
277 // Got the greet data. | 278 // Got the greet data. |
278 if (buffer_[0] != kSOCKS5Version) { | 279 if (buffer_[0] != kSOCKS5Version) { |
279 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 280 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
280 "version", buffer_[0]); | 281 new NetLogIntegerParameter("version", buffer_[0])); |
281 return ERR_SOCKS_CONNECTION_FAILED; | 282 return ERR_SOCKS_CONNECTION_FAILED; |
282 } | 283 } |
283 if (buffer_[1] != 0x00) { | 284 if (buffer_[1] != 0x00) { |
284 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, | 285 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, |
285 "method", buffer_[1]); | 286 new NetLogIntegerParameter("method", buffer_[1])); |
286 return ERR_SOCKS_CONNECTION_FAILED; | 287 return ERR_SOCKS_CONNECTION_FAILED; |
287 } | 288 } |
288 | 289 |
289 buffer_.clear(); | 290 buffer_.clear(); |
290 next_state_ = STATE_HANDSHAKE_WRITE; | 291 next_state_ = STATE_HANDSHAKE_WRITE; |
291 return OK; | 292 return OK; |
292 } | 293 } |
293 | 294 |
294 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 295 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
295 const { | 296 const { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 367 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
367 &io_callback_); | 368 &io_callback_); |
368 } | 369 } |
369 | 370 |
370 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 371 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
371 if (result < 0) | 372 if (result < 0) |
372 return result; | 373 return result; |
373 | 374 |
374 // The underlying socket closed unexpectedly. | 375 // The underlying socket closed unexpectedly. |
375 if (result == 0) { | 376 if (result == 0) { |
376 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); | 377 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE, |
| 378 NULL); |
377 return ERR_SOCKS_CONNECTION_FAILED; | 379 return ERR_SOCKS_CONNECTION_FAILED; |
378 } | 380 } |
379 | 381 |
380 buffer_.append(handshake_buf_->data(), result); | 382 buffer_.append(handshake_buf_->data(), result); |
381 bytes_received_ += result; | 383 bytes_received_ += result; |
382 | 384 |
383 // When the first few bytes are read, check how many more are required | 385 // When the first few bytes are read, check how many more are required |
384 // and accordingly increase them | 386 // and accordingly increase them |
385 if (bytes_received_ == kReadHeaderSize) { | 387 if (bytes_received_ == kReadHeaderSize) { |
386 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { | 388 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { |
387 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 389 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
388 "version", buffer_[0]); | 390 new NetLogIntegerParameter("version", buffer_[0])); |
389 return ERR_SOCKS_CONNECTION_FAILED; | 391 return ERR_SOCKS_CONNECTION_FAILED; |
390 } | 392 } |
391 if (buffer_[1] != 0x00) { | 393 if (buffer_[1] != 0x00) { |
392 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_SERVER_ERROR, | 394 net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR, |
393 "error_code", buffer_[1]); | 395 new NetLogIntegerParameter("error_code", buffer_[1])); |
394 return ERR_SOCKS_CONNECTION_FAILED; | 396 return ERR_SOCKS_CONNECTION_FAILED; |
395 } | 397 } |
396 | 398 |
397 // We check the type of IP/Domain the server returns and accordingly | 399 // We check the type of IP/Domain the server returns and accordingly |
398 // increase the size of the response. For domains, we need to read the | 400 // increase the size of the response. For domains, we need to read the |
399 // size of the domain, so the initial request size is upto the domain | 401 // size of the domain, so the initial request size is upto the domain |
400 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 402 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
401 // read, we substract 1 byte from the additional request size. | 403 // read, we substract 1 byte from the additional request size. |
402 SocksEndPointAddressType address_type = | 404 SocksEndPointAddressType address_type = |
403 static_cast<SocksEndPointAddressType>(buffer_[3]); | 405 static_cast<SocksEndPointAddressType>(buffer_[3]); |
404 if (address_type == kEndPointDomain) | 406 if (address_type == kEndPointDomain) |
405 read_header_size += static_cast<uint8>(buffer_[4]); | 407 read_header_size += static_cast<uint8>(buffer_[4]); |
406 else if (address_type == kEndPointResolvedIPv4) | 408 else if (address_type == kEndPointResolvedIPv4) |
407 read_header_size += sizeof(struct in_addr) - 1; | 409 read_header_size += sizeof(struct in_addr) - 1; |
408 else if (address_type == kEndPointResolvedIPv6) | 410 else if (address_type == kEndPointResolvedIPv6) |
409 read_header_size += sizeof(struct in6_addr) - 1; | 411 read_header_size += sizeof(struct in6_addr) - 1; |
410 else { | 412 else { |
411 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, | 413 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, |
412 "address_type", buffer_[3]); | 414 new NetLogIntegerParameter("address_type", buffer_[3])); |
413 return ERR_SOCKS_CONNECTION_FAILED; | 415 return ERR_SOCKS_CONNECTION_FAILED; |
414 } | 416 } |
415 | 417 |
416 read_header_size += 2; // for the port. | 418 read_header_size += 2; // for the port. |
417 next_state_ = STATE_HANDSHAKE_READ; | 419 next_state_ = STATE_HANDSHAKE_READ; |
418 return OK; | 420 return OK; |
419 } | 421 } |
420 | 422 |
421 // When the final bytes are read, setup handshake. We ignore the rest | 423 // When the final bytes are read, setup handshake. We ignore the rest |
422 // of the response since they represent the SOCKSv5 endpoint and have | 424 // of the response since they represent the SOCKSv5 endpoint and have |
423 // no use when doing a tunnel connection. | 425 // no use when doing a tunnel connection. |
424 if (bytes_received_ == read_header_size) { | 426 if (bytes_received_ == read_header_size) { |
425 completed_handshake_ = true; | 427 completed_handshake_ = true; |
426 buffer_.clear(); | 428 buffer_.clear(); |
427 next_state_ = STATE_NONE; | 429 next_state_ = STATE_NONE; |
428 return OK; | 430 return OK; |
429 } | 431 } |
430 | 432 |
431 next_state_ = STATE_HANDSHAKE_READ; | 433 next_state_ = STATE_HANDSHAKE_READ; |
432 return OK; | 434 return OK; |
433 } | 435 } |
434 | 436 |
435 int SOCKS5ClientSocket::GetPeerAddress(AddressList* address) const { | 437 int SOCKS5ClientSocket::GetPeerAddress(AddressList* address) const { |
436 return transport_->socket()->GetPeerAddress(address); | 438 return transport_->socket()->GetPeerAddress(address); |
437 } | 439 } |
438 | 440 |
439 } // namespace net | 441 } // namespace net |
OLD | NEW |