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_connection.h" | 5 #include "net/quic/quic_connection.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 least_packet_awaited_by_peer_(1), | 92 least_packet_awaited_by_peer_(1), |
93 peer_least_packet_awaiting_ack_(0), | 93 peer_least_packet_awaiting_ack_(0), |
94 handling_retransmission_timeout_(false), | 94 handling_retransmission_timeout_(false), |
95 write_blocked_(false), | 95 write_blocked_(false), |
96 debug_visitor_(NULL), | 96 debug_visitor_(NULL), |
97 packet_creator_(guid_, &framer_, random_generator_, is_server), | 97 packet_creator_(guid_, &framer_, random_generator_, is_server), |
98 packet_generator_(this, &packet_creator_), | 98 packet_generator_(this, &packet_creator_), |
99 timeout_(QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)), | 99 timeout_(QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)), |
100 time_of_last_received_packet_(clock_->ApproximateNow()), | 100 time_of_last_received_packet_(clock_->ApproximateNow()), |
101 time_of_last_sent_packet_(clock_->ApproximateNow()), | 101 time_of_last_sent_packet_(clock_->ApproximateNow()), |
| 102 time_largest_observed_(QuicTime::Zero()), |
102 congestion_manager_(clock_, kTCP), | 103 congestion_manager_(clock_, kTCP), |
103 version_negotiation_state_(START_NEGOTIATION), | 104 version_negotiation_state_(START_NEGOTIATION), |
104 quic_version_(kQuicVersion1), | 105 quic_version_(kQuicVersion1), |
105 is_server_(is_server), | 106 is_server_(is_server), |
106 connected_(true), | 107 connected_(true), |
107 received_truncated_ack_(false), | 108 received_truncated_ack_(false), |
108 send_ack_in_response_to_packet_(false) { | 109 send_ack_in_response_to_packet_(false) { |
109 helper_->SetConnection(this); | 110 helper_->SetConnection(this); |
110 // TODO(satyamshekhar): Have a smaller timeout till version is negotiated and | 111 // TODO(satyamshekhar): Have a smaller timeout till version is negotiated and |
111 // connection is established (CHLO fully processed). | 112 // connection is established (CHLO fully processed). |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 return false; | 144 return false; |
144 } | 145 } |
145 | 146 |
146 // Right now we only support kQuicVersion1 so it's okay not to | 147 // Right now we only support kQuicVersion1 so it's okay not to |
147 // update the framer and quic_version_. When start supporting more | 148 // update the framer and quic_version_. When start supporting more |
148 // versions please update both. | 149 // versions please update both. |
149 return true; | 150 return true; |
150 } | 151 } |
151 | 152 |
152 void QuicConnection::OnError(QuicFramer* framer) { | 153 void QuicConnection::OnError(QuicFramer* framer) { |
| 154 if (!connected_) { |
| 155 return; |
| 156 } |
153 SendConnectionClose(framer->error()); | 157 SendConnectionClose(framer->error()); |
154 } | 158 } |
155 | 159 |
156 void QuicConnection::OnPacket() { | 160 void QuicConnection::OnPacket() { |
157 // TODO(satyamshekhar): Validate packet before updating the time | 161 // TODO(satyamshekhar): Validate packet before updating the time |
158 // since it affects the timeout of the connection. | 162 // since it affects the timeout of the connection. |
159 time_of_last_received_packet_ = clock_->Now(); | 163 time_of_last_received_packet_ = clock_->Now(); |
160 DVLOG(1) << "time of last received packet: " | 164 DVLOG(1) << "time of last received packet: " |
161 << time_of_last_received_packet_.ToDebuggingValue(); | 165 << time_of_last_received_packet_.ToDebuggingValue(); |
162 | 166 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 last_header_ = header; | 326 last_header_ = header; |
323 return true; | 327 return true; |
324 } | 328 } |
325 | 329 |
326 void QuicConnection::OnFecProtectedPayload(StringPiece payload) { | 330 void QuicConnection::OnFecProtectedPayload(StringPiece payload) { |
327 DCHECK_NE(0u, last_header_.fec_group); | 331 DCHECK_NE(0u, last_header_.fec_group); |
328 QuicFecGroup* group = GetFecGroup(); | 332 QuicFecGroup* group = GetFecGroup(); |
329 group->Update(last_header_, payload); | 333 group->Update(last_header_, payload); |
330 } | 334 } |
331 | 335 |
332 void QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { | 336 bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { |
| 337 DCHECK(connected_); |
333 if (debug_visitor_) { | 338 if (debug_visitor_) { |
334 debug_visitor_->OnStreamFrame(frame); | 339 debug_visitor_->OnStreamFrame(frame); |
335 } | 340 } |
336 last_stream_frames_.push_back(frame); | 341 last_stream_frames_.push_back(frame); |
| 342 return true; |
337 } | 343 } |
338 | 344 |
339 void QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) { | 345 bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) { |
| 346 DCHECK(connected_); |
340 if (debug_visitor_) { | 347 if (debug_visitor_) { |
341 debug_visitor_->OnAckFrame(incoming_ack); | 348 debug_visitor_->OnAckFrame(incoming_ack); |
342 } | 349 } |
343 DVLOG(1) << "OnAckFrame: " << incoming_ack; | 350 DVLOG(1) << "OnAckFrame: " << incoming_ack; |
344 | 351 |
345 if (last_header_.packet_sequence_number <= largest_seen_packet_with_ack_) { | 352 if (last_header_.packet_sequence_number <= largest_seen_packet_with_ack_) { |
346 DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; | 353 DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; |
347 return; | 354 return true; |
348 } | 355 } |
349 largest_seen_packet_with_ack_ = last_header_.packet_sequence_number; | 356 largest_seen_packet_with_ack_ = last_header_.packet_sequence_number; |
350 | 357 |
351 if (!ValidateAckFrame(incoming_ack)) { | 358 if (!ValidateAckFrame(incoming_ack)) { |
352 SendConnectionClose(QUIC_INVALID_ACK_DATA); | 359 SendConnectionClose(QUIC_INVALID_ACK_DATA); |
353 return; | 360 return false; |
354 } | 361 } |
355 | 362 |
356 // TODO(satyamshekhar): Not true if missing_packets.size() was actually | 363 // TODO(satyamshekhar): Not true if missing_packets.size() was actually |
357 // kMaxUnackedPackets. This can result in a dead connection if all the | 364 // kMaxUnackedPackets. This can result in a dead connection if all the |
358 // missing packets get lost during retransmission. Now the new packets(or the | 365 // missing packets get lost during retransmission. Now the new packets(or the |
359 // older packets) will not be retransmitted due to RTO | 366 // older packets) will not be retransmitted due to RTO |
360 // since received_truncated_ack_ is true and their sequence_number is > | 367 // since received_truncated_ack_ is true and their sequence_number is > |
361 // peer_largest_observed_packet. Fix either by resetting it in | 368 // peer_largest_observed_packet. Fix either by resetting it in |
362 // MaybeRetransmitPacketForRTO or keeping an explicit flag for ack truncation. | 369 // MaybeRetransmitPacketForRTO or keeping an explicit flag for ack truncation. |
363 received_truncated_ack_ = | 370 received_truncated_ack_ = |
364 incoming_ack.received_info.missing_packets.size() >= | 371 incoming_ack.received_info.missing_packets.size() >= |
365 GetMaxUnackedPackets(last_header_.public_header.version_flag); | 372 GetMaxUnackedPackets(last_header_.public_header.version_flag); |
366 | 373 |
367 UpdatePacketInformationReceivedByPeer(incoming_ack); | 374 UpdatePacketInformationReceivedByPeer(incoming_ack); |
368 UpdatePacketInformationSentByPeer(incoming_ack); | 375 UpdatePacketInformationSentByPeer(incoming_ack); |
369 congestion_manager_.OnIncomingAckFrame(incoming_ack, | 376 congestion_manager_.OnIncomingAckFrame(incoming_ack, |
370 time_of_last_received_packet_); | 377 time_of_last_received_packet_); |
371 | 378 |
372 // Now the we have received an ack, we might be able to send queued packets. | 379 // Now the we have received an ack, we might be able to send queued packets. |
373 if (queued_packets_.empty()) { | 380 if (!queued_packets_.empty()) { |
374 return; | 381 QuicTime::Delta delay = congestion_manager_.TimeUntilSend( |
| 382 time_of_last_received_packet_, NOT_RETRANSMISSION, |
| 383 HAS_RETRANSMITTABLE_DATA); |
| 384 if (delay.IsZero()) { |
| 385 helper_->UnregisterSendAlarmIfRegistered(); |
| 386 if (!write_blocked_) { |
| 387 OnCanWrite(); |
| 388 } |
| 389 } else if (!delay.IsInfinite()) { |
| 390 helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay)); |
| 391 } |
375 } | 392 } |
376 QuicTime::Delta delay = congestion_manager_.TimeUntilSend( | 393 return connected_; |
377 time_of_last_received_packet_, NOT_RETRANSMISSION, | |
378 HAS_RETRANSMITTABLE_DATA); | |
379 if (delay.IsZero()) { | |
380 helper_->UnregisterSendAlarmIfRegistered(); | |
381 if (!write_blocked_) { | |
382 OnCanWrite(); | |
383 } | |
384 } else if (!delay.IsInfinite()) { | |
385 helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay)); | |
386 } | |
387 } | 394 } |
388 | 395 |
389 void QuicConnection::OnCongestionFeedbackFrame( | 396 bool QuicConnection::OnCongestionFeedbackFrame( |
390 const QuicCongestionFeedbackFrame& feedback) { | 397 const QuicCongestionFeedbackFrame& feedback) { |
| 398 DCHECK(connected_); |
391 if (debug_visitor_) { | 399 if (debug_visitor_) { |
392 debug_visitor_->OnCongestionFeedbackFrame(feedback); | 400 debug_visitor_->OnCongestionFeedbackFrame(feedback); |
393 } | 401 } |
394 congestion_manager_.OnIncomingQuicCongestionFeedbackFrame( | 402 congestion_manager_.OnIncomingQuicCongestionFeedbackFrame( |
395 feedback, time_of_last_received_packet_); | 403 feedback, time_of_last_received_packet_); |
| 404 return connected_; |
396 } | 405 } |
397 | 406 |
398 bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) { | 407 bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) { |
399 if (incoming_ack.received_info.largest_observed > | 408 if (incoming_ack.received_info.largest_observed > |
400 packet_creator_.sequence_number()) { | 409 packet_creator_.sequence_number()) { |
401 DLOG(ERROR) << ENDPOINT << "Peer's observed unsent packet:" | 410 DLOG(ERROR) << ENDPOINT << "Peer's observed unsent packet:" |
402 << incoming_ack.received_info.largest_observed << " vs " | 411 << incoming_ack.received_info.largest_observed << " vs " |
403 << packet_creator_.sequence_number(); | 412 << packet_creator_.sequence_number(); |
404 // We got an error for data we have not sent. Error out. | 413 // We got an error for data we have not sent. Error out. |
405 return false; | 414 return false; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 CloseFecGroupsBefore(incoming_ack.sent_info.least_unacked + 1); | 582 CloseFecGroupsBefore(incoming_ack.sent_info.least_unacked + 1); |
574 } | 583 } |
575 | 584 |
576 void QuicConnection::OnFecData(const QuicFecData& fec) { | 585 void QuicConnection::OnFecData(const QuicFecData& fec) { |
577 DCHECK_NE(0u, last_header_.fec_group); | 586 DCHECK_NE(0u, last_header_.fec_group); |
578 QuicFecGroup* group = GetFecGroup(); | 587 QuicFecGroup* group = GetFecGroup(); |
579 group->UpdateFec(last_header_.packet_sequence_number, | 588 group->UpdateFec(last_header_.packet_sequence_number, |
580 last_header_.fec_entropy_flag, fec); | 589 last_header_.fec_entropy_flag, fec); |
581 } | 590 } |
582 | 591 |
583 void QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) { | 592 bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) { |
| 593 DCHECK(connected_); |
584 if (debug_visitor_) { | 594 if (debug_visitor_) { |
585 debug_visitor_->OnRstStreamFrame(frame); | 595 debug_visitor_->OnRstStreamFrame(frame); |
586 } | 596 } |
587 DLOG(INFO) << "Stream reset with error " | 597 DLOG(INFO) << "Stream reset with error " |
588 << QuicUtils::StreamErrorToString(frame.error_code); | 598 << QuicUtils::StreamErrorToString(frame.error_code); |
589 visitor_->OnRstStream(frame); | 599 visitor_->OnRstStream(frame); |
| 600 return connected_; |
590 } | 601 } |
591 | 602 |
592 void QuicConnection::OnConnectionCloseFrame( | 603 bool QuicConnection::OnConnectionCloseFrame( |
593 const QuicConnectionCloseFrame& frame) { | 604 const QuicConnectionCloseFrame& frame) { |
| 605 DCHECK(connected_); |
594 if (debug_visitor_) { | 606 if (debug_visitor_) { |
595 debug_visitor_->OnConnectionCloseFrame(frame); | 607 debug_visitor_->OnConnectionCloseFrame(frame); |
596 } | 608 } |
597 DLOG(INFO) << ENDPOINT << "Connection closed with error " | 609 DLOG(INFO) << ENDPOINT << "Connection closed with error " |
598 << QuicUtils::ErrorToString(frame.error_code); | 610 << QuicUtils::ErrorToString(frame.error_code); |
599 CloseConnection(frame.error_code, true); | 611 CloseConnection(frame.error_code, true); |
| 612 return false; |
600 } | 613 } |
601 | 614 |
602 void QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) { | 615 bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) { |
| 616 DCHECK(connected_); |
603 DLOG(INFO) << ENDPOINT << "Go away received with error " | 617 DLOG(INFO) << ENDPOINT << "Go away received with error " |
604 << QuicUtils::ErrorToString(frame.error_code) | 618 << QuicUtils::ErrorToString(frame.error_code) |
605 << " and reason:" << frame.reason_phrase; | 619 << " and reason:" << frame.reason_phrase; |
606 visitor_->OnGoAway(frame); | 620 visitor_->OnGoAway(frame); |
| 621 return connected_; |
607 } | 622 } |
608 | 623 |
609 void QuicConnection::OnPacketComplete() { | 624 void QuicConnection::OnPacketComplete() { |
610 // TODO(satyamshekhar): Don't do anything if this packet closed the | 625 // TODO(satyamshekhar): Don't do anything if this packet closed the |
611 // connection. | 626 // connection. |
612 if (!last_packet_revived_) { | 627 if (!last_packet_revived_) { |
613 DLOG(INFO) << ENDPOINT << "Got packet " | 628 DLOG(INFO) << ENDPOINT << "Got packet " |
614 << last_header_.packet_sequence_number | 629 << last_header_.packet_sequence_number |
615 << " with " << last_stream_frames_.size() | 630 << " with " << last_stream_frames_.size() |
616 << " stream frames for " << last_header_.public_header.guid; | 631 << " stream frames for " << last_header_.public_header.guid; |
617 congestion_manager_.RecordIncomingPacket( | 632 congestion_manager_.RecordIncomingPacket( |
618 last_size_, last_header_.packet_sequence_number, | 633 last_size_, last_header_.packet_sequence_number, |
619 time_of_last_received_packet_, last_packet_revived_); | 634 time_of_last_received_packet_, last_packet_revived_); |
620 } else { | 635 } else { |
621 DLOG(INFO) << ENDPOINT << "Got revived packet with " | 636 DLOG(INFO) << ENDPOINT << "Got revived packet with " |
622 << last_stream_frames_.size() << " frames."; | 637 << last_stream_frames_.size() << " frames."; |
623 } | 638 } |
624 | 639 |
625 if ((last_stream_frames_.empty() || | 640 if ((last_stream_frames_.empty() || |
626 visitor_->OnPacket(self_address_, peer_address_, | 641 visitor_->OnPacket(self_address_, peer_address_, |
627 last_header_, last_stream_frames_))) { | 642 last_header_, last_stream_frames_))) { |
628 RecordPacketReceived(last_header_); | 643 RecordPacketReceived(last_header_); |
629 } | 644 } |
630 | 645 |
631 MaybeSendAckInResponseToPacket(); | 646 MaybeSendAckInResponseToPacket(); |
632 last_stream_frames_.clear(); | 647 last_stream_frames_.clear(); |
633 } | 648 } |
634 | 649 |
635 QuicAckFrame* QuicConnection::CreateAckFrame() { | 650 QuicAckFrame* QuicConnection::CreateAckFrame() { |
| 651 UpdateOutgoingAck(); |
| 652 if (time_largest_observed_ == QuicTime::Zero()) { |
| 653 // We have not received any new higher sequence numbers since we sent our |
| 654 // last ACK. |
| 655 outgoing_ack_.received_info.delta_time_largest_observed = |
| 656 QuicTime::Delta::Infinite(); |
| 657 } else { |
| 658 outgoing_ack_.received_info.delta_time_largest_observed = |
| 659 clock_->ApproximateNow().Subtract(time_largest_observed_); |
| 660 |
| 661 time_largest_observed_ = QuicTime::Zero(); |
| 662 } |
636 return new QuicAckFrame(outgoing_ack_); | 663 return new QuicAckFrame(outgoing_ack_); |
637 } | 664 } |
638 | 665 |
639 QuicCongestionFeedbackFrame* QuicConnection::CreateFeedbackFrame() { | 666 QuicCongestionFeedbackFrame* QuicConnection::CreateFeedbackFrame() { |
640 return new QuicCongestionFeedbackFrame(outgoing_congestion_feedback_); | 667 return new QuicCongestionFeedbackFrame(outgoing_congestion_feedback_); |
641 } | 668 } |
642 | 669 |
643 void QuicConnection::MaybeSendAckInResponseToPacket() { | 670 void QuicConnection::MaybeSendAckInResponseToPacket() { |
644 if (send_ack_in_response_to_packet_) { | 671 if (send_ack_in_response_to_packet_) { |
645 SendAck(); | 672 SendAck(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 peer_least_packet_awaiting_ack_), | 797 peer_least_packet_awaiting_ack_), |
771 header.packet_sequence_number); | 798 header.packet_sequence_number); |
772 | 799 |
773 if (outgoing_ack_.received_info.largest_observed > | 800 if (outgoing_ack_.received_info.largest_observed > |
774 header.packet_sequence_number) { | 801 header.packet_sequence_number) { |
775 // We've gotten one of the out of order packets - remove it from our | 802 // We've gotten one of the out of order packets - remove it from our |
776 // "missing packets" list. | 803 // "missing packets" list. |
777 DVLOG(1) << "Removing " << sequence_number << " from missing list"; | 804 DVLOG(1) << "Removing " << sequence_number << " from missing list"; |
778 outgoing_ack_.received_info.missing_packets.erase(sequence_number); | 805 outgoing_ack_.received_info.missing_packets.erase(sequence_number); |
779 } | 806 } |
780 outgoing_ack_.received_info.largest_observed = max( | 807 if (header.packet_sequence_number > |
781 outgoing_ack_.received_info.largest_observed, | 808 outgoing_ack_.received_info.largest_observed) { |
782 header.packet_sequence_number); | 809 outgoing_ack_.received_info.largest_observed = |
783 // TODO(pwestin): update received_info with time_of_last_received_packet_. | 810 header.packet_sequence_number; |
| 811 time_largest_observed_ = time_of_last_received_packet_; |
| 812 } |
784 entropy_manager_.RecordReceivedPacketEntropyHash(sequence_number, | 813 entropy_manager_.RecordReceivedPacketEntropyHash(sequence_number, |
785 header.entropy_hash); | 814 header.entropy_hash); |
786 } | 815 } |
787 | 816 |
788 bool QuicConnection::MaybeRetransmitPacketForRTO( | 817 bool QuicConnection::MaybeRetransmitPacketForRTO( |
789 QuicPacketSequenceNumber sequence_number) { | 818 QuicPacketSequenceNumber sequence_number) { |
790 DCHECK_EQ(ContainsKey(unacked_packets_, sequence_number), | 819 DCHECK_EQ(ContainsKey(unacked_packets_, sequence_number), |
791 ContainsKey(retransmission_map_, sequence_number)); | 820 ContainsKey(retransmission_map_, sequence_number)); |
792 | 821 |
793 if (!ContainsKey(unacked_packets_, sequence_number)) { | 822 if (!ContainsKey(unacked_packets_, sequence_number)) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 // TODO(ianswett): If the packet is a retransmit, the current send alarm may | 894 // TODO(ianswett): If the packet is a retransmit, the current send alarm may |
866 // be too long. | 895 // be too long. |
867 if (write_blocked_ || helper_->IsSendAlarmSet()) { | 896 if (write_blocked_ || helper_->IsSendAlarmSet()) { |
868 return false; | 897 return false; |
869 } | 898 } |
870 | 899 |
871 QuicTime now = clock_->Now(); | 900 QuicTime now = clock_->Now(); |
872 QuicTime::Delta delay = congestion_manager_.TimeUntilSend( | 901 QuicTime::Delta delay = congestion_manager_.TimeUntilSend( |
873 now, retransmission, retransmittable); | 902 now, retransmission, retransmittable); |
874 if (delay.IsInfinite()) { | 903 if (delay.IsInfinite()) { |
875 // TODO(pwestin): should be false but trigger other bugs see b/8350327. | 904 return false; |
876 return true; | |
877 } | 905 } |
878 | 906 |
879 // If the scheduler requires a delay, then we can not send this packet now. | 907 // If the scheduler requires a delay, then we can not send this packet now. |
880 if (!delay.IsZero()) { | 908 if (!delay.IsZero()) { |
881 helper_->SetSendAlarm(now.Add(delay)); | 909 helper_->SetSendAlarm(now.Add(delay)); |
882 return false; | 910 return false; |
883 } | 911 } |
884 return true; | 912 return true; |
885 } | 913 } |
886 | 914 |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1244 << " delta:" << delta.ToMicroseconds(); | 1272 << " delta:" << delta.ToMicroseconds(); |
1245 if (delta >= timeout_) { | 1273 if (delta >= timeout_) { |
1246 SendConnectionClose(QUIC_CONNECTION_TIMED_OUT); | 1274 SendConnectionClose(QUIC_CONNECTION_TIMED_OUT); |
1247 return true; | 1275 return true; |
1248 } | 1276 } |
1249 helper_->SetTimeoutAlarm(timeout_.Subtract(delta)); | 1277 helper_->SetTimeoutAlarm(timeout_.Subtract(delta)); |
1250 return false; | 1278 return false; |
1251 } | 1279 } |
1252 | 1280 |
1253 } // namespace net | 1281 } // namespace net |
OLD | NEW |