master
go 115 lines 2.19 KB
Raw
1 package p2p
2
3 import (
4 "context"
5 "fmt"
6
7 net "github.com/libp2p/go-libp2p/core/network"
8 "github.com/libp2p/go-libp2p/core/protocol"
9 ma "github.com/multiformats/go-multiaddr"
10 manet "github.com/multiformats/go-multiaddr/net"
11 )
12
13 var maPrefix = "/" + ma.ProtocolWithCode(ma.P_IPFS).Name + "/"
14
15 // remoteListener accepts libp2p streams and proxies them to a manet host.
16 type remoteListener struct {
17 p2p *P2P
18
19 // Application proto identifier.
20 proto protocol.ID
21
22 // Address to proxy the incoming connections to
23 addr ma.Multiaddr
24
25 // reportRemote if set to true makes the handler send '<base58 remote peerid>\n'
26 // to target before any data is forwarded
27 reportRemote bool
28
29 done chan struct{}
30 }
31
32 // ForwardRemote creates new p2p listener.
33 func (p2p *P2P) ForwardRemote(ctx context.Context, proto protocol.ID, addr ma.Multiaddr, reportRemote bool) (Listener, error) {
34 listener := &remoteListener{
35 p2p: p2p,
36
37 proto: proto,
38 addr: addr,
39
40 reportRemote: reportRemote,
41 done: make(chan struct{}),
42 }
43
44 if err := p2p.ListenersP2P.Register(listener); err != nil {
45 return nil, err
46 }
47
48 return listener, nil
49 }
50
51 func (l *remoteListener) handleStream(remote net.Stream) {
52 local, err := manet.Dial(l.addr)
53 if err != nil {
54 _ = remote.Reset()
55 return
56 }
57
58 peer := remote.Conn().RemotePeer()
59
60 if l.reportRemote {
61 if _, err := fmt.Fprintf(local, "%s\n", peer); err != nil {
62 _ = remote.Reset()
63 return
64 }
65 }
66
67 peerMa, err := ma.NewMultiaddr(maPrefix + peer.String())
68 if err != nil {
69 _ = remote.Reset()
70 return
71 }
72
73 stream := &Stream{
74 Protocol: l.proto,
75
76 OriginAddr: peerMa,
77 TargetAddr: l.addr,
78 peer: peer,
79
80 Local: local,
81 Remote: remote,
82
83 Registry: l.p2p.Streams,
84 }
85
86 l.p2p.Streams.Register(stream)
87 }
88
89 func (l *remoteListener) Protocol() protocol.ID {
90 return l.proto
91 }
92
93 func (l *remoteListener) ListenAddress() ma.Multiaddr {
94 addr, err := ma.NewMultiaddr(maPrefix + l.p2p.identity.String())
95 if err != nil {
96 panic(err)
97 }
98 return addr
99 }
100
101 func (l *remoteListener) TargetAddress() ma.Multiaddr {
102 return l.addr
103 }
104
105 func (l *remoteListener) close() {
106 close(l.done)
107 }
108
109 func (l *remoteListener) Done() <-chan struct{} {
110 return l.done
111 }
112
113 func (l *remoteListener) key() protocol.ID {
114 return l.proto
115 }