Repository: libp2p/go-libp2p
Pull request #2753 (2024-03-25 22:10:41)

quic: make server cmd use RFC 9000 instead of draft-29 
Continues from https://github.com/libp2p/go-libp2p/pull/2751. I was not able to push to that branch.

- Does the same as #2751 
- Moves run code to a lib package and runs a test on it.

Closes #2751 


Patch:
diff --git a/p2p/transport/quic/cmd/client/main.go b/p2p/transport/quic/cmd/client/main.go
index 78736253..5736d895 100644
--- a/p2p/transport/quic/cmd/client/main.go
+++ b/p2p/transport/quic/cmd/client/main.go
@@ -1,20 +1,11 @@
 package main
 
 import (
-	"context"
-	"crypto/rand"
 	"fmt"
-	"io"
 	"log"
 	"os"
 
-	ic "github.com/libp2p/go-libp2p/core/crypto"
-	"github.com/libp2p/go-libp2p/core/peer"
-	libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
-	"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
-
-	ma "github.com/multiformats/go-multiaddr"
-	"github.com/quic-go/quic-go"
+	cmdlib "github.com/libp2p/go-libp2p/p2p/transport/quic/cmd/lib"
 )
 
 func main() {
@@ -22,57 +13,7 @@ func main() {
 		fmt.Printf("Usage: %s <multiaddr> <peer id>", os.Args[0])
 		return
 	}
-	if err := run(os.Args[1], os.Args[2]); err != nil {
+	if err := cmdlib.RunClient(os.Args[1], os.Args[2]); err != nil {
 		log.Fatalf(err.Error())
 	}
 }
-
-func run(raddr string, p string) error {
-	peerID, err := peer.Decode(p)
-	if err != nil {
-		return err
-	}
-	addr, err := ma.NewMultiaddr(raddr)
-	if err != nil {
-		return err
-	}
-	priv, _, err := ic.GenerateECDSAKeyPair(rand.Reader)
-	if err != nil {
-		return err
-	}
-
-	reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
-	if err != nil {
-		return err
-	}
-	t, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil)
-	if err != nil {
-		return err
-	}
-
-	log.Printf("Dialing %s\n", addr.String())
-	conn, err := t.Dial(context.Background(), addr, peerID)
-	if err != nil {
-		return err
-	}
-	defer conn.Close()
-	str, err := conn.OpenStream(context.Background())
-	if err != nil {
-		return err
-	}
-	defer str.Close()
-	const msg = "Hello world!"
-	log.Printf("Sending: %s\n", msg)
-	if _, err := str.Write([]byte(msg)); err != nil {
-		return err
-	}
-	if err := str.CloseWrite(); err != nil {
-		return err
-	}
-	data, err := io.ReadAll(str)
-	if err != nil {
-		return err
-	}
-	log.Printf("Received: %s\n", data)
-	return nil
-}
diff --git a/p2p/transport/quic/cmd/lib/lib.go b/p2p/transport/quic/cmd/lib/lib.go
new file mode 100644
index 00000000..fd2a270a
--- /dev/null
+++ b/p2p/transport/quic/cmd/lib/lib.go
@@ -0,0 +1,129 @@
+package cmdlib
+
+import (
+	"context"
+	"crypto/rand"
+	"fmt"
+	"io"
+	"log"
+
+	ic "github.com/libp2p/go-libp2p/core/crypto"
+	"github.com/libp2p/go-libp2p/core/peer"
+	tpt "github.com/libp2p/go-libp2p/core/transport"
+	libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
+	"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
+
+	ma "github.com/multiformats/go-multiaddr"
+	"github.com/quic-go/quic-go"
+)
+
+func RunClient(raddr string, p string) error {
+	peerID, err := peer.Decode(p)
+	if err != nil {
+		return err
+	}
+	addr, err := ma.NewMultiaddr(raddr)
+	if err != nil {
+		return err
+	}
+	priv, _, err := ic.GenerateECDSAKeyPair(rand.Reader)
+	if err != nil {
+		return err
+	}
+
+	reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
+	if err != nil {
+		return err
+	}
+	t, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil)
+	if err != nil {
+		return err
+	}
+
+	log.Printf("Dialing %s\n", addr.String())
+	conn, err := t.Dial(context.Background(), addr, peerID)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+	str, err := conn.OpenStream(context.Background())
+	if err != nil {
+		return err
+	}
+	defer str.Close()
+	const msg = "Hello world!"
+	log.Printf("Sending: %s\n", msg)
+	if _, err := str.Write([]byte(msg)); err != nil {
+		return err
+	}
+	if err := str.CloseWrite(); err != nil {
+		return err
+	}
+	data, err := io.ReadAll(str)
+	if err != nil {
+		return err
+	}
+	log.Printf("Received: %s\n", data)
+	return nil
+}
+
+func RunServer(port string, location chan peer.AddrInfo) error {
+	addr, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/udp/%s/quic-v1", port))
+	if err != nil {
+		return err
+	}
+	priv, _, err := ic.GenerateECDSAKeyPair(rand.Reader)
+	if err != nil {
+		return err
+	}
+	peerID, err := peer.IDFromPrivateKey(priv)
+	if err != nil {
+		return err
+	}
+
+	reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
+	if err != nil {
+		return err
+	}
+	t, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil)
+	if err != nil {
+		return err
+	}
+
+	ln, err := t.Listen(addr)
+	if err != nil {
+		return err
+	}
+	fmt.Printf("Listening. Now run: go run cmd/client/main.go %s %s\n", ln.Multiaddr(), peerID)
+	if location != nil {
+		location <- peer.AddrInfo{ID: peerID, Addrs: []ma.Multiaddr{ln.Multiaddr()}}
+	}
+	for {
+		conn, err := ln.Accept()
+		if err != nil {
+			return err
+		}
+		log.Printf("Accepted new connection from %s (%s)\n", conn.RemotePeer(), conn.RemoteMultiaddr())
+		go func() {
+			if err := handleConn(conn); err != nil {
+				log.Printf("handling conn failed: %s", err.Error())
+			}
+		}()
+	}
+}
+
+func handleConn(conn tpt.CapableConn) error {
+	str, err := conn.AcceptStream()
+	if err != nil {
+		return err
+	}
+	data, err := io.ReadAll(str)
+	if err != nil {
+		return err
+	}
+	log.Printf("Received: %s\n", data)
+	if _, err := str.Write(data); err != nil {
+		return err
+	}
+	return str.Close()
+}
diff --git a/p2p/transport/quic/cmd/server/main.go b/p2p/transport/quic/cmd/server/main.go
index 222841d4..ef3f90a4 100644
--- a/p2p/transport/quic/cmd/server/main.go
+++ b/p2p/transport/quic/cmd/server/main.go
@@ -1,20 +1,11 @@
 package main
 
 import (
-	"crypto/rand"
 	"fmt"
-	"io"
 	"log"
 	"os"
 
-	ic "github.com/libp2p/go-libp2p/core/crypto"
-	"github.com/libp2p/go-libp2p/core/peer"
-	tpt "github.com/libp2p/go-libp2p/core/transport"
-	libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
-	"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
-
-	ma "github.com/multiformats/go-multiaddr"
-	"github.com/quic-go/quic-go"
+	cmdlib "github.com/libp2p/go-libp2p/p2p/transport/quic/cmd/lib"
 )
 
 func main() {
@@ -22,65 +13,7 @@ func main() {
 		fmt.Printf("Usage: %s <port>", os.Args[0])
 		return
 	}
-	if err := run(os.Args[1]); err != nil {
+	if err := cmdlib.RunServer(os.Args[1], nil); err != nil {
 		log.Fatalf(err.Error())
 	}
 }
-
-func run(port string) error {
-	addr, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/udp/%s/quic", port))
-	if err != nil {
-		return err
-	}
-	priv, _, err := ic.GenerateECDSAKeyPair(rand.Reader)
-	if err != nil {
-		return err
-	}
-	peerID, err := peer.IDFromPrivateKey(priv)
-	if err != nil {
-		return err
-	}
-
-	reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
-	if err != nil {
-		return err
-	}
-	t, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil)
-	if err != nil {
-		return err
-	}
-
-	ln, err := t.Listen(addr)
-	if err != nil {
-		return err
-	}
-	fmt.Printf("Listening. Now run: go run cmd/client/main.go %s %s\n", ln.Multiaddr(), peerID)
-	for {
-		conn, err := ln.Accept()
-		if err != nil {
-			return err
-		}
-		log.Printf("Accepted new connection from %s (%s)\n", conn.RemotePeer(), conn.RemoteMultiaddr())
-		go func() {
-			if err := handleConn(conn); err != nil {
-				log.Printf("handling conn failed: %s", err.Error())
-			}
-		}()
-	}
-}
-
-func handleConn(conn tpt.CapableConn) error {
-	str, err := conn.AcceptStream()
-	if err != nil {
-		return err
-	}
-	data, err := io.ReadAll(str)
-	if err != nil {
-		return err
-	}
-	log.Printf("Received: %s\n", data)
-	if _, err := str.Write(data); err != nil {
-		return err
-	}
-	return str.Close()
-}


