mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-12 03:37:59 +08:00
Merge pull request #608 from jbenet/ipfs-multiaddr
multiaddrs with .../ipfs/...
This commit is contained in:
commit
fbf1a50a54
17
CHANGELOG.md
Normal file
17
CHANGELOG.md
Normal file
@ -0,0 +1,17 @@
|
||||
# go-ipfs changelog
|
||||
|
||||
Until we near full stability, this changelog must only
|
||||
list breakages and backwards incompatible changes.
|
||||
|
||||
|
||||
### 2015-01-31:
|
||||
|
||||
* bootstrap addresses now have .../ipfs/... in format
|
||||
config file Bootstrap field changed accordingly. users
|
||||
can upgrade cleanly with:
|
||||
|
||||
ipfs bootstrap >boostrap_peers
|
||||
ipfs bootstrap rm --all
|
||||
<install new ipfs>
|
||||
<manually add .../ipfs/... to addrs in bootstrap_peers>
|
||||
ipfs bootstrap add <bootstrap_peers
|
||||
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
@ -167,8 +167,8 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jbenet/go-multiaddr",
|
||||
"Comment": "0.1.2-34-g0d7b54b",
|
||||
"Rev": "0d7b54ba432fda14bac37cdad717bd6270eacc85"
|
||||
"Comment": "0.1.2-38-gc13f11b",
|
||||
"Rev": "c13f11bbfe6439771f4df7bfb330f686826144e8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jbenet/go-multiaddr-net",
|
||||
|
||||
3
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml
generated
vendored
3
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml
generated
vendored
@ -1,10 +1,9 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- release
|
||||
- tip
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
||||
- go test -race -cpu=5 -v ./...
|
||||
|
||||
100
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
generated
vendored
100
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
generated
vendored
@ -2,10 +2,13 @@ package multiaddr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
|
||||
)
|
||||
|
||||
func stringToBytes(s string) ([]byte, error) {
|
||||
@ -31,17 +34,19 @@ func stringToBytes(s string) ([]byte, error) {
|
||||
b = append(b, CodeToVarint(p.Code)...)
|
||||
sp = sp[1:]
|
||||
|
||||
if p.Size > 0 {
|
||||
if len(sp) < 1 {
|
||||
return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
|
||||
}
|
||||
a, err := addressStringToBytes(p, sp[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
|
||||
}
|
||||
b = append(b, a...)
|
||||
sp = sp[1:]
|
||||
if p.Size == 0 { // no length.
|
||||
continue
|
||||
}
|
||||
|
||||
if len(sp) < 1 {
|
||||
return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
|
||||
}
|
||||
a, err := addressStringToBytes(p, sp[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
|
||||
}
|
||||
b = append(b, a...)
|
||||
sp = sp[1:]
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
@ -51,7 +56,14 @@ func bytesToString(b []byte) (ret string, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
ret = ""
|
||||
err = e.(error)
|
||||
switch e := e.(type) {
|
||||
case error:
|
||||
err = e
|
||||
case string:
|
||||
err = errors.New(e)
|
||||
default:
|
||||
err = fmt.Errorf("%v", e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@ -65,20 +77,38 @@ func bytesToString(b []byte) (ret string, err error) {
|
||||
if p.Code == 0 {
|
||||
return "", fmt.Errorf("no protocol with code %d", code)
|
||||
}
|
||||
s = strings.Join([]string{s, "/", p.Name}, "")
|
||||
s += "/" + p.Name
|
||||
|
||||
if p.Size > 0 {
|
||||
a := addressBytesToString(p, b[:(p.Size/8)])
|
||||
if len(a) > 0 {
|
||||
s = strings.Join([]string{s, "/", a}, "")
|
||||
}
|
||||
b = b[(p.Size / 8):]
|
||||
if p.Size == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
size := sizeForAddr(p, b)
|
||||
a, err := addressBytesToString(p, b[:size])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(a) > 0 {
|
||||
s += "/" + a
|
||||
}
|
||||
b = b[size:]
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func sizeForAddr(p Protocol, b []byte) int {
|
||||
switch {
|
||||
case p.Size > 0:
|
||||
return (p.Size / 8)
|
||||
case p.Size == 0:
|
||||
return 0
|
||||
default:
|
||||
size, n := ReadVarintCode(b)
|
||||
return size + n
|
||||
}
|
||||
}
|
||||
|
||||
func bytesSplit(b []byte) (ret [][]byte, err error) {
|
||||
// panic handler, in case we try accessing bytes incorrectly.
|
||||
defer func() {
|
||||
@ -96,7 +126,8 @@ func bytesSplit(b []byte) (ret [][]byte, err error) {
|
||||
return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0])
|
||||
}
|
||||
|
||||
length := n + (p.Size / 8)
|
||||
size := sizeForAddr(p, b[n:])
|
||||
length := n + size
|
||||
ret = append(ret, b[:length])
|
||||
b = b[length:]
|
||||
}
|
||||
@ -133,23 +164,46 @@ func addressStringToBytes(p Protocol, s string) ([]byte, error) {
|
||||
b := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(b, uint16(i))
|
||||
return b, nil
|
||||
|
||||
case P_IPFS: // ipfs
|
||||
// the address is a varint prefixed multihash string representation
|
||||
m, err := mh.FromB58String(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err)
|
||||
}
|
||||
size := CodeToVarint(len(m))
|
||||
b := append(size, m...)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name)
|
||||
}
|
||||
|
||||
func addressBytesToString(p Protocol, b []byte) string {
|
||||
func addressBytesToString(p Protocol, b []byte) (string, error) {
|
||||
switch p.Code {
|
||||
|
||||
// ipv4,6
|
||||
case P_IP4, P_IP6:
|
||||
return net.IP(b).String()
|
||||
return net.IP(b).String(), nil
|
||||
|
||||
// tcp udp dccp sctp
|
||||
case P_TCP, P_UDP, P_DCCP, P_SCTP:
|
||||
i := binary.BigEndian.Uint16(b)
|
||||
return strconv.Itoa(int(i))
|
||||
return strconv.Itoa(int(i)), nil
|
||||
|
||||
case P_IPFS: // ipfs
|
||||
// the address is a varint-prefixed multihash string representation
|
||||
size, n := ReadVarintCode(b)
|
||||
b = b[n:]
|
||||
if len(b) != size {
|
||||
panic("inconsistent lengths")
|
||||
}
|
||||
m, err := mh.Cast(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return m.B58String(), nil
|
||||
}
|
||||
|
||||
return ""
|
||||
return "", fmt.Errorf("unknown protocol")
|
||||
}
|
||||
|
||||
6
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
generated
vendored
6
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
generated
vendored
@ -64,6 +64,7 @@ func (m *multiaddr) Protocols() []Protocol {
|
||||
}
|
||||
}()
|
||||
|
||||
size := 0
|
||||
ps := []Protocol{}
|
||||
b := m.bytes[:]
|
||||
for len(b) > 0 {
|
||||
@ -75,7 +76,10 @@ func (m *multiaddr) Protocols() []Protocol {
|
||||
panic(fmt.Errorf("no protocol with code %d", b[0]))
|
||||
}
|
||||
ps = append(ps, p)
|
||||
b = b[n+(p.Size/8):]
|
||||
b = b[n:]
|
||||
|
||||
size = sizeForAddr(p, b)
|
||||
b = b[size:]
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
12
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
generated
vendored
12
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
generated
vendored
@ -32,11 +32,13 @@ func TestConstructFails(t *testing.T) {
|
||||
"/ip4/127.0.0.1/udp",
|
||||
"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
|
||||
"/ip4/127.0.0.1/tcp",
|
||||
"/ip4/127.0.0.1/ipfs",
|
||||
"/ip4/127.0.0.1/ipfs/tcp",
|
||||
}
|
||||
|
||||
for _, a := range cases {
|
||||
if _, err := NewMultiaddr(a); err == nil {
|
||||
t.Errorf("should have failed: %s", a)
|
||||
t.Errorf("should have failed: %s - %s", a, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -55,18 +57,24 @@ func TestConstructSucceeds(t *testing.T) {
|
||||
"/sctp/1234",
|
||||
"/udp/65535",
|
||||
"/tcp/65535",
|
||||
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"/udp/1234/sctp/1234",
|
||||
"/udp/1234/udt",
|
||||
"/udp/1234/utp",
|
||||
"/tcp/1234/http",
|
||||
"/tcp/1234/https",
|
||||
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
|
||||
"/ip4/127.0.0.1/udp/1234",
|
||||
"/ip4/127.0.0.1/udp/0",
|
||||
"/ip4/127.0.0.1/tcp/1234",
|
||||
"/ip4/127.0.0.1/tcp/1234/",
|
||||
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
|
||||
}
|
||||
|
||||
for _, a := range cases {
|
||||
if _, err := NewMultiaddr(a); err != nil {
|
||||
t.Errorf("should have succeeded: %s", a)
|
||||
t.Errorf("should have succeeded: %s -- %s", a, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv
generated
vendored
1
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv
generated
vendored
@ -7,5 +7,6 @@ code size name
|
||||
132 16 sctp
|
||||
301 0 udt
|
||||
302 0 utp
|
||||
421 V ipfs
|
||||
480 0 http
|
||||
443 0 https
|
||||
|
||||
|
31
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go
generated
vendored
31
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
||||
// Protocol is a Multiaddr protocol description structure.
|
||||
type Protocol struct {
|
||||
Code int
|
||||
Size int
|
||||
Size int // a size of -1 indicates a length-prefixed variable size
|
||||
Name string
|
||||
VCode []byte
|
||||
}
|
||||
@ -19,14 +19,22 @@ type Protocol struct {
|
||||
// 2. ensuring errors in the csv don't screw up code.
|
||||
// 3. changing a number has to happen in two places.
|
||||
const (
|
||||
P_IP4 = 4
|
||||
P_TCP = 6
|
||||
P_UDP = 17
|
||||
P_DCCP = 33
|
||||
P_IP6 = 41
|
||||
P_SCTP = 132
|
||||
P_UTP = 301
|
||||
P_UDT = 302
|
||||
P_IP4 = 4
|
||||
P_TCP = 6
|
||||
P_UDP = 17
|
||||
P_DCCP = 33
|
||||
P_IP6 = 41
|
||||
P_SCTP = 132
|
||||
P_UTP = 301
|
||||
P_UDT = 302
|
||||
P_IPFS = 421
|
||||
P_HTTP = 480
|
||||
P_HTTPS = 443
|
||||
)
|
||||
|
||||
// These are special sizes
|
||||
const (
|
||||
LengthPrefixedVarSize = -1
|
||||
)
|
||||
|
||||
// Protocols is the list of multiaddr protocols supported by this module.
|
||||
@ -40,8 +48,9 @@ var Protocols = []Protocol{
|
||||
Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
|
||||
Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
|
||||
Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
|
||||
// {480, 0, "http"},
|
||||
// {443, 0, "https"},
|
||||
Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
|
||||
Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)},
|
||||
Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)},
|
||||
}
|
||||
|
||||
// ProtocolWithName returns the Protocol description with given string name.
|
||||
|
||||
@ -220,32 +220,25 @@ func bootstrapConnect(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func toPeerInfos(bpeers []config.BootstrapPeer) ([]peer.PeerInfo, error) {
|
||||
func toPeerInfos(bpeers []config.BootstrapPeer) []peer.PeerInfo {
|
||||
var peers []peer.PeerInfo
|
||||
for _, bootstrap := range bpeers {
|
||||
p, err := toPeerInfo(bootstrap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
peers = append(peers, p)
|
||||
peers = append(peers, toPeerInfo(bootstrap))
|
||||
}
|
||||
return peers, nil
|
||||
return peers
|
||||
}
|
||||
|
||||
func toPeerInfo(bootstrap config.BootstrapPeer) (p peer.PeerInfo, err error) {
|
||||
id, err := peer.IDB58Decode(bootstrap.PeerID)
|
||||
if err != nil {
|
||||
return
|
||||
func toPeerInfo(bp config.BootstrapPeer) peer.PeerInfo {
|
||||
// for now, we drop the "ipfs addr" part of the multiaddr. the rest
|
||||
// of the codebase currently uses addresses without the peerid part.
|
||||
m := bp.Multiaddr()
|
||||
s := ma.Split(m)
|
||||
m = ma.Join(s[:len(s)-1]...)
|
||||
|
||||
return peer.PeerInfo{
|
||||
ID: bp.ID(),
|
||||
Addrs: []ma.Multiaddr{m},
|
||||
}
|
||||
maddr, err := ma.NewMultiaddr(bootstrap.Address)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p = peer.PeerInfo{
|
||||
ID: id,
|
||||
Addrs: []ma.Multiaddr{maddr},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func randomSubsetOfPeers(in []peer.PeerInfo, max int) []peer.PeerInfo {
|
||||
|
||||
@ -3,6 +3,7 @@ package commands
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
cmds "github.com/jbenet/go-ipfs/commands"
|
||||
repo "github.com/jbenet/go-ipfs/repo"
|
||||
@ -13,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
type BootstrapOutput struct {
|
||||
Peers []config.BootstrapPeer
|
||||
Peers []string
|
||||
}
|
||||
|
||||
var peerOptionDesc = "A peer to add to the bootstrap list (in the format '<multiaddr>/<peerID>')"
|
||||
@ -90,18 +91,18 @@ in the bootstrap list).
|
||||
inputPeers = append(inputPeers, defltPeers...)
|
||||
}
|
||||
|
||||
if len(inputPeers) == 0 {
|
||||
res.SetError(errors.New("no bootstrap peers to add"), cmds.ErrClient)
|
||||
return
|
||||
}
|
||||
|
||||
added, err := bootstrapAdd(r, cfg, inputPeers)
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
if len(inputPeers) == 0 {
|
||||
res.SetError(errors.New("no bootstrap peers to add"), cmds.ErrClient)
|
||||
return
|
||||
}
|
||||
|
||||
res.SetOutput(&BootstrapOutput{added})
|
||||
res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(added)})
|
||||
},
|
||||
Type: BootstrapOutput{},
|
||||
Marshalers: cmds.MarshalerMap{
|
||||
@ -167,7 +168,7 @@ var bootstrapRemoveCmd = &cmds.Command{
|
||||
return
|
||||
}
|
||||
|
||||
res.SetOutput(&BootstrapOutput{removed})
|
||||
res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(removed)})
|
||||
},
|
||||
Type: BootstrapOutput{},
|
||||
Marshalers: cmds.MarshalerMap{
|
||||
@ -191,14 +192,21 @@ var bootstrapListCmd = &cmds.Command{
|
||||
},
|
||||
|
||||
Run: func(req cmds.Request, res cmds.Response) {
|
||||
cfg, err := req.Context().GetConfig()
|
||||
r := fsrepo.At(req.Context().ConfigRoot)
|
||||
if err := r.Open(); err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
defer r.Close()
|
||||
cfg := r.Config()
|
||||
|
||||
peers, err := cfg.BootstrapPeers()
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
peers := cfg.Bootstrap
|
||||
res.SetOutput(&BootstrapOutput{peers})
|
||||
res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(peers)})
|
||||
return
|
||||
},
|
||||
Type: BootstrapOutput{},
|
||||
Marshalers: cmds.MarshalerMap{
|
||||
@ -217,11 +225,11 @@ func bootstrapMarshaler(res cmds.Response) (io.Reader, error) {
|
||||
return &buf, err
|
||||
}
|
||||
|
||||
func bootstrapWritePeers(w io.Writer, prefix string, peers []config.BootstrapPeer) error {
|
||||
func bootstrapWritePeers(w io.Writer, prefix string, peers []string) error {
|
||||
|
||||
sort.Stable(sort.StringSlice(peers))
|
||||
for _, peer := range peers {
|
||||
s := prefix + peer.Address + "/" + peer.PeerID + "\n"
|
||||
_, err := w.Write([]byte(s))
|
||||
_, err := w.Write([]byte(peer + "\n"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -230,38 +238,55 @@ func bootstrapWritePeers(w io.Writer, prefix string, peers []config.BootstrapPee
|
||||
}
|
||||
|
||||
func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
|
||||
added := make([]config.BootstrapPeer, 0, len(peers))
|
||||
addedMap := map[string]struct{}{}
|
||||
addedList := make([]config.BootstrapPeer, 0, len(peers))
|
||||
|
||||
// re-add cfg bootstrap peers to rm dupes
|
||||
bpeers := cfg.Bootstrap
|
||||
cfg.Bootstrap = nil
|
||||
|
||||
// add new peers
|
||||
for _, peer := range peers {
|
||||
duplicate := false
|
||||
for _, peer2 := range cfg.Bootstrap {
|
||||
if peer.Address == peer2.Address && peer.PeerID == peer2.PeerID {
|
||||
duplicate = true
|
||||
break
|
||||
}
|
||||
s := peer.String()
|
||||
if _, found := addedMap[s]; found {
|
||||
continue
|
||||
}
|
||||
|
||||
if !duplicate {
|
||||
cfg.Bootstrap = append(cfg.Bootstrap, peer)
|
||||
added = append(added, peer)
|
||||
cfg.Bootstrap = append(cfg.Bootstrap, s)
|
||||
addedList = append(addedList, peer)
|
||||
addedMap[s] = struct{}{}
|
||||
}
|
||||
|
||||
// add back original peers. in this order so that we output them.
|
||||
for _, s := range bpeers {
|
||||
if _, found := addedMap[s]; found {
|
||||
continue
|
||||
}
|
||||
|
||||
cfg.Bootstrap = append(cfg.Bootstrap, s)
|
||||
addedMap[s] = struct{}{}
|
||||
}
|
||||
|
||||
if err := r.SetConfig(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return added, nil
|
||||
return addedList, nil
|
||||
}
|
||||
|
||||
func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
|
||||
removed := make([]config.BootstrapPeer, 0, len(toRemove))
|
||||
keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap))
|
||||
|
||||
for _, peer := range cfg.Bootstrap {
|
||||
peers, err := cfg.BootstrapPeers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, peer := range peers {
|
||||
found := false
|
||||
for _, peer2 := range toRemove {
|
||||
if peer.Address == peer2.Address && peer.PeerID == peer2.PeerID {
|
||||
if peer.Equal(peer2) {
|
||||
found = true
|
||||
removed = append(removed, peer)
|
||||
break
|
||||
@ -272,7 +297,7 @@ func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.Bootstra
|
||||
keep = append(keep, peer)
|
||||
}
|
||||
}
|
||||
cfg.Bootstrap = keep
|
||||
cfg.SetBootstrapPeers(keep)
|
||||
|
||||
if err := r.SetConfig(cfg); err != nil {
|
||||
return nil, err
|
||||
@ -282,8 +307,10 @@ func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.Bootstra
|
||||
}
|
||||
|
||||
func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]config.BootstrapPeer, error) {
|
||||
removed := make([]config.BootstrapPeer, len(cfg.Bootstrap))
|
||||
copy(removed, cfg.Bootstrap)
|
||||
removed, err := cfg.BootstrapPeers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.Bootstrap = nil
|
||||
if err := r.SetConfig(cfg); err != nil {
|
||||
|
||||
@ -4,15 +4,14 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"sort"
|
||||
|
||||
cmds "github.com/jbenet/go-ipfs/commands"
|
||||
peer "github.com/jbenet/go-ipfs/p2p/peer"
|
||||
errors "github.com/jbenet/go-ipfs/util/debugerror"
|
||||
iaddr "github.com/jbenet/go-ipfs/util/ipfsaddr"
|
||||
|
||||
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
|
||||
)
|
||||
|
||||
type stringList struct {
|
||||
@ -23,8 +22,9 @@ var SwarmCmd = &cmds.Command{
|
||||
Helptext: cmds.HelpText{
|
||||
Tagline: "swarm inspection tool",
|
||||
Synopsis: `
|
||||
ipfs swarm peers - List peers with open connections
|
||||
ipfs swarm connect <address> - Open connection to a given peer
|
||||
ipfs swarm peers - List peers with open connections
|
||||
ipfs swarm connect <address> - Open connection to a given address
|
||||
ipfs swarm disconnect <address> - Close connection to a given address
|
||||
`,
|
||||
ShortDescription: `
|
||||
ipfs swarm is a tool to manipulate the network swarm. The swarm is the
|
||||
@ -33,8 +33,9 @@ ipfs peers in the internet.
|
||||
`,
|
||||
},
|
||||
Subcommands: map[string]*cmds.Command{
|
||||
"peers": swarmPeersCmd,
|
||||
"connect": swarmConnectCmd,
|
||||
"peers": swarmPeersCmd,
|
||||
"connect": swarmConnectCmd,
|
||||
"disconnect": swarmDisconnectCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -64,7 +65,7 @@ ipfs swarm peers lists the set of peers this node is connected to.
|
||||
for i, c := range conns {
|
||||
pid := c.RemotePeer()
|
||||
addr := c.RemoteMultiaddr()
|
||||
addrs[i] = fmt.Sprintf("%s/%s", addr, pid.Pretty())
|
||||
addrs[i] = fmt.Sprintf("%s/ipfs/%s", addr, pid.Pretty())
|
||||
}
|
||||
|
||||
sort.Sort(sort.StringSlice(addrs))
|
||||
@ -78,12 +79,12 @@ ipfs swarm peers lists the set of peers this node is connected to.
|
||||
|
||||
var swarmConnectCmd = &cmds.Command{
|
||||
Helptext: cmds.HelpText{
|
||||
Tagline: "Open connection to a given peer",
|
||||
Tagline: "Open connection to a given address",
|
||||
ShortDescription: `
|
||||
'ipfs swarm connect' opens a connection to a peer address. The address format
|
||||
is an ipfs multiaddr:
|
||||
|
||||
ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
|
||||
ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
|
||||
`,
|
||||
},
|
||||
Arguments: []cmds.Argument{
|
||||
@ -92,7 +93,6 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8Szb
|
||||
Run: func(req cmds.Request, res cmds.Response) {
|
||||
ctx := context.TODO()
|
||||
|
||||
log.Debug("ipfs swarm connect")
|
||||
n, err := req.Context().GetNode()
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
@ -132,6 +132,73 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8Szb
|
||||
Type: stringList{},
|
||||
}
|
||||
|
||||
var swarmDisconnectCmd = &cmds.Command{
|
||||
Helptext: cmds.HelpText{
|
||||
Tagline: "Close connection to a given address",
|
||||
ShortDescription: `
|
||||
'ipfs swarm disconnect' closes a connection to a peer address. The address format
|
||||
is an ipfs multiaddr:
|
||||
|
||||
ipfs swarm disconnect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
|
||||
`,
|
||||
},
|
||||
Arguments: []cmds.Argument{
|
||||
cmds.StringArg("address", true, true, "address of peer to connect to").EnableStdin(),
|
||||
},
|
||||
Run: func(req cmds.Request, res cmds.Response) {
|
||||
n, err := req.Context().GetNode()
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
addrs := req.Arguments()
|
||||
|
||||
if n.PeerHost == nil {
|
||||
res.SetError(errNotOnline, cmds.ErrClient)
|
||||
return
|
||||
}
|
||||
|
||||
iaddrs, err := parseAddresses(addrs)
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
output := make([]string, len(iaddrs))
|
||||
for i, addr := range iaddrs {
|
||||
taddr := addr.Transport()
|
||||
output[i] = "disconnect " + addr.ID().Pretty()
|
||||
|
||||
found := false
|
||||
conns := n.PeerHost.Network().ConnsToPeer(addr.ID())
|
||||
for _, conn := range conns {
|
||||
if !conn.RemoteMultiaddr().Equal(taddr) {
|
||||
log.Error("it's not", conn.RemoteMultiaddr(), taddr)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := conn.Close(); err != nil {
|
||||
output[i] += " failure: " + err.Error()
|
||||
} else {
|
||||
output[i] += " success"
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
if !found {
|
||||
output[i] += " failure: conn not found"
|
||||
}
|
||||
}
|
||||
res.SetOutput(&stringList{output})
|
||||
},
|
||||
Marshalers: cmds.MarshalerMap{
|
||||
cmds.Text: stringListMarshaler,
|
||||
},
|
||||
Type: stringList{},
|
||||
}
|
||||
|
||||
func stringListMarshaler(res cmds.Response) (io.Reader, error) {
|
||||
list, ok := res.Output().(*stringList)
|
||||
if !ok {
|
||||
@ -146,37 +213,30 @@ func stringListMarshaler(res cmds.Response) (io.Reader, error) {
|
||||
return &buf, nil
|
||||
}
|
||||
|
||||
// splitAddresses is a function that takes in a slice of string peer addresses
|
||||
// parseAddresses is a function that takes in a slice of string peer addresses
|
||||
// (multiaddr + peerid) and returns slices of multiaddrs and peerids.
|
||||
func splitAddresses(addrs []string) (maddrs []ma.Multiaddr, pids []peer.ID, err error) {
|
||||
|
||||
maddrs = make([]ma.Multiaddr, len(addrs))
|
||||
pids = make([]peer.ID, len(addrs))
|
||||
for i, addr := range addrs {
|
||||
a, err := ma.NewMultiaddr(path.Dir(addr))
|
||||
func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) {
|
||||
iaddrs = make([]iaddr.IPFSAddr, len(addrs))
|
||||
for i, saddr := range addrs {
|
||||
iaddrs[i], err = iaddr.ParseString(saddr)
|
||||
if err != nil {
|
||||
return nil, nil, cmds.ClientError("invalid peer address: " + err.Error())
|
||||
return nil, cmds.ClientError("invalid peer address: " + err.Error())
|
||||
}
|
||||
id, err := peer.IDB58Decode(path.Base(addr))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pids[i] = id
|
||||
maddrs[i] = a
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// peersWithAddresses is a function that takes in a slice of string peer addresses
|
||||
// (multiaddr + peerid) and returns a slice of properly constructed peers
|
||||
func peersWithAddresses(ps peer.Peerstore, addrs []string) ([]peer.ID, error) {
|
||||
maddrs, pids, err := splitAddresses(addrs)
|
||||
func peersWithAddresses(ps peer.Peerstore, addrs []string) (pids []peer.ID, err error) {
|
||||
iaddrs, err := parseAddresses(addrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, p := range pids {
|
||||
ps.AddAddress(p, maddrs[i])
|
||||
for _, iaddr := range iaddrs {
|
||||
pids = append(pids, iaddr.ID())
|
||||
ps.AddAddress(iaddr.ID(), iaddr.Multiaddr())
|
||||
}
|
||||
return pids, nil
|
||||
}
|
||||
|
||||
13
core/core.go
13
core/core.go
@ -318,10 +318,9 @@ func (n *IpfsNode) Bootstrap(cfg BootstrapConfig) error {
|
||||
// freshest bootstrap peers from config. this responds to live changes.
|
||||
if cfg.BootstrapPeers == nil {
|
||||
cfg.BootstrapPeers = func() []peer.PeerInfo {
|
||||
bpeers := n.Repo.Config().Bootstrap
|
||||
ps, err := toPeerInfos(bpeers)
|
||||
ps, err := n.loadBootstrapPeers()
|
||||
if err != nil {
|
||||
log.Warningf("failed to parse bootstrap peers from config: %s", bpeers)
|
||||
log.Warningf("failed to parse bootstrap peers from config: %s", n.Repo.Config().Bootstrap)
|
||||
return nil
|
||||
}
|
||||
return ps
|
||||
@ -370,6 +369,14 @@ func (n *IpfsNode) loadPrivateKey() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *IpfsNode) loadBootstrapPeers() ([]peer.PeerInfo, error) {
|
||||
parsed, err := n.Repo.Config().BootstrapPeers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPeerInfos(parsed), nil
|
||||
}
|
||||
|
||||
// SetupOfflineRouting loads the local nodes private key and
|
||||
// uses it to instantiate a routing system in offline mode.
|
||||
// This is primarily used for offline ipns modifications.
|
||||
|
||||
@ -18,6 +18,8 @@ import (
|
||||
type Map map[u.Key]Conn
|
||||
|
||||
type PeerConn interface {
|
||||
io.Closer
|
||||
|
||||
// LocalPeer (this side) ID, PrivateKey, and Address
|
||||
LocalPeer() peer.ID
|
||||
LocalPrivateKey() ic.PrivKey
|
||||
@ -45,7 +47,6 @@ type Conn interface {
|
||||
|
||||
msgio.Reader
|
||||
msgio.Writer
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// Dialer is an object that can open connections. We could have a "convenience"
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
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"
|
||||
|
||||
errors "github.com/jbenet/go-ipfs/util/debugerror"
|
||||
|
||||
iaddr "github.com/jbenet/go-ipfs/util/ipfsaddr"
|
||||
)
|
||||
|
||||
// DefaultBootstrapAddresses are the hardcoded bootstrap addresses
|
||||
@ -16,21 +13,25 @@ import (
|
||||
// Note: this is here -- and not inside cmd/ipfs/init.go -- because of an
|
||||
// import dependency issue. TODO: move this into a config/default/ package.
|
||||
var DefaultBootstrapAddresses = []string{
|
||||
"/ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
|
||||
"/ip4/104.236.176.52/tcp/4001/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune (to be neptune.i.ipfs.io)
|
||||
"/ip4/104.236.179.241/tcp/4001/QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm", // pluto (to be pluto.i.ipfs.io)
|
||||
"/ip4/162.243.248.213/tcp/4001/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus (to be uranus.i.ipfs.io)
|
||||
"/ip4/128.199.219.111/tcp/4001/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn (to be saturn.i.ipfs.io)
|
||||
"/ip4/104.236.76.40/tcp/4001/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus (to be venus.i.ipfs.io)
|
||||
"/ip4/178.62.158.247/tcp/4001/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth (to be earth.i.ipfs.io)
|
||||
"/ip4/178.62.61.185/tcp/4001/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury (to be mercury.i.ipfs.io)
|
||||
"/ip4/104.236.151.122/tcp/4001/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter (to be jupiter.i.ipfs.io)
|
||||
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
|
||||
"/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune (to be neptune.i.ipfs.io)
|
||||
"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm", // pluto (to be pluto.i.ipfs.io)
|
||||
"/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus (to be uranus.i.ipfs.io)
|
||||
"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn (to be saturn.i.ipfs.io)
|
||||
"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus (to be venus.i.ipfs.io)
|
||||
"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth (to be earth.i.ipfs.io)
|
||||
"/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury (to be mercury.i.ipfs.io)
|
||||
"/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter (to be jupiter.i.ipfs.io)
|
||||
}
|
||||
|
||||
// BootstrapPeer is a peer used to bootstrap the network.
|
||||
type BootstrapPeer struct {
|
||||
Address string
|
||||
PeerID string // until multiaddr supports ipfs, use another field.
|
||||
type BootstrapPeer iaddr.IPFSAddr
|
||||
|
||||
// ErrInvalidPeerAddr signals an address is not a valid peer address.
|
||||
var ErrInvalidPeerAddr = errors.New("invalid peer address")
|
||||
|
||||
func (c *Config) BootstrapPeers() ([]BootstrapPeer, error) {
|
||||
return ParseBootstrapPeers(c.Bootstrap)
|
||||
}
|
||||
|
||||
// DefaultBootstrapPeers returns the (parsed) set of default bootstrap peers.
|
||||
@ -45,39 +46,16 @@ This is a problem with the ipfs codebase. Please report it to the dev team.`, er
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func (bp *BootstrapPeer) String() string {
|
||||
return bp.Address + "/" + bp.PeerID
|
||||
func (c *Config) SetBootstrapPeers(bps []BootstrapPeer) {
|
||||
c.Bootstrap = BootstrapPeerStrings(bps)
|
||||
}
|
||||
|
||||
func ParseBootstrapPeer(addr string) (BootstrapPeer, error) {
|
||||
// to be replaced with just multiaddr parsing, once ptp is a multiaddr protocol
|
||||
idx := strings.LastIndex(addr, "/")
|
||||
if idx == -1 {
|
||||
return BootstrapPeer{}, errors.New("invalid address")
|
||||
}
|
||||
addrS := addr[:idx]
|
||||
peeridS := addr[idx+1:]
|
||||
|
||||
// make sure addrS parses as a multiaddr.
|
||||
if len(addrS) > 0 {
|
||||
maddr, err := ma.NewMultiaddr(addrS)
|
||||
if err != nil {
|
||||
return BootstrapPeer{}, err
|
||||
}
|
||||
|
||||
addrS = maddr.String()
|
||||
}
|
||||
|
||||
// make sure idS parses as a peer.ID
|
||||
_, err := mh.FromB58String(peeridS)
|
||||
ia, err := iaddr.ParseString(addr)
|
||||
if err != nil {
|
||||
return BootstrapPeer{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return BootstrapPeer{
|
||||
Address: addrS,
|
||||
PeerID: peeridS,
|
||||
}, nil
|
||||
return BootstrapPeer(ia), err
|
||||
}
|
||||
|
||||
func ParseBootstrapPeers(addrs []string) ([]BootstrapPeer, error) {
|
||||
@ -91,3 +69,11 @@ func ParseBootstrapPeers(addrs []string) ([]BootstrapPeer, error) {
|
||||
}
|
||||
return peers, nil
|
||||
}
|
||||
|
||||
func BootstrapPeerStrings(bps []BootstrapPeer) []string {
|
||||
bpss := make([]string, len(bps))
|
||||
for i, p := range bps {
|
||||
bpss[i] = p.String()
|
||||
}
|
||||
return bpss
|
||||
}
|
||||
|
||||
@ -16,14 +16,14 @@ var log = u.Logger("config")
|
||||
|
||||
// Config is used to load IPFS config files.
|
||||
type Config struct {
|
||||
Identity Identity // local node's peer identity
|
||||
Datastore Datastore // local node's storage
|
||||
Addresses Addresses // local node's addresses
|
||||
Mounts Mounts // local node's mount points
|
||||
Version Version // local node's version management
|
||||
Bootstrap []BootstrapPeer // local nodes's bootstrap peers
|
||||
Tour Tour // local node's tour position
|
||||
Gateway Gateway // local node's gateway server options
|
||||
Identity Identity // local node's peer identity
|
||||
Datastore Datastore // local node's storage
|
||||
Addresses Addresses // local node's addresses
|
||||
Mounts Mounts // local node's mount points
|
||||
Version Version // local node's version management
|
||||
Bootstrap []string // local nodes's bootstrap peer addresses
|
||||
Tour Tour // local node's tour position
|
||||
Gateway Gateway // local node's gateway server options
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@ -38,7 +38,7 @@ func Init(out io.Writer, nBitsForKeypair int) (*Config, error) {
|
||||
API: "/ip4/127.0.0.1/tcp/5001",
|
||||
},
|
||||
|
||||
Bootstrap: bootstrapPeers,
|
||||
Bootstrap: BootstrapPeerStrings(bootstrapPeers),
|
||||
Datastore: *ds,
|
||||
Identity: identity,
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
|
||||
ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
|
||||
ipfs bootstrap # list bootstrap nodes for debugging
|
||||
|
||||
|
||||
echo "3nodetest> starting client daemon"
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
# must be connected to bootstrap node
|
||||
ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
|
||||
ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
|
||||
ipfs bootstrap # list bootstrap nodes for debugging
|
||||
|
||||
# wait for daemon to start/bootstrap
|
||||
# alternatively use ipfs swarm connect
|
||||
echo "3nodetest> starting server daemon"
|
||||
ipfs daemon &
|
||||
sleep 3
|
||||
# TODO instead of bootrapping: ipfs swarm connect /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
|
||||
# TODO instead of bootrapping: ipfs swarm connect /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
|
||||
|
||||
# must mount this volume from data container
|
||||
ipfs add -q /data/filetiny > tmptiny
|
||||
|
||||
131
test/sharness/t0120-bootstrap.sh
Executable file
131
test/sharness/t0120-bootstrap.sh
Executable file
@ -0,0 +1,131 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014 Jeromy Johnson
|
||||
# MIT Licensed; see the LICENSE file in this repository.
|
||||
#
|
||||
|
||||
# changing the bootstrap peers will require changing it in two places :)
|
||||
BP1="/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
|
||||
BP2="/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx"
|
||||
BP3="/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z"
|
||||
BP4="/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm"
|
||||
BP5="/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
|
||||
BP6="/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu"
|
||||
BP7="/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm"
|
||||
BP8="/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd"
|
||||
BP9="/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"
|
||||
|
||||
test_description="Test ipfs repo operations"
|
||||
|
||||
. lib/test-lib.sh
|
||||
|
||||
test_init_ipfs
|
||||
|
||||
# we use a function so that we can run it both offline + online
|
||||
test_bootstrap_list_cmd() {
|
||||
printf "" >list_expected
|
||||
for BP in "$@"
|
||||
do
|
||||
echo "$BP" >>list_expected
|
||||
done
|
||||
|
||||
test_expect_success "'ipfs bootstrap' succeeds" '
|
||||
ipfs bootstrap >list_actual
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap' output looks good" '
|
||||
test_cmp list_actual list_expected
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap list' succeeds" '
|
||||
ipfs bootstrap list >list2_actual
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap list' output looks good" '
|
||||
test_cmp list2_actual list_expected
|
||||
'
|
||||
}
|
||||
|
||||
# we use a function so that we can run it both offline + online
|
||||
test_bootstrap_cmd() {
|
||||
|
||||
# remove all peers just in case.
|
||||
# if this fails, the first listing may not be empty
|
||||
ipfs bootstrap rm --all
|
||||
|
||||
test_bootstrap_list_cmd
|
||||
|
||||
test_expect_success "'ipfs bootstrap add' succeeds" '
|
||||
ipfs bootstrap add "$BP1" "$BP2" "$BP3" >add_actual
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap add' output looks good" '
|
||||
echo $BP1 >add_expected
|
||||
echo $BP2 >>add_expected
|
||||
echo $BP3 >>add_expected
|
||||
test_cmp add_actual add_expected
|
||||
'
|
||||
|
||||
test_bootstrap_list_cmd $BP1 $BP2 $BP3
|
||||
|
||||
test_expect_success "'ipfs bootstrap rm' succeeds" '
|
||||
ipfs bootstrap rm "$BP1" "$BP3" >rm_actual
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap rm' output looks good" '
|
||||
echo $BP1 >rm_expected
|
||||
echo $BP3 >>rm_expected
|
||||
test_cmp rm_actual rm_expected
|
||||
'
|
||||
|
||||
test_bootstrap_list_cmd $BP2
|
||||
|
||||
test_expect_success "'ipfs bootstrap add --default' succeeds" '
|
||||
ipfs bootstrap add --default >add2_actual
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap add --default' output has default BP" '
|
||||
echo $BP1 >add2_expected
|
||||
echo $BP2 >>add2_expected
|
||||
echo $BP3 >>add2_expected
|
||||
echo $BP4 >>add2_expected
|
||||
echo $BP5 >>add2_expected
|
||||
echo $BP6 >>add2_expected
|
||||
echo $BP7 >>add2_expected
|
||||
echo $BP8 >>add2_expected
|
||||
echo $BP9 >>add2_expected
|
||||
test_cmp add2_actual add2_expected
|
||||
'
|
||||
|
||||
test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 $BP6 $BP7 $BP8 $BP9
|
||||
|
||||
test_expect_success "'ipfs bootstrap rm --all' succeeds" '
|
||||
ipfs bootstrap rm --all >rm2_actual
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs bootstrap rm' output looks good" '
|
||||
echo $BP1 >rm2_expected
|
||||
echo $BP2 >>rm2_expected
|
||||
echo $BP3 >>rm2_expected
|
||||
echo $BP4 >>rm2_expected
|
||||
echo $BP5 >>rm2_expected
|
||||
echo $BP6 >>rm2_expected
|
||||
echo $BP7 >>rm2_expected
|
||||
echo $BP8 >>rm2_expected
|
||||
echo $BP9 >>rm2_expected
|
||||
test_cmp rm2_actual rm2_expected
|
||||
'
|
||||
|
||||
test_bootstrap_list_cmd
|
||||
}
|
||||
|
||||
# should work offline
|
||||
test_bootstrap_cmd
|
||||
|
||||
# should work online
|
||||
test_launch_ipfs_daemon
|
||||
test_bootstrap_cmd
|
||||
test_kill_ipfs_daemon
|
||||
|
||||
|
||||
test_done
|
||||
112
util/ipfsaddr/ipfsaddr.go
Normal file
112
util/ipfsaddr/ipfsaddr.go
Normal file
@ -0,0 +1,112 @@
|
||||
package ipfsaddr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
|
||||
|
||||
peer "github.com/jbenet/go-ipfs/p2p/peer"
|
||||
eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog"
|
||||
)
|
||||
|
||||
var log = eventlog.Logger("ipfsaddr")
|
||||
|
||||
// ErrInvalidAddr signals an address is not a valid ipfs address.
|
||||
var ErrInvalidAddr = errors.New("invalid ipfs address")
|
||||
|
||||
type IPFSAddr interface {
|
||||
ID() peer.ID
|
||||
Multiaddr() ma.Multiaddr
|
||||
Transport() ma.Multiaddr
|
||||
String() string
|
||||
Equal(b interface{}) bool
|
||||
}
|
||||
|
||||
type ipfsAddr struct {
|
||||
ma ma.Multiaddr
|
||||
id peer.ID
|
||||
}
|
||||
|
||||
func (a ipfsAddr) ID() peer.ID {
|
||||
return a.id
|
||||
}
|
||||
|
||||
func (a ipfsAddr) Multiaddr() ma.Multiaddr {
|
||||
return a.ma
|
||||
}
|
||||
|
||||
func (a ipfsAddr) Transport() ma.Multiaddr {
|
||||
return Transport(a)
|
||||
}
|
||||
|
||||
func (a ipfsAddr) String() string {
|
||||
return a.ma.String()
|
||||
}
|
||||
|
||||
func (a ipfsAddr) Equal(b interface{}) bool {
|
||||
if ib, ok := b.(IPFSAddr); ok {
|
||||
return a.Multiaddr().Equal(ib.Multiaddr())
|
||||
}
|
||||
if mb, ok := b.(ma.Multiaddr); ok {
|
||||
return a.Multiaddr().Equal(mb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ParseString parses a string representation of an address into an IPFSAddr
|
||||
func ParseString(str string) (a IPFSAddr, err error) {
|
||||
if str == "" {
|
||||
return nil, ErrInvalidAddr
|
||||
}
|
||||
|
||||
m, err := ma.NewMultiaddr(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseMultiaddr(m)
|
||||
}
|
||||
|
||||
// ParseMultiaddr parses a multiaddr into an IPFSAddr
|
||||
func ParseMultiaddr(m ma.Multiaddr) (a IPFSAddr, err error) {
|
||||
// never panic.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Debug("recovered from panic: ", r)
|
||||
a = nil
|
||||
err = ErrInvalidAddr
|
||||
}
|
||||
}()
|
||||
|
||||
if m == nil {
|
||||
return nil, ErrInvalidAddr
|
||||
}
|
||||
|
||||
// make sure it's an ipfs addr
|
||||
parts := ma.Split(m)
|
||||
if len(parts) < 1 {
|
||||
return nil, ErrInvalidAddr
|
||||
}
|
||||
ipfspart := parts[len(parts)-1] // last part
|
||||
if ipfspart.Protocols()[0].Code != ma.P_IPFS {
|
||||
return nil, ErrInvalidAddr
|
||||
}
|
||||
|
||||
// make sure ipfs id parses as a peer.ID
|
||||
peerIdParts := strings.Split(ipfspart.String(), "/")
|
||||
peerIdStr := peerIdParts[len(peerIdParts)-1]
|
||||
id, err := peer.IDB58Decode(peerIdStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ipfsAddr{ma: m, id: id}, nil
|
||||
}
|
||||
|
||||
func Transport(iaddr IPFSAddr) (maddr ma.Multiaddr) {
|
||||
maddr = iaddr.Multiaddr()
|
||||
split := ma.Split(maddr)
|
||||
maddr = ma.Join(split[:len(split)-1]...)
|
||||
return
|
||||
}
|
||||
137
util/ipfsaddr/ipfsaddr_test.go
Normal file
137
util/ipfsaddr/ipfsaddr_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
package ipfsaddr
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
|
||||
peer "github.com/jbenet/go-ipfs/p2p/peer"
|
||||
)
|
||||
|
||||
var good = []string{
|
||||
"/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok",
|
||||
"/ipfs/kTRX47RthhwNzWdi6ggwqjuX",
|
||||
"/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR",
|
||||
"/ip4/1.2.3.4/tcp/1234/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok",
|
||||
"/ip4/1.2.3.4/tcp/1234/ipfs/kTRX47RthhwNzWdi6ggwqjuX",
|
||||
"/ip4/1.2.3.4/tcp/1234/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR",
|
||||
}
|
||||
|
||||
var bad = []string{
|
||||
"5dru6bJPUM1B7N69528u49DJiWZnok", // bad ma
|
||||
"kTRX47RthhwNzWdi6ggwqjuX", // bad ma
|
||||
"QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR", // bad ma
|
||||
"ipfs/5dru6bJPUM1B7N69528u49DJiWZnok", // bad ma
|
||||
"ipfs/kTRX47RthhwNzWdi6ggwqjuX", // bad ma
|
||||
"ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR", // bad ma
|
||||
"/ipfs/5dru6bJPUM1B7N69528u49DJiWZno", // bad mh
|
||||
"/ipfs/kTRX47RthhwNzWdi6ggwqju", // bad mh
|
||||
"/ipfs/QmUCseQWXCSrhf9edzVKTvj8o8Ts5aXFGNPameZRPJ6uR", // bad mh
|
||||
"/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR/tcp/1234", // ipfs not last
|
||||
"/ip4/1.2.3.4/tcp/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok", // bad tcp part
|
||||
"/ip4/tcp/1234/ipfs/kTRX47RthhwNzWdi6ggwqjuX", // bad ip part
|
||||
"/ip4/1.2.3.4/tcp/1234/ipfs", // no id
|
||||
"/ip4/1.2.3.4/tcp/1234/ipfs/", // no id
|
||||
}
|
||||
|
||||
func newMultiaddr(t *testing.T, s string) ma.Multiaddr {
|
||||
maddr, err := ma.NewMultiaddr(s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return maddr
|
||||
}
|
||||
|
||||
func TestParseStringGood(t *testing.T) {
|
||||
for _, g := range good {
|
||||
if _, err := ParseString(g); err != nil {
|
||||
t.Error("failed to parse", g, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseStringBad(t *testing.T) {
|
||||
for _, b := range bad {
|
||||
if _, err := ParseString(b); err == nil {
|
||||
t.Error("succeeded in parsing", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMultiaddrGood(t *testing.T) {
|
||||
for _, g := range good {
|
||||
if _, err := ParseMultiaddr(newMultiaddr(t, g)); err != nil {
|
||||
t.Error("failed to parse", g, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMultiaddrBad(t *testing.T) {
|
||||
for _, b := range bad {
|
||||
m, err := ma.NewMultiaddr(b)
|
||||
if err != nil {
|
||||
continue // skip these.
|
||||
}
|
||||
|
||||
if _, err := ParseMultiaddr(m); err == nil {
|
||||
t.Error("succeeded in parsing", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDMatches(t *testing.T) {
|
||||
for _, g := range good {
|
||||
a, err := ParseString(g)
|
||||
if err != nil {
|
||||
t.Error("failed to parse", g, err)
|
||||
continue
|
||||
}
|
||||
|
||||
sp := strings.Split(g, "/")
|
||||
sid := sp[len(sp)-1]
|
||||
id, err := peer.IDB58Decode(sid)
|
||||
if err != nil {
|
||||
t.Error("failed to parse", sid, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if a.ID() != id {
|
||||
t.Error("not equal", a.ID(), id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiaddrMatches(t *testing.T) {
|
||||
for _, g := range good {
|
||||
a, err := ParseString(g)
|
||||
if err != nil {
|
||||
t.Error("failed to parse", g, err)
|
||||
continue
|
||||
}
|
||||
|
||||
m := newMultiaddr(t, g)
|
||||
if !a.Multiaddr().Equal(m) {
|
||||
t.Error("not equal", a.Multiaddr(), m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransport(t *testing.T) {
|
||||
for _, g := range good {
|
||||
a, err := ParseString(g)
|
||||
if err != nil {
|
||||
t.Error("failed to parse", g, err)
|
||||
continue
|
||||
}
|
||||
|
||||
m := newMultiaddr(t, g)
|
||||
split := ma.Split(m)
|
||||
m = ma.Join(split[:len(split)-1]...)
|
||||
if a.Multiaddr().Equal(m) {
|
||||
t.Error("should not be equal", a.Multiaddr(), m)
|
||||
}
|
||||
if !Transport(a).Equal(m) {
|
||||
t.Error("should be equal", Transport(a), m)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user