// 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/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) {
  VLOG(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() {
  VLOG(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) {
  VLOG(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() {
  VLOG(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 {
    VLOG(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) {
  VLOG(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) {
  VLOG(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) {
  VLOG(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() {
  VLOG(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);
  VLOG(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);
  VLOG(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
