master
go 120 lines 2.26 KB
Raw
1 package p2p
2
3 import (
4 "io"
5 "sync"
6
7 ifconnmgr "github.com/libp2p/go-libp2p/core/connmgr"
8 net "github.com/libp2p/go-libp2p/core/network"
9 peer "github.com/libp2p/go-libp2p/core/peer"
10 protocol "github.com/libp2p/go-libp2p/core/protocol"
11 ma "github.com/multiformats/go-multiaddr"
12 manet "github.com/multiformats/go-multiaddr/net"
13 )
14
15 const cmgrTag = "stream-fwd"
16
17 // Stream holds information on active incoming and outgoing p2p streams.
18 type Stream struct {
19 id uint64
20
21 Protocol protocol.ID
22
23 OriginAddr ma.Multiaddr
24 TargetAddr ma.Multiaddr
25 peer peer.ID
26
27 Local manet.Conn
28 Remote net.Stream
29
30 Registry *StreamRegistry
31 }
32
33 // close stream endpoints and deregister it.
34 func (s *Stream) close() {
35 s.Registry.Close(s)
36 }
37
38 // reset closes stream endpoints and deregisters it.
39 func (s *Stream) reset() {
40 s.Registry.Reset(s)
41 }
42
43 func (s *Stream) startStreaming() {
44 go func() {
45 _, err := io.Copy(s.Local, s.Remote)
46 if err != nil {
47 s.reset()
48 } else {
49 s.close()
50 }
51 }()
52
53 go func() {
54 _, err := io.Copy(s.Remote, s.Local)
55 if err != nil {
56 s.reset()
57 } else {
58 s.close()
59 }
60 }()
61 }
62
63 // StreamRegistry is a collection of active incoming and outgoing proto app streams.
64 type StreamRegistry struct {
65 sync.Mutex
66
67 Streams map[uint64]*Stream
68 conns map[peer.ID]int
69 nextID uint64
70
71 ifconnmgr.ConnManager
72 }
73
74 // Register registers a stream to the registry.
75 func (r *StreamRegistry) Register(streamInfo *Stream) {
76 r.Lock()
77 defer r.Unlock()
78
79 r.ConnManager.TagPeer(streamInfo.peer, cmgrTag, 20)
80 r.conns[streamInfo.peer]++
81
82 streamInfo.id = r.nextID
83 r.Streams[r.nextID] = streamInfo
84 r.nextID++
85
86 streamInfo.startStreaming()
87 }
88
89 // Deregister deregisters stream from the registry.
90 func (r *StreamRegistry) Deregister(streamID uint64) {
91 r.Lock()
92 defer r.Unlock()
93
94 s, ok := r.Streams[streamID]
95 if !ok {
96 return
97 }
98 p := s.peer
99 r.conns[p]--
100 if r.conns[p] < 1 {
101 delete(r.conns, p)
102 r.ConnManager.UntagPeer(p, cmgrTag)
103 }
104
105 delete(r.Streams, streamID)
106 }
107
108 // Close stream endpoints and deregister it.
109 func (r *StreamRegistry) Close(s *Stream) {
110 _ = s.Local.Close()
111 _ = s.Remote.Close()
112 s.Registry.Deregister(s.id)
113 }
114
115 // Reset closes stream endpoints and deregisters it.
116 func (r *StreamRegistry) Reset(s *Stream) {
117 _ = s.Local.Close()
118 _ = s.Remote.Reset()
119 s.Registry.Deregister(s.id)
120 }