diff --git a/libp2p/builders.nim b/libp2p/builders.nim index e15ccc10b..b2729362e 100644 --- a/libp2p/builders.nim +++ b/libp2p/builders.nim @@ -136,7 +136,7 @@ proc withNameResolver*(b: SwitchBuilder, nameResolver: NameResolver): SwitchBuil b proc build*(b: SwitchBuilder): Switch - {.raises: [Defect, LPError].} = + {.raises: [Defect, LPDefect, LPError].} = if b.rng == nil: # newRng could fail raise newException(Defect, "Cannot initialize RNG") @@ -210,7 +210,7 @@ proc newStandardSwitch*( maxOut = -1, maxConnsPerPeer = MaxConnectionsPerPeer, nameResolver: NameResolver = nil): Switch - {.raises: [Defect, LPError].} = + {.raises: [Defect, LPDefect, LPError].} = if SecureProtocol.Secio in secureManagers: quit("Secio is deprecated!") # use of secio is unsafe diff --git a/libp2p/errors.nim b/libp2p/errors.nim index 83d41162a..16b166382 100644 --- a/libp2p/errors.nim +++ b/libp2p/errors.nim @@ -9,6 +9,8 @@ type # Base exception type for libp2p LPError* = object of CatchableError + LPDefect* = object of CatchableError + func toException*(e: cstring): ref LPError = (ref LPError)(msg: $e) diff --git a/libp2p/switch.nim b/libp2p/switch.nim index 673ff8f0f..fca3705c1 100644 --- a/libp2p/switch.nim +++ b/libp2p/switch.nim @@ -261,7 +261,13 @@ proc newSwitch*(peerInfo: PeerInfo, connManager: ConnManager, ms: MultistreamSelect, nameResolver: NameResolver = nil): Switch - {.raises: [Defect, LPError].} = + {.raises: [Defect, LPDefect, LPError].} = + + if transports.len == 0: + raise newException(LPDefect, "Provide at least one transport") + + if peerInfo.addrs.len == 0: + raise newException(LPDefect, "Provide at least one address") if secureManagers.len == 0: raise newException(LPError, "Provide at least one secure manager") diff --git a/libp2p/transports/transport.nim b/libp2p/transports/transport.nim index 3ae1bb093..7b07bcebe 100644 --- a/libp2p/transports/transport.nim +++ b/libp2p/transports/transport.nim @@ -21,6 +21,7 @@ logScope: topics = "libp2p transport" type + TransportDefect* = object of Defect ListenErrorCallback* = proc ( ma: MultiAddress, err: ref CatchableError): Future[ref TransportListenError] @@ -56,11 +57,16 @@ const ListenErrorDefault* = method start*( self: Transport, - addrs: seq[MultiAddress]) {.base, async, raises: [Defect, TransportListenError].} = + addrs: seq[MultiAddress]) + {.base, async, raises: [Defect, TransportDefect, TransportListenError].} = ## start the transport ## trace "starting transport on addrs", address = $addrs + if addrs.len == 0: + raise newException(TransportDefect, + "Transport requires at least one address to be started") + self.addrs = addrs self.running = true diff --git a/tests/testswitch.nim b/tests/testswitch.nim index 2ace7c070..5d708d8c6 100644 --- a/tests/testswitch.nim +++ b/tests/testswitch.nim @@ -1,6 +1,6 @@ {.used.} -import options, sequtils, sets, tables +import options, sequtils, sets, sugar, tables import chronos import stew/byteutils import nimcrypto/sysrand @@ -17,6 +17,7 @@ import ../libp2p/[errors, protocols/secure/secure, muxers/muxer, muxers/mplex/lpchannel, + muxers/mplex/mplex, stream/lpstream, nameresolving/nameresolver, nameresolving/mockresolver, @@ -1492,3 +1493,60 @@ suite "Switch": check switch.transports[0].addrs == @[maTcp1, maUdp, maTcp2] await switch.stop() + + asyncTest "should raise defect if no transports provided during construction": + let + mAddrs = buildLocalTcpAddrs(3) + transport = (upgr: Upgrade) -> Transport => MockTransport.new(upgr) + + # builder should raise defect with addresses, but no transports + expect LPDefect: + discard SwitchBuilder + .new() + .withRng(rng) # Give the application RNG + .withAddresses(mAddrs) # Our local address(es) + .withMplex() # Use Mplex as muxer + .withNoise() # Use Noise as secure manager + .build() + + # builder should raise defect with transports, but no addresses + expect LPDefect: + echo "[testswitch] building switch with no addresses" + discard SwitchBuilder + .new() + .withRng(rng) # Give the application RNG + .withTransport(transport) + .withAddresses(@[]) + .withMplex() # Use Mplex as muxer + .withNoise() # Use Noise as secure manager + .build() + + # should raise defect with addresses, but no transports + var + seckey = PrivateKey.random(rng[]).get() + peerInfo = PeerInfo.new(seckey, mAddrs) + identify = Identify.new(peerInfo) + muxers = initTable[string, MuxerProvider]() + + muxers[MplexCodec] = + MuxerProvider.new((conn: Connection) -> Muxer => Mplex.new(conn), MplexCodec) + + expect LPDefect: + discard newSwitch( + peerInfo = peerInfo, + transports = @[], + identity = identify, + muxers = muxers, + connManager = ConnManager.new(), + ms = MultistreamSelect.new()) + + # should raise defect with transports, but no addresses + peerInfo.addrs = @[] + expect LPDefect: + discard newSwitch( + peerInfo = peerInfo, + transports = @[transport(Upgrade.new())], + identity = identify, + muxers = muxers, + connManager = ConnManager.new(), + ms = MultistreamSelect.new()) diff --git a/tests/testtcptransport.nim b/tests/testtcptransport.nim index 94baaf087..4f0392e86 100644 --- a/tests/testtcptransport.nim +++ b/tests/testtcptransport.nim @@ -250,6 +250,14 @@ suite "TCP transport": await transport.stop() + asyncTest "should raise Defect on start with no addresses": + let transport = TcpTransport.new(upgrade = Upgrade()) + + expect TransportDefect: + await transport.start(@[]) + + await transport.stop() + commonTransportTest( "TcpTransport", proc (): Transport = TcpTransport.new(upgrade = Upgrade()), diff --git a/tests/testwstransport.nim b/tests/testwstransport.nim index baf4eb796..3b41d6902 100644 --- a/tests/testwstransport.nim +++ b/tests/testwstransport.nim @@ -180,6 +180,14 @@ suite "WebSocket transport": await transport.stop() + asyncTest "should raise Defect on start with no addresses": + let transport = WsTransport.new(upgrade = Upgrade()) + + expect TransportDefect: + await transport.start(@[]) + + await transport.stop() + commonTransportTest( "WebSocket", proc (): Transport = WsTransport.new(Upgrade()),