// 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/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(this, 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
