1. 背景
截止目前,IETF QUIC最新版本已至draft-29。chromium官方也放出消息说正在加大部署IQUIC。IQUIC成为未来的QUIC标准,这促使我们去关注IQUIC的各种特性。0-RTT可以提高建连的速度。但是在实际测试IQUIC时,我们发现GQUIC可以正常启用0-RTT,但是IQUIC却始终无法生效。
2. 分析
客户端测试工具:
1) google quiche的quic_client
2) chrome浏览器: stable和canary
0-RTT建连没能成功,就是要找到其中的原因。我们的开发环境是chromium 87.0.4259.0,这是官方的一个中间版本,大概在2020年9月1日放出。经过调研我们发现这个版本的quiche还没有实现early_data_reason的相关接口,也就是没有提供0-RTT被拒绝的接口。不过在一个星期后(大约9月7日)的版本增加了该接口。这个接口还是挺有用的,方便系统告知我们0-RTT失败的原因。考虑到更新chromium的时间成本略高,于是我们自己复制相关代码实现了该接口:
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -12,6 +12,7 @@
#include "third_party/boringssl/src/include/openssl/hkdf.h"
#include "third_party/boringssl/src/include/openssl/mem.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter.h"
@@ -690,6 +691,29 @@ const char* CryptoUtils::HandshakeFailureReasonToString(
return "INVALID_HANDSHAKE_FAILURE_REASON";
}
+const char* CryptoUtils::EarlyDataReasonToString(
+ ssl_early_data_reason_t reason) {
+ switch (reason) {
+ RETURN_STRING_LITERAL(ssl_early_data_unknown);
+ RETURN_STRING_LITERAL(ssl_early_data_disabled);
+ RETURN_STRING_LITERAL(ssl_early_data_accepted);
+ RETURN_STRING_LITERAL(ssl_early_data_protocol_version);
+ RETURN_STRING_LITERAL(ssl_early_data_peer_declined);
+ RETURN_STRING_LITERAL(ssl_early_data_no_session_offered);
+ RETURN_STRING_LITERAL(ssl_early_data_session_not_resumed);
+ RETURN_STRING_LITERAL(ssl_early_data_unsupported_for_session);
+ RETURN_STRING_LITERAL(ssl_early_data_hello_retry_request);
+ RETURN_STRING_LITERAL(ssl_early_data_alpn_mismatch);
+ RETURN_STRING_LITERAL(ssl_early_data_channel_id);
+ RETURN_STRING_LITERAL(ssl_early_data_token_binding);
+ RETURN_STRING_LITERAL(ssl_early_data_ticket_age_skew);
+ RETURN_STRING_LITERAL(ssl_early_data_quic_parameter_mismatch);
+ }
+ QUIC_BUG_IF(reason < 0 || reason > ssl_early_data_reason_max_value)
+ << "Unknown ssl_early_data_reason_t " << reason;
+ return "unknown ssl_early_data_reason_t";
+}
+
// static
std::string CryptoUtils::HashHandshakeMessage(
const CryptoHandshakeMessage& message,
diff --git a/quic/core/crypto/crypto_utils.h b/quic/core/crypto/crypto_utils.h
index 6c167f8..ce3e1d8 100644
--- a/quic/core/crypto/crypto_utils.h
+++ b/quic/core/crypto/crypto_utils.h
@@ -210,7 +210,7 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
// Returns the name of the HandshakeFailureReason as a char*
static const char* HandshakeFailureReasonToString(
HandshakeFailureReason