// 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 {

#if MHD_VERSION >= 0x00097002
// libmicrohttpd 0.9.71 broke API
#define MHD_RESULT enum MHD_Result
#else
#define MHD_RESULT int
#endif

// Helper class to provide static callback methods to microhttpd library,
// with the ability to access private methods of Request class.
class RequestHelper {
 public:
  static MHD_RESULT 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 MHD_RESULT 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
