// 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 QuicString& 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 QuicString& 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);

    QuicString file_name_;
    QuicString 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 QuicString& cache_directory);

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

  // Implements the functions for interface QuicSimpleServerBackend
  // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
  bool InitializeBackend(const QuicString& cache_directory) override;
  bool IsBackendInitialized() const override;
  void FetchResponseFromBackend(
      const spdy::SpdyHeaderBlock& request_headers,
      const QuicString& 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);

  QuicString 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(QuicString original_request_url,
                                 QuicBackendResponse::ServerPushInfo resource);

  // Cached responses.
  QuicUnorderedMap<QuicString, 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<QuicString, 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_
