Permalink
Cannot retrieve contributors at this time
171 lines (150 sloc)
4.44 KB
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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{ | |
| Helptext: cmds.HelpText{ | |
| Tagline: "Issue commands directly through the DHT.", | |
| ShortDescription: ``, | |
| }, | |
| Subcommands: map[string]*cmds.Command{ | |
| "query": queryDhtCmd, | |
| "findprovs": findProvidersDhtCmd, | |
| "findpeer": findPeerDhtCmd, | |
| "get": getValueDhtCmd, | |
| "put": putValueDhtCmd, | |
| "provide": provideRefDhtCmd, | |
| }, | |
| } | |
| var findProvidersDhtCmd = &cmds.Command{ | |
| Helptext: findProvidersRoutingCmd.Helptext, | |
| Arguments: findProvidersRoutingCmd.Arguments, | |
| Options: findProvidersRoutingCmd.Options, | |
| Run: findProvidersRoutingCmd.Run, | |
| Encoders: findProvidersRoutingCmd.Encoders, | |
| Type: findProvidersRoutingCmd.Type, | |
| Status: cmds.Deprecated, | |
| } | |
| var findPeerDhtCmd = &cmds.Command{ | |
| Helptext: findPeerRoutingCmd.Helptext, | |
| Arguments: findPeerRoutingCmd.Arguments, | |
| Options: findPeerRoutingCmd.Options, | |
| Run: findPeerRoutingCmd.Run, | |
| Encoders: findPeerRoutingCmd.Encoders, | |
| Type: findPeerRoutingCmd.Type, | |
| Status: cmds.Deprecated, | |
| } | |
| var getValueDhtCmd = &cmds.Command{ | |
| Helptext: getValueRoutingCmd.Helptext, | |
| Arguments: getValueRoutingCmd.Arguments, | |
| Options: getValueRoutingCmd.Options, | |
| Run: getValueRoutingCmd.Run, | |
| Encoders: getValueRoutingCmd.Encoders, | |
| Type: getValueRoutingCmd.Type, | |
| Status: cmds.Deprecated, | |
| } | |
| var putValueDhtCmd = &cmds.Command{ | |
| Helptext: putValueRoutingCmd.Helptext, | |
| Arguments: putValueRoutingCmd.Arguments, | |
| Options: putValueRoutingCmd.Options, | |
| Run: putValueRoutingCmd.Run, | |
| Encoders: putValueRoutingCmd.Encoders, | |
| Type: putValueRoutingCmd.Type, | |
| Status: cmds.Deprecated, | |
| } | |
| var provideRefDhtCmd = &cmds.Command{ | |
| Helptext: provideRefRoutingCmd.Helptext, | |
| Arguments: provideRefRoutingCmd.Arguments, | |
| Options: provideRefRoutingCmd.Options, | |
| Run: provideRefRoutingCmd.Run, | |
| Encoders: provideRefRoutingCmd.Encoders, | |
| Type: provideRefRoutingCmd.Type, | |
| Status: cmds.Deprecated, | |
| } | |
| // 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{ | |
| 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{}, | |
| } |