@cryptotaxi247 / kubo / commits / eac71847b

Corenet API: Move more logic away from commands

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Jun 2, 2017 at 15:57 UTC eac71847bdbcd2e44f4eee7f8fc926f47e609085
6 files changed +214 -149
core/commands/corenet.go
+23 -145
@@ -9,14 +9,10 @@ import (
9 "text/tabwriter"
10
11 cmds "github.com/ipfs/go-ipfs/commands"
12 - core "github.com/ipfs/go-ipfs/core"
13 - corenet "github.com/ipfs/go-ipfs/corenet"
12 + "github.com/ipfs/go-ipfs/core"
13 cnet "github.com/ipfs/go-ipfs/corenet/net"
14
16 - net "gx/ipfs/QmRscs8KxrSmSv4iuevHv8JfuUzHBMoqiaHzxfDRiksd6e/go-libp2p-net"
17 - peerstore "gx/ipfs/QmXZSd1qR5BxZkPyuwfT5jpqQFScZccoZvDneXsKzCNHWX/go-libp2p-peerstore"
15 ma "gx/ipfs/QmcyqRMCAXVtYPS4DiBrA7sezL9rRGfW8Ctx7cywL4TXJj/go-multiaddr"
19 - manet "gx/ipfs/Qmf1Gq7N45Rpuw7ev47uWgH6dLPtdnvcMRNPkVBwqjLJg2/go-multiaddr-net"
16 )
17
18 // CorenetAppInfoOutput is output type of ls command
@@ -188,6 +184,12 @@ var corenetStreamsCmd = &cmds.Command{
184 var corenetListenCmd = &cmds.Command{
185 Helptext: cmds.HelpText{
186 Tagline: "Create application protocol listener and proxy to network multiaddr.",
187 + ShortDescription: `
188 +Register a p2p connection handler and proxies the connections to a specified
189 +address.
190 +
191 +Note that the connections originate from the ipfs daemon process.
192 + `,
193 },
194 Arguments: []cmds.Argument{
195 cmds.StringArg("Protocol", true, false, "Protocol identifier."),
@@ -212,7 +214,7 @@ var corenetListenCmd = &cmds.Command{
214 }
215
216 proto := "/app/" + req.Arguments()[0]
215 - if checkProtoExists(n.PeerHost.Mux().Protocols(), proto) {
217 + if cnet.CheckProtoExists(n, proto) {
218 res.SetError(errors.New("protocol handler already registered"), cmds.ErrNormal)
219 return
220 }
@@ -223,25 +225,12 @@ var corenetListenCmd = &cmds.Command{
225 return
226 }
227
226 - listener, err := cnet.Listen(n, proto)
228 + _, err = cnet.NewListener(n, proto, addr)
229 if err != nil {
230 res.SetError(err, cmds.ErrNormal)
231 return
232 }
233
232 - app := corenet.AppInfo{
233 - Identity: n.Identity,
234 - Protocol: proto,
235 - Address: addr,
236 - Closer: listener,
237 - Running: true,
238 - Registry: &n.Corenet.Apps,
239 - }
240 -
241 - go acceptStreams(n, &app, listener)
242 -
243 - n.Corenet.Apps.Register(&app)
244 -
234 // Successful response.
235 res.SetOutput(&CorenetAppInfoOutput{
236 Protocol: proto,
@@ -250,66 +239,17 @@ var corenetListenCmd = &cmds.Command{
239 },
240 }
241
253 -func checkProtoExists(protos []string, proto string) bool {
254 - for _, p := range protos {
255 - if p != proto {
256 - continue
257 - }
258 - return true
259 - }
260 - return false
261 -}
262 -
263 -func acceptStreams(n *core.IpfsNode, app *corenet.AppInfo, listener cnet.Listener) {
264 - for app.Running {
265 - remote, err := listener.Accept()
266 - if err != nil {
267 - listener.Close()
268 - break
269 - }
270 -
271 - local, err := manet.Dial(app.Address)
272 - if err != nil {
273 - remote.Close()
274 - continue
275 - }
276 -
277 - stream := corenet.StreamInfo{
278 - Protocol: app.Protocol,
279 -
280 - LocalPeer: app.Identity,
281 - LocalAddr: app.Address,
282 -
283 - RemotePeer: remote.Conn().RemotePeer(),
284 - RemoteAddr: remote.Conn().RemoteMultiaddr(),
285 -
286 - Local: local,
287 - Remote: remote,
288 -
289 - Registry: &n.Corenet.Streams,
290 - }
291 -
292 - n.Corenet.Streams.Register(&stream)
293 - startStreaming(&stream)
294 - }
295 - n.Corenet.Apps.Deregister(app.Protocol)
296 -}
297 -
298 -func startStreaming(stream *corenet.StreamInfo) {
299 - go func() {
300 - io.Copy(stream.Local, stream.Remote)
301 - stream.Close()
302 - }()
303 -
304 - go func() {
305 - io.Copy(stream.Remote, stream.Local)
306 - stream.Close()
307 - }()
308 -}
309 -
242 var corenetDialCmd = &cmds.Command{
243 Helptext: cmds.HelpText{
244 Tagline: "Dial to an application service.",
245 +
246 + ShortDescription: `
247 +Establish a new connection to a peer service.
248 +
249 +When a connection is made to a peer service the ipfs daemon will setup one time
250 +TCP listener and return it's bind port, this way a dialing application can
251 +transparently connect to a corenet service.
252 + `,
253 },
254 Arguments: []cmds.Argument{
255 cmds.StringArg("Peer", true, false, "Remote peer to connect to"),
@@ -351,47 +291,12 @@ var corenetDialCmd = &cmds.Command{
291 }
292 }
293
354 - lnet, _, err := manet.DialArgs(bindAddr)
294 + app, err := cnet.Dial(n, addr, peer, proto, bindAddr)
295 if err != nil {
296 res.SetError(err, cmds.ErrNormal)
297 return
298 }
299
360 - app := corenet.AppInfo{
361 - Identity: n.Identity,
362 - Protocol: proto,
363 - }
364 -
365 - n.Peerstore.AddAddr(peer, addr, peerstore.TempAddrTTL)
366 -
367 - remote, err := cnet.Dial(n, peer, proto)
368 - if err != nil {
369 - res.SetError(err, cmds.ErrNormal)
370 - return
371 - }
372 -
373 - switch lnet {
374 - case "tcp", "tcp4", "tcp6":
375 - listener, err := manet.Listen(bindAddr)
376 - if err != nil {
377 - res.SetError(err, cmds.ErrNormal)
378 - if err := remote.Close(); err != nil {
379 - res.SetError(err, cmds.ErrNormal)
380 - }
381 - return
382 - }
383 -
384 - app.Address = listener.Multiaddr()
385 - app.Closer = listener
386 - app.Running = true
387 -
388 - go doAccept(n, &app, remote, listener)
389 -
390 - default:
391 - res.SetError(errors.New("unsupported protocol: "+lnet), cmds.ErrNormal)
392 - return
393 - }
394 -
300 output := CorenetAppInfoOutput{
301 Protocol: app.Protocol,
302 Address: app.Address.String(),
@@ -401,33 +306,6 @@ var corenetDialCmd = &cmds.Command{
306 },
307 }
308
404 -func doAccept(n *core.IpfsNode, app *corenet.AppInfo, remote net.Stream, listener manet.Listener) {
405 - defer listener.Close()
406 -
407 - local, err := listener.Accept()
408 - if err != nil {
409 - return
410 - }
411 -
412 - stream := corenet.StreamInfo{
413 - Protocol: app.Protocol,
414 -
415 - LocalPeer: app.Identity,
416 - LocalAddr: app.Address,
417 -
418 - RemotePeer: remote.Conn().RemotePeer(),
419 - RemoteAddr: remote.Conn().RemoteMultiaddr(),
420 -
421 - Local: local,
422 - Remote: remote,
423 -
424 - Registry: &n.Corenet.Streams,
425 - }
426 -
427 - n.Corenet.Streams.Register(&stream)
428 - startStreaming(&stream)
429 -}
430 -
309 var corenetCloseCmd = &cmds.Command{
310 Helptext: cmds.HelpText{
311 Tagline: "Closes an active stream listener or client.",
@@ -464,15 +342,15 @@ var corenetCloseCmd = &cmds.Command{
342
343 useHandlerID := false
344
467 - if !closeAll && len(req.Arguments()) == 0 {
468 - res.SetError(errors.New("no handlerID nor stream protocol specified"), cmds.ErrNormal)
469 - return
345 + if !closeAll {
346 + if len(req.Arguments()) == 0 {
347 + res.SetError(errors.New("no handlerID nor stream protocol specified"), cmds.ErrNormal)
348 + return
349 + }
350
471 - } else if !closeAll {
351 handlerID, err = strconv.ParseUint(req.Arguments()[0], 10, 64)
352 if err != nil {
353 proto = "/app/" + req.Arguments()[0]
475 -
354 } else {
355 useHandlerID = true
356 }
corenet/apps.go
+7 -3
@@ -5,6 +5,7 @@ import (
5
6 ma "gx/ipfs/QmcyqRMCAXVtYPS4DiBrA7sezL9rRGfW8Ctx7cywL4TXJj/go-multiaddr"
7 peer "gx/ipfs/QmdS9KpbDyPrieswibZhkod1oXqRwZJrUPzxCofAMWpFGq/go-libp2p-peer"
8 + "fmt"
9 )
10
11 // AppInfo holds information on a local application protocol listener service.
@@ -30,9 +31,9 @@ type AppInfo struct {
31
32 // Close closes the listener. Does not affect child streams
33 func (c *AppInfo) Close() error {
33 - c.Registry.Deregister(c.Protocol)
34 c.Closer.Close()
35 - return nil
35 + err := c.Registry.Deregister(c.Protocol)
36 + return err
37 }
38
39 // AppRegistry is a collection of local application protocol listeners.
@@ -46,7 +47,7 @@ func (c *AppRegistry) Register(appInfo *AppInfo) {
47 }
48
49 // Deregister deregisters protocol handler from this registry
49 -func (c *AppRegistry) Deregister(proto string) {
50 +func (c *AppRegistry) Deregister(proto string) error {
51 foundAt := -1
52 for i, a := range c.Apps {
53 if a.Protocol == proto {
@@ -57,5 +58,8 @@ func (c *AppRegistry) Deregister(proto string) {
58
59 if foundAt != -1 {
60 c.Apps = append(c.Apps[:foundAt], c.Apps[foundAt+1:]...)
61 + return nil
62 }
63 +
64 + return fmt.Errorf("failed to deregister proto %s", proto)
65 }
corenet/net/dial.go new
+82
@@ -0,0 +1,82 @@
1 +package net
2 +
3 +import (
4 + "errors"
5 +
6 + core "github.com/ipfs/go-ipfs/core"
7 + corenet "github.com/ipfs/go-ipfs/corenet"
8 +
9 + net "gx/ipfs/QmRscs8KxrSmSv4iuevHv8JfuUzHBMoqiaHzxfDRiksd6e/go-libp2p-net"
10 + peerstore "gx/ipfs/QmXZSd1qR5BxZkPyuwfT5jpqQFScZccoZvDneXsKzCNHWX/go-libp2p-peerstore"
11 + ma "gx/ipfs/QmcyqRMCAXVtYPS4DiBrA7sezL9rRGfW8Ctx7cywL4TXJj/go-multiaddr"
12 + peer "gx/ipfs/QmdS9KpbDyPrieswibZhkod1oXqRwZJrUPzxCofAMWpFGq/go-libp2p-peer"
13 + manet "gx/ipfs/Qmf1Gq7N45Rpuw7ev47uWgH6dLPtdnvcMRNPkVBwqjLJg2/go-multiaddr-net"
14 +)
15 +
16 +func Dial(n *core.IpfsNode, addr ma.Multiaddr, peer peer.ID, proto string, bindAddr ma.Multiaddr) (*corenet.AppInfo, error) {
17 + lnet, _, err := manet.DialArgs(bindAddr)
18 + if err != nil {
19 + return nil, err
20 + }
21 +
22 + app := corenet.AppInfo{
23 + Identity: n.Identity,
24 + Protocol: proto,
25 + }
26 +
27 + n.Peerstore.AddAddr(peer, addr, peerstore.TempAddrTTL)
28 +
29 + remote, err := dial(n, peer, proto)
30 + if err != nil {
31 + return nil, err
32 + }
33 +
34 + switch lnet {
35 + case "tcp", "tcp4", "tcp6":
36 + listener, err := manet.Listen(bindAddr)
37 + if err != nil {
38 + if err2 := remote.Close(); err2 != nil {
39 + return nil, err2
40 + }
41 + return nil, err
42 + }
43 +
44 + app.Address = listener.Multiaddr()
45 + app.Closer = listener
46 + app.Running = true
47 +
48 + go doAccept(n, &app, remote, listener)
49 +
50 + default:
51 + return nil, errors.New("unsupported protocol: " + lnet)
52 + }
53 +
54 + return &app, nil
55 +}
56 +
57 +func doAccept(n *core.IpfsNode, app *corenet.AppInfo, remote net.Stream, listener manet.Listener) {
58 + defer listener.Close()
59 +
60 + local, err := listener.Accept()
61 + if err != nil {
62 + return
63 + }
64 +
65 + stream := corenet.StreamInfo{
66 + Protocol: app.Protocol,
67 +
68 + LocalPeer: app.Identity,
69 + LocalAddr: app.Address,
70 +
71 + RemotePeer: remote.Conn().RemotePeer(),
72 + RemoteAddr: remote.Conn().RemoteMultiaddr(),
73 +
74 + Local: local,
75 + Remote: remote,
76 +
77 + Registry: &n.Corenet.Streams,
78 + }
79 +
80 + n.Corenet.Streams.Register(&stream)
81 + startStreaming(&stream)
82 +}
corenet/net/listen.go new
+67
@@ -0,0 +1,67 @@
1 +package net
2 +
3 +import (
4 + "github.com/ipfs/go-ipfs/core"
5 + "github.com/ipfs/go-ipfs/corenet"
6 +
7 + ma "gx/ipfs/QmcyqRMCAXVtYPS4DiBrA7sezL9rRGfW8Ctx7cywL4TXJj/go-multiaddr"
8 + manet "gx/ipfs/Qmf1Gq7N45Rpuw7ev47uWgH6dLPtdnvcMRNPkVBwqjLJg2/go-multiaddr-net"
9 +)
10 +
11 +// NewListener creates new corenet listener
12 +func NewListener(n *core.IpfsNode, proto string, addr ma.Multiaddr) (*corenet.AppInfo, error) {
13 + listener, err := Listen(n, proto)
14 + if err != nil {
15 + return nil, err
16 + }
17 +
18 + app := corenet.AppInfo{
19 + Identity: n.Identity,
20 + Protocol: proto,
21 + Address: addr,
22 + Closer: listener,
23 + Running: true,
24 + Registry: &n.Corenet.Apps,
25 + }
26 +
27 + go acceptStreams(n, &app, listener)
28 +
29 + n.Corenet.Apps.Register(&app)
30 +
31 + return &app, nil
32 +}
33 +
34 +func acceptStreams(n *core.IpfsNode, app *corenet.AppInfo, listener Listener) {
35 + for app.Running {
36 + remote, err := listener.Accept()
37 + if err != nil {
38 + listener.Close()
39 + break
40 + }
41 +
42 + local, err := manet.Dial(app.Address)
43 + if err != nil {
44 + remote.Close()
45 + continue
46 + }
47 +
48 + stream := corenet.StreamInfo{
49 + Protocol: app.Protocol,
50 +
51 + LocalPeer: app.Identity,
52 + LocalAddr: app.Address,
53 +
54 + RemotePeer: remote.Conn().RemotePeer(),
55 + RemoteAddr: remote.Conn().RemoteMultiaddr(),
56 +
57 + Local: local,
58 + Remote: remote,
59 +
60 + Registry: &n.Corenet.Streams,
61 + }
62 +
63 + n.Corenet.Streams.Register(&stream)
64 + startStreaming(&stream)
65 + }
66 + n.Corenet.Apps.Deregister(app.Protocol)
67 +}
corenet/net/net.go
+16 -1
@@ -5,6 +5,7 @@ import (
5
6 context "context"
7 core "github.com/ipfs/go-ipfs/core"
8 +
9 net "gx/ipfs/QmRscs8KxrSmSv4iuevHv8JfuUzHBMoqiaHzxfDRiksd6e/go-libp2p-net"
10 pstore "gx/ipfs/QmXZSd1qR5BxZkPyuwfT5jpqQFScZccoZvDneXsKzCNHWX/go-libp2p-peerstore"
11 pro "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol"
@@ -67,7 +68,7 @@ func Listen(nd *core.IpfsNode, protocol string) (*IpfsListener, error) {
68 }
69
70 // Dial dials to a specified node and protocol
70 -func Dial(nd *core.IpfsNode, p peer.ID, protocol string) (net.Stream, error) {
71 +func dial(nd *core.IpfsNode, p peer.ID, protocol string) (net.Stream, error) {
72 ctx, cancel := context.WithTimeout(nd.Context(), time.Second*30)
73 defer cancel()
74 err := nd.PeerHost.Connect(ctx, pstore.PeerInfo{ID: p})
@@ -76,3 +77,17 @@ func Dial(nd *core.IpfsNode, p peer.ID, protocol string) (net.Stream, error) {
77 }
78 return nd.PeerHost.NewStream(nd.Context(), p, pro.ID(protocol))
79 }
80 +
81 +// CheckProtoExists checks whether a protocol handler is registered to
82 +// mux handler
83 +func CheckProtoExists(n *core.IpfsNode, proto string) bool {
84 + protos := n.PeerHost.Mux().Protocols()
85 +
86 + for _, p := range protos {
87 + if p != proto {
88 + continue
89 + }
90 + return true
91 + }
92 + return false
93 +}
corenet/net/util.go new
+19
@@ -0,0 +1,19 @@
1 +package net
2 +
3 +import (
4 + "io"
5 +
6 + corenet "github.com/ipfs/go-ipfs/corenet"
7 +)
8 +
9 +func startStreaming(stream *corenet.StreamInfo) {
10 + go func() {
11 + io.Copy(stream.Local, stream.Remote)
12 + stream.Close()
13 + }()
14 +
15 + go func() {
16 + io.Copy(stream.Remote, stream.Local)
17 + stream.Close()
18 + }()
19 +}