Skip to content

Commit b45a4d1

Browse files
author
navigaid
committed
switch back to nhooyr websocket for browser support
reverting libp2p/go-libp2p#2280
1 parent e620f11 commit b45a4d1

File tree

10 files changed

+142
-195
lines changed

10 files changed

+142
-195
lines changed

cmd/dial/main.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"os"
8+
9+
// We need to import libp2p's libraries that we use in this project.
10+
"github.com/libp2p/go-libp2p"
11+
"github.com/libp2p/go-libp2p/core/host"
12+
"github.com/libp2p/go-libp2p/core/peer"
13+
14+
"github.com/btwiuse/wsport"
15+
)
16+
17+
func getEnv(key, def string) string {
18+
if v := os.Getenv(key); v != "" {
19+
return v
20+
}
21+
return def
22+
}
23+
24+
var RELAY = getEnv("RELAY", "https://example.com")
25+
26+
// makeRandomHost creates a libp2p host with a randomly generated identity.
27+
// This step is described in depth in other tutorials.
28+
func makeRandomHost(port int) host.Host {
29+
log.SetFlags(log.LstdFlags | log.Llongfile)
30+
addr := fmt.Sprintf(RELAY+"/ws%d", port)
31+
log.Println("ListenAddr", addr)
32+
host, err := libp2p.New(
33+
libp2p.Transport(wsport.New),
34+
wsport.ListenAddrStrings(addr),
35+
)
36+
if err != nil {
37+
log.Fatalln(err)
38+
}
39+
return host
40+
}
41+
42+
func main() {
43+
host := makeRandomHost(1000)
44+
fmt.Println("host is ready")
45+
fmt.Println("libp2p-peer addresses:")
46+
for _, a := range host.Addrs() {
47+
fmt.Printf("%s/p2p/%s\n", a, host.ID())
48+
}
49+
50+
addrInfo, err := peer.AddrInfoFromString(os.Args[1])
51+
if err != nil {
52+
log.Fatalln(err)
53+
}
54+
55+
err = host.Connect(context.Background(), *addrInfo)
56+
if err != nil {
57+
log.Fatalln(err)
58+
} else {
59+
fmt.Println("Connected to", addrInfo.ID)
60+
}
61+
62+
select {}
63+
}

cmd/reconnect/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ func Run(args []string) error {
5555
time.Sleep(time.Duration(i) * time.Second)
5656
}
5757
},
58+
onConnected: func(n network.Network, c network.Conn) {
59+
log.Println("[Connected]", c.ID())
60+
},
61+
onDisconnected: func(n network.Network, c network.Conn) {
62+
log.Println("[Disconnected]", c.ID())
63+
},
5864
}
5965

6066
host.Network().Notify(notifiee)

conn.go

Lines changed: 0 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,10 @@
11
package wsport
22

33
import (
4-
"io"
5-
"net"
6-
"sync"
7-
"time"
8-
94
"github.com/libp2p/go-libp2p/core/network"
105
"github.com/libp2p/go-libp2p/core/transport"
11-
12-
ws "github.com/gorilla/websocket"
136
)
147

