mirror of
https://github.com/ipfs/kubo.git
synced 2025-05-21 00:47:22 +08:00
133 lines
3.2 KiB
Go
133 lines
3.2 KiB
Go
package commands
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
cmds "github.com/ipfs/go-ipfs-cmds"
|
|
"github.com/ipfs/kubo/core/commands/cmdenv"
|
|
peer "github.com/libp2p/go-libp2p/core/peer"
|
|
routing "github.com/libp2p/go-libp2p/core/routing"
|
|
)
|
|
|
|
var ErrNotDHT = errors.New("routing service is not a DHT")
|
|
|
|
var DhtCmd = &cmds.Command{
|
|
Status: cmds.Deprecated,
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Issue commands directly through the DHT.",
|
|
ShortDescription: ``,
|
|
},
|
|
|
|
Subcommands: map[string]*cmds.Command{
|
|
"query": queryDhtCmd,
|
|
"findprovs": RemovedDHTCmd,
|
|
"findpeer": RemovedDHTCmd,
|
|
"get": RemovedDHTCmd,
|
|
"put": RemovedDHTCmd,
|
|
"provide": RemovedDHTCmd,
|
|
},
|
|
}
|
|
|
|
// kademlia extends the routing interface with a command to get the peers closest to the target
|
|
type kademlia interface {
|
|
routing.Routing
|
|
GetClosestPeers(ctx context.Context, key string) ([]peer.ID, error)
|
|
}
|
|
|
|
var queryDhtCmd = &cmds.Command{
|
|
Status: cmds.Deprecated,
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Find the closest Peer IDs to a given Peer ID by querying the DHT.",
|
|
ShortDescription: "Outputs a list of newline-delimited Peer IDs.",
|
|
},
|
|
|
|
Arguments: []cmds.Argument{
|
|
cmds.StringArg("peerID", true, true, "The peerID to run the query against."),
|
|
},
|
|
Options: []cmds.Option{
|
|
cmds.BoolOption(dhtVerboseOptionName, "v", "Print extra information."),
|
|
},
|
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
|
nd, err := cmdenv.GetNode(env)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if nd.DHTClient == nil {
|
|
return ErrNotDHT
|
|
}
|
|
|
|
id, err := peer.Decode(req.Arguments[0])
|
|
if err != nil {
|
|
return cmds.ClientError("invalid peer ID")
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(req.Context)
|
|
defer cancel()
|
|
ctx, events := routing.RegisterForQueryEvents(ctx)
|
|
|
|
client := nd.DHTClient
|
|
if client == nd.DHT {
|
|
client = nd.DHT.WAN
|
|
if !nd.DHT.WANActive() {
|
|
client = nd.DHT.LAN
|
|
}
|
|
}
|
|
|
|
if d, ok := client.(kademlia); !ok {
|
|
return fmt.Errorf("dht client does not support GetClosestPeers")
|
|
} else {
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
defer close(errCh)
|
|
defer cancel()
|
|
closestPeers, err := d.GetClosestPeers(ctx, string(id))
|
|
for _, p := range closestPeers {
|
|
routing.PublishQueryEvent(ctx, &routing.QueryEvent{
|
|
ID: p,
|
|
Type: routing.FinalPeer,
|
|
})
|
|
}
|
|
|
|
if err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
}()
|
|
|
|
for e := range events {
|
|
if err := res.Emit(e); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return <-errCh
|
|
}
|
|
},
|
|
Encoders: cmds.EncoderMap{
|
|
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error {
|
|
pfm := pfuncMap{
|
|
routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error {
|
|
fmt.Fprintf(out, "%s\n", obj.ID)
|
|
return nil
|
|
},
|
|
}
|
|
verbose, _ := req.Options[dhtVerboseOptionName].(bool)
|
|
return printEvent(out, w, verbose, pfm)
|
|
}),
|
|
},
|
|
Type: routing.QueryEvent{},
|
|
}
|
|
var RemovedDHTCmd = &cmds.Command{
|
|
Status: cmds.Removed,
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Removed, use 'ipfs routing' instead.",
|
|
},
|
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
|
return errors.New("removed, use 'ipfs routing' instead")
|
|
},
|
|
}
|