include the maximum payload size in the DatagramTooLargeError (#4470)

This is more useful than the maximum frame size. The user of the library
shouldn't have to care about the QUIC framing layer.

---------

Co-authored-by: 世界 <i@sekai.icu>
This commit is contained in:
Marten Seemann
2024-04-27 14:54:16 +02:00
committed by GitHub
parent 34f4d1443f
commit c0250ce824
4 changed files with 39 additions and 6 deletions

View File

@@ -2358,10 +2358,9 @@ func (s *connection) SendDatagram(p []byte) error {
}
f := &wire.DatagramFrame{DataLenPresent: true}
if protocol.ByteCount(len(p)) > f.MaxDataLen(s.peerParams.MaxDatagramFrameSize, s.version) {
return &DatagramTooLargeError{
PeerMaxDatagramFrameSize: int64(s.peerParams.MaxDatagramFrameSize),
}
maxDataLen := f.MaxDataLen(s.peerParams.MaxDatagramFrameSize, s.version)
if protocol.ByteCount(len(p)) > maxDataLen {
return &DatagramTooLargeError{MaxDatagramPayloadSize: int64(maxDataLen)}
}
f.Data = make([]byte, len(p))
copy(f.Data, p)

View File

@@ -2477,6 +2477,40 @@ var _ = Describe("Connection", func() {
})
})
Context("datagrams", func() {
It("doesn't allow datagrams if the peer didn't enable support", func() {
conn.peerParams = &wire.TransportParameters{MaxDatagramFrameSize: 0}
Expect(conn.SendDatagram(make([]byte, 200))).To(MatchError("datagram support disabled"))
})
It("sends a datagram", func() {
conn.peerParams = &wire.TransportParameters{MaxDatagramFrameSize: 1000}
Expect(conn.SendDatagram([]byte("foobar"))).To(Succeed())
f := conn.datagramQueue.Peek()
Expect(f).ToNot(BeNil())
Expect(f.Data).To(Equal([]byte("foobar")))
})
It("says when a datagram is too big", func() {
conn.peerParams = &wire.TransportParameters{MaxDatagramFrameSize: 1000}
err := conn.SendDatagram(make([]byte, 2000))
Expect(err).To(HaveOccurred())
Expect(err).To(BeAssignableToTypeOf(&DatagramTooLargeError{}))
derr := err.(*DatagramTooLargeError)
Expect(derr.MaxDatagramPayloadSize).To(BeNumerically("<", 1000))
fmt.Println(derr.MaxDatagramPayloadSize)
Expect(conn.SendDatagram(make([]byte, derr.MaxDatagramPayloadSize))).To(Succeed())
})
It("receives datagrams", func() {
conn.config.EnableDatagrams = true
conn.datagramQueue.HandleDatagramFrame(&wire.DatagramFrame{Data: []byte("foobar")})
data, err := conn.ReceiveDatagram(context.Background())
Expect(err).ToNot(HaveOccurred())
Expect(data).To(Equal([]byte("foobar")))
})
})
It("returns the local address", func() {
Expect(conn.LocalAddr()).To(Equal(localAddr))
})

View File

@@ -64,7 +64,7 @@ func (e *StreamError) Error() string {
// DatagramTooLargeError is returned from Connection.SendDatagram if the payload is too large to be sent.
type DatagramTooLargeError struct {
PeerMaxDatagramFrameSize int64
MaxDatagramPayloadSize int64
}
func (e *DatagramTooLargeError) Is(target error) bool {

View File

@@ -64,7 +64,7 @@ var _ = Describe("Datagram test", func() {
maxDatagramMessageSize := f.MaxDataLen(maxDatagramSize, conn.ConnectionState().Version)
b := make([]byte, maxDatagramMessageSize+1)
Expect(conn.SendDatagram(b)).To(MatchError(&quic.DatagramTooLargeError{
PeerMaxDatagramFrameSize: int64(maxDatagramMessageSize),
MaxDatagramPayloadSize: int64(maxDatagramMessageSize),
}))
wg.Wait()
}