forked from quic-go/quic-go
We're not sending the initial_max_stream_id_uni parameter, which implicitely sets this value to 0, i.e. the peer is not allowed to open unidirectional streams.
249 lines
9.9 KiB
Go
249 lines
9.9 KiB
Go
package handshake
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Transport Parameters", func() {
|
|
Context("for gQUIC", func() {
|
|
Context("parsing", func() {
|
|
It("sets all values", func() {
|
|
values := map[Tag][]byte{
|
|
TagSFCW: {0xad, 0xfb, 0xca, 0xde},
|
|
TagCFCW: {0xef, 0xbe, 0xad, 0xde},
|
|
TagICSL: {0x0d, 0xf0, 0xad, 0xba},
|
|
TagMIDS: {0xff, 0x10, 0x00, 0xc0},
|
|
}
|
|
params, err := readHelloMap(values)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(params.StreamFlowControlWindow).To(Equal(protocol.ByteCount(0xdecafbad)))
|
|
Expect(params.ConnectionFlowControlWindow).To(Equal(protocol.ByteCount(0xdeadbeef)))
|
|
Expect(params.IdleTimeout).To(Equal(time.Duration(0xbaadf00d) * time.Second))
|
|
Expect(params.MaxStreams).To(Equal(uint32(0xc00010ff)))
|
|
Expect(params.OmitConnectionID).To(BeFalse())
|
|
})
|
|
|
|
It("reads if the connection ID should be omitted", func() {
|
|
values := map[Tag][]byte{TagTCID: {0, 0, 0, 0}}
|
|
params, err := readHelloMap(values)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(params.OmitConnectionID).To(BeTrue())
|
|
})
|
|
|
|
It("doesn't allow idle timeouts below the minimum remote idle timeout", func() {
|
|
t := 2 * time.Second
|
|
Expect(t).To(BeNumerically("<", protocol.MinRemoteIdleTimeout))
|
|
values := map[Tag][]byte{
|
|
TagICSL: {uint8(t.Seconds()), 0, 0, 0},
|
|
}
|
|
params, err := readHelloMap(values)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(params.IdleTimeout).To(Equal(protocol.MinRemoteIdleTimeout))
|
|
})
|
|
|
|
It("errors when given an invalid SFCW value", func() {
|
|
values := map[Tag][]byte{TagSFCW: {2, 0, 0}} // 1 byte too short
|
|
_, err := readHelloMap(values)
|
|
Expect(err).To(MatchError(errMalformedTag))
|
|
})
|
|
|
|
It("errors when given an invalid CFCW value", func() {
|
|
values := map[Tag][]byte{TagCFCW: {2, 0, 0}} // 1 byte too short
|
|
_, err := readHelloMap(values)
|
|
Expect(err).To(MatchError(errMalformedTag))
|
|
})
|
|
|
|
It("errors when given an invalid TCID value", func() {
|
|
values := map[Tag][]byte{TagTCID: {2, 0, 0}} // 1 byte too short
|
|
_, err := readHelloMap(values)
|
|
Expect(err).To(MatchError(errMalformedTag))
|
|
})
|
|
|
|
It("errors when given an invalid ICSL value", func() {
|
|
values := map[Tag][]byte{TagICSL: {2, 0, 0}} // 1 byte too short
|
|
_, err := readHelloMap(values)
|
|
Expect(err).To(MatchError(errMalformedTag))
|
|
})
|
|
|
|
It("errors when given an invalid MIDS value", func() {
|
|
values := map[Tag][]byte{TagMIDS: {2, 0, 0}} // 1 byte too short
|
|
_, err := readHelloMap(values)
|
|
Expect(err).To(MatchError(errMalformedTag))
|
|
})
|
|
})
|
|
|
|
Context("writing", func() {
|
|
It("returns all necessary parameters ", func() {
|
|
params := &TransportParameters{
|
|
StreamFlowControlWindow: 0xdeadbeef,
|
|
ConnectionFlowControlWindow: 0xdecafbad,
|
|
IdleTimeout: 0xbaaaaaad * time.Second,
|
|
MaxStreams: 0x1337,
|
|
}
|
|
entryMap := params.getHelloMap()
|
|
Expect(entryMap).To(HaveLen(4))
|
|
Expect(entryMap).ToNot(HaveKey(TagTCID))
|
|
Expect(entryMap).To(HaveKeyWithValue(TagSFCW, []byte{0xef, 0xbe, 0xad, 0xde}))
|
|
Expect(entryMap).To(HaveKeyWithValue(TagCFCW, []byte{0xad, 0xfb, 0xca, 0xde}))
|
|
Expect(entryMap).To(HaveKeyWithValue(TagICSL, []byte{0xad, 0xaa, 0xaa, 0xba}))
|
|
Expect(entryMap).To(HaveKeyWithValue(TagMIDS, []byte{0x37, 0x13, 0, 0}))
|
|
})
|
|
|
|
It("requests omission of the connection ID", func() {
|
|
params := &TransportParameters{OmitConnectionID: true}
|
|
entryMap := params.getHelloMap()
|
|
Expect(entryMap).To(HaveKeyWithValue(TagTCID, []byte{0, 0, 0, 0}))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("for TLS", func() {
|
|
paramsMapToList := func(p map[transportParameterID][]byte) []transportParameter {
|
|
var list []transportParameter
|
|
for id, val := range p {
|
|
list = append(list, transportParameter{id, val})
|
|
}
|
|
return list
|
|
}
|
|
|
|
Context("parsing", func() {
|
|
var parameters map[transportParameterID][]byte
|
|
|
|
BeforeEach(func() {
|
|
parameters = map[transportParameterID][]byte{
|
|
initialMaxStreamDataParameterID: []byte{0x11, 0x22, 0x33, 0x44},
|
|
initialMaxDataParameterID: []byte{0x22, 0x33, 0x44, 0x55},
|
|
initialMaxStreamIDBiDiParameterID: []byte{0x33, 0x44, 0x55, 0x66},
|
|
initialMaxStreamIDUniParameterID: []byte{0x44, 0x55, 0x66, 0x77},
|
|
idleTimeoutParameterID: []byte{0x13, 0x37},
|
|
}
|
|
})
|
|
It("reads parameters", func() {
|
|
params, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(params.StreamFlowControlWindow).To(Equal(protocol.ByteCount(0x11223344)))
|
|
Expect(params.ConnectionFlowControlWindow).To(Equal(protocol.ByteCount(0x22334455)))
|
|
Expect(params.IdleTimeout).To(Equal(0x1337 * time.Second))
|
|
Expect(params.OmitConnectionID).To(BeFalse())
|
|
})
|
|
|
|
It("saves if it should omit the connection ID", func() {
|
|
parameters[omitConnectionIDParameterID] = []byte{}
|
|
params, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(params.OmitConnectionID).To(BeTrue())
|
|
})
|
|
|
|
It("rejects the parameters if the initial_max_stream_data is missing", func() {
|
|
delete(parameters, initialMaxStreamDataParameterID)
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("missing parameter"))
|
|
})
|
|
|
|
It("rejects the parameters if the initial_max_data is missing", func() {
|
|
delete(parameters, initialMaxDataParameterID)
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("missing parameter"))
|
|
})
|
|
|
|
It("rejects the parameters if the idle_timeout is missing", func() {
|
|
delete(parameters, idleTimeoutParameterID)
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("missing parameter"))
|
|
})
|
|
|
|
It("doesn't allow values below the minimum remote idle timeout", func() {
|
|
t := 2 * time.Second
|
|
Expect(t).To(BeNumerically("<", protocol.MinRemoteIdleTimeout))
|
|
parameters[idleTimeoutParameterID] = []byte{0, uint8(t.Seconds())}
|
|
params, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(params.IdleTimeout).To(Equal(protocol.MinRemoteIdleTimeout))
|
|
})
|
|
|
|
It("rejects the parameters if the initial_max_stream_data has the wrong length", func() {
|
|
parameters[initialMaxStreamDataParameterID] = []byte{0x11, 0x22, 0x33} // should be 4 bytes
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("wrong length for initial_max_stream_data: 3 (expected 4)"))
|
|
})
|
|
|
|
It("rejects the parameters if the initial_max_data has the wrong length", func() {
|
|
parameters[initialMaxDataParameterID] = []byte{0x11, 0x22, 0x33} // should be 4 bytes
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("wrong length for initial_max_data: 3 (expected 4)"))
|
|
})
|
|
|
|
It("rejects the parameters if the initial_max_stream_id_bidi has the wrong length", func() {
|
|
parameters[initialMaxStreamIDBiDiParameterID] = []byte{0x11, 0x22, 0x33, 0x44, 0x55} // should be 4 bytes
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("wrong length for initial_max_stream_id_bidi: 5 (expected 4)"))
|
|
})
|
|
|
|
It("rejects the parameters if the initial_max_stream_id_bidi has the wrong length", func() {
|
|
parameters[initialMaxStreamIDUniParameterID] = []byte{0x11, 0x22, 0x33, 0x44, 0x55} // should be 4 bytes
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("wrong length for initial_max_stream_id_uni: 5 (expected 4)"))
|
|
})
|
|
|
|
It("rejects the parameters if the initial_idle_timeout has the wrong length", func() {
|
|
parameters[idleTimeoutParameterID] = []byte{0x11, 0x22, 0x33} // should be 2 bytes
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("wrong length for idle_timeout: 3 (expected 2)"))
|
|
})
|
|
|
|
It("rejects the parameters if omit_connection_id is non-empty", func() {
|
|
parameters[omitConnectionIDParameterID] = []byte{0} // should be empty
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).To(MatchError("wrong length for omit_connection_id: 1 (expected empty)"))
|
|
})
|
|
|
|
It("ignores unknown parameters", func() {
|
|
parameters[1337] = []byte{42}
|
|
_, err := readTransportParamters(paramsMapToList(parameters))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
})
|
|
|
|
Context("writing", func() {
|
|
var params *TransportParameters
|
|
|
|
paramsListToMap := func(l []transportParameter) map[transportParameterID][]byte {
|
|
p := make(map[transportParameterID][]byte)
|
|
for _, v := range l {
|
|
p[v.Parameter] = v.Value
|
|
}
|
|
return p
|
|
}
|
|
|
|
BeforeEach(func() {
|
|
params = &TransportParameters{
|
|
StreamFlowControlWindow: 0xdeadbeef,
|
|
ConnectionFlowControlWindow: 0xdecafbad,
|
|
IdleTimeout: 0xcafe * time.Second,
|
|
}
|
|
})
|
|
|
|
It("creates the parameters list", func() {
|
|
values := paramsListToMap(params.getTransportParameters())
|
|
Expect(values).To(HaveLen(5))
|
|
Expect(values).To(HaveKeyWithValue(initialMaxStreamDataParameterID, []byte{0xde, 0xad, 0xbe, 0xef}))
|
|
Expect(values).To(HaveKeyWithValue(initialMaxDataParameterID, []byte{0xde, 0xca, 0xfb, 0xad}))
|
|
Expect(values).To(HaveKeyWithValue(initialMaxStreamIDBiDiParameterID, []byte{0xff, 0xff, 0xff, 0xff}))
|
|
Expect(values).To(HaveKeyWithValue(idleTimeoutParameterID, []byte{0xca, 0xfe}))
|
|
Expect(values).To(HaveKeyWithValue(maxPacketSizeParameterID, []byte{0x5, 0xac})) // 1452 = 0x5ac
|
|
Expect(values).ToNot(HaveKey(initialMaxStreamIDUniParameterID))
|
|
})
|
|
|
|
It("request ommision of the connection ID", func() {
|
|
params.OmitConnectionID = true
|
|
values := paramsListToMap(params.getTransportParameters())
|
|
Expect(values).To(HaveKeyWithValue(omitConnectionIDParameterID, []byte{}))
|
|
})
|
|
})
|
|
})
|
|
})
|