Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / tools / quic / quic_server_session.cc
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
3 // found in the LICENSE file.
4
5 #include "net/tools/quic/quic_server_session.h"
6
7 #include "base/logging.h"
8 #include "net/quic/crypto/source_address_token.h"
9 #include "net/quic/quic_connection.h"
10 #include "net/quic/quic_flags.h"
11 #include "net/quic/reliable_quic_stream.h"
12 #include "net/tools/quic/quic_spdy_server_stream.h"
13
14 namespace net {
15 namespace tools {
16
17 QuicServerSession::QuicServerSession(const QuicConfig& config,
18                                      QuicConnection* connection,
19                                      QuicServerSessionVisitor* visitor,
20                                      bool is_secure)
21     : QuicSession(connection, config, is_secure),
22       visitor_(visitor),
23       bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()),
24       last_scup_time_(QuicTime::Zero()),
25       last_scup_sequence_number_(0) {}
26
27 QuicServerSession::~QuicServerSession() {}
28
29 void QuicServerSession::InitializeSession(
30     const QuicCryptoServerConfig& crypto_config) {
31   QuicSession::InitializeSession();
32   crypto_stream_.reset(CreateQuicCryptoServerStream(crypto_config));
33 }
34
35 QuicCryptoServerStream* QuicServerSession::CreateQuicCryptoServerStream(
36     const QuicCryptoServerConfig& crypto_config) {
37   return new QuicCryptoServerStream(crypto_config, this);
38 }
39
40 void QuicServerSession::OnConfigNegotiated() {
41   QuicSession::OnConfigNegotiated();
42   if (!FLAGS_enable_quic_fec ||
43       !config()->HasReceivedConnectionOptions() ||
44       !net::ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
45     return;
46   }
47   // kFHDR config maps to FEC protection always for headers stream.
48   // TODO(jri): Add crypto stream in addition to headers for kHDR.
49   headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
50 }
51
52 void QuicServerSession::OnConnectionClosed(QuicErrorCode error,
53                                            bool from_peer) {
54   QuicSession::OnConnectionClosed(error, from_peer);
55   // In the unlikely event we get a connection close while doing an asynchronous
56   // crypto event, make sure we cancel the callback.
57   if (crypto_stream_.get() != nullptr) {
58     crypto_stream_->CancelOutstandingCallbacks();
59   }
60   visitor_->OnConnectionClosed(connection()->connection_id(), error);
61 }
62
63 void QuicServerSession::OnWriteBlocked() {
64   QuicSession::OnWriteBlocked();
65   visitor_->OnWriteBlocked(connection());
66 }
67
68 void QuicServerSession::OnCongestionWindowChange(QuicTime now) {
69   if (connection()->version() <= QUIC_VERSION_21) {
70     return;
71   }
72
73   // If not enough time has passed since the last time we sent an update to the
74   // client, or not enough packets have been sent, then return early.
75   const QuicSentPacketManager& sent_packet_manager =
76       connection()->sent_packet_manager();
77   int64 srtt_ms =
78       sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds();
79   int64 now_ms = now.Subtract(last_scup_time_).ToMilliseconds();
80   int64 packets_since_last_scup =
81       connection()->sequence_number_of_last_sent_packet() -
82       last_scup_sequence_number_;
83   if (now_ms < (kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms) ||
84       now_ms < kMinIntervalBetweenServerConfigUpdatesMs ||
85       packets_since_last_scup < kMinPacketsBetweenServerConfigUpdates) {
86     return;
87   }
88
89   // If the bandwidth recorder does not have a valid estimate, return early.
90   const QuicSustainedBandwidthRecorder& bandwidth_recorder =
91       sent_packet_manager.SustainedBandwidthRecorder();
92   if (!bandwidth_recorder.HasEstimate()) {
93     return;
94   }
95
96   // The bandwidth recorder has recorded at least one sustained bandwidth
97   // estimate. Check that it's substantially different from the last one that
98   // we sent to the client, and if so, send the new one.
99   QuicBandwidth new_bandwidth_estimate = bandwidth_recorder.BandwidthEstimate();
100
101   int64 bandwidth_delta =
102       std::abs(new_bandwidth_estimate.ToBitsPerSecond() -
103                bandwidth_estimate_sent_to_client_.ToBitsPerSecond());
104
105   // Define "substantial" difference as a 50% increase or decrease from the
106   // last estimate.
107   bool substantial_difference =
108       bandwidth_delta >
109       0.5 * bandwidth_estimate_sent_to_client_.ToBitsPerSecond();
110   if (!substantial_difference) {
111     return;
112   }
113
114   bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
115   DVLOG(1) << "Server: sending new bandwidth estimate (KBytes/s): "
116            << bandwidth_estimate_sent_to_client_.ToKBytesPerSecond();
117
118   // Include max bandwidth in the update.
119   QuicBandwidth max_bandwidth_estimate =
120       bandwidth_recorder.MaxBandwidthEstimate();
121   int32 max_bandwidth_timestamp = bandwidth_recorder.MaxBandwidthTimestamp();
122
123   // Fill the proto before passing it to the crypto stream to send.
124   CachedNetworkParameters cached_network_params;
125   cached_network_params.set_bandwidth_estimate_bytes_per_second(
126       bandwidth_estimate_sent_to_client_.ToBytesPerSecond());
127   cached_network_params.set_max_bandwidth_estimate_bytes_per_second(
128       max_bandwidth_estimate.ToBytesPerSecond());
129   cached_network_params.set_max_bandwidth_timestamp_seconds(
130       max_bandwidth_timestamp);
131   cached_network_params.set_min_rtt_ms(
132       sent_packet_manager.GetRttStats()->min_rtt().ToMilliseconds());
133   cached_network_params.set_previous_connection_state(
134       bandwidth_recorder.EstimateRecordedDuringSlowStart()
135           ? CachedNetworkParameters::SLOW_START
136           : CachedNetworkParameters::CONGESTION_AVOIDANCE);
137   cached_network_params.set_timestamp(
138       connection()->clock()->WallNow().ToUNIXSeconds());
139   if (!serving_region_.empty()) {
140     cached_network_params.set_serving_region(serving_region_);
141   }
142
143   crypto_stream_->SendServerConfigUpdate(&cached_network_params);
144   last_scup_time_ = now;
145   last_scup_sequence_number_ =
146       connection()->sequence_number_of_last_sent_packet();
147 }
148
149 bool QuicServerSession::ShouldCreateIncomingDataStream(QuicStreamId id) {
150   if (id % 2 == 0) {
151     DVLOG(1) << "Invalid incoming even stream_id:" << id;
152     connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
153     return false;
154   }
155   if (GetNumOpenStreams() >= get_max_open_streams()) {
156     DVLOG(1) << "Failed to create a new incoming stream with id:" << id
157              << " Already " << GetNumOpenStreams() << " streams open (max "
158              << get_max_open_streams() << ").";
159     connection()->SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS);
160     return false;
161   }
162   return true;
163 }
164
165 QuicDataStream* QuicServerSession::CreateIncomingDataStream(
166     QuicStreamId id) {
167   if (!ShouldCreateIncomingDataStream(id)) {
168     return nullptr;
169   }
170
171   return new QuicSpdyServerStream(id, this);
172 }
173
174 QuicDataStream* QuicServerSession::CreateOutgoingDataStream() {
175   DLOG(ERROR) << "Server push not yet supported";
176   return nullptr;
177 }
178
179 QuicCryptoServerStream* QuicServerSession::GetCryptoStream() {
180   return crypto_stream_.get();
181 }
182
183 }  // namespace tools
184 }  // namespace net