1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_QUIC_QUIC_IN_MEMORY_CACHE_H_
6#define NET_QUIC_QUIC_IN_MEMORY_CACHE_H_
7
8#include <string>
9
10#include "base/containers/hash_tables.h"
11#include "base/memory/singleton.h"
12#include "base/strings/string_piece.h"
13#include "net/base/net_export.h"
14#include "net/tools/balsa/balsa_frame.h"
15#include "net/tools/balsa/balsa_headers.h"
16#include "net/tools/balsa/noop_balsa_visitor.h"
17
18template <typename T> struct DefaultSingletonTraits;
19
20namespace net {
21
22namespace test {
23class QuicInMemoryCachePeer;
24}  // namespace
25
26class QuicServer;
27
28// In-memory cache for HTTP responses.
29// Reads from disk cache generated by:
30// `wget -p --save_headers <url>`
31class QuicInMemoryCache {
32 public:
33  enum SpecialResponseType {
34    REGULAR_RESPONSE,  // Send the headers and body like a server should.
35    CLOSE_CONNECTION,  // Close the connection (sending the close packet).
36    IGNORE_REQUEST,    // Do nothing, expect the client to time out.
37  };
38
39  // Container for response header/body pairs.
40  class Response {
41   public:
42    Response() : response_type_(REGULAR_RESPONSE) {}
43    ~Response() {}
44
45    SpecialResponseType response_type() const { return response_type_; }
46    const BalsaHeaders& headers() const { return headers_; }
47    const base::StringPiece body() const { return base::StringPiece(body_); }
48
49   private:
50    friend class QuicInMemoryCache;
51
52    void set_headers(const BalsaHeaders& headers) {
53      headers_.CopyFrom(headers);
54    }
55    void set_body(base::StringPiece body) {
56      body.CopyToString(&body_);
57    }
58
59    SpecialResponseType response_type_;
60    BalsaHeaders headers_;
61    std::string body_;
62
63    DISALLOW_COPY_AND_ASSIGN(Response);
64  };
65
66  // Returns the singleton instance of the cache.
67  static QuicInMemoryCache* GetInstance();
68
69  // Retrieve a response from this cache for a given request.
70  // If no appropriate response exists, NULL is returned.
71  // Currently, responses are selected based on request URI only.
72  const Response* GetResponse(const BalsaHeaders& request_headers) const;
73
74  // Adds a simple response to the cache.  The response headers will
75  // only contain the "content-length" header with the lenght of |body|.
76  void AddSimpleResponse(base::StringPiece method,
77                         base::StringPiece path,
78                         base::StringPiece version,
79                         base::StringPiece response_code,
80                         base::StringPiece response_detail,
81                         base::StringPiece body);
82
83  // Add a response to the cache.
84  void AddResponse(const BalsaHeaders& request_headers,
85                   const BalsaHeaders& response_headers,
86                   base::StringPiece response_body);
87
88  // Simulate a special behavior at a particular path.
89  void AddSpecialResponse(base::StringPiece method,
90                          base::StringPiece path,
91                          base::StringPiece version,
92                          SpecialResponseType response_type);
93
94 private:
95  typedef base::hash_map<std::string, Response*> ResponseMap;
96  friend struct DefaultSingletonTraits<QuicInMemoryCache>;
97  friend class test::QuicInMemoryCachePeer;
98
99  QuicInMemoryCache();
100  ~QuicInMemoryCache();
101
102  void ResetForTests();
103
104  void Initialize();
105
106  std::string GetKey(const BalsaHeaders& response_headers) const;
107
108  // Cached responses.
109  ResponseMap responses_;
110
111  DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
112};
113
114}  // namespace net
115
116#endif  // NET_QUIC_QUIC_IN_MEMORY_CACHE_H_
117