Repository: libp2p/go-libp2p
Pull request #3054 (2024-11-21 00:13:07)

chore(dashboard/alertmanager): update api version from v1 to v2
The error message was:
Error loading config (--config.file=/etc/prometheus/prometheus.yml): expected Alertmanager API version to be one of [v2] but got v1

MarcoPolo: Our config is still valid with just this version change? 
cpeliciari: Just changing this functioning normally. I thought of fixing the version of prometheus and grafana. But I see no need
cpeliciari: Currently in the version, when you try to run the compose of the Prometheus initialization failure, it only reports the version.

Patch:
diff --git a/dashboards/prometheus.yml b/dashboards/prometheus.yml
index f0917188..89534d55 100644
--- a/dashboards/prometheus.yml
+++ b/dashboards/prometheus.yml
@@ -6,7 +6,7 @@ alerting:
   alertmanagers:
   - scheme: http
     timeout: 10s
-    api_version: v1
+    api_version: v2
     static_configs:
     - targets: []
 scrape_configs:
diff --git a/p2p/transport/tcpreuse/demultiplex.go b/p2p/transport/tcpreuse/demultiplex.go
index fe58243d..f9175ecf 100644
--- a/p2p/transport/tcpreuse/demultiplex.go
+++ b/p2p/transport/tcpreuse/demultiplex.go
@@ -9,8 +9,11 @@ import (
 	manet "github.com/multiformats/go-multiaddr/net"
 )
 
-// This is readiung the first 3 bytes of the packet. It should be instant.
-const identifyConnTimeout = 1 * time.Second
+// This is reading the first 3 bytes of the first packet after the handshake.
+// It's set to the default TCP connect timeout in the TCP Transport.
+//
+// A var so we can change it in tests.
+var identifyConnTimeout = 5 * time.Second
 
 type DemultiplexedConnType int
 
