* use a builder pattern to build the switch (#551)

* use a builder pattern to build the switch

* with with

* more refs

* Merge master (#555)

* Revisit Floodsub (#543)

Fixes #525

add coverage to unsubscribeAll and testing

* add mounted protos to identify message (#546)

* add stable/unstable auto bumps

* fix auto-bump CI

* merge nbc auto bump with CI in order to bump only on CI success

* put conditional locks on nbc bump (#549)

* Fix minor exception issues (#550)

Makes code compatible with
https://github.com/status-im/nim-chronos/pull/166 without requiring it.

* fix nimbus ref for auto-bump stable's PR

* Split dialer (#542)

* extracting dialing logic to dialer

* exposing upgrade methods on transport

* cleanup

* fixing tests to use new interfaces

* add comments

* add base exception class and fix hierarchy

* fix imports

* `doAssert` is `ValueError` not `AssertionError`?

* revert back to `AssertionError`

Co-authored-by: Giovanni Petrantoni <7008900+sinkingsugar@users.noreply.github.com>
Co-authored-by: Jacek Sieka <jacek@status.im>

* `doAssert` is `ValueError` not `AssertionError`?

* revert back to `AssertionError`

* fix builders

* more builder stuff

* more builders

Co-authored-by: Giovanni Petrantoni <7008900+sinkingsugar@users.noreply.github.com>
Co-authored-by: Jacek Sieka <jacek@status.im>
This commit is contained in:
Dmitriy Ryajov 2021-04-05 13:37:14 -06:00 committed by GitHub
parent 1a00ef0a1e
commit a21d300e3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 209 additions and 80 deletions

View File

@ -26,7 +26,7 @@ import
peerid, peerid,
peerinfo, peerinfo,
multiaddress, multiaddress,
standard_setup, builders,
crypto/crypto] crypto/crypto]
import bearssl import bearssl
@ -36,4 +36,4 @@ export
connection, multiaddress, crypto, lpstream, connection, multiaddress, crypto, lpstream,
bufferstream, bearssl, muxer, mplex, transport, bufferstream, bearssl, muxer, mplex, transport,
tcptransport, noise, errors, cid, multihash, tcptransport, noise, errors, cid, multihash,
multicodec, standard_setup multicodec, builders

198
libp2p/builders.nim Normal file
View File

@ -0,0 +1,198 @@
import
options, tables, chronos, bearssl,
switch, peerid, peerinfo, stream/connection, multiaddress,
crypto/crypto, transports/[transport, tcptransport],
muxers/[muxer, mplex/mplex],
protocols/[identify, secure/secure, secure/noise],
connmanager, upgrademngrs/muxedupgrade
export
switch, peerid, peerinfo, connection, multiaddress, crypto
type
SecureProtocol* {.pure.} = enum
Noise,
Secio {.deprecated.}
TcpTransportOpts = object
enable: bool
flags: set[ServerFlags]
MplexOpts = object
enable: bool
newMuxer: MuxerConstructor
SwitchBuilder* = ref object
privKey: Option[PrivateKey]
address: MultiAddress
secureManagers: seq[SecureProtocol]
mplexOpts: MplexOpts
tcpTransportOpts: TcpTransportOpts
rng: ref BrHmacDrbgContext
inTimeout: Duration
outTimeout: Duration
maxConnections: int
maxIn: int
maxOut: int
maxConnsPerPeer: int
protoVersion: string
agentVersion: string
proc init*(T: type[SwitchBuilder]): T =
SwitchBuilder(
privKey: none(PrivateKey),
address: MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(),
secureManagers: @[],
tcpTransportOpts: TcpTransportOpts(),
rng: newRng(),
maxConnections: MaxConnections,
maxIn: -1,
maxOut: -1,
maxConnsPerPeer: MaxConnectionsPerPeer,
protoVersion: ProtoVersion,
agentVersion: AgentVersion)
proc withPrivateKey*(b: SwitchBuilder, privateKey: PrivateKey): SwitchBuilder =
b.privKey = some(privateKey)
b
proc withAddress*(b: SwitchBuilder, address: MultiAddress): SwitchBuilder =
b.address = address
b
proc withMplex*(b: SwitchBuilder, inTimeout = 5.minutes, outTimeout = 5.minutes): SwitchBuilder =
proc newMuxer(conn: Connection): Muxer =
Mplex.init(
conn,
inTimeout = inTimeout,
outTimeout = outTimeout)
b.mplexOpts = MplexOpts(
enable: true,
newMuxer: newMuxer,
)
b
proc withNoise*(b: SwitchBuilder): SwitchBuilder =
b.secureManagers.add(SecureProtocol.Noise)
b
proc withTcpTransport*(b: SwitchBuilder, flags: set[ServerFlags] = {}): SwitchBuilder =
b.tcpTransportOpts.enable = true
b.tcpTransportOpts.flags = flags
b
proc withRng*(b: SwitchBuilder, rng: ref BrHmacDrbgContext): SwitchBuilder =
b.rng = rng
b
proc withMaxConnections*(b: SwitchBuilder, maxConnections: int): SwitchBuilder =
b.maxConnections = maxConnections
b
proc withMaxIn*(b: SwitchBuilder, maxIn: int): SwitchBuilder =
b.maxIn = maxIn
b
proc withMaxOut*(b: SwitchBuilder, maxOut: int): SwitchBuilder =
b.maxOut = maxOut
b
proc withMaxConnsPerPeer*(b: SwitchBuilder, maxConnsPerPeer: int): SwitchBuilder =
b.maxConnsPerPeer = maxConnsPerPeer
b
proc withProtoVersion*(b: SwitchBuilder, protoVersion: string): SwitchBuilder =
b.protoVersion = protoVersion
b
proc withAgentVersion*(b: SwitchBuilder, agentVersion: string): SwitchBuilder =
b.agentVersion = agentVersion
b
proc build*(b: SwitchBuilder): Switch =
if b.rng == nil: # newRng could fail
raise (ref CatchableError)(msg: "Cannot initialize RNG")
let
seckey = b.privKey.get(otherwise = PrivateKey.random(b.rng[]).tryGet())
var
secureManagerInstances: seq[Secure]
if SecureProtocol.Noise in b.secureManagers:
secureManagerInstances.add(newNoise(b.rng, seckey).Secure)
let
peerInfo = block:
var info = PeerInfo.init(seckey, [b.address])
info.protoVersion = b.protoVersion
info.agentVersion = b.agentVersion
info
let
muxers = block:
var muxers: Table[string, MuxerProvider]
if b.mplexOpts.enable:
muxers.add(MplexCodec, newMuxerProvider(b.mplexOpts.newMuxer, MplexCodec))
muxers
let
identify = newIdentify(peerInfo)
connManager = ConnManager.init(b.maxConnsPerPeer, b.maxConnections, b.maxIn, b.maxOut)
ms = newMultistream()
muxedUpgrade = MuxedUpgrade.init(identify, muxers, secureManagerInstances, connManager, ms)
let
transports = block:
var transports: seq[Transport]
if b.tcpTransportOpts.enable:
transports.add(Transport(TcpTransport.init(b.tcpTransportOpts.flags, muxedUpgrade)))
transports
if b.secureManagers.len == 0:
b.secureManagers &= SecureProtocol.Noise
let switch = newSwitch(
peerInfo = peerInfo,
transports = transports,
identity = identify,
muxers = muxers,
secureManagers = secureManagerInstances,
connManager = connManager,
ms = ms)
return switch
proc newStandardSwitch*(privKey = none(PrivateKey),
address = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(),
secureManagers: openarray[SecureProtocol] = [
SecureProtocol.Noise,
],
transportFlags: set[ServerFlags] = {},
rng = newRng(),
inTimeout: Duration = 5.minutes,
outTimeout: Duration = 5.minutes,
maxConnections = MaxConnections,
maxIn = -1,
maxOut = -1,
maxConnsPerPeer = MaxConnectionsPerPeer): Switch =
if SecureProtocol.Secio in secureManagers:
quit("Secio is deprecated!") # use of secio is unsafe
var b = SwitchBuilder
.init()
.withAddress(address)
.withRng(rng)
.withMaxConnections(maxConnections)
.withMaxIn(maxIn)
.withMaxOut(maxOut)
.withMaxConnsPerPeer(maxConnsPerPeer)
.withMplex(inTimeout, outTimeout)
.withTcpTransport(transportFlags)
.withNoise()
if privKey.isSome():
b = b.withPrivateKey(privKey.get())
b.build()

View File

@ -578,8 +578,10 @@ method init*(p: Noise) {.gcsafe.} =
p.codec = NoiseCodec p.codec = NoiseCodec
proc newNoise*( proc newNoise*(
rng: ref BrHmacDrbgContext, privateKey: PrivateKey; rng: ref BrHmacDrbgContext,
outgoing: bool = true; commonPrologue: seq[byte] = @[]): Noise = privateKey: PrivateKey;
outgoing: bool = true;
commonPrologue: seq[byte] = @[]): Noise =
result = Noise( result = Noise(
rng: rng, rng: rng,
outgoing: outgoing, outgoing: outgoing,

View File

@ -1,71 +0,0 @@
import
options, tables, chronos, bearssl,
switch, peerid, peerinfo, stream/connection, multiaddress,
crypto/crypto, transports/[transport, tcptransport],
muxers/[muxer, mplex/mplex],
protocols/[identify, secure/secure, secure/noise],
upgrademngrs/[upgrade, muxedupgrade], connmanager
export
switch, peerid, peerinfo, connection, multiaddress, crypto
type
SecureProtocol* {.pure.} = enum
Noise,
Secio {.deprecated.}
proc newStandardSwitch*(privKey = none(PrivateKey),
address = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(),
secureManagers: openarray[SecureProtocol] = [
SecureProtocol.Noise,
],
transportFlags: set[ServerFlags] = {},
rng = newRng(),
inTimeout: Duration = 5.minutes,
outTimeout: Duration = 5.minutes,
maxConnections = MaxConnections,
maxIn = -1,
maxOut = -1,
maxConnsPerPeer = MaxConnectionsPerPeer): Switch =
proc createMplex(conn: Connection): Muxer =
Mplex.init(
conn,
inTimeout = inTimeout,
outTimeout = outTimeout)
if rng == nil: # newRng could fail
raise (ref CatchableError)(msg: "Cannot initialize RNG")
let
seckey = privKey.get(otherwise = PrivateKey.random(rng[]).tryGet())
peerInfo = PeerInfo.init(seckey, [address])
var
secureManagerInstances: seq[Secure]
for sec in secureManagers:
case sec
of SecureProtocol.Noise:
secureManagerInstances &= newNoise(rng, seckey).Secure
of SecureProtocol.Secio:
quit("Secio is deprecated!") # use of secio is unsafe
let
mplexProvider = newMuxerProvider(createMplex, MplexCodec)
ms = newMultistream()
identify = newIdentify(peerInfo)
muxers = {MplexCodec: mplexProvider}.toTable
connManager = ConnManager.init(maxConnsPerPeer, maxConnections, maxIn, maxOut)
muxedUpgrade = MuxedUpgrade.init(identify, muxers, secureManagerInstances, connManager, ms)
transports = @[Transport(TcpTransport.init(transportFlags, muxedUpgrade))]
let switch = newSwitch(
peerInfo,
transports,
identify,
muxers,
secureManagers = secureManagerInstances,
connManager = connManager,
ms = ms)
return switch

View File

@ -5,7 +5,7 @@ include ../../libp2p/protocols/pubsub/gossipsub
import options import options
import unittest, bearssl import unittest, bearssl
import stew/byteutils import stew/byteutils
import ../../libp2p/standard_setup import ../../libp2p/builders
import ../../libp2p/errors import ../../libp2p/errors
import ../../libp2p/crypto/crypto import ../../libp2p/crypto/crypto
import ../../libp2p/stream/bufferstream import ../../libp2p/stream/bufferstream

View File

@ -6,13 +6,13 @@ const
import random, tables import random, tables
import chronos import chronos
import ../../libp2p/[standard_setup, import ../../libp2p/[builders,
protocols/pubsub/pubsub, protocols/pubsub/pubsub,
protocols/pubsub/gossipsub, protocols/pubsub/gossipsub,
protocols/pubsub/floodsub, protocols/pubsub/floodsub,
protocols/secure/secure] protocols/secure/secure]
export standard_setup export builders
randomize() randomize()

View File

@ -10,7 +10,7 @@ import ../libp2p/[daemon/daemonapi,
cid, cid,
varint, varint,
multihash, multihash,
standard_setup, builders,
peerid, peerid,
peerinfo, peerinfo,
switch, switch,

View File

@ -7,7 +7,7 @@ import nimcrypto/sysrand
import ../libp2p/[errors, import ../libp2p/[errors,
switch, switch,
multistream, multistream,
standard_setup, builders,
stream/bufferstream, stream/bufferstream,
stream/connection, stream/connection,
multiaddress, multiaddress,