/
transport.go
89 lines (72 loc) · 2.12 KB
/
transport.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package client
import (
"context"
"fmt"
"io"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/transport"
ma "github.com/multiformats/go-multiaddr"
)
var circuitProtocol = ma.ProtocolWithCode(ma.P_CIRCUIT)
var circuitAddr = ma.Cast(circuitProtocol.VCode)
// AddTransport constructs a new p2p-circuit/v2 client and adds it as a transport to the
// host network
func AddTransport(h host.Host, upgrader transport.Upgrader) error {
n, ok := h.Network().(transport.TransportNetwork)
if !ok {
return fmt.Errorf("%v is not a transport network", h.Network())
}
c, err := New(h, upgrader)
if err != nil {
return fmt.Errorf("error constructing circuit client: %w", err)
}
err = n.AddTransport(c)
if err != nil {
return fmt.Errorf("error adding circuit transport: %w", err)
}
err = n.Listen(circuitAddr)
if err != nil {
return fmt.Errorf("error listening to circuit addr: %w", err)
}
c.Start()
return nil
}
// Transport interface
var _ transport.Transport = (*Client)(nil)
var _ io.Closer = (*Client)(nil)
func (c *Client) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (transport.CapableConn, error) {
connScope, err := c.host.Network().ResourceManager().OpenConnection(network.DirOutbound, false, a)
if err != nil {
return nil, err
}
if err := connScope.SetPeer(p); err != nil {
connScope.Done()
return nil, err
}
conn, err := c.dial(ctx, a, p)
if err != nil {
connScope.Done()
return nil, err
}
conn.tagHop()
return c.upgrader.Upgrade(ctx, c, conn, network.DirOutbound, p, connScope)
}
func (c *Client) CanDial(addr ma.Multiaddr) bool {
_, err := addr.ValueForProtocol(ma.P_CIRCUIT)
return err == nil
}
func (c *Client) Listen(addr ma.Multiaddr) (transport.Listener, error) {
// TODO connect to the relay and reserve slot if specified
if _, err := addr.ValueForProtocol(ma.P_CIRCUIT); err != nil {
return nil, err
}
return c.upgrader.UpgradeListener(c, c.Listener()), nil
}
func (c *Client) Protocols() []int {
return []int{ma.P_CIRCUIT}
}
func (c *Client) Proxy() bool {
return true
}