// Copyright 2015 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 "webservd/request.h"

#include <arpa/inet.h>
#include <microhttpd.h>
#include <netinet/in.h>

#include <base/bind.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file.h>
#include <base/guid.h>
#include <brillo/http/http_request.h>
#include <brillo/http/http_utils.h>
#include <brillo/mime_utils.h>
#include <brillo/streams/file_stream.h>
#include <brillo/strings/string_utils.h>
#include "webservd/log_manager.h"
#include "webservd/protocol_handler.h"
#include "webservd/request_handler_interface.h"
#include "webservd/server_interface.h"
#include "webservd/temp_file_manager.h"

namespace webservd {

// Helper class to provide static callback methods to microhttpd library,
// with the ability to access private methods of Request class.
class RequestHelper {
 public:
  static int PostDataIterator(void* cls,
                              MHD_ValueKind /* kind */,
                              const char* key,
                              const char* filename,
                              const char* content_type,
                              const char* transfer_encoding,
                              const char* data,
                              uint64_t off,
                              size_t size) {
    auto self = reinterpret_cast<Request*>(cls);
    return self->ProcessPostData(key, filename, content_type, transfer_encoding,
                                 data, off, size)
               ? MHD_YES
               : MHD_NO;
  }

  static int ValueCallback(void* cls,
                           MHD_ValueKind kind,
                           const char* key,
                           const char* value) {
    auto self = reinterpret_cast<Request*>(cls);
    std::string data;
    if (value)
      data = value;
    if (kind == MHD_HEADER_KIND) {
      self->headers_.emplace_back(brillo::http::GetCanonicalHeaderName(key),
                                  data);
    } else if (kind == MHD_COOKIE_KIND) {
      // TODO(avakulenko): add support for cookies...
    } else if (kind == MHD_POSTDATA_KIND) {
      self->post_data_.emplace_back(key, data);
    } else if (kind == MHD_GET_ARGUMENT_KIND) {
      self->get_data_.emplace_back(key, data);
    }
    return MHD_YES;
  }
};

FileInfo::FileInfo(const std::string& in_field_name,
                   const std::string& in_file_name,
                   const std::string& in_content_type,
                   const std::string& in_transfer_encoding)
    : field_name(in_field_name),
      file_name(in_file_name),
      content_type(in_content_type),
      transfer_encoding(in_transfer_encoding) {}

Request::Request(const std::string& request_handler_id,
                 const std::string& url,
                 const std::string& method,
                 const std::string& version,
                 MHD_Connection* connection,
                 ProtocolHandler* protocol_handler)
    : id_{base::GenerateGUID()},
      request_handler_id_{request_handler_id},
      url_{url},
      method_{method},
      version_{version},
      connection_{connection},
      protocol_handler_{protocol_handler} {
  // Here we create the data pipe used to transfer the request body from the
  // web server to the remote request handler.
  int pipe_fds[2] = {-1, -1};
  CHECK_EQ(0, pipe(pipe_fds));
  request_data_pipe_out_ = base::File{pipe_fds[0]};
  CHECK(request_data_pipe_out_.IsValid());
  request_data_stream_ =
      brillo::FileStream::FromFileDescriptor(pipe_fds[1], true, nullptr);
  CHECK(request_data_stream_);

  // POST request processor.
  post_processor_ = MHD_create_post_processor(
      connection, 1024, &RequestHelper::PostDataIterator, this);
}

Request::~Request() {
  if (post_processor_)
    MHD_destroy_post_processor(post_processor_);
  GetTempFileManager()->DeleteRequestTempFiles(id_);
  protocol_handler_->RemoveRequest(this);
}

base::File Request::GetFileData(int file_id) {
  base::File file;
  if (file_id >= 0 && static_cast<size_t>(file_id) < file_info_.size()) {
    file.Initialize(file_info_[file_id]->temp_file_name,
                    base::File::FLAG_OPEN | base::File::FLAG_READ);
  }
  return file;
}

base::File Request::Complete(
    int32_t status_code,
    const std::vector<std::tuple<std::string, std::string>>& headers,
    int64_t in_data_size) {
  base::File file;
  if (response_data_started_)
    return file;

  response_status_code_ = status_code;
  response_headers_.reserve(headers.size());
  for (const auto& tuple : headers) {
    response_headers_.emplace_back(std::get<0>(tuple), std::get<1>(tuple));
  }

  // Create the pipe for response data.
  int pipe_fds[2] = {-1, -1};
  CHECK_EQ(0, pipe(pipe_fds));
  file = base::File{pipe_fds[1]};
  CHECK(file.IsValid());
  response_data_stream_ =
      brillo::FileStream::FromFileDescriptor(pipe_fds[0], true, nullptr);
  CHECK(response_data_stream_);

  response_data_size_ = in_data_size;
  response_data_started_ = true;
  const MHD_ConnectionInfo* info =
      MHD_get_connection_info(connection_, MHD_CONNECTION_INFO_CLIENT_ADDRESS);

  const sockaddr* client_addr = (info ? info->client_addr : nullptr);
  LogManager::OnRequestCompleted(base::Time::Now(), client_addr, method_, url_,
                                 version_, status_code, in_data_size);
  protocol_handler_->ScheduleWork();
  return file;
}

bool Request::Complete(
    int32_t status_code,
    const std::vector<std::tuple<std::string, std::string>>& /* headers */,
    const std::string& mime_type,
    const std::string& data) {
  std::vector<std::tuple<std::string, std::string>> headers_copy;
  headers_copy.emplace_back(brillo::http::response_header::kContentType,
                            mime_type);
  base::File file = Complete(status_code, headers_copy, data.size());
  bool success = false;
  if (file.IsValid()) {
    const int size = data.size();
    success = (file.WriteAtCurrentPos(data.c_str(), size) == size);
  }
  return success;
}

const std::string& Request::GetProtocolHandlerID() const {
  return protocol_handler_->GetID();
}

int Request::GetBodyDataFileDescriptor() const {
  int fd = dup(request_data_pipe_out_.GetPlatformFile());
  CHECK_GE(fd, 0);
  return fd;
}

bool Request::BeginRequestData() {
  MHD_get_connection_values(connection_, MHD_HEADER_KIND,
                            &RequestHelper::ValueCallback, this);
  MHD_get_connection_values(connection_, MHD_COOKIE_KIND,
                            &RequestHelper::ValueCallback, this);
  MHD_get_connection_values(connection_, MHD_POSTDATA_KIND,
                            &RequestHelper::ValueCallback, this);
  MHD_get_connection_values(connection_, MHD_GET_ARGUMENT_KIND,
                            &RequestHelper::ValueCallback, this);
  // If we have POST processor, then we are parsing the request ourselves and
  // we need to dispatch it to the handler only after all the data is parsed.
  // Otherwise forward the request immediately and let the handler read the
  // request data as needed.
  if (!post_processor_)
    ForwardRequestToHandler();
  return true;
}

bool Request::AddRequestData(const void* data, size_t* size) {
  if (!post_processor_)
    return AddRawRequestData(data, size);
  int result =
      MHD_post_process(post_processor_, static_cast<const char*>(data), *size);
  *size = 0;
  return result == MHD_YES;
}

void Request::EndRequestData() {
  if (!request_data_finished_) {
    if (request_data_stream_)
      request_data_stream_->CloseBlocking(nullptr);
    if (!request_forwarded_)
      ForwardRequestToHandler();
    request_data_finished_ = true;
  }

  if (response_data_started_ && !response_data_finished_) {
    MHD_Response* resp = MHD_create_response_from_callback(
        response_data_size_, 4096, &Request::ResponseDataCallback, this,
        nullptr);
    CHECK(resp);
    for (const auto& pair : response_headers_) {
      MHD_add_response_header(resp, pair.first.c_str(), pair.second.c_str());
    }
    CHECK_EQ(MHD_YES,
             MHD_queue_response(connection_, response_status_code_, resp))
        << "Failed to queue response";
    MHD_destroy_response(resp);  // |resp| is ref-counted.
    response_data_finished_ = true;
  }
}

void Request::ForwardRequestToHandler() {
  request_forwarded_ = true;
  if (!request_handler_id_.empty()) {
    // Close all temporary file streams, if any.
    for (auto& file : file_info_)
      file->data_stream->CloseBlocking(nullptr);

    protocol_handler_->AddRequest(this);
    auto p = protocol_handler_->request_handlers_.find(request_handler_id_);
    CHECK(p != protocol_handler_->request_handlers_.end());
    const MHD_ConnectionInfo* info = MHD_get_connection_info(
        connection_, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
    struct sockaddr_in6* sock_addr;
    char src[INET6_ADDRSTRLEN] = {};
    if (info) {
      sock_addr = reinterpret_cast<struct sockaddr_in6*>(info->client_addr);
      inet_ntop(AF_INET6, &sock_addr->sin6_addr, src, INET6_ADDRSTRLEN);
    }
    // Send the request over D-Bus and await the response.
    p->second.handler->HandleRequest(weak_ptr_factory_.GetWeakPtr(), src);
  } else {
    // There was no handler found when request was made, respond with
    // 404 Page Not Found.
    Complete(brillo::http::status_code::NotFound, {},
             brillo::mime::text::kPlain, "Not Found");
  }
}

bool Request::ProcessPostData(const char* key,
                              const char* filename,
                              const char* content_type,
                              const char* transfer_encoding,
                              const char* data,
                              uint64_t off,
                              size_t size) {
  if (off > 0)
    return AppendPostFieldData(key, data, size);

  return AddPostFieldData(key, filename, content_type, transfer_encoding, data,
                          size);
}

bool Request::AddRawRequestData(const void* data, size_t* size) {
  CHECK(*size);
  CHECK(request_data_stream_) << "Data pipe hasn't been created.";

  size_t written = 0;
  if (!request_data_stream_->WriteNonBlocking(data, *size, &written, nullptr))
    return false;

  CHECK_LE(written, *size);

  // If we didn't write all the data requested, we need to let libmicrohttpd do
  // another write cycle. Schedule a DoWork() action here.
  if (written != *size)
    protocol_handler_->ScheduleWork();

  *size -= written;

  // If written at least some data, we are good. We will be called again if more
  // data is available.
  if (written > 0 || waiting_for_data_)
    return true;

  // Nothing has been written. The output pipe is full. Need to stop the data
  // transfer on the connection and wait till some data is being read from the
  // pipe by the request handler.
  MHD_suspend_connection(connection_);

  // Now, just monitor the pipe and figure out when we can resume sending data
  // over it.
  waiting_for_data_ = request_data_stream_->WaitForData(
      brillo::Stream::AccessMode::WRITE,
      base::Bind(&Request::OnPipeAvailable, weak_ptr_factory_.GetWeakPtr()),
      nullptr);

  if (!waiting_for_data_)
    MHD_resume_connection(connection_);

  return waiting_for_data_;
}

ssize_t Request::ResponseDataCallback(void* cls,
                                      uint64_t /* pos */,
                                      char* buf,
                                      size_t max) {
  Request* self = static_cast<Request*>(cls);
  size_t read = 0;
  bool eos = false;
  if (!self->response_data_stream_->ReadNonBlocking(buf, max, &read, &eos,
                                                    nullptr)) {
    return MHD_CONTENT_READER_END_WITH_ERROR;
  }

  if (read > 0 || self->waiting_for_data_)
    return read;

  if (eos)
    return MHD_CONTENT_READER_END_OF_STREAM;

  // Nothing can be read. The input pipe is empty. Need to stop the data
  // transfer on the connection and wait till some data is available from the
  // pipe.
  MHD_suspend_connection(self->connection_);

  self->waiting_for_data_ = self->response_data_stream_->WaitForData(
      brillo::Stream::AccessMode::READ,
      base::Bind(&Request::OnPipeAvailable,
                 self->weak_ptr_factory_.GetWeakPtr()),
      nullptr);

  if (!self->waiting_for_data_) {
    MHD_resume_connection(self->connection_);
    return MHD_CONTENT_READER_END_WITH_ERROR;
  }
  return 0;
}

void Request::OnPipeAvailable(brillo::Stream::AccessMode /* mode */) {
  MHD_resume_connection(connection_);
  waiting_for_data_ = false;
  protocol_handler_->ScheduleWork();
}

bool Request::AddPostFieldData(const char* key,
                               const char* filename,
                               const char* content_type,
                               const char* transfer_encoding,
                               const char* data,
                               size_t size) {
  if (filename) {
    std::unique_ptr<FileInfo> file_info{
        new FileInfo{key, filename, content_type ? content_type : "",
                     transfer_encoding ? transfer_encoding : ""}};
    file_info->temp_file_name = GetTempFileManager()->CreateTempFileName(id_);
    file_info->data_stream = brillo::FileStream::Open(
        file_info->temp_file_name, brillo::Stream::AccessMode::READ_WRITE,
        brillo::FileStream::Disposition::CREATE_ALWAYS, nullptr);
    if (!file_info->data_stream ||
        !file_info->data_stream->WriteAllBlocking(data, size, nullptr)) {
      return false;
    }
    file_info_.push_back(std::move(file_info));
    last_posted_data_was_file_ = true;
    return true;
  }
  std::string value{data, size};
  post_data_.emplace_back(key, value);
  last_posted_data_was_file_ = false;
  return true;
}

bool Request::AppendPostFieldData(const char* key,
                                  const char* data,
                                  size_t size) {
  if (last_posted_data_was_file_) {
    CHECK(!file_info_.empty());
    CHECK(file_info_.back()->field_name == key);
    FileInfo* file_info = file_info_.back().get();
    return file_info->data_stream->WriteAllBlocking(data, size, nullptr);
  }

  CHECK(!post_data_.empty());
  CHECK(post_data_.back().first == key);
  post_data_.back().second.append(data, size);
  return true;
}

TempFileManager* Request::GetTempFileManager() {
  return protocol_handler_->GetServer()->GetTempFileManager();
}

}  // namespace webservd
