mirror of
https://github.com/vacp2p/nim-libp2p.git
synced 2025-01-12 17:54:46 +00:00
d02735dc46
Peer Info is now for local peer data only. For other peers info, use the peer store. Previous reference to peer info are replaced with the peerid
466 lines
14 KiB
Nim
466 lines
14 KiB
Nim
import sequtils
|
|
import chronos
|
|
import ../libp2p/[connmanager,
|
|
stream/connection,
|
|
crypto/crypto,
|
|
muxers/muxer,
|
|
peerinfo,
|
|
errors]
|
|
|
|
import helpers
|
|
|
|
type
|
|
TestMuxer = ref object of Muxer
|
|
peerId: PeerId
|
|
|
|
method newStream*(
|
|
m: TestMuxer,
|
|
name: string = "",
|
|
lazy: bool = false):
|
|
Future[Connection] {.async, gcsafe.} =
|
|
result = Connection.init(m.peerId, Direction.Out)
|
|
|
|
suite "Connection Manager":
|
|
teardown:
|
|
checkTrackers()
|
|
|
|
asyncTest "add and retrieve a connection":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
|
|
connMngr.storeConn(conn)
|
|
check conn in connMngr
|
|
|
|
let peerConn = connMngr.selectConn(peerId)
|
|
check peerConn == conn
|
|
check peerConn.dir == Direction.In
|
|
|
|
await connMngr.close()
|
|
|
|
asyncTest "shouldn't allow a closed connection":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
await conn.close()
|
|
|
|
expect CatchableError:
|
|
connMngr.storeConn(conn)
|
|
|
|
await connMngr.close()
|
|
|
|
asyncTest "shouldn't allow an EOFed connection":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
conn.isEof = true
|
|
|
|
expect CatchableError:
|
|
connMngr.storeConn(conn)
|
|
|
|
await conn.close()
|
|
await connMngr.close()
|
|
|
|
asyncTest "add and retrieve a muxer":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
let muxer = new Muxer
|
|
muxer.connection = conn
|
|
|
|
connMngr.storeConn(conn)
|
|
connMngr.storeMuxer(muxer)
|
|
check muxer in connMngr
|
|
|
|
let peerMuxer = connMngr.selectMuxer(conn)
|
|
check peerMuxer == muxer
|
|
|
|
await connMngr.close()
|
|
|
|
asyncTest "shouldn't allow a muxer for an untracked connection":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
let muxer = new Muxer
|
|
muxer.connection = conn
|
|
|
|
expect CatchableError:
|
|
connMngr.storeMuxer(muxer)
|
|
|
|
await conn.close()
|
|
await muxer.close()
|
|
await connMngr.close()
|
|
|
|
asyncTest "get conn with direction":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn1 = Connection.init(peerId, Direction.Out)
|
|
let conn2 = Connection.init(peerId, Direction.In)
|
|
|
|
connMngr.storeConn(conn1)
|
|
connMngr.storeConn(conn2)
|
|
check conn1 in connMngr
|
|
check conn2 in connMngr
|
|
|
|
let outConn = connMngr.selectConn(peerId, Direction.Out)
|
|
let inConn = connMngr.selectConn(peerId, Direction.In)
|
|
|
|
check outConn != inConn
|
|
check outConn.dir == Direction.Out
|
|
check inConn.dir == Direction.In
|
|
|
|
await connMngr.close()
|
|
|
|
asyncTest "get muxed stream for peer":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
|
|
let muxer = new TestMuxer
|
|
muxer.peerId = peerId
|
|
muxer.connection = conn
|
|
|
|
connMngr.storeConn(conn)
|
|
connMngr.storeMuxer(muxer)
|
|
check muxer in connMngr
|
|
|
|
let stream = await connMngr.getStream(peerId)
|
|
check not(isNil(stream))
|
|
check stream.peerId == peerId
|
|
|
|
await connMngr.close()
|
|
await stream.close()
|
|
|
|
asyncTest "get stream from directed connection":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
|
|
let muxer = new TestMuxer
|
|
muxer.peerId = peerId
|
|
muxer.connection = conn
|
|
|
|
connMngr.storeConn(conn)
|
|
connMngr.storeMuxer(muxer)
|
|
check muxer in connMngr
|
|
|
|
let stream1 = await connMngr.getStream(peerId, Direction.In)
|
|
check not(isNil(stream1))
|
|
let stream2 = await connMngr.getStream(peerId, Direction.Out)
|
|
check isNil(stream2)
|
|
|
|
await connMngr.close()
|
|
await stream1.close()
|
|
|
|
asyncTest "get stream from any connection":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
|
|
let muxer = new TestMuxer
|
|
muxer.peerId = peerId
|
|
muxer.connection = conn
|
|
|
|
connMngr.storeConn(conn)
|
|
connMngr.storeMuxer(muxer)
|
|
check muxer in connMngr
|
|
|
|
let stream = await connMngr.getStream(conn)
|
|
check not(isNil(stream))
|
|
|
|
await connMngr.close()
|
|
await stream.close()
|
|
|
|
asyncTest "should raise on too many connections":
|
|
let connMngr = ConnManager.init(maxConnsPerPeer = 1)
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
|
|
connMngr.storeConn(Connection.init(peerId, Direction.In))
|
|
|
|
let conns = @[
|
|
Connection.init(peerId, Direction.In),
|
|
Connection.init(peerId, Direction.In)]
|
|
|
|
expect TooManyConnectionsError:
|
|
connMngr.storeConn(conns[0])
|
|
connMngr.storeConn(conns[1])
|
|
|
|
await connMngr.close()
|
|
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "cleanup on connection close":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
let conn = Connection.init(peerId, Direction.In)
|
|
let muxer = new Muxer
|
|
|
|
muxer.connection = conn
|
|
connMngr.storeConn(conn)
|
|
connMngr.storeMuxer(muxer)
|
|
|
|
check conn in connMngr
|
|
check muxer in connMngr
|
|
|
|
await conn.close()
|
|
await sleepAsync(10.millis)
|
|
|
|
check conn notin connMngr
|
|
check muxer notin connMngr
|
|
|
|
await connMngr.close()
|
|
|
|
asyncTest "drop connections for peer":
|
|
let connMngr = ConnManager.init()
|
|
let peerId = PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet()
|
|
|
|
for i in 0..<2:
|
|
let dir = if i mod 2 == 0:
|
|
Direction.In else:
|
|
Direction.Out
|
|
|
|
let conn = Connection.init(peerId, dir)
|
|
let muxer = new Muxer
|
|
muxer.connection = conn
|
|
|
|
connMngr.storeConn(conn)
|
|
connMngr.storeMuxer(muxer)
|
|
|
|
check conn in connMngr
|
|
check muxer in connMngr
|
|
check not(isNil(connMngr.selectConn(peerId, dir)))
|
|
|
|
check peerId in connMngr
|
|
await connMngr.dropPeer(peerId)
|
|
|
|
check peerId notin connMngr
|
|
check isNil(connMngr.selectConn(peerId, Direction.In))
|
|
check isNil(connMngr.selectConn(peerId, Direction.Out))
|
|
|
|
await connMngr.close()
|
|
|
|
asyncTest "track total incoming connection limits":
|
|
let connMngr = ConnManager.init(maxConnections = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check await conn.withTimeout(10.millis)
|
|
conns.add(await conn)
|
|
|
|
# should timeout adding a connection over the limit
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check not(await conn.withTimeout(10.millis))
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track total outgoing connection limits":
|
|
let connMngr = ConnManager.init(maxConnections = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
conns.add(conn)
|
|
|
|
# should throw adding a connection over the limit
|
|
expect TooManyConnectionsError:
|
|
discard await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track both incoming and outgoing total connections limits - fail on incoming":
|
|
let connMngr = ConnManager.init(maxConnections = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
conns.add(conn)
|
|
|
|
# should timeout adding a connection over the limit
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check not(await conn.withTimeout(10.millis))
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track both incoming and outgoing total connections limits - fail on outgoing":
|
|
let connMngr = ConnManager.init(maxConnections = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check await conn.withTimeout(10.millis)
|
|
conns.add(await conn)
|
|
|
|
# should throw adding a connection over the limit
|
|
expect TooManyConnectionsError:
|
|
discard await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track max incoming connection limits":
|
|
let connMngr = ConnManager.init(maxIn = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check await conn.withTimeout(10.millis)
|
|
conns.add(await conn)
|
|
|
|
# should timeout adding a connection over the limit
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check not(await conn.withTimeout(10.millis))
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track max outgoing connection limits":
|
|
let connMngr = ConnManager.init(maxOut = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
conns.add(conn)
|
|
|
|
# should throw adding a connection over the limit
|
|
expect TooManyConnectionsError:
|
|
discard await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track incoming max connections limits - fail on incoming":
|
|
let connMngr = ConnManager.init(maxOut = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
conns.add(conn)
|
|
|
|
# should timeout adding a connection over the limit
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check not(await conn.withTimeout(10.millis))
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|
|
|
|
asyncTest "track incoming max connections limits - fail on outgoing":
|
|
let connMngr = ConnManager.init(maxIn = 3)
|
|
|
|
var conns: seq[Connection]
|
|
for i in 0..<3:
|
|
let conn = connMngr.trackIncomingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
check await conn.withTimeout(10.millis)
|
|
conns.add(await conn)
|
|
|
|
# should throw adding a connection over the limit
|
|
expect TooManyConnectionsError:
|
|
discard await connMngr.trackOutgoingConn(
|
|
proc(): Future[Connection] {.async.} =
|
|
return Connection.init(
|
|
PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(),
|
|
Direction.In)
|
|
)
|
|
|
|
await connMngr.close()
|
|
await allFuturesThrowing(
|
|
allFutures(conns.mapIt( it.close() )))
|