@@ -40,35 +43,35 @@ func (t DemultiplexedConnType) IsKnown() bool {
 
 // identifyConnType attempts to identify the connection type by peeking at the
 // first few bytes.
-// It Callers must not use the passed in Conn after this
-// function returns. if an error is returned, the connection will be closed.
+// Its Callers must not use the passed in Conn after this function returns.
+// If an error is returned, the connection will be closed.
 func identifyConnType(c manet.Conn) (DemultiplexedConnType, manet.Conn, error) {
 	if err := c.SetReadDeadline(time.Now().Add(identifyConnTimeout)); err != nil {
 		closeErr := c.Close()
 		return 0, nil, errors.Join(err, closeErr)
 	}
 
-	s, c, err := sampledconn.PeekBytes(c)
+	s, peekedConn, err := sampledconn.PeekBytes(c)
 	if err != nil {
 		closeErr := c.Close()
 		return 0, nil, errors.Join(err, closeErr)
 	}
 
-	if err := c.SetReadDeadline(time.Time{}); err != nil {
-		closeErr := c.Close()
+	if err := peekedConn.SetReadDeadline(time.Time{}); err != nil {
+		closeErr := peekedConn.Close()
 		return 0, nil, errors.Join(err, closeErr)
 	}
 
 	if IsMultistreamSelect(s) {
-		return DemultiplexedConnType_MultistreamSelect, c, nil
+		return DemultiplexedConnType_MultistreamSelect, peekedConn, nil
 	}
 	if IsTLS(s) {
-		return DemultiplexedConnType_TLS, c, nil
+		return DemultiplexedConnType_TLS, peekedConn, nil
 	}
 	if IsHTTP(s) {
-		return DemultiplexedConnType_HTTP, c, nil
+		return DemultiplexedConnType_HTTP, peekedConn, nil
 	}
-	return DemultiplexedConnType_Unknown, c, nil
+	return DemultiplexedConnType_Unknown, peekedConn, nil
 }
 
 // Matchers are implemented here instead of in the transports so we can easily fuzz them together.
diff --git a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_other.go b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_other.go
index 73861123..5197052f 100644
--- a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_other.go
+++ b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_other.go
@@ -1,4 +1,4 @@
-//go:build !unix && !windows
+//go:build !unix
 
 package sampledconn
 
diff --git a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_windows.go b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_windows.go
deleted file mode 100644
index 46b06179..00000000
--- a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_windows.go
+++ /dev/null
@@ -1,49 +0,0 @@
-//go:build windows
-
-package sampledconn
-
-import (
-	"errors"
-	"golang.org/x/sys/windows"
-	"syscall"
-)
-
-func OSPeekConn(conn syscall.Conn) (PeekedBytes, error) {
-	s := PeekedBytes{}
-
-	rawConn, err := conn.SyscallConn()
-	if err != nil {
-		return s, err
-	}
-
-	readBytes := 0
-	var readErr error
-	err = rawConn.Read(func(fd uintptr) bool {
-		for readBytes < peekSize {
-			var n uint32
-			flags := uint32(windows.MSG_PEEK)
-			wsabuf := windows.WSABuf{
-				Len: uint32(len(s) - readBytes),
-				Buf: &s[readBytes],
-			}
-
-			readErr = windows.WSARecv(windows.Handle(fd), &wsabuf, 1, &n, &flags, nil, nil)
-			if errors.Is(readErr, windows.WSAEWOULDBLOCK) {
-				return false
-			}
-			if readErr != nil {
-				return true
-			}
-			readBytes += int(n)
-		}
-		return true
-	})
-	if readErr != nil {
-		return s, readErr
-	}
-	if err != nil {
-		return s, err
-	}
-
-	return s, nil
-}
diff --git a/p2p/transport/tcpreuse/listener.go b/p2p/transport/tcpreuse/listener.go
index 326e1e15..d94186e7 100644
--- a/p2p/transport/tcpreuse/listener.go
+++ b/p2p/transport/tcpreuse/listener.go
@@ -231,8 +231,6 @@ func (m *multiplexedListener) run() error {
 			t, c, err := identifyConnType(c)
 			if err != nil {
 				connScope.Done()
-				closeErr := c.Close()
-				err = errors.Join(err, closeErr)
 				log.Debugf("error demultiplexing connection: %s", err.Error())
 				return
 			}


Test patch:
diff --git a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go
index a7c5a65f..d5b31009 100644
--- a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go
+++ b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go
@@ -58,7 +58,7 @@ func TestSampledConn(t *testing.T) {
 				assert.Equal(t, "hel", string(peeked[:]))
 
 				buf := make([]byte, 5)
-				_, err = clientConn.Read(buf)
+				_, err = io.ReadFull(clientConn, buf)
 				assert.NoError(t, err)
 				assert.Equal(t, "hello", string(buf))
 			} else {
diff --git a/p2p/transport/tcpreuse/listener_test.go b/p2p/transport/tcpreuse/listener_test.go
index bdb030a6..b5dc49f2 100644
--- a/p2p/transport/tcpreuse/listener_test.go
+++ b/p2p/transport/tcpreuse/listener_test.go
@@ -447,3 +447,30 @@ func TestListenerClose(t *testing.T) {
 		testClose(listenAddr)
 	}
 }
+
+func setDeferReset[T any](t testing.TB, ptr *T, val T) {
+	t.Helper()
+	orig := *ptr
+	*ptr = val
+	t.Cleanup(func() { *ptr = orig })
+}
+
+// TestHitTimeout asserts that we don't panic in case we fail to peek at the connection.
+func TestHitTimeout(t *testing.T) {
+	setDeferReset(t, &identifyConnTimeout, 100*time.Millisecond)
+	// listen on port 0
+	cm := NewConnMgr(false, nil, nil)
+
+	listenAddr := ma.StringCast("/ip4/127.0.0.1/tcp/0")
+	ml, err := cm.DemultiplexedListen(listenAddr, DemultiplexedConnType_MultistreamSelect)
+	require.NoError(t, err)
+	defer ml.Close()
+
+	tcpConn, err := net.Dial(ml.Addr().Network(), ml.Addr().String())
+	require.NoError(t, err)
+
+	// Stall tcp conn for over the timeout.
+	time.Sleep(identifyConnTimeout + 100*time.Millisecond)
+
+	tcpConn.Close()
+}