Test patch:
diff --git a/p2p/http/example_test.go b/p2p/http/example_test.go
index 719badea..2e90f8cc 100644
--- a/p2p/http/example_test.go
+++ b/p2p/http/example_test.go
@@ -57,7 +57,7 @@ func ExampleHost_withAStockGoHTTPClient() {
 }
 
 func ExampleHost_listenOnHTTPTransportAndStreams() {
-	serverStreamHost, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/50124/quic-v1"))
+	serverStreamHost, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"))
 	if err != nil {
 		log.Fatal(err)
 	}
@@ -65,14 +65,18 @@ func ExampleHost_listenOnHTTPTransportAndStreams() {
 
 	server := libp2phttp.Host{
 		InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
-		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50124/http")},
+		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
 		StreamHost:        serverStreamHost,
 	}
 	go server.Serve()
 	defer server.Close()
 
-	fmt.Println("Server listening on:", server.Addrs())
-	// Output: Server listening on: [/ip4/127.0.0.1/udp/50124/quic-v1 /ip4/127.0.0.1/tcp/50124/http]
+	for _, a := range server.Addrs() {
+		_, transport := ma.SplitLast(a)
+		fmt.Printf("Server listening on transport: %s\n", transport)
+	}
+	// Output: Server listening on transport: /quic-v1
+	// Server listening on transport: /http
 }
 
 func ExampleHost_overLibp2pStreams() {
diff --git a/p2p/transport/quic/cmd/lib/lib_test.go b/p2p/transport/quic/cmd/lib/lib_test.go
new file mode 100644
index 00000000..1058b078
--- /dev/null
+++ b/p2p/transport/quic/cmd/lib/lib_test.go
@@ -0,0 +1,30 @@
+package cmdlib
+
+import (
+	"testing"
+
+	"github.com/libp2p/go-libp2p/core/peer"
+	"github.com/multiformats/go-multiaddr"
+)
+
+func TestCmd(t *testing.T) {
+	serverLocation := make(chan peer.AddrInfo)
+	go RunServer("0", serverLocation)
+
+	l := <-serverLocation
+
+	ip, rest := multiaddr.SplitFirst(l.Addrs[0])
+	if ip.Protocol().Code == multiaddr.P_IP4 && ip.Value() == "0.0.0.0" {
+		// Windows can't dial to 0.0.0.0 so replace with localhost
+		var err error
+		ip, err = multiaddr.NewComponent("ip4", "127.0.0.1")
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	err := RunClient(multiaddr.Join(ip, rest).String(), l.ID.String())
+	if err != nil {
+		t.Fatal(err)
+	}
+}