Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/http_proxy.h"
     18 
     19 #include <errno.h>
     20 #include <netinet/in.h>
     21 #include <linux/if.h>  // NOLINT - Needs definitions from netinet/in.h
     22 #include <stdio.h>
     23 #include <time.h>
     24 
     25 #include <string>
     26 #include <vector>
     27 
     28 #include <base/bind.h>
     29 #include <base/strings/string_number_conversions.h>
     30 #include <base/strings/string_split.h>
     31 #include <base/strings/string_util.h>
     32 #include <base/strings/stringprintf.h>
     33 
     34 #include "shill/async_connection.h"
     35 #include "shill/connection.h"
     36 #include "shill/dns_client.h"
     37 #include "shill/event_dispatcher.h"
     38 #include "shill/logging.h"
     39 #include "shill/net/ip_address.h"
     40 #include "shill/net/sockets.h"
     41 
     42 using base::Bind;
     43 using base::StringPrintf;
     44 using std::string;
     45 using std::vector;
     46 
     47 namespace shill {
     48 
     49 namespace Logging {
     50 static auto kModuleLogScope = ScopeLogger::kHTTPProxy;
     51 static string ObjectID(Connection* c) {
     52   return c->interface_name();
     53 }
     54 }
     55 
     56 const int HTTPProxy::kClientHeaderTimeoutSeconds = 1;
     57 const int HTTPProxy::kConnectTimeoutSeconds = 10;
     58 const int HTTPProxy::kDNSTimeoutSeconds = 5;
     59 const int HTTPProxy::kDefaultServerPort = 80;
     60 const int HTTPProxy::kInputTimeoutSeconds = 30;
     61 const size_t HTTPProxy::kMaxClientQueue = 10;
     62 const size_t HTTPProxy::kMaxHeaderCount = 128;
     63 const size_t HTTPProxy::kMaxHeaderSize = 2048;
     64 const int HTTPProxy::kTransactionTimeoutSeconds = 600;
     65 
     66 const char HTTPProxy::kHTTPMethodConnect[] = "connect";
     67 const char HTTPProxy::kHTTPMethodTerminator[] = " ";
     68 const char HTTPProxy::kHTTPURLDelimiters[] = " /#?";
     69 const char HTTPProxy::kHTTPURLPrefix[] = "http://";
     70 const char HTTPProxy::kHTTPVersionPrefix[] = " HTTP/1";
     71 const char HTTPProxy::kInternalErrorMsg[] = "Proxy Failed: Internal Error";
     72 
     73 HTTPProxy::HTTPProxy(ConnectionRefPtr connection)
     74     : state_(kStateIdle),
     75       connection_(connection),
     76       weak_ptr_factory_(this),
     77       accept_callback_(Bind(&HTTPProxy::AcceptClient,
     78                             weak_ptr_factory_.GetWeakPtr())),
     79       connect_completion_callback_(Bind(&HTTPProxy::OnConnectCompletion,
     80                                         weak_ptr_factory_.GetWeakPtr())),
     81       dns_client_callback_(Bind(&HTTPProxy::GetDNSResult,
     82                                 weak_ptr_factory_.GetWeakPtr())),
     83       read_client_callback_(Bind(&HTTPProxy::ReadFromClient,
     84                                  weak_ptr_factory_.GetWeakPtr())),
     85       read_server_callback_(Bind(&HTTPProxy::ReadFromServer,
     86                                  weak_ptr_factory_.GetWeakPtr())),
     87       write_client_callback_(Bind(&HTTPProxy::WriteToClient,
     88                                   weak_ptr_factory_.GetWeakPtr())),
     89       write_server_callback_(Bind(&HTTPProxy::WriteToServer,
     90                                   weak_ptr_factory_.GetWeakPtr())),
     91       dispatcher_(nullptr),
     92       proxy_port_(-1),
     93       proxy_socket_(-1),
     94       sockets_(nullptr),
     95       client_socket_(-1),
     96       server_port_(kDefaultServerPort),
     97       server_socket_(-1),
     98       is_route_requested_(false) { }
     99 
    100 HTTPProxy::~HTTPProxy() {
    101   Stop();
    102 }
    103 
    104 bool HTTPProxy::Start(EventDispatcher* dispatcher,
    105                       Sockets* sockets) {
    106   SLOG(connection_.get(), 3) << "In " << __func__;
    107 
    108   if (sockets_) {
    109     // We are already running.
    110     return true;
    111   }
    112 
    113   proxy_socket_ = sockets->Socket(PF_INET, SOCK_STREAM, 0);
    114   if (proxy_socket_ < 0) {
    115     PLOG(ERROR) << "Failed to open proxy socket";
    116     return false;
    117   }
    118 
    119   struct sockaddr_in addr;
    120   socklen_t addrlen = sizeof(addr);
    121   memset(&addr, 0, sizeof(addr));
    122   addr.sin_family = AF_INET;
    123   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    124   if (sockets->Bind(proxy_socket_,
    125                     reinterpret_cast<struct sockaddr*>(&addr),
    126                     sizeof(addr)) < 0 ||
    127       sockets->GetSockName(proxy_socket_,
    128                            reinterpret_cast<struct sockaddr*>(&addr),
    129                            &addrlen) < 0 ||
    130       sockets->SetNonBlocking(proxy_socket_) < 0 ||
    131       sockets->Listen(proxy_socket_, kMaxClientQueue) < 0) {
    132     sockets->Close(proxy_socket_);
    133     proxy_socket_ = -1;
    134     PLOG(ERROR) << "HTTPProxy socket setup failed";
    135     return false;
    136   }
    137 
    138   accept_handler_.reset(
    139       dispatcher->CreateReadyHandler(proxy_socket_, IOHandler::kModeInput,
    140                                      accept_callback_));
    141   dispatcher_ = dispatcher;
    142   dns_client_.reset(new DNSClient(IPAddress::kFamilyIPv4,
    143                                   connection_->interface_name(),
    144                                   connection_->dns_servers(),
    145                                   kDNSTimeoutSeconds * 1000,
    146                                   dispatcher,
    147                                   dns_client_callback_));
    148   proxy_port_ = ntohs(addr.sin_port);
    149   server_async_connection_.reset(
    150       new AsyncConnection(connection_->interface_name(), dispatcher, sockets,
    151                           connect_completion_callback_));
    152   sockets_ = sockets;
    153   state_ = kStateWaitConnection;
    154   return true;
    155 }
    156 
    157 void HTTPProxy::Stop() {
    158   SLOG(connection_.get(), 3) << "In " << __func__;
    159 
    160   if (!sockets_) {
    161     return;
    162   }
    163 
    164   StopClient();
    165 
    166   accept_handler_.reset();
    167   dispatcher_ = nullptr;
    168   dns_client_.reset();
    169   proxy_port_ = -1;
    170   server_async_connection_.reset();
    171   sockets_->Close(proxy_socket_);
    172   proxy_socket_ = -1;
    173   sockets_ = nullptr;
    174   state_ = kStateIdle;
    175 }
    176 
    177 // IOReadyHandler callback routine fired when a client connects to the
    178 // proxy's socket.  We Accept() the client and start reading a request
    179 // from it.
    180 void HTTPProxy::AcceptClient(int fd) {
    181   SLOG(connection_.get(), 3) << "In " << __func__;
    182 
    183   int client_fd = sockets_->Accept(fd, nullptr, nullptr);
    184   if (client_fd < 0) {
    185     PLOG(ERROR) << "Client accept failed";
    186     return;
    187   }
    188 
    189   accept_handler_->Stop();
    190 
    191   client_socket_ = client_fd;
    192 
    193   sockets_->SetNonBlocking(client_socket_);
    194   read_client_handler_.reset(dispatcher_->CreateInputHandler(
    195       client_socket_,
    196       read_client_callback_,
    197       Bind(&HTTPProxy::OnReadError, weak_ptr_factory_.GetWeakPtr())));
    198   // Overall transaction timeout.
    199   transaction_timeout_.Reset(Bind(&HTTPProxy::StopClient,
    200                                   weak_ptr_factory_.GetWeakPtr()));
    201   dispatcher_->PostDelayedTask(transaction_timeout_.callback(),
    202                                kTransactionTimeoutSeconds * 1000);
    203 
    204   state_ = kStateReadClientHeader;
    205   StartIdleTimeout();
    206 }
    207 
    208 bool HTTPProxy::ConnectServer(const IPAddress& address, int port) {
    209   state_ = kStateConnectServer;
    210   if (!server_async_connection_->Start(address, port)) {
    211     SendClientError(500, "Could not create socket to connect to server");
    212     return false;
    213   }
    214   StartIdleTimeout();
    215   return true;
    216 }
    217 
    218 // DNSClient callback that fires when the DNS request completes.
    219 void HTTPProxy::GetDNSResult(const Error& error, const IPAddress& address) {
    220   if (!error.IsSuccess()) {
    221     SendClientError(502, string("Could not resolve hostname: ") +
    222                     error.message());
    223     return;
    224   }
    225   ConnectServer(address, server_port_);
    226 }
    227 
    228 // IOReadyHandler callback routine which fires when the asynchronous Connect()
    229 // to the remote server completes (or fails).
    230 void HTTPProxy::OnConnectCompletion(bool success, int fd) {
    231   if (!success) {
    232     SendClientError(500, string("Socket connection delayed failure: ") +
    233                     server_async_connection_->error());
    234     return;
    235   }
    236   server_socket_ = fd;
    237   state_ = kStateTunnelData;
    238 
    239   // If this was a "CONNECT" request, notify the client that the connection
    240   // has been established by sending an "OK" response.
    241   if (base::LowerCaseEqualsASCII(client_method_, kHTTPMethodConnect)) {
    242     SetClientResponse(200, "OK", "", "");
    243     StartReceive();
    244   }
    245 
    246   StartTransmit();
    247 }
    248 
    249 void HTTPProxy::OnReadError(const string& error_msg) {
    250   StopClient();
    251 }
    252 
    253 // Read through the header lines from the client, modifying or adding
    254 // lines as necessary.  Perform final determination of the hostname/port
    255 // we should connect to and either start a DNS request or connect to a
    256 // numeric address.
    257 bool HTTPProxy::ParseClientRequest() {
    258   SLOG(connection_.get(), 3) << "In " << __func__;
    259 
    260   string host;
    261   bool found_via = false;
    262   bool found_connection = false;
    263   for (auto& header : client_headers_) {
    264     if (base::StartsWith(header, "Host:",
    265                          base::CompareCase::INSENSITIVE_ASCII)) {
    266       host = header.substr(5);
    267     } else if (base::StartsWith(header, "Via:",
    268                                 base::CompareCase::INSENSITIVE_ASCII)) {
    269       found_via = true;
    270       header.append(StringPrintf(", %s shill-proxy", client_version_.c_str()));
    271     } else if (base::StartsWith(header, "Connection:",
    272                                 base::CompareCase::INSENSITIVE_ASCII)) {
    273       found_connection = true;
    274       header.assign("Connection: close");
    275     } else if (base::StartsWith(header, "Proxy-Connection:",
    276                                 base::CompareCase::INSENSITIVE_ASCII)) {
    277       header.assign("Proxy-Connection: close");
    278     }
    279   }
    280 
    281   if (!found_connection) {
    282     client_headers_.push_back("Connection: close");
    283   }
    284   if (!found_via) {
    285     client_headers_.push_back(
    286         StringPrintf("Via: %s shill-proxy", client_version_.c_str()));
    287   }
    288 
    289   // Assemble the request as it will be sent to the server.
    290   client_data_.Clear();
    291   if (!base::LowerCaseEqualsASCII(client_method_, kHTTPMethodConnect)) {
    292     for (const auto& header : client_headers_) {
    293       client_data_.Append(ByteString(header + "\r\n", false));
    294     }
    295     client_data_.Append(ByteString(string("\r\n"), false));
    296   }
    297 
    298   base::TrimWhitespaceASCII(host, base::TRIM_ALL, &host);
    299   if (host.empty()) {
    300     // Revert to using the hostname in the URL if no "Host:" header exists.
    301     host = server_hostname_;
    302   }
    303 
    304   if (host.empty()) {
    305     SendClientError(400, "I don't know what host you want me to connect to");
    306     return false;
    307   }
    308 
    309   server_port_ = 80;
    310   vector<string> host_parts = base::SplitString(
    311       host, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
    312 
    313   if (host_parts.size() > 2) {
    314     SendClientError(400, "Too many colons in hostname");
    315     return false;
    316   } else if (host_parts.size() == 2) {
    317     server_hostname_ = host_parts[0];
    318     if (!base::StringToInt(host_parts[1], &server_port_)) {
    319       SendClientError(400, "Could not parse port number");
    320       return false;
    321     }
    322   } else {
    323     server_hostname_ = host;
    324   }
    325 
    326   connection_->RequestRouting();
    327   is_route_requested_ = true;
    328 
    329   IPAddress addr(IPAddress::kFamilyIPv4);
    330   if (addr.SetAddressFromString(server_hostname_)) {
    331     if (!ConnectServer(addr, server_port_)) {
    332       return false;
    333     }
    334   } else {
    335     SLOG(connection_.get(), 3) << "Looking up host: " << server_hostname_;
    336     Error error;
    337     if (!dns_client_->Start(server_hostname_, &error)) {
    338       SendClientError(502, "Could not resolve hostname: " + error.message());
    339       return false;
    340     }
    341     state_ = kStateLookupServer;
    342   }
    343   return true;
    344 }
    345 
    346 // Accept a new line into the client headers.  Returns false if a parse
    347 // error occurs.
    348 bool HTTPProxy::ProcessLastHeaderLine() {
    349   string* header = &client_headers_.back();
    350   base::TrimString(*header, "\r", header);
    351 
    352   if (header->empty()) {
    353     // Empty line terminates client headers.
    354     client_headers_.pop_back();
    355     if (!ParseClientRequest()) {
    356       return false;
    357     }
    358   }
    359 
    360   // Is this is the first header line?
    361   if (client_headers_.size() == 1) {
    362     if (!ReadClientHTTPMethod(header) ||
    363         !ReadClientHTTPVersion(header) ||
    364         !ReadClientHostname(header)) {
    365       return false;
    366     }
    367   }
    368 
    369   if (client_headers_.size() >= kMaxHeaderCount) {
    370     SendClientError(500, kInternalErrorMsg);
    371     return false;
    372   }
    373 
    374   return true;
    375 }
    376 
    377 // Split input from client into header lines, and consume parsed lines
    378 // from InputData.  The passed in |data| is modified to indicate the
    379 // characters consumed.
    380 bool HTTPProxy::ReadClientHeaders(InputData* data) {
    381   unsigned char* ptr = data->buf;
    382   unsigned char* end = ptr + data->len;
    383 
    384   if (client_headers_.empty()) {
    385     client_headers_.push_back(string());
    386   }
    387 
    388   for (; ptr < end && state_ == kStateReadClientHeader; ++ptr) {
    389     if (*ptr == '\n') {
    390       if (!ProcessLastHeaderLine()) {
    391         return false;
    392       }
    393 
    394       // Start a new line.  New chararacters we receive will be appended there.
    395       client_headers_.push_back(string());
    396       continue;
    397     }
    398 
    399     string* header = &client_headers_.back();
    400     // Is the first character of the header line a space or tab character?
    401     if (header->empty() && (*ptr == ' ' || *ptr == '\t') &&
    402         client_headers_.size() > 1) {
    403       // Line Continuation: Add this character to the previous header line.
    404       // This way, all of the data (including newlines and line continuation
    405       // characters) related to a specific header will be contained within
    406       // a single element of |client_headers_|, and manipulation of headers
    407       // such as appending will be simpler.  This is accomplished by removing
    408       // the empty line we started, and instead appending the whitespace
    409       // and following characters to the previous line.
    410       client_headers_.pop_back();
    411       header = &client_headers_.back();
    412       header->append("\r\n");
    413     }
    414 
    415     if (header->length() >= kMaxHeaderSize) {
    416       SendClientError(500, kInternalErrorMsg);
    417       return false;
    418     }
    419     header->push_back(*ptr);
    420   }
    421 
    422   // Return the remaining data to the caller -- this could be POST data
    423   // or other non-header data sent with the client request.
    424   data->buf = ptr;
    425   data->len = end - ptr;
    426 
    427   return true;
    428 }
    429 
    430 // Finds the URL in the first line of an HTTP client header, and extracts
    431 // and removes the hostname (and port) from the URL.  Returns false if a
    432 // parse error occurs, and true otherwise (whether or not the hostname was
    433 // found).
    434 bool HTTPProxy::ReadClientHostname(string* header) {
    435   const string http_url_prefix(kHTTPURLPrefix);
    436   size_t url_idx = header->find(http_url_prefix);
    437   if (url_idx != string::npos) {
    438     size_t host_start = url_idx + http_url_prefix.length();
    439     size_t host_end =
    440       header->find_first_of(kHTTPURLDelimiters, host_start);
    441     if (host_end != string::npos) {
    442       server_hostname_ = header->substr(host_start,
    443                                         host_end - host_start);
    444       // Modify the URL passed upstream to remove "http://<hostname>".
    445       header->erase(url_idx, host_end - url_idx);
    446       if ((*header)[url_idx] != '/') {
    447         header->insert(url_idx, "/");
    448       }
    449     } else {
    450       LOG(ERROR) << "Could not find end of hostname in request.  Line was: "
    451                  << *header;
    452       SendClientError(500, kInternalErrorMsg);
    453       return false;
    454     }
    455   }
    456   return true;
    457 }
    458 
    459 bool HTTPProxy::ReadClientHTTPMethod(string* header) {
    460   size_t method_end = header->find(kHTTPMethodTerminator);
    461   if (method_end == string::npos || method_end == 0) {
    462     LOG(ERROR) << "Could not parse HTTP method.  Line was: " << *header;
    463     SendClientError(501, "Server could not parse HTTP method");
    464     return false;
    465   }
    466   client_method_ = header->substr(0, method_end);
    467   return true;
    468 }
    469 
    470 // Extract the HTTP version number from the first line of the client headers.
    471 // Returns true if found.
    472 bool HTTPProxy::ReadClientHTTPVersion(string* header) {
    473   const string http_version_prefix(kHTTPVersionPrefix);
    474   size_t http_ver_pos = header->find(http_version_prefix);
    475   if (http_ver_pos != string::npos) {
    476     client_version_ =
    477       header->substr(http_ver_pos + http_version_prefix.length() - 1);
    478   } else {
    479     SendClientError(501, "Server only accepts HTTP/1.x requests");
    480     return false;
    481   }
    482   return true;
    483 }
    484 
    485 // IOInputHandler callback that fires when data is read from the client.
    486 // This could be header data, or perhaps POST data that follows the headers.
    487 void HTTPProxy::ReadFromClient(InputData* data) {
    488   SLOG(connection_.get(), 3) << "In " << __func__ << " length " << data->len;
    489 
    490   if (data->len == 0) {
    491     // EOF from client.
    492     StopClient();
    493     return;
    494   }
    495 
    496   if (state_ == kStateReadClientHeader) {
    497     if (!ReadClientHeaders(data)) {
    498       return;
    499     }
    500     if (state_ == kStateReadClientHeader) {
    501       // Still consuming client headers; restart the input timer.
    502       StartIdleTimeout();
    503       return;
    504     }
    505   }
    506 
    507   // Check data->len again since ReadClientHeaders() may have consumed some
    508   // part of it.
    509   if (data->len != 0) {
    510     // The client sent some information after its headers.  Buffer the client
    511     // input and temporarily disable input events from the client.
    512     client_data_.Append(ByteString(data->buf, data->len));
    513     read_client_handler_->Stop();
    514     StartTransmit();
    515   }
    516 }
    517 
    518 // IOInputHandler callback which fires when data has been read from the
    519 // server.
    520 void HTTPProxy::ReadFromServer(InputData* data) {
    521   SLOG(connection_.get(), 3) << "In " << __func__ << " length " << data->len;
    522   if (data->len == 0) {
    523     // Server closed connection.
    524     if (server_data_.IsEmpty()) {
    525       StopClient();
    526       return;
    527     }
    528     state_ = kStateFlushResponse;
    529   } else {
    530     read_server_handler_->Stop();
    531   }
    532 
    533   server_data_.Append(ByteString(data->buf, data->len));
    534 
    535   StartTransmit();
    536 }
    537 
    538 // Return an HTTP error message back to the client.
    539 void HTTPProxy::SendClientError(int code, const string& error) {
    540   SLOG(connection_.get(), 3) << "In " << __func__;
    541   LOG(ERROR) << "Sending error " << error;
    542   SetClientResponse(code, "ERROR", "text/plain", error);
    543   state_ = kStateFlushResponse;
    544   StartTransmit();
    545 }
    546 
    547 // Create an HTTP response message to be sent to the client.
    548 void HTTPProxy::SetClientResponse(int code, const string& type,
    549                                   const string& content_type,
    550                                   const string& message) {
    551   string content_line;
    552   if (!message.empty() && !content_type.empty()) {
    553     content_line = StringPrintf("Content-Type: %s\r\n", content_type.c_str());
    554   }
    555   string response = StringPrintf("HTTP/1.1 %d %s\r\n"
    556                                  "%s\r\n"
    557                                  "%s", code, type.c_str(),
    558                                  content_line.c_str(),
    559                                  message.c_str());
    560   server_data_ = ByteString(response, false);
    561 }
    562 
    563 // Start a timeout for "the next event".  This timeout augments the overall
    564 // transaction timeout to make sure there is some activity occurring at
    565 // reasonable intervals.
    566 void HTTPProxy::StartIdleTimeout() {
    567   int timeout_seconds = 0;
    568   switch (state_) {
    569     case kStateReadClientHeader:
    570       timeout_seconds = kClientHeaderTimeoutSeconds;
    571       break;
    572     case kStateConnectServer:
    573       timeout_seconds = kConnectTimeoutSeconds;
    574       break;
    575     case kStateLookupServer:
    576       // DNSClient has its own internal timeout, so we need not set one here.
    577       timeout_seconds = 0;
    578       break;
    579     default:
    580       timeout_seconds = kInputTimeoutSeconds;
    581       break;
    582   }
    583   idle_timeout_.Cancel();
    584   if (timeout_seconds != 0) {
    585     idle_timeout_.Reset(Bind(&HTTPProxy::StopClient,
    586                              weak_ptr_factory_.GetWeakPtr()));
    587     dispatcher_->PostDelayedTask(idle_timeout_.callback(),
    588                                  timeout_seconds * 1000);
    589   }
    590 }
    591 
    592 // Start the various input handlers.  Listen for new data only if we have
    593 // completely written the last data we've received to the other end.
    594 void HTTPProxy::StartReceive() {
    595   if (state_ == kStateTunnelData && client_data_.IsEmpty()) {
    596     read_client_handler_->Start();
    597   }
    598   if (server_data_.IsEmpty()) {
    599     if (state_ == kStateTunnelData) {
    600       if (read_server_handler_.get()) {
    601         read_server_handler_->Start();
    602       } else {
    603         read_server_handler_.reset(dispatcher_->CreateInputHandler(
    604             server_socket_,
    605             read_server_callback_,
    606             Bind(&HTTPProxy::OnReadError, weak_ptr_factory_.GetWeakPtr())));
    607       }
    608     } else if (state_ == kStateFlushResponse) {
    609       StopClient();
    610       return;
    611     }
    612   }
    613   StartIdleTimeout();
    614 }
    615 
    616 // Start the various output-ready handlers for the endpoints we have
    617 // data waiting for.
    618 void HTTPProxy::StartTransmit() {
    619   if (state_ == kStateTunnelData && !client_data_.IsEmpty()) {
    620     if (write_server_handler_.get()) {
    621       write_server_handler_->Start();
    622     } else {
    623       write_server_handler_.reset(
    624           dispatcher_->CreateReadyHandler(server_socket_,
    625                                           IOHandler::kModeOutput,
    626                                           write_server_callback_));
    627     }
    628   }
    629   if ((state_ == kStateFlushResponse || state_ == kStateTunnelData) &&
    630       !server_data_.IsEmpty()) {
    631     if (write_client_handler_.get()) {
    632       write_client_handler_->Start();
    633     } else {
    634       write_client_handler_.reset(
    635           dispatcher_->CreateReadyHandler(client_socket_,
    636                                           IOHandler::kModeOutput,
    637                                           write_client_callback_));
    638     }
    639   }
    640   StartIdleTimeout();
    641 }
    642 
    643 // End the transaction with the current client, restart the IOHandler
    644 // which alerts us to new clients connecting.  This function is called
    645 // during various error conditions and is a callback for all timeouts.
    646 void HTTPProxy::StopClient() {
    647   SLOG(connection_.get(), 3) << "In " << __func__;
    648 
    649   if (is_route_requested_) {
    650     connection_->ReleaseRouting();
    651     is_route_requested_ = false;
    652   }
    653   write_client_handler_.reset();
    654   read_client_handler_.reset();
    655   if (client_socket_ != -1) {
    656     sockets_->Close(client_socket_);
    657     client_socket_ = -1;
    658   }
    659   client_headers_.clear();
    660   client_method_.clear();
    661   client_version_.clear();
    662   server_port_ = kDefaultServerPort;
    663   write_server_handler_.reset();
    664   read_server_handler_.reset();
    665   if (server_socket_ != -1) {
    666     sockets_->Close(server_socket_);
    667     server_socket_ = -1;
    668   }
    669   server_hostname_.clear();
    670   client_data_.Clear();
    671   server_data_.Clear();
    672   dns_client_->Stop();
    673   server_async_connection_->Stop();
    674   idle_timeout_.Cancel();
    675   transaction_timeout_.Cancel();
    676   accept_handler_->Start();
    677   state_ = kStateWaitConnection;
    678 }
    679 
    680 // Output ReadyHandler callback which fires when the client socket is
    681 // ready for data to be sent to it.
    682 void HTTPProxy::WriteToClient(int fd) {
    683   CHECK_EQ(client_socket_, fd);
    684   int ret = sockets_->Send(fd, server_data_.GetConstData(),
    685                            server_data_.GetLength(), 0);
    686   SLOG(connection_.get(), 3) << "In " << __func__ << " wrote " << ret << " of "
    687                              << server_data_.GetLength();
    688   if (ret < 0) {
    689     LOG(ERROR) << "Server write failed";
    690     StopClient();
    691     return;
    692   }
    693 
    694   server_data_ = ByteString(server_data_.GetConstData() + ret,
    695                             server_data_.GetLength() - ret);
    696 
    697   if (server_data_.IsEmpty()) {
    698     write_client_handler_->Stop();
    699   }
    700 
    701   StartReceive();
    702 }
    703 
    704 // Output ReadyHandler callback which fires when the server socket is
    705 // ready for data to be sent to it.
    706 void HTTPProxy::WriteToServer(int fd) {
    707   CHECK_EQ(server_socket_, fd);
    708   int ret = sockets_->Send(fd, client_data_.GetConstData(),
    709                            client_data_.GetLength(), 0);
    710   SLOG(connection_.get(), 3) << "In " << __func__ << " wrote " << ret << " of "
    711                              << client_data_.GetLength();
    712 
    713   if (ret < 0) {
    714     LOG(ERROR) << "Client write failed";
    715     StopClient();
    716     return;
    717   }
    718 
    719   client_data_ = ByteString(client_data_.GetConstData() + ret,
    720                             client_data_.GetLength() - ret);
    721 
    722   if (client_data_.IsEmpty()) {
    723     write_server_handler_->Stop();
    724   }
    725 
    726   StartReceive();
    727 }
    728 
    729 }  // namespace shill
    730