github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/cmd/ipfs/bootstrap.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  
     7  	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
     8  	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
     9  	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
    10  	mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
    11  
    12  	config "github.com/jbenet/go-ipfs/config"
    13  	peer "github.com/jbenet/go-ipfs/peer"
    14  	u "github.com/jbenet/go-ipfs/util"
    15  )
    16  
    17  var cmdIpfsBootstrap = &commander.Command{
    18  	UsageLine: "bootstrap",
    19  	Short:     "Show a list of bootstrapped addresses.",
    20  	Long: `ipfs bootstrap - show, or manipulate bootstrap node addresses
    21  
    22  Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
    23  
    24  Commands:
    25  
    26  	list               Show the boostrap list.
    27  	add <address>      Add a node's address to the bootstrap list.
    28  	remove <address>   Remove an address from the bootstrap list.
    29  
    30  ` + bootstrapSecurityWarning,
    31  	Run: bootstrapListCmd,
    32  	Subcommands: []*commander.Command{
    33  		cmdIpfsBootstrapRemove,
    34  		cmdIpfsBootstrapAdd,
    35  		cmdIpfsBootstrapList,
    36  	},
    37  	Flag: *flag.NewFlagSet("ipfs-bootstrap", flag.ExitOnError),
    38  }
    39  
    40  var cmdIpfsBootstrapRemove = &commander.Command{
    41  	UsageLine: "remove <address | peerid>",
    42  	Short:     "Remove addresses from the bootstrap list.",
    43  	Long: `ipfs bootstrap remove - remove addresses from the bootstrap list
    44  ` + bootstrapSecurityWarning,
    45  	Run:  bootstrapRemoveCmd,
    46  	Flag: *flag.NewFlagSet("ipfs-bootstrap-remove", flag.ExitOnError),
    47  }
    48  
    49  var cmdIpfsBootstrapAdd = &commander.Command{
    50  	UsageLine: "add <address | peerid>",
    51  	Short:     "Add addresses to the bootstrap list.",
    52  	Long: `ipfs bootstrap add - add addresses to the bootstrap list
    53  ` + bootstrapSecurityWarning,
    54  	Run:  bootstrapAddCmd,
    55  	Flag: *flag.NewFlagSet("ipfs-bootstrap-add", flag.ExitOnError),
    56  }
    57  
    58  var cmdIpfsBootstrapList = &commander.Command{
    59  	UsageLine: "list",
    60  	Short:     "Show addresses in the bootstrap list.",
    61  	Run:       bootstrapListCmd,
    62  	Flag:      *flag.NewFlagSet("ipfs-bootstrap-list", flag.ExitOnError),
    63  }
    64  
    65  func bootstrapRemoveCmd(c *commander.Command, inp []string) error {
    66  
    67  	if len(inp) == 0 {
    68  		return errors.New("remove: no address or peerid specified")
    69  	}
    70  
    71  	toRemove, err := bootstrapInputToPeers(inp)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	cfg, err := getConfig(c)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	keep := []*config.BootstrapPeer{}
    82  	remove := []*config.BootstrapPeer{}
    83  
    84  	// function to filer what to keep
    85  	shouldKeep := func(bp *config.BootstrapPeer) bool {
    86  		for _, skipBP := range toRemove {
    87  
    88  			// IDs must match to skip.
    89  			if bp.PeerID != skipBP.PeerID {
    90  				continue
    91  			}
    92  
    93  			// if Addresses match, or skipBP has no addr (wildcard)
    94  			if skipBP.Address == bp.Address || skipBP.Address == "" {
    95  				return false
    96  			}
    97  		}
    98  		return true
    99  	}
   100  
   101  	// filter all the existing peers
   102  	for _, currBP := range cfg.Bootstrap {
   103  		if shouldKeep(currBP) {
   104  			keep = append(keep, currBP)
   105  		} else {
   106  			remove = append(remove, currBP)
   107  		}
   108  	}
   109  
   110  	// if didn't remove anyone, bail.
   111  	if len(keep) == len(cfg.Bootstrap) {
   112  		return errors.New("remove: peer given did not match any in list")
   113  	}
   114  
   115  	// write new config
   116  	cfg.Bootstrap = keep
   117  	if err := writeConfig(c, cfg); err != nil {
   118  		return err
   119  	}
   120  
   121  	for _, bp := range remove {
   122  		u.POut("removed %s\n", bp)
   123  	}
   124  	return nil
   125  }
   126  
   127  func bootstrapAddCmd(c *commander.Command, inp []string) error {
   128  
   129  	if len(inp) == 0 {
   130  		return errors.New("add: no address specified")
   131  	}
   132  
   133  	toAdd, err := bootstrapInputToPeers(inp)
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	cfg, err := getConfig(c)
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	// function to check whether a peer is already in the list.
   144  	combine := func(lists ...[]*config.BootstrapPeer) []*config.BootstrapPeer {
   145  
   146  		set := map[string]struct{}{}
   147  		final := []*config.BootstrapPeer{}
   148  
   149  		for _, list := range lists {
   150  			for _, peer := range list {
   151  				// if already in the set, continue
   152  				_, found := set[peer.String()]
   153  				if found {
   154  					continue
   155  				}
   156  
   157  				set[peer.String()] = struct{}{}
   158  				final = append(final, peer)
   159  			}
   160  		}
   161  		return final
   162  	}
   163  
   164  	// combine both lists, removing dups.
   165  	cfg.Bootstrap = combine(cfg.Bootstrap, toAdd)
   166  	if err := writeConfig(c, cfg); err != nil {
   167  		return err
   168  	}
   169  
   170  	for _, bp := range toAdd {
   171  		u.POut("added %s\n", bp)
   172  	}
   173  	return nil
   174  }
   175  
   176  func bootstrapListCmd(c *commander.Command, inp []string) error {
   177  
   178  	cfg, err := getConfig(c)
   179  	if err != nil {
   180  		return err
   181  	}
   182  
   183  	for _, bp := range cfg.Bootstrap {
   184  		u.POut("%s\n", bp)
   185  	}
   186  
   187  	return nil
   188  }
   189  
   190  func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
   191  	split := func(addr string) (string, string) {
   192  		idx := strings.LastIndex(addr, "/")
   193  		if idx == -1 {
   194  			return "", addr
   195  		}
   196  		return addr[:idx], addr[idx+1:]
   197  	}
   198  
   199  	peers := []*config.BootstrapPeer{}
   200  	for _, addr := range input {
   201  		addrS, peeridS := split(addr)
   202  
   203  		// make sure addrS parses as a multiaddr.
   204  		if len(addrS) > 0 {
   205  			maddr, err := ma.NewMultiaddr(addrS)
   206  			if err != nil {
   207  				return nil, err
   208  			}
   209  
   210  			addrS = maddr.String()
   211  		}
   212  
   213  		// make sure idS parses as a peer.ID
   214  		peerid, err := mh.FromB58String(peeridS)
   215  		if err != nil {
   216  			return nil, err
   217  		}
   218  
   219  		// construct config entry
   220  		peers = append(peers, &config.BootstrapPeer{
   221  			Address: addrS,
   222  			PeerID:  peer.ID(peerid).Pretty(),
   223  		})
   224  	}
   225  	return peers, nil
   226  }
   227  
   228  const bootstrapSecurityWarning = `
   229  SECURITY WARNING:
   230  
   231  The bootstrap command manipulates the "bootstrap list", which contains
   232  the addresses of bootstrap nodes. These are the *trusted peers* from
   233  which to learn about other peers in the network. Only edit this list
   234  if you understand the risks of adding or removing nodes from this list.
   235  
   236  `