diff --git a/api/api.go b/api/api.go index 8e523d874..ce5f4f376 100644 --- a/api/api.go +++ b/api/api.go @@ -3,6 +3,7 @@ package api import ( "context" + "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/filecoin-project/go-lotus/chain" @@ -45,9 +46,11 @@ type Common interface { // network + NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) NetPeers(context.Context) ([]peer.AddrInfo, error) NetConnect(context.Context, peer.AddrInfo) error NetAddrsListen(context.Context) (peer.AddrInfo, error) + NetDisconnect(context.Context, peer.ID) error // ID returns peerID of libp2p node backing this API ID(context.Context) (peer.ID, error) diff --git a/api/struct.go b/api/struct.go index 921ded8e6..c9da191a5 100644 --- a/api/struct.go +++ b/api/struct.go @@ -3,6 +3,8 @@ package api import ( "context" + "github.com/libp2p/go-libp2p-core/network" + "github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" @@ -19,9 +21,11 @@ type CommonStruct struct { AuthVerify func(ctx context.Context, token string) ([]string, error) `perm:"read"` AuthNew func(ctx context.Context, perms []string) ([]byte, error) `perm:"admin"` - NetPeers func(context.Context) ([]peer.AddrInfo, error) `perm:"read"` - NetConnect func(context.Context, peer.AddrInfo) error `perm:"write"` - NetAddrsListen func(context.Context) (peer.AddrInfo, error) `perm:"read"` + NetConnectedness func(context.Context, peer.ID) (network.Connectedness, error) `perm:"read"` + NetPeers func(context.Context) ([]peer.AddrInfo, error) `perm:"read"` + NetConnect func(context.Context, peer.AddrInfo) error `perm:"write"` + NetAddrsListen func(context.Context) (peer.AddrInfo, error) `perm:"read"` + NetDisconnect func(context.Context, peer.ID) error `perm:"write"` ID func(context.Context) (peer.ID, error) `perm:"read"` Version func(context.Context) (Version, error) `perm:"read"` @@ -73,6 +77,10 @@ func (c *CommonStruct) AuthNew(ctx context.Context, perms []string) ([]byte, err return c.Internal.AuthNew(ctx, perms) } +func (c *CommonStruct) NetConnectedness(ctx context.Context, pid peer.ID) (network.Connectedness, error) { + return c.Internal.NetConnectedness(ctx, pid) +} + func (c *CommonStruct) NetPeers(ctx context.Context) ([]peer.AddrInfo, error) { return c.Internal.NetPeers(ctx) } @@ -85,6 +93,10 @@ func (c *CommonStruct) NetAddrsListen(ctx context.Context) (peer.AddrInfo, error return c.Internal.NetAddrsListen(ctx) } +func (c *CommonStruct) NetDisconnect(ctx context.Context, p peer.ID) error { + return c.Internal.NetDisconnect(ctx, p) +} + // ID implements API.ID func (c *CommonStruct) ID(ctx context.Context) (peer.ID, error) { return c.Internal.ID(ctx) diff --git a/lotuspond/front/src/ConnMgr.js b/lotuspond/front/src/ConnMgr.js index 7c87fdce8..e55706578 100644 --- a/lotuspond/front/src/ConnMgr.js +++ b/lotuspond/front/src/ConnMgr.js @@ -1,6 +1,11 @@ import React from 'react'; import Cristal from 'react-cristal' +async function awaitReducer(prev, c) { + await prev + await c +} + class ConnMgr extends React.Component { constructor(props) { super(props) @@ -9,32 +14,59 @@ class ConnMgr extends React.Component { this.connectAll = this.connectAll.bind(this) this.connect1 = this.connect1.bind(this) this.connectChain = this.connectChain.bind(this) + this.getActualState = this.getActualState.bind(this) - this.state = {conns: {}} + this.state = {conns: {}, lock: true} + + this.getActualState() + setInterval(this.getActualState, 2000) + } + + async getActualState() { + const nodes = this.props.nodes + let keys = Object.keys(nodes) + + await keys.filter((_, i) => i > 0).map(async (kfrom, i) => { + await keys.filter((_, j) => i >= j).map(async kto => { + + const fromNd = this.props.nodes[kfrom] + const toNd = this.props.nodes[kto] + + const connectedness = await fromNd.conn.call('Filecoin.NetConnectedness', [toNd.peerid]) + + this.setState(prev => ({conns: {...prev.conns, [`${kfrom},${kto}`]: connectedness === 1}})) + }).reduce(awaitReducer) + }).reduce(awaitReducer) + + this.setState({lock: false}) } async connect(action, from, to) { - if (action) { - const fromNd = this.props.nodes[from] - const toNd = this.props.nodes[to] + const fromNd = this.props.nodes[from] + const toNd = this.props.nodes[to] + if (action) { const toPeerInfo = await toNd.conn.call('Filecoin.NetAddrsListen', []) await fromNd.conn.call('Filecoin.NetConnect', [toPeerInfo]) + } else { + await fromNd.conn.call('Filecoin.NetDisconnect', [toNd.peerid]) } this.setState(prev => ({conns: {...prev.conns, [`${from},${to}`]: action}})) } - connectAll() { - const nodes = this.props.nodes - let keys = Object.keys(nodes) + connectAll(discon) { + return () => { + const nodes = this.props.nodes + let keys = Object.keys(nodes) - keys.filter((_, i) => i > 0).forEach((k, i) => { - keys.filter((_, j) => i >= j).forEach((kt, i) => { - this.connect(true, k, kt) + keys.filter((_, i) => i > 0).forEach((kfrom, i) => { + keys.filter((_, j) => i >= j).forEach((kto, i) => { + this.connect(!discon, kfrom, kto) + }) }) - }) + } } connect1() { @@ -63,7 +95,11 @@ class ConnMgr extends React.Component { const cols = keys.filter((_, j) => i >= j).map((kt, i) => { const checked = this.state.conns[`${k},${kt}`] === true - return (
{keys.slice(0, -1).map((i) => ( | {i} | ))}