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

Side by Side Diff: net/server/http_server.cc

Issue 2314073003: Handle non-HTTP/1.1 requests more gracefully in net::HttpServer. (Closed)
Patch Set: Close the connection on a parsing error Created 4 years, 3 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) 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/server/http_server.h" 5 #include "net/server/http_server.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 return ERR_CONNECTION_CLOSED; 223 return ERR_CONNECTION_CLOSED;
224 } 224 }
225 delegate_->OnWebSocketMessage(connection->id(), message); 225 delegate_->OnWebSocketMessage(connection->id(), message);
226 if (HasClosedConnection(connection)) 226 if (HasClosedConnection(connection))
227 return ERR_CONNECTION_CLOSED; 227 return ERR_CONNECTION_CLOSED;
228 continue; 228 continue;
229 } 229 }
230 230
231 HttpServerRequestInfo request; 231 HttpServerRequestInfo request;
232 size_t pos = 0; 232 size_t pos = 0;
233 if (!ParseHeaders(read_buf->StartOfBuffer(), read_buf->GetSize(), 233 if (!ParseHeaders(connection->id(), read_buf->StartOfBuffer(),
234 &request, &pos)) { 234 read_buf->GetSize(), &request, &pos)) {
235 // Check if a parsing error has caused the connection to close.
236 if (HasClosedConnection(connection))
237 return ERR_CONNECTION_CLOSED;
235 break; 238 break;
236 } 239 }
237 240
238 // Sets peer address if exists. 241 // Sets peer address if exists.
239 connection->socket()->GetPeerAddress(&request.peer); 242 connection->socket()->GetPeerAddress(&request.peer);
240 243
241 if (request.HasHeaderValue("connection", "upgrade")) { 244 if (request.HasHeaderValue("connection", "upgrade")) {
242 connection->SetWebSocket( 245 connection->SetWebSocket(
243 base::WrapUnique(new WebSocket(this, connection))); 246 base::WrapUnique(new WebSocket(this, connection)));
244 read_buf->DidConsume(pos); 247 read_buf->DidConsume(pos);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 case '\n': 374 case '\n':
372 return INPUT_LF; 375 return INPUT_LF;
373 case ':': 376 case ':':
374 return INPUT_COLON; 377 return INPUT_COLON;
375 } 378 }
376 return INPUT_DEFAULT; 379 return INPUT_DEFAULT;
377 } 380 }
378 381
379 } // namespace 382 } // namespace
380 383
381 bool HttpServer::ParseHeaders(const char* data, 384 bool HttpServer::ParseHeaders(int connection_id,
385 const char* data,
382 size_t data_len, 386 size_t data_len,
383 HttpServerRequestInfo* info, 387 HttpServerRequestInfo* info,
384 size_t* ppos) { 388 size_t* ppos) {
385 size_t& pos = *ppos; 389 size_t& pos = *ppos;
386 int state = ST_METHOD; 390 int state = ST_METHOD;
387 std::string buffer; 391 std::string buffer;
388 std::string header_name; 392 std::string header_name;
389 std::string header_value; 393 std::string header_value;
390 while (pos < data_len) { 394 while (pos < data_len) {
391 char ch = data[pos++]; 395 char ch = data[pos++];
392 int input = charToInput(ch); 396 int input = charToInput(ch);
393 int next_state = parser_state[state][input]; 397 int next_state = parser_state[state][input];
394 398
395 bool transition = (next_state != state); 399 bool transition = (next_state != state);
396 HttpServerRequestInfo::HeadersMap::iterator it; 400 HttpServerRequestInfo::HeadersMap::iterator it;
397 if (transition) { 401 if (transition) {
398 // Do any actions based on state transitions. 402 // Do any actions based on state transitions.
399 switch (state) { 403 switch (state) {
400 case ST_METHOD: 404 case ST_METHOD:
401 info->method = buffer; 405 info->method = buffer;
402 buffer.clear(); 406 buffer.clear();
403 break; 407 break;
404 case ST_URL: 408 case ST_URL:
405 info->path = buffer; 409 info->path = buffer;
406 buffer.clear(); 410 buffer.clear();
407 break; 411 break;
408 case ST_PROTO: 412 case ST_PROTO:
409 // TODO(mbelshe): Deal better with parsing protocol. 413 if (buffer != "HTTP/1.1") {
410 DCHECK(buffer == "HTTP/1.1"); 414 LOG(ERROR) << "Ignoring request with protocol: " << buffer;
415 next_state = ST_ERR;
416 }
411 buffer.clear(); 417 buffer.clear();
412 break; 418 break;
413 case ST_NAME: 419 case ST_NAME:
414 header_name = base::ToLowerASCII(buffer); 420 header_name = base::ToLowerASCII(buffer);
415 buffer.clear(); 421 buffer.clear();
416 break; 422 break;
417 case ST_VALUE: 423 case ST_VALUE:
418 base::TrimWhitespaceASCII(buffer, base::TRIM_LEADING, &header_value); 424 base::TrimWhitespaceASCII(buffer, base::TRIM_LEADING, &header_value);
419 it = info->headers.find(header_name); 425 it = info->headers.find(header_name);
420 // See the second paragraph ("A sender MUST NOT generate multiple 426 // See the second paragraph ("A sender MUST NOT generate multiple
(...skipping 17 matching lines...) Expand all
438 case ST_URL: 444 case ST_URL:
439 case ST_PROTO: 445 case ST_PROTO:
440 case ST_VALUE: 446 case ST_VALUE:
441 case ST_NAME: 447 case ST_NAME:
442 buffer.append(&ch, 1); 448 buffer.append(&ch, 1);
443 break; 449 break;
444 case ST_DONE: 450 case ST_DONE:
445 DCHECK(input == INPUT_LF); 451 DCHECK(input == INPUT_LF);
446 return true; 452 return true;
447 case ST_ERR: 453 case ST_ERR:
454 Close(connection_id);
448 return false; 455 return false;
449 } 456 }
450 } 457 }
451 } 458 }
452 // No more characters, but we haven't finished parsing yet. 459 // No more characters, but we haven't finished parsing yet.
453 return false; 460 return false;
454 } 461 }
455 462
456 HttpConnection* HttpServer::FindConnection(int connection_id) { 463 HttpConnection* HttpServer::FindConnection(int connection_id) {
457 IdToConnectionMap::iterator it = id_to_connection_.find(connection_id); 464 IdToConnectionMap::iterator it = id_to_connection_.find(connection_id);
458 if (it == id_to_connection_.end()) 465 if (it == id_to_connection_.end())
459 return NULL; 466 return NULL;
460 return it->second; 467 return it->second;
461 } 468 }
462 469
463 // This is called after any delegate callbacks are called to check if Close() 470 // This is called after any delegate callbacks are called to check if Close()
464 // has been called during callback processing. Using the pointer of connection, 471 // has been called during callback processing. Using the pointer of connection,
465 // |connection| is safe here because Close() deletes the connection in next run 472 // |connection| is safe here because Close() deletes the connection in next run
466 // loop. 473 // loop.
467 bool HttpServer::HasClosedConnection(HttpConnection* connection) { 474 bool HttpServer::HasClosedConnection(HttpConnection* connection) {
468 return FindConnection(connection->id()) != connection; 475 return FindConnection(connection->id()) != connection;
469 } 476 }
470 477
471 } // namespace net 478 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698