1/*
2 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#if defined(_MSC_VER) && _MSC_VER < 1300
12#pragma warning(disable:4786)
13#endif
14
15#include <time.h>
16#include <errno.h>
17
18#if defined(WEBRTC_WIN)
19#define WIN32_LEAN_AND_MEAN
20#include <windows.h>
21#include <winsock2.h>
22#include <ws2tcpip.h>
23#define SECURITY_WIN32
24#include <security.h>
25#endif
26
27#include "webrtc/base/bytebuffer.h"
28#include "webrtc/base/common.h"
29#include "webrtc/base/httpcommon.h"
30#include "webrtc/base/logging.h"
31#include "webrtc/base/socketadapters.h"
32#include "webrtc/base/stringencode.h"
33#include "webrtc/base/stringutils.h"
34
35#if defined(WEBRTC_WIN)
36#include "webrtc/base/sec_buffer.h"
37#endif  // WEBRTC_WIN
38
39namespace rtc {
40
41BufferedReadAdapter::BufferedReadAdapter(AsyncSocket* socket, size_t size)
42    : AsyncSocketAdapter(socket), buffer_size_(size),
43      data_len_(0), buffering_(false) {
44  buffer_ = new char[buffer_size_];
45}
46
47BufferedReadAdapter::~BufferedReadAdapter() {
48  delete [] buffer_;
49}
50
51int BufferedReadAdapter::Send(const void *pv, size_t cb) {
52  if (buffering_) {
53    // TODO: Spoof error better; Signal Writeable
54    socket_->SetError(EWOULDBLOCK);
55    return -1;
56  }
57  return AsyncSocketAdapter::Send(pv, cb);
58}
59
60int BufferedReadAdapter::Recv(void *pv, size_t cb) {
61  if (buffering_) {
62    socket_->SetError(EWOULDBLOCK);
63    return -1;
64  }
65
66  size_t read = 0;
67
68  if (data_len_) {
69    read = _min(cb, data_len_);
70    memcpy(pv, buffer_, read);
71    data_len_ -= read;
72    if (data_len_ > 0) {
73      memmove(buffer_, buffer_ + read, data_len_);
74    }
75    pv = static_cast<char *>(pv) + read;
76    cb -= read;
77  }
78
79  // FIX: If cb == 0, we won't generate another read event
80
81  int res = AsyncSocketAdapter::Recv(pv, cb);
82  if (res < 0)
83    return res;
84
85  return res + static_cast<int>(read);
86}
87
88void BufferedReadAdapter::BufferInput(bool on) {
89  buffering_ = on;
90}
91
92void BufferedReadAdapter::OnReadEvent(AsyncSocket * socket) {
93  ASSERT(socket == socket_);
94
95  if (!buffering_) {
96    AsyncSocketAdapter::OnReadEvent(socket);
97    return;
98  }
99
100  if (data_len_ >= buffer_size_) {
101    LOG(INFO) << "Input buffer overflow";
102    ASSERT(false);
103    data_len_ = 0;
104  }
105
106  int len = socket_->Recv(buffer_ + data_len_, buffer_size_ - data_len_);
107  if (len < 0) {
108    // TODO: Do something better like forwarding the error to the user.
109    LOG_ERR(INFO) << "Recv";
110    return;
111  }
112
113  data_len_ += len;
114
115  ProcessInput(buffer_, &data_len_);
116}
117
118///////////////////////////////////////////////////////////////////////////////
119
120// This is a SSL v2 CLIENT_HELLO message.
121// TODO: Should this have a session id? The response doesn't have a
122// certificate, so the hello should have a session id.
123static const uint8 kSslClientHello[] = {
124  0x80, 0x46,                                            // msg len
125  0x01,                                                  // CLIENT_HELLO
126  0x03, 0x01,                                            // SSL 3.1
127  0x00, 0x2d,                                            // ciphersuite len
128  0x00, 0x00,                                            // session id len
129  0x00, 0x10,                                            // challenge len
130  0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x07, 0x00, 0xc0,  // ciphersuites
131  0x06, 0x00, 0x40, 0x02, 0x00, 0x80, 0x04, 0x00, 0x80,  //
132  0x00, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a,  //
133  0x00, 0xfe, 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64,  //
134  0x00, 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06,  //
135  0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc,        // challenge
136  0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea         //
137};
138
139// This is a TLSv1 SERVER_HELLO message.
140static const uint8 kSslServerHello[] = {
141  0x16,                                            // handshake message
142  0x03, 0x01,                                      // SSL 3.1
143  0x00, 0x4a,                                      // message len
144  0x02,                                            // SERVER_HELLO
145  0x00, 0x00, 0x46,                                // handshake len
146  0x03, 0x01,                                      // SSL 3.1
147  0x42, 0x85, 0x45, 0xa7, 0x27, 0xa9, 0x5d, 0xa0,  // server random
148  0xb3, 0xc5, 0xe7, 0x53, 0xda, 0x48, 0x2b, 0x3f,  //
149  0xc6, 0x5a, 0xca, 0x89, 0xc1, 0x58, 0x52, 0xa1,  //
150  0x78, 0x3c, 0x5b, 0x17, 0x46, 0x00, 0x85, 0x3f,  //
151  0x20,                                            // session id len
152  0x0e, 0xd3, 0x06, 0x72, 0x5b, 0x5b, 0x1b, 0x5f,  // session id
153  0x15, 0xac, 0x13, 0xf9, 0x88, 0x53, 0x9d, 0x9b,  //
154  0xe8, 0x3d, 0x7b, 0x0c, 0x30, 0x32, 0x6e, 0x38,  //
155  0x4d, 0xa2, 0x75, 0x57, 0x41, 0x6c, 0x34, 0x5c,  //
156  0x00, 0x04,                                      // RSA/RC4-128/MD5
157  0x00                                             // null compression
158};
159
160AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
161    : BufferedReadAdapter(socket, 1024) {
162}
163
164int AsyncSSLSocket::Connect(const SocketAddress& addr) {
165  // Begin buffering before we connect, so that there isn't a race condition
166  // between potential senders and receiving the OnConnectEvent signal
167  BufferInput(true);
168  return BufferedReadAdapter::Connect(addr);
169}
170
171void AsyncSSLSocket::OnConnectEvent(AsyncSocket * socket) {
172  ASSERT(socket == socket_);
173  // TODO: we could buffer output too...
174  VERIFY(sizeof(kSslClientHello) ==
175      DirectSend(kSslClientHello, sizeof(kSslClientHello)));
176}
177
178void AsyncSSLSocket::ProcessInput(char* data, size_t* len) {
179  if (*len < sizeof(kSslServerHello))
180    return;
181
182  if (memcmp(kSslServerHello, data, sizeof(kSslServerHello)) != 0) {
183    Close();
184    SignalCloseEvent(this, 0);  // TODO: error code?
185    return;
186  }
187
188  *len -= sizeof(kSslServerHello);
189  if (*len > 0) {
190    memmove(data, data + sizeof(kSslServerHello), *len);
191  }
192
193  bool remainder = (*len > 0);
194  BufferInput(false);
195  SignalConnectEvent(this);
196
197  // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
198  if (remainder)
199    SignalReadEvent(this);
200}
201
202AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
203     : BufferedReadAdapter(socket, 1024) {
204  BufferInput(true);
205}
206
207void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
208  // We only accept client hello messages.
209  if (*len < sizeof(kSslClientHello)) {
210    return;
211  }
212
213  if (memcmp(kSslClientHello, data, sizeof(kSslClientHello)) != 0) {
214    Close();
215    SignalCloseEvent(this, 0);
216    return;
217  }
218
219  *len -= sizeof(kSslClientHello);
220
221  // Clients should not send more data until the handshake is completed.
222  ASSERT(*len == 0);
223
224  // Send a server hello back to the client.
225  DirectSend(kSslServerHello, sizeof(kSslServerHello));
226
227  // Handshake completed for us, redirect input to our parent.
228  BufferInput(false);
229}
230
231///////////////////////////////////////////////////////////////////////////////
232
233AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket,
234                                             const std::string& user_agent,
235                                             const SocketAddress& proxy,
236                                             const std::string& username,
237                                             const CryptString& password)
238  : BufferedReadAdapter(socket, 1024), proxy_(proxy), agent_(user_agent),
239    user_(username), pass_(password), force_connect_(false), state_(PS_ERROR),
240    context_(0) {
241}
242
243AsyncHttpsProxySocket::~AsyncHttpsProxySocket() {
244  delete context_;
245}
246
247int AsyncHttpsProxySocket::Connect(const SocketAddress& addr) {
248  int ret;
249  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::Connect("
250                  << proxy_.ToSensitiveString() << ")";
251  dest_ = addr;
252  state_ = PS_INIT;
253  if (ShouldIssueConnect()) {
254    BufferInput(true);
255  }
256  ret = BufferedReadAdapter::Connect(proxy_);
257  // TODO: Set state_ appropriately if Connect fails.
258  return ret;
259}
260
261SocketAddress AsyncHttpsProxySocket::GetRemoteAddress() const {
262  return dest_;
263}
264
265int AsyncHttpsProxySocket::Close() {
266  headers_.clear();
267  state_ = PS_ERROR;
268  dest_.Clear();
269  delete context_;
270  context_ = NULL;
271  return BufferedReadAdapter::Close();
272}
273
274Socket::ConnState AsyncHttpsProxySocket::GetState() const {
275  if (state_ < PS_TUNNEL) {
276    return CS_CONNECTING;
277  } else if (state_ == PS_TUNNEL) {
278    return CS_CONNECTED;
279  } else {
280    return CS_CLOSED;
281  }
282}
283
284void AsyncHttpsProxySocket::OnConnectEvent(AsyncSocket * socket) {
285  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnConnectEvent";
286  if (!ShouldIssueConnect()) {
287    state_ = PS_TUNNEL;
288    BufferedReadAdapter::OnConnectEvent(socket);
289    return;
290  }
291  SendRequest();
292}
293
294void AsyncHttpsProxySocket::OnCloseEvent(AsyncSocket * socket, int err) {
295  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnCloseEvent(" << err << ")";
296  if ((state_ == PS_WAIT_CLOSE) && (err == 0)) {
297    state_ = PS_ERROR;
298    Connect(dest_);
299  } else {
300    BufferedReadAdapter::OnCloseEvent(socket, err);
301  }
302}
303
304void AsyncHttpsProxySocket::ProcessInput(char* data, size_t* len) {
305  size_t start = 0;
306  for (size_t pos = start; state_ < PS_TUNNEL && pos < *len;) {
307    if (state_ == PS_SKIP_BODY) {
308      size_t consume = _min(*len - pos, content_length_);
309      pos += consume;
310      start = pos;
311      content_length_ -= consume;
312      if (content_length_ == 0) {
313        EndResponse();
314      }
315      continue;
316    }
317
318    if (data[pos++] != '\n')
319      continue;
320
321    size_t len = pos - start - 1;
322    if ((len > 0) && (data[start + len - 1] == '\r'))
323      --len;
324
325    data[start + len] = 0;
326    ProcessLine(data + start, len);
327    start = pos;
328  }
329
330  *len -= start;
331  if (*len > 0) {
332    memmove(data, data + start, *len);
333  }
334
335  if (state_ != PS_TUNNEL)
336    return;
337
338  bool remainder = (*len > 0);
339  BufferInput(false);
340  SignalConnectEvent(this);
341
342  // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
343  if (remainder)
344    SignalReadEvent(this);  // TODO: signal this??
345}
346
347bool AsyncHttpsProxySocket::ShouldIssueConnect() const {
348  // TODO: Think about whether a more sophisticated test
349  // than dest port == 80 is needed.
350  return force_connect_ || (dest_.port() != 80);
351}
352
353void AsyncHttpsProxySocket::SendRequest() {
354  std::stringstream ss;
355  ss << "CONNECT " << dest_.ToString() << " HTTP/1.0\r\n";
356  ss << "User-Agent: " << agent_ << "\r\n";
357  ss << "Host: " << dest_.HostAsURIString() << "\r\n";
358  ss << "Content-Length: 0\r\n";
359  ss << "Proxy-Connection: Keep-Alive\r\n";
360  ss << headers_;
361  ss << "\r\n";
362  std::string str = ss.str();
363  DirectSend(str.c_str(), str.size());
364  state_ = PS_LEADER;
365  expect_close_ = true;
366  content_length_ = 0;
367  headers_.clear();
368
369  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket >> " << str;
370}
371
372void AsyncHttpsProxySocket::ProcessLine(char * data, size_t len) {
373  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket << " << data;
374
375  if (len == 0) {
376    if (state_ == PS_TUNNEL_HEADERS) {
377      state_ = PS_TUNNEL;
378    } else if (state_ == PS_ERROR_HEADERS) {
379      Error(defer_error_);
380      return;
381    } else if (state_ == PS_SKIP_HEADERS) {
382      if (content_length_) {
383        state_ = PS_SKIP_BODY;
384      } else {
385        EndResponse();
386        return;
387      }
388    } else {
389      static bool report = false;
390      if (!unknown_mechanisms_.empty() && !report) {
391        report = true;
392        std::string msg(
393          "Unable to connect to the Google Talk service due to an incompatibility "
394          "with your proxy.\r\nPlease help us resolve this issue by submitting the "
395          "following information to us using our technical issue submission form "
396          "at:\r\n\r\n"
397          "http://www.google.com/support/talk/bin/request.py\r\n\r\n"
398          "We apologize for the inconvenience.\r\n\r\n"
399          "Information to submit to Google: "
400          );
401        //std::string msg("Please report the following information to foo@bar.com:\r\nUnknown methods: ");
402        msg.append(unknown_mechanisms_);
403#if defined(WEBRTC_WIN)
404        MessageBoxA(0, msg.c_str(), "Oops!", MB_OK);
405#endif
406#if defined(WEBRTC_POSIX)
407        // TODO: Raise a signal so the UI can be separated.
408        LOG(LS_ERROR) << "Oops!\n\n" << msg;
409#endif
410      }
411      // Unexpected end of headers
412      Error(0);
413      return;
414    }
415  } else if (state_ == PS_LEADER) {
416    unsigned int code;
417    if (sscanf(data, "HTTP/%*u.%*u %u", &code) != 1) {
418      Error(0);
419      return;
420    }
421    switch (code) {
422    case 200:
423      // connection good!
424      state_ = PS_TUNNEL_HEADERS;
425      return;
426#if defined(HTTP_STATUS_PROXY_AUTH_REQ) && (HTTP_STATUS_PROXY_AUTH_REQ != 407)
427#error Wrong code for HTTP_STATUS_PROXY_AUTH_REQ
428#endif
429    case 407:  // HTTP_STATUS_PROXY_AUTH_REQ
430      state_ = PS_AUTHENTICATE;
431      return;
432    default:
433      defer_error_ = 0;
434      state_ = PS_ERROR_HEADERS;
435      return;
436    }
437  } else if ((state_ == PS_AUTHENTICATE)
438             && (_strnicmp(data, "Proxy-Authenticate:", 19) == 0)) {
439    std::string response, auth_method;
440    switch (HttpAuthenticate(data + 19, len - 19,
441                             proxy_, "CONNECT", "/",
442                             user_, pass_, context_, response, auth_method)) {
443    case HAR_IGNORE:
444      LOG(LS_VERBOSE) << "Ignoring Proxy-Authenticate: " << auth_method;
445      if (!unknown_mechanisms_.empty())
446        unknown_mechanisms_.append(", ");
447      unknown_mechanisms_.append(auth_method);
448      break;
449    case HAR_RESPONSE:
450      headers_ = "Proxy-Authorization: ";
451      headers_.append(response);
452      headers_.append("\r\n");
453      state_ = PS_SKIP_HEADERS;
454      unknown_mechanisms_.clear();
455      break;
456    case HAR_CREDENTIALS:
457      defer_error_ = SOCKET_EACCES;
458      state_ = PS_ERROR_HEADERS;
459      unknown_mechanisms_.clear();
460      break;
461    case HAR_ERROR:
462      defer_error_ = 0;
463      state_ = PS_ERROR_HEADERS;
464      unknown_mechanisms_.clear();
465      break;
466    }
467  } else if (_strnicmp(data, "Content-Length:", 15) == 0) {
468    content_length_ = strtoul(data + 15, 0, 0);
469  } else if (_strnicmp(data, "Proxy-Connection: Keep-Alive", 28) == 0) {
470    expect_close_ = false;
471    /*
472  } else if (_strnicmp(data, "Connection: close", 17) == 0) {
473    expect_close_ = true;
474    */
475  }
476}
477
478void AsyncHttpsProxySocket::EndResponse() {
479  if (!expect_close_) {
480    SendRequest();
481    return;
482  }
483
484  // No point in waiting for the server to close... let's close now
485  // TODO: Refactor out PS_WAIT_CLOSE
486  state_ = PS_WAIT_CLOSE;
487  BufferedReadAdapter::Close();
488  OnCloseEvent(this, 0);
489}
490
491void AsyncHttpsProxySocket::Error(int error) {
492  BufferInput(false);
493  Close();
494  SetError(error);
495  SignalCloseEvent(this, error);
496}
497
498///////////////////////////////////////////////////////////////////////////////
499
500AsyncSocksProxySocket::AsyncSocksProxySocket(AsyncSocket* socket,
501                                             const SocketAddress& proxy,
502                                             const std::string& username,
503                                             const CryptString& password)
504    : BufferedReadAdapter(socket, 1024), state_(SS_ERROR), proxy_(proxy),
505      user_(username), pass_(password) {
506}
507
508int AsyncSocksProxySocket::Connect(const SocketAddress& addr) {
509  int ret;
510  dest_ = addr;
511  state_ = SS_INIT;
512  BufferInput(true);
513  ret = BufferedReadAdapter::Connect(proxy_);
514  // TODO: Set state_ appropriately if Connect fails.
515  return ret;
516}
517
518SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const {
519  return dest_;
520}
521
522int AsyncSocksProxySocket::Close() {
523  state_ = SS_ERROR;
524  dest_.Clear();
525  return BufferedReadAdapter::Close();
526}
527
528Socket::ConnState AsyncSocksProxySocket::GetState() const {
529  if (state_ < SS_TUNNEL) {
530    return CS_CONNECTING;
531  } else if (state_ == SS_TUNNEL) {
532    return CS_CONNECTED;
533  } else {
534    return CS_CLOSED;
535  }
536}
537
538void AsyncSocksProxySocket::OnConnectEvent(AsyncSocket* socket) {
539  SendHello();
540}
541
542void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) {
543  ASSERT(state_ < SS_TUNNEL);
544
545  ByteBuffer response(data, *len);
546
547  if (state_ == SS_HELLO) {
548    uint8 ver, method;
549    if (!response.ReadUInt8(&ver) ||
550        !response.ReadUInt8(&method))
551      return;
552
553    if (ver != 5) {
554      Error(0);
555      return;
556    }
557
558    if (method == 0) {
559      SendConnect();
560    } else if (method == 2) {
561      SendAuth();
562    } else {
563      Error(0);
564      return;
565    }
566  } else if (state_ == SS_AUTH) {
567    uint8 ver, status;
568    if (!response.ReadUInt8(&ver) ||
569        !response.ReadUInt8(&status))
570      return;
571
572    if ((ver != 1) || (status != 0)) {
573      Error(SOCKET_EACCES);
574      return;
575    }
576
577    SendConnect();
578  } else if (state_ == SS_CONNECT) {
579    uint8 ver, rep, rsv, atyp;
580    if (!response.ReadUInt8(&ver) ||
581        !response.ReadUInt8(&rep) ||
582        !response.ReadUInt8(&rsv) ||
583        !response.ReadUInt8(&atyp))
584      return;
585
586    if ((ver != 5) || (rep != 0)) {
587      Error(0);
588      return;
589    }
590
591    uint16 port;
592    if (atyp == 1) {
593      uint32 addr;
594      if (!response.ReadUInt32(&addr) ||
595          !response.ReadUInt16(&port))
596        return;
597      LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
598    } else if (atyp == 3) {
599      uint8 len;
600      std::string addr;
601      if (!response.ReadUInt8(&len) ||
602          !response.ReadString(&addr, len) ||
603          !response.ReadUInt16(&port))
604        return;
605      LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
606    } else if (atyp == 4) {
607      std::string addr;
608      if (!response.ReadString(&addr, 16) ||
609          !response.ReadUInt16(&port))
610        return;
611      LOG(LS_VERBOSE) << "Bound on <IPV6>:" << port;
612    } else {
613      Error(0);
614      return;
615    }
616
617    state_ = SS_TUNNEL;
618  }
619
620  // Consume parsed data
621  *len = response.Length();
622  memcpy(data, response.Data(), *len);
623
624  if (state_ != SS_TUNNEL)
625    return;
626
627  bool remainder = (*len > 0);
628  BufferInput(false);
629  SignalConnectEvent(this);
630
631  // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
632  if (remainder)
633    SignalReadEvent(this);  // TODO: signal this??
634}
635
636void AsyncSocksProxySocket::SendHello() {
637  ByteBuffer request;
638  request.WriteUInt8(5);    // Socks Version
639  if (user_.empty()) {
640    request.WriteUInt8(1);  // Authentication Mechanisms
641    request.WriteUInt8(0);  // No authentication
642  } else {
643    request.WriteUInt8(2);  // Authentication Mechanisms
644    request.WriteUInt8(0);  // No authentication
645    request.WriteUInt8(2);  // Username/Password
646  }
647  DirectSend(request.Data(), request.Length());
648  state_ = SS_HELLO;
649}
650
651void AsyncSocksProxySocket::SendAuth() {
652  ByteBuffer request;
653  request.WriteUInt8(1);           // Negotiation Version
654  request.WriteUInt8(static_cast<uint8>(user_.size()));
655  request.WriteString(user_);      // Username
656  request.WriteUInt8(static_cast<uint8>(pass_.GetLength()));
657  size_t len = pass_.GetLength() + 1;
658  char * sensitive = new char[len];
659  pass_.CopyTo(sensitive, true);
660  request.WriteString(sensitive);  // Password
661  memset(sensitive, 0, len);
662  delete [] sensitive;
663  DirectSend(request.Data(), request.Length());
664  state_ = SS_AUTH;
665}
666
667void AsyncSocksProxySocket::SendConnect() {
668  ByteBuffer request;
669  request.WriteUInt8(5);              // Socks Version
670  request.WriteUInt8(1);              // CONNECT
671  request.WriteUInt8(0);              // Reserved
672  if (dest_.IsUnresolved()) {
673    std::string hostname = dest_.hostname();
674    request.WriteUInt8(3);            // DOMAINNAME
675    request.WriteUInt8(static_cast<uint8>(hostname.size()));
676    request.WriteString(hostname);    // Destination Hostname
677  } else {
678    request.WriteUInt8(1);            // IPV4
679    request.WriteUInt32(dest_.ip());  // Destination IP
680  }
681  request.WriteUInt16(dest_.port());  // Destination Port
682  DirectSend(request.Data(), request.Length());
683  state_ = SS_CONNECT;
684}
685
686void AsyncSocksProxySocket::Error(int error) {
687  state_ = SS_ERROR;
688  BufferInput(false);
689  Close();
690  SetError(SOCKET_EACCES);
691  SignalCloseEvent(this, error);
692}
693
694AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket)
695    : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
696  BufferInput(true);
697}
698
699void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
700  // TODO: See if the whole message has arrived
701  ASSERT(state_ < SS_CONNECT_PENDING);
702
703  ByteBuffer response(data, *len);
704  if (state_ == SS_HELLO) {
705    HandleHello(&response);
706  } else if (state_ == SS_AUTH) {
707    HandleAuth(&response);
708  } else if (state_ == SS_CONNECT) {
709    HandleConnect(&response);
710  }
711
712  // Consume parsed data
713  *len = response.Length();
714  memcpy(data, response.Data(), *len);
715}
716
717void AsyncSocksProxyServerSocket::DirectSend(const ByteBuffer& buf) {
718  BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
719}
720
721void AsyncSocksProxyServerSocket::HandleHello(ByteBuffer* request) {
722  uint8 ver, num_methods;
723  if (!request->ReadUInt8(&ver) ||
724      !request->ReadUInt8(&num_methods)) {
725    Error(0);
726    return;
727  }
728
729  if (ver != 5) {
730    Error(0);
731    return;
732  }
733
734  // Handle either no-auth (0) or user/pass auth (2)
735  uint8 method = 0xFF;
736  if (num_methods > 0 && !request->ReadUInt8(&method)) {
737    Error(0);
738    return;
739  }
740
741  // TODO: Ask the server which method to use.
742  SendHelloReply(method);
743  if (method == 0) {
744    state_ = SS_CONNECT;
745  } else if (method == 2) {
746    state_ = SS_AUTH;
747  } else {
748    state_ = SS_ERROR;
749  }
750}
751
752void AsyncSocksProxyServerSocket::SendHelloReply(uint8 method) {
753  ByteBuffer response;
754  response.WriteUInt8(5);  // Socks Version
755  response.WriteUInt8(method);  // Auth method
756  DirectSend(response);
757}
758
759void AsyncSocksProxyServerSocket::HandleAuth(ByteBuffer* request) {
760  uint8 ver, user_len, pass_len;
761  std::string user, pass;
762  if (!request->ReadUInt8(&ver) ||
763      !request->ReadUInt8(&user_len) ||
764      !request->ReadString(&user, user_len) ||
765      !request->ReadUInt8(&pass_len) ||
766      !request->ReadString(&pass, pass_len)) {
767    Error(0);
768    return;
769  }
770
771  // TODO: Allow for checking of credentials.
772  SendAuthReply(0);
773  state_ = SS_CONNECT;
774}
775
776void AsyncSocksProxyServerSocket::SendAuthReply(uint8 result) {
777  ByteBuffer response;
778  response.WriteUInt8(1);  // Negotiation Version
779  response.WriteUInt8(result);
780  DirectSend(response);
781}
782
783void AsyncSocksProxyServerSocket::HandleConnect(ByteBuffer* request) {
784  uint8 ver, command, reserved, addr_type;
785  uint32 ip;
786  uint16 port;
787  if (!request->ReadUInt8(&ver) ||
788      !request->ReadUInt8(&command) ||
789      !request->ReadUInt8(&reserved) ||
790      !request->ReadUInt8(&addr_type) ||
791      !request->ReadUInt32(&ip) ||
792      !request->ReadUInt16(&port)) {
793      Error(0);
794      return;
795  }
796
797  if (ver != 5 || command != 1 ||
798      reserved != 0 || addr_type != 1) {
799      Error(0);
800      return;
801  }
802
803  SignalConnectRequest(this, SocketAddress(ip, port));
804  state_ = SS_CONNECT_PENDING;
805}
806
807void AsyncSocksProxyServerSocket::SendConnectResult(int result,
808                                                    const SocketAddress& addr) {
809  if (state_ != SS_CONNECT_PENDING)
810    return;
811
812  ByteBuffer response;
813  response.WriteUInt8(5);  // Socks version
814  response.WriteUInt8((result != 0));  // 0x01 is generic error
815  response.WriteUInt8(0);  // reserved
816  response.WriteUInt8(1);  // IPv4 address
817  response.WriteUInt32(addr.ip());
818  response.WriteUInt16(addr.port());
819  DirectSend(response);
820  BufferInput(false);
821  state_ = SS_TUNNEL;
822}
823
824void AsyncSocksProxyServerSocket::Error(int error) {
825  state_ = SS_ERROR;
826  BufferInput(false);
827  Close();
828  SetError(SOCKET_EACCES);
829  SignalCloseEvent(this, error);
830}
831
832///////////////////////////////////////////////////////////////////////////////
833
834LoggingSocketAdapter::LoggingSocketAdapter(AsyncSocket* socket,
835                                           LoggingSeverity level,
836                                           const char * label, bool hex_mode)
837    : AsyncSocketAdapter(socket), level_(level), hex_mode_(hex_mode) {
838  label_.append("[");
839  label_.append(label);
840  label_.append("]");
841}
842
843int LoggingSocketAdapter::Send(const void *pv, size_t cb) {
844  int res = AsyncSocketAdapter::Send(pv, cb);
845  if (res > 0)
846    LogMultiline(level_, label_.c_str(), false, pv, res, hex_mode_, &lms_);
847  return res;
848}
849
850int LoggingSocketAdapter::SendTo(const void *pv, size_t cb,
851                             const SocketAddress& addr) {
852  int res = AsyncSocketAdapter::SendTo(pv, cb, addr);
853  if (res > 0)
854    LogMultiline(level_, label_.c_str(), false, pv, res, hex_mode_, &lms_);
855  return res;
856}
857
858int LoggingSocketAdapter::Recv(void *pv, size_t cb) {
859  int res = AsyncSocketAdapter::Recv(pv, cb);
860  if (res > 0)
861    LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_);
862  return res;
863}
864
865int LoggingSocketAdapter::RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
866  int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
867  if (res > 0)
868    LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_);
869  return res;
870}
871
872int LoggingSocketAdapter::Close() {
873  LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_);
874  LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_);
875  LOG_V(level_) << label_ << " Closed locally";
876  return socket_->Close();
877}
878
879void LoggingSocketAdapter::OnConnectEvent(AsyncSocket * socket) {
880  LOG_V(level_) << label_ << " Connected";
881  AsyncSocketAdapter::OnConnectEvent(socket);
882}
883
884void LoggingSocketAdapter::OnCloseEvent(AsyncSocket * socket, int err) {
885  LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_);
886  LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_);
887  LOG_V(level_) << label_ << " Closed with error: " << err;
888  AsyncSocketAdapter::OnCloseEvent(socket, err);
889}
890
891///////////////////////////////////////////////////////////////////////////////
892
893}  // namespace rtc
894