p2p: implement forward cmd
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
May 23, 2018 at 15:05 UTC
48d83be05215b8d1886d27541c58c4a43c40d5ad
1 file changed
+101
-1
core/commands/p2p.go
+101
-1
@@ -2,14 +2,17 @@ package commands
2
3
import (
4
"bytes"
5
+ "context"
6
"errors"
7
"fmt"
8
"io"
9
"strconv"
10
+ "strings"
11
"text/tabwriter"
12
13
cmds "github.com/ipfs/go-ipfs/commands"
14
core "github.com/ipfs/go-ipfs/core"
15
+ p2p "github.com/ipfs/go-ipfs/p2p"
16
17
pstore "gx/ipfs/QmXauCuJzmzapetmC6W4TuDJLL1yFFrVzSHoWv8YdbmnxH/go-libp2p-peerstore"
18
ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
@@ -56,9 +59,107 @@ are refined`,
59
Subcommands: map[string]*cmds.Command{
60
"listener": p2pListenerCmd,
61
"stream": p2pStreamCmd,
62
+ "forward": p2pForwardCmd,
63
},
64
}
65
66
+var p2pForwardCmd = &cmds.Command{
67
+ Helptext: cmdkit.HelpText{
68
+ Tagline: "Forward connections to or from libp2p services",
69
+ ShortDescription: `
70
+Forward connections to <listen-address> to <target-address>. Protocol specifies
71
+the libp2p protocol to use.
72
+
73
+To create libp2p service listener, specify '/ipfs' as <listen-address>
74
+
75
+Examples:
76
+ ipfs p2p forward myproto /ipfs /ip4/127.0.0.1/tcp/1234
77
+ - Forward connections to 'myproto' libp2p service to 127.0.0.1:1234
78
+
79
+ ipfs p2p forward myproto /ip4/127.0.0.1/tcp/4567 /ipfs/QmPeer
80
+ - Forward connections to 127.0.0.1:4567 to 'myproto' service on /ipfs/QmPeer
81
+
82
+`,
83
+ },
84
+ Arguments: []cmdkit.Argument{
85
+ cmdkit.StringArg("protocol", true, false, "Protocol identifier."),
86
+ cmdkit.StringArg("listen-address", true, false, "Listening endpoint"),
87
+ cmdkit.StringArg("target-address", true, false, "Target endpoint."),
88
+ },
89
+ Run: func(req cmds.Request, res cmds.Response) {
90
+ n, err := getNode(req)
91
+ if err != nil {
92
+ res.SetError(err, cmdkit.ErrNormal)
93
+ return
94
+ }
95
+
96
+ //TODO: Do we really want/need implicit prefix?
97
+ proto := "/p2p/" + req.Arguments()[0]
98
+ listen := req.Arguments()[1]
99
+ target := req.Arguments()[2]
100
+
101
+ if strings.HasPrefix(listen, "/ipfs") {
102
+ if listen != "/ipfs" {
103
+ res.SetError(errors.New("only '/ipfs' is allowed as libp2p listen address"), cmdkit.ErrNormal)
104
+ return
105
+ }
106
+
107
+ if err := forwardRemote(n.Context(), n.P2P, proto, target); err != nil {
108
+ res.SetError(err, cmdkit.ErrNormal)
109
+ return
110
+ }
111
+ } else {
112
+ if err := forwardLocal(n.Context(), n.P2P, n.Peerstore, proto, listen, target); err != nil {
113
+ res.SetError(err, cmdkit.ErrNormal)
114
+ return
115
+ }
116
+ }
117
+ res.SetOutput(nil)
118
+ },
119
+}
120
+
121
+// forwardRemote forwards libp2p service connections to a manet address
122
+func forwardRemote(ctx context.Context, p *p2p.P2P, proto string, target string) error {
123
+ if strings.HasPrefix(target, "/ipfs") {
124
+ return errors.New("cannot forward libp2p service connections to another libp2p service")
125
+ }
126
+
127
+ addr, err := ma.NewMultiaddr(target)
128
+ if err != nil {
129
+ return err
130
+ }
131
+
132
+ // TODO: return some info
133
+ _, err = p.NewListener(ctx, proto, addr)
134
+ return err
135
+}
136
+
137
+// forwardLocal forwards local connections to a libp2p service
138
+func forwardLocal(ctx context.Context, p *p2p.P2P, ps pstore.Peerstore, proto string, listen string, target string) error {
139
+ bindAddr, err := ma.NewMultiaddr(listen)
140
+ if err != nil {
141
+ return err
142
+ }
143
+
144
+ addr, peer, err := ParsePeerParam(target)
145
+ if err != nil {
146
+ return err
147
+ }
148
+
149
+ if addr != nil {
150
+ ps.AddAddr(peer, addr, pstore.TempAddrTTL)
151
+ }
152
+
153
+ // TODO: return some info
154
+ _, err = p.Dial(ctx, peer, proto, bindAddr)
155
+ return err
156
+}
157
+
158
+////
159
+// LEGACY
160
+//
161
+//
162
+
163
// p2pListenerCmd is the 'ipfs p2p listener' command
164
var p2pListenerCmd = &cmds.Command{
165
Helptext: cmdkit.HelpText{
@@ -95,7 +196,6 @@ var p2pListenerLsCmd = &cmds.Command{
196
cmdkit.BoolOption("headers", "v", "Print table headers (Id, Protocol, Local, Remote)."),
197
},
198
Run: func(req cmds.Request, res cmds.Response) {
98
-
199
n, err := getNode(req)
200
if err != nil {
201
res.SetError(err, cmdkit.ErrNormal)