diff --git a/src/core/connection.c b/src/core/connection.c index 01f536f223..878982aebe 100644 --- a/src/core/connection.c +++ b/src/core/connection.c @@ -433,6 +433,14 @@ QuicConnApplySettings( Settings->UnidiStreamCount); } + if (Settings->ServerResumptionLevel > QUIC_SERVER_NO_RESUME) { + QUIC_DBG_ASSERT(!Connection->State.Started); + // + // TODO: allocate memory for handshake TP here + // + Connection->State.ResumptionEnabled = TRUE; + } + QuicSendApplySettings(&Connection->Send, Settings); QuicCongestionControlInitialize(&Connection->CongestionControl, Settings); } diff --git a/src/core/connection.h b/src/core/connection.h index f3a4413cef..88a700cbcf 100644 --- a/src/core/connection.h +++ b/src/core/connection.h @@ -140,6 +140,13 @@ typedef union QUIC_CONNECTION_STATE { // BOOLEAN UseRoundRobinStreamScheduling : 1; + // + // Indicates that this connection has resumption enabled and needs to + // keep the TLS state and transport parameters until it is done sending + // resumption tickets. + // + BOOLEAN ResumptionEnabled : 1; + #ifdef QuicVerifierEnabledByAddr // // The calling app is being verified (app or driver verifier). diff --git a/src/core/quicdef.h b/src/core/quicdef.h index 5d36e2bcff..c48bdf1ef5 100644 --- a/src/core/quicdef.h +++ b/src/core/quicdef.h @@ -403,6 +403,12 @@ QUIC_STATIC_ASSERT( // #define QUIC_DEFAULT_MAX_DATAGRAM_LENGTH 0xFFFF +// +// By default, resumption and 0-RTT are not enabled for servers. +// If an application want to use these features, it must explicitly enable them. +// +#define QUIC_DEFAULT_SERVER_RESUMPTION_LEVEL QUIC_SERVER_NO_RESUME + /************************************************************* PERSISTENT SETTINGS *************************************************************/ @@ -437,3 +443,5 @@ QUIC_STATIC_ASSERT( #define QUIC_SETTING_CONN_FLOW_CONTROL_WINDOW "ConnFlowControlWindow" #define QUIC_SETTING_MAX_BYTES_PER_KEY_PHASE "MaxBytesPerKey" + +#define QUIC_SETTING_SERVER_RESUMPTION_OR_ZERORTT "ResumptionLevel" diff --git a/src/core/session.c b/src/core/session.c index 31b0a046a3..45fe01fd89 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -881,6 +881,25 @@ QuicSessionParamGet( Status = QUIC_STATUS_SUCCESS; break; + case QUIC_PARAM_SESSION_SERVER_RESUMPTION_LEVEL: + if (*BufferLength < sizeof(QUIC_SERVER_RESUMPTION_LEVEL)) { + *BufferLength = sizeof(QUIC_SERVER_RESUMPTION_LEVEL); + Status = QUIC_STATUS_BUFFER_TOO_SMALL; + break; + } + + if (Buffer == NULL) { + Status = QUIC_STATUS_INVALID_PARAMETER; + break; + } + + *BufferLength = sizeof(QUIC_SERVER_RESUMPTION_LEVEL); + *(QUIC_SERVER_RESUMPTION_LEVEL*)Buffer = + (QUIC_SERVER_RESUMPTION_LEVEL)Session->Settings.ServerResumptionLevel; + + Status = QUIC_STATUS_SUCCESS; + break; + default: Status = QUIC_STATUS_INVALID_PARAMETER; break; @@ -1095,6 +1114,27 @@ QuicSessionParamSet( break; } + case QUIC_PARAM_SESSION_SERVER_RESUMPTION_LEVEL: { + if (BufferLength != sizeof(QUIC_SERVER_RESUMPTION_LEVEL) || + *(QUIC_SERVER_RESUMPTION_LEVEL*)Buffer > QUIC_SERVER_RESUME_AND_ZERORTT) { + Status = QUIC_STATUS_INVALID_PARAMETER; + break; + } + + Session->Settings.AppSet.ServerResumptionLevel = TRUE; + Session->Settings.ServerResumptionLevel = + *(QUIC_SERVER_RESUMPTION_LEVEL*)Buffer; + + QuicTraceLogInfo( + SessionServerResumptionLevelSet, + "[sess][%p] Updated Server resume/0-RTT to %hhu", + Session, + Session->Settings.ServerResumptionLevel); + + Status = QUIC_STATUS_SUCCESS; + break; + } + default: Status = QUIC_STATUS_INVALID_PARAMETER; break; diff --git a/src/core/settings.c b/src/core/settings.c index 8675c158da..7e3d68ea3d 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -92,6 +92,9 @@ QuicSettingsSetDefault( if (!Settings->AppSet.MaxBytesPerKey) { Settings->MaxBytesPerKey = QUIC_DEFAULT_MAX_BYTES_PER_KEY; } + if (!Settings->AppSet.ServerResumptionLevel) { + Settings->ServerResumptionLevel = QUIC_DEFAULT_SERVER_RESUMPTION_LEVEL; + } } _IRQL_requires_max_(PASSIVE_LEVEL) @@ -176,6 +179,9 @@ QuicSettingsCopy( if (!Settings->AppSet.MaxBytesPerKey) { Settings->MaxBytesPerKey = ParentSettings->MaxBytesPerKey; } + if (!Settings->AppSet.ServerResumptionLevel) { + Settings->ServerResumptionLevel = ParentSettings->ServerResumptionLevel; + } } _IRQL_requires_max_(PASSIVE_LEVEL) @@ -455,6 +461,19 @@ QuicSettingsLoad( Settings->MaxBytesPerKey = QUIC_DEFAULT_MAX_BYTES_PER_KEY; } } + + if (!Settings->AppSet.ServerResumptionLevel) { + ValueLen = sizeof(Value); + QuicStorageReadValue( + Storage, + QUIC_SETTING_SERVER_RESUMPTION_OR_ZERORTT, + (uint8_t*)&Value, + &ValueLen); + if (Value > QUIC_SERVER_RESUME_AND_ZERORTT) { + Value = QUIC_SERVER_RESUME_AND_ZERORTT; + } + Settings->ServerResumptionLevel = (uint8_t)Value; + } } _IRQL_requires_max_(PASSIVE_LEVEL) @@ -488,4 +507,5 @@ QuicSettingsDump( QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); QuicTraceLogVerbose(SettingDumpConnFlowControlWindow, "[sett] ConnFlowControlWindow = %u", Settings->ConnFlowControlWindow); QuicTraceLogVerbose(SettingDumpMaxBytesPerKey, "[sett] MaxBytesPerKey = %llu", Settings->MaxBytesPerKey); + QuicTraceLogVerbose(SettingDumpServerResumptionLevel, "[sett] ServerResumptionLevel = %hhu", Settings->ServerResumptionLevel); } diff --git a/src/core/settings.h b/src/core/settings.h index 5a82c9f6b5..09ed76ed17 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -10,6 +10,7 @@ typedef struct QUIC_SETTINGS { BOOLEAN PacingDefault : 1; BOOLEAN MigrationEnabled : 1; BOOLEAN DatagramReceiveEnabled : 1; + uint8_t ServerResumptionLevel : 2; uint8_t MaxPartitionCount; // Global only uint8_t MaxOperationsPerDrain; // Global only uint16_t RetryMemoryLimit; // Global only @@ -59,6 +60,7 @@ typedef struct QUIC_SETTINGS { BOOLEAN StreamRecvBufferDefault : 1; BOOLEAN ConnFlowControlWindow : 1; BOOLEAN MaxBytesPerKey : 1; + BOOLEAN ServerResumptionLevel : 1; } AppSet; } QUIC_SETTINGS; diff --git a/src/inc/msquic.h b/src/inc/msquic.h index d3d607b1b8..9632af38c3 100644 --- a/src/inc/msquic.h +++ b/src/inc/msquic.h @@ -328,6 +328,12 @@ typedef enum QUIC_PARAM_LEVEL { QUIC_PARAM_LEVEL_STREAM } QUIC_PARAM_LEVEL; +typedef enum QUIC_SERVER_RESUMPTION_LEVEL { + QUIC_SERVER_NO_RESUME, + QUIC_SERVER_RESUME_ONLY, + QUIC_SERVER_RESUME_AND_ZERORTT +} QUIC_SERVER_RESUMPTION_LEVEL; + // // Parameters for QUIC_PARAM_LEVEL_GLOBAL. // @@ -351,6 +357,7 @@ typedef enum QUIC_PARAM_LEVEL { #define QUIC_PARAM_SESSION_MAX_BYTES_PER_KEY 5 // uint64_t - bytes #define QUIC_PARAM_SESSION_MIGRATION_ENABLED 6 // uint8_t (BOOLEAN) #define QUIC_PARAM_SESSION_DATAGRAM_RECEIVE_ENABLED 7 // uint8_t (BOOLEAN) +#define QUIC_PARAM_SESSION_SERVER_RESUMPTION_LEVEL 8 // QUIC_SERVER_RESUMPTION_LEVEL // // Parameters for QUIC_PARAM_LEVEL_LISTENER.