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/quic/quic_session.h" | 5 #include "net/quic/quic_session.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "net/quic/crypto/proof_verifier.h" | 8 #include "net/quic/crypto/proof_verifier.h" |
9 #include "net/quic/quic_connection.h" | 9 #include "net/quic/quic_connection.h" |
10 #include "net/quic/quic_headers_stream.h" | 10 #include "net/quic/quic_headers_stream.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE { | 38 virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE { |
39 session_->OnRstStream(frame); | 39 session_->OnRstStream(frame); |
40 session_->PostProcessAfterData(); | 40 session_->PostProcessAfterData(); |
41 } | 41 } |
42 | 42 |
43 virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE { | 43 virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE { |
44 session_->OnGoAway(frame); | 44 session_->OnGoAway(frame); |
45 session_->PostProcessAfterData(); | 45 session_->PostProcessAfterData(); |
46 } | 46 } |
47 | 47 |
48 virtual void OnWindowUpdateFrames(const vector<QuicWindowUpdateFrame>& frames) | 48 virtual void OnWindowUpdateFrames( |
49 OVERRIDE { | 49 const vector<QuicWindowUpdateFrame>& frames) OVERRIDE { |
50 session_->OnWindowUpdateFrames(frames); | 50 session_->OnWindowUpdateFrames(frames); |
51 session_->PostProcessAfterData(); | 51 session_->PostProcessAfterData(); |
52 } | 52 } |
53 | 53 |
54 virtual void OnBlockedFrames(const vector<QuicBlockedFrame>& frames) | 54 virtual void OnBlockedFrames( |
55 OVERRIDE { | 55 const vector<QuicBlockedFrame>& frames) OVERRIDE { |
56 session_->OnBlockedFrames(frames); | 56 session_->OnBlockedFrames(frames); |
57 session_->PostProcessAfterData(); | 57 session_->PostProcessAfterData(); |
58 } | 58 } |
59 | 59 |
60 virtual void OnCanWrite() OVERRIDE { | 60 virtual void OnCanWrite() OVERRIDE { |
61 session_->OnCanWrite(); | 61 session_->OnCanWrite(); |
62 session_->PostProcessAfterData(); | 62 session_->PostProcessAfterData(); |
63 } | 63 } |
64 | 64 |
65 virtual void OnSuccessfulVersionNegotiation( | 65 virtual void OnSuccessfulVersionNegotiation( |
66 const QuicVersion& version) OVERRIDE { | 66 const QuicVersion& version) OVERRIDE { |
67 session_->OnSuccessfulVersionNegotiation(version); | 67 session_->OnSuccessfulVersionNegotiation(version); |
68 } | 68 } |
69 | 69 |
70 virtual void OnConnectionClosed( | 70 virtual void OnConnectionClosed(QuicErrorCode error, |
71 QuicErrorCode error, bool from_peer) OVERRIDE { | 71 bool from_peer) OVERRIDE { |
72 session_->OnConnectionClosed(error, from_peer); | 72 session_->OnConnectionClosed(error, from_peer); |
73 // The session will go away, so don't bother with cleanup. | 73 // The session will go away, so don't bother with cleanup. |
74 } | 74 } |
75 | 75 |
76 virtual void OnWriteBlocked() OVERRIDE { | 76 virtual void OnWriteBlocked() OVERRIDE { session_->OnWriteBlocked(); } |
77 session_->OnWriteBlocked(); | |
78 } | |
79 | 77 |
80 virtual bool HasPendingWrites() const OVERRIDE { | 78 virtual bool HasPendingWrites() const OVERRIDE { |
81 return session_->HasPendingWrites(); | 79 return session_->HasPendingWrites(); |
82 } | 80 } |
83 | 81 |
84 virtual bool HasPendingHandshake() const OVERRIDE { | 82 virtual bool HasPendingHandshake() const OVERRIDE { |
85 return session_->HasPendingHandshake(); | 83 return session_->HasPendingHandshake(); |
86 } | 84 } |
87 | 85 |
88 virtual bool HasOpenDataStreams() const OVERRIDE { | 86 virtual bool HasOpenDataStreams() const OVERRIDE { |
89 return session_->HasOpenDataStreams(); | 87 return session_->HasOpenDataStreams(); |
90 } | 88 } |
91 | 89 |
92 private: | 90 private: |
93 QuicSession* session_; | 91 QuicSession* session_; |
94 }; | 92 }; |
95 | 93 |
96 QuicSession::QuicSession(QuicConnection* connection, | 94 QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) |
97 const QuicConfig& config) | |
98 : connection_(connection), | 95 : connection_(connection), |
99 visitor_shim_(new VisitorShim(this)), | 96 visitor_shim_(new VisitorShim(this)), |
100 config_(config), | 97 config_(config), |
101 max_open_streams_(config_.max_streams_per_connection()), | 98 max_open_streams_(config_.max_streams_per_connection()), |
102 next_stream_id_(is_server() ? 2 : 3), | 99 next_stream_id_(is_server() ? 2 : 3), |
103 largest_peer_created_stream_id_(0), | 100 largest_peer_created_stream_id_(0), |
104 error_(QUIC_NO_ERROR), | 101 error_(QUIC_NO_ERROR), |
105 goaway_received_(false), | 102 goaway_received_(false), |
106 goaway_sent_(false), | 103 goaway_sent_(false), |
107 has_pending_handshake_(false) { | 104 has_pending_handshake_(false) { |
108 | |
109 connection_->set_visitor(visitor_shim_.get()); | 105 connection_->set_visitor(visitor_shim_.get()); |
110 connection_->SetFromConfig(config_); | 106 connection_->SetFromConfig(config_); |
111 if (connection_->connected()) { | 107 if (connection_->connected()) { |
112 connection_->SetOverallConnectionTimeout( | 108 connection_->SetOverallConnectionTimeout( |
113 config_.max_time_before_crypto_handshake()); | 109 config_.max_time_before_crypto_handshake()); |
114 } | 110 } |
115 headers_stream_.reset(new QuicHeadersStream(this)); | 111 headers_stream_.reset(new QuicHeadersStream(this)); |
116 if (!is_server()) { | 112 if (!is_server()) { |
117 // For version above QUIC v12, the headers stream is stream 3, so the | 113 // For version above QUIC v12, the headers stream is stream 3, so the |
118 // next available local stream ID should be 5. | 114 // next available local stream ID should be 5. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 if (!stream) { | 161 if (!stream) { |
166 // It's quite possible to receive headers after a stream has been reset. | 162 // It's quite possible to receive headers after a stream has been reset. |
167 return; | 163 return; |
168 } | 164 } |
169 stream->OnStreamHeadersComplete(fin, frame_len); | 165 stream->OnStreamHeadersComplete(fin, frame_len); |
170 } | 166 } |
171 | 167 |
172 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { | 168 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { |
173 if (frame.stream_id == kCryptoStreamId) { | 169 if (frame.stream_id == kCryptoStreamId) { |
174 connection()->SendConnectionCloseWithDetails( | 170 connection()->SendConnectionCloseWithDetails( |
175 QUIC_INVALID_STREAM_ID, | 171 QUIC_INVALID_STREAM_ID, "Attempt to reset the crypto stream"); |
176 "Attempt to reset the crypto stream"); | |
177 return; | 172 return; |
178 } | 173 } |
179 if (frame.stream_id == kHeadersStreamId) { | 174 if (frame.stream_id == kHeadersStreamId) { |
180 connection()->SendConnectionCloseWithDetails( | 175 connection()->SendConnectionCloseWithDetails( |
181 QUIC_INVALID_STREAM_ID, | 176 QUIC_INVALID_STREAM_ID, "Attempt to reset the headers stream"); |
182 "Attempt to reset the headers stream"); | |
183 return; | 177 return; |
184 } | 178 } |
185 QuicDataStream* stream = GetDataStream(frame.stream_id); | 179 QuicDataStream* stream = GetDataStream(frame.stream_id); |
186 if (!stream) { | 180 if (!stream) { |
187 return; // Errors are handled by GetStream. | 181 return; // Errors are handled by GetStream. |
188 } | 182 } |
189 | 183 |
190 stream->OnStreamReset(frame); | 184 stream->OnStreamReset(frame); |
191 } | 185 } |
192 | 186 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 | 243 |
250 void QuicSession::OnCanWrite() { | 244 void QuicSession::OnCanWrite() { |
251 // We limit the number of writes to the number of pending streams. If more | 245 // We limit the number of writes to the number of pending streams. If more |
252 // streams become pending, HasPendingWrites will be true, which will cause | 246 // streams become pending, HasPendingWrites will be true, which will cause |
253 // the connection to request resumption before yielding to other connections. | 247 // the connection to request resumption before yielding to other connections. |
254 size_t num_writes = write_blocked_streams_.NumBlockedStreams(); | 248 size_t num_writes = write_blocked_streams_.NumBlockedStreams(); |
255 if (num_writes == 0) { | 249 if (num_writes == 0) { |
256 return; | 250 return; |
257 } | 251 } |
258 | 252 |
259 QuicConnection::ScopedPacketBundler ack_bundler( | 253 QuicConnection::ScopedPacketBundler ack_bundler(connection_.get(), |
260 connection_.get(), QuicConnection::NO_ACK); | 254 QuicConnection::NO_ACK); |
261 for (size_t i = 0; i < num_writes; ++i) { | 255 for (size_t i = 0; i < num_writes; ++i) { |
262 if (!write_blocked_streams_.HasWriteBlockedStreams()) { | 256 if (!write_blocked_streams_.HasWriteBlockedStreams()) { |
263 // Writing one stream removed another?! Something's broken. | 257 // Writing one stream removed another?! Something's broken. |
264 LOG(DFATAL) << "WriteBlockedStream is missing"; | 258 LOG(DFATAL) << "WriteBlockedStream is missing"; |
265 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); | 259 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); |
266 return; | 260 return; |
267 } | 261 } |
268 if (!connection_->CanWriteStreamData()) { | 262 if (!connection_->CanWriteStreamData()) { |
269 return; | 263 return; |
270 } | 264 } |
(...skipping 21 matching lines...) Expand all Loading... |
292 bool QuicSession::HasOpenDataStreams() const { | 286 bool QuicSession::HasOpenDataStreams() const { |
293 return GetNumOpenStreams() > 0; | 287 return GetNumOpenStreams() > 0; |
294 } | 288 } |
295 | 289 |
296 QuicConsumedData QuicSession::WritevData( | 290 QuicConsumedData QuicSession::WritevData( |
297 QuicStreamId id, | 291 QuicStreamId id, |
298 const IOVector& data, | 292 const IOVector& data, |
299 QuicStreamOffset offset, | 293 QuicStreamOffset offset, |
300 bool fin, | 294 bool fin, |
301 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { | 295 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { |
302 return connection_->SendStreamData(id, data, offset, fin, | 296 return connection_->SendStreamData( |
303 ack_notifier_delegate); | 297 id, data, offset, fin, ack_notifier_delegate); |
304 } | 298 } |
305 | 299 |
306 size_t QuicSession::WriteHeaders( | 300 size_t QuicSession::WriteHeaders( |
307 QuicStreamId id, | 301 QuicStreamId id, |
308 const SpdyHeaderBlock& headers, | 302 const SpdyHeaderBlock& headers, |
309 bool fin, | 303 bool fin, |
310 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { | 304 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { |
311 return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate); | 305 return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate); |
312 } | 306 } |
313 | 307 |
(...skipping 12 matching lines...) Expand all Loading... |
326 return; | 320 return; |
327 } | 321 } |
328 goaway_sent_ = true; | 322 goaway_sent_ = true; |
329 connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason); | 323 connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason); |
330 } | 324 } |
331 | 325 |
332 void QuicSession::CloseStream(QuicStreamId stream_id) { | 326 void QuicSession::CloseStream(QuicStreamId stream_id) { |
333 CloseStreamInner(stream_id, false); | 327 CloseStreamInner(stream_id, false); |
334 } | 328 } |
335 | 329 |
336 void QuicSession::CloseStreamInner(QuicStreamId stream_id, | 330 void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) { |
337 bool locally_reset) { | |
338 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; | 331 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; |
339 | 332 |
340 DataStreamMap::iterator it = stream_map_.find(stream_id); | 333 DataStreamMap::iterator it = stream_map_.find(stream_id); |
341 if (it == stream_map_.end()) { | 334 if (it == stream_map_.end()) { |
342 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; | 335 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; |
343 return; | 336 return; |
344 } | 337 } |
345 QuicDataStream* stream = it->second; | 338 QuicDataStream* stream = it->second; |
346 | 339 |
347 // Tell the stream that a RST has been sent. | 340 // Tell the stream that a RST has been sent. |
(...skipping 17 matching lines...) Expand all Loading... |
365 void QuicSession::OnConfigNegotiated() { | 358 void QuicSession::OnConfigNegotiated() { |
366 connection_->SetFromConfig(config_); | 359 connection_->SetFromConfig(config_); |
367 // Tell all streams about the newly received peer receive window. | 360 // Tell all streams about the newly received peer receive window. |
368 if (connection()->version() >= QUIC_VERSION_17 && | 361 if (connection()->version() >= QUIC_VERSION_17 && |
369 config_.HasReceivedInitialFlowControlWindowBytes()) { | 362 config_.HasReceivedInitialFlowControlWindowBytes()) { |
370 // Streams which were created before the SHLO was received (0RTT requests) | 363 // Streams which were created before the SHLO was received (0RTT requests) |
371 // are now informed of the peer's initial flow control window. | 364 // are now informed of the peer's initial flow control window. |
372 uint32 new_flow_control_send_window = | 365 uint32 new_flow_control_send_window = |
373 config_.ReceivedInitialFlowControlWindowBytes(); | 366 config_.ReceivedInitialFlowControlWindowBytes(); |
374 if (new_flow_control_send_window < kDefaultFlowControlSendWindow) { | 367 if (new_flow_control_send_window < kDefaultFlowControlSendWindow) { |
375 LOG(ERROR) | 368 LOG(ERROR) << "Peer sent us an invalid flow control send window: " |
376 << "Peer sent us an invalid flow control send window: " | 369 << new_flow_control_send_window |
377 << new_flow_control_send_window | 370 << ", below default: " << kDefaultFlowControlSendWindow; |
378 << ", below default: " << kDefaultFlowControlSendWindow; | |
379 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR); | 371 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR); |
380 return; | 372 return; |
381 } | 373 } |
382 DataStreamMap::iterator it = stream_map_.begin(); | 374 DataStreamMap::iterator it = stream_map_.begin(); |
383 while (it != stream_map_.end()) { | 375 while (it != stream_map_.end()) { |
384 it->second->flow_controller()->UpdateSendWindowOffset( | 376 it->second->flow_controller()->UpdateSendWindowOffset( |
385 new_flow_control_send_window); | 377 new_flow_control_send_window); |
386 it++; | 378 it++; |
387 } | 379 } |
388 } | 380 } |
389 } | 381 } |
390 | 382 |
391 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { | 383 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { |
392 switch (event) { | 384 switch (event) { |
393 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter | 385 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter |
394 // to QuicSession since it is the glue. | 386 // to QuicSession since it is the glue. |
395 case ENCRYPTION_FIRST_ESTABLISHED: | 387 case ENCRYPTION_FIRST_ESTABLISHED: |
396 break; | 388 break; |
397 | 389 |
398 case ENCRYPTION_REESTABLISHED: | 390 case ENCRYPTION_REESTABLISHED: |
399 // Retransmit originally packets that were sent, since they can't be | 391 // Retransmit originally packets that were sent, since they can't be |
400 // decrypted by the peer. | 392 // decrypted by the peer. |
401 connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY); | 393 connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY); |
402 break; | 394 break; |
403 | 395 |
404 case HANDSHAKE_CONFIRMED: | 396 case HANDSHAKE_CONFIRMED: |
405 LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT | 397 LOG_IF(DFATAL, !config_.negotiated()) |
406 << "Handshake confirmed without parameter negotiation."; | 398 << ENDPOINT << "Handshake confirmed without parameter negotiation."; |
407 // Discard originally encrypted packets, since they can't be decrypted by | 399 // Discard originally encrypted packets, since they can't be decrypted by |
408 // the peer. | 400 // the peer. |
409 connection_->NeuterUnencryptedPackets(); | 401 connection_->NeuterUnencryptedPackets(); |
410 connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite()); | 402 connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite()); |
411 max_open_streams_ = config_.max_streams_per_connection(); | 403 max_open_streams_ = config_.max_streams_per_connection(); |
412 break; | 404 break; |
413 | 405 |
414 default: | 406 default: |
415 LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event; | 407 LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event; |
416 } | 408 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 LOG(ERROR) << "Trying to get stream: " << stream_id | 488 LOG(ERROR) << "Trying to get stream: " << stream_id |
497 << ", largest peer created stream: " | 489 << ", largest peer created stream: " |
498 << largest_peer_created_stream_id_ | 490 << largest_peer_created_stream_id_ |
499 << ", max delta: " << kMaxStreamIdDelta; | 491 << ", max delta: " << kMaxStreamIdDelta; |
500 connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); | 492 connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); |
501 } | 493 } |
502 return NULL; | 494 return NULL; |
503 } | 495 } |
504 if (largest_peer_created_stream_id_ == 0) { | 496 if (largest_peer_created_stream_id_ == 0) { |
505 if (is_server()) { | 497 if (is_server()) { |
506 largest_peer_created_stream_id_= 3; | 498 largest_peer_created_stream_id_ = 3; |
507 } else { | 499 } else { |
508 largest_peer_created_stream_id_= 1; | 500 largest_peer_created_stream_id_ = 1; |
509 } | 501 } |
510 } | 502 } |
511 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; | 503 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; id < stream_id; |
512 id < stream_id; | |
513 id += 2) { | 504 id += 2) { |
514 implicitly_created_streams_.insert(id); | 505 implicitly_created_streams_.insert(id); |
515 } | 506 } |
516 largest_peer_created_stream_id_ = stream_id; | 507 largest_peer_created_stream_id_ = stream_id; |
517 } | 508 } |
518 QuicDataStream* stream = CreateIncomingDataStream(stream_id); | 509 QuicDataStream* stream = CreateIncomingDataStream(stream_id); |
519 if (stream == NULL) { | 510 if (stream == NULL) { |
520 return NULL; | 511 return NULL; |
521 } | 512 } |
522 ActivateStream(stream); | 513 ActivateStream(stream); |
(...skipping 13 matching lines...) Expand all Loading... |
536 return false; | 527 return false; |
537 } | 528 } |
538 if (id % 2 == next_stream_id_ % 2) { | 529 if (id % 2 == next_stream_id_ % 2) { |
539 // Locally created streams are strictly in-order. If the id is in the | 530 // Locally created streams are strictly in-order. If the id is in the |
540 // range of created streams and it's not active, it must have been closed. | 531 // range of created streams and it's not active, it must have been closed. |
541 return id < next_stream_id_; | 532 return id < next_stream_id_; |
542 } | 533 } |
543 // For peer created streams, we also need to consider implicitly created | 534 // For peer created streams, we also need to consider implicitly created |
544 // streams. | 535 // streams. |
545 return id <= largest_peer_created_stream_id_ && | 536 return id <= largest_peer_created_stream_id_ && |
546 implicitly_created_streams_.count(id) == 0; | 537 implicitly_created_streams_.count(id) == 0; |
547 } | 538 } |
548 | 539 |
549 size_t QuicSession::GetNumOpenStreams() const { | 540 size_t QuicSession::GetNumOpenStreams() const { |
550 return stream_map_.size() + implicitly_created_streams_.size(); | 541 return stream_map_.size() + implicitly_created_streams_.size(); |
551 } | 542 } |
552 | 543 |
553 void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { | 544 void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { |
554 #ifndef NDEBUG | 545 #ifndef NDEBUG |
555 ReliableQuicStream* stream = GetStream(id); | 546 ReliableQuicStream* stream = GetStream(id); |
556 if (stream != NULL) { | 547 if (stream != NULL) { |
(...skipping 16 matching lines...) Expand all Loading... |
573 // TODO(jar): Be sure to use the highest priority for the crypto stream, | 564 // TODO(jar): Be sure to use the highest priority for the crypto stream, |
574 // perhaps by adding a "special" priority for it that is higher than | 565 // perhaps by adding a "special" priority for it that is higher than |
575 // kHighestPriority. | 566 // kHighestPriority. |
576 priority = kHighestPriority; | 567 priority = kHighestPriority; |
577 } | 568 } |
578 write_blocked_streams_.PushBack(id, priority); | 569 write_blocked_streams_.PushBack(id, priority); |
579 } | 570 } |
580 | 571 |
581 bool QuicSession::HasDataToWrite() const { | 572 bool QuicSession::HasDataToWrite() const { |
582 return write_blocked_streams_.HasWriteBlockedStreams() || | 573 return write_blocked_streams_.HasWriteBlockedStreams() || |
583 connection_->HasQueuedData(); | 574 connection_->HasQueuedData(); |
584 } | 575 } |
585 | 576 |
586 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { | 577 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { |
587 NOTIMPLEMENTED(); | 578 NOTIMPLEMENTED(); |
588 return false; | 579 return false; |
589 } | 580 } |
590 | 581 |
591 void QuicSession::PostProcessAfterData() { | 582 void QuicSession::PostProcessAfterData() { |
592 STLDeleteElements(&closed_streams_); | 583 STLDeleteElements(&closed_streams_); |
593 closed_streams_.clear(); | 584 closed_streams_.clear(); |
594 } | 585 } |
595 | 586 |
596 } // namespace net | 587 } // namespace net |
OLD | NEW |