| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/trace_event.h" | 9 #include "base/trace_event.h" |
| 10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
| 11 #include "net/base/load_log.h" | 11 #include "net/base/load_log.h" |
| 12 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
| 13 #include "net/base/sys_addrinfo.h" | 13 #include "net/base/sys_addrinfo.h" |
| 14 | 14 |
| 15 namespace net { | 15 namespace net { |
| 16 | 16 |
| 17 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; | 17 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; |
| 18 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; | 18 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; |
| 19 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; | 19 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; |
| 20 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; | 20 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; |
| 21 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; | 21 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; |
| 22 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; | 22 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; |
| 23 | 23 |
| 24 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); | 24 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); |
| 25 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); | 25 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); |
| 26 | 26 |
| 27 SOCKS5ClientSocket::SOCKS5ClientSocket(ClientSocket* transport_socket, | 27 SOCKS5ClientSocket::SOCKS5ClientSocket(ClientSocket* transport_socket, |
| 28 const HostResolver::RequestInfo& req_info, | 28 const HostResolver::RequestInfo& req_info) |
| 29 HostResolver* host_resolver) | |
| 30 : ALLOW_THIS_IN_INITIALIZER_LIST( | 29 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 31 io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)), | 30 io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)), |
| 32 transport_(transport_socket), | 31 transport_(transport_socket), |
| 33 next_state_(STATE_NONE), | 32 next_state_(STATE_NONE), |
| 34 address_type_(kEndPointUnresolved), | |
| 35 user_callback_(NULL), | 33 user_callback_(NULL), |
| 36 completed_handshake_(false), | 34 completed_handshake_(false), |
| 37 bytes_sent_(0), | 35 bytes_sent_(0), |
| 38 bytes_received_(0), | 36 bytes_received_(0), |
| 39 read_header_size(kReadHeaderSize), | 37 read_header_size(kReadHeaderSize), |
| 40 host_request_info_(req_info) { | 38 host_request_info_(req_info) { |
| 41 if (host_resolver) | |
| 42 host_resolver_.reset(new SingleRequestHostResolver(host_resolver)); | |
| 43 } | 39 } |
| 44 | 40 |
| 45 SOCKS5ClientSocket::~SOCKS5ClientSocket() { | 41 SOCKS5ClientSocket::~SOCKS5ClientSocket() { |
| 46 Disconnect(); | 42 Disconnect(); |
| 47 } | 43 } |
| 48 | 44 |
| 49 int SOCKS5ClientSocket::Connect(CompletionCallback* callback, | 45 int SOCKS5ClientSocket::Connect(CompletionCallback* callback, |
| 50 LoadLog* load_log) { | 46 LoadLog* load_log) { |
| 51 DCHECK(transport_.get()); | 47 DCHECK(transport_.get()); |
| 52 DCHECK(transport_->IsConnected()); | 48 DCHECK(transport_->IsConnected()); |
| 53 DCHECK_EQ(STATE_NONE, next_state_); | 49 DCHECK_EQ(STATE_NONE, next_state_); |
| 54 DCHECK(!user_callback_); | 50 DCHECK(!user_callback_); |
| 55 | 51 |
| 56 // If already connected, then just return OK. | 52 // If already connected, then just return OK. |
| 57 if (completed_handshake_) | 53 if (completed_handshake_) |
| 58 return OK; | 54 return OK; |
| 59 | 55 |
| 60 load_log_ = load_log; | 56 load_log_ = load_log; |
| 61 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); | 57 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); |
| 62 | 58 |
| 63 // If a host resolver was given, try to resolve the address locally. | 59 next_state_ = STATE_GREET_WRITE; |
| 64 // Otherwise let the proxy server handle the resolving. | 60 buffer_.clear(); |
| 65 if (host_resolver_.get()) { | |
| 66 next_state_ = STATE_RESOLVE_HOST; | |
| 67 } else { | |
| 68 next_state_ = STATE_GREET_WRITE; | |
| 69 address_type_ = kEndPointFailedDomain; | |
| 70 } | |
| 71 | 61 |
| 72 int rv = DoLoop(OK); | 62 int rv = DoLoop(OK); |
| 73 if (rv == ERR_IO_PENDING) { | 63 if (rv == ERR_IO_PENDING) { |
| 74 user_callback_ = callback; | 64 user_callback_ = callback; |
| 75 } else { | 65 } else { |
| 76 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); | 66 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); |
| 77 load_log_ = NULL; | 67 load_log_ = NULL; |
| 78 } | 68 } |
| 79 return rv; | 69 return rv; |
| 80 } | 70 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 } | 134 } |
| 145 } | 135 } |
| 146 | 136 |
| 147 int SOCKS5ClientSocket::DoLoop(int last_io_result) { | 137 int SOCKS5ClientSocket::DoLoop(int last_io_result) { |
| 148 DCHECK_NE(next_state_, STATE_NONE); | 138 DCHECK_NE(next_state_, STATE_NONE); |
| 149 int rv = last_io_result; | 139 int rv = last_io_result; |
| 150 do { | 140 do { |
| 151 State state = next_state_; | 141 State state = next_state_; |
| 152 next_state_ = STATE_NONE; | 142 next_state_ = STATE_NONE; |
| 153 switch (state) { | 143 switch (state) { |
| 154 case STATE_RESOLVE_HOST: | |
| 155 DCHECK_EQ(OK, rv); | |
| 156 rv = DoResolveHost(); | |
| 157 break; | |
| 158 case STATE_RESOLVE_HOST_COMPLETE: | |
| 159 rv = DoResolveHostComplete(rv); | |
| 160 break; | |
| 161 case STATE_GREET_WRITE: | 144 case STATE_GREET_WRITE: |
| 162 DCHECK_EQ(OK, rv); | 145 DCHECK_EQ(OK, rv); |
| 163 rv = DoGreetWrite(); | 146 rv = DoGreetWrite(); |
| 164 break; | 147 break; |
| 165 case STATE_GREET_WRITE_COMPLETE: | 148 case STATE_GREET_WRITE_COMPLETE: |
| 166 rv = DoGreetWriteComplete(rv); | 149 rv = DoGreetWriteComplete(rv); |
| 167 break; | 150 break; |
| 168 case STATE_GREET_READ: | 151 case STATE_GREET_READ: |
| 169 DCHECK_EQ(OK, rv); | 152 DCHECK_EQ(OK, rv); |
| 170 rv = DoGreetRead(); | 153 rv = DoGreetRead(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 188 break; | 171 break; |
| 189 default: | 172 default: |
| 190 NOTREACHED() << "bad state"; | 173 NOTREACHED() << "bad state"; |
| 191 rv = ERR_UNEXPECTED; | 174 rv = ERR_UNEXPECTED; |
| 192 break; | 175 break; |
| 193 } | 176 } |
| 194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 177 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 195 return rv; | 178 return rv; |
| 196 } | 179 } |
| 197 | 180 |
| 198 int SOCKS5ClientSocket::DoResolveHost() { | |
| 199 DCHECK_EQ(kEndPointUnresolved, address_type_); | |
| 200 | |
| 201 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | |
| 202 return host_resolver_->Resolve( | |
| 203 host_request_info_, &addresses_, &io_callback_, load_log_); | |
| 204 } | |
| 205 | |
| 206 int SOCKS5ClientSocket::DoResolveHostComplete(int result) { | |
| 207 DCHECK_EQ(kEndPointUnresolved, address_type_); | |
| 208 | |
| 209 bool ok = (result == OK); | |
| 210 next_state_ = STATE_GREET_WRITE; | |
| 211 if (ok) { | |
| 212 DCHECK(addresses_.head()); | |
| 213 struct sockaddr* host_info = addresses_.head()->ai_addr; | |
| 214 if (host_info->sa_family == AF_INET) { | |
| 215 address_type_ = kEndPointResolvedIPv4; | |
| 216 } else if (host_info->sa_family == AF_INET6) { | |
| 217 address_type_ = kEndPointResolvedIPv6; | |
| 218 } | |
| 219 } else { | |
| 220 address_type_ = kEndPointFailedDomain; | |
| 221 } | |
| 222 | |
| 223 buffer_.clear(); | |
| 224 | |
| 225 // Even if DNS resolution fails, we send OK since the server | |
| 226 // resolves the domain. | |
| 227 return OK; | |
| 228 } | |
| 229 | |
| 230 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 181 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
| 231 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; | 182 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; |
| 232 | 183 |
| 233 int SOCKS5ClientSocket::DoGreetWrite() { | 184 int SOCKS5ClientSocket::DoGreetWrite() { |
| 234 if (buffer_.empty()) { | 185 if (buffer_.empty()) { |
| 235 buffer_ = std::string(kSOCKS5GreetWriteData, | 186 buffer_ = std::string(kSOCKS5GreetWriteData, |
| 236 arraysize(kSOCKS5GreetWriteData)); | 187 arraysize(kSOCKS5GreetWriteData)); |
| 237 bytes_sent_ = 0; | 188 bytes_sent_ = 0; |
| 238 } | 189 } |
| 239 | 190 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 if (buffer_[0] != kSOCKS5Version || buffer_[1] != 0x00) | 236 if (buffer_[0] != kSOCKS5Version || buffer_[1] != 0x00) |
| 286 return ERR_INVALID_RESPONSE; // Unknown error | 237 return ERR_INVALID_RESPONSE; // Unknown error |
| 287 | 238 |
| 288 buffer_.clear(); | 239 buffer_.clear(); |
| 289 next_state_ = STATE_HANDSHAKE_WRITE; | 240 next_state_ = STATE_HANDSHAKE_WRITE; |
| 290 return OK; | 241 return OK; |
| 291 } | 242 } |
| 292 | 243 |
| 293 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 244 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
| 294 const { | 245 const { |
| 295 DCHECK_NE(kEndPointUnresolved, address_type_); | |
| 296 DCHECK(handshake->empty()); | 246 DCHECK(handshake->empty()); |
| 297 | 247 |
| 298 handshake->push_back(kSOCKS5Version); | 248 handshake->push_back(kSOCKS5Version); |
| 299 handshake->push_back(kTunnelCommand); // Connect command | 249 handshake->push_back(kTunnelCommand); // Connect command |
| 300 handshake->push_back(kNullByte); // Reserved null | 250 handshake->push_back(kNullByte); // Reserved null |
| 301 | 251 |
| 302 handshake->push_back(address_type_); // The type of connection | 252 handshake->push_back(kEndPointDomain); // The type of the address. |
| 303 if (address_type_ == kEndPointFailedDomain) { | |
| 304 if(256 <= host_request_info_.hostname().size()) | |
| 305 return ERR_ADDRESS_INVALID; | |
| 306 | 253 |
| 307 // First add the size of the hostname, followed by the hostname. | 254 // We only have 1 byte to send the length in, so if the hostname is |
| 308 handshake->push_back(static_cast<unsigned char>( | 255 // longer than this we can't send it! |
| 309 host_request_info_.hostname().size())); | 256 if(256 <= host_request_info_.hostname().size()) |
| 310 handshake->append(host_request_info_.hostname()); | 257 return ERR_INVALID_URL; |
| 311 | 258 |
| 312 } else if (address_type_ == kEndPointResolvedIPv4) { | 259 // First add the size of the hostname, followed by the hostname. |
| 313 struct sockaddr_in* ipv4_host = | 260 handshake->push_back(static_cast<unsigned char>( |
| 314 reinterpret_cast<struct sockaddr_in*>(addresses_.head()->ai_addr); | 261 host_request_info_.hostname().size())); |
| 315 handshake->append(reinterpret_cast<char*>(&ipv4_host->sin_addr), | 262 handshake->append(host_request_info_.hostname()); |
| 316 sizeof(ipv4_host->sin_addr)); | |
| 317 | |
| 318 } else if (address_type_ == kEndPointResolvedIPv6) { | |
| 319 struct sockaddr_in6* ipv6_host = | |
| 320 reinterpret_cast<struct sockaddr_in6*>(addresses_.head()->ai_addr); | |
| 321 handshake->append(reinterpret_cast<char*>(&ipv6_host->sin6_addr), | |
| 322 sizeof(ipv6_host->sin6_addr)); | |
| 323 | |
| 324 } else { | |
| 325 NOTREACHED(); | |
| 326 } | |
| 327 | 263 |
| 328 uint16 nw_port = htons(host_request_info_.port()); | 264 uint16 nw_port = htons(host_request_info_.port()); |
| 329 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); | 265 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); |
| 330 return OK; | 266 return OK; |
| 331 } | 267 } |
| 332 | 268 |
| 333 // Writes the SOCKS handshake data to the underlying socket connection. | 269 // Writes the SOCKS handshake data to the underlying socket connection. |
| 334 int SOCKS5ClientSocket::DoHandshakeWrite() { | 270 int SOCKS5ClientSocket::DoHandshakeWrite() { |
| 335 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; | 271 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; |
| 336 | 272 |
| 337 if (buffer_.empty()) { | 273 if (buffer_.empty()) { |
| 338 int rv = BuildHandshakeWriteBuffer(&buffer_); | 274 int rv = BuildHandshakeWriteBuffer(&buffer_); |
| 339 if (rv != OK) | 275 if (rv != OK) |
| 340 return rv; | 276 return rv; |
| 341 bytes_sent_ = 0; | 277 bytes_sent_ = 0; |
| 342 } | 278 } |
| 343 | 279 |
| 344 int handshake_buf_len = buffer_.size() - bytes_sent_; | 280 int handshake_buf_len = buffer_.size() - bytes_sent_; |
| 345 DCHECK_LT(0, handshake_buf_len); | 281 DCHECK_LT(0, handshake_buf_len); |
| 346 handshake_buf_ = new IOBuffer(handshake_buf_len); | 282 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 347 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], | 283 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], |
| 348 handshake_buf_len); | 284 handshake_buf_len); |
| 349 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); | 285 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); |
| 350 } | 286 } |
| 351 | 287 |
| 352 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { | 288 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { |
| 353 DCHECK_NE(kEndPointUnresolved, address_type_); | |
| 354 | |
| 355 if (result < 0) | 289 if (result < 0) |
| 356 return result; | 290 return result; |
| 357 | 291 |
| 358 // We ignore the case when result is 0, since the underlying Write | 292 // We ignore the case when result is 0, since the underlying Write |
| 359 // may return spurious writes while waiting on the socket. | 293 // may return spurious writes while waiting on the socket. |
| 360 | 294 |
| 361 bytes_sent_ += result; | 295 bytes_sent_ += result; |
| 362 if (bytes_sent_ == buffer_.size()) { | 296 if (bytes_sent_ == buffer_.size()) { |
| 363 next_state_ = STATE_HANDSHAKE_READ; | 297 next_state_ = STATE_HANDSHAKE_READ; |
| 364 buffer_.clear(); | 298 buffer_.clear(); |
| 365 } else if (bytes_sent_ < buffer_.size()) { | 299 } else if (bytes_sent_ < buffer_.size()) { |
| 366 next_state_ = STATE_HANDSHAKE_WRITE; | 300 next_state_ = STATE_HANDSHAKE_WRITE; |
| 367 } else { | 301 } else { |
| 368 NOTREACHED(); | 302 NOTREACHED(); |
| 369 } | 303 } |
| 370 | 304 |
| 371 return OK; | 305 return OK; |
| 372 } | 306 } |
| 373 | 307 |
| 374 int SOCKS5ClientSocket::DoHandshakeRead() { | 308 int SOCKS5ClientSocket::DoHandshakeRead() { |
| 375 DCHECK_NE(kEndPointUnresolved, address_type_); | |
| 376 | |
| 377 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 309 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 378 | 310 |
| 379 if (buffer_.empty()) { | 311 if (buffer_.empty()) { |
| 380 bytes_received_ = 0; | 312 bytes_received_ = 0; |
| 381 read_header_size = kReadHeaderSize; | 313 read_header_size = kReadHeaderSize; |
| 382 } | 314 } |
| 383 | 315 |
| 384 int handshake_buf_len = read_header_size - bytes_received_; | 316 int handshake_buf_len = read_header_size - bytes_received_; |
| 385 handshake_buf_ = new IOBuffer(handshake_buf_len); | 317 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 386 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); | 318 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); |
| 387 } | 319 } |
| 388 | 320 |
| 389 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 321 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
| 390 DCHECK_NE(kEndPointUnresolved, address_type_); | |
| 391 | |
| 392 if (result < 0) | 322 if (result < 0) |
| 393 return result; | 323 return result; |
| 394 | 324 |
| 395 // The underlying socket closed unexpectedly. | 325 // The underlying socket closed unexpectedly. |
| 396 if (result == 0) | 326 if (result == 0) |
| 397 return ERR_CONNECTION_CLOSED; | 327 return ERR_CONNECTION_CLOSED; |
| 398 | 328 |
| 399 buffer_.append(handshake_buf_->data(), result); | 329 buffer_.append(handshake_buf_->data(), result); |
| 400 bytes_received_ += result; | 330 bytes_received_ += result; |
| 401 | 331 |
| 402 // When the first few bytes are read, check how many more are required | 332 // When the first few bytes are read, check how many more are required |
| 403 // and accordingly increase them | 333 // and accordingly increase them |
| 404 if (bytes_received_ == kReadHeaderSize) { | 334 if (bytes_received_ == kReadHeaderSize) { |
| 405 // TODO(arindam): add error codes to net/error_list.h | 335 // TODO(arindam): add error codes to net/error_list.h |
| 406 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) | 336 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) |
| 407 return ERR_INVALID_RESPONSE; | 337 return ERR_INVALID_RESPONSE; |
| 408 if (buffer_[1] != 0x00) | 338 if (buffer_[1] != 0x00) |
| 409 return ERR_FAILED; | 339 return ERR_FAILED; |
| 410 | 340 |
| 411 // We check the type of IP/Domain the server returns and accordingly | 341 // We check the type of IP/Domain the server returns and accordingly |
| 412 // increase the size of the response. For domains, we need to read the | 342 // increase the size of the response. For domains, we need to read the |
| 413 // size of the domain, so the initial request size is upto the domain | 343 // size of the domain, so the initial request size is upto the domain |
| 414 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 344 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
| 415 // read, we substract 1 byte from the additional request size. | 345 // read, we substract 1 byte from the additional request size. |
| 416 SocksEndPointAddressType address_type = | 346 SocksEndPointAddressType address_type = |
| 417 static_cast<SocksEndPointAddressType>(buffer_[3]); | 347 static_cast<SocksEndPointAddressType>(buffer_[3]); |
| 418 if (address_type == kEndPointFailedDomain) | 348 if (address_type == kEndPointDomain) |
| 419 read_header_size += static_cast<uint8>(buffer_[4]); | 349 read_header_size += static_cast<uint8>(buffer_[4]); |
| 420 else if (address_type == kEndPointResolvedIPv4) | 350 else if (address_type == kEndPointResolvedIPv4) |
| 421 read_header_size += sizeof(struct in_addr) - 1; | 351 read_header_size += sizeof(struct in_addr) - 1; |
| 422 else if (address_type == kEndPointResolvedIPv6) | 352 else if (address_type == kEndPointResolvedIPv6) |
| 423 read_header_size += sizeof(struct in6_addr) - 1; | 353 read_header_size += sizeof(struct in6_addr) - 1; |
| 424 else | 354 else |
| 425 return ERR_INVALID_RESPONSE; | 355 return ERR_INVALID_RESPONSE; |
| 426 | 356 |
| 427 read_header_size += 2; // for the port. | 357 read_header_size += 2; // for the port. |
| 428 next_state_ = STATE_HANDSHAKE_READ; | 358 next_state_ = STATE_HANDSHAKE_READ; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 444 } | 374 } |
| 445 | 375 |
| 446 #if defined(OS_LINUX) | 376 #if defined(OS_LINUX) |
| 447 int SOCKS5ClientSocket::GetPeerName(struct sockaddr* name, | 377 int SOCKS5ClientSocket::GetPeerName(struct sockaddr* name, |
| 448 socklen_t* namelen) { | 378 socklen_t* namelen) { |
| 449 return transport_->GetPeerName(name, namelen); | 379 return transport_->GetPeerName(name, namelen); |
| 450 } | 380 } |
| 451 #endif | 381 #endif |
| 452 | 382 |
| 453 } // namespace net | 383 } // namespace net |
| OLD | NEW |