p2p: separate listener types
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Sep 5, 2018 at 23:06 UTC
dd48b8237a402c765e8afb7360336ef194b06893
6 files changed
+162
-40
core/commands/p2p.go
+26
-8
@@ -230,15 +230,25 @@ var p2pLsCmd = &cmds.Command{
230
231
output := &P2PLsOutput{}
232
233
- n.P2P.Listeners.Lock()
234
- for _, listener := range n.P2P.Listeners.Listeners {
233
+ n.P2P.ListenersLocal.Lock()
234
+ for _, listener := range n.P2P.ListenersLocal.Listeners {
235
output.Listeners = append(output.Listeners, P2PListenerInfoOutput{
236
Protocol: string(listener.Protocol()),
237
ListenAddress: listener.ListenAddress().String(),
238
TargetAddress: listener.TargetAddress().String(),
239
})
240
}
241
- n.P2P.Listeners.Unlock()
241
+ n.P2P.ListenersLocal.Unlock()
242
+
243
+ n.P2P.ListenersP2P.Lock()
244
+ for _, listener := range n.P2P.ListenersP2P.Listeners {
245
+ output.Listeners = append(output.Listeners, P2PListenerInfoOutput{
246
+ Protocol: string(listener.Protocol()),
247
+ ListenAddress: listener.ListenAddress().String(),
248
+ TargetAddress: listener.TargetAddress().String(),
249
+ })
250
+ }
251
+ n.P2P.ListenersP2P.Unlock()
252
253
res.SetOutput(output)
254
},
@@ -314,7 +324,7 @@ var p2pCloseCmd = &cmds.Command{
324
return
325
}
326
317
- match := func(listener p2p.Listener) bool {
327
+ match := func(listener p2p.ListenerLocal) bool {
328
if closeAll {
329
return true
330
}
@@ -330,15 +340,23 @@ var p2pCloseCmd = &cmds.Command{
340
return true
341
}
342
333
- todo := make([]p2p.Listener, 0)
334
- n.P2P.Listeners.Lock()
335
- for _, l := range n.P2P.Listeners.Listeners {
343
+ todo := make([]p2p.ListenerLocal, 0)
344
+ n.P2P.ListenersLocal.Lock()
345
+ for _, l := range n.P2P.ListenersLocal.Listeners {
346
+ if !match(l) {
347
+ continue
348
+ }
349
+ todo = append(todo, l)
350
+ }
351
+ n.P2P.ListenersLocal.Unlock()
352
+ n.P2P.ListenersP2P.Lock()
353
+ for _, l := range n.P2P.ListenersP2P.Listeners {
354
if !match(l) {
355
continue
356
}
357
todo = append(todo, l)
358
}
341
- n.P2P.Listeners.Unlock()
359
+ n.P2P.ListenersP2P.Unlock()
360
361
var errs []string
362
for _, l := range todo {
p2p/local.go
+3
-3
@@ -27,7 +27,7 @@ type localListener struct {
27
}
28
29
// ForwardLocal creates new P2P stream to a remote listener
30
-func (p2p *P2P) ForwardLocal(ctx context.Context, peer peer.ID, proto protocol.ID, bindAddr ma.Multiaddr) (Listener, error) {
30
+func (p2p *P2P) ForwardLocal(ctx context.Context, peer peer.ID, proto protocol.ID, bindAddr ma.Multiaddr) (ListenerLocal, error) {
31
listener := &localListener{
32
ctx: ctx,
33
@@ -39,7 +39,7 @@ func (p2p *P2P) ForwardLocal(ctx context.Context, peer peer.ID, proto protocol.I
39
peer: peer,
40
}
41
42
- if err := p2p.Listeners.Register(listener); err != nil {
42
+ if err := p2p.ListenersLocal.Register(listener); err != nil {
43
return nil, err
44
}
45
@@ -111,7 +111,7 @@ func (l *localListener) start() error {
111
}
112
113
func (l *localListener) Close() error {
114
- ok, err := l.p2p.Listeners.Deregister(getListenerKey(l))
114
+ ok, err := l.p2p.ListenersLocal.Deregister(l.laddr.String())
115
if err != nil {
116
return err
117
}
p2p/local_listener.go
new
+113
@@ -0,0 +1,113 @@
1
+package p2p
2
+
3
+import (
4
+ "errors"
5
+ "sync"
6
+
7
+ net "gx/ipfs/QmQSbtGXCyNrj34LWL8EgXyNNYDZ8r3SwQcpW5pPxVhLnM/go-libp2p-net"
8
+ peer "gx/ipfs/QmQsErDt8Qgw1XrsXf2BpEzDgGWtB1YLsTAARBup5b6B9W/go-libp2p-peer"
9
+ ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
10
+ "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol"
11
+ p2phost "gx/ipfs/QmfH9FKYv3Jp1xiyL8sPchGBUBg6JA6XviwajAo3qgnT3B/go-libp2p-host"
12
+)
13
+
14
+// ListenerLocal listens for connections and proxies them to a target
15
+type ListenerLocal interface {
16
+ Protocol() protocol.ID
17
+ ListenAddress() ma.Multiaddr
18
+ TargetAddress() ma.Multiaddr
19
+
20
+ start() error
21
+
22
+ // Close closes the listener. Does not affect child streams
23
+ Close() error
24
+}
25
+
26
+// ListenersLocal is a collection of local application proto listeners.
27
+type ListenersLocal struct {
28
+ sync.RWMutex
29
+
30
+ Listeners map[string]ListenerLocal
31
+ starting map[string]struct{}
32
+}
33
+
34
+func newListenerRegistry(id peer.ID, host p2phost.Host) *ListenersLocal {
35
+ reg := &ListenersLocal{
36
+ Listeners: map[string]ListenerLocal{},
37
+ starting: map[string]struct{}{},
38
+ }
39
+
40
+ addr, err := ma.NewMultiaddr(maPrefix + id.Pretty())
41
+ if err != nil {
42
+ panic(err)
43
+ }
44
+
45
+ host.SetStreamHandlerMatch("/x/", func(p string) bool {
46
+ reg.RLock()
47
+ defer reg.RUnlock()
48
+
49
+ for _, l := range reg.Listeners {
50
+ if l.ListenAddress().Equal(addr) && string(l.Protocol()) == p {
51
+ return true
52
+ }
53
+ }
54
+
55
+ return false
56
+ }, func(stream net.Stream) {
57
+ reg.RLock()
58
+ defer reg.RUnlock()
59
+
60
+ for _, l := range reg.Listeners {
61
+ if l.ListenAddress().Equal(addr) && l.Protocol() == stream.Protocol() {
62
+ go l.(*remoteListener).handleStream(stream)
63
+ return
64
+ }
65
+ }
66
+ })
67
+
68
+ return reg
69
+}
70
+
71
+// Register registers listenerInfo into this registry and starts it
72
+func (r *ListenersLocal) Register(l ListenerLocal) error {
73
+ r.Lock()
74
+ k := l.ListenAddress().String()
75
+
76
+ if _, ok := r.Listeners[k]; ok {
77
+ r.Unlock()
78
+ return errors.New("listener already registered")
79
+ }
80
+
81
+ r.Listeners[k] = l
82
+ r.starting[k] = struct{}{}
83
+
84
+ r.Unlock()
85
+
86
+ err := l.start()
87
+
88
+ r.Lock()
89
+ defer r.Unlock()
90
+
91
+ delete(r.starting, k)
92
+
93
+ if err != nil {
94
+ delete(r.Listeners, k)
95
+ return err
96
+ }
97
+
98
+ return nil
99
+}
100
+
101
+// Deregister removes p2p listener from this registry
102
+func (r *ListenersLocal) Deregister(k string) (bool, error) {
103
+ r.Lock()
104
+ defer r.Unlock()
105
+
106
+ if _, ok := r.starting[k]; ok {
107
+ return false, errors.New("listener didn't start yet")
108
+ }
109
+
110
+ _, ok := r.Listeners[k]
111
+ delete(r.Listeners, k)
112
+ return ok, nil
113
+}
p2p/p2p.go
+6
-3
@@ -11,8 +11,9 @@ var log = logging.Logger("p2p-mount")
11
12
// P2P structure holds information on currently running streams/listeners
13
type P2P struct {
14
- Listeners *ListenerRegistry
15
- Streams *StreamRegistry
14
+ ListenersLocal *ListenersLocal
15
+ ListenersP2P *ListenersP2P
16
+ Streams *StreamRegistry
17
18
identity peer.ID
19
peerHost p2phost.Host
@@ -26,7 +27,9 @@ func NewP2P(identity peer.ID, peerHost p2phost.Host, peerstore pstore.Peerstore)
27
peerHost: peerHost,
28
peerstore: peerstore,
29
29
- Listeners: newListenerRegistry(identity, peerHost),
30
+ ListenersLocal: newListenerRegistry(identity, peerHost),
31
+ ListenersP2P: newListenerP2PRegistry(identity, peerHost),
32
+
33
Streams: &StreamRegistry{
34
Streams: map[uint64]*Stream{},
35
},
p2p/p2p_listener.go
renamed
+11
-23
@@ -12,7 +12,7 @@ import (
12
)
13
14
// Listener listens for connections and proxies them to a target
15
-type Listener interface {
15
+type P2PListener interface {
16
Protocol() protocol.ID
17
ListenAddress() ma.Multiaddr
18
TargetAddress() ma.Multiaddr
@@ -23,23 +23,18 @@ type Listener interface {
23
Close() error
24
}
25
26
-type listenerKey struct {
27
- proto string
28
- listen string
29
-}
30
-
26
// ListenerRegistry is a collection of local application proto listeners.
32
-type ListenerRegistry struct {
27
+type ListenersP2P struct {
28
sync.RWMutex
29
35
- Listeners map[listenerKey]Listener
36
- starting map[listenerKey]struct{}
30
+ Listeners map[protocol.ID]ListenerLocal
31
+ starting map[protocol.ID]struct{}
32
}
33
39
-func newListenerRegistry(id peer.ID, host p2phost.Host) *ListenerRegistry {
40
- reg := &ListenerRegistry{
41
- Listeners: map[listenerKey]Listener{},
42
- starting: map[listenerKey]struct{}{},
34
+func newListenerP2PRegistry(id peer.ID, host p2phost.Host) *ListenersP2P {
35
+ reg := &ListenersP2P{
36
+ Listeners: map[protocol.ID]ListenerLocal{},
37
+ starting: map[protocol.ID]struct{}{},
38
}
39
40
addr, err := ma.NewMultiaddr(maPrefix + id.Pretty())
@@ -74,10 +69,10 @@ func newListenerRegistry(id peer.ID, host p2phost.Host) *ListenerRegistry {
69
}
70
71
// Register registers listenerInfo into this registry and starts it
77
-func (r *ListenerRegistry) Register(l Listener) error {
72
+func (r *ListenersP2P) Register(l ListenerLocal) error {
73
r.Lock()
79
- k := getListenerKey(l)
74
75
+ k := l.Protocol()
76
if _, ok := r.Listeners[k]; ok {
77
r.Unlock()
78
return errors.New("listener already registered")
@@ -104,7 +99,7 @@ func (r *ListenerRegistry) Register(l Listener) error {
99
}
100
101
// Deregister removes p2p listener from this registry
107
-func (r *ListenerRegistry) Deregister(k listenerKey) (bool, error) {
102
+func (r *ListenersP2P) Deregister(k protocol.ID) (bool, error) {
103
r.Lock()
104
defer r.Unlock()
105
@@ -116,10 +111,3 @@ func (r *ListenerRegistry) Deregister(k listenerKey) (bool, error) {
111
delete(r.Listeners, k)
112
return ok, nil
113
}
119
-
120
-func getListenerKey(l Listener) listenerKey {
121
- return listenerKey{
122
- proto: string(l.Protocol()),
123
- listen: l.ListenAddress().String(),
124
- }
125
-}
p2p/remote.go
+3
-3
@@ -23,7 +23,7 @@ type remoteListener struct {
23
}
24
25
// ForwardRemote creates new p2p listener
26
-func (p2p *P2P) ForwardRemote(ctx context.Context, proto protocol.ID, addr ma.Multiaddr) (Listener, error) {
26
+func (p2p *P2P) ForwardRemote(ctx context.Context, proto protocol.ID, addr ma.Multiaddr) (P2PListener, error) {
27
listener := &remoteListener{
28
p2p: p2p,
29
@@ -31,7 +31,7 @@ func (p2p *P2P) ForwardRemote(ctx context.Context, proto protocol.ID, addr ma.Mu
31
addr: addr,
32
}
33
34
- if err := p2p.Listeners.Register(listener); err != nil {
34
+ if err := p2p.ListenersP2P.Register(listener); err != nil {
35
return nil, err
36
}
37
@@ -97,7 +97,7 @@ func (l *remoteListener) TargetAddress() ma.Multiaddr {
97
}
98
99
func (l *remoteListener) Close() error {
100
- ok, err := l.p2p.Listeners.Deregister(getListenerKey(l))
100
+ ok, err := l.p2p.ListenersP2P.Deregister(l.proto)
101
if err != nil {
102
return err
103
}