gfe-relnote: Remove client-side support for Channel ID from QUIC. Not flag protected. PiperOrigin-RevId: 247261939 Change-Id: Id2d70ab42cb47b76c783a06b7773871886c75c56
diff --git a/quic/core/crypto/channel_id.h b/quic/core/crypto/channel_id.h index 309aaf2..8719394 100644 --- a/quic/core/crypto/channel_id.h +++ b/quic/core/crypto/channel_id.h
@@ -14,54 +14,6 @@ namespace quic { -// ChannelIDKey is an interface that supports signing with and serializing a -// ChannelID key. -class QUIC_EXPORT_PRIVATE ChannelIDKey { - public: - virtual ~ChannelIDKey() {} - - // Sign signs |signed_data| using the ChannelID private key and puts the - // signature into |out_signature|. It returns true on success. - virtual bool Sign(QuicStringPiece signed_data, - std::string* out_signature) const = 0; - - // SerializeKey returns the serialized ChannelID public key. - virtual std::string SerializeKey() const = 0; -}; - -// ChannelIDSourceCallback provides a generic mechanism for a ChannelIDSource -// to call back after an asynchronous GetChannelIDKey operation. -class ChannelIDSourceCallback { - public: - virtual ~ChannelIDSourceCallback() {} - - // Run is called on the original thread to mark the completion of an - // asynchonous GetChannelIDKey operation. If |*channel_id_key| is not nullptr - // then the channel ID lookup is successful. |Run| may take ownership of - // |*channel_id_key| by calling |release| on it. - virtual void Run(std::unique_ptr<ChannelIDKey>* channel_id_key) = 0; -}; - -// ChannelIDSource is an abstract interface by which a QUIC client can obtain -// a ChannelIDKey for a given hostname. -class QUIC_EXPORT_PRIVATE ChannelIDSource { - public: - virtual ~ChannelIDSource() {} - - // GetChannelIDKey looks up the ChannelIDKey for |hostname|. On success it - // returns QUIC_SUCCESS and stores the ChannelIDKey in |*channel_id_key|, - // which the caller takes ownership of. On failure, it returns QUIC_FAILURE. - // - // This function may also return QUIC_PENDING, in which case the - // ChannelIDSource will call back, on the original thread, via |callback| - // when complete. In this case, the ChannelIDSource will take ownership of - // |callback|. - virtual QuicAsyncStatus GetChannelIDKey( - const std::string& hostname, - std::unique_ptr<ChannelIDKey>* channel_id_key, - ChannelIDSourceCallback* callback) = 0; -}; - // ChannelIDVerifier verifies ChannelID signatures. class QUIC_EXPORT_PRIVATE ChannelIDVerifier { public:
diff --git a/quic/core/crypto/channel_id_test.cc b/quic/core/crypto/channel_id_test.cc index 99a84dd..d367382 100644 --- a/quic/core/crypto/channel_id_test.cc +++ b/quic/core/crypto/channel_id_test.cc
@@ -282,40 +282,5 @@ } } -TEST_F(ChannelIDTest, SignAndVerify) { - std::unique_ptr<ChannelIDSource> source( - crypto_test_utils::ChannelIDSourceForTesting()); - - const std::string signed_data = "signed data"; - const std::string hostname = "foo.example.com"; - std::unique_ptr<ChannelIDKey> channel_id_key; - QuicAsyncStatus status = - source->GetChannelIDKey(hostname, &channel_id_key, nullptr); - ASSERT_EQ(QUIC_SUCCESS, status); - - std::string signature; - ASSERT_TRUE(channel_id_key->Sign(signed_data, &signature)); - - std::string key = channel_id_key->SerializeKey(); - EXPECT_TRUE(ChannelIDVerifier::Verify(key, signed_data, signature)); - - EXPECT_FALSE(ChannelIDVerifier::Verify("a" + key, signed_data, signature)); - EXPECT_FALSE(ChannelIDVerifier::Verify(key, "a" + signed_data, signature)); - - std::unique_ptr<char[]> bad_key(new char[key.size()]); - memcpy(bad_key.get(), key.data(), key.size()); - bad_key[1] ^= 0x80; - EXPECT_FALSE(ChannelIDVerifier::Verify(std::string(bad_key.get(), key.size()), - signed_data, signature)); - - std::unique_ptr<char[]> bad_signature(new char[signature.size()]); - memcpy(bad_signature.get(), signature.data(), signature.size()); - bad_signature[1] ^= 0x80; - EXPECT_FALSE(ChannelIDVerifier::Verify( - key, signed_data, std::string(bad_signature.get(), signature.size()))); - - EXPECT_FALSE(ChannelIDVerifier::Verify(key, "wrong signed data", signature)); -} - } // namespace test } // namespace quic
diff --git a/quic/core/crypto/quic_crypto_client_config.cc b/quic/core/crypto/quic_crypto_client_config.cc index 3983836..d216f66 100644 --- a/quic/core/crypto/quic_crypto_client_config.cc +++ b/quic/core/crypto/quic_crypto_client_config.cc
@@ -11,7 +11,6 @@ #include "third_party/boringssl/src/include/openssl/ssl.h" #include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h" #include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter.h" -#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h" #include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" @@ -517,7 +516,6 @@ const CachedState* cached, QuicWallTime now, QuicRandom* rand, - const ChannelIDKey* channel_id_key, QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params, CryptoHandshakeMessage* out, std::string* error_details) const { @@ -643,65 +641,6 @@ } out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0])); - if (channel_id_key) { - // In order to calculate the encryption key for the CETV block we need to - // serialise the client hello as it currently is (i.e. without the CETV - // block). For this, the client hello is serialized without padding. - const size_t orig_min_size = out->minimum_size(); - out->set_minimum_size(0); - - CryptoHandshakeMessage cetv; - cetv.set_tag(kCETV); - - std::string hkdf_input; - const QuicData& client_hello_serialized = out->GetSerialized(); - hkdf_input.append(QuicCryptoConfig::kCETVLabel, - strlen(QuicCryptoConfig::kCETVLabel) + 1); - hkdf_input.append(connection_id.data(), connection_id.length()); - hkdf_input.append(client_hello_serialized.data(), - client_hello_serialized.length()); - hkdf_input.append(cached->server_config()); - - std::string key = channel_id_key->SerializeKey(); - std::string signature; - if (!channel_id_key->Sign(hkdf_input, &signature)) { - *error_details = "Channel ID signature failed"; - return QUIC_INVALID_CHANNEL_ID_SIGNATURE; - } - - cetv.SetStringPiece(kCIDK, key); - cetv.SetStringPiece(kCIDS, signature); - - CrypterPair crypters; - if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, - out_params->aead, out_params->client_nonce, - out_params->server_nonce, pre_shared_key_, - hkdf_input, Perspective::IS_CLIENT, - CryptoUtils::Diversification::Never(), - &crypters, nullptr /* subkey secret */)) { - *error_details = "Symmetric key setup failed"; - return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; - } - - const QuicData& cetv_plaintext = cetv.GetSerialized(); - const size_t encrypted_len = - crypters.encrypter->GetCiphertextSize(cetv_plaintext.length()); - std::unique_ptr<char[]> output(new char[encrypted_len]); - size_t output_size = 0; - if (!crypters.encrypter->EncryptPacket( - 0 /* packet number */, QuicStringPiece() /* associated data */, - cetv_plaintext.AsStringPiece(), output.get(), &output_size, - encrypted_len)) { - *error_details = "Packet encryption failed"; - return QUIC_ENCRYPTION_FAILURE; - } - - out->SetStringPiece(kCETV, QuicStringPiece(output.get(), output_size)); - out->MarkDirty(); - - out->set_minimum_size(orig_min_size); - } - // Derive the symmetric keys and set up the encrypters and decrypters. // Set the following members of out_params: // out_params->hkdf_input_suffix @@ -951,19 +890,10 @@ return proof_verifier_.get(); } -ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const { - return channel_id_source_.get(); -} - SSL_CTX* QuicCryptoClientConfig::ssl_ctx() const { return ssl_ctx_.get(); } -void QuicCryptoClientConfig::SetChannelIDSource( - std::unique_ptr<ChannelIDSource> source) { - channel_id_source_ = std::move(source); -} - void QuicCryptoClientConfig::InitializeFrom( const QuicServerId& server_id, const QuicServerId& canonical_server_id,
diff --git a/quic/core/crypto/quic_crypto_client_config.h b/quic/core/crypto/quic_crypto_client_config.h index f4293c0..2918a23 100644 --- a/quic/core/crypto/quic_crypto_client_config.h +++ b/quic/core/crypto/quic_crypto_client_config.h
@@ -22,8 +22,6 @@ namespace quic { -class ChannelIDKey; -class ChannelIDSource; class CryptoHandshakeMessage; class ProofVerifier; class ProofVerifyDetails; @@ -258,7 +256,6 @@ const CachedState* cached, QuicWallTime now, QuicRandom* rand, - const ChannelIDKey* channel_id_key, QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params, CryptoHandshakeMessage* out, std::string* error_details) const; @@ -312,15 +309,8 @@ ProofVerifier* proof_verifier() const; - ChannelIDSource* channel_id_source() const; - SSL_CTX* ssl_ctx() const; - // SetChannelIDSource sets a ChannelIDSource that will be called, when the - // server supports channel IDs, to obtain a channel ID for signing a message - // proving possession of the channel ID. - void SetChannelIDSource(std::unique_ptr<ChannelIDSource> source); - // Initialize the CachedState from |canonical_crypto_config| for the // |canonical_server_id| as the initial CachedState for |server_id|. We will // copy config data only if |canonical_crypto_config| has valid proof. @@ -397,7 +387,6 @@ std::vector<std::string> canonical_suffixes_; std::unique_ptr<ProofVerifier> proof_verifier_; - std::unique_ptr<ChannelIDSource> channel_id_source_; bssl::UniquePtr<SSL_CTX> ssl_ctx_; // The |user_agent_id_| passed in QUIC's CHLO message.
diff --git a/quic/core/crypto/quic_crypto_client_config_test.cc b/quic/core/crypto/quic_crypto_client_config_test.cc index 2158cd3..b7dd529 100644 --- a/quic/core/crypto/quic_crypto_client_config_test.cc +++ b/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -323,7 +323,6 @@ QuicServerId server_id("www.google.com", 443, false); config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state, QuicWallTime::Zero(), &rand, - nullptr, // channel_id_key params, &chlo, &error_details); // Verify that the version label has been set correctly in the CHLO. @@ -346,7 +345,6 @@ QuicServerId server_id("www.google.com", 443, false); config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state, QuicWallTime::Zero(), &rand, - nullptr, // channel_id_key params, &chlo, &error_details); // Verify that the version label has been set correctly in the CHLO.
diff --git a/quic/core/crypto/testdata/README.md b/quic/core/crypto/testdata/README.md new file mode 100644 index 0000000..509d261 --- /dev/null +++ b/quic/core/crypto/testdata/README.md
@@ -0,0 +1,15 @@ +# QUIC Crypto Test Data + +This directory contains certificates and keys used for testing QUIC. Most of the +contents are generated by manual invocation of a script. The steps to +regnenerate everything are: + +* Build the ssl key encryptor: `blaze build + //gfe/gfe2/ssl_cert_storage:ssl_key_encryptor` + +* Update the nonce (`nonce.txt`) to whatever stable value. If the nonce + changes, the process of encrypting keys must be repeated. + +* Invoke the script: `go run generate.go` + +Make sure to commit everything to Piper when done.
diff --git a/quic/core/qpack/offline/README.md b/quic/core/qpack/offline/README.md new file mode 100644 index 0000000..4f6697c --- /dev/null +++ b/quic/core/qpack/offline/README.md
@@ -0,0 +1,28 @@ +# QPACK Offline Interop Testing tools + +See +[QPACK Offline Interop](https://github.com/quicwg/base-drafts/wiki/QPACK-Offline-Interop) +for description of test data format. + +Example usage: + +```shell +$ # Download test data +$ cd $TEST_DATA +$ git clone https://github.com/qpackers/qifs.git +$ TEST_ENCODED_DATA=`pwd`/qifs/encoded/qpack-03 +$ TEST_QIF_DATA=`pwd`/qifs/qifs +$ +$ # Decode encoded test data in four files and verify that they match +$ # the original headers in corresponding files +$ $BIN/qpack_offline_decoder \ +> $TEST_ENCODED_DATA/f5/fb-req.qifencoded.4096.100.0 \ +> $TEST_QIF_DATA/fb-req.qif +> $TEST_ENCODED_DATA/h2o/fb-req-hq.out.512.0.1 \ +> $TEST_QIF_DATA/fb-req-hq.qif +> $TEST_ENCODED_DATA/ls-qpack/fb-resp-hq.out.0.0.0 \ +> $TEST_QIF_DATA/fb-resp-hq.qif +> $TEST_ENCODED_DATA/proxygen/netbsd.qif.proxygen.out.4096.0.0 \ +> $TEST_QIF_DATA/netbsd.qif +$ +```
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc index 1877537..57d8c28 100644 --- a/quic/core/quic_crypto_client_handshaker.cc +++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -17,32 +17,6 @@ namespace quic { -QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl:: - ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent) - : parent_(parent) {} - -QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl:: - ~ChannelIDSourceCallbackImpl() {} - -void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Run( - std::unique_ptr<ChannelIDKey>* channel_id_key) { - if (parent_ == nullptr) { - return; - } - - parent_->channel_id_key_ = std::move(*channel_id_key); - parent_->channel_id_source_callback_run_ = true; - parent_->channel_id_source_callback_ = nullptr; - parent_->DoHandshakeLoop(nullptr); - - // The ChannelIDSource owns this object and will delete it when this method - // returns. -} - -void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Cancel() { - parent_ = nullptr; -} - QuicCryptoClientHandshaker::ProofVerifierCallbackImpl:: ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent) : parent_(parent) {} @@ -87,9 +61,6 @@ crypto_config_(crypto_config), server_id_(server_id), generation_counter_(0), - channel_id_sent_(false), - channel_id_source_callback_run_(false), - channel_id_source_callback_(nullptr), verify_context_(std::move(verify_context)), proof_verify_callback_(nullptr), proof_handler_(proof_handler), @@ -102,9 +73,6 @@ crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {} QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() { - if (channel_id_source_callback_) { - channel_id_source_callback_->Cancel(); - } if (proof_verify_callback_) { proof_verify_callback_->Cancel(); } @@ -153,14 +121,6 @@ return num_scup_messages_received_; } -bool QuicCryptoClientHandshaker::WasChannelIDSent() const { - return channel_id_sent_; -} - -bool QuicCryptoClientHandshaker::WasChannelIDSourceCallbackRun() const { - return channel_id_source_callback_run_; -} - std::string QuicCryptoClientHandshaker::chlo_hash() const { return chlo_hash_; } @@ -234,12 +194,6 @@ case STATE_VERIFY_PROOF_COMPLETE: DoVerifyProofComplete(cached); break; - case STATE_GET_CHANNEL_ID: - rv = DoGetChannelID(cached); - break; - case STATE_GET_CHANNEL_ID_COMPLETE: - DoGetChannelIDComplete(); - break; case STATE_RECV_SHLO: DoReceiveSHLO(in, cached); break; @@ -272,7 +226,7 @@ // If the cached state needs to be verified, do it now. next_state_ = STATE_VERIFY_PROOF; } else { - next_state_ = STATE_GET_CHANNEL_ID; + next_state_ = STATE_SEND_CHLO; } } @@ -355,8 +309,8 @@ server_id_, session()->connection()->connection_id(), session()->supported_versions().front(), cached, session()->connection()->clock()->WallNow(), - session()->connection()->random_generator(), channel_id_key_.get(), - crypto_negotiated_params_, &out, &error_details); + session()->connection()->random_generator(), crypto_negotiated_params_, + &out, &error_details); if (error != QUIC_NO_ERROR) { // Flush the cached config so that, if it's bad, the server has a // chance to send us another in the future. @@ -365,7 +319,6 @@ return; } chlo_hash_ = CryptoUtils::HashHandshakeMessage(out, Perspective::IS_CLIENT); - channel_id_sent_ = (channel_id_key_ != nullptr); if (cached->proof_verify_details()) { proof_handler_->OnProofVerifyDetailsAvailable( *cached->proof_verify_details()); @@ -461,7 +414,7 @@ return; } } - next_state_ = STATE_GET_CHANNEL_ID; + next_state_ = STATE_SEND_CHLO; } QuicAsyncStatus QuicCryptoClientHandshaker::DoVerifyProof( @@ -531,7 +484,7 @@ SetCachedProofValid(cached); cached->SetProofVerifyDetails(verify_details_.release()); if (!handshake_confirmed()) { - next_state_ = STATE_GET_CHANNEL_ID; + next_state_ = STATE_SEND_CHLO; } else { // TODO: Enable Expect-Staple. https://crbug.com/631101 next_state_ = STATE_NONE; @@ -539,48 +492,6 @@ } } -QuicAsyncStatus QuicCryptoClientHandshaker::DoGetChannelID( - QuicCryptoClientConfig::CachedState* cached) { - next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; - channel_id_key_.reset(); - if (!RequiresChannelID(cached)) { - next_state_ = STATE_SEND_CHLO; - return QUIC_SUCCESS; - } - - ChannelIDSourceCallbackImpl* channel_id_source_callback = - new ChannelIDSourceCallbackImpl(this); - QuicAsyncStatus status = crypto_config_->channel_id_source()->GetChannelIDKey( - server_id_.host(), &channel_id_key_, channel_id_source_callback); - - switch (status) { - case QUIC_PENDING: - channel_id_source_callback_ = channel_id_source_callback; - QUIC_DVLOG(1) << "Looking up channel ID"; - break; - case QUIC_FAILURE: - next_state_ = STATE_NONE; - delete channel_id_source_callback; - stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE, - "Channel ID lookup failed"); - break; - case QUIC_SUCCESS: - delete channel_id_source_callback; - break; - } - return status; -} - -void QuicCryptoClientHandshaker::DoGetChannelIDComplete() { - if (!channel_id_key_.get()) { - next_state_ = STATE_NONE; - stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE, - "Channel ID lookup failed"); - return; - } - next_state_ = STATE_SEND_CHLO; -} - void QuicCryptoClientHandshaker::DoReceiveSHLO( const CryptoHandshakeMessage* in, QuicCryptoClientConfig::CachedState* cached) { @@ -677,26 +588,4 @@ proof_handler_->OnProofValid(*cached); } -bool QuicCryptoClientHandshaker::RequiresChannelID( - QuicCryptoClientConfig::CachedState* cached) { - if (server_id_.privacy_mode_enabled() || - !crypto_config_->channel_id_source()) { - return false; - } - const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); - if (!scfg) { // scfg may be null then we send an inchoate CHLO. - return false; - } - QuicTagVector their_proof_demands; - if (scfg->GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) { - return false; - } - for (const QuicTag tag : their_proof_demands) { - if (tag == kCHID) { - return true; - } - } - return false; -} - } // namespace quic
diff --git a/quic/core/quic_crypto_client_handshaker.h b/quic/core/quic_crypto_client_handshaker.h index 4aa5d46..023905b 100644 --- a/quic/core/quic_crypto_client_handshaker.h +++ b/quic/core/quic_crypto_client_handshaker.h
@@ -7,7 +7,6 @@ #include <string> -#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h" #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h" @@ -39,8 +38,6 @@ bool CryptoConnect() override; int num_sent_client_hellos() const override; int num_scup_messages_received() const override; - bool WasChannelIDSent() const override; - bool WasChannelIDSourceCallbackRun() const override; std::string chlo_hash() const override; bool encryption_established() const override; bool handshake_confirmed() const override; @@ -59,25 +56,6 @@ void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached); private: - // ChannelIDSourceCallbackImpl is passed as the callback method to - // GetChannelIDKey. The ChannelIDSource calls this class with the result of - // channel ID lookup when lookup is performed asynchronously. - class ChannelIDSourceCallbackImpl : public ChannelIDSourceCallback { - public: - explicit ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent); - ~ChannelIDSourceCallbackImpl() override; - - // ChannelIDSourceCallback interface. - void Run(std::unique_ptr<ChannelIDKey>* channel_id_key) override; - - // Cancel causes any future callbacks to be ignored. It must be called on - // the same thread as the callback will be made on. - void Cancel(); - - private: - QuicCryptoClientHandshaker* parent_; - }; - // ProofVerifierCallbackImpl is passed as the callback method to VerifyProof. // The ProofVerifier calls this class with the result of proof verification // when verification is performed asynchronously. @@ -106,8 +84,6 @@ STATE_RECV_REJ, STATE_VERIFY_PROOF, STATE_VERIFY_PROOF_COMPLETE, - STATE_GET_CHANNEL_ID, - STATE_GET_CHANNEL_ID_COMPLETE, STATE_RECV_SHLO, STATE_INITIALIZE_SCUP, STATE_NONE, @@ -137,15 +113,6 @@ // server config). If not, it closes the connection. void DoVerifyProofComplete(QuicCryptoClientConfig::CachedState* cached); - // Start the look up of Channel ID process. Returns either QUIC_SUCCESS if - // RequiresChannelID returns false or QuicAsyncStatus returned by - // GetChannelIDKey. - QuicAsyncStatus DoGetChannelID(QuicCryptoClientConfig::CachedState* cached); - - // If there is no channel ID, then close the connection otherwise transtion to - // STATE_SEND_CHLO state. - void DoGetChannelIDComplete(); - // Process SHLO message from the server. void DoReceiveSHLO(const CryptoHandshakeMessage* in, QuicCryptoClientConfig::CachedState* cached); @@ -159,10 +126,6 @@ // OnProofValid() method. void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached); - // Returns true if the server crypto config in |cached| requires a ChannelID - // and the client config settings also allow sending a ChannelID. - bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached); - QuicCryptoClientStream* stream_; QuicSession* session_; @@ -183,22 +146,6 @@ // Generation counter from QuicCryptoClientConfig's CachedState. uint64_t generation_counter_; - // True if a channel ID was sent. - bool channel_id_sent_; - - // True if channel_id_source_callback_ was run. - bool channel_id_source_callback_run_; - - // channel_id_source_callback_ contains the callback object that we passed - // to an asynchronous channel ID lookup. The ChannelIDSource owns this - // object. - ChannelIDSourceCallbackImpl* channel_id_source_callback_; - - // These members are used to store the result of an asynchronous channel ID - // lookup. These members must not be used after - // STATE_GET_CHANNEL_ID_COMPLETE. - std::unique_ptr<ChannelIDKey> channel_id_key_; - // verify_context_ contains the context object that we pass to asynchronous // proof verifications. std::unique_ptr<ProofVerifyContext> verify_context_;
diff --git a/quic/core/quic_crypto_client_stream.cc b/quic/core/quic_crypto_client_stream.cc index 7c2aa40..93f2a61 100644 --- a/quic/core/quic_crypto_client_stream.cc +++ b/quic/core/quic_crypto_client_stream.cc
@@ -84,14 +84,6 @@ return handshaker_->crypto_message_parser(); } -bool QuicCryptoClientStream::WasChannelIDSent() const { - return handshaker_->WasChannelIDSent(); -} - -bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const { - return handshaker_->WasChannelIDSourceCallbackRun(); -} - std::string QuicCryptoClientStream::chlo_hash() const { return handshaker_->chlo_hash(); }
diff --git a/quic/core/quic_crypto_client_stream.h b/quic/core/quic_crypto_client_stream.h index d0e4ee1..b8dff7e 100644 --- a/quic/core/quic_crypto_client_stream.h +++ b/quic/core/quic_crypto_client_stream.h
@@ -9,7 +9,6 @@ #include <memory> #include <string> -#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h" #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" #include "net/third_party/quiche/src/quic/core/quic_config.h" @@ -85,13 +84,6 @@ // to handshake confirmation. virtual int num_scup_messages_received() const = 0; - // Returns true if a channel ID was sent on this connection. - virtual bool WasChannelIDSent() const = 0; - - // Returns true if our ChannelIDSourceCallback was run, which implies the - // ChannelIDSource operated asynchronously. Intended for testing. - virtual bool WasChannelIDSourceCallbackRun() const = 0; - virtual std::string chlo_hash() const = 0; // Returns true once any encrypter (initial/0RTT or final/1RTT) has been set @@ -151,13 +143,6 @@ const override; CryptoMessageParser* crypto_message_parser() override; - // Returns true if a channel ID was sent on this connection. - bool WasChannelIDSent() const; - - // Returns true if our ChannelIDSourceCallback was run, which implies the - // ChannelIDSource operated asynchronously. Intended for testing. - bool WasChannelIDSourceCallbackRun() const; - std::string chlo_hash() const; protected:
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc index 0cb130e..2d3702f 100644 --- a/quic/core/quic_crypto_client_stream_test.cc +++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -321,14 +321,6 @@ stream(), server_config_update, Perspective::IS_SERVER); } -TEST_F(QuicCryptoClientStreamTest, NoChannelID) { - crypto_config_.SetChannelIDSource(nullptr); - - CompleteCryptoHandshake(); - EXPECT_FALSE(stream()->WasChannelIDSent()); - EXPECT_FALSE(stream()->WasChannelIDSourceCallbackRun()); -} - TEST_F(QuicCryptoClientStreamTest, PreferredVersion) { // This mimics the case where client receives version negotiation packet, such // that, the preferred version is different from the packets' version.
diff --git a/quic/core/quic_crypto_server_stream_test.cc b/quic/core/quic_crypto_server_stream_test.cc index e01414b..ff7111c 100644 --- a/quic/core/quic_crypto_server_stream_test.cc +++ b/quic/core/quic_crypto_server_stream_test.cc
@@ -418,30 +418,6 @@ Perspective::IS_SERVER); } -TEST_P(QuicCryptoServerStreamTest, ChannelID) { - Initialize(); - - client_options_.channel_id_enabled = true; - client_options_.channel_id_source_async = false; - // CompleteCryptoHandshake verifies - // server_stream()->crypto_negotiated_params().channel_id is correct. - EXPECT_EQ(2, CompleteCryptoHandshake()); - EXPECT_TRUE(server_stream()->encryption_established()); - EXPECT_TRUE(server_stream()->handshake_confirmed()); -} - -TEST_P(QuicCryptoServerStreamTest, ChannelIDAsync) { - Initialize(); - - client_options_.channel_id_enabled = true; - client_options_.channel_id_source_async = true; - // CompleteCryptoHandshake verifies - // server_stream()->crypto_negotiated_params().channel_id is correct. - EXPECT_EQ(2, CompleteCryptoHandshake()); - EXPECT_TRUE(server_stream()->encryption_established()); - EXPECT_TRUE(server_stream()->handshake_confirmed()); -} - TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) { // An attempt to send a SCUP before completing handshake should fail. Initialize();
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc index 1087844..db1f6b4 100644 --- a/quic/core/tls_client_handshaker.cc +++ b/quic/core/tls_client_handshaker.cc
@@ -190,16 +190,6 @@ return 0; } -bool TlsClientHandshaker::WasChannelIDSent() const { - // Channel ID is not used with TLS in QUIC. - return false; -} - -bool TlsClientHandshaker::WasChannelIDSourceCallbackRun() const { - // Channel ID is not used with TLS in QUIC. - return false; -} - std::string TlsClientHandshaker::chlo_hash() const { return ""; }
diff --git a/quic/core/tls_client_handshaker.h b/quic/core/tls_client_handshaker.h index c2243b3..3647e10 100644 --- a/quic/core/tls_client_handshaker.h +++ b/quic/core/tls_client_handshaker.h
@@ -42,8 +42,6 @@ bool CryptoConnect() override; int num_sent_client_hellos() const override; int num_scup_messages_received() const override; - bool WasChannelIDSent() const override; - bool WasChannelIDSourceCallbackRun() const override; std::string chlo_hash() const override; // From QuicCryptoClientStream::HandshakerDelegate and TlsHandshaker
diff --git a/quic/platform/README.md b/quic/platform/README.md new file mode 100644 index 0000000..6538de1 --- /dev/null +++ b/quic/platform/README.md
@@ -0,0 +1,12 @@ +# QUIC platform + +This platform/ directory exists in order to allow QUIC code to be built on +numerous platforms. It contains two subdirectories: + +- api/ contains platform independent class definitions for fundamental data + structures (e.g., IPAddress, SocketAddress, etc.). +- impl/ contains platform specific implementations of these data structures. + The content of files in impl/ will vary depending on the platform. + +Code in the parent quic/ directory should not depend on any platform specific +code, other than that found in impl/.
diff --git a/quic/platform/api/README.md b/quic/platform/api/README.md new file mode 100644 index 0000000..d3de2e1 --- /dev/null +++ b/quic/platform/api/README.md
@@ -0,0 +1,67 @@ +# QUIC platform API + +This directory contains the infrastructure blocks needed to support QUIC in +certain platform. These APIs act as interaction layers between QUIC core and +either the upper layer application (i.e. Chrome, Envoy) or the platform's own +infrastructure (i.e. logging, test framework and system IO). QUIC core needs the +implementations of these APIs to build and function appropriately. There is +unidirectional dependency from QUIC core to most of the APIs here, such as +QUIC_LOG and QuicMutex, but a few APIs also depend back on QUIC core's basic +QUIC data types, such as QuicClock and QuicSleep. + +- APIs used by QUIC core: + + Most APIs are used by QUIC core to interact with platform infrastructure + (i.e. QUIC_LOG) or to wrap around platform dependent data types (i.e. + QuicIntervalSet), the dependency is: + + ```dot + digraph { + application -> quic_core -> quic_platform_api -> quic_platform_impl -> platform_infrastructure + application -> platform_infrastructure + } + ``` + +- APIs used by applications: + + Some APIs are used by applications to interact with QUIC core (i.e. + QuicMemSlice). For such APIs, their dependency model is: + + ```dot + digraph { + application -> quic_platform_impl -> platform_infrastructure + application -> quic_core -> quic_platform_api + quic_platform_impl -> quic_platform_api + application -> platform_infrastructure + } + ``` + + An example for such dependency is QuicClock. + + Or + + ```dot + digraph { + application -> quic_platform_impl -> platform_infrastructure + application -> quic_core -> quic_platform_api -> quic_platform_impl + quic_platform_impl -> quic_platform_api + application -> platform_infrastructure + } + ``` + + An example for such dependency is QuicMemSlice. + +# Documentation of each API and its usage. + +QuicMemSlice +: QuicMemSlice is used to wrap application data and pass to QUIC stream's + write interface. It refers to a memory block of data which should be around + till QuicMemSlice::Reset() is called. It's upto each platform, to implement + it as reference counted or not. + +QuicClock +: QuicClock is used by QUIC core to get current time. Its instance is created + by applications and passed into QuicDispatcher and + QuicConnectionHelperInterface. + +TODO(b/131224336) add document for other APIs
diff --git a/quic/test_tools/crypto_test_utils.cc b/quic/test_tools/crypto_test_utils.cc index 318cd73..0157456 100644 --- a/quic/test_tools/crypto_test_utils.cc +++ b/quic/test_tools/crypto_test_utils.cc
@@ -43,126 +43,6 @@ namespace quic { namespace test { -TestChannelIDKey::TestChannelIDKey(EVP_PKEY* ecdsa_key) - : ecdsa_key_(ecdsa_key) {} -TestChannelIDKey::~TestChannelIDKey() {} - -bool TestChannelIDKey::Sign(QuicStringPiece signed_data, - std::string* out_signature) const { - bssl::ScopedEVP_MD_CTX md_ctx; - if (EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr, - ecdsa_key_.get()) != 1) { - return false; - } - - EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kContextStr, - strlen(ChannelIDVerifier::kContextStr) + 1); - EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kClientToServerStr, - strlen(ChannelIDVerifier::kClientToServerStr) + 1); - EVP_DigestUpdate(md_ctx.get(), signed_data.data(), signed_data.size()); - - size_t sig_len; - if (!EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)) { - return false; - } - - std::unique_ptr<uint8_t[]> der_sig(new uint8_t[sig_len]); - if (!EVP_DigestSignFinal(md_ctx.get(), der_sig.get(), &sig_len)) { - return false; - } - - uint8_t* derp = der_sig.get(); - bssl::UniquePtr<ECDSA_SIG> sig( - d2i_ECDSA_SIG(nullptr, const_cast<const uint8_t**>(&derp), sig_len)); - if (sig.get() == nullptr) { - return false; - } - - // The signature consists of a pair of 32-byte numbers. - static const size_t kSignatureLength = 32 * 2; - std::unique_ptr<uint8_t[]> signature(new uint8_t[kSignatureLength]); - if (!BN_bn2bin_padded(&signature[0], 32, sig->r) || - !BN_bn2bin_padded(&signature[32], 32, sig->s)) { - return false; - } - - *out_signature = - std::string(reinterpret_cast<char*>(signature.get()), kSignatureLength); - - return true; -} - -std::string TestChannelIDKey::SerializeKey() const { - // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 - // key, is 0x04 (meaning uncompressed) followed by the x and y field - // elements as 32-byte, big-endian numbers. - static const int kExpectedKeyLength = 65; - - int len = i2d_PublicKey(ecdsa_key_.get(), nullptr); - if (len != kExpectedKeyLength) { - return ""; - } - - uint8_t buf[kExpectedKeyLength]; - uint8_t* derp = buf; - i2d_PublicKey(ecdsa_key_.get(), &derp); - - return std::string(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); -} - -TestChannelIDSource::~TestChannelIDSource() {} - -QuicAsyncStatus TestChannelIDSource::GetChannelIDKey( - const std::string& hostname, - std::unique_ptr<ChannelIDKey>* channel_id_key, - ChannelIDSourceCallback* /*callback*/) { - *channel_id_key = QuicMakeUnique<TestChannelIDKey>(HostnameToKey(hostname)); - return QUIC_SUCCESS; -} - -// static -EVP_PKEY* TestChannelIDSource::HostnameToKey(const std::string& hostname) { - // In order to generate a deterministic key for a given hostname the - // hostname is hashed with SHA-256 and the resulting digest is treated as a - // big-endian number. The most-significant bit is cleared to ensure that - // the resulting value is less than the order of the group and then it's - // taken as a private key. Given the private key, the public key is - // calculated with a group multiplication. - SHA256_CTX sha256; - SHA256_Init(&sha256); - SHA256_Update(&sha256, hostname.data(), hostname.size()); - - unsigned char digest[SHA256_DIGEST_LENGTH]; - SHA256_Final(digest, &sha256); - - // Ensure that the digest is less than the order of the P-256 group by - // clearing the most-significant bit. - digest[0] &= 0x7f; - - bssl::UniquePtr<BIGNUM> k(BN_new()); - CHECK(BN_bin2bn(digest, sizeof(digest), k.get()) != nullptr); - - bssl::UniquePtr<EC_GROUP> p256( - EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); - CHECK(p256); - - bssl::UniquePtr<EC_KEY> ecdsa_key(EC_KEY_new()); - CHECK(ecdsa_key && EC_KEY_set_group(ecdsa_key.get(), p256.get())); - - bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get())); - CHECK(EC_POINT_mul(p256.get(), point.get(), k.get(), nullptr, nullptr, - nullptr)); - - EC_KEY_set_private_key(ecdsa_key.get(), k.get()); - EC_KEY_set_public_key(ecdsa_key.get(), point.get()); - - bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new()); - // EVP_PKEY_set1_EC_KEY takes a reference so no |release| here. - EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa_key.get()); - - return pkey.release(); -} - namespace crypto_test_utils { namespace { @@ -207,57 +87,13 @@ return false; } -// A ChannelIDSource that works in asynchronous mode unless the |callback| -// argument to GetChannelIDKey is nullptr. -class AsyncTestChannelIDSource : public ChannelIDSource, public CallbackSource { - public: - // |sync_source| is a synchronous ChannelIDSource. - explicit AsyncTestChannelIDSource( - std::unique_ptr<ChannelIDSource> sync_source) - : sync_source_(std::move(sync_source)) {} - ~AsyncTestChannelIDSource() override {} - - // ChannelIDSource implementation. - QuicAsyncStatus GetChannelIDKey(const std::string& hostname, - std::unique_ptr<ChannelIDKey>* channel_id_key, - ChannelIDSourceCallback* callback) override { - // Synchronous mode. - if (!callback) { - return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr); - } - - // Asynchronous mode. - QuicAsyncStatus status = - sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr); - if (status != QUIC_SUCCESS) { - return QUIC_FAILURE; - } - callback_.reset(callback); - return QUIC_PENDING; - } - - // CallbackSource implementation. - void RunPendingCallbacks() override { - if (callback_) { - callback_->Run(&channel_id_key_); - callback_.reset(); - } - } - - private: - std::unique_ptr<ChannelIDSource> sync_source_; - std::unique_ptr<ChannelIDSourceCallback> callback_; - std::unique_ptr<ChannelIDKey> channel_id_key_; -}; - } // anonymous namespace FakeServerOptions::FakeServerOptions() {} FakeServerOptions::~FakeServerOptions() {} -FakeClientOptions::FakeClientOptions() - : channel_id_enabled(false), channel_id_source_async(false) {} +FakeClientOptions::FakeClientOptions() {} FakeClientOptions::~FakeClientOptions() {} @@ -446,19 +282,6 @@ QuicCryptoClientConfig crypto_config(ProofVerifierForTesting(), TlsClientHandshaker::CreateSslCtx()); - AsyncTestChannelIDSource* async_channel_id_source = nullptr; - if (options.channel_id_enabled) { - std::unique_ptr<ChannelIDSource> source = ChannelIDSourceForTesting(); - if (options.channel_id_source_async) { - auto temp = QuicMakeUnique<AsyncTestChannelIDSource>(std::move(source)); - async_channel_id_source = temp.get(); - source = std::move(temp); - } - crypto_config.SetChannelIDSource(std::move(source)); - } - if (!options.token_binding_params.empty()) { - crypto_config.tb_key_params = options.token_binding_params; - } TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(), supported_versions, server_id, &crypto_config); @@ -471,25 +294,12 @@ client_session.GetMutableCryptoStream()->CryptoConnect(); CHECK_EQ(1u, client_conn->encrypted_packets_.size()); - CommunicateHandshakeMessagesAndRunCallbacks( - client_conn, client_session.GetMutableCryptoStream(), server_conn, server, - async_channel_id_source); + CommunicateHandshakeMessages(client_conn, + client_session.GetMutableCryptoStream(), + server_conn, server); if (server->handshake_confirmed() && server->encryption_established()) { CompareClientAndServerKeys(client_session.GetMutableCryptoStream(), server); - - if (options.channel_id_enabled) { - std::unique_ptr<ChannelIDKey> channel_id_key; - QuicAsyncStatus status = - crypto_config.channel_id_source()->GetChannelIDKey( - server_id.host(), &channel_id_key, nullptr); - EXPECT_EQ(QUIC_SUCCESS, status); - EXPECT_EQ(channel_id_key->SerializeKey(), - server->crypto_negotiated_params().channel_id); - EXPECT_EQ( - options.channel_id_source_async, - client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun()); - } } return client_session.GetCryptoStream()->num_sent_client_hellos(); @@ -530,16 +340,6 @@ QuicCryptoStream* client, PacketSavingConnection* server_conn, QuicCryptoStream* server) { - CommunicateHandshakeMessagesAndRunCallbacks(client_conn, client, server_conn, - server, nullptr); -} - -void CommunicateHandshakeMessagesAndRunCallbacks( - PacketSavingConnection* client_conn, - QuicCryptoStream* client, - PacketSavingConnection* server_conn, - QuicCryptoStream* server, - CallbackSource* callback_source) { size_t client_i = 0, server_i = 0; while (!client->handshake_confirmed() || !server->handshake_confirmed()) { ASSERT_GT(client_conn->encrypted_packets_.size(), client_i); @@ -548,9 +348,6 @@ << " packets client->server"; MovePackets(client_conn, &client_i, server, server_conn, Perspective::IS_SERVER); - if (callback_source) { - callback_source->RunPendingCallbacks(); - } if (client->handshake_confirmed() && server->handshake_confirmed()) { break; @@ -561,9 +358,6 @@ << " packets server->client"; MovePackets(server_conn, &server_i, client, client_conn, Perspective::IS_CLIENT); - if (callback_source) { - callback_source->RunPendingCallbacks(); - } } } @@ -898,10 +692,6 @@ return *parsed; } -std::unique_ptr<ChannelIDSource> ChannelIDSourceForTesting() { - return QuicMakeUnique<TestChannelIDSource>(); -} - void MovePackets(PacketSavingConnection* source_conn, size_t* inout_packet_index, QuicCryptoStream* dest_stream,
diff --git a/quic/test_tools/crypto_test_utils.h b/quic/test_tools/crypto_test_utils.h index 5bb4b4e..1091c8c 100644 --- a/quic/test_tools/crypto_test_utils.h +++ b/quic/test_tools/crypto_test_utils.h
@@ -20,7 +20,6 @@ namespace quic { -class ChannelIDSource; class CommonCertSets; class ProofSource; class ProofVerifier; @@ -38,37 +37,6 @@ class PacketSavingConnection; -class TestChannelIDKey : public ChannelIDKey { - public: - explicit TestChannelIDKey(EVP_PKEY* ecdsa_key); - ~TestChannelIDKey() override; - - // ChannelIDKey implementation. - - bool Sign(QuicStringPiece signed_data, - std::string* out_signature) const override; - - std::string SerializeKey() const override; - - private: - bssl::UniquePtr<EVP_PKEY> ecdsa_key_; -}; - -class TestChannelIDSource : public ChannelIDSource { - public: - ~TestChannelIDSource() override; - - // ChannelIDSource implementation. - - QuicAsyncStatus GetChannelIDKey( - const std::string& hostname, - std::unique_ptr<ChannelIDKey>* channel_id_key, - ChannelIDSourceCallback* /*callback*/) override; - - private: - static EVP_PKEY* HostnameToKey(const std::string& hostname); -}; - namespace crypto_test_utils { // An interface for a source of callbacks. This is used for invoking @@ -101,17 +69,6 @@ FakeClientOptions(); ~FakeClientOptions(); - // If channel_id_enabled is true then the client will attempt to send a - // ChannelID. - bool channel_id_enabled; - - // If channel_id_source_async is true then the client will use an async - // ChannelIDSource for testing. Ignored if channel_id_enabled is false. - bool channel_id_source_async; - - // The Token Binding params that the client supports and will negotiate. - QuicTagVector token_binding_params; - // If only_tls_versions is set, then the client will only use TLS for the // crypto handshake. bool only_tls_versions = false; @@ -153,18 +110,6 @@ PacketSavingConnection* server_conn, QuicCryptoStream* server); -// CommunicateHandshakeMessagesAndRunCallbacks moves messages from |client| -// to |server| and back until |client|'s handshake has completed. If -// |callback_source| is not nullptr, -// CommunicateHandshakeMessagesAndRunCallbacks also runs callbacks from -// |callback_source| between processing messages. -void CommunicateHandshakeMessagesAndRunCallbacks( - PacketSavingConnection* client_conn, - QuicCryptoStream* client, - PacketSavingConnection* server_conn, - QuicCryptoStream* server, - CallbackSource* callback_source); - // AdvanceHandshake attempts to moves messages from |client| to |server| and // |server| to |client|. Returns the number of messages moved. std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, @@ -222,12 +167,6 @@ std::vector<std::pair<std::string, std::string>> tags_and_values, int minimum_size_bytes); -// ChannelIDSourceForTesting returns a ChannelIDSource that generates keys -// deterministically based on the hostname given in the GetChannelIDKey call. -// This ChannelIDSource works in synchronous mode, i.e., its GetChannelIDKey -// method never returns QUIC_PENDING. -std::unique_ptr<ChannelIDSource> ChannelIDSourceForTesting(); - // MovePackets parses crypto handshake messages from packet number // |*inout_packet_index| through to the last packet (or until a packet fails // to decrypt) and has |dest_stream| process them. |*inout_packet_index| is
diff --git a/quic/test_tools/fuzzing/README.md b/quic/test_tools/fuzzing/README.md new file mode 100644 index 0000000..b30ba8b --- /dev/null +++ b/quic/test_tools/fuzzing/README.md
@@ -0,0 +1,16 @@ +Examples of fuzz testing QUIC code using libfuzzer (go/libfuzzer). + +To build and run the examples: + +```sh +$ blaze build --config=asan-fuzzer //gfe/quic/test_tools/fuzzing/... +$ CORPUS_DIR=`mktemp -d` && echo ${CORPUS_DIR} +$ ./blaze-bin/gfe/quic/test_tools/fuzzing/quic_framer_fuzzer ${CORPUS_DIR} -use_counters=0 +``` + +By default this fuzzes with 64 byte chunks, to test the framer with more realistic +size input, try 1350 (max payload size of a QUIC packet): + +```sh +$ ./blaze-bin/gfe/quic/test_tools/fuzzing/quic_framer_fuzzer ${CORPUS_DIR} -use_counters=0 -max_len=1350 +```
diff --git a/quic/test_tools/simulator/README.md b/quic/test_tools/simulator/README.md new file mode 100644 index 0000000..8582962 --- /dev/null +++ b/quic/test_tools/simulator/README.md
@@ -0,0 +1,99 @@ +# QUIC network simulator + +This directory contains a discrete event network simulator which QUIC code uses +for testing congestion control and other transmission control code that requires +a network simulation for tests on QuicConnection level of abstraction. + +## Actors + +The core of the simulator is the Simulator class, which maintains a virtual +clock and an event queue. Any object in a simulation that needs to schedule +events has to subclass Actor. Subclassing Actor involves: + +1. Calling the `Actor::Actor(Simulator*, std::string)` constructor to establish + the name of the object and the simulator it is associated with. +2. Calling `Schedule(QuicTime)` to schedule the time at which `Act()` method is + called. `Schedule` will only cause the object to be rescheduled if the time + for which it is currently scheduled is later than the new time. +3. Implementing `Act()` method with the relevant logic. The actor will be + removed from the event queue right before `Act()` is called. + +Here is a simple example of an object that outputs simulation time into the log +every 100 ms. + +```c++ +class LogClock : public Actor { + public: + LogClock(Simulator* simulator, std::string name) : Actor(simulator, name) { + Schedule(clock_->Now()); + } + ~LogClock() override {} + + void Act() override { + QUIC_LOG(INFO) << "The current time is " + << clock_->Now().ToDebuggingValue(); + Schedule(clock_->Now() + QuicTime::Delta::FromMilliseconds(100)); + } +}; +``` + +A QuicAlarm object can be used to schedule events in the simulation using +`Simulator::GetAlarmFactory()`. + +## Ports + +The simulated network transfers packets, which are modelled as an instance of +struct `Packet`. A packet consists of source and destination address (which are +just plain strings), a transmission timestamp and the UDP-layer payload. + +The simulation uses the push model: any object that wishes to transfer a packet +to another component in the simulation has to explicitly do it itself. Any +object that can accept a packet is called a *port*. There are two types of +ports: unconstrained ports, which can always accept packets, and constrained +ports, which signal when they can accept a new packet. + +An endpoint is an object that is connected to the network and can both receive +and send packets. In our model, the endpoint always receives packets as an +unconstrained port (*RX port*), and always writes packets to a constrained port +(*TX port*). + +## Links + +The `SymmetricLink` class models a symmetric duplex links with finite bandwidth +and propagation delay. It consists of a pair of identical `OneWayLink`s, which +accept packets as a constrained port (where constrain comes from the finiteness +of bandwidth) and outputs them into an unconstrained port. Two endpoints +connected via a `SymmetricLink` look like this: + +```none + Endpoint A Endpoint B ++-----------+ SymmetricLink +-----------+ +| | +------------------------------+ | | +| +---------+ | +------------------------+ | +---------+ | +| | RX port <-----| OneWayLink *<-----| TX port | | +| +---------+ | +------------------------+ | +---------+ | +| | | | | | +| +---------+ | +------------------------+ | +---------+ | +| | TX port |----->* OneWayLink |-----> RX port | | +| +---------+ | +------------------------+ | +---------+ | +| | +------------------------------+ | | ++-----------+ +-----------+ + + ( -->* denotes constrained port) +``` + +In most common scenario, one of the endpoints is going to be a QUIC endpoint, +and another is going to be a switch port. + +## Other objects + +Besides `SymmetricLink`, the simulator provides the following objects: + +* `Queue` allows to convert a constrained port into an unconstrained one by + buffering packets upon arrival. The queue has a finite size, and once the + queue is full, the packets are silently dropped. +* `Switch` simulates a multi-port learning switch with a fixed queue for each + output port. +* `QuicEndpoint` allows QuicConnection to be run over the simulated network. +* `QuicEndpointMultiplexer` allows multiple connections to share the same + network endpoint.
diff --git a/quic/tools/quic_client_base.h b/quic/tools/quic_client_base.h index 69aa86d..0cc4d71 100644 --- a/quic/tools/quic_client_base.h +++ b/quic/tools/quic_client_base.h
@@ -131,13 +131,6 @@ crypto_config_.set_user_agent_id(user_agent_id); } - // SetChannelIDSource sets a ChannelIDSource that will be called, when the - // server supports channel IDs, to obtain a channel ID for signing a message - // proving possession of the channel ID. - void SetChannelIDSource(std::unique_ptr<ChannelIDSource> source) { - crypto_config_.SetChannelIDSource(std::move(source)); - } - const ParsedQuicVersionVector& supported_versions() const { return supported_versions_; }