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,165 +19,236 @@ 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:
list Show the boostrap list.
add <address> Add a node's address to the bootstrap list.
remove <address> Remove an address from the bootstrap list.
list Show the boostrap list.
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,
Flag: *flag.NewFlagSet("ipfs-bootstrap-remove", flag.ExitOnError),
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,
Flag: *flag.NewFlagSet("ipfs-bootstrap-add", flag.ExitOnError),
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()
if err != nil {
return err
}
cfg, err := getConfig(c)
if err != nil {
return err
}
peer := config.BootstrapPeer{
Address: address,
PeerID: pID,
}
keep := []*config.BootstrapPeer{}
remove := []*config.BootstrapPeer{}
configpath, _ := config.Filename("~/.go-ipfs/config")
var cfg config.Config
readErr := config.ReadConfigFile(configpath, &cfg)
if readErr != nil {
return readErr
}
// function to filer what to keep
shouldKeep := func(bp *config.BootstrapPeer) bool {
for _, skipBP := range toRemove {
i := 0
for _, v := range cfg.Bootstrap {
if v.PeerID == peer.PeerID && v.Address == peer.Address {
// IDs must match to skip.
if bp.PeerID != skipBP.PeerID {
continue
}
cfg.Bootstrap[i] = v
i++
}
cfg.Bootstrap = cfg.Bootstrap[:i]
writeErr := config.WriteConfigFile(configpath, cfg)
if writeErr != nil {
return writeErr
// if Addresses match, or skipBP has no addr (wildcard)
if skipBP.Address == bp.Address || skipBP.Address == "" {
return false
}
}
return true
}
if !strings.Contains(inp[0], "/") {
var peerID = inp[0]
configpath, _ := config.Filename("~/.go-ipfs/config")
var cfg config.Config
readErr := config.ReadConfigFile(configpath, &cfg)
if readErr != nil {
return readErr
// filter all the existing peers
for _, currBP := range cfg.Bootstrap {
if shouldKeep(currBP) {
keep = append(keep, currBP)
} else {
remove = append(remove, currBP)
}
}
i := 0
for _, v := range cfg.Bootstrap {
if v.PeerID == peerID {
continue
}
cfg.Bootstrap[i] = v
i++
}
cfg.Bootstrap = cfg.Bootstrap[:i]
// if didn't remove anyone, bail.
if len(keep) == len(cfg.Bootstrap) {
return errors.New("remove: peer given did not match any in list")
}
writeErr := config.WriteConfigFile(configpath, cfg)
if writeErr != nil {
return writeErr
}
// write new config
cfg.Bootstrap = keep
if err := writeConfig(c, cfg); err != nil {
return err
}
for _, bp := range remove {
u.POut("removed %s\n", bp)
}
return nil
}
func IpfsBootstrapAddCmd(c *commander.Command, inp []string) error {
func bootstrapAddCmd(c *commander.Command, inp []string) error {
if len(inp) == 0 {
fmt.Println("No peer specified.")
return nil
return errors.New("add: no address specified")
}
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()
toAdd, err := bootstrapInputToPeers(inp)
if err != nil {
return err
}
peer := config.BootstrapPeer{
Address: address,
PeerID: pID,
cfg, err := getConfig(c)
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
// 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
}
set[peer.String()] = struct{}{}
final = append(final, peer)
}
}
return final
}
addedPeer := append(cfg.Bootstrap, &peer)
cfg.Bootstrap = addedPeer
// combine both lists, removing dups.
cfg.Bootstrap = combine(cfg.Bootstrap, toAdd)
if err := writeConfig(c, cfg); err != nil {
return err
}
writeErr := config.WriteConfigFile(configpath, cfg)
if writeErr != nil {
return writeErr
for _, bp := range toAdd {
u.POut("added %s\n", bp)
}
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)
func bootstrapListCmd(c *commander.Command, inp []string) error {
for i := range cfg.Bootstrap {
s := []string{cfg.Bootstrap[i].Address, "/", cfg.Bootstrap[i].PeerID, "\n"}
fmt.Printf(strings.Join(s, ""))
cfg, err := getConfig(c)
if err != nil {
return err
}
for _, bp := range cfg.Bootstrap {
u.POut("%s\n", bp)
}
return nil
}
func writeConfig(c *commander.Command, cfg *config.Config) error {
confdir, err := getConfigDir(c)
if err != nil {
return err
}
filename, err := config.Filename(confdir)
if err != nil {
return err
}
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:]
}
peers := []*config.BootstrapPeer{}
for _, addr := range input {
addrS, peeridS := split(addr)
// make sure addrS parses as a multiaddr.
if len(addrS) > 0 {
maddr, err := ma.NewMultiaddr(addrS)
if err != nil {
return nil, err
}
addrS, err = maddr.String()
if err != nil {
return nil, err
}
}
// 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