Repository: quic-go/quic-go
Pull request #4470 (2024-04-27 12:36:23)

include the maximum payload size in the DatagramTooLargeError
Closes #4436.

This is more useful than the maximum frame size. The user of the library shouldn't have to care about the QUIC framing layer.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/quic-go/quic-go/pull/4470?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 85.72%. Comparing base [(`afd0b06`)](https://app.codecov.io/gh/quic-go/quic-go/commit/afd0b061d5f2b38a6fd73207b08fe556a055f8b2?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) to head [(`7c083c1`)](https://app.codecov.io/gh/quic-go/quic-go/pull/4470?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).
> Report is 23 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4470      +/-   ##
==========================================
+ Coverage   84.74%   85.72%   +0.98%     
==========================================
  Files         152      154       +2     
  Lines       14369    15101     +732     
==========================================
+ Hits        12176    12944     +768     
+ Misses       1691     1662      -29     
+ Partials      502      495       -7     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/quic-go/quic-go/pull/4470?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).


Patch:
diff --git a/connection.go b/connection.go
index 9c8821d9..b1e9aaee 100644
--- a/connection.go
+++ b/connection.go
@@ -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)
diff --git a/errors.go b/errors.go
index fda3c924..3fe1e0a9 100644
--- a/errors.go
+++ b/errors.go
@@ -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 {


Test patch:
diff --git a/connection_test.go b/connection_test.go
index c6d9d24e..7f9468d9 100644
--- a/connection_test.go
+++ b/connection_test.go
@@ -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))
 	})
diff --git a/integrationtests/self/datagram_test.go b/integrationtests/self/datagram_test.go
index f9608272..1b4f0efd 100644
--- a/integrationtests/self/datagram_test.go
+++ b/integrationtests/self/datagram_test.go
@@ -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()
 				}