15-
// GracefulCloseTimeout is the time to wait trying to gracefully close a
16-
// connection before simply cutting it.
17-
var GracefulCloseTimeout = 100 * time.Millisecond
18-
19-
// Conn implements net.Conn interface for gorilla/websocket.
20-
type Conn struct {
21-
*ws.Conn
22-
secure bool
23-
DefaultMessageType int
24-
reader io.Reader
25-
closeOnce sync.Once
26-
27-
readLock, writeLock sync.Mutex
28-
}
29-
30-
var _ net.Conn = (*Conn)(nil)
31-
32-
// NewConn creates a Conn given a regular gorilla/websocket Conn.
33-
func NewConn(raw *ws.Conn, secure bool) *Conn {
34-
return &Conn{
35-
Conn: raw,
36-
secure: secure,
37-
DefaultMessageType: ws.BinaryMessage,
38-
}
39-
}
40-
41-
func (c *Conn) Read(b []byte) (int, error) {
42-
c.readLock.Lock()
43-
defer c.readLock.Unlock()
44-
45-
if c.reader == nil {
46-
if err := c.prepNextReader(); err != nil {
47-
return 0, err
48-
}
49-
}
50-
51-
for {
52-
n, err := c.reader.Read(b)
53-
switch err {
54-
case io.EOF:
55-
c.reader = nil
56-
57-
if n > 0 {
58-
return n, nil
59-
}
60-
61-
if err := c.prepNextReader(); err != nil {
62-
return 0, err
63-
}
64-
65-
// explicitly looping
66-
default:
67-
return n, err
68-
}
69-
}
70-
}
71-
72-
func (c *Conn) prepNextReader() error {
73-
t, r, err := c.Conn.NextReader()
74-
if err != nil {
75-
if wserr, ok := err.(*ws.CloseError); ok {
76-
if wserr.Code == 1000 || wserr.Code == 1005 {
77-
return io.EOF
78-
}
79-
}
80-
return err
81-
}
82-
83-
if t == ws.CloseMessage {
84-
return io.EOF
85-
}
86-
87-
c.reader = r
88-
return nil
89-
}
90-
91-
func (c *Conn) Write(b []byte) (n int, err error) {
92-
c.writeLock.Lock()
93-
defer c.writeLock.Unlock()
94-
95-
if err := c.Conn.WriteMessage(c.DefaultMessageType, b); err != nil {
96-
return 0, err
97-
}
98-
99-
return len(b), nil
100-
}
101-
102-
// Close closes the connection. Only the first call to Close will receive the
103-
// close error, subsequent and concurrent calls will return nil.
104-
// This method is thread-safe.
105-
func (c *Conn) Close() error {
106-
var err error
107-
c.closeOnce.Do(func() {
108-
err1 := c.Conn.WriteControl(
109-
ws.CloseMessage,
110-
ws.FormatCloseMessage(ws.CloseNormalClosure, "closed"),
111-
time.Now().Add(GracefulCloseTimeout),
112-
)
113-
err2 := c.Conn.Close()
114-
switch {
115-
case err1 != nil:
116-
err = err1
117-
case err2 != nil:
118-
err = err2
119-
}
120-
})
121-
return err
122-
}
123-
124-
func (c *Conn) LocalAddr() net.Addr {
125-
return NewAddrWithScheme(c.Conn.LocalAddr().String(), c.secure)
126-
}
127-
128-
func (c *Conn) RemoteAddr() net.Addr {
129-
return NewAddrWithScheme(c.Conn.RemoteAddr().String(), c.secure)
130-
}
131-
132-
func (c *Conn) SetDeadline(t time.Time) error {
133-
if err := c.SetReadDeadline(t); err != nil {
134-
return err
135-
}
136-
137-
return c.SetWriteDeadline(t)
138-
}
139-
140-
func (c *Conn) SetReadDeadline(t time.Time) error {
141-
// Don't lock when setting the read deadline. That would prevent us from
142-
// interrupting an in-progress read.
143-
return c.Conn.SetReadDeadline(t)
144-
}
145-
146-
func (c *Conn) SetWriteDeadline(t time.Time) error {
147-
// Unlike the read deadline, we need to lock when setting the write
148-
// deadline.
149-
150-
c.writeLock.Lock()
151-
defer c.writeLock.Unlock()
152-
153-
return c.Conn.SetWriteDeadline(t)
154-
}
155-
1568
type capableConn struct {
1579
transport.CapableConn
15810
}

dial.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package wsport
2+
3+
import (
4+
"context"
5+
"net"
6+
"net/http"
7+
8+
"nhooyr.io/websocket"
9+
)
10+
11+
func DialConn(ctx context.Context, addr string, hdr http.Header) (conn net.Conn, err error) {
12+
wsconn, _, err := websocket.Dial(
13+
ctx,
14+
addr,
15+
dialOptions(hdr),
16+
)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
return websocket.NetConn(context.Background(), wsconn, websocket.MessageBinary), nil
22+
}

dial_js.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//go:build js
2+
3+
package wsport
4+
5+
import (
6+
"net/http"
7+
8+
"nhooyr.io/websocket"
9+
)
10+
11+
func dialOptions(http.Header) *websocket.DialOptions {
12+
return &websocket.DialOptions{}
13+
}

