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/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/linked_ptr.h" | |
14 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
15 #include "base/metrics/field_trial.h" | 14 #include "base/metrics/field_trial.h" |
16 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
17 #include "base/metrics/stats_counters.h" | 16 #include "base/metrics/stats_counters.h" |
18 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
19 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
20 #include "base/string_util.h" | 19 #include "base/string_util.h" |
21 #include "base/stringprintf.h" | 20 #include "base/stringprintf.h" |
22 #include "base/time.h" | 21 #include "base/time.h" |
23 #include "base/utf_string_conversions.h" | 22 #include "base/utf_string_conversions.h" |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 int SpdySession::GetProtocolVersion() const { | 528 int SpdySession::GetProtocolVersion() const { |
530 DCHECK(buffered_spdy_framer_.get()); | 529 DCHECK(buffered_spdy_framer_.get()); |
531 return buffered_spdy_framer_->protocol_version(); | 530 return buffered_spdy_framer_->protocol_version(); |
532 } | 531 } |
533 | 532 |
534 int SpdySession::WriteSynStream( | 533 int SpdySession::WriteSynStream( |
535 SpdyStreamId stream_id, | 534 SpdyStreamId stream_id, |
536 RequestPriority priority, | 535 RequestPriority priority, |
537 uint8 credential_slot, | 536 uint8 credential_slot, |
538 SpdyControlFlags flags, | 537 SpdyControlFlags flags, |
539 const linked_ptr<SpdyHeaderBlock>& headers) { | 538 const SpdyHeaderBlock& headers) { |
540 // Find our stream | 539 // Find our stream |
541 if (!IsStreamActive(stream_id)) | 540 if (!IsStreamActive(stream_id)) |
542 return ERR_INVALID_SPDY_STREAM; | 541 return ERR_INVALID_SPDY_STREAM; |
543 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | 542 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; |
544 CHECK_EQ(stream->stream_id(), stream_id); | 543 CHECK_EQ(stream->stream_id(), stream_id); |
545 | 544 |
546 SendPrefacePingIfNoneInFlight(); | 545 SendPrefacePingIfNoneInFlight(); |
547 | 546 |
548 DCHECK(buffered_spdy_framer_.get()); | 547 DCHECK(buffered_spdy_framer_.get()); |
549 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | 548 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
550 buffered_spdy_framer_->CreateSynStream( | 549 buffered_spdy_framer_->CreateSynStream( |
551 stream_id, 0, | 550 stream_id, 0, |
552 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), | 551 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), |
553 credential_slot, flags, false, headers.get())); | 552 credential_slot, flags, false, &headers)); |
554 // We enqueue all SYN_STREAM frames at the same priority to ensure | 553 // We enqueue all SYN_STREAM frames at the same priority to ensure |
555 // that we do not send them out-of-order. | 554 // that we do not send them out-of-order. |
556 // http://crbug.com/111708 | 555 // http://crbug.com/111708 |
557 QueueFrame(syn_frame.get(), HIGHEST, stream); | 556 QueueFrame(syn_frame.get(), HIGHEST, stream); |
558 | 557 |
559 base::StatsCounter spdy_requests("spdy.requests"); | 558 base::StatsCounter spdy_requests("spdy.requests"); |
560 spdy_requests.Increment(); | 559 spdy_requests.Increment(); |
561 streams_initiated_count_++; | 560 streams_initiated_count_++; |
562 | 561 |
563 if (net_log().IsLoggingAllEvents()) { | 562 if (net_log().IsLoggingAllEvents()) { |
564 net_log().AddEvent( | 563 net_log().AddEvent( |
565 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, | 564 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |
566 base::Bind(&NetLogSpdySynCallback, headers.get(), | 565 base::Bind(&NetLogSpdySynCallback, &headers, |
567 (flags & CONTROL_FLAG_FIN) != 0, | 566 (flags & CONTROL_FLAG_FIN) != 0, |
568 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, | 567 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, |
569 stream_id, 0)); | 568 stream_id, 0)); |
570 } | 569 } |
571 | 570 |
572 return ERR_IO_PENDING; | 571 return ERR_IO_PENDING; |
573 } | 572 } |
574 | 573 |
575 int SpdySession::WriteCredentialFrame(const std::string& origin, | 574 int SpdySession::WriteCredentialFrame(const std::string& origin, |
576 SSLClientCertType type, | 575 SSLClientCertType type, |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1267 } | 1266 } |
1268 return true; | 1267 return true; |
1269 } | 1268 } |
1270 | 1269 |
1271 void SpdySession::OnSynStream(SpdyStreamId stream_id, | 1270 void SpdySession::OnSynStream(SpdyStreamId stream_id, |
1272 SpdyStreamId associated_stream_id, | 1271 SpdyStreamId associated_stream_id, |
1273 SpdyPriority priority, | 1272 SpdyPriority priority, |
1274 uint8 credential_slot, | 1273 uint8 credential_slot, |
1275 bool fin, | 1274 bool fin, |
1276 bool unidirectional, | 1275 bool unidirectional, |
1277 const linked_ptr<SpdyHeaderBlock>& headers) { | 1276 const SpdyHeaderBlock& headers) { |
1278 if (net_log_.IsLoggingAllEvents()) { | 1277 if (net_log_.IsLoggingAllEvents()) { |
1279 net_log_.AddEvent( | 1278 net_log_.AddEvent( |
1280 NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, | 1279 NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, |
1281 base::Bind(&NetLogSpdySynCallback, | 1280 base::Bind(&NetLogSpdySynCallback, |
1282 headers.get(), fin, unidirectional, | 1281 &headers, fin, unidirectional, |
1283 stream_id, associated_stream_id)); | 1282 stream_id, associated_stream_id)); |
1284 } | 1283 } |
1285 | 1284 |
1286 // Server-initiated streams should have even sequence numbers. | 1285 // Server-initiated streams should have even sequence numbers. |
1287 if ((stream_id & 0x1) != 0) { | 1286 if ((stream_id & 0x1) != 0) { |
1288 LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id; | 1287 LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id; |
1289 return; | 1288 return; |
1290 } | 1289 } |
1291 | 1290 |
1292 if (IsStreamActive(stream_id)) { | 1291 if (IsStreamActive(stream_id)) { |
1293 LOG(WARNING) << "Received OnSyn for active stream " << stream_id; | 1292 LOG(WARNING) << "Received OnSyn for active stream " << stream_id; |
1294 return; | 1293 return; |
1295 } | 1294 } |
1296 | 1295 |
1297 if (associated_stream_id == 0) { | 1296 if (associated_stream_id == 0) { |
1298 std::string description = base::StringPrintf( | 1297 std::string description = base::StringPrintf( |
1299 "Received invalid OnSyn associated stream id %d for stream %d", | 1298 "Received invalid OnSyn associated stream id %d for stream %d", |
1300 associated_stream_id, stream_id); | 1299 associated_stream_id, stream_id); |
1301 ResetStream(stream_id, INVALID_STREAM, description); | 1300 ResetStream(stream_id, INVALID_STREAM, description); |
1302 return; | 1301 return; |
1303 } | 1302 } |
1304 | 1303 |
1305 streams_pushed_count_++; | 1304 streams_pushed_count_++; |
1306 | 1305 |
1307 // TODO(mbelshe): DCHECK that this is a GET method? | 1306 // TODO(mbelshe): DCHECK that this is a GET method? |
1308 | 1307 |
1309 // Verify that the response had a URL for us. | 1308 // Verify that the response had a URL for us. |
1310 GURL gurl = GetUrlFromHeaderBlock(*headers, GetProtocolVersion(), true); | 1309 GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true); |
1311 if (!gurl.is_valid()) { | 1310 if (!gurl.is_valid()) { |
1312 ResetStream(stream_id, PROTOCOL_ERROR, | 1311 ResetStream(stream_id, PROTOCOL_ERROR, |
1313 "Pushed stream url was invalid: " + gurl.spec()); | 1312 "Pushed stream url was invalid: " + gurl.spec()); |
1314 return; | 1313 return; |
1315 } | 1314 } |
1316 const std::string& url = gurl.spec(); | 1315 const std::string& url = gurl.spec(); |
1317 | 1316 |
1318 // Verify we have a valid stream association. | 1317 // Verify we have a valid stream association. |
1319 if (!IsStreamActive(associated_stream_id)) { | 1318 if (!IsStreamActive(associated_stream_id)) { |
1320 ResetStream(stream_id, INVALID_STREAM, | 1319 ResetStream(stream_id, INVALID_STREAM, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1362 stream->set_path(gurl.PathForRequest()); | 1361 stream->set_path(gurl.PathForRequest()); |
1363 stream->set_send_window_size(initial_send_window_size_); | 1362 stream->set_send_window_size(initial_send_window_size_); |
1364 stream->set_recv_window_size(initial_recv_window_size_); | 1363 stream->set_recv_window_size(initial_recv_window_size_); |
1365 | 1364 |
1366 unclaimed_pushed_streams_[url] = stream; | 1365 unclaimed_pushed_streams_[url] = stream; |
1367 | 1366 |
1368 ActivateStream(stream); | 1367 ActivateStream(stream); |
1369 stream->set_response_received(); | 1368 stream->set_response_received(); |
1370 | 1369 |
1371 // Parse the headers. | 1370 // Parse the headers. |
1372 if (!Respond(*headers, stream)) | 1371 if (!Respond(headers, stream)) |
1373 return; | 1372 return; |
1374 | 1373 |
1375 base::StatsCounter push_requests("spdy.pushed_streams"); | 1374 base::StatsCounter push_requests("spdy.pushed_streams"); |
1376 push_requests.Increment(); | 1375 push_requests.Increment(); |
1377 } | 1376 } |
1378 | 1377 |
1379 void SpdySession::OnSynReply(SpdyStreamId stream_id, | 1378 void SpdySession::OnSynReply(SpdyStreamId stream_id, |
1380 bool fin, | 1379 bool fin, |
1381 const linked_ptr<SpdyHeaderBlock>& headers) { | 1380 const SpdyHeaderBlock& headers) { |
1382 if (net_log().IsLoggingAllEvents()) { | 1381 if (net_log().IsLoggingAllEvents()) { |
1383 net_log().AddEvent( | 1382 net_log().AddEvent( |
1384 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, | 1383 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, |
1385 base::Bind(&NetLogSpdySynCallback, | 1384 base::Bind(&NetLogSpdySynCallback, |
1386 headers.get(), fin, false,// not unidirectional | 1385 &headers, fin, false,// not unidirectional |
1387 stream_id, 0)); | 1386 stream_id, 0)); |
1388 } | 1387 } |
1389 | 1388 |
1390 if (!IsStreamActive(stream_id)) { | 1389 if (!IsStreamActive(stream_id)) { |
1391 // NOTE: it may just be that the stream was cancelled. | 1390 // NOTE: it may just be that the stream was cancelled. |
1392 LOG(WARNING) << "Received SYN_REPLY for invalid stream " << stream_id; | 1391 LOG(WARNING) << "Received SYN_REPLY for invalid stream " << stream_id; |
1393 return; | 1392 return; |
1394 } | 1393 } |
1395 | 1394 |
1396 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 1395 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
1397 CHECK_EQ(stream->stream_id(), stream_id); | 1396 CHECK_EQ(stream->stream_id(), stream_id); |
1398 CHECK(!stream->cancelled()); | 1397 CHECK(!stream->cancelled()); |
1399 | 1398 |
1400 if (stream->response_received()) { | 1399 if (stream->response_received()) { |
1401 stream->LogStreamError(ERR_SYN_REPLY_NOT_RECEIVED, | 1400 stream->LogStreamError(ERR_SYN_REPLY_NOT_RECEIVED, |
1402 "Received duplicate SYN_REPLY for stream."); | 1401 "Received duplicate SYN_REPLY for stream."); |
1403 RecordProtocolErrorHistogram(PROTOCOL_ERROR_SYN_REPLY_NOT_RECEIVED); | 1402 RecordProtocolErrorHistogram(PROTOCOL_ERROR_SYN_REPLY_NOT_RECEIVED); |
1404 CloseStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR); | 1403 CloseStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR); |
1405 return; | 1404 return; |
1406 } | 1405 } |
1407 stream->set_response_received(); | 1406 stream->set_response_received(); |
1408 | 1407 |
1409 Respond(*headers, stream); | 1408 Respond(headers, stream); |
1410 } | 1409 } |
1411 | 1410 |
1412 void SpdySession::OnHeaders(SpdyStreamId stream_id, | 1411 void SpdySession::OnHeaders(SpdyStreamId stream_id, |
1413 bool fin, | 1412 bool fin, |
1414 const linked_ptr<SpdyHeaderBlock>& headers) { | 1413 const SpdyHeaderBlock& headers) { |
1415 if (net_log().IsLoggingAllEvents()) { | 1414 if (net_log().IsLoggingAllEvents()) { |
1416 net_log().AddEvent( | 1415 net_log().AddEvent( |
1417 NetLog::TYPE_SPDY_SESSION_HEADERS, | 1416 NetLog::TYPE_SPDY_SESSION_HEADERS, |
1418 base::Bind(&NetLogSpdySynCallback, | 1417 base::Bind(&NetLogSpdySynCallback, |
1419 headers.get(), fin, /*unidirectional=*/false, | 1418 &headers, fin, /*unidirectional=*/false, |
1420 stream_id, 0)); | 1419 stream_id, 0)); |
1421 } | 1420 } |
1422 | 1421 |
1423 if (!IsStreamActive(stream_id)) { | 1422 if (!IsStreamActive(stream_id)) { |
1424 // NOTE: it may just be that the stream was cancelled. | 1423 // NOTE: it may just be that the stream was cancelled. |
1425 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; | 1424 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; |
1426 return; | 1425 return; |
1427 } | 1426 } |
1428 | 1427 |
1429 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 1428 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
1430 CHECK_EQ(stream->stream_id(), stream_id); | 1429 CHECK_EQ(stream->stream_id(), stream_id); |
1431 CHECK(!stream->cancelled()); | 1430 CHECK(!stream->cancelled()); |
1432 | 1431 |
1433 int rv = stream->OnHeaders(*headers); | 1432 int rv = stream->OnHeaders(headers); |
1434 if (rv < 0) { | 1433 if (rv < 0) { |
1435 DCHECK_NE(rv, ERR_IO_PENDING); | 1434 DCHECK_NE(rv, ERR_IO_PENDING); |
1436 const SpdyStreamId stream_id = stream->stream_id(); | 1435 const SpdyStreamId stream_id = stream->stream_id(); |
1437 DeleteStream(stream_id, rv); | 1436 DeleteStream(stream_id, rv); |
1438 } | 1437 } |
1439 } | 1438 } |
1440 | 1439 |
1441 void SpdySession::OnRstStream(SpdyStreamId stream_id, SpdyStatusCodes status) { | 1440 void SpdySession::OnRstStream(SpdyStreamId stream_id, SpdyStatusCodes status) { |
1442 std::string description; | 1441 std::string description; |
1443 net_log().AddEvent( | 1442 net_log().AddEvent( |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1855 SSLClientSocket* SpdySession::GetSSLClientSocket() const { | 1854 SSLClientSocket* SpdySession::GetSSLClientSocket() const { |
1856 if (!is_secure_) | 1855 if (!is_secure_) |
1857 return NULL; | 1856 return NULL; |
1858 SSLClientSocket* ssl_socket = | 1857 SSLClientSocket* ssl_socket = |
1859 reinterpret_cast<SSLClientSocket*>(connection_->socket()); | 1858 reinterpret_cast<SSLClientSocket*>(connection_->socket()); |
1860 DCHECK(ssl_socket); | 1859 DCHECK(ssl_socket); |
1861 return ssl_socket; | 1860 return ssl_socket; |
1862 } | 1861 } |
1863 | 1862 |
1864 } // namespace net | 1863 } // namespace net |
OLD | NEW |