@cryptotaxi247 / kubo / commits / 069966d55

ping WIP

License: MIT Signed-off-by: Brian Tiger Chow <brian@perfmode.com> Conflicts: core/commands/root.go begin ping command, WIP finish initial ping implementation

Brian Tiger Chow committed Dec 4, 2014 at 21:31 UTC 069966d55a0f9ee7d6e1b6f084d54ce8a331f7f0
4 files changed +116
core/commands/ping.go new
+108
@@ -0,0 +1,108 @@
1 +package commands
2 +
3 +import (
4 + "bytes"
5 + "fmt"
6 + "io"
7 + "time"
8 +
9 + cmds "github.com/jbenet/go-ipfs/commands"
10 + peer "github.com/jbenet/go-ipfs/p2p/peer"
11 + u "github.com/jbenet/go-ipfs/util"
12 +
13 + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
14 +)
15 +
16 +type PingResult struct {
17 + Success bool
18 + Time time.Duration
19 +}
20 +
21 +var PingCmd = &cmds.Command{
22 + Helptext: cmds.HelpText{
23 + Tagline: "send echo request packets to IPFS hosts",
24 + Synopsis: `
25 +ipfs ping <peer.ID> - Send pings to a peer using the routing system to discover its address
26 +`,
27 + ShortDescription: `
28 +ipfs ping is a tool to find a node (in the routing system),
29 +send pings, wait for pongs, and print out round-trip latency information.
30 +`,
31 + },
32 + Arguments: []cmds.Argument{
33 + cmds.StringArg("peer-id", true, true, "ID of peer to ping"),
34 + },
35 + Marshalers: cmds.MarshalerMap{
36 + cmds.Text: func(res cmds.Response) (io.Reader, error) {
37 + outChan, ok := res.Output().(chan interface{})
38 + if !ok {
39 + return nil, u.ErrCast()
40 + }
41 +
42 + marshal := func(v interface{}) (io.Reader, error) {
43 + obj, ok := v.(*PingResult)
44 + if !ok {
45 + return nil, u.ErrCast()
46 + }
47 +
48 + buf := new(bytes.Buffer)
49 + if obj.Success {
50 + fmt.Fprintf(buf, "Pong took %.2fms\n", obj.Time.Seconds()*1000)
51 + } else {
52 + fmt.Fprintf(buf, "Pong failed\n")
53 + }
54 + return buf, nil
55 + }
56 +
57 + return &cmds.ChannelMarshaler{
58 + Channel: outChan,
59 + Marshaler: marshal,
60 + }, nil
61 + },
62 + },
63 + Run: func(req cmds.Request) (interface{}, error) {
64 + n, err := req.Context().GetNode()
65 + if err != nil {
66 + return nil, err
67 + }
68 +
69 + if !n.OnlineMode() {
70 + return nil, errNotOnline
71 + }
72 +
73 + peerID, err := peer.IDB58Decode("QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ")
74 + if err != nil {
75 + return nil, err
76 + }
77 + const kPingTimeout = 10 * time.Second
78 + ctx, _ := context.WithTimeout(context.Background(), kPingTimeout)
79 + p, err := n.Routing.FindPeer(ctx, peerID)
80 + if err != nil {
81 + return nil, err
82 + }
83 +
84 + outChan := make(chan interface{})
85 +
86 + go func() {
87 + defer close(outChan)
88 + for i := 0; i < 10; i++ {
89 + ctx, _ = context.WithTimeout(context.Background(), kPingTimeout)
90 + before := time.Now()
91 + err := n.Routing.Ping(ctx, p.ID)
92 + if err != nil {
93 + outChan <- &PingResult{}
94 + break
95 + }
96 + took := time.Now().Sub(before)
97 + outChan <- &PingResult{
98 + Success: true,
99 + Time: took,
100 + }
101 + time.Sleep(time.Second)
102 + }
103 + }()
104 +
105 + return outChan, nil
106 + },
107 + Type: PingResult{},
108 +}
core/commands/root.go
+1
@@ -81,6 +81,7 @@ var rootSubcommands = map[string]*cmds.Command{
81 "pin": PinCmd,
82 "refs": RefsCmd,
83 "swarm": SwarmCmd,
84 + "ping": PingCmd,
85 "update": UpdateCmd,
86 "version": VersionCmd,
87 }
routing/mock/centralized_client.go
+4
@@ -79,4 +79,8 @@ func (c *client) Provide(_ context.Context, key u.Key) error {
79 return c.server.Announce(info, key)
80 }
81
82 +func (c *client) Ping(ctx context.Context, p peer.ID) error {
83 + return nil
84 +}
85 +
86 var _ routing.IpfsRouting = &client{}
routing/routing.go
+3
@@ -36,4 +36,7 @@ type IpfsRouting interface {
36 // FindPeer searches for a peer with given ID, returns a peer.PeerInfo
37 // with relevant addresses.
38 FindPeer(context.Context, peer.ID) (peer.PeerInfo, error)
39 +
40 + // Ping a peer, log the time it took
41 + Ping(context.Context, peer.ID) error
42 }