Skip to content

Commit

Permalink
quic: make server cmd use RFC 9000 instead of draft-29 (#2753)
Browse files Browse the repository at this point in the history
* quic: make server cmd use RFC 9000 instead of draft-29

* Move code to lib and add a test

* Change example to not rely on specific port

* Replace 0.0.0.0 with localhost

---------

Co-authored-by: Leon Rinkel <leon@rinkel.me>
  • Loading branch information
MarcoPolo and leonrinkel committed Apr 3, 2024
1 parent 86a6720 commit a2da8e0
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 134 deletions.
12 changes: 8 additions & 4 deletions p2p/http/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,26 @@ 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)
}
defer serverStreamHost.Close()

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() {
Expand Down
63 changes: 2 additions & 61 deletions p2p/transport/quic/cmd/client/main.go
Original file line number Diff line number Diff line change
@@ -1,78 +1,19 @@
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() {
if len(os.Args) != 3 {
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
}
129 changes: 129 additions & 0 deletions p2p/transport/quic/cmd/lib/lib.go
Original file line number Diff line number Diff line change
@@ -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()
}
30 changes: 30 additions & 0 deletions p2p/transport/quic/cmd/lib/lib_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
71 changes: 2 additions & 69 deletions p2p/transport/quic/cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -1,86 +1,19 @@
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() {
if len(os.Args) != 2 {
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()
}

0 comments on commit a2da8e0

Please sign in to comment.