forked from quic-go/quic-go
The maximum number of incoming streams doesn't need to be negotiated. It is a value that is only announced by the peer, and has to be respected. Furthermore, Chrome doesn't seem to care about the MSPC value anymore (since MIDS was introduced), so there's no need to send this in the handshake any more.
113 lines
4.2 KiB
Go
113 lines
4.2 KiB
Go
package handshake
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
)
|
|
|
|
// The ParamsNegotiator negotiates and stores the connection parameters.
|
|
// It can be used for a server as well as a client.
|
|
type ParamsNegotiator interface {
|
|
GetSendStreamFlowControlWindow() protocol.ByteCount
|
|
GetSendConnectionFlowControlWindow() protocol.ByteCount
|
|
GetReceiveStreamFlowControlWindow() protocol.ByteCount
|
|
GetReceiveConnectionFlowControlWindow() protocol.ByteCount
|
|
GetMaxOutgoingStreams() uint32
|
|
// get the idle timeout that was sent by the peer
|
|
GetRemoteIdleTimeout() time.Duration
|
|
// determines if the client requests omission of connection IDs.
|
|
OmitConnectionID() bool
|
|
}
|
|
|
|
// For the server:
|
|
// 1. call SetFromMap with the values received in the CHLO. This sets the corresponding values here, subject to negotiation
|
|
// 2. call GetHelloMap to get the values to send in the SHLO
|
|
// For the client:
|
|
// 1. call GetHelloMap to get the values to send in a CHLO
|
|
// 2. call SetFromMap with the values received in the SHLO
|
|
type paramsNegotiatorBase struct {
|
|
mutex sync.RWMutex
|
|
|
|
version protocol.VersionNumber
|
|
perspective protocol.Perspective
|
|
|
|
flowControlNegotiated bool
|
|
|
|
omitConnectionID bool
|
|
requestConnectionIDOmission bool
|
|
|
|
maxIncomingDynamicStreamsPerConnection uint32
|
|
idleTimeout time.Duration
|
|
remoteIdleTimeout time.Duration
|
|
sendStreamFlowControlWindow protocol.ByteCount
|
|
sendConnectionFlowControlWindow protocol.ByteCount
|
|
receiveStreamFlowControlWindow protocol.ByteCount
|
|
receiveConnectionFlowControlWindow protocol.ByteCount
|
|
}
|
|
|
|
func (h *paramsNegotiatorBase) init(params *TransportParameters) {
|
|
h.sendStreamFlowControlWindow = protocol.InitialStreamFlowControlWindow // can only be changed by the client
|
|
h.sendConnectionFlowControlWindow = protocol.InitialConnectionFlowControlWindow // can only be changed by the client
|
|
h.receiveStreamFlowControlWindow = protocol.ReceiveStreamFlowControlWindow
|
|
h.receiveConnectionFlowControlWindow = protocol.ReceiveConnectionFlowControlWindow
|
|
h.requestConnectionIDOmission = params.RequestConnectionIDOmission
|
|
|
|
h.idleTimeout = params.IdleTimeout
|
|
if h.perspective == protocol.PerspectiveServer {
|
|
h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the client's perspective
|
|
} else {
|
|
h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the server's perspective
|
|
}
|
|
}
|
|
|
|
func (h *paramsNegotiatorBase) negotiateMaxIncomingDynamicStreamsPerConnection(clientValue uint32) uint32 {
|
|
return utils.MinUint32(clientValue, protocol.MaxIncomingDynamicStreamsPerConnection)
|
|
}
|
|
|
|
// GetSendStreamFlowControlWindow gets the size of the stream-level flow control window for sending data
|
|
func (h *paramsNegotiatorBase) GetSendStreamFlowControlWindow() protocol.ByteCount {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
return h.sendStreamFlowControlWindow
|
|
}
|
|
|
|
// GetSendConnectionFlowControlWindow gets the size of the stream-level flow control window for sending data
|
|
func (h *paramsNegotiatorBase) GetSendConnectionFlowControlWindow() protocol.ByteCount {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
return h.sendConnectionFlowControlWindow
|
|
}
|
|
|
|
func (h *paramsNegotiatorBase) GetReceiveStreamFlowControlWindow() protocol.ByteCount {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
return h.receiveStreamFlowControlWindow
|
|
}
|
|
|
|
// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
|
|
func (h *paramsNegotiatorBase) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
return h.receiveConnectionFlowControlWindow
|
|
}
|
|
|
|
func (h *paramsNegotiatorBase) GetMaxOutgoingStreams() uint32 {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
|
|
return h.maxIncomingDynamicStreamsPerConnection
|
|
}
|
|
|
|
func (h *paramsNegotiatorBase) setRemoteIdleTimeout(t time.Duration) {
|
|
h.remoteIdleTimeout = utils.MaxDuration(protocol.MinRemoteIdleTimeout, t)
|
|
}
|
|
|
|
func (h *paramsNegotiatorBase) GetRemoteIdleTimeout() time.Duration {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
return h.remoteIdleTimeout
|
|
}
|