提交 22ee73d0 作者: Jeromy Johnson 提交者: GitHub

Merge pull request #4091 from ipfs/feat/circuit-relay

Circuit Relay integration
......@@ -7,6 +7,7 @@ import (
"io"
"path"
"sort"
"strings"
cmds "github.com/ipfs/go-ipfs/commands"
repo "github.com/ipfs/go-ipfs/repo"
......@@ -127,8 +128,14 @@ var swarmPeersCmd = &cmds.Command{
}
buf := new(bytes.Buffer)
pipfs := ma.ProtocolWithCode(ma.P_IPFS).Name
for _, info := range ci.Peers {
fmt.Fprintf(buf, "%s/ipfs/%s", info.Addr, info.Peer)
ids := fmt.Sprintf("/%s/%s", pipfs, info.Peer)
if strings.HasSuffix(info.Addr, ids) {
fmt.Fprintf(buf, "%s", info.Addr)
} else {
fmt.Fprintf(buf, "%s%s", info.Addr, ids)
}
if info.Latency != "" {
fmt.Fprintf(buf, " %s", info.Latency)
}
......@@ -197,7 +204,8 @@ var swarmAddrsCmd = &cmds.Command{
`,
},
Subcommands: map[string]*cmds.Command{
"local": swarmAddrsLocalCmd,
"local": swarmAddrsLocalCmd,
"listen": swarmAddrsListenCmd,
},
Run: func(req cmds.Request, res cmds.Response) {
......@@ -256,7 +264,7 @@ var swarmAddrsLocalCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "List local addresses.",
ShortDescription: `
'ipfs swarm addrs local' lists all local addresses the node is listening on.
'ipfs swarm addrs local' lists all local listening addresses announced to the network.
`,
},
Options: []cmds.Option{
......@@ -296,6 +304,46 @@ var swarmAddrsLocalCmd = &cmds.Command{
},
}
var swarmAddrsListenCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "List interface listening addresses.",
ShortDescription: `
'ipfs swarm addrs listen' lists all interface addresses the node is listening on.
`,
},
Run: func(req cmds.Request, res cmds.Response) {
n, err := req.InvocContext().GetNode()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
if n.PeerHost == nil {
res.SetError(errNotOnline, cmds.ErrClient)
return
}
var addrs []string
maddrs, err := n.PeerHost.Network().InterfaceListenAddresses()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
for _, addr := range maddrs {
addrs = append(addrs, addr.String())
}
sort.Sort(sort.StringSlice(addrs))
res.SetOutput(&stringList{addrs})
},
Type: stringList{},
Marshalers: cmds.MarshalerMap{
cmds.Text: stringListMarshaler,
},
}
var swarmConnectCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Open connection to a given address.",
......
......@@ -50,6 +50,7 @@ import (
ipnet "gx/ipfs/QmQq9YzmdFdWNTDdArueGyD7L5yyiRQigrRHJnTGkxcEjT/go-libp2p-interface-pnet"
p2phost "gx/ipfs/QmRNyPNJGNCaZyYonJj7owciWTsMd9gRfEKmZY3o6xwN3h/go-libp2p-host"
mssmux "gx/ipfs/QmRVYfZ7tWNHPBzWiG6KWGzvT2hcGems8srihsQE29x1U5/go-smux-multistream"
circuit "gx/ipfs/QmSC7288aesJAC3BQ4Duy6Pk2CMfQWL7cr5t9SV4HBmKFT/go-libp2p-circuit"
goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
mamask "gx/ipfs/QmSMZwvs3n4GBikZ7hKzT17c3bk65FmyZo2JqtJ16swqCv/multiaddr-filter"
u "gx/ipfs/QmSU6eubNdhXjFBJBSksTp8kv8YRub8mGAPv8tVJHmL2EU/go-ipfs-util"
......@@ -221,9 +222,12 @@ func (n *IpfsNode) startOnlineServices(ctx context.Context, routingOption Routin
hostopts := &ConstructPeerHostOpts{
AddrsFactory: addrsFactory,
DisableNatPortMap: cfg.Swarm.DisableNatPortMap,
DisableRelay: cfg.Swarm.DisableRelay,
EnableRelayHop: cfg.Swarm.EnableRelayHop,
}
peerhost, err := hostOption(ctx, n.Identity, n.Peerstore, n.Reporter,
addrfilter, tpt, protec, hostopts)
if err != nil {
return err
}
......@@ -783,8 +787,10 @@ func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) {
}
type ConstructPeerHostOpts struct {
DisableNatPortMap bool
AddrsFactory p2pbhost.AddrsFactory
DisableNatPortMap bool
DisableRelay bool
EnableRelayHop bool
}
type HostOption func(ctx context.Context, id peer.ID, ps pstore.Peerstore, bwr metrics.Reporter, fs []*net.IPNet, tpt smux.Transport, protc ipnet.Protector, opts *ConstructPeerHostOpts) (p2phost.Host, error)
......@@ -810,15 +816,56 @@ func constructPeerHost(ctx context.Context, id peer.ID, ps pstore.Peerstore, bwr
if !opts.DisableNatPortMap {
hostOpts = append(hostOpts, p2pbhost.NATPortMap)
}
if opts.AddrsFactory != nil {
hostOpts = append(hostOpts, opts.AddrsFactory)
addrsFactory := opts.AddrsFactory
if !opts.DisableRelay {
if addrsFactory != nil {
addrsFactory = composeAddrsFactory(addrsFactory, filterRelayAddrs)
} else {
addrsFactory = filterRelayAddrs
}
}
if addrsFactory != nil {
hostOpts = append(hostOpts, addrsFactory)
}
host := p2pbhost.New(network, hostOpts...)
if !opts.DisableRelay {
var relayOpts []circuit.RelayOpt
if opts.EnableRelayHop {
relayOpts = append(relayOpts, circuit.OptHop)
}
err := circuit.AddRelayTransport(ctx, host, relayOpts...)
if err != nil {
host.Close()
return nil, err
}
}
return host, nil
}
func filterRelayAddrs(addrs []ma.Multiaddr) []ma.Multiaddr {
var raddrs []ma.Multiaddr
for _, addr := range addrs {
_, err := addr.ValueForProtocol(circuit.P_CIRCUIT)
if err == nil {
continue
}
raddrs = append(raddrs, addr)
}
return raddrs
}
func composeAddrsFactory(f, g p2pbhost.AddrsFactory) p2pbhost.AddrsFactory {
return func(addrs []ma.Multiaddr) []ma.Multiaddr {
return f(g(addrs))
}
}
// startListening on the network addresses
func startListening(ctx context.Context, host p2phost.Host, cfg *config.Config) error {
listenAddrs, err := listenAddresses(cfg)
......
......@@ -102,7 +102,7 @@ A boolean value. If set to true, all block reads from disk will be hashed and ve
- `BloomFilterSize`
A number representing the size in bytes of the blockstore's bloom filter. A value of zero represents the feature being disabled.
Default: `0`
Default: `0`
- `Params`
Extra parameters for datastore construction, not currently used.
......@@ -228,3 +228,9 @@ improvement, as well as a reduction in memory usage.
- `DisableNatPortMap`
Disable NAT discovery.
- `DisableRelay`
Disables the p2p-circuit relay transport.
- `EnableRelayHop`
Enables HOP relay for the node. If this is enabled, the node will act as
an intermediate (Hop Relay) node in relay circuits for connected peers.
......@@ -451,6 +451,12 @@
"hash": "QmQBB2dQLmQHJgs2gqZ3iqL2XiuCtUCvXzWt5kMXDf5Zcr",
"name": "go-maddr-filter",
"version": "1.1.4"
},
{
"author": "vyzo",
"hash": "QmSC7288aesJAC3BQ4Duy6Pk2CMfQWL7cr5t9SV4HBmKFT",
"name": "go-libp2p-circuit",
"version": "1.1.2"
}
],
"gxVersion": "0.10.0",
......
......@@ -4,4 +4,6 @@ type SwarmConfig struct {
AddrFilters []string
DisableBandwidthMetrics bool
DisableNatPortMap bool
DisableRelay bool
EnableRelayHop bool
}
......@@ -21,6 +21,10 @@ test_expect_success "'ipfs swarm addrs local' works" '
ipfs swarm addrs local >local_addrs
'
test_expect_success "ipfs swarm addrs listen; works" '
ipfs swarm addrs listen >listen_addrs
'
test_expect_success "ipfs peer id looks good" '
test_check_peerid "$PEERID"
'
......@@ -38,7 +42,7 @@ test_expect_success "ipfs gateway works with the correct allowed origin port" '
test_expect_success "ipfs daemon output looks good" '
STARTFILE="ipfs cat /ipfs/$HASH_WELCOME_DOCS/readme" &&
echo "Initializing daemon..." >expected_daemon &&
sed "s/^/Swarm listening on /" local_addrs >>expected_daemon &&
sed "s/^/Swarm listening on /" listen_addrs >>expected_daemon &&
sed "s/^/Swarm announcing /" local_addrs >>expected_daemon &&
echo "API server listening on '$API_MADDR'" >>expected_daemon &&
echo "Gateway (readonly) server listening on '$GWAY_MADDR'" >>expected_daemon &&
......
#!/bin/sh
test_description="Test circuit relay"
. lib/test-lib.sh
# start iptb + wait for peering
NUM_NODES=3
test_expect_success 'init iptb' '
iptb init -n $NUM_NODES --bootstrap=none --port=0
'
# Network toplogy: A <-> Relay <-> B
test_expect_success 'start up nodes for configuration' '
iptb start --args --routing=none
'
test_expect_success 'configure EnableRelayHop in relay node' '
ipfsi 1 config --json Swarm.EnableRelayHop true
'
test_expect_success 'restart nodes' '
iptb stop &&
iptb start --args --routing=none
'
test_expect_success 'connect A <-> Relay' '
iptb connect 0 1
'
test_expect_success 'connect B <-> Relay' '
iptb connect 2 1
'
test_expect_success 'wait until relay is ready to do work' '
sleep 1
'
test_expect_success 'peer ids' '
PEERID_0=$(iptb get id 0) &&
PEERID_1=$(iptb get id 1) &&
PEERID_2=$(iptb get id 2)
'
test_expect_success 'connect A <-Relay-> B' '
ipfsi 0 swarm connect /p2p-circuit/ipfs/$PEERID_2 > peers_out
'
test_expect_success 'output looks good' '
echo "connect $PEERID_2 success" > peers_exp &&
test_cmp peers_exp peers_out
'
test_expect_success 'peers for A look good' '
ipfsi 0 swarm peers | grep p2p-circuit > peers_out &&
echo "/ipfs/$PEERID_1/p2p-circuit/ipfs/$PEERID_2" > peers_exp &&
test_cmp peers_exp peers_out
'
test_expect_success 'peers for B look good' '
ipfsi 2 swarm peers | grep p2p-circuit > peers_out &&
echo "/ipfs/$PEERID_1/p2p-circuit/ipfs/$PEERID_0" > peers_exp &&
test_cmp peers_exp peers_out
'
test_expect_success 'add an object in A' '
echo "hello relay" | ipfsi 0 add > peers_out
'
test_expect_success 'object ID' '
OBJID=$(cut -f3 -d " " peers_out)
'
test_expect_success 'cat the object in B' '
ipfsi 2 cat $OBJID > peers_out
'
test_expect_success 'output looks good' '
echo "hello relay" > peers_exp &&
test_cmp peers_exp peers_out
'
test_expect_success 'stop iptb' '
iptb stop
'
test_done
......@@ -6,6 +6,7 @@ import (
ma "gx/ipfs/QmXY77cVe7rVRQXZZQRioukUM7aRW3BTcAgJe12MCtb3Ji/go-multiaddr"
path "github.com/ipfs/go-ipfs/path"
circuit "gx/ipfs/QmSC7288aesJAC3BQ4Duy6Pk2CMfQWL7cr5t9SV4HBmKFT/go-libp2p-circuit"
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
)
......@@ -106,6 +107,16 @@ func ParseMultiaddr(m ma.Multiaddr) (a IPFSAddr, err error) {
func Transport(iaddr IPFSAddr) (maddr ma.Multiaddr) {
maddr = iaddr.Multiaddr()
// /ipfs/QmId is part of the transport address for p2p-circuit
// TODO clean up the special case
// we need a consistent way of composing and consumig multiaddrs
// so that we don't have to do this
_, err := maddr.ValueForProtocol(circuit.P_CIRCUIT)
if err == nil {
return maddr
}
split := ma.Split(maddr)
maddr = ma.Join(split[:len(split)-1]...)
return
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论