Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: net/websockets/websocket_handshake_handler.cc

Issue 2743003: Add Spdy support in WebSocketHandshake*Handler (Closed)
Patch Set: fix Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "base/md5.h" 7 #include "base/md5.h"
8 #include "base/string_piece.h" 8 #include "base/string_piece.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "googleurl/src/gurl.h" 10 #include "googleurl/src/gurl.h"
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 87 }
88 } 88 }
89 if (!should_remove) { 89 if (!should_remove) {
90 filtered_headers.append(line_begin, line_end); 90 filtered_headers.append(line_begin, line_end);
91 filtered_headers.append("\r\n"); 91 filtered_headers.append("\r\n");
92 } 92 }
93 } 93 }
94 return filtered_headers; 94 return filtered_headers;
95 } 95 }
96 96
97 // Gets a key number for |key_name| in |headers| and appends the number to 97 // Gets a key number from |key| and appends the number to |challenge|.
98 // |challenge|.
99 // The key number (/part_N/) is extracted as step 4.-8. in 98 // The key number (/part_N/) is extracted as step 4.-8. in
100 // 5.2. Sending the server's opening handshake of 99 // 5.2. Sending the server's opening handshake of
101 // http://www.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt 100 // http://www.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt
102 void GetKeyNumber(net::HttpRequestHeaders* headers, const char* key_name, 101 void GetKeyNumber(const std::string& key, std::string* challenge) {
103 std::string* challenge) {
104 std::string key;
105 headers->GetHeader(key_name, &key);
106 headers->RemoveHeader(key_name);
107
108 uint32 key_number = 0; 102 uint32 key_number = 0;
109 uint32 spaces = 0; 103 uint32 spaces = 0;
110 for (size_t i = 0; i < key.size(); ++i) { 104 for (size_t i = 0; i < key.size(); ++i) {
111 if (isdigit(key[i])) 105 if (isdigit(key[i])) {
106 // key_number should not overflow. (it comes from
107 // WebCore/websockets/WebSocketHandshake.cpp).
112 key_number = key_number * 10 + key[i] - '0'; 108 key_number = key_number * 10 + key[i] - '0';
113 else if (key[i] == ' ') 109 } else if (key[i] == ' ') {
114 ++spaces; 110 ++spaces;
111 }
115 } 112 }
116 // spaces should not be zero in valid handshake request. 113 // spaces should not be zero in valid handshake request.
117 if (spaces == 0) 114 if (spaces == 0)
118 return; 115 return;
119 key_number /= spaces; 116 key_number /= spaces;
120 117
121 char part[4]; 118 char part[4];
122 for (int i = 0; i < 4; i++) { 119 for (int i = 0; i < 4; i++) {
123 part[3 - i] = key_number & 0xFF; 120 part[3 - i] = key_number & 0xFF;
124 key_number >>= 8; 121 key_number >>= 8;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 if (method_end != base::StringPiece::npos) 189 if (method_end != base::StringPiece::npos)
193 request_info.method = std::string(status_line_.data(), method_end); 190 request_info.method = std::string(status_line_.data(), method_end);
194 191
195 request_info.extra_headers.Clear(); 192 request_info.extra_headers.Clear();
196 request_info.extra_headers.AddHeadersFromString(headers_); 193 request_info.extra_headers.AddHeadersFromString(headers_);
197 194
198 request_info.extra_headers.RemoveHeader("Upgrade"); 195 request_info.extra_headers.RemoveHeader("Upgrade");
199 request_info.extra_headers.RemoveHeader("Connection"); 196 request_info.extra_headers.RemoveHeader("Connection");
200 197
201 challenge->clear(); 198 challenge->clear();
202 GetKeyNumber(&request_info.extra_headers, "Sec-WebSocket-Key1", challenge); 199 std::string key;
203 GetKeyNumber(&request_info.extra_headers, "Sec-WebSocket-Key2", challenge); 200 request_info.extra_headers.GetHeader("Sec-WebSocket-Key1", &key);
201 request_info.extra_headers.RemoveHeader("Sec-WebSocket-Key1");
202 GetKeyNumber(key, challenge);
203
204 request_info.extra_headers.GetHeader("Sec-WebSocket-Key2", &key);
205 request_info.extra_headers.RemoveHeader("Sec-WebSocket-Key2");
206 GetKeyNumber(key, challenge);
207
204 challenge->append(key3_); 208 challenge->append(key3_);
205 209
206 return request_info; 210 return request_info;
207 } 211 }
208 212
213 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
214 const GURL& url, spdy::SpdyHeaderBlock* headers, std::string* challenge) {
215 // We don't set "method" and "version". These are fixed value in WebSocket
216 // protocol.
217 (*headers)["url"] = url.spec();
218
219 std::string key1;
220 std::string key2;
221 HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n");
222 while (iter.GetNext()) {
223 if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(),
224 "connection")) {
225 // Ignore "Connection" header.
226 continue;
227 } else if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(),
228 "upgrade")) {
229 // Ignore "Upgrade" header.
230 continue;
231 } else if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(),
232 "sec-websocket-key1")) {
233 // Use only for generating challenge.
234 key1 = iter.values();
235 continue;
236 } else if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(),
237 "sec-websocket-key2")) {
238 // Use only for generating challenge.
239 key2 = iter.values();
240 continue;
241 }
242 // Others should be sent out to |headers|.
243 std::string name = StringToLowerASCII(iter.name());
244 spdy::SpdyHeaderBlock::iterator found = headers->find(name);
245 if (found == headers->end()) {
246 (*headers)[name] = iter.values();
247 } else {
248 // For now, websocket doesn't use multiple headers, but follows to http.
249 found->second.append(1, '\0'); // +=() doesn't append 0's
250 found->second.append(iter.values());
251 }
252 }
253
254 challenge->clear();
255 GetKeyNumber(key1, challenge);
256 GetKeyNumber(key2, challenge);
257 challenge->append(key3_);
258
259 return true;
260 }
261
209 std::string WebSocketHandshakeRequestHandler::GetRawRequest() { 262 std::string WebSocketHandshakeRequestHandler::GetRawRequest() {
210 DCHECK(status_line_.size() > 0); 263 DCHECK(status_line_.size() > 0);
211 DCHECK(headers_.size() > 0); 264 DCHECK(headers_.size() > 0);
212 DCHECK_EQ(kRequestKey3Size, key3_.size()); 265 DCHECK_EQ(kRequestKey3Size, key3_.size());
213 std::string raw_request = status_line_ + headers_ + "\r\n" + key3_; 266 std::string raw_request = status_line_ + headers_ + "\r\n" + key3_;
214 raw_length_ = raw_request.size(); 267 raw_length_ = raw_request.size();
215 return raw_request; 268 return raw_request;
216 } 269 }
217 270
218 size_t WebSocketHandshakeRequestHandler::raw_length() const { 271 size_t WebSocketHandshakeRequestHandler::raw_length() const {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 MD5Digest digest; 333 MD5Digest digest;
281 MD5Sum(challenge.data(), challenge.size(), &digest); 334 MD5Sum(challenge.data(), challenge.size(), &digest);
282 335
283 const char* digest_data = reinterpret_cast<char*>(digest.a); 336 const char* digest_data = reinterpret_cast<char*>(digest.a);
284 response_message.append(digest_data, sizeof(digest.a)); 337 response_message.append(digest_data, sizeof(digest.a));
285 338
286 return ParseRawResponse(response_message.data(), 339 return ParseRawResponse(response_message.data(),
287 response_message.size()) == response_message.size(); 340 response_message.size()) == response_message.size();
288 } 341 }
289 342
343 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
344 const spdy::SpdyHeaderBlock& headers,
345 const std::string& challenge) {
346 std::string response_message;
347 response_message = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n";
348 response_message += "Upgrade: WebSocket\r\n";
349 response_message += "Connection: Upgrade\r\n";
350 for (spdy::SpdyHeaderBlock::const_iterator iter = headers.begin();
351 iter != headers.end();
352 ++iter) {
353 // For each value, if the server sends a NUL-separated list of values,
354 // we separate that back out into individual headers for each value
355 // in the list.
356 const std::string& value = iter->second;
357 size_t start = 0;
358 size_t end = 0;
359 do {
360 end = value.find('\0', start);
361 std::string tval;
362 if (end != std::string::npos)
363 tval = value.substr(start, (end - start));
364 else
365 tval = value.substr(start);
366 response_message += iter->first + ": " + tval + "\r\n";
367 start = end + 1;
368 } while (end != std::string::npos);
369 }
370 response_message += "\r\n";
371
372 MD5Digest digest;
373 MD5Sum(challenge.data(), challenge.size(), &digest);
374
375 const char* digest_data = reinterpret_cast<char*>(digest.a);
376 response_message.append(digest_data, sizeof(digest.a));
377
378 return ParseRawResponse(response_message.data(),
379 response_message.size()) == response_message.size();
380 }
381
290 void WebSocketHandshakeResponseHandler::GetHeaders( 382 void WebSocketHandshakeResponseHandler::GetHeaders(
291 const char* const headers_to_get[], 383 const char* const headers_to_get[],
292 size_t headers_to_get_len, 384 size_t headers_to_get_len,
293 std::vector<std::string>* values) { 385 std::vector<std::string>* values) {
294 DCHECK(HasResponse()); 386 DCHECK(HasResponse());
295 DCHECK(status_line_.size() > 0); 387 DCHECK(status_line_.size() > 0);
296 DCHECK(headers_.size() > 0); 388 DCHECK(headers_.size() > 0);
297 DCHECK_EQ(kResponseKeySize, key_.size()); 389 DCHECK_EQ(kResponseKeySize, key_.size());
298 390
299 FetchHeaders(headers_, headers_to_get, headers_to_get_len, values); 391 FetchHeaders(headers_, headers_to_get, headers_to_get_len, values);
(...skipping 13 matching lines...) Expand all
313 std::string WebSocketHandshakeResponseHandler::GetResponse() { 405 std::string WebSocketHandshakeResponseHandler::GetResponse() {
314 DCHECK(HasResponse()); 406 DCHECK(HasResponse());
315 DCHECK(status_line_.size() > 0); 407 DCHECK(status_line_.size() > 0);
316 DCHECK(headers_.size() > 0); 408 DCHECK(headers_.size() > 0);
317 DCHECK_EQ(kResponseKeySize, key_.size()); 409 DCHECK_EQ(kResponseKeySize, key_.size());
318 410
319 return status_line_ + headers_ + "\r\n" + key_; 411 return status_line_ + headers_ + "\r\n" + key_;
320 } 412 }
321 413
322 } // namespace net 414 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698