diff --git a/core/commands2/id.go b/core/commands2/id.go new file mode 100644 index 0000000000000000000000000000000000000000..3a0bd6a77be9be47de7055ec04a3a3c31e13087a --- /dev/null +++ b/core/commands2/id.go @@ -0,0 +1,103 @@ +package commands + +import ( + "encoding/base64" + "encoding/json" + "errors" + "time" + + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" + + b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" + + cmds "github.com/jbenet/go-ipfs/commands" + "github.com/jbenet/go-ipfs/peer" + kb "github.com/jbenet/go-ipfs/routing/kbucket" + u "github.com/jbenet/go-ipfs/util" +) + +const offlineIdErrorMessage = `ID command fails when run without daemon, we are working +to fix this In the meantime, please run the daemon if you want to use 'ipfs id'` + +type IdOutput struct { + ID string + PublicKey string + Addresses []string + AgentVersion string + ProtocolVersion string +} + +var idCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Show IPFS Node ID info", + ShortDescription: ` +Prints out information about the specified peer, +if no peer is specified, prints out local peers info. +`, + }, + Arguments: nil, + Run: func(req cmds.Request) (interface{}, error) { + node, err := req.Context().GetNode() + if err != nil { + return nil, err + } + + if len(req.Arguments()) == 0 { + return printPeer(node.Identity) + } + + pid, ok := req.Arguments()[0].(string) + if !ok { + return nil, errors.New("Improperly formatted peer id") + } + + id := peer.ID(b58.Decode(pid)) + ctx, _ := context.WithTimeout(context.TODO(), time.Second*5) + p, err := node.Routing.FindPeer(ctx, id) + if err == kb.ErrLookupFailure { + return nil, errors.New(offlineIdErrorMessage) + } + if err != nil { + return nil, err + } + return printPeer(p) + }, + Marshalers: cmds.MarshalerMap{ + cmds.Text: func(res cmds.Response) ([]byte, error) { + val, ok := res.Output().(*IdOutput) + if !ok { + return nil, u.ErrCast() + } + + return json.MarshalIndent(val, "", "\t") + }, + }, + Type: &IdOutput{}, +} + +func printPeer(p peer.Peer) (interface{}, error) { + if p == nil { + return nil, errors.New("Attempted to print nil peer!") + } + info := new(IdOutput) + + info.ID = p.ID().String() + if p.PubKey() == nil { + return nil, errors.New(`peer publickey not populated on offline runs, +please run the daemon to use ipfs id!`) + } + pkb, err := p.PubKey().Bytes() + if err != nil { + return nil, err + } + info.PublicKey = base64.StdEncoding.EncodeToString(pkb) + for _, a := range p.Addresses() { + info.Addresses = append(info.Addresses, a.String()) + } + + agent, protocol := p.GetVersions() + info.AgentVersion = agent + info.ProtocolVersion = protocol + + return info, nil +} diff --git a/core/commands2/root.go b/core/commands2/root.go index f71b759557aa1181fd5e6adb1f6b3b1eae608ebb..3e711092e63d2c3b9f35db836f8e76e4b289e54e 100644 --- a/core/commands2/root.go +++ b/core/commands2/root.go @@ -32,6 +32,7 @@ Tool commands: update Download and apply go-ipfs updates version Show ipfs version information commands List all available commands + id Show info about ipfs peers Advanced Commands: @@ -77,6 +78,7 @@ var rootSubcommands = map[string]*cmds.Command{ "update": UpdateCmd, "object": objectCmd, "refs": refsCmd, + "id": idCmd, } func init() { diff --git a/core/core.go b/core/core.go index 716369826a108bfae9acc7f6ac904f669d0aa709..09014cd1108274283b735670eb642d78af802e10 100644 --- a/core/core.go +++ b/core/core.go @@ -18,6 +18,7 @@ import ( merkledag "github.com/jbenet/go-ipfs/merkledag" namesys "github.com/jbenet/go-ipfs/namesys" inet "github.com/jbenet/go-ipfs/net" + handshake "github.com/jbenet/go-ipfs/net/handshake" mux "github.com/jbenet/go-ipfs/net/mux" netservice "github.com/jbenet/go-ipfs/net/service" path "github.com/jbenet/go-ipfs/path" @@ -223,6 +224,8 @@ func initIdentity(cfg *config.Identity, peers peer.Peerstore, online bool) (peer return nil, err } + self.SetVersions(handshake.ClientVersion, handshake.IpfsVersion.String()) + // when not online, don't need to parse private keys (yet) if online { skb, err := base64.StdEncoding.DecodeString(cfg.PrivKey) diff --git a/net/handshake/handshake1.go b/net/handshake/handshake1.go index 306c933908e9f5603f455dd7cc3490a90d720ba4..99f8e2ac741cc14b086897517da5b939d100e430 100644 --- a/net/handshake/handshake1.go +++ b/net/handshake/handshake1.go @@ -10,13 +10,13 @@ import ( semver "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/coreos/go-semver/semver" ) -// ipfsVersion holds the current protocol version for a client running this code -var ipfsVersion *semver.Version -var clientVersion = "go-ipfs/" + config.CurrentVersionNumber +// IpfsVersion holds the current protocol version for a client running this code +var IpfsVersion *semver.Version +var ClientVersion = "go-ipfs/" + config.CurrentVersionNumber func init() { var err error - ipfsVersion, err = semver.NewVersion("0.0.1") + IpfsVersion, err = semver.NewVersion("0.0.1") if err != nil { panic(fmt.Errorf("invalid protocol version: %v", err)) } @@ -24,7 +24,7 @@ func init() { // Handshake1Msg returns the current protocol version as a protobuf message func Handshake1Msg() *pb.Handshake1 { - return NewHandshake1(ipfsVersion.String(), clientVersion) + return NewHandshake1(IpfsVersion.String(), ClientVersion) } // ErrVersionMismatch is returned when two clients don't share a protocol version diff --git a/peer/peer.go b/peer/peer.go index f38a2df211d755809ebc6d4f4ecc56806a9981dc..32751e7b0221c37430a520de293603a4a3e107bc 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -99,6 +99,9 @@ type Peer interface { GetType() Type SetType(Type) + //Get/Set Agent and Protocol Versions + GetVersions() (agent, protocol string) + SetVersions(agent, protocol string) // Update with the data of another peer instance Update(Peer) error @@ -137,6 +140,9 @@ type peer struct { // within that package, map from ID to latency value. latency time.Duration + protocolVersion string + agentVersion string + // typ can be Local, Remote, or Unspecified (default) typ Type @@ -372,6 +378,19 @@ func (p *peer) Update(other Peer) error { return nil } +func (p *peer) GetVersions() (agent, protocol string) { + p.RLock() + defer p.RUnlock() + return p.agentVersion, p.protocolVersion +} + +func (p *peer) SetVersions(agent, protocol string) { + p.Lock() + defer p.Unlock() + p.agentVersion = agent + p.protocolVersion = protocol +} + // WithKeyPair returns a Peer object with given keys. func WithKeyPair(sk ic.PrivKey, pk ic.PubKey) (Peer, error) { if sk == nil && pk == nil {