QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2017 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/third_party/quiche/src/quic/quartc/quartc_factory.h" |
| 6 | |
| 7 | #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" |
| 8 | #include "net/third_party/quiche/src/quic/core/quic_utils.h" |
| 9 | #include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" |
| 10 | #include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" |
| 11 | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| 12 | #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" |
| 13 | #include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h" |
| 14 | #include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h" |
| 15 | #include "net/third_party/quiche/src/quic/quartc/quartc_session.h" |
| 16 | |
| 17 | namespace quic { |
| 18 | |
QUICHE team | b114092 | 2019-03-22 05:24:05 -0700 | [diff] [blame] | 19 | std::unique_ptr<QuartcSession> CreateQuartcClientSession( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 20 | const QuartcSessionConfig& quartc_session_config, |
QUICHE team | b114092 | 2019-03-22 05:24:05 -0700 | [diff] [blame] | 21 | const QuicClock* clock, |
| 22 | QuicAlarmFactory* alarm_factory, |
| 23 | QuicConnectionHelperInterface* connection_helper, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 24 | const ParsedQuicVersionVector& supported_versions, |
| 25 | QuicStringPiece server_crypto_config, |
| 26 | QuartcPacketTransport* packet_transport) { |
| 27 | DCHECK(packet_transport); |
| 28 | |
| 29 | // QuartcSession will eventually own both |writer| and |quic_connection|. |
| 30 | auto writer = QuicMakeUnique<QuartcPacketWriter>( |
| 31 | packet_transport, quartc_session_config.max_packet_size); |
| 32 | |
| 33 | // While the QuicConfig is not directly used by the connection, creating it |
| 34 | // also sets flag values which must be set before creating the connection. |
| 35 | QuicConfig quic_config = CreateQuicConfig(quartc_session_config); |
QUICHE team | b114092 | 2019-03-22 05:24:05 -0700 | [diff] [blame] | 36 | |
| 37 | // |dummy_id| and |dummy_address| are used because Quartc network layer will |
| 38 | // not use these two. |
| 39 | QuicConnectionId dummy_id = QuicUtils::CreateZeroConnectionId( |
| 40 | supported_versions[0].transport_version); |
| 41 | QuicSocketAddress dummy_address(QuicIpAddress::Any4(), /*port=*/0); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 42 | std::unique_ptr<QuicConnection> quic_connection = CreateQuicConnection( |
QUICHE team | b114092 | 2019-03-22 05:24:05 -0700 | [diff] [blame] | 43 | dummy_id, dummy_address, connection_helper, alarm_factory, writer.get(), |
| 44 | Perspective::IS_CLIENT, supported_versions); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 45 | |
| 46 | return QuicMakeUnique<QuartcClientSession>( |
QUICHE team | b114092 | 2019-03-22 05:24:05 -0700 | [diff] [blame] | 47 | std::move(quic_connection), quic_config, supported_versions, clock, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 48 | std::move(writer), |
| 49 | CreateCryptoClientConfig(quartc_session_config.pre_shared_key), |
| 50 | server_crypto_config); |
| 51 | } |
| 52 | |
| 53 | void ConfigureGlobalQuicSettings() { |
| 54 | // Fixes behavior of StopReading() with level-triggered stream sequencers. |
| 55 | SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true); |
| 56 | |
| 57 | // Fix b/110259444. |
| 58 | SetQuicReloadableFlag(quic_fix_spurious_ack_alarm, true); |
| 59 | |
QUICHE team | b740f7a | 2019-03-27 15:24:01 -0700 | [diff] [blame] | 60 | // Enable version 46 to enable SendMessage API and 'quic bit' per draft 17. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 61 | SetQuicReloadableFlag(quic_enable_version_46, true); |
| 62 | |
QUICHE team | b740f7a | 2019-03-27 15:24:01 -0700 | [diff] [blame] | 63 | // Enable version 47 to enable variable-length connection ids. |
| 64 | SetQuicReloadableFlag(quic_enable_version_47, true); |
| 65 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 66 | // Fix for inconsistent reporting of crypto handshake. |
| 67 | SetQuicReloadableFlag(quic_fix_has_pending_crypto_data, true); |
| 68 | |
| 69 | // Ensure that we don't drop data because QUIC streams refuse to buffer it. |
| 70 | // TODO(b/120099046): Replace this with correct handling of WriteMemSlices(). |
wub | 4985598 | 2019-05-01 14:16:26 -0700 | [diff] [blame] | 71 | SetQuicFlag(FLAGS_quic_buffered_data_threshold, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 72 | std::numeric_limits<int>::max()); |
| 73 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 74 | // Enable and request QUIC to include receive timestamps in ACK frames. |
| 75 | SetQuicReloadableFlag(quic_send_timestamps, true); |
| 76 | |
| 77 | // Enable ACK_DECIMATION_WITH_REORDERING. It requires ack_decimation to be |
| 78 | // false. |
| 79 | SetQuicReloadableFlag(quic_enable_ack_decimation, false); |
| 80 | |
| 81 | // Note: flag settings have no effect for Exoblaze builds since |
| 82 | // SetQuicReloadableFlag() gets stubbed out. |
| 83 | SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true); // Enable BBR6,7,8. |
| 84 | SetQuicReloadableFlag(quic_unified_iw_options, true); // Enable IWXX opts. |
| 85 | SetQuicReloadableFlag(quic_bbr_slower_startup3, true); // Enable BBQX opts. |
| 86 | SetQuicReloadableFlag(quic_bbr_flexible_app_limited, true); // Enable BBR9. |
| 87 | } |
| 88 | |
| 89 | QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) { |
| 90 | // TODO(b/124398962): Figure out a better way to initialize QUIC flags. |
| 91 | // Creating a config shouldn't have global side-effects on flags. However, |
| 92 | // this has the advantage of ensuring that flag values stay in sync with the |
| 93 | // options requested by configs, so simply splitting the config and flag |
| 94 | // settings doesn't seem preferable. |
| 95 | ConfigureGlobalQuicSettings(); |
| 96 | |
| 97 | // In exoblaze this may return false. DCHECK to avoid problems caused by |
| 98 | // incorrect flags configuration. |
| 99 | DCHECK(GetQuicReloadableFlag(quic_enable_version_46)) |
| 100 | << "Your build does not support quic reloadable flags and shouldn't " |
| 101 | "place Quartc calls"; |
| 102 | |
| 103 | QuicTagVector copt; |
| 104 | copt.push_back(kNSTP); |
| 105 | |
| 106 | // Enable and request QUIC to include receive timestamps in ACK frames. |
| 107 | copt.push_back(kSTMP); |
| 108 | |
| 109 | // Enable ACK_DECIMATION_WITH_REORDERING. It requires ack_decimation to be |
| 110 | // false. |
| 111 | copt.push_back(kAKD2); |
| 112 | |
| 113 | // Use unlimited decimation in order to reduce number of unbundled ACKs. |
| 114 | copt.push_back(kAKDU); |
| 115 | |
| 116 | // Enable time-based loss detection. |
| 117 | copt.push_back(kTIME); |
| 118 | |
| 119 | copt.push_back(kBBR3); // Stay in low-gain until in-flight < BDP. |
| 120 | copt.push_back(kBBR5); // 40 RTT ack aggregation. |
| 121 | copt.push_back(kBBR6); // Use a 0.75 * BDP cwnd during PROBE_RTT. |
| 122 | copt.push_back(kBBR8); // Skip PROBE_RTT if app-limited. |
| 123 | copt.push_back(kBBR9); // Ignore app-limited if enough data is in flight. |
| 124 | copt.push_back(kBBQ1); // 2.773 pacing gain in STARTUP. |
| 125 | copt.push_back(kBBQ2); // 2.0 CWND gain in STARTUP. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 126 | copt.push_back(k1RTT); // Exit STARTUP after 1 RTT with no gains. |
| 127 | copt.push_back(kIW10); // 10-packet (14600 byte) initial cwnd. |
| 128 | |
| 129 | if (!quartc_session_config.enable_tail_loss_probe) { |
| 130 | copt.push_back(kNTLP); |
| 131 | } |
| 132 | |
| 133 | // TODO(b/112192153): Test and possible enable slower startup when pipe |
| 134 | // filling is ready to use. Slower startup is kBBRS. |
| 135 | |
| 136 | QuicConfig quic_config; |
| 137 | |
| 138 | // Use the limits for the session & stream flow control. The default 16KB |
| 139 | // limit leads to significantly undersending (not reaching BWE on the outgoing |
| 140 | // bitrate) due to blocked frames, and it leads to high latency (and one-way |
| 141 | // delay). Setting it to its limits is not going to cause issues (our streams |
| 142 | // are small generally, and if we were to buffer 24MB it wouldn't be the end |
| 143 | // of the world). We can consider setting different limits in future (e.g. 1MB |
| 144 | // stream, 1.5MB session). It's worth noting that on 1mbps bitrate, limit of |
| 145 | // 24MB can capture approx 4 minutes of the call, and the default increase in |
| 146 | // size of the window (half of the window size) is approximately 2 minutes of |
| 147 | // the call. |
| 148 | quic_config.SetInitialSessionFlowControlWindowToSend( |
| 149 | kSessionReceiveWindowLimit); |
| 150 | quic_config.SetInitialStreamFlowControlWindowToSend( |
| 151 | kStreamReceiveWindowLimit); |
| 152 | quic_config.SetConnectionOptionsToSend(copt); |
| 153 | quic_config.SetClientConnectionOptions(copt); |
| 154 | if (quartc_session_config.max_time_before_crypto_handshake > |
| 155 | QuicTime::Delta::Zero()) { |
| 156 | quic_config.set_max_time_before_crypto_handshake( |
| 157 | quartc_session_config.max_time_before_crypto_handshake); |
| 158 | } |
| 159 | if (quartc_session_config.max_idle_time_before_crypto_handshake > |
| 160 | QuicTime::Delta::Zero()) { |
| 161 | quic_config.set_max_idle_time_before_crypto_handshake( |
| 162 | quartc_session_config.max_idle_time_before_crypto_handshake); |
| 163 | } |
| 164 | if (quartc_session_config.idle_network_timeout > QuicTime::Delta::Zero()) { |
| 165 | quic_config.SetIdleNetworkTimeout( |
| 166 | quartc_session_config.idle_network_timeout, |
| 167 | quartc_session_config.idle_network_timeout); |
| 168 | } |
| 169 | |
| 170 | // The ICE transport provides a unique 5-tuple for each connection. Save |
| 171 | // overhead by omitting the connection id. |
| 172 | quic_config.SetBytesForConnectionIdToSend(0); |
| 173 | |
| 174 | // Allow up to 1000 incoming streams at once. Quartc streams typically contain |
| 175 | // one audio or video frame and close immediately. However, when a video frame |
| 176 | // becomes larger than one packet, there is some delay between the start and |
| 177 | // end of each stream. The default maximum of 100 only leaves about 1 second |
| 178 | // of headroom (Quartc sends ~30 video frames per second) before QUIC starts |
| 179 | // to refuse incoming streams. Back-pressure should clear backlogs of |
| 180 | // incomplete streams, but targets 1 second for recovery. Increasing the |
| 181 | // number of open streams gives sufficient headroom to recover before QUIC |
| 182 | // refuses new streams. |
fkastenholz | d3a1de9 | 2019-05-15 07:00:07 -0700 | [diff] [blame] | 183 | quic_config.SetMaxIncomingBidirectionalStreamsToSend(1000); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 184 | |
| 185 | return quic_config; |
| 186 | } |
| 187 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 188 | std::unique_ptr<QuicConnection> CreateQuicConnection( |
| 189 | QuicConnectionId connection_id, |
| 190 | const QuicSocketAddress& peer_address, |
| 191 | QuicConnectionHelperInterface* connection_helper, |
| 192 | QuicAlarmFactory* alarm_factory, |
| 193 | QuicPacketWriter* packet_writer, |
| 194 | Perspective perspective, |
| 195 | ParsedQuicVersionVector supported_versions) { |
| 196 | auto quic_connection = QuicMakeUnique<QuicConnection>( |
| 197 | connection_id, peer_address, connection_helper, alarm_factory, |
| 198 | packet_writer, |
| 199 | /*owns_writer=*/false, perspective, supported_versions); |
QUICHE team | 9e75db1 | 2019-04-02 17:21:31 -0400 | [diff] [blame] | 200 | quic_connection->SetMaxPacketLength( |
| 201 | packet_writer->GetMaxPacketSize(peer_address)); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 202 | |
| 203 | QuicSentPacketManager& sent_packet_manager = |
| 204 | quic_connection->sent_packet_manager(); |
| 205 | |
| 206 | // Default delayed ack time is 25ms. |
| 207 | // If data packets are sent less often (e.g. because p-time was modified), |
| 208 | // we would force acks to be sent every 25ms regardless, increasing |
| 209 | // overhead. Since generally we guarantee a packet every 20ms, changing |
| 210 | // this value should have miniscule effect on quality on good connections, |
| 211 | // but on poor connections, changing this number significantly reduced the |
| 212 | // number of ack-only packets. |
| 213 | // The p-time can go up to as high as 120ms, and when it does, it's |
| 214 | // when the low overhead is the most important thing. Ideally it should be |
| 215 | // above 120ms, but it cannot be higher than 0.5*RTO, which equals to 100ms. |
| 216 | sent_packet_manager.set_delayed_ack_time( |
| 217 | QuicTime::Delta::FromMilliseconds(100)); |
| 218 | |
| 219 | quic_connection->set_fill_up_link_during_probing(true); |
| 220 | |
| 221 | // We start ack decimation after 15 packets. Typically, we would see |
| 222 | // 1-2 crypto handshake packets, one media packet, and 10 probing packets. |
| 223 | // We want to get acks for the probing packets as soon as possible, |
| 224 | // but we can start using ack decimation right after first probing completes. |
| 225 | // The default was to not start ack decimation for the first 100 packets. |
| 226 | quic_connection->set_min_received_before_ack_decimation(15); |
| 227 | |
| 228 | return quic_connection; |
| 229 | } |
| 230 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 231 | } // namespace quic |