// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/http_proxy.h"

#include <errno.h>
#include <netinet/in.h>
#include <linux/if.h>  // Needs definitions from netinet/in.h
#include <stdio.h>
#include <time.h>

#include <string>
#include <vector>

#include <base/bind.h>
#include <base/logging.h>
#include <base/string_number_conversions.h>
#include <base/string_split.h>
#include <base/string_util.h>
#include <base/stringprintf.h>

#include "shill/async_connection.h"
#include "shill/connection.h"
#include "shill/dns_client.h"
#include "shill/event_dispatcher.h"
#include "shill/ip_address.h"
#include "shill/scope_logger.h"
#include "shill/sockets.h"

using base::Bind;
using base::StringPrintf;
using std::string;
using std::vector;

namespace shill {

const int HTTPProxy::kClientHeaderTimeoutSeconds = 1;
const int HTTPProxy::kConnectTimeoutSeconds = 10;
const int HTTPProxy::kDNSTimeoutSeconds = 5;
const int HTTPProxy::kDefaultServerPort = 80;
const int HTTPProxy::kInputTimeoutSeconds = 30;
const size_t HTTPProxy::kMaxClientQueue = 10;
const size_t HTTPProxy::kMaxHeaderCount = 128;
const size_t HTTPProxy::kMaxHeaderSize = 2048;
const int HTTPProxy::kTransactionTimeoutSeconds = 600;

const char HTTPProxy::kHTTPMethodConnect[] = "connect";
const char HTTPProxy::kHTTPMethodTerminator[] = " ";
const char HTTPProxy::kHTTPURLDelimiters[] = " /#?";
const char HTTPProxy::kHTTPURLPrefix[] = "http://";
const char HTTPProxy::kHTTPVersionPrefix[] = " HTTP/1";
const char HTTPProxy::kInternalErrorMsg[] = "Proxy Failed: Internal Error";

HTTPProxy::HTTPProxy(ConnectionRefPtr connection)
    : state_(kStateIdle),
      connection_(connection),
      weak_ptr_factory_(this),
      accept_callback_(Bind(&HTTPProxy::AcceptClient,
                            weak_ptr_factory_.GetWeakPtr())),
      connect_completion_callback_(Bind(&HTTPProxy::OnConnectCompletion,
                                        weak_ptr_factory_.GetWeakPtr())),
      dns_client_callback_(Bind(&HTTPProxy::GetDNSResult,
                                weak_ptr_factory_.GetWeakPtr())),
      read_client_callback_(Bind(&HTTPProxy::ReadFromClient,
                                 weak_ptr_factory_.GetWeakPtr())),
      read_server_callback_(Bind(&HTTPProxy::ReadFromServer,
                                 weak_ptr_factory_.GetWeakPtr())),
      write_client_callback_(Bind(&HTTPProxy::WriteToClient,
                                  weak_ptr_factory_.GetWeakPtr())),
      write_server_callback_(Bind(&HTTPProxy::WriteToServer,
                                  weak_ptr_factory_.GetWeakPtr())),
      dispatcher_(NULL),
      dns_client_(NULL),
      proxy_port_(-1),
      proxy_socket_(-1),
      server_async_connection_(NULL),
      sockets_(NULL),
      client_socket_(-1),
      server_port_(kDefaultServerPort),
      server_socket_(-1),
      is_route_requested_(false) { }

HTTPProxy::~HTTPProxy() {
  Stop();
}

bool HTTPProxy::Start(EventDispatcher *dispatcher,
                      Sockets *sockets) {
  SLOG(HTTPProxy, 3) << "In " << __func__;

  if (sockets_) {
    // We are already running.
    return true;
  }

  proxy_socket_ = sockets->Socket(PF_INET, SOCK_STREAM, 0);
  if (proxy_socket_ < 0) {
    PLOG(ERROR) << "Failed to open proxy socket";
    return false;
  }

  struct sockaddr_in addr;
  socklen_t addrlen = sizeof(addr);
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  if (sockets->Bind(proxy_socket_,
                    reinterpret_cast<struct sockaddr *>(&addr),
                    sizeof(addr)) < 0 ||
      sockets->GetSockName(proxy_socket_,
                           reinterpret_cast<struct sockaddr *>(&addr),
                           &addrlen) < 0 ||
      sockets->SetNonBlocking(proxy_socket_) < 0 ||
      sockets->Listen(proxy_socket_, kMaxClientQueue) < 0) {
    sockets->Close(proxy_socket_);
    proxy_socket_ = -1;
    PLOG(ERROR) << "HTTPProxy socket setup failed";
    return false;
  }

  accept_handler_.reset(
      dispatcher->CreateReadyHandler(proxy_socket_, IOHandler::kModeInput,
                                     accept_callback_));
  dispatcher_ = dispatcher;
  dns_client_.reset(new DNSClient(IPAddress::kFamilyIPv4,
                                  connection_->interface_name(),
                                  connection_->dns_servers(),
                                  kDNSTimeoutSeconds * 1000,
                                  dispatcher,
                                  dns_client_callback_));
  proxy_port_ = ntohs(addr.sin_port);
  server_async_connection_.reset(
      new AsyncConnection(connection_->interface_name(), dispatcher, sockets,
                          connect_completion_callback_));
  sockets_ = sockets;
  state_ = kStateWaitConnection;
  return true;
}

void HTTPProxy::Stop() {
  SLOG(HTTPProxy, 3) << "In " << __func__;

  if (!sockets_ ) {
    return;
  }

  StopClient();

  accept_handler_.reset();
  dispatcher_ = NULL;
  dns_client_.reset();
  proxy_port_ = -1;
  server_async_connection_.reset();
  sockets_->Close(proxy_socket_);
  proxy_socket_ = -1;
  sockets_ = NULL;
  state_ = kStateIdle;
}

// IOReadyHandler callback routine fired when a client connects to the
// proxy's socket.  We Accept() the client and start reading a request
// from it.
void HTTPProxy::AcceptClient(int fd) {
  SLOG(HTTPProxy, 3) << "In " << __func__;

  int client_fd = sockets_->Accept(fd, NULL, NULL);
  if (client_fd < 0) {
    PLOG(ERROR) << "Client accept failed";
    return;
  }

  accept_handler_->Stop();

  client_socket_ = client_fd;

  sockets_->SetNonBlocking(client_socket_);
  read_client_handler_.reset(
      dispatcher_->CreateInputHandler(client_socket_,
                                      read_client_callback_));
  // Overall transaction timeout.
  transaction_timeout_.Reset(Bind(&HTTPProxy::StopClient,
                                  weak_ptr_factory_.GetWeakPtr()));
  dispatcher_->PostDelayedTask(transaction_timeout_.callback(),
                               kTransactionTimeoutSeconds * 1000);

  state_ = kStateReadClientHeader;
  StartIdleTimeout();
}

bool HTTPProxy::ConnectServer(const IPAddress &address, int port) {
  state_ = kStateConnectServer;
  if (!server_async_connection_->Start(address, port)) {
    SendClientError(500, "Could not create socket to connect to server");
    return false;
  }
  StartIdleTimeout();
  return true;
}

// DNSClient callback that fires when the DNS request completes.
void HTTPProxy::GetDNSResult(const Error &error, const IPAddress &address) {
  if (!error.IsSuccess()) {
    SendClientError(502, string("Could not resolve hostname: ") +
                    error.message());
    return;
  }
  ConnectServer(address, server_port_);
}

// IOReadyHandler callback routine which fires when the asynchronous Connect()
// to the remote server completes (or fails).
void HTTPProxy::OnConnectCompletion(bool success, int fd) {
  if (!success) {
    SendClientError(500, string("Socket connection delayed failure: ") +
                    server_async_connection_->error());
    return;
  }
  server_socket_ = fd;
  state_ = kStateTunnelData;

  // If this was a "CONNECT" request, notify the client that the connection
  // has been established by sending an "OK" response.
  if (LowerCaseEqualsASCII(client_method_, kHTTPMethodConnect)) {
    SetClientResponse(200, "OK", "", "");
    StartReceive();
  }

  StartTransmit();
}

// Read through the header lines from the client, modifying or adding
// lines as necessary.  Perform final determination of the hostname/port
// we should connect to and either start a DNS request or connect to a
// numeric address.
bool HTTPProxy::ParseClientRequest() {
  SLOG(HTTPProxy, 3) << "In " << __func__;

  string host;
  bool found_via = false;
  bool found_connection = false;
  for (vector<string>::iterator it = client_headers_.begin();
       it != client_headers_.end(); ++it) {
    if (StartsWithASCII(*it, "Host:", false)) {
      host = it->substr(5);
    } else if (StartsWithASCII(*it, "Via:", false)) {
      found_via = true;
      (*it).append(StringPrintf(", %s shill-proxy", client_version_.c_str()));
    } else if (StartsWithASCII(*it, "Connection:", false)) {
      found_connection = true;
      (*it).assign("Connection: close");
    } else if (StartsWithASCII(*it, "Proxy-Connection:", false)) {
      (*it).assign("Proxy-Connection: close");
    }
  }

  if (!found_connection) {
    client_headers_.push_back("Connection: close");
  }
  if (!found_via) {
    client_headers_.push_back(
        StringPrintf("Via: %s shill-proxy", client_version_.c_str()));
  }

  // Assemble the request as it will be sent to the server.
  client_data_.Clear();
  if (!LowerCaseEqualsASCII(client_method_, kHTTPMethodConnect)) {
    for (vector<string>::iterator it = client_headers_.begin();
         it != client_headers_.end(); ++it) {
      client_data_.Append(ByteString(*it + "\r\n", false));
    }
    client_data_.Append(ByteString(string("\r\n"), false));
  }

  TrimWhitespaceASCII(host, TRIM_ALL, &host);
  if (host.empty()) {
    // Revert to using the hostname in the URL if no "Host:" header exists.
    host = server_hostname_;
  }

  if (host.empty()) {
    SendClientError(400, "I don't know what host you want me to connect to");
    return false;
  }

  server_port_ = 80;
  vector<string> host_parts;
  base::SplitString(host, ':', &host_parts);

  if (host_parts.size() > 2) {
    SendClientError(400, "Too many colons in hostname");
    return false;
  } else if (host_parts.size() == 2) {
    server_hostname_ = host_parts[0];
    if (!base::StringToInt(host_parts[1], &server_port_)) {
      SendClientError(400, "Could not parse port number");
      return false;
    }
  } else {
    server_hostname_ = host;
  }

  connection_->RequestRouting();
  is_route_requested_ = true;

  IPAddress addr(IPAddress::kFamilyIPv4);
  if (addr.SetAddressFromString(server_hostname_)) {
    if (!ConnectServer(addr, server_port_)) {
      return false;
    }
  } else {
    SLOG(HTTPProxy, 3) << "Looking up host: " << server_hostname_;
    Error error;
    if (!dns_client_->Start(server_hostname_, &error)) {
      SendClientError(502, "Could not resolve hostname: " + error.message());
      return false;
    }
    state_ = kStateLookupServer;
  }
  return true;
}

// Accept a new line into the client headers.  Returns false if a parse
// error occurs.
bool HTTPProxy::ProcessLastHeaderLine() {
  string *header = &client_headers_.back();
  TrimString(*header, "\r", header);

  if (header->empty()) {
    // Empty line terminates client headers.
    client_headers_.pop_back();
    if (!ParseClientRequest()) {
      return false;
    }
  }

  // Is this is the first header line?
  if (client_headers_.size() == 1) {
    if (!ReadClientHTTPMethod(header) ||
        !ReadClientHTTPVersion(header) ||
        !ReadClientHostname(header)) {
      return false;
    }
  }

  if (client_headers_.size() >= kMaxHeaderCount) {
    SendClientError(500, kInternalErrorMsg);
    return false;
  }

  return true;
}

// Split input from client into header lines, and consume parsed lines
// from InputData.  The passed in |data| is modified to indicate the
// characters consumed.
bool HTTPProxy::ReadClientHeaders(InputData *data) {
  unsigned char *ptr = data->buf;
  unsigned char *end = ptr + data->len;

  if (client_headers_.empty()) {
    client_headers_.push_back(string());
  }

  for (; ptr < end && state_ == kStateReadClientHeader; ++ptr) {
    if (*ptr == '\n') {
      if (!ProcessLastHeaderLine()) {
        return false;
      }

      // Start a new line.  New chararacters we receive will be appended there.
      client_headers_.push_back(string());
      continue;
    }

    string *header = &client_headers_.back();
    // Is the first character of the header line a space or tab character?
    if (header->empty() && (*ptr == ' ' || *ptr == '\t') &&
        client_headers_.size() > 1) {
      // Line Continuation: Add this character to the previous header line.
      // This way, all of the data (including newlines and line continuation
      // characters) related to a specific header will be contained within
      // a single element of |client_headers_|, and manipulation of headers
      // such as appending will be simpler.  This is accomplished by removing
      // the empty line we started, and instead appending the whitespace
      // and following characters to the previous line.
      client_headers_.pop_back();
      header = &client_headers_.back();
      header->append("\r\n");
    }

    if (header->length() >= kMaxHeaderSize) {
      SendClientError(500, kInternalErrorMsg);
      return false;
    }
    header->push_back(*ptr);
  }

  // Return the remaining data to the caller -- this could be POST data
  // or other non-header data sent with the client request.
  data->buf = ptr;
  data->len = end - ptr;

  return true;
}

// Finds the URL in the first line of an HTTP client header, and extracts
// and removes the hostname (and port) from the URL.  Returns false if a
// parse error occurs, and true otherwise (whether or not the hostname was
// found).
bool HTTPProxy::ReadClientHostname(string *header) {
  const string http_url_prefix(kHTTPURLPrefix);
  size_t url_idx = header->find(http_url_prefix);
  if (url_idx != string::npos) {
    size_t host_start = url_idx + http_url_prefix.length();
    size_t host_end =
      header->find_first_of(kHTTPURLDelimiters, host_start);
    if (host_end != string::npos) {
      server_hostname_ = header->substr(host_start,
                                        host_end - host_start);
      // Modify the URL passed upstream to remove "http://<hostname>".
      header->erase(url_idx, host_end - url_idx);
      if ((*header)[url_idx] != '/') {
        header->insert(url_idx, "/");
      }
    } else {
      LOG(ERROR) << "Could not find end of hostname in request.  Line was: "
                 << *header;
      SendClientError(500, kInternalErrorMsg);
      return false;
    }
  }
  return true;
}

bool HTTPProxy::ReadClientHTTPMethod(string *header) {
  size_t method_end = header->find(kHTTPMethodTerminator);
  if (method_end == string::npos || method_end == 0) {
    LOG(ERROR) << "Could not parse HTTP method.  Line was: " << *header;
    SendClientError(501, "Server could not parse HTTP method");
    return false;
  }
  client_method_ = header->substr(0, method_end);
  return true;
}

// Extract the HTTP version number from the first line of the client headers.
// Returns true if found.
bool HTTPProxy::ReadClientHTTPVersion(string *header) {
  const string http_version_prefix(kHTTPVersionPrefix);
  size_t http_ver_pos = header->find(http_version_prefix);
  if (http_ver_pos != string::npos) {
    client_version_ =
      header->substr(http_ver_pos + http_version_prefix.length() - 1);
  } else {
    SendClientError(501, "Server only accepts HTTP/1.x requests");
    return false;
  }
  return true;
}

// IOInputHandler callback that fires when data is read from the client.
// This could be header data, or perhaps POST data that follows the headers.
void HTTPProxy::ReadFromClient(InputData *data) {
  SLOG(HTTPProxy, 3) << "In " << __func__ << " length " << data->len;

  if (data->len == 0) {
    // EOF from client.
    StopClient();
    return;
  }

  if (state_ == kStateReadClientHeader) {
    if (!ReadClientHeaders(data)) {
      return;
    }
    if (state_ == kStateReadClientHeader) {
      // Still consuming client headers; restart the input timer.
      StartIdleTimeout();
      return;
    }
  }

  // Check data->len again since ReadClientHeaders() may have consumed some
  // part of it.
  if (data->len != 0) {
    // The client sent some information after its headers.  Buffer the client
    // input and temporarily disable input events from the client.
    client_data_.Append(ByteString(data->buf, data->len));
    read_client_handler_->Stop();
    StartTransmit();
  }
}

// IOInputHandler callback which fires when data has been read from the
// server.
void HTTPProxy::ReadFromServer(InputData *data) {
  SLOG(HTTPProxy, 3) << "In " << __func__ << " length " << data->len;
  if (data->len == 0) {
    // Server closed connection.
    if (server_data_.IsEmpty()) {
      StopClient();
      return;
    }
    state_ = kStateFlushResponse;
  } else {
    read_server_handler_->Stop();
  }

  server_data_.Append(ByteString(data->buf, data->len));

  StartTransmit();
}

// Return an HTTP error message back to the client.
void HTTPProxy::SendClientError(int code, const string &error) {
  SLOG(HTTPProxy, 3) << "In " << __func__;
  LOG(ERROR) << "Sending error " << error;
  SetClientResponse(code, "ERROR", "text/plain", error);
  state_ = kStateFlushResponse;
  StartTransmit();
}

// Create an HTTP response message to be sent to the client.
void HTTPProxy::SetClientResponse(int code, const string &type,
                                  const string &content_type,
                                  const string &message) {
  string content_line;
  if (!message.empty() && !content_type.empty()) {
    content_line = StringPrintf("Content-Type: %s\r\n", content_type.c_str());
  }
  string response = StringPrintf("HTTP/1.1 %d %s\r\n"
                                 "%s\r\n"
                                 "%s", code, type.c_str(),
                                 content_line.c_str(),
                                 message.c_str());
  server_data_ = ByteString(response, false);
}

// Start a timeout for "the next event".  This timeout augments the overall
// transaction timeout to make sure there is some activity occurring at
// reasonable intervals.
void HTTPProxy::StartIdleTimeout() {
  int timeout_seconds = 0;
  switch (state_) {
    case kStateReadClientHeader:
      timeout_seconds = kClientHeaderTimeoutSeconds;
      break;
    case kStateConnectServer:
      timeout_seconds = kConnectTimeoutSeconds;
      break;
    case kStateLookupServer:
      // DNSClient has its own internal timeout, so we need not set one here.
      timeout_seconds = 0;
      break;
    default:
      timeout_seconds = kInputTimeoutSeconds;
      break;
  }
  idle_timeout_.Cancel();
  if (timeout_seconds != 0) {
    idle_timeout_.Reset(Bind(&HTTPProxy::StopClient,
                             weak_ptr_factory_.GetWeakPtr()));
    dispatcher_->PostDelayedTask(idle_timeout_.callback(),
                                 timeout_seconds * 1000);
  }
}

// Start the various input handlers.  Listen for new data only if we have
// completely written the last data we've received to the other end.
void HTTPProxy::StartReceive() {
  if (state_ == kStateTunnelData && client_data_.IsEmpty()) {
    read_client_handler_->Start();
  }
  if (server_data_.IsEmpty()) {
    if (state_ == kStateTunnelData) {
      if (read_server_handler_.get()) {
        read_server_handler_->Start();
      } else {
        read_server_handler_.reset(
            dispatcher_->CreateInputHandler(server_socket_,
                                            read_server_callback_));
      }
    } else if (state_ == kStateFlushResponse) {
      StopClient();
      return;
    }
  }
  StartIdleTimeout();
}

// Start the various output-ready handlers for the endpoints we have
// data waiting for.
void HTTPProxy::StartTransmit() {
  if (state_ == kStateTunnelData && !client_data_.IsEmpty()) {
    if (write_server_handler_.get()) {
      write_server_handler_->Start();
    } else {
      write_server_handler_.reset(
          dispatcher_->CreateReadyHandler(server_socket_,
                                          IOHandler::kModeOutput,
                                          write_server_callback_));
    }
  }
  if ((state_ == kStateFlushResponse || state_ == kStateTunnelData) &&
      !server_data_.IsEmpty()) {
    if (write_client_handler_.get()) {
      write_client_handler_->Start();
    } else {
      write_client_handler_.reset(
          dispatcher_->CreateReadyHandler(client_socket_,
                                          IOHandler::kModeOutput,
                                          write_client_callback_));
    }
  }
  StartIdleTimeout();
}

// End the transaction with the current client, restart the IOHandler
// which alerts us to new clients connecting.  This function is called
// during various error conditions and is a callback for all timeouts.
void HTTPProxy::StopClient() {
  SLOG(HTTPProxy, 3) << "In " << __func__;

  if (is_route_requested_) {
    connection_->ReleaseRouting();
    is_route_requested_ = false;
  }
  write_client_handler_.reset();
  read_client_handler_.reset();
  if (client_socket_ != -1) {
    sockets_->Close(client_socket_);
    client_socket_ = -1;
  }
  client_headers_.clear();
  client_method_.clear();
  client_version_.clear();
  server_port_ = kDefaultServerPort;
  write_server_handler_.reset();
  read_server_handler_.reset();
  if (server_socket_ != -1) {
    sockets_->Close(server_socket_);
    server_socket_ = -1;
  }
  server_hostname_.clear();
  client_data_.Clear();
  server_data_.Clear();
  dns_client_->Stop();
  server_async_connection_->Stop();
  idle_timeout_.Cancel();
  transaction_timeout_.Cancel();
  accept_handler_->Start();
  state_ = kStateWaitConnection;
}

// Output ReadyHandler callback which fires when the client socket is
// ready for data to be sent to it.
void HTTPProxy::WriteToClient(int fd) {
  CHECK_EQ(client_socket_, fd);
  int ret = sockets_->Send(fd, server_data_.GetConstData(),
                           server_data_.GetLength(), 0);
  SLOG(HTTPProxy, 3) << "In " << __func__ << " wrote " << ret << " of "
                     << server_data_.GetLength();
  if (ret < 0) {
    LOG(ERROR) << "Server write failed";
    StopClient();
    return;
  }

  server_data_ = ByteString(server_data_.GetConstData() + ret,
                            server_data_.GetLength() - ret);

  if (server_data_.IsEmpty()) {
    write_client_handler_->Stop();
  }

  StartReceive();
}

// Output ReadyHandler callback which fires when the server socket is
// ready for data to be sent to it.
void HTTPProxy::WriteToServer(int fd) {
  CHECK_EQ(server_socket_, fd);
  int ret = sockets_->Send(fd, client_data_.GetConstData(),
                           client_data_.GetLength(), 0);
  SLOG(HTTPProxy, 3) << "In " << __func__ << " wrote " << ret << " of "
                     << client_data_.GetLength();

  if (ret < 0) {
    LOG(ERROR) << "Client write failed";
    StopClient();
    return;
  }

  client_data_ = ByteString(client_data_.GetConstData() + ret,
                            client_data_.GetLength() - ret);

  if (client_data_.IsEmpty()) {
    write_server_handler_->Stop();
  }

  StartReceive();
}

}  // namespace shill