dial_nojs.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//go:build !js
2+
3+
package wsport
4+
5+
import (
6+
"crypto/tls"
7+
"net/http"
8+
9+
"nhooyr.io/websocket"
10+
)
11+
12+
func dialOptions(hdr http.Header) *websocket.DialOptions {
13+
return &websocket.DialOptions{
14+
HTTPClient: &http.Client{
15+
Transport: &http.Transport{
16+
Proxy: http.ProxyFromEnvironment,
17+
TLSClientConfig: &tls.Config{
18+
InsecureSkipVerify: true,
19+
},
20+
},
21+
},
22+
HTTPHeader: hdr,
23+
}
24+
}

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ go 1.22.2
55
replace github.com/libp2p/go-libp2p => github.com/btwiuse/go-libp2p v0.33.1-0.20240506191734-9e95b7cfe073
66

77
require (
8+
github.com/btwiuse/wsconn v0.0.2
89
github.com/btwiuse/x-parity-wss v0.0.2
9-
github.com/gorilla/websocket v1.5.1
1010
github.com/libp2p/go-libp2p v0.33.2
1111
github.com/multiformats/go-multiaddr v0.12.3
1212
github.com/multiformats/go-multiaddr-fmt v0.1.0
1313
github.com/stretchr/testify v1.8.4
1414
github.com/webteleport/webteleport v0.5.28
15+
nhooyr.io/websocket v1.8.11
1516
)
1617

1718
require (
1819
github.com/benbjohnson/clock v1.3.5 // indirect
1920
github.com/beorn7/perks v1.0.1 // indirect
20-
github.com/btwiuse/wsconn v0.0.2 // indirect
2121
github.com/cespare/xxhash/v2 v2.2.0 // indirect
2222
github.com/containerd/cgroups v1.1.0 // indirect
2323
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
@@ -36,6 +36,7 @@ require (
3636
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
3737
github.com/google/uuid v1.4.0 // indirect
3838
github.com/gorilla/handlers v1.5.2 // indirect
39+
github.com/gorilla/websocket v1.5.1 // indirect
3940
github.com/hashicorp/yamux v0.1.1 // indirect
4041
github.com/huin/goupnp v1.3.0 // indirect
4142
github.com/ipfs/go-cid v0.4.1 // indirect
@@ -117,5 +118,4 @@ require (
117118
google.golang.org/protobuf v1.32.0 // indirect
118119
gopkg.in/yaml.v3 v3.0.1 // indirect
119120
lukechampine.com/blake3 v1.2.1 // indirect
120-
nhooyr.io/websocket v1.8.11 // indirect
121121
)

listener.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/libp2p/go-libp2p/core/transport"
1313
"github.com/webteleport/webteleport/transport/websocket"
1414

15+
"github.com/btwiuse/wsconn"
1516
ma "github.com/multiformats/go-multiaddr"
1617
manet "github.com/multiformats/go-multiaddr/net"
1718
)
@@ -25,7 +26,7 @@ type listener struct {
2526
laddr ma.Multiaddr
2627

2728
closed chan struct{}
28-
incoming chan *Conn
29+
incoming chan net.Conn
2930
}
3031

3132
func (pwma *parsedWebsocketMultiaddr) toMultiaddr() ma.Multiaddr {
@@ -97,7 +98,7 @@ func newListener(a ma.Multiaddr, tlsConf *tls.Config) (*listener, error) {
9798
nl: nl,
9899
isWss: parsed.isWSS,
99100
laddr: laddr,
100-
incoming: make(chan *Conn),
101+
incoming: make(chan net.Conn),
101102
closed: make(chan struct{}),
102103
}
103104
return ln, nil
@@ -121,14 +122,14 @@ func (l *listener) serve() {
121122
}
122123

123124
func (l *listener) ServeHTTP(w http.ResponseWriter, r *http.Request) {
124-
c, err := upgrader.Upgrade(w, r, nil)
125+
c, err := wsconn.Wrconn(w, r)
125126
if err != nil {
126127
// The upgrader writes a response for us.
127128
return
128129
}
129130

130131
select {
131-
case l.incoming <- NewConn(c, l.isWss):
132+
case l.incoming <- c:
132133
case <-l.closed:
133134
c.Close()
134135
}

0 commit comments

Comments
 (0)