@cryptotaxi247 / kubo / commits / 48d83be05

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)