OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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/websockets/websocket_deflate_parameters.h" | |
6 | |
7 #include "base/strings/string_number_conversions.h" | |
8 | |
9 namespace net { | |
10 | |
11 namespace { | |
12 | |
13 const char kServerNoContextTakeOver[] = "server_no_context_takeover"; | |
14 const char kClientNoContextTakeOver[] = "client_no_context_takeover"; | |
15 const char kServerMaxWindowBits[] = "server_max_window_bits"; | |
16 const char kClientMaxWindowBits[] = "client_max_window_bits"; | |
17 const char kExtensionName[] = "permessage-deflate"; | |
18 | |
19 bool GetWindowBits(const std::string& value, int* window_bits) { | |
20 return !value.empty() && value[0] != '0' && | |
21 value.find_first_not_of("0123456789") == std::string::npos && | |
22 base::StringToInt(value, window_bits); | |
23 } | |
24 | |
25 bool DuplicateError(const std::string& name, std::string* failure_message) { | |
26 *failure_message = | |
27 "Received duplicate permessage-deflate extension parameter " + name; | |
28 return false; | |
29 } | |
30 | |
31 bool InvalidError(const std::string& name, std::string* failure_message) { | |
32 *failure_message = "Received invalid " + name + " parameter"; | |
33 return false; | |
34 } | |
35 | |
36 } // namespace | |
37 | |
38 WebSocketExtension WebSocketDeflateParameters::AsExtension() const { | |
39 WebSocketExtension e(kExtensionName); | |
40 | |
41 if (server_context_take_over_mode_ == DO_NOT_TAKE_OVER_CONTEXT) | |
42 e.Add(WebSocketExtension::Parameter(kServerNoContextTakeOver)); | |
43 if (client_context_take_over_mode_ == DO_NOT_TAKE_OVER_CONTEXT) | |
44 e.Add(WebSocketExtension::Parameter(kClientNoContextTakeOver)); | |
45 if (is_server_max_window_bits_specified()) { | |
46 DCHECK(server_max_window_bits_.has_value); | |
47 e.Add(WebSocketExtension::Parameter( | |
48 kServerMaxWindowBits, base::IntToString(server_max_window_bits()))); | |
49 } | |
50 if (is_client_max_window_bits_specified()) { | |
51 if (has_client_max_window_bits_value()) { | |
52 e.Add(WebSocketExtension::Parameter( | |
53 kClientMaxWindowBits, base::IntToString(client_max_window_bits()))); | |
54 } else { | |
55 e.Add(WebSocketExtension::Parameter(kClientMaxWindowBits)); | |
56 } | |
57 } | |
58 | |
59 return e; | |
60 } | |
61 | |
62 bool WebSocketDeflateParameters::IsValidAsRequest(std::string*) const { | |
63 if (server_max_window_bits_.is_specified) { | |
64 DCHECK(server_max_window_bits_.has_value); | |
65 DCHECK(IsValidWindowBits(server_max_window_bits_.bits)); | |
66 } | |
67 if (client_max_window_bits_.is_specified && | |
68 client_max_window_bits_.has_value) { | |
69 DCHECK(IsValidWindowBits(client_max_window_bits_.bits)); | |
70 } | |
71 return true; | |
72 } | |
73 | |
74 bool WebSocketDeflateParameters::IsValidAsResponse( | |
75 std::string* failure_message) const { | |
76 if (server_max_window_bits_.is_specified) { | |
77 DCHECK(server_max_window_bits_.has_value); | |
78 DCHECK(IsValidWindowBits(server_max_window_bits_.bits)); | |
79 } | |
80 if (client_max_window_bits_.is_specified) { | |
81 if (!client_max_window_bits_.has_value) { | |
82 *failure_message = "client_max_window_bits must have value"; | |
83 return false; | |
84 } | |
85 DCHECK(IsValidWindowBits(client_max_window_bits_.bits)); | |
86 } | |
87 | |
88 return true; | |
89 } | |
90 | |
91 bool WebSocketDeflateParameters::Initialize(const WebSocketExtension& extension, | |
92 std::string* failure_message) { | |
93 *this = WebSocketDeflateParameters(); | |
94 | |
95 if (extension.name() != kExtensionName) { | |
96 *failure_message = "extension name doesn't match"; | |
97 return false; | |
98 } | |
99 for (const auto& p : extension.parameters()) { | |
100 if (p.name() == kServerNoContextTakeOver) { | |
101 if (server_context_take_over_mode() == DO_NOT_TAKE_OVER_CONTEXT) | |
102 return DuplicateError(p.name(), failure_message); | |
103 if (p.HasValue()) | |
104 return InvalidError(p.name(), failure_message); | |
105 SetServerNoContextTakeOver(); | |
106 } else if (p.name() == kClientNoContextTakeOver) { | |
107 if (client_context_take_over_mode() == DO_NOT_TAKE_OVER_CONTEXT) | |
108 return DuplicateError(p.name(), failure_message); | |
109 if (p.HasValue()) | |
110 return InvalidError(p.name(), failure_message); | |
111 SetClientNoContextTakeOver(); | |
112 } else if (p.name() == kServerMaxWindowBits) { | |
113 if (server_max_window_bits_.is_specified) | |
114 return DuplicateError(p.name(), failure_message); | |
115 int bits; | |
116 if (!GetWindowBits(p.value(), &bits) || !IsValidWindowBits(bits)) | |
117 return InvalidError(p.name(), failure_message); | |
118 SetServerMaxWindowBits(bits); | |
119 } else if (p.name() == kClientMaxWindowBits) { | |
120 if (client_max_window_bits_.is_specified) | |
121 return DuplicateError(p.name(), failure_message); | |
122 if (p.value().empty()) { | |
123 SetClientMaxWindowBits(); | |
124 } else { | |
125 int bits; | |
126 if (!GetWindowBits(p.value(), &bits) || !IsValidWindowBits(bits)) | |
127 return InvalidError(p.name(), failure_message); | |
128 SetClientMaxWindowBits(bits); | |
129 } | |
130 } else { | |
131 *failure_message = | |
132 "Received an unexpected permessage-deflate extension parameter"; | |
133 return false; | |
134 } | |
135 } | |
136 return true; | |
137 } | |
138 | |
139 bool WebSocketDeflateParameters::IsCompatibleWith( | |
140 const WebSocketDeflateParameters& response) const { | |
141 const auto& request = *this; | |
142 DCHECK(request.IsValidAsRequest()); | |
143 DCHECK(response.IsValidAsResponse()); | |
144 | |
145 // server_no_context_take_over | |
146 if (request.server_context_take_over_mode() == DO_NOT_TAKE_OVER_CONTEXT && | |
147 response.server_context_take_over_mode() == TAKE_OVER_CONTEXT) { | |
148 return false; | |
149 } | |
150 | |
151 // No compatibility check is needed for client_no_context_take_over | |
152 | |
153 // server_max_window_bits | |
154 if (request.server_max_window_bits_.is_specified) { | |
155 DCHECK(request.server_max_window_bits_.has_value); | |
156 if (!response.server_max_window_bits_.is_specified) | |
157 return false; | |
158 DCHECK(response.server_max_window_bits_.has_value); | |
159 if (request.server_max_window_bits_.bits < | |
160 response.server_max_window_bits_.bits) { | |
161 return false; | |
162 } | |
163 } | |
164 | |
165 // client_max_window_bits | |
166 if (request.client_max_window_bits_.is_specified) { | |
167 if (request.client_max_window_bits_.has_value && | |
168 response.client_max_window_bits_.is_specified) { | |
169 DCHECK(response.client_max_window_bits_.has_value); | |
170 if (request.client_max_window_bits_.bits < | |
171 response.client_max_window_bits_.bits) { | |
172 return false; | |
173 } | |
174 } | |
tyoshino (SeeGerritForStatus)
2015/09/10 09:06:19
L166-174 are unnecessary. The value part of the cl
yhirano
2015/09/10 11:20:13
Done.
| |
175 } else if (response.client_max_window_bits_.is_specified) { | |
176 return false; | |
177 } | |
178 | |
179 return true; | |
180 } | |
181 | |
182 } // namespace net | |
OLD | NEW |