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