From 00325b9c126e60ab132eef23c7bbbceefe3ae146 Mon Sep 17 00:00:00 2001 From: Wigy Date: Tue, 27 Dec 2016 10:22:05 +0100 Subject: [PATCH 1/2] Fixing typos while reading code License: MIT Signed-off-by: Wigy --- core/commands/swarm.go | 16 ++++++++-------- exchange/bitswap/network/interface.go | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 3f914839847..c661c0e5a12 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -9,15 +9,15 @@ import ( "sort" cmds "github.com/ipfs/go-ipfs/commands" - repo "github.com/ipfs/go-ipfs/repo" - config "github.com/ipfs/go-ipfs/repo/config" + "github.com/ipfs/go-ipfs/repo" + "github.com/ipfs/go-ipfs/repo/config" "github.com/ipfs/go-ipfs/repo/fsrepo" - iaddr "github.com/ipfs/go-ipfs/thirdparty/ipfsaddr" - swarm "gx/ipfs/QmWfxnAiQ5TnnCgiX9ikVUKFNHRgGhbgKdx5DoKPELD7P4/go-libp2p-swarm" - pstore "gx/ipfs/QmeXj9VAjmYQZxpmVz7VzccbJrpmr8qkCDSjfVNsPTWTYU/go-libp2p-peerstore" + "github.com/ipfs/go-ipfs/thirdparty/ipfsaddr" mafilter "gx/ipfs/QmSMZwvs3n4GBikZ7hKzT17c3bk65FmyZo2JqtJ16swqCv/multiaddr-filter" ma "gx/ipfs/QmUAQaWbKxGCUTuoQVvvicbQNZ9APF5pDGWyAZSe93AtKH/go-multiaddr" + swarm "gx/ipfs/QmWfxnAiQ5TnnCgiX9ikVUKFNHRgGhbgKdx5DoKPELD7P4/go-libp2p-swarm" + pstore "gx/ipfs/QmeXj9VAjmYQZxpmVz7VzccbJrpmr8qkCDSjfVNsPTWTYU/go-libp2p-peerstore" ) type stringList struct { @@ -448,10 +448,10 @@ func stringListMarshaler(res cmds.Response) (io.Reader, error) { // parseAddresses is a function that takes in a slice of string peer addresses // (multiaddr + peerid) and returns slices of multiaddrs and peerids. -func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) { - iaddrs = make([]iaddr.IPFSAddr, len(addrs)) +func parseAddresses(addrs []string) (iaddrs []ipfsaddr.IPFSAddr, err error) { + iaddrs = make([]ipfsaddr.IPFSAddr, len(addrs)) for i, saddr := range addrs { - iaddrs[i], err = iaddr.ParseString(saddr) + iaddrs[i], err = ipfsaddr.ParseString(saddr) if err != nil { return nil, cmds.ClientError("invalid peer address: " + err.Error()) } diff --git a/exchange/bitswap/network/interface.go b/exchange/bitswap/network/interface.go index dfc1b3f029b..9436c10f9a3 100644 --- a/exchange/bitswap/network/interface.go +++ b/exchange/bitswap/network/interface.go @@ -26,7 +26,7 @@ type BitSwapNetwork interface { peer.ID, bsmsg.BitSwapMessage) error - // SetDelegate registers the Reciver to handle messages received from the + // SetDelegate registers the Receiver to handle messages received from the // network. SetDelegate(Receiver) From cd58254e24bcc73acdc8a3f59858f0014d7989b7 Mon Sep 17 00:00:00 2001 From: Wigy Date: Tue, 27 Dec 2016 14:21:04 +0100 Subject: [PATCH 2/2] Implemented discover on the gateway interface License: MIT Signed-off-by: Wigy --- core/commands/root.go | 1 + core/commands/swarm.go | 132 ++++++++++++++++++++++++------------ core/commands/swarm_test.go | 37 ++++++++++ 3 files changed, 127 insertions(+), 43 deletions(-) create mode 100644 core/commands/swarm_test.go diff --git a/core/commands/root.go b/core/commands/root.go index 93687c37ef4..0ae45da572c 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -141,6 +141,7 @@ var rootROSubcommands = map[string]*cmds.Command{ }, "cat": CatCmd, "commands": CommandsDaemonROCmd, + "discover": DiscoverCmd, "dns": DNSCmd, "get": GetCmd, "ls": LsCmd, diff --git a/core/commands/swarm.go b/core/commands/swarm.go index c661c0e5a12..cba6785f657 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -5,10 +5,12 @@ import ( "errors" "fmt" "io" + "math/rand" "path" "sort" cmds "github.com/ipfs/go-ipfs/commands" + "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/repo" "github.com/ipfs/go-ipfs/repo/config" "github.com/ipfs/go-ipfs/repo/fsrepo" @@ -46,6 +48,67 @@ ipfs peers in the internet. }, } +var DiscoverCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Get random peers of the IPFS node.", + ShortDescription: ` +'ipfs discover' is useful for discovering the whole IPFS network without +being a peer on the network. The client starts discovering from some +bootstrap nodes and gets some random nodes. Recursively continuing to +crawl they can reach each node without putting too much strain on any +of the nodes. +`, + }, + Run: func(req cmds.Request, res cmds.Response) { + log.Debug("ipfs discover") + n := getNode(req, res) + if n == nil { + return + } + + conns := n.PeerHost.Network().Conns() + var sample []int = shuffle(len(conns), 5) + + var addrs []string + for _, i := range sample { + pid := conns[i].RemotePeer() + addr := conns[i].RemoteMultiaddr() + + saddr := path.Join(addr.String(), "ipfs", pid.Pretty()) + addrs = append(addrs, saddr) + } + sort.Sort(sort.StringSlice(addrs)) + + res.SetOutput(&stringList{addrs}) + }, + Type: stringList{}, + Marshalers: cmds.MarshalerMap{ + cmds.Text: stringListMarshaler, + }, +} + +func shuffle(input, output int) []int { + indexes := make([]int, input) + for i := range indexes { + indexes[i] = i + } + done := 0 + unsorted := indexes + for done < output { + left := len(unsorted) + if left <= 0 { + break + } + picked := rand.Intn(left) + if picked > 0 { + unsorted[0], unsorted[picked] = unsorted[picked], unsorted[0] + } + unsorted = unsorted[1:] + done += 1 + } + return indexes[:done] +} + var swarmPeersCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List peers with open connections.", @@ -61,14 +124,8 @@ var swarmPeersCmd = &cmds.Command{ Run: func(req cmds.Request, res cmds.Response) { log.Debug("ipfs swarm peers") - n, err := req.InvocContext().GetNode() - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) + n := getNode(req, res) + if n == nil { return } @@ -77,7 +134,6 @@ var swarmPeersCmd = &cmds.Command{ streams, _, _ := req.Option("streams").Bool() conns := n.PeerHost.Network().Conns() - var out connInfos for _, c := range conns { pid := c.RemotePeer() @@ -201,14 +257,8 @@ var swarmAddrsCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) + n := getNode(req, res) + if n == nil { return } @@ -264,14 +314,8 @@ var swarmAddrsLocalCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) + n := getNode(req, res) + if n == nil { return } @@ -311,21 +355,15 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3 cmds.StringArg("address", true, true, "Address of peer to connect to.").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - ctx := req.Context() - n, err := req.InvocContext().GetNode() - if err != nil { - res.SetError(err, cmds.ErrNormal) + n := getNode(req, res) + if n == nil { return } + ctx := req.Context() addrs := req.Arguments() - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) - return - } - snet, ok := n.PeerHost.Network().(*swarm.Network) if !ok { res.SetError(fmt.Errorf("peerhost network was not swarm"), cmds.ErrNormal) @@ -379,19 +417,12 @@ it will reconnect. cmds.StringArg("address", true, true, "Address of peer to disconnect from.").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() - if err != nil { - res.SetError(err, cmds.ErrNormal) + n := getNode(req, res) + if n == nil { return } addrs := req.Arguments() - - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) - return - } - iaddrs, err := parseAddresses(addrs) if err != nil { res.SetError(err, cmds.ErrNormal) @@ -476,6 +507,21 @@ func peersWithAddresses(addrs []string) (pis []pstore.PeerInfo, err error) { return pis, nil } +func getNode(req cmds.Request, res cmds.Response) *core.IpfsNode { + n, err := req.InvocContext().GetNode() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return nil + } + + if n.PeerHost == nil { + res.SetError(errNotOnline, cmds.ErrClient) + return nil + } + + return n +} + var swarmFiltersCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Manipulate address filters.", diff --git a/core/commands/swarm_test.go b/core/commands/swarm_test.go new file mode 100644 index 00000000000..9434ee3b6ce --- /dev/null +++ b/core/commands/swarm_test.go @@ -0,0 +1,37 @@ +package commands + +import ( + "testing" + "sort" +) + +func TestShuffleEmpty(t *testing.T) { + actual := shuffle(0, 3) + assertLen(t, actual, 0) +} + +func TestShuffleSingle(t *testing.T) { + actual := shuffle(1, 3) + assertLen(t, actual, 1) + if actual[0] != 0 { + t.Errorf("Expected 0 as the only value, but got %d", actual[0]) + } +} + +func TestShuffleUnique(t *testing.T) { + actual := shuffle(100, 100) + assertLen(t, actual, 100) + sort.Ints(actual) + for i, v := range actual { + if i != v { + t.Fatalf("Not each value is present exactly once") + } + } +} + +func assertLen(t *testing.T, actual []int, expected int) { + actualLen := len(actual) + if actualLen != expected { + t.Error("Expected a slice with %d items, but got %d", expected, actualLen) + } +}