// Copyright (c) 2012 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.

#ifndef QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
#define QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_

#include <list>
#include <map>
#include <memory>
#include <vector>

#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"

namespace quic {

// In-memory cache for HTTP responses.
// Reads from disk cache generated by:
// `wget -p --save_headers <url>`
class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
 public:
  // Class to manage loading a resource file into memory.  There are
  // two uses: called by InitializeBackend to load resources
  // from files, and recursively called when said resources specify
  // server push associations.
  class ResourceFile {
   public:
    explicit ResourceFile(const std::string& file_name);
    ResourceFile(const ResourceFile&) = delete;
    ResourceFile& operator=(const ResourceFile&) = delete;
    virtual ~ResourceFile();

    void Read();

    // |base| is |file_name_| with |cache_directory| prefix stripped.
    void SetHostPathFromBase(QuicStringPiece base);

    const std::string& file_name() { return file_name_; }

    QuicStringPiece host() { return host_; }

    QuicStringPiece path() { return path_; }

    const spdy::SpdyHeaderBlock& spdy_headers() { return spdy_headers_; }

    QuicStringPiece body() { return body_; }

    const std::vector<QuicStringPiece>& push_urls() { return push_urls_; }

   protected:
    void HandleXOriginalUrl();
    QuicStringPiece RemoveScheme(QuicStringPiece url);

    std::string file_name_;
    std::string file_contents_;
    QuicStringPiece body_;
    spdy::SpdyHeaderBlock spdy_headers_;
    QuicStringPiece x_original_url_;
    std::vector<QuicStringPiece> push_urls_;

   private:
    QuicStringPiece host_;
    QuicStringPiece path_;
  };

  QuicMemoryCacheBackend();
  QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete;
  QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete;
  ~QuicMemoryCacheBackend() override;

  // Retrieve a response from this cache for a given host and path..
  // If no appropriate response exists, nullptr is returned.
  const QuicBackendResponse* GetResponse(QuicStringPiece host,
                                         QuicStringPiece path) const;

  // Adds a simple response to the cache.  The response headers will
  // only contain the "content-length" header with the length of |body|.
  void AddSimpleResponse(QuicStringPiece host,
                         QuicStringPiece path,
                         int response_code,
                         QuicStringPiece body);

  // Add a simple response to the cache as AddSimpleResponse() does, and add
  // some server push resources(resource path, corresponding response status and
  // path) associated with it.
  // Push resource implicitly come from the same host.
  void AddSimpleResponseWithServerPushResources(
      QuicStringPiece host,
      QuicStringPiece path,
      int response_code,
      QuicStringPiece body,
      std::list<QuicBackendResponse::ServerPushInfo> push_resources);

  // Add a response to the cache.
  void AddResponse(QuicStringPiece host,
                   QuicStringPiece path,
                   spdy::SpdyHeaderBlock response_headers,
                   QuicStringPiece response_body);

  // Add a response, with trailers, to the cache.
  void AddResponse(QuicStringPiece host,
                   QuicStringPiece path,
                   spdy::SpdyHeaderBlock response_headers,
                   QuicStringPiece response_body,
                   spdy::SpdyHeaderBlock response_trailers);

  // Simulate a special behavior at a particular path.
  void AddSpecialResponse(
      QuicStringPiece host,
      QuicStringPiece path,
      QuicBackendResponse::SpecialResponseType response_type);

  void AddSpecialResponse(
      QuicStringPiece host,
      QuicStringPiece path,
      spdy::SpdyHeaderBlock response_headers,
      QuicStringPiece response_body,
      QuicBackendResponse::SpecialResponseType response_type);

  void AddStopSendingResponse(QuicStringPiece host,
                              QuicStringPiece path,
                              spdy::SpdyHeaderBlock response_headers,
                              QuicStringPiece response_body,
                              uint16_t stop_sending_code);

  // Sets a default response in case of cache misses.  Takes ownership of
  // 'response'.
  void AddDefaultResponse(QuicBackendResponse* response);

  // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
  void InitializeFromDirectory(const std::string& cache_directory);

  // Find all the server push resources associated with |request_url|.
  std::list<QuicBackendResponse::ServerPushInfo> GetServerPushResources(
      std::string request_url);

  // Implements the functions for interface QuicSimpleServerBackend
  // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
  bool InitializeBackend(const std::string& cache_directory) override;
  bool IsBackendInitialized() const override;
  void FetchResponseFromBackend(
      const spdy::SpdyHeaderBlock& request_headers,
      const std::string& request_body,
      QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
  void CloseBackendResponseStream(
      QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;

 private:
  void AddResponseImpl(QuicStringPiece host,
                       QuicStringPiece path,
                       QuicBackendResponse::SpecialResponseType response_type,
                       spdy::SpdyHeaderBlock response_headers,
                       QuicStringPiece response_body,
                       spdy::SpdyHeaderBlock response_trailers,
                       uint16_t stop_sending_code);

  std::string GetKey(QuicStringPiece host, QuicStringPiece path) const;

  // Add some server push urls with given responses for specified
  // request if these push resources are not associated with this request yet.
  void MaybeAddServerPushResources(
      QuicStringPiece request_host,
      QuicStringPiece request_path,
      std::list<QuicBackendResponse::ServerPushInfo> push_resources);

  // Check if push resource(push_host/push_path) associated with given request
  // url already exists in server push map.
  bool PushResourceExistsInCache(std::string original_request_url,
                                 QuicBackendResponse::ServerPushInfo resource);

  // Cached responses.
  QuicUnorderedMap<std::string, std::unique_ptr<QuicBackendResponse>> responses_
      GUARDED_BY(response_mutex_);

  // The default response for cache misses, if set.
  std::unique_ptr<QuicBackendResponse> default_response_
      GUARDED_BY(response_mutex_);

  // A map from request URL to associated server push responses (if any).
  std::multimap<std::string, QuicBackendResponse::ServerPushInfo>
      server_push_resources_ GUARDED_BY(response_mutex_);

  // Protects against concurrent access from test threads setting responses, and
  // server threads accessing those responses.
  mutable QuicMutex response_mutex_;
  bool cache_initialized_;
};

}  // namespace quic

#endif  // QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
