github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/core/commands/id.go (about) 1 package commands 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/json" 7 "errors" 8 "io" 9 "strings" 10 11 b58 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" 12 13 cmds "github.com/ipfs/go-ipfs/commands" 14 core "github.com/ipfs/go-ipfs/core" 15 ic "github.com/ipfs/go-ipfs/p2p/crypto" 16 "github.com/ipfs/go-ipfs/p2p/peer" 17 identify "github.com/ipfs/go-ipfs/p2p/protocol/identify" 18 kb "github.com/ipfs/go-ipfs/routing/kbucket" 19 u "github.com/ipfs/go-ipfs/util" 20 ) 21 22 const offlineIdErrorMessage = `ID command fails when run without daemon, we are working to fix this. 23 In the meantime, please run the daemon if you want to use 'ipfs id': 24 25 ipfs daemon & 26 ipfs id QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ 27 ` 28 29 type IdOutput struct { 30 ID string 31 PublicKey string 32 Addresses []string 33 AgentVersion string 34 ProtocolVersion string 35 } 36 37 var IDCmd = &cmds.Command{ 38 Helptext: cmds.HelpText{ 39 Tagline: "Show IPFS Node ID info", 40 ShortDescription: ` 41 Prints out information about the specified peer, 42 if no peer is specified, prints out local peers info. 43 44 ipfs id supports the format option for output with the following keys: 45 <id> : the peers id 46 <aver>: agent version 47 <pver>: protocol version 48 <pubkey>: public key 49 <addrs>: addresses (newline delimited) 50 `, 51 }, 52 Arguments: []cmds.Argument{ 53 cmds.StringArg("peerid", false, false, "peer.ID of node to look up").EnableStdin(), 54 }, 55 Options: []cmds.Option{ 56 cmds.StringOption("f", "format", "optional output format"), 57 }, 58 Run: func(req cmds.Request, res cmds.Response) { 59 node, err := req.InvocContext().GetNode() 60 if err != nil { 61 res.SetError(err, cmds.ErrNormal) 62 return 63 } 64 65 if len(req.Arguments()) == 0 { 66 output, err := printSelf(node) 67 if err != nil { 68 res.SetError(err, cmds.ErrNormal) 69 return 70 } 71 res.SetOutput(output) 72 return 73 } 74 75 pid := req.Arguments()[0] 76 77 id := peer.ID(b58.Decode(pid)) 78 if len(id) == 0 { 79 res.SetError(cmds.ClientError("Invalid peer id"), cmds.ErrClient) 80 return 81 } 82 83 // TODO handle offline mode with polymorphism instead of conditionals 84 if !node.OnlineMode() { 85 res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient) 86 return 87 } 88 89 p, err := node.Routing.FindPeer(req.Context(), id) 90 if err == kb.ErrLookupFailure { 91 res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient) 92 return 93 } 94 if err != nil { 95 res.SetError(err, cmds.ErrNormal) 96 return 97 } 98 99 output, err := printPeer(node.Peerstore, p.ID) 100 if err != nil { 101 res.SetError(err, cmds.ErrNormal) 102 return 103 } 104 res.SetOutput(output) 105 }, 106 Marshalers: cmds.MarshalerMap{ 107 cmds.Text: func(res cmds.Response) (io.Reader, error) { 108 val, ok := res.Output().(*IdOutput) 109 if !ok { 110 return nil, u.ErrCast() 111 } 112 113 format, found, err := res.Request().Option("format").String() 114 if err != nil { 115 return nil, err 116 } 117 if found { 118 output := format 119 output = strings.Replace(output, "<id>", val.ID, -1) 120 output = strings.Replace(output, "<aver>", val.AgentVersion, -1) 121 output = strings.Replace(output, "<pver>", val.ProtocolVersion, -1) 122 output = strings.Replace(output, "<pubkey>", val.PublicKey, -1) 123 output = strings.Replace(output, "<addrs>", strings.Join(val.Addresses, "\n"), -1) 124 output = strings.Replace(output, "\\n", "\n", -1) 125 output = strings.Replace(output, "\\t", "\t", -1) 126 return strings.NewReader(output), nil 127 } else { 128 129 marshaled, err := json.MarshalIndent(val, "", "\t") 130 if err != nil { 131 return nil, err 132 } 133 return bytes.NewReader(marshaled), nil 134 } 135 }, 136 }, 137 Type: IdOutput{}, 138 } 139 140 func printPeer(ps peer.Peerstore, p peer.ID) (interface{}, error) { 141 if p == "" { 142 return nil, errors.New("Attempted to print nil peer!") 143 } 144 145 info := new(IdOutput) 146 info.ID = p.Pretty() 147 148 if pk := ps.PubKey(p); pk != nil { 149 pkb, err := ic.MarshalPublicKey(pk) 150 if err != nil { 151 return nil, err 152 } 153 info.PublicKey = base64.StdEncoding.EncodeToString(pkb) 154 } 155 156 for _, a := range ps.Addrs(p) { 157 info.Addresses = append(info.Addresses, a.String()) 158 } 159 160 if v, err := ps.Get(p, "ProtocolVersion"); err == nil { 161 if vs, ok := v.(string); ok { 162 info.ProtocolVersion = vs 163 } 164 } 165 if v, err := ps.Get(p, "AgentVersion"); err == nil { 166 if vs, ok := v.(string); ok { 167 info.AgentVersion = vs 168 } 169 } 170 171 return info, nil 172 } 173 174 // printing self is special cased as we get values differently. 175 func printSelf(node *core.IpfsNode) (interface{}, error) { 176 info := new(IdOutput) 177 info.ID = node.Identity.Pretty() 178 179 if node.PrivateKey == nil { 180 if err := node.LoadPrivateKey(); err != nil { 181 return nil, err 182 } 183 } 184 185 pk := node.PrivateKey.GetPublic() 186 pkb, err := ic.MarshalPublicKey(pk) 187 if err != nil { 188 return nil, err 189 } 190 info.PublicKey = base64.StdEncoding.EncodeToString(pkb) 191 192 if node.PeerHost != nil { 193 for _, a := range node.PeerHost.Addrs() { 194 s := a.String() + "/ipfs/" + info.ID 195 info.Addresses = append(info.Addresses, s) 196 } 197 } 198 info.ProtocolVersion = identify.IpfsVersion 199 info.AgentVersion = identify.ClientVersion 200 return info, nil 201 }