2021-06-30 08:59:30 +00:00
|
|
|
{.used.}
|
|
|
|
|
2022-09-22 19:55:59 +00:00
|
|
|
import chronos, stew/[byteutils, results]
|
2021-06-30 08:59:30 +00:00
|
|
|
import
|
|
|
|
../libp2p/
|
2024-06-11 15:18:06 +00:00
|
|
|
[
|
2021-06-30 08:59:30 +00:00
|
|
|
stream/connection,
|
|
|
|
transports/transport,
|
|
|
|
upgrademngrs/upgrade,
|
|
|
|
multiaddress,
|
2023-05-18 08:24:17 +00:00
|
|
|
errors,
|
|
|
|
]
|
2021-06-30 08:59:30 +00:00
|
|
|
|
|
|
|
import ./helpers
|
|
|
|
|
2023-06-07 11:12:49 +00:00
|
|
|
type TransportProvider* = proc(): Transport {.gcsafe, raises: [].}
|
2021-08-03 13:48:03 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
template commonTransportTest*(prov: TransportProvider, ma1: string, ma2: string = "") =
|
|
|
|
block:
|
|
|
|
let transpProvider = prov
|
2021-08-03 13:48:03 +00:00
|
|
|
|
|
|
|
asyncTest "can handle local address":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
|
|
|
let transport1 = transpProvider()
|
2021-08-03 13:48:03 +00:00
|
|
|
await transport1.start(ma)
|
2021-11-24 20:01:12 +00:00
|
|
|
check transport1.handles(transport1.addrs[0])
|
2021-08-03 13:48:03 +00:00
|
|
|
await transport1.stop()
|
|
|
|
|
2021-10-14 11:16:34 +00:00
|
|
|
asyncTest "e2e: handle observedAddr":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
2021-10-14 11:16:34 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport1 = transpProvider()
|
2021-10-14 11:16:34 +00:00
|
|
|
await transport1.start(ma)
|
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport2 = transpProvider()
|
2021-10-14 11:16:34 +00:00
|
|
|
|
2023-12-05 07:05:32 +00:00
|
|
|
proc acceptHandler() {.async.} =
|
2021-10-14 11:16:34 +00:00
|
|
|
let conn = await transport1.accept()
|
2022-09-22 19:55:59 +00:00
|
|
|
if conn.observedAddr.isSome():
|
|
|
|
check transport1.handles(conn.observedAddr.get())
|
2021-10-14 11:16:34 +00:00
|
|
|
await conn.close()
|
|
|
|
|
|
|
|
let handlerWait = acceptHandler()
|
|
|
|
|
2021-11-24 20:01:12 +00:00
|
|
|
let conn = await transport2.dial(transport1.addrs[0])
|
2021-10-14 11:16:34 +00:00
|
|
|
|
2022-09-22 19:55:59 +00:00
|
|
|
if conn.observedAddr.isSome():
|
|
|
|
check transport2.handles(conn.observedAddr.get())
|
2021-10-14 11:16:34 +00:00
|
|
|
|
|
|
|
await conn.close()
|
|
|
|
#for some protocols, closing requires actively reading, so we must close here
|
|
|
|
|
|
|
|
await allFuturesThrowing(allFinished(transport1.stop(), transport2.stop()))
|
|
|
|
|
|
|
|
await handlerWait.wait(1.seconds) # when no issues will not wait that long!
|
|
|
|
|
2021-06-30 08:59:30 +00:00
|
|
|
asyncTest "e2e: handle write":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
2021-06-30 08:59:30 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport1 = transpProvider()
|
2021-06-30 08:59:30 +00:00
|
|
|
await transport1.start(ma)
|
|
|
|
|
2023-12-05 07:05:32 +00:00
|
|
|
proc acceptHandler() {.async.} =
|
2021-06-30 08:59:30 +00:00
|
|
|
let conn = await transport1.accept()
|
|
|
|
await conn.write("Hello!")
|
|
|
|
await conn.close()
|
|
|
|
|
|
|
|
let handlerWait = acceptHandler()
|
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport2 = transpProvider()
|
2021-11-24 20:01:12 +00:00
|
|
|
let conn = await transport2.dial(transport1.addrs[0])
|
2021-06-30 08:59:30 +00:00
|
|
|
var msg = newSeq[byte](6)
|
|
|
|
await conn.readExactly(addr msg[0], 6)
|
|
|
|
|
2021-08-03 13:48:03 +00:00
|
|
|
await conn.close()
|
|
|
|
#for some protocols, closing requires actively reading, so we must close here
|
2021-06-30 08:59:30 +00:00
|
|
|
|
2021-08-03 13:48:03 +00:00
|
|
|
await allFuturesThrowing(allFinished(transport1.stop(), transport2.stop()))
|
2021-06-30 08:59:30 +00:00
|
|
|
|
|
|
|
check string.fromBytes(msg) == "Hello!"
|
2021-08-03 13:48:03 +00:00
|
|
|
await handlerWait.wait(1.seconds) # when no issues will not wait that long!
|
2021-06-30 08:59:30 +00:00
|
|
|
|
|
|
|
asyncTest "e2e: handle read":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
|
|
|
let transport1 = transpProvider()
|
2021-08-03 13:48:03 +00:00
|
|
|
await transport1.start(ma)
|
2021-06-30 08:59:30 +00:00
|
|
|
|
2023-12-05 07:05:32 +00:00
|
|
|
proc acceptHandler() {.async.} =
|
2021-06-30 08:59:30 +00:00
|
|
|
let conn = await transport1.accept()
|
|
|
|
var msg = newSeq[byte](6)
|
|
|
|
await conn.readExactly(addr msg[0], 6)
|
|
|
|
check string.fromBytes(msg) == "Hello!"
|
|
|
|
await conn.close()
|
|
|
|
|
|
|
|
let handlerWait = acceptHandler()
|
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport2 = transpProvider()
|
2021-11-24 20:01:12 +00:00
|
|
|
let conn = await transport2.dial(transport1.addrs[0])
|
2021-06-30 08:59:30 +00:00
|
|
|
await conn.write("Hello!")
|
|
|
|
|
2021-08-03 13:48:03 +00:00
|
|
|
await conn.close()
|
|
|
|
#for some protocols, closing requires actively reading, so we must close here
|
2021-06-30 08:59:30 +00:00
|
|
|
await handlerWait.wait(1.seconds) # when no issues will not wait that long!
|
|
|
|
|
2021-08-03 13:48:03 +00:00
|
|
|
await allFuturesThrowing(allFinished(transport1.stop(), transport2.stop()))
|
2021-06-30 08:59:30 +00:00
|
|
|
|
|
|
|
asyncTest "e2e: handle dial cancellation":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
2021-06-30 08:59:30 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport1 = transpProvider()
|
2021-06-30 08:59:30 +00:00
|
|
|
await transport1.start(ma)
|
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport2 = transpProvider()
|
2021-11-24 20:01:12 +00:00
|
|
|
let cancellation = transport2.dial(transport1.addrs[0])
|
2021-06-30 08:59:30 +00:00
|
|
|
|
|
|
|
await cancellation.cancelAndWait()
|
|
|
|
check cancellation.cancelled
|
|
|
|
|
2021-08-03 13:48:03 +00:00
|
|
|
await allFuturesThrowing(allFinished(transport1.stop(), transport2.stop()))
|
2021-06-30 08:59:30 +00:00
|
|
|
|
|
|
|
asyncTest "e2e: handle accept cancellation":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
2021-06-30 08:59:30 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport1 = transpProvider()
|
2021-06-30 08:59:30 +00:00
|
|
|
await transport1.start(ma)
|
|
|
|
|
|
|
|
let acceptHandler = transport1.accept()
|
|
|
|
await acceptHandler.cancelAndWait()
|
|
|
|
check acceptHandler.cancelled
|
|
|
|
|
|
|
|
await transport1.stop()
|
2021-08-03 13:48:03 +00:00
|
|
|
|
2021-11-24 20:01:12 +00:00
|
|
|
asyncTest "e2e should allow multiple local addresses":
|
2022-01-10 11:29:52 +00:00
|
|
|
when defined(windows):
|
|
|
|
# this randomly locks the Windows CI job
|
|
|
|
skip()
|
|
|
|
return
|
2022-11-04 18:20:23 +00:00
|
|
|
let addrs =
|
|
|
|
@[
|
|
|
|
MultiAddress.init(ma1).tryGet(),
|
|
|
|
MultiAddress.init(if ma2 == "": ma1 else: ma2).tryGet(),
|
|
|
|
]
|
2021-11-24 20:01:12 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport1 = transpProvider()
|
2021-11-24 20:01:12 +00:00
|
|
|
await transport1.start(addrs)
|
|
|
|
|
2023-12-05 07:05:32 +00:00
|
|
|
proc acceptHandler() {.async.} =
|
2021-11-24 20:01:12 +00:00
|
|
|
while true:
|
|
|
|
let conn = await transport1.accept()
|
2023-07-10 13:52:08 +00:00
|
|
|
await conn.write(newSeq[byte](0))
|
2021-11-24 20:01:12 +00:00
|
|
|
await conn.write("Hello!")
|
|
|
|
await conn.close()
|
|
|
|
|
|
|
|
let handlerWait = acceptHandler()
|
|
|
|
|
|
|
|
check transport1.addrs.len == 2
|
|
|
|
check transport1.addrs[0] != transport1.addrs[1]
|
|
|
|
|
|
|
|
var msg = newSeq[byte](6)
|
|
|
|
|
|
|
|
proc client(ma: MultiAddress) {.async.} =
|
|
|
|
let conn1 = await transport1.dial(ma)
|
|
|
|
await conn1.readExactly(addr msg[0], 6)
|
|
|
|
check string.fromBytes(msg) == "Hello!"
|
|
|
|
await conn1.close()
|
|
|
|
|
|
|
|
#Dial the same server multiple time in a row
|
|
|
|
await client(transport1.addrs[0])
|
|
|
|
await client(transport1.addrs[0])
|
|
|
|
await client(transport1.addrs[0])
|
|
|
|
|
|
|
|
#Dial the same server on different addresses
|
|
|
|
await client(transport1.addrs[1])
|
|
|
|
await client(transport1.addrs[0])
|
|
|
|
await client(transport1.addrs[1])
|
|
|
|
|
|
|
|
#Cancel a dial
|
|
|
|
#TODO add back once chronos fixes cancellation
|
|
|
|
#let
|
|
|
|
# dial1 = transport1.dial(transport1.addrs[1])
|
|
|
|
# dial2 = transport1.dial(transport1.addrs[0])
|
|
|
|
#await dial1.cancelAndWait()
|
|
|
|
#await dial2.cancelAndWait()
|
|
|
|
|
|
|
|
await handlerWait.cancelAndWait()
|
|
|
|
|
|
|
|
await transport1.stop()
|
|
|
|
|
2021-08-03 13:48:03 +00:00
|
|
|
asyncTest "e2e: stopping transport kills connections":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
2021-08-03 13:48:03 +00:00
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport1 = transpProvider()
|
2021-08-03 13:48:03 +00:00
|
|
|
await transport1.start(ma)
|
|
|
|
|
2022-11-04 18:20:23 +00:00
|
|
|
let transport2 = transpProvider()
|
2021-08-03 13:48:03 +00:00
|
|
|
|
|
|
|
let acceptHandler = transport1.accept()
|
2021-11-24 20:01:12 +00:00
|
|
|
let conn = await transport2.dial(transport1.addrs[0])
|
2021-08-03 13:48:03 +00:00
|
|
|
let serverConn = await acceptHandler
|
|
|
|
|
|
|
|
await allFuturesThrowing(allFinished(transport1.stop(), transport2.stop()))
|
|
|
|
|
|
|
|
check serverConn.closed()
|
|
|
|
check conn.closed()
|
|
|
|
|
|
|
|
asyncTest "read or write on closed connection":
|
2022-11-04 18:20:23 +00:00
|
|
|
let ma = @[MultiAddress.init(ma1).tryGet()]
|
|
|
|
let transport1 = transpProvider()
|
2021-08-03 13:48:03 +00:00
|
|
|
await transport1.start(ma)
|
|
|
|
|
2023-12-05 07:05:32 +00:00
|
|
|
proc acceptHandler() {.async.} =
|
2021-08-03 13:48:03 +00:00
|
|
|
let conn = await transport1.accept()
|
|
|
|
await conn.close()
|
|
|
|
|
|
|
|
let handlerWait = acceptHandler()
|
|
|
|
|
2021-11-24 20:01:12 +00:00
|
|
|
let conn = await transport1.dial(transport1.addrs[0])
|
2021-08-03 13:48:03 +00:00
|
|
|
|
|
|
|
var msg = newSeq[byte](6)
|
|
|
|
try:
|
|
|
|
await conn.readExactly(addr msg[0], 6)
|
|
|
|
check false
|
|
|
|
except CatchableError as exc:
|
|
|
|
check true
|
|
|
|
|
|
|
|
# we don't HAVE to throw on write on EOF
|
|
|
|
# (at least TCP doesn't)
|
|
|
|
try:
|
|
|
|
await conn.write(msg)
|
|
|
|
except CatchableError as exc:
|
|
|
|
check true
|
|
|
|
|
|
|
|
await conn.close()
|
|
|
|
#for some protocols, closing requires actively reading, so we must close here
|
|
|
|
await handlerWait.wait(1.seconds) # when no issues will not wait that long!
|
|
|
|
|
|
|
|
await transport1.stop()
|