Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / net / spdy / hpack_encoding_context.cc
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 #include "net/spdy/hpack_encoding_context.h"
6
7 #include <cstddef>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "net/spdy/hpack_constants.h"
12 #include "net/spdy/hpack_entry.h"
13
14 namespace net {
15
16 using base::StringPiece;
17
18 namespace {
19
20 // An entry in the static table. Must be a POD in order to avoid
21 // static initializers, i.e. no user-defined constructors or
22 // destructors.
23 struct StaticEntry {
24   const char* const name;
25   const size_t name_len;
26   const char* const value;
27   const size_t value_len;
28 };
29
30 // The "constructor" for a StaticEntry that computes the lengths at
31 // compile time.
32 #define STATIC_ENTRY(name, value) \
33   { name, arraysize(name) - 1, value, arraysize(value) - 1 }
34
35 const StaticEntry kStaticTable[] = {
36   STATIC_ENTRY(":authority"                  , ""),             // 1
37   STATIC_ENTRY(":method"                     , "GET"),          // 2
38   STATIC_ENTRY(":method"                     , "POST"),         // 3
39   STATIC_ENTRY(":path"                       , "/"),            // 4
40   STATIC_ENTRY(":path"                       , "/index.html"),  // 5
41   STATIC_ENTRY(":scheme"                     , "http"),         // 6
42   STATIC_ENTRY(":scheme"                     , "https"),        // 7
43   STATIC_ENTRY(":status"                     , "200"),          // 8
44   STATIC_ENTRY(":status"                     , "500"),          // 9
45   STATIC_ENTRY(":status"                     , "404"),          // 10
46   STATIC_ENTRY(":status"                     , "403"),          // 11
47   STATIC_ENTRY(":status"                     , "400"),          // 12
48   STATIC_ENTRY(":status"                     , "401"),          // 13
49   STATIC_ENTRY("accept-charset"              , ""),             // 14
50   STATIC_ENTRY("accept-encoding"             , ""),             // 15
51   STATIC_ENTRY("accept-language"             , ""),             // 16
52   STATIC_ENTRY("accept-ranges"               , ""),             // 17
53   STATIC_ENTRY("accept"                      , ""),             // 18
54   STATIC_ENTRY("access-control-allow-origin" , ""),             // 19
55   STATIC_ENTRY("age"                         , ""),             // 20
56   STATIC_ENTRY("allow"                       , ""),             // 21
57   STATIC_ENTRY("authorization"               , ""),             // 22
58   STATIC_ENTRY("cache-control"               , ""),             // 23
59   STATIC_ENTRY("content-disposition"         , ""),             // 24
60   STATIC_ENTRY("content-encoding"            , ""),             // 25
61   STATIC_ENTRY("content-language"            , ""),             // 26
62   STATIC_ENTRY("content-length"              , ""),             // 27
63   STATIC_ENTRY("content-location"            , ""),             // 28
64   STATIC_ENTRY("content-range"               , ""),             // 29
65   STATIC_ENTRY("content-type"                , ""),             // 30
66   STATIC_ENTRY("cookie"                      , ""),             // 31
67   STATIC_ENTRY("date"                        , ""),             // 32
68   STATIC_ENTRY("etag"                        , ""),             // 33
69   STATIC_ENTRY("expect"                      , ""),             // 34
70   STATIC_ENTRY("expires"                     , ""),             // 35
71   STATIC_ENTRY("from"                        , ""),             // 36
72   STATIC_ENTRY("host"                        , ""),             // 37
73   STATIC_ENTRY("if-match"                    , ""),             // 38
74   STATIC_ENTRY("if-modified-since"           , ""),             // 39
75   STATIC_ENTRY("if-none-match"               , ""),             // 40
76   STATIC_ENTRY("if-range"                    , ""),             // 41
77   STATIC_ENTRY("if-unmodified-since"         , ""),             // 42
78   STATIC_ENTRY("last-modified"               , ""),             // 43
79   STATIC_ENTRY("link"                        , ""),             // 44
80   STATIC_ENTRY("location"                    , ""),             // 45
81   STATIC_ENTRY("max-forwards"                , ""),             // 46
82   STATIC_ENTRY("proxy-authenticate"          , ""),             // 47
83   STATIC_ENTRY("proxy-authorization"         , ""),             // 48
84   STATIC_ENTRY("range"                       , ""),             // 49
85   STATIC_ENTRY("referer"                     , ""),             // 50
86   STATIC_ENTRY("refresh"                     , ""),             // 51
87   STATIC_ENTRY("retry-after"                 , ""),             // 52
88   STATIC_ENTRY("server"                      , ""),             // 53
89   STATIC_ENTRY("set-cookie"                  , ""),             // 54
90   STATIC_ENTRY("strict-transport-security"   , ""),             // 55
91   STATIC_ENTRY("transfer-encoding"           , ""),             // 56
92   STATIC_ENTRY("user-agent"                  , ""),             // 57
93   STATIC_ENTRY("vary"                        , ""),             // 58
94   STATIC_ENTRY("via"                         , ""),             // 59
95   STATIC_ENTRY("www-authenticate"            , ""),             // 60
96 };
97
98 #undef STATIC_ENTRY
99
100 const size_t kStaticEntryCount = arraysize(kStaticTable);
101
102 }  // namespace
103
104 // Must match HpackEntry::kUntouched.
105 const uint32 HpackEncodingContext::kUntouched = 0x7fffffff;
106
107 HpackEncodingContext::HpackEncodingContext()
108     : settings_header_table_size_(kDefaultHeaderTableSizeSetting) {
109   DCHECK_EQ(HpackEncodingContext::kUntouched, HpackEntry::kUntouched);
110 }
111
112 HpackEncodingContext::~HpackEncodingContext() {}
113
114 uint32 HpackEncodingContext::GetMutableEntryCount() const {
115   return header_table_.GetEntryCount();
116 }
117
118 uint32 HpackEncodingContext::GetEntryCount() const {
119   return GetMutableEntryCount() + kStaticEntryCount;
120 }
121
122 StringPiece HpackEncodingContext::GetNameAt(uint32 index) const {
123   CHECK_GE(index, 1u);
124   CHECK_LE(index, GetEntryCount());
125   if (index > header_table_.GetEntryCount()) {
126     const StaticEntry& entry =
127         kStaticTable[index - header_table_.GetEntryCount() - 1];
128     return StringPiece(entry.name, entry.name_len);
129   }
130   return header_table_.GetEntry(index).name();
131 }
132
133 StringPiece HpackEncodingContext::GetValueAt(uint32 index) const {
134   CHECK_GE(index, 1u);
135   CHECK_LE(index, GetEntryCount());
136   if (index > header_table_.GetEntryCount()) {
137     const StaticEntry& entry =
138         kStaticTable[index - header_table_.GetEntryCount() - 1];
139     return StringPiece(entry.value, entry.value_len);
140   }
141   return header_table_.GetEntry(index).value();
142 }
143
144 bool HpackEncodingContext::IsReferencedAt(uint32 index) const {
145   CHECK_GE(index, 1u);
146   CHECK_LE(index, GetEntryCount());
147   if (index > header_table_.GetEntryCount())
148     return false;
149   return header_table_.GetEntry(index).IsReferenced();
150 }
151
152 uint32 HpackEncodingContext::GetTouchCountAt(uint32 index) const {
153   CHECK_GE(index, 1u);
154   CHECK_LE(index, GetEntryCount());
155   if (index > header_table_.GetEntryCount())
156     return 0;
157   return header_table_.GetEntry(index).TouchCount();
158 }
159
160 void HpackEncodingContext::SetReferencedAt(uint32 index, bool referenced) {
161   header_table_.GetMutableEntry(index)->SetReferenced(referenced);
162 }
163
164 void HpackEncodingContext::AddTouchesAt(uint32 index, uint32 touch_count) {
165   header_table_.GetMutableEntry(index)->AddTouches(touch_count);
166 }
167
168 void HpackEncodingContext::ClearTouchesAt(uint32 index) {
169   header_table_.GetMutableEntry(index)->ClearTouches();
170 }
171
172 void HpackEncodingContext::ApplyHeaderTableSizeSetting(uint32 size) {
173   settings_header_table_size_ = size;
174   if (size < header_table_.max_size()) {
175     // Implicit maximum-size context update.
176     CHECK(ProcessContextUpdateNewMaximumSize(size));
177   }
178 }
179
180 bool HpackEncodingContext::ProcessContextUpdateNewMaximumSize(uint32 size) {
181   if (size > settings_header_table_size_) {
182     return false;
183   }
184   header_table_.SetMaxSize(size);
185   return true;
186 }
187
188 bool HpackEncodingContext::ProcessContextUpdateEmptyReferenceSet() {
189   for (size_t i = 1; i <= header_table_.GetEntryCount(); ++i) {
190     HpackEntry* entry = header_table_.GetMutableEntry(i);
191     if (entry->IsReferenced()) {
192       entry->SetReferenced(false);
193     }
194   }
195   return true;
196 }
197
198 bool HpackEncodingContext::ProcessIndexedHeader(uint32 index, uint32* new_index,
199     std::vector<uint32>* removed_referenced_indices) {
200   CHECK_GT(index, 0u);
201   CHECK_LT(index, GetEntryCount());
202
203   if (index <= header_table_.GetEntryCount()) {
204     *new_index = index;
205     removed_referenced_indices->clear();
206     HpackEntry* entry = header_table_.GetMutableEntry(index);
207     entry->SetReferenced(!entry->IsReferenced());
208   } else {
209     // TODO(akalin): Make HpackEntry know about owned strings and
210     // non-owned strings so that it can potentially avoid copies here.
211     HpackEntry entry(GetNameAt(index), GetValueAt(index));
212
213     header_table_.TryAddEntry(entry, new_index, removed_referenced_indices);
214     if (*new_index >= 1) {
215       header_table_.GetMutableEntry(*new_index)->SetReferenced(true);
216     }
217   }
218   return true;
219 }
220
221 bool HpackEncodingContext::ProcessLiteralHeaderWithIncrementalIndexing(
222     StringPiece name,
223     StringPiece value,
224     uint32* index,
225     std::vector<uint32>* removed_referenced_indices) {
226   HpackEntry entry(name, value);
227   header_table_.TryAddEntry(entry, index, removed_referenced_indices);
228   if (*index >= 1) {
229     header_table_.GetMutableEntry(*index)->SetReferenced(true);
230   }
231   return true;
232 }
233
234 }  // namespace net