// Copyright (c) 2009 The Chromium 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 "net/tools/flip_server/mem_cache.h"

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <deque>
#include <map>
#include <string>

#include "base/strings/string_util.h"
#include "net/tools/balsa/balsa_frame.h"
#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/dump_cache/url_to_filename_encoder.h"
#include "net/tools/dump_cache/url_utilities.h"

namespace {
// The directory where cache locates);
const char FLAGS_cache_base_dir[] = ".";
}  // namespace

namespace net {

void StoreBodyAndHeadersVisitor::ProcessBodyData(const char* input,
                                                 size_t size) {
  body.append(input, size);
}

void StoreBodyAndHeadersVisitor::HandleHeaderError(BalsaFrame* framer) {
  HandleError();
}

void StoreBodyAndHeadersVisitor::HandleHeaderWarning(BalsaFrame* framer) {
  HandleError();
}

void StoreBodyAndHeadersVisitor::HandleChunkingError(BalsaFrame* framer) {
  HandleError();
}

void StoreBodyAndHeadersVisitor::HandleBodyError(BalsaFrame* framer) {
  HandleError();
}

FileData::FileData(const BalsaHeaders* headers,
                   const std::string& filename,
                   const std::string& body)
    : filename_(filename), body_(body) {
  if (headers) {
    headers_.reset(new BalsaHeaders);
    headers_->CopyFrom(*headers);
  }
}

FileData::FileData() {}

FileData::~FileData() {}

MemoryCache::MemoryCache() : cwd_(FLAGS_cache_base_dir) {}

MemoryCache::~MemoryCache() { ClearFiles(); }

void MemoryCache::CloneFrom(const MemoryCache& mc) {
  DCHECK_NE(this, &mc);
  ClearFiles();
  files_ = mc.files_;
  cwd_ = mc.cwd_;
}

void MemoryCache::AddFiles() {
  std::deque<std::string> paths;
  paths.push_back(cwd_ + "/GET_");
  DIR* current_dir = NULL;
  while (!paths.empty()) {
    while (current_dir == NULL && !paths.empty()) {
      std::string current_dir_name = paths.front();
      VLOG(1) << "Attempting to open dir: \"" << current_dir_name << "\"";
      current_dir = opendir(current_dir_name.c_str());
      paths.pop_front();

      if (current_dir == NULL) {
        perror("Unable to open directory. ");
        current_dir_name.clear();
        continue;
      }

      if (current_dir) {
        VLOG(1) << "Succeeded opening";
        for (struct dirent* dir_data = readdir(current_dir); dir_data != NULL;
             dir_data = readdir(current_dir)) {
          std::string current_entry_name =
              current_dir_name + "/" + dir_data->d_name;
          if (dir_data->d_type == DT_REG) {
            VLOG(1) << "Found file: " << current_entry_name;
            ReadAndStoreFileContents(current_entry_name.c_str());
          } else if (dir_data->d_type == DT_DIR) {
            VLOG(1) << "Found subdir: " << current_entry_name;
            if (std::string(dir_data->d_name) != "." &&
                std::string(dir_data->d_name) != "..") {
              VLOG(1) << "Adding to search path: " << current_entry_name;
              paths.push_front(current_entry_name);
            }
          }
        }
        VLOG(1) << "Oops, no data left. Closing dir.";
        closedir(current_dir);
        current_dir = NULL;
      }
    }
  }
}

void MemoryCache::ReadToString(const char* filename, std::string* output) {
  output->clear();
  int fd = open(filename, 0, "r");
  if (fd == -1)
    return;
  char buffer[4096];
  ssize_t read_status = read(fd, buffer, sizeof(buffer));
  while (read_status > 0) {
    output->append(buffer, static_cast<size_t>(read_status));
    do {
      read_status = read(fd, buffer, sizeof(buffer));
    } while (read_status <= 0 && errno == EINTR);
  }
  close(fd);
}

void MemoryCache::ReadAndStoreFileContents(const char* filename) {
  StoreBodyAndHeadersVisitor visitor;
  BalsaFrame framer;
  framer.set_balsa_visitor(&visitor);
  framer.set_balsa_headers(&(visitor.headers));
  std::string filename_contents;
  ReadToString(filename, &filename_contents);

  // Ugly hack to make everything look like 1.1.
  if (filename_contents.find("HTTP/1.0") == 0)
    filename_contents[7] = '1';

  size_t pos = 0;
  size_t old_pos = 0;
  while (true) {
    old_pos = pos;
    pos += framer.ProcessInput(filename_contents.data() + pos,
                               filename_contents.size() - pos);
    if (framer.Error() || pos == old_pos) {
      LOG(ERROR) << "Unable to make forward progress, or error"
                    " framing file: " << filename;
      if (framer.Error()) {
        LOG(INFO) << "********************************************ERROR!";
        return;
      }
      return;
    }
    if (framer.MessageFullyRead()) {
      // If no Content-Length or Transfer-Encoding was captured in the
      // file, then the rest of the data is the body.  Many of the captures
      // from within Chrome don't have content-lengths.
      if (!visitor.body.length())
        visitor.body = filename_contents.substr(pos);
      break;
    }
  }
  visitor.headers.RemoveAllOfHeader("content-length");
  visitor.headers.RemoveAllOfHeader("transfer-encoding");
  visitor.headers.RemoveAllOfHeader("connection");
  visitor.headers.AppendHeader("transfer-encoding", "chunked");
  visitor.headers.AppendHeader("connection", "keep-alive");

// Experiment with changing headers for forcing use of cached
// versions of content.
// TODO(mbelshe) REMOVE ME
#if 0
  // TODO(mbelshe) append current date.
  visitor.headers.RemoveAllOfHeader("date");
  if (visitor.headers.HasHeader("expires")) {
    visitor.headers.RemoveAllOfHeader("expires");
    visitor.headers.AppendHeader("expires",
                               "Fri, 30 Aug, 2019 12:00:00 GMT");
  }
#endif
  DCHECK_GE(std::string(filename).size(), cwd_.size() + 1);
  DCHECK_EQ(std::string(filename).substr(0, cwd_.size()), cwd_);
  DCHECK_EQ(filename[cwd_.size()], '/');
  std::string filename_stripped = std::string(filename).substr(cwd_.size() + 1);
  LOG(INFO) << "Adding file (" << visitor.body.length()
            << " bytes): " << filename_stripped;
  size_t slash_pos = filename_stripped.find('/');
  if (slash_pos == std::string::npos) {
    slash_pos = filename_stripped.size();
  }
  InsertFile(
      &visitor.headers, filename_stripped.substr(0, slash_pos), visitor.body);
}

FileData* MemoryCache::GetFileData(const std::string& filename) {
  Files::iterator fi = files_.end();
  if (EndsWith(filename, ".html", true)) {
    fi = files_.find(filename.substr(0, filename.size() - 5) + ".http");
  }
  if (fi == files_.end())
    fi = files_.find(filename);

  if (fi == files_.end()) {
    return NULL;
  }
  return fi->second;
}

bool MemoryCache::AssignFileData(const std::string& filename,
                                 MemCacheIter* mci) {
  mci->file_data = GetFileData(filename);
  if (mci->file_data == NULL) {
    LOG(ERROR) << "Could not find file data for " << filename;
    return false;
  }
  return true;
}

void MemoryCache::InsertFile(const BalsaHeaders* headers,
                             const std::string& filename,
                             const std::string& body) {
  InsertFile(new FileData(headers, filename, body));
}

void MemoryCache::InsertFile(FileData* file_data) {
  Files::iterator it = files_.find(file_data->filename());
  if (it != files_.end()) {
    delete it->second;
    it->second = file_data;
  } else {
    files_.insert(std::make_pair(file_data->filename(), file_data));
  }
}

void MemoryCache::ClearFiles() {
  for (Files::const_iterator i = files_.begin(); i != files_.end(); ++i) {
    delete i->second;
  }
  files_.clear();
}

}  // namespace net
