OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/websockets/websocket_handshake_handler.h" | 5 #include "net/websockets/websocket_handshake_handler.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/sha1.h" | 10 #include "base/sha1.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
13 #include "base/strings/string_tokenizer.h" | 13 #include "base/strings/string_tokenizer.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "net/http/http_request_headers.h" | 16 #include "net/http/http_request_headers.h" |
17 #include "net/http/http_response_headers.h" | 17 #include "net/http/http_response_headers.h" |
18 #include "net/http/http_util.h" | 18 #include "net/http/http_util.h" |
19 #include "net/websockets/websocket_handshake_constants.h" | 19 #include "net/websockets/websocket_handshake_constants.h" |
20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
21 | 21 |
22 namespace net { | 22 namespace net { |
23 namespace { | 23 namespace { |
24 | 24 |
25 const int kVersionHeaderValueForRFC6455 = 13; | 25 const int kVersionHeaderValueForRFC6455 = 13; |
26 | 26 |
27 // Splits |handshake_message| into Status-Line or Request-Line (including CRLF) | 27 // Splits |handshake_message| into Status-Line or Request-Line (including CRLF) |
28 // and headers (excluding 2nd CRLF of double CRLFs at the end of a handshake | 28 // and headers (excluding 2nd CRLF of double CRLFs at the end of a handshake |
29 // response). | 29 // response). |
30 void ParseHandshakeHeader( | 30 void ParseHandshakeHeader(const char* handshake_message, |
31 const char* handshake_message, int len, | 31 int len, |
32 std::string* request_line, | 32 std::string* request_line, |
33 std::string* headers) { | 33 std::string* headers) { |
34 size_t i = base::StringPiece(handshake_message, len).find_first_of("\r\n"); | 34 size_t i = base::StringPiece(handshake_message, len).find_first_of("\r\n"); |
35 if (i == base::StringPiece::npos) { | 35 if (i == base::StringPiece::npos) { |
36 *request_line = std::string(handshake_message, len); | 36 *request_line = std::string(handshake_message, len); |
37 *headers = ""; | 37 *headers = ""; |
38 return; | 38 return; |
39 } | 39 } |
40 // |request_line| includes \r\n. | 40 // |request_line| includes \r\n. |
41 *request_line = std::string(handshake_message, i + 2); | 41 *request_line = std::string(handshake_message, i + 2); |
42 | 42 |
43 int header_len = len - (i + 2) - 2; | 43 int header_len = len - (i + 2) - 2; |
44 if (header_len > 0) { | 44 if (header_len > 0) { |
45 // |handshake_message| includes trailing \r\n\r\n. | 45 // |handshake_message| includes trailing \r\n\r\n. |
46 // |headers| doesn't include 2nd \r\n. | 46 // |headers| doesn't include 2nd \r\n. |
47 *headers = std::string(handshake_message + i + 2, header_len); | 47 *headers = std::string(handshake_message + i + 2, header_len); |
48 } else { | 48 } else { |
49 *headers = ""; | 49 *headers = ""; |
50 } | 50 } |
51 } | 51 } |
52 | 52 |
53 void FetchHeaders(const std::string& headers, | 53 void FetchHeaders(const std::string& headers, |
54 const char* const headers_to_get[], | 54 const char* const headers_to_get[], |
55 size_t headers_to_get_len, | 55 size_t headers_to_get_len, |
56 std::vector<std::string>* values) { | 56 std::vector<std::string>* values) { |
57 net::HttpUtil::HeadersIterator iter(headers.begin(), headers.end(), "\r\n"); | 57 net::HttpUtil::HeadersIterator iter(headers.begin(), headers.end(), "\r\n"); |
58 while (iter.GetNext()) { | 58 while (iter.GetNext()) { |
59 for (size_t i = 0; i < headers_to_get_len; i++) { | 59 for (size_t i = 0; i < headers_to_get_len; i++) { |
60 if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), | 60 if (LowerCaseEqualsASCII( |
61 headers_to_get[i])) { | 61 iter.name_begin(), iter.name_end(), headers_to_get[i])) { |
62 values->push_back(iter.values()); | 62 values->push_back(iter.values()); |
63 } | 63 } |
64 } | 64 } |
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 bool GetHeaderName(std::string::const_iterator line_begin, | 68 bool GetHeaderName(std::string::const_iterator line_begin, |
69 std::string::const_iterator line_end, | 69 std::string::const_iterator line_end, |
70 std::string::const_iterator* name_begin, | 70 std::string::const_iterator* name_begin, |
71 std::string::const_iterator* name_end) { | 71 std::string::const_iterator* name_end) { |
72 std::string::const_iterator colon = std::find(line_begin, line_end, ':'); | 72 std::string::const_iterator colon = std::find(line_begin, line_end, ':'); |
73 if (colon == line_end) { | 73 if (colon == line_end) { |
74 return false; | 74 return false; |
75 } | 75 } |
76 *name_begin = line_begin; | 76 *name_begin = line_begin; |
77 *name_end = colon; | 77 *name_end = colon; |
78 if (*name_begin == *name_end || net::HttpUtil::IsLWS(**name_begin)) | 78 if (*name_begin == *name_end || net::HttpUtil::IsLWS(**name_begin)) |
79 return false; | 79 return false; |
80 net::HttpUtil::TrimLWS(name_begin, name_end); | 80 net::HttpUtil::TrimLWS(name_begin, name_end); |
81 return true; | 81 return true; |
82 } | 82 } |
83 | 83 |
84 // Similar to HttpUtil::StripHeaders, but it preserves malformed headers, that | 84 // Similar to HttpUtil::StripHeaders, but it preserves malformed headers, that |
85 // is, lines that are not formatted as "<name>: <value>\r\n". | 85 // is, lines that are not formatted as "<name>: <value>\r\n". |
86 std::string FilterHeaders( | 86 std::string FilterHeaders(const std::string& headers, |
87 const std::string& headers, | 87 const char* const headers_to_remove[], |
88 const char* const headers_to_remove[], | 88 size_t headers_to_remove_len) { |
89 size_t headers_to_remove_len) { | |
90 std::string filtered_headers; | 89 std::string filtered_headers; |
91 | 90 |
92 base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n"); | 91 base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n"); |
93 while (lines.GetNext()) { | 92 while (lines.GetNext()) { |
94 std::string::const_iterator line_begin = lines.token_begin(); | 93 std::string::const_iterator line_begin = lines.token_begin(); |
95 std::string::const_iterator line_end = lines.token_end(); | 94 std::string::const_iterator line_end = lines.token_end(); |
96 std::string::const_iterator name_begin; | 95 std::string::const_iterator name_begin; |
97 std::string::const_iterator name_end; | 96 std::string::const_iterator name_end; |
98 bool should_remove = false; | 97 bool should_remove = false; |
99 if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) { | 98 if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) { |
100 for (size_t i = 0; i < headers_to_remove_len; ++i) { | 99 for (size_t i = 0; i < headers_to_remove_len; ++i) { |
101 if (LowerCaseEqualsASCII(name_begin, name_end, headers_to_remove[i])) { | 100 if (LowerCaseEqualsASCII(name_begin, name_end, headers_to_remove[i])) { |
102 should_remove = true; | 101 should_remove = true; |
103 break; | 102 break; |
104 } | 103 } |
105 } | 104 } |
106 } | 105 } |
107 if (!should_remove) { | 106 if (!should_remove) { |
108 filtered_headers.append(line_begin, line_end); | 107 filtered_headers.append(line_begin, line_end); |
109 filtered_headers.append("\r\n"); | 108 filtered_headers.append("\r\n"); |
110 } | 109 } |
111 } | 110 } |
112 return filtered_headers; | 111 return filtered_headers; |
113 } | 112 } |
114 | 113 |
115 bool CheckVersionInRequest(const std::string& request_headers) { | 114 bool CheckVersionInRequest(const std::string& request_headers) { |
116 std::vector<std::string> values; | 115 std::vector<std::string> values; |
117 const char* const headers_to_get[1] = { | 116 const char* const headers_to_get[1] = { |
118 websockets::kSecWebSocketVersionLowercase}; | 117 websockets::kSecWebSocketVersionLowercase}; |
119 FetchHeaders(request_headers, headers_to_get, 1, &values); | 118 FetchHeaders(request_headers, headers_to_get, 1, &values); |
120 DCHECK_LE(values.size(), 1U); | 119 DCHECK_LE(values.size(), 1U); |
121 if (values.empty()) | 120 if (values.empty()) |
122 return false; | 121 return false; |
123 | 122 |
124 int version; | 123 int version; |
125 bool conversion_success = base::StringToInt(values[0], &version); | 124 bool conversion_success = base::StringToInt(values[0], &version); |
126 if (!conversion_success) | 125 if (!conversion_success) |
127 return false; | 126 return false; |
128 | 127 |
(...skipping 16 matching lines...) Expand all Loading... |
145 response_message->reserve(response_message->size() + extra_size); | 144 response_message->reserve(response_message->size() + extra_size); |
146 response_message->append(header.begin(), header.end()); | 145 response_message->append(header.begin(), header.end()); |
147 response_message->append(kColonSpace, kColonSpace + kColonSpaceSize); | 146 response_message->append(kColonSpace, kColonSpace + kColonSpaceSize); |
148 response_message->append(value.begin(), value.end()); | 147 response_message->append(value.begin(), value.end()); |
149 response_message->append(kCrNl, kCrNl + kCrNlSize); | 148 response_message->append(kCrNl, kCrNl + kCrNlSize); |
150 } | 149 } |
151 | 150 |
152 } // namespace | 151 } // namespace |
153 | 152 |
154 WebSocketHandshakeRequestHandler::WebSocketHandshakeRequestHandler() | 153 WebSocketHandshakeRequestHandler::WebSocketHandshakeRequestHandler() |
155 : original_length_(0), | 154 : original_length_(0), raw_length_(0) { |
156 raw_length_(0) {} | 155 } |
157 | 156 |
158 bool WebSocketHandshakeRequestHandler::ParseRequest( | 157 bool WebSocketHandshakeRequestHandler::ParseRequest(const char* data, |
159 const char* data, int length) { | 158 int length) { |
160 DCHECK_GT(length, 0); | 159 DCHECK_GT(length, 0); |
161 std::string input(data, length); | 160 std::string input(data, length); |
162 int input_header_length = | 161 int input_header_length = |
163 HttpUtil::LocateEndOfHeaders(input.data(), input.size(), 0); | 162 HttpUtil::LocateEndOfHeaders(input.data(), input.size(), 0); |
164 if (input_header_length <= 0) | 163 if (input_header_length <= 0) |
165 return false; | 164 return false; |
166 | 165 |
167 ParseHandshakeHeader(input.data(), | 166 ParseHandshakeHeader( |
168 input_header_length, | 167 input.data(), input_header_length, &request_line_, &headers_); |
169 &request_line_, | |
170 &headers_); | |
171 | 168 |
172 if (!CheckVersionInRequest(headers_)) { | 169 if (!CheckVersionInRequest(headers_)) { |
173 NOTREACHED(); | 170 NOTREACHED(); |
174 return false; | 171 return false; |
175 } | 172 } |
176 | 173 |
177 original_length_ = input_header_length; | 174 original_length_ = input_header_length; |
178 return true; | 175 return true; |
179 } | 176 } |
180 | 177 |
181 size_t WebSocketHandshakeRequestHandler::original_length() const { | 178 size_t WebSocketHandshakeRequestHandler::original_length() const { |
182 return original_length_; | 179 return original_length_; |
183 } | 180 } |
184 | 181 |
185 void WebSocketHandshakeRequestHandler::AppendHeaderIfMissing( | 182 void WebSocketHandshakeRequestHandler::AppendHeaderIfMissing( |
186 const std::string& name, const std::string& value) { | 183 const std::string& name, |
| 184 const std::string& value) { |
187 DCHECK(!headers_.empty()); | 185 DCHECK(!headers_.empty()); |
188 HttpUtil::AppendHeaderIfMissing(name.c_str(), value, &headers_); | 186 HttpUtil::AppendHeaderIfMissing(name.c_str(), value, &headers_); |
189 } | 187 } |
190 | 188 |
191 void WebSocketHandshakeRequestHandler::RemoveHeaders( | 189 void WebSocketHandshakeRequestHandler::RemoveHeaders( |
192 const char* const headers_to_remove[], | 190 const char* const headers_to_remove[], |
193 size_t headers_to_remove_len) { | 191 size_t headers_to_remove_len) { |
194 DCHECK(!headers_.empty()); | 192 DCHECK(!headers_.empty()); |
195 headers_ = FilterHeaders( | 193 headers_ = FilterHeaders(headers_, headers_to_remove, headers_to_remove_len); |
196 headers_, headers_to_remove, headers_to_remove_len); | |
197 } | 194 } |
198 | 195 |
199 HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo( | 196 HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo( |
200 const GURL& url, std::string* challenge) { | 197 const GURL& url, |
| 198 std::string* challenge) { |
201 HttpRequestInfo request_info; | 199 HttpRequestInfo request_info; |
202 request_info.url = url; | 200 request_info.url = url; |
203 size_t method_end = base::StringPiece(request_line_).find_first_of(" "); | 201 size_t method_end = base::StringPiece(request_line_).find_first_of(" "); |
204 if (method_end != base::StringPiece::npos) | 202 if (method_end != base::StringPiece::npos) |
205 request_info.method = std::string(request_line_.data(), method_end); | 203 request_info.method = std::string(request_line_.data(), method_end); |
206 | 204 |
207 request_info.extra_headers.Clear(); | 205 request_info.extra_headers.Clear(); |
208 request_info.extra_headers.AddHeadersFromString(headers_); | 206 request_info.extra_headers.AddHeadersFromString(headers_); |
209 | 207 |
210 request_info.extra_headers.RemoveHeader(websockets::kUpgrade); | 208 request_info.extra_headers.RemoveHeader(websockets::kUpgrade); |
211 request_info.extra_headers.RemoveHeader(HttpRequestHeaders::kConnection); | 209 request_info.extra_headers.RemoveHeader(HttpRequestHeaders::kConnection); |
212 | 210 |
213 std::string key; | 211 std::string key; |
214 bool header_present = request_info.extra_headers.GetHeader( | 212 bool header_present = |
215 websockets::kSecWebSocketKey, &key); | 213 request_info.extra_headers.GetHeader(websockets::kSecWebSocketKey, &key); |
216 DCHECK(header_present); | 214 DCHECK(header_present); |
217 request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey); | 215 request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey); |
218 *challenge = key; | 216 *challenge = key; |
219 return request_info; | 217 return request_info; |
220 } | 218 } |
221 | 219 |
222 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock( | 220 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock( |
223 const GURL& url, | 221 const GURL& url, |
224 SpdyHeaderBlock* headers, | 222 SpdyHeaderBlock* headers, |
225 std::string* challenge, | 223 std::string* challenge, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 raw_length_ = raw_request.size(); | 297 raw_length_ = raw_request.size(); |
300 return raw_request; | 298 return raw_request; |
301 } | 299 } |
302 | 300 |
303 size_t WebSocketHandshakeRequestHandler::raw_length() const { | 301 size_t WebSocketHandshakeRequestHandler::raw_length() const { |
304 DCHECK_GT(raw_length_, 0); | 302 DCHECK_GT(raw_length_, 0); |
305 return raw_length_; | 303 return raw_length_; |
306 } | 304 } |
307 | 305 |
308 WebSocketHandshakeResponseHandler::WebSocketHandshakeResponseHandler() | 306 WebSocketHandshakeResponseHandler::WebSocketHandshakeResponseHandler() |
309 : original_header_length_(0) {} | 307 : original_header_length_(0) { |
| 308 } |
310 | 309 |
311 WebSocketHandshakeResponseHandler::~WebSocketHandshakeResponseHandler() {} | 310 WebSocketHandshakeResponseHandler::~WebSocketHandshakeResponseHandler() { |
| 311 } |
312 | 312 |
313 size_t WebSocketHandshakeResponseHandler::ParseRawResponse( | 313 size_t WebSocketHandshakeResponseHandler::ParseRawResponse(const char* data, |
314 const char* data, int length) { | 314 int length) { |
315 DCHECK_GT(length, 0); | 315 DCHECK_GT(length, 0); |
316 if (HasResponse()) { | 316 if (HasResponse()) { |
317 DCHECK(!status_line_.empty()); | 317 DCHECK(!status_line_.empty()); |
318 // headers_ might be empty for wrong response from server. | 318 // headers_ might be empty for wrong response from server. |
319 | 319 |
320 return 0; | 320 return 0; |
321 } | 321 } |
322 | 322 |
323 size_t old_original_length = original_.size(); | 323 size_t old_original_length = original_.size(); |
324 | 324 |
325 original_.append(data, length); | 325 original_.append(data, length); |
326 // TODO(ukai): fail fast when response gives wrong status code. | 326 // TODO(ukai): fail fast when response gives wrong status code. |
327 original_header_length_ = HttpUtil::LocateEndOfHeaders( | 327 original_header_length_ = |
328 original_.data(), original_.size(), 0); | 328 HttpUtil::LocateEndOfHeaders(original_.data(), original_.size(), 0); |
329 if (!HasResponse()) | 329 if (!HasResponse()) |
330 return length; | 330 return length; |
331 | 331 |
332 ParseHandshakeHeader(original_.data(), | 332 ParseHandshakeHeader( |
333 original_header_length_, | 333 original_.data(), original_header_length_, &status_line_, &headers_); |
334 &status_line_, | |
335 &headers_); | |
336 int header_size = status_line_.size() + headers_.size(); | 334 int header_size = status_line_.size() + headers_.size(); |
337 DCHECK_GE(original_header_length_, header_size); | 335 DCHECK_GE(original_header_length_, header_size); |
338 header_separator_ = std::string(original_.data() + header_size, | 336 header_separator_ = std::string(original_.data() + header_size, |
339 original_header_length_ - header_size); | 337 original_header_length_ - header_size); |
340 return original_header_length_ - old_original_length; | 338 return original_header_length_ - old_original_length; |
341 } | 339 } |
342 | 340 |
343 bool WebSocketHandshakeResponseHandler::HasResponse() const { | 341 bool WebSocketHandshakeResponseHandler::HasResponse() const { |
344 return original_header_length_ > 0 && | 342 return original_header_length_ > 0 && |
345 static_cast<size_t>(original_header_length_) <= original_.size(); | 343 static_cast<size_t>(original_header_length_) <= original_.size(); |
346 } | 344 } |
347 | 345 |
348 void ComputeSecWebSocketAccept(const std::string& key, | 346 void ComputeSecWebSocketAccept(const std::string& key, std::string* accept) { |
349 std::string* accept) { | |
350 DCHECK(accept); | 347 DCHECK(accept); |
351 | 348 |
352 std::string hash = | 349 std::string hash = base::SHA1HashString(key + websockets::kWebSocketGuid); |
353 base::SHA1HashString(key + websockets::kWebSocketGuid); | |
354 base::Base64Encode(hash, accept); | 350 base::Base64Encode(hash, accept); |
355 } | 351 } |
356 | 352 |
357 bool WebSocketHandshakeResponseHandler::ParseResponseInfo( | 353 bool WebSocketHandshakeResponseHandler::ParseResponseInfo( |
358 const HttpResponseInfo& response_info, | 354 const HttpResponseInfo& response_info, |
359 const std::string& challenge) { | 355 const std::string& challenge) { |
360 if (!response_info.headers.get()) | 356 if (!response_info.headers.get()) |
361 return false; | 357 return false; |
362 | 358 |
363 // TODO(ricea): Eliminate all the reallocations and string copies. | 359 // TODO(ricea): Eliminate all the reallocations and string copies. |
364 std::string response_message; | 360 std::string response_message; |
365 response_message = response_info.headers->GetStatusLine(); | 361 response_message = response_info.headers->GetStatusLine(); |
366 response_message += "\r\n"; | 362 response_message += "\r\n"; |
367 | 363 |
368 AppendHeader(websockets::kUpgrade, | 364 AppendHeader( |
369 websockets::kWebSocketLowercase, | 365 websockets::kUpgrade, websockets::kWebSocketLowercase, &response_message); |
370 &response_message); | |
371 | 366 |
372 AppendHeader( | 367 AppendHeader( |
373 HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message); | 368 HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message); |
374 | 369 |
375 std::string websocket_accept; | 370 std::string websocket_accept; |
376 ComputeSecWebSocketAccept(challenge, &websocket_accept); | 371 ComputeSecWebSocketAccept(challenge, &websocket_accept); |
377 AppendHeader( | 372 AppendHeader( |
378 websockets::kSecWebSocketAccept, websocket_accept, &response_message); | 373 websockets::kSecWebSocketAccept, websocket_accept, &response_message); |
379 | 374 |
380 void* iter = NULL; | 375 void* iter = NULL; |
381 std::string name; | 376 std::string name; |
382 std::string value; | 377 std::string value; |
383 while (response_info.headers->EnumerateHeaderLines(&iter, &name, &value)) { | 378 while (response_info.headers->EnumerateHeaderLines(&iter, &name, &value)) { |
384 AppendHeader(name, value, &response_message); | 379 AppendHeader(name, value, &response_message); |
385 } | 380 } |
386 response_message += "\r\n"; | 381 response_message += "\r\n"; |
387 | 382 |
388 return ParseRawResponse(response_message.data(), | 383 return ParseRawResponse(response_message.data(), response_message.size()) == |
389 response_message.size()) == response_message.size(); | 384 response_message.size(); |
390 } | 385 } |
391 | 386 |
392 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock( | 387 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock( |
393 const SpdyHeaderBlock& headers, | 388 const SpdyHeaderBlock& headers, |
394 const std::string& challenge, | 389 const std::string& challenge, |
395 int spdy_protocol_version) { | 390 int spdy_protocol_version) { |
396 SpdyHeaderBlock::const_iterator status; | 391 SpdyHeaderBlock::const_iterator status; |
397 if (spdy_protocol_version <= 2) | 392 if (spdy_protocol_version <= 2) |
398 status = headers.find("status"); | 393 status = headers.find("status"); |
399 else | 394 else |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 LowerCaseEqualsASCII(iter->first, | 441 LowerCaseEqualsASCII(iter->first, |
447 websockets::kSecWebSocketExtensionsSpdy3))) | 442 websockets::kSecWebSocketExtensionsSpdy3))) |
448 AppendHeader(iter->first.substr(1), tval, &response_message); | 443 AppendHeader(iter->first.substr(1), tval, &response_message); |
449 else | 444 else |
450 AppendHeader(iter->first, tval, &response_message); | 445 AppendHeader(iter->first, tval, &response_message); |
451 start = end + 1; | 446 start = end + 1; |
452 } while (end != std::string::npos); | 447 } while (end != std::string::npos); |
453 } | 448 } |
454 response_message += "\r\n"; | 449 response_message += "\r\n"; |
455 | 450 |
456 return ParseRawResponse(response_message.data(), | 451 return ParseRawResponse(response_message.data(), response_message.size()) == |
457 response_message.size()) == response_message.size(); | 452 response_message.size(); |
458 } | 453 } |
459 | 454 |
460 void WebSocketHandshakeResponseHandler::GetHeaders( | 455 void WebSocketHandshakeResponseHandler::GetHeaders( |
461 const char* const headers_to_get[], | 456 const char* const headers_to_get[], |
462 size_t headers_to_get_len, | 457 size_t headers_to_get_len, |
463 std::vector<std::string>* values) { | 458 std::vector<std::string>* values) { |
464 DCHECK(HasResponse()); | 459 DCHECK(HasResponse()); |
465 DCHECK(!status_line_.empty()); | 460 DCHECK(!status_line_.empty()); |
466 // headers_ might be empty for wrong response from server. | 461 // headers_ might be empty for wrong response from server. |
467 if (headers_.empty()) | 462 if (headers_.empty()) |
(...skipping 21 matching lines...) Expand all Loading... |
489 | 484 |
490 std::string WebSocketHandshakeResponseHandler::GetResponse() { | 485 std::string WebSocketHandshakeResponseHandler::GetResponse() { |
491 DCHECK(HasResponse()); | 486 DCHECK(HasResponse()); |
492 DCHECK(!status_line_.empty()); | 487 DCHECK(!status_line_.empty()); |
493 // headers_ might be empty for wrong response from server. | 488 // headers_ might be empty for wrong response from server. |
494 | 489 |
495 return status_line_ + headers_ + header_separator_; | 490 return status_line_ + headers_ + header_separator_; |
496 } | 491 } |
497 | 492 |
498 } // namespace net | 493 } // namespace net |
OLD | NEW |