-
Notifications
You must be signed in to change notification settings - Fork 376
/
transport.go
137 lines (114 loc) · 4.38 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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package mc
import (
"context"
"fmt"
mcdrv "berty.tech/berty/v2/go/internal/multipeer-connectivity-transport/driver"
mcma "berty.tech/berty/v2/go/internal/multipeer-connectivity-transport/multiaddr"
host "github.com/libp2p/go-libp2p-core/host"
peer "github.com/libp2p/go-libp2p-core/peer"
tpt "github.com/libp2p/go-libp2p-core/transport"
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
"go.uber.org/zap"
)
const DefaultBind = "/mc/Qmeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
// logger is global because HandleFoundPeer must be able to call it
// FIXME: remove global logger
var logger *zap.Logger = zap.L().Named("mc-transport")
// Transport is a tpt.transport.
var _ tpt.Transport = &Transport{}
// Transport represents any device by which you can connect to and accept
// connections from other peers.
type Transport struct {
host host.Host
upgrader *tptu.Upgrader
}
func NewTransportConstructorWithLogger(l *zap.Logger) func(h host.Host, u *tptu.Upgrader) (*Transport, error) {
if l != nil {
l.Named("MC Transport")
logger = l
}
return NewTransport
}
// NewTransport creates a transport object that tracks dialers and listener.
// It also starts the discovery service.
func NewTransport(h host.Host, u *tptu.Upgrader) (*Transport, error) {
logger.Debug("New multipeer connectivity transport")
return &Transport{
host: h,
upgrader: u,
}, nil
}
// Dial dials the peer at the remote address.
// With MC you can only dial a device that is already connected with the native driver.
func (t *Transport) Dial(ctx context.Context, remoteMa ma.Multiaddr, remotePID peer.ID) (tpt.CapableConn, error) {
// MC transport needs to have a running listener in order to dial other peer
// because native driver is initialized during listener creation.
if gListener == nil {
return nil, errors.New("transport dialing peer failed: no active listener")
}
// remoteAddr is supposed to be equal to remotePID since with MC transport:
// multiaddr = /mc/<peerID>
remoteAddr, err := remoteMa.ValueForProtocol(mcma.P_MC)
if err != nil || remoteAddr != remotePID.Pretty() {
return nil, errors.Wrap(err, "transport dialing peer failed: wrong multiaddr")
}
// Ensures that gListener won't be unset until operations using it are finished
gListener.inUse.Add(1)
// Check if native driver is already connected to peer's device.
// With MC you can't really dial, only auto-connect with peer nearby.
if !mcdrv.DialPeer(remoteAddr) {
gListener.inUse.Done()
return nil, errors.New("transport dialing peer failed: peer not connected through MC")
}
// Can't have two connections on the same multiaddr
if _, ok := connMap.Load(remoteAddr); ok {
gListener.inUse.Done()
return nil, errors.New("transport dialing peer failed: already connected to this address")
}
// Returns an outbound conn.
return newConn(ctx, t, remoteMa, remotePID, false)
}
// CanDial returns true if this transport believes it can dial the given
// multiaddr.
func (t *Transport) CanDial(remoteMa ma.Multiaddr) bool {
return mcma.MC.Matches(remoteMa)
}
// Listen listens on the given multiaddr.
// MC can't listen on more than one listener.
func (t *Transport) Listen(localMa ma.Multiaddr) (tpt.Listener, error) {
// localAddr is supposed to be equal to the localPID
// or to DefaultBind since multiaddr == /mc/<peerID>
localPID := t.host.ID().Pretty()
localAddr, err := localMa.ValueForProtocol(mcma.P_MC)
if err != nil || (localMa.String() != DefaultBind && localAddr != localPID) {
return nil, errors.Wrap(err, "transport listen failed: wrong multiaddr")
}
// Replaces default bind by local host peerID
if localMa.String() == DefaultBind {
localMa, err = ma.NewMultiaddr(fmt.Sprintf("/mc/%s", localPID))
if err != nil { // Should never append.
panic(err)
}
}
// If a global listener already exists, returns an error.
if gListener != nil {
// TODO: restore this when published as generic lib / fixed in Berty network
// config update
// return nil, errors.New("transport listen failed: one listener maximum")
gListener.Close()
}
return newListener(localMa, t), nil
}
// Proxy returns true if this transport proxies.
func (t *Transport) Proxy() bool {
return false
}
// Protocols returns the set of protocols handled by this transport.
func (t *Transport) Protocols() []int {
return []int{mcma.P_MC}
}
func (t *Transport) String() string {
return "MC"
}