Commit abefd93f authored by Juan Batiz-Benet's avatar Juan Batiz-Benet

edited bootstrap cmd

- safer parsing
- multiple inputs
- add: dup detection
- common cfg writing
parent 091f6f85
package main
import (
"fmt"
"errors"
"strings"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
config "github.com/jbenet/go-ipfs/config"
"strings"
peer "github.com/jbenet/go-ipfs/peer"
u "github.com/jbenet/go-ipfs/util"
)
var cmdIpfsBootstrap = &commander.Command{
......@@ -14,13 +19,6 @@ var cmdIpfsBootstrap = &commander.Command{
Short: "Show a list of bootstrapped addresses.",
Long: `ipfs bootstrap - show, or manipulate bootstrap node addresses
SECURITY WARNING:
The bootstrap command manipulates the "bootstrap list", which contains
the addresses of bootstrap nodes. These are the *trusted peers* from
which to learn about other peers in the network. Only edit this list
if you understand the risks of adding or removing nodes from this list.
Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
Commands:
......@@ -29,150 +27,228 @@ Commands:
add <address> Add a node's address to the bootstrap list.
remove <address> Remove an address from the bootstrap list.
`,
Run: bootstrapCmd,
` + bootstrapSecurityWarning,
Run: bootstrapListCmd,
Subcommands: []*commander.Command{
cmdIpfsBootstrapRemove,
cmdIpfsBootstrapAdd,
cmdIpfsBootstrapList,
},
Flag: *flag.NewFlagSet("ipfs-bootstrap", flag.ExitOnError),
}
var cmdIpfsBootstrapRemove = &commander.Command{
UsageLine: "remove",
Run: IpfsBootstrapRemoveCmd,
UsageLine: "remove <address | peerid>",
Short: "Remove addresses from the bootstrap list.",
Long: `ipfs bootstrap remove - remove addresses from the bootstrap list
` + bootstrapSecurityWarning,
Run: bootstrapRemoveCmd,
Flag: *flag.NewFlagSet("ipfs-bootstrap-remove", flag.ExitOnError),
}
var cmdIpfsBootstrapAdd = &commander.Command{
UsageLine: "add",
Run: IpfsBootstrapAddCmd,
UsageLine: "add <address | peerid>",
Short: "Add addresses to the bootstrap list.",
Long: `ipfs bootstrap add - add addresses to the bootstrap list
` + bootstrapSecurityWarning,
Run: bootstrapAddCmd,
Flag: *flag.NewFlagSet("ipfs-bootstrap-add", flag.ExitOnError),
}
func IpfsBootstrapRemoveCmd(c *commander.Command, inp []string) error {
var cmdIpfsBootstrapList = &commander.Command{
UsageLine: "list",
Short: "Show addresses in the bootstrap list.",
Run: bootstrapListCmd,
Flag: *flag.NewFlagSet("ipfs-bootstrap-list", flag.ExitOnError),
}
func bootstrapRemoveCmd(c *commander.Command, inp []string) error {
if len(inp) == 0 {
fmt.Println("No peer specified.")
return nil
return errors.New("remove: no address or peerid specified")
}
if strings.Contains(inp[0], "/") {
toRemove, err := bootstrapInputToPeers(inp)
if err != nil {
return err
}
var pID = inp[0][len(inp[0])-46:]
var ip = strings.TrimSuffix(inp[0], pID)
maddr, err := ma.NewMultiaddr(strings.TrimSuffix(ip, "/"))
var address, _ = maddr.String()
cfg, err := getConfig(c)
if err != nil {
return err
}
peer := config.BootstrapPeer{
Address: address,
PeerID: pID,
keep := []*config.BootstrapPeer{}
remove := []*config.BootstrapPeer{}
// function to filer what to keep
shouldKeep := func(bp *config.BootstrapPeer) bool {
for _, skipBP := range toRemove {
// IDs must match to skip.
if bp.PeerID != skipBP.PeerID {
continue
}
configpath, _ := config.Filename("~/.go-ipfs/config")
var cfg config.Config
readErr := config.ReadConfigFile(configpath, &cfg)
if readErr != nil {
return readErr
// if Addresses match, or skipBP has no addr (wildcard)
if skipBP.Address == bp.Address || skipBP.Address == "" {
return false
}
}
return true
}
i := 0
for _, v := range cfg.Bootstrap {
if v.PeerID == peer.PeerID && v.Address == peer.Address {
continue
// filter all the existing peers
for _, currBP := range cfg.Bootstrap {
if shouldKeep(currBP) {
keep = append(keep, currBP)
} else {
remove = append(remove, currBP)
}
cfg.Bootstrap[i] = v
i++
}
cfg.Bootstrap = cfg.Bootstrap[:i]
writeErr := config.WriteConfigFile(configpath, cfg)
if writeErr != nil {
return writeErr
// if didn't remove anyone, bail.
if len(keep) == len(cfg.Bootstrap) {
return errors.New("remove: peer given did not match any in list")
}
// write new config
cfg.Bootstrap = keep
if err := writeConfig(c, cfg); err != nil {
return err
}
if !strings.Contains(inp[0], "/") {
for _, bp := range remove {
u.POut("removed %s\n", bp)
}
return nil
}
var peerID = inp[0]
func bootstrapAddCmd(c *commander.Command, inp []string) error {
configpath, _ := config.Filename("~/.go-ipfs/config")
var cfg config.Config
readErr := config.ReadConfigFile(configpath, &cfg)
if readErr != nil {
return readErr
if len(inp) == 0 {
return errors.New("add: no address specified")
}
i := 0
for _, v := range cfg.Bootstrap {
if v.PeerID == peerID {
toAdd, err := bootstrapInputToPeers(inp)
if err != nil {
return err
}
cfg, err := getConfig(c)
if err != nil {
return err
}
// function to check whether a peer is already in the list.
combine := func(lists ...[]*config.BootstrapPeer) []*config.BootstrapPeer {
set := map[string]struct{}{}
final := []*config.BootstrapPeer{}
for _, list := range lists {
for _, peer := range list {
// if already in the set, continue
_, found := set[peer.String()]
if found {
continue
}
cfg.Bootstrap[i] = v
i++
set[peer.String()] = struct{}{}
final = append(final, peer)
}
}
return final
}
cfg.Bootstrap = cfg.Bootstrap[:i]
writeErr := config.WriteConfigFile(configpath, cfg)
if writeErr != nil {
return writeErr
// combine both lists, removing dups.
cfg.Bootstrap = combine(cfg.Bootstrap, toAdd)
if err := writeConfig(c, cfg); err != nil {
return err
}
for _, bp := range toAdd {
u.POut("added %s\n", bp)
}
return nil
}
func IpfsBootstrapAddCmd(c *commander.Command, inp []string) error {
func bootstrapListCmd(c *commander.Command, inp []string) error {
if len(inp) == 0 {
fmt.Println("No peer specified.")
return nil
cfg, err := getConfig(c)
if err != nil {
return err
}
for _, bp := range cfg.Bootstrap {
u.POut("%s\n", bp)
}
var pID = inp[0][len(inp[0])-46:]
var ip = strings.TrimSuffix(inp[0], pID)
maddr, err := ma.NewMultiaddr(strings.TrimSuffix(ip, "/"))
var address, _ = maddr.String()
return nil
}
func writeConfig(c *commander.Command, cfg *config.Config) error {
confdir, err := getConfigDir(c)
if err != nil {
return err
}
peer := config.BootstrapPeer{
Address: address,
PeerID: pID,
filename, err := config.Filename(confdir)
if err != nil {
return err
}
configpath, _ := config.Filename("~/.go-ipfs/config")
var cfg config.Config
readErr := config.ReadConfigFile(configpath, &cfg)
if readErr != nil {
return readErr
return config.WriteConfigFile(filename, cfg)
}
func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
split := func(addr string) (string, string) {
idx := strings.LastIndex(addr, "/")
if idx == -1 {
return "", addr
}
return addr[:idx], addr[idx+1:]
}
addedPeer := append(cfg.Bootstrap, &peer)
cfg.Bootstrap = addedPeer
peers := []*config.BootstrapPeer{}
for _, addr := range input {
addrS, peeridS := split(addr)
writeErr := config.WriteConfigFile(configpath, cfg)
if writeErr != nil {
return writeErr
// make sure addrS parses as a multiaddr.
if len(addrS) > 0 {
maddr, err := ma.NewMultiaddr(addrS)
if err != nil {
return nil, err
}
return nil
return nil
}
func bootstrapCmd(c *commander.Command, inp []string) error {
configpath, _ := config.Filename("~/.go-ipfs/config")
var cfg config.Config
config.ReadConfigFile(configpath, &cfg)
for i := range cfg.Bootstrap {
s := []string{cfg.Bootstrap[i].Address, "/", cfg.Bootstrap[i].PeerID, "\n"}
fmt.Printf(strings.Join(s, ""))
addrS, err = maddr.String()
if err != nil {
return nil, err
}
}
return nil
// make sure idS parses as a peer.ID
peerid, err := mh.FromB58String(peeridS)
if err != nil {
return nil, err
}
// construct config entry
peers = append(peers, &config.BootstrapPeer{
Address: addrS,
PeerID: peer.ID(peerid).Pretty(),
})
}
return peers, nil
}
const bootstrapSecurityWarning = `
SECURITY WARNING:
The bootstrap command manipulates the "bootstrap list", which contains
the addresses of bootstrap nodes. These are the *trusted peers* from
which to learn about other peers in the network. Only edit this list
if you understand the risks of adding or removing nodes from this list.
`
......@@ -35,6 +35,10 @@ type BootstrapPeer struct {
PeerID string // until multiaddr supports ipfs, use another field.
}
func (bp *BootstrapPeer) String() string {
return bp.Address + "/" + bp.PeerID
}
// Config is used to load IPFS config files.
type Config struct {
Identity Identity // local node's peer identity
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment