Repository: quic-go/quic-go
Pull request #4789 (2024-12-23 08:24:35)

trace dropping of packets by the Transport when no server is set

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/quic-go/quic-go/pull/4789?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 83.93%. Comparing base [(`b493c5d`)](https://app.codecov.io/gh/quic-go/quic-go/commit/b493c5d827cda015e603c692168e6acf4103512c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) to head [(`52e1205`)](https://app.codecov.io/gh/quic-go/quic-go/commit/52e120540b7ba8d5d9b0b2949bba496f92a9bcac?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).

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


```diff
@@            Coverage Diff             @@
##           master    #4789      +/-   ##
==========================================
- Coverage   83.96%   83.93%   -0.03%     
==========================================
  Files         149      146       -3     
  Lines       16056    15714     -342     
==========================================
- Hits        13481    13189     -292     
+ Misses       2046     2015      -31     
+ Partials      529      510      -19     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/quic-go/quic-go/pull/4789?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/transport.go b/transport.go
index f9518beb..9f9327f5 100644
--- a/transport.go
+++ b/transport.go
@@ -438,6 +438,10 @@ func (t *Transport) handlePacket(p receivedPacket) {
 	defer t.mutex.Unlock()
 	if t.server == nil { // no server set
 		t.logger.Debugf("received a packet with an unexpected connection ID %s", connID)
+		if t.Tracer != nil && t.Tracer.DroppedPacket != nil {
+			t.Tracer.DroppedPacket(p.remoteAddr, logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropUnknownConnectionID)
+		}
+		p.buffer.MaybeRelease()
 		return
 	}
 	t.server.handlePacket(p)


Test patch:
diff --git a/transport_test.go b/transport_test.go
index 33a60b32..fcea40a3 100644
--- a/transport_test.go
+++ b/transport_test.go
@@ -286,16 +286,57 @@ func TestTransportDropsUnparseableQUICPackets(t *testing.T) {
 	}
 }
 
-func TestTransportSingleListener(t *testing.T) {
-	tr := &Transport{Conn: newUPDConnLocalhost(t)}
+func TestTransportListening(t *testing.T) {
+	mockTracer, tracer := mocklogging.NewMockTracer(gomock.NewController(t))
+	tr := &Transport{
+		Conn:               newUPDConnLocalhost(t),
+		ConnectionIDLength: 5,
+		Tracer:             mockTracer,
+	}
 	require.NoError(t, tr.init(true))
-	defer tr.Close()
+	defer func() {
+		tracer.EXPECT().Close()
+		tr.Close()
+	}()
 
-	// TODO(#4779): test that packets are dropped if no listener is set
+	conn := newUPDConnLocalhost(t)
+	data := wire.ComposeVersionNegotiation([]byte{1, 2, 3, 4, 5}, []byte{6, 7, 8, 9, 10}, []protocol.Version{protocol.Version1})
+	dropped := make(chan struct{}, 10)
+	tracer.EXPECT().DroppedPacket(conn.LocalAddr(), logging.PacketTypeNotDetermined, protocol.ByteCount(len(data)), logging.PacketDropUnknownConnectionID).Do(
+		func(net.Addr, logging.PacketType, protocol.ByteCount, logging.PacketDropReason) {
+			dropped <- struct{}{}
+		},
+	)
+
+	_, err := conn.WriteTo(data, tr.Conn.LocalAddr())
+	require.NoError(t, err)
+	select {
+	case <-dropped:
+	case <-time.After(time.Second):
+		t.Fatal("timeout")
+	}
 
 	ln, err := tr.Listen(&tls.Config{}, nil)
 	require.NoError(t, err)
 
+	// send the packet again
+	lnDropped := make(chan struct{}, 10)
+	tracer.EXPECT().DroppedPacket(conn.LocalAddr(), logging.PacketTypeVersionNegotiation, protocol.ByteCount(len(data)), logging.PacketDropUnexpectedPacket).Do(
+		func(net.Addr, logging.PacketType, protocol.ByteCount, logging.PacketDropReason) {
+			lnDropped <- struct{}{}
+		},
+	)
+
+	_, err = conn.WriteTo(data, tr.Conn.LocalAddr())
+	require.NoError(t, err)
+	select {
+	case <-lnDropped:
+	case <-dropped:
+		t.Fatal("packet should have been handled by the listener")
+	case <-time.After(time.Second):
+		t.Fatal("timeout")
+	}
+
 	// only a single listener can be set
 	_, err = tr.Listen(&tls.Config{}, nil)
 	require.Error(t, err)