- add sources.
[platform/framework/web/crosswalk.git] / src / net / socket / socks5_client_socket.cc
1 // Copyright (c) 2012 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 "net/socket/socks5_client_socket.h"
6
7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h"
9 #include "base/debug/trace_event.h"
10 #include "base/format_macros.h"
11 #include "base/strings/string_util.h"
12 #include "base/sys_byteorder.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_log.h"
15 #include "net/base/net_util.h"
16 #include "net/socket/client_socket_handle.h"
17
18 namespace net {
19
20 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2;
21 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10;
22 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5;
23 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05;
24 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01;
25 const uint8 SOCKS5ClientSocket::kNullByte = 0x00;
26
27 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4);
28 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6);
29
30 SOCKS5ClientSocket::SOCKS5ClientSocket(
31     scoped_ptr<ClientSocketHandle> transport_socket,
32     const HostResolver::RequestInfo& req_info)
33     : io_callback_(base::Bind(&SOCKS5ClientSocket::OnIOComplete,
34                               base::Unretained(this))),
35       transport_(transport_socket.Pass()),
36       next_state_(STATE_NONE),
37       completed_handshake_(false),
38       bytes_sent_(0),
39       bytes_received_(0),
40       read_header_size(kReadHeaderSize),
41       host_request_info_(req_info),
42       net_log_(transport_->socket()->NetLog()) {
43 }
44
45 SOCKS5ClientSocket::~SOCKS5ClientSocket() {
46   Disconnect();
47 }
48
49 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) {
50   DCHECK(transport_.get());
51   DCHECK(transport_->socket());
52   DCHECK_EQ(STATE_NONE, next_state_);
53   DCHECK(user_callback_.is_null());
54
55   // If already connected, then just return OK.
56   if (completed_handshake_)
57     return OK;
58
59   net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT);
60
61   next_state_ = STATE_GREET_WRITE;
62   buffer_.clear();
63
64   int rv = DoLoop(OK);
65   if (rv == ERR_IO_PENDING) {
66     user_callback_ = callback;
67   } else {
68     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv);
69   }
70   return rv;
71 }
72
73 void SOCKS5ClientSocket::Disconnect() {
74   completed_handshake_ = false;
75   transport_->socket()->Disconnect();
76
77   // Reset other states to make sure they aren't mistakenly used later.
78   // These are the states initialized by Connect().
79   next_state_ = STATE_NONE;
80   user_callback_.Reset();
81 }
82
83 bool SOCKS5ClientSocket::IsConnected() const {
84   return completed_handshake_ && transport_->socket()->IsConnected();
85 }
86
87 bool SOCKS5ClientSocket::IsConnectedAndIdle() const {
88   return completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
89 }
90
91 const BoundNetLog& SOCKS5ClientSocket::NetLog() const {
92   return net_log_;
93 }
94
95 void SOCKS5ClientSocket::SetSubresourceSpeculation() {
96   if (transport_.get() && transport_->socket()) {
97     transport_->socket()->SetSubresourceSpeculation();
98   } else {
99     NOTREACHED();
100   }
101 }
102
103 void SOCKS5ClientSocket::SetOmniboxSpeculation() {
104   if (transport_.get() && transport_->socket()) {
105     transport_->socket()->SetOmniboxSpeculation();
106   } else {
107     NOTREACHED();
108   }
109 }
110
111 bool SOCKS5ClientSocket::WasEverUsed() const {
112   if (transport_.get() && transport_->socket()) {
113     return transport_->socket()->WasEverUsed();
114   }
115   NOTREACHED();
116   return false;
117 }
118
119 bool SOCKS5ClientSocket::UsingTCPFastOpen() const {
120   if (transport_.get() && transport_->socket()) {
121     return transport_->socket()->UsingTCPFastOpen();
122   }
123   NOTREACHED();
124   return false;
125 }
126
127 bool SOCKS5ClientSocket::WasNpnNegotiated() const {
128   if (transport_.get() && transport_->socket()) {
129     return transport_->socket()->WasNpnNegotiated();
130   }
131   NOTREACHED();
132   return false;
133 }
134
135 NextProto SOCKS5ClientSocket::GetNegotiatedProtocol() const {
136   if (transport_.get() && transport_->socket()) {
137     return transport_->socket()->GetNegotiatedProtocol();
138   }
139   NOTREACHED();
140   return kProtoUnknown;
141 }
142
143 bool SOCKS5ClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
144   if (transport_.get() && transport_->socket()) {
145     return transport_->socket()->GetSSLInfo(ssl_info);
146   }
147   NOTREACHED();
148   return false;
149
150 }
151
152 // Read is called by the transport layer above to read. This can only be done
153 // if the SOCKS handshake is complete.
154 int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len,
155                              const CompletionCallback& callback) {
156   DCHECK(completed_handshake_);
157   DCHECK_EQ(STATE_NONE, next_state_);
158   DCHECK(user_callback_.is_null());
159
160   return transport_->socket()->Read(buf, buf_len, callback);
161 }
162
163 // Write is called by the transport layer. This can only be done if the
164 // SOCKS handshake is complete.
165 int SOCKS5ClientSocket::Write(IOBuffer* buf, int buf_len,
166                              const CompletionCallback& callback) {
167   DCHECK(completed_handshake_);
168   DCHECK_EQ(STATE_NONE, next_state_);
169   DCHECK(user_callback_.is_null());
170
171   return transport_->socket()->Write(buf, buf_len, callback);
172 }
173
174 bool SOCKS5ClientSocket::SetReceiveBufferSize(int32 size) {
175   return transport_->socket()->SetReceiveBufferSize(size);
176 }
177
178 bool SOCKS5ClientSocket::SetSendBufferSize(int32 size) {
179   return transport_->socket()->SetSendBufferSize(size);
180 }
181
182 void SOCKS5ClientSocket::DoCallback(int result) {
183   DCHECK_NE(ERR_IO_PENDING, result);
184   DCHECK(!user_callback_.is_null());
185
186   // Since Run() may result in Read being called,
187   // clear user_callback_ up front.
188   CompletionCallback c = user_callback_;
189   user_callback_.Reset();
190   c.Run(result);
191 }
192
193 void SOCKS5ClientSocket::OnIOComplete(int result) {
194   DCHECK_NE(STATE_NONE, next_state_);
195   int rv = DoLoop(result);
196   if (rv != ERR_IO_PENDING) {
197     net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT);
198     DoCallback(rv);
199   }
200 }
201
202 int SOCKS5ClientSocket::DoLoop(int last_io_result) {
203   DCHECK_NE(next_state_, STATE_NONE);
204   int rv = last_io_result;
205   do {
206     State state = next_state_;
207     next_state_ = STATE_NONE;
208     switch (state) {
209       case STATE_GREET_WRITE:
210         DCHECK_EQ(OK, rv);
211         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE);
212         rv = DoGreetWrite();
213         break;
214       case STATE_GREET_WRITE_COMPLETE:
215         rv = DoGreetWriteComplete(rv);
216         net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv);
217         break;
218       case STATE_GREET_READ:
219         DCHECK_EQ(OK, rv);
220         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ);
221         rv = DoGreetRead();
222         break;
223       case STATE_GREET_READ_COMPLETE:
224         rv = DoGreetReadComplete(rv);
225         net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv);
226         break;
227       case STATE_HANDSHAKE_WRITE:
228         DCHECK_EQ(OK, rv);
229         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE);
230         rv = DoHandshakeWrite();
231         break;
232       case STATE_HANDSHAKE_WRITE_COMPLETE:
233         rv = DoHandshakeWriteComplete(rv);
234         net_log_.EndEventWithNetErrorCode(
235             NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv);
236         break;
237       case STATE_HANDSHAKE_READ:
238         DCHECK_EQ(OK, rv);
239         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ);
240         rv = DoHandshakeRead();
241         break;
242       case STATE_HANDSHAKE_READ_COMPLETE:
243         rv = DoHandshakeReadComplete(rv);
244         net_log_.EndEventWithNetErrorCode(
245             NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv);
246         break;
247       default:
248         NOTREACHED() << "bad state";
249         rv = ERR_UNEXPECTED;
250         break;
251     }
252   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
253   return rv;
254 }
255
256 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 };  // no authentication
257
258 int SOCKS5ClientSocket::DoGreetWrite() {
259   // Since we only have 1 byte to send the hostname length in, if the
260   // URL has a hostname longer than 255 characters we can't send it.
261   if (0xFF < host_request_info_.hostname().size()) {
262     net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG);
263     return ERR_SOCKS_CONNECTION_FAILED;
264   }
265
266   if (buffer_.empty()) {
267     buffer_ = std::string(kSOCKS5GreetWriteData,
268                           arraysize(kSOCKS5GreetWriteData));
269     bytes_sent_ = 0;
270   }
271
272   next_state_ = STATE_GREET_WRITE_COMPLETE;
273   size_t handshake_buf_len = buffer_.size() - bytes_sent_;
274   handshake_buf_ = new IOBuffer(handshake_buf_len);
275   memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_],
276          handshake_buf_len);
277   return transport_->socket()
278       ->Write(handshake_buf_.get(), handshake_buf_len, io_callback_);
279 }
280
281 int SOCKS5ClientSocket::DoGreetWriteComplete(int result) {
282   if (result < 0)
283     return result;
284
285   bytes_sent_ += result;
286   if (bytes_sent_ == buffer_.size()) {
287     buffer_.clear();
288     bytes_received_ = 0;
289     next_state_ = STATE_GREET_READ;
290   } else {
291     next_state_ = STATE_GREET_WRITE;
292   }
293   return OK;
294 }
295
296 int SOCKS5ClientSocket::DoGreetRead() {
297   next_state_ = STATE_GREET_READ_COMPLETE;
298   size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_;
299   handshake_buf_ = new IOBuffer(handshake_buf_len);
300   return transport_->socket()
301       ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_);
302 }
303
304 int SOCKS5ClientSocket::DoGreetReadComplete(int result) {
305   if (result < 0)
306     return result;
307
308   if (result == 0) {
309     net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING);
310     return ERR_SOCKS_CONNECTION_FAILED;
311   }
312
313   bytes_received_ += result;
314   buffer_.append(handshake_buf_->data(), result);
315   if (bytes_received_ < kGreetReadHeaderSize) {
316     next_state_ = STATE_GREET_READ;
317     return OK;
318   }
319
320   // Got the greet data.
321   if (buffer_[0] != kSOCKS5Version) {
322     net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
323                       NetLog::IntegerCallback("version", buffer_[0]));
324     return ERR_SOCKS_CONNECTION_FAILED;
325   }
326   if (buffer_[1] != 0x00) {
327     net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH,
328                       NetLog::IntegerCallback("method", buffer_[1]));
329     return ERR_SOCKS_CONNECTION_FAILED;
330   }
331
332   buffer_.clear();
333   next_state_ = STATE_HANDSHAKE_WRITE;
334   return OK;
335 }
336
337 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake)
338     const {
339   DCHECK(handshake->empty());
340
341   handshake->push_back(kSOCKS5Version);
342   handshake->push_back(kTunnelCommand);  // Connect command
343   handshake->push_back(kNullByte);  // Reserved null
344
345   handshake->push_back(kEndPointDomain);  // The type of the address.
346
347   DCHECK_GE(static_cast<size_t>(0xFF), host_request_info_.hostname().size());
348
349   // First add the size of the hostname, followed by the hostname.
350   handshake->push_back(static_cast<unsigned char>(
351       host_request_info_.hostname().size()));
352   handshake->append(host_request_info_.hostname());
353
354   uint16 nw_port = base::HostToNet16(host_request_info_.port());
355   handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port));
356   return OK;
357 }
358
359 // Writes the SOCKS handshake data to the underlying socket connection.
360 int SOCKS5ClientSocket::DoHandshakeWrite() {
361   next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
362
363   if (buffer_.empty()) {
364     int rv = BuildHandshakeWriteBuffer(&buffer_);
365     if (rv != OK)
366       return rv;
367     bytes_sent_ = 0;
368   }
369
370   int handshake_buf_len = buffer_.size() - bytes_sent_;
371   DCHECK_LT(0, handshake_buf_len);
372   handshake_buf_ = new IOBuffer(handshake_buf_len);
373   memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
374          handshake_buf_len);
375   return transport_->socket()
376       ->Write(handshake_buf_.get(), handshake_buf_len, io_callback_);
377 }
378
379 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) {
380   if (result < 0)
381     return result;
382
383   // We ignore the case when result is 0, since the underlying Write
384   // may return spurious writes while waiting on the socket.
385
386   bytes_sent_ += result;
387   if (bytes_sent_ == buffer_.size()) {
388     next_state_ = STATE_HANDSHAKE_READ;
389     buffer_.clear();
390   } else if (bytes_sent_ < buffer_.size()) {
391     next_state_ = STATE_HANDSHAKE_WRITE;
392   } else {
393     NOTREACHED();
394   }
395
396   return OK;
397 }
398
399 int SOCKS5ClientSocket::DoHandshakeRead() {
400   next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
401
402   if (buffer_.empty()) {
403     bytes_received_ = 0;
404     read_header_size = kReadHeaderSize;
405   }
406
407   int handshake_buf_len = read_header_size - bytes_received_;
408   handshake_buf_ = new IOBuffer(handshake_buf_len);
409   return transport_->socket()
410       ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_);
411 }
412
413 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
414   if (result < 0)
415     return result;
416
417   // The underlying socket closed unexpectedly.
418   if (result == 0) {
419     net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE);
420     return ERR_SOCKS_CONNECTION_FAILED;
421   }
422
423   buffer_.append(handshake_buf_->data(), result);
424   bytes_received_ += result;
425
426   // When the first few bytes are read, check how many more are required
427   // and accordingly increase them
428   if (bytes_received_ == kReadHeaderSize) {
429     if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) {
430       net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
431                         NetLog::IntegerCallback("version", buffer_[0]));
432       return ERR_SOCKS_CONNECTION_FAILED;
433     }
434     if (buffer_[1] != 0x00) {
435       net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR,
436                         NetLog::IntegerCallback("error_code", buffer_[1]));
437       return ERR_SOCKS_CONNECTION_FAILED;
438     }
439
440     // We check the type of IP/Domain the server returns and accordingly
441     // increase the size of the response. For domains, we need to read the
442     // size of the domain, so the initial request size is upto the domain
443     // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is
444     // read, we substract 1 byte from the additional request size.
445     SocksEndPointAddressType address_type =
446         static_cast<SocksEndPointAddressType>(buffer_[3]);
447     if (address_type == kEndPointDomain)
448       read_header_size += static_cast<uint8>(buffer_[4]);
449     else if (address_type == kEndPointResolvedIPv4)
450       read_header_size += sizeof(struct in_addr) - 1;
451     else if (address_type == kEndPointResolvedIPv6)
452       read_header_size += sizeof(struct in6_addr) - 1;
453     else {
454       net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE,
455                         NetLog::IntegerCallback("address_type", buffer_[3]));
456       return ERR_SOCKS_CONNECTION_FAILED;
457     }
458
459     read_header_size += 2;  // for the port.
460     next_state_ = STATE_HANDSHAKE_READ;
461     return OK;
462   }
463
464   // When the final bytes are read, setup handshake. We ignore the rest
465   // of the response since they represent the SOCKSv5 endpoint and have
466   // no use when doing a tunnel connection.
467   if (bytes_received_ == read_header_size) {
468     completed_handshake_ = true;
469     buffer_.clear();
470     next_state_ = STATE_NONE;
471     return OK;
472   }
473
474   next_state_ = STATE_HANDSHAKE_READ;
475   return OK;
476 }
477
478 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const {
479   return transport_->socket()->GetPeerAddress(address);
480 }
481
482 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const {
483   return transport_->socket()->GetLocalAddress(address);
484 }
485
486 }  // namespace net