Closed oblique closed 1 year ago
For completeness I provide an example that listener accepts a stream, which works.
package main
import (
"context"
"crypto/rand"
"fmt"
webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
"golang.org/x/exp/slices"
)
func startListener() (multiaddr.Multiaddr, peer.ID) {
priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
if err != nil {
panic(err)
}
peerId, err := peer.IDFromPublicKey(pub)
if err != nil {
panic(err)
}
connManager, err := quicreuse.NewConnManager([32]byte{})
if err != nil {
panic(err)
}
transport, err := webtransport.New(priv, nil, connManager, nil, nil);
if err != nil {
panic(err)
}
listener, err := transport.Listen(multiaddr.StringCast("/ip4/127.0.0.1/udp/0/quic-v1/webtransport"))
if err != nil {
panic(err)
}
fmt.Printf("Listener: Listening\n")
ma := listener.Multiaddr()
go func() {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
fmt.Printf("Listener: Accepted connection\n")
fmt.Printf("Listener: Accepting stream\n")
stream, err := conn.AcceptStream()
if err != nil {
panic(err)
}
fmt.Printf("Listener: Accepted stream\n")
fmt.Printf("Listener: Receiving\n")
recvBuf := make([]byte, 8)
stream.Read(recvBuf)
fmt.Printf("Listener: Received: %v\n", recvBuf)
stream.Write(recvBuf)
fmt.Printf("Listener: Send: %v\n", recvBuf)
}()
return ma, peerId
}
func connectAndTest(ma multiaddr.Multiaddr, peerId peer.ID) {
priv, _, err := crypto.GenerateEd25519Key(rand.Reader)
if err != nil {
panic(err)
}
connManager, err := quicreuse.NewConnManager([32]byte{})
if err != nil {
panic(err)
}
transport, err := webtransport.New(priv, nil, connManager, nil, nil);
if err != nil {
panic(err)
}
fmt.Printf("Dialer: Dialing\n")
conn, err := transport.Dial(context.Background(), ma, peerId)
if err != nil {
panic(err)
}
fmt.Printf("Dialer: Dialed\n")
// This works
fmt.Printf("Dialer: Opening stream\n")
stream, err := conn.OpenStream(context.Background())
if err != nil {
panic(err)
}
fmt.Printf("Dialer: Stream opened\n")
sendBuf := make([]byte, 8)
rand.Read(sendBuf)
stream.Write(sendBuf)
fmt.Printf("Dialer: Send: %v\n", sendBuf)
recvBuf := make([]byte, 8)
stream.Read(recvBuf)
fmt.Printf("Dialer: Received: %v\n", recvBuf)
if !slices.Equal(sendBuf, recvBuf) {
panic("sendBuf is not equal to recvBuf")
}
}
func main() {
ma, peerId := startListener()
connectAndTest(ma, peerId)
}
Output:
Listener: Listening
Dialer: Dialing
Dialer: Dialed
Dialer: Opening stream
Dialer: Stream opened
Dialer: Send: [3 149 155 96 203 87 215 219]
Listener: Accepted connection
Listener: Accepting stream
Listener: Accepted stream
Listener: Receiving
Listener: Received: [3 149 155 96 203 87 215 219]
Listener: Send: [3 149 155 96 203 87 215 219]
Dialer: Received: [3 149 155 96 203 87 215 219]
Works as expected. Opening a stream is a local operation, until you send data on that stream. You never do that.
Thanks a lot! I didn't know this detail
I was using WebTransport implementation as an echo server to write some test cases for https://github.com/libp2p/rust-libp2p/pull/4015 and I found the following bug:
A WebTransport listener can not receive data from a stream opened by OpenStream.
The following code reproduces the problem:
Output:
Version Information