Add Autonat timeout (#829)

Co-authored-by: Ludovic Chenut <ludovic@status.im>
This commit is contained in:
diegomrsantos 2022-12-22 20:29:31 +01:00 committed by GitHub
parent d521c57b82
commit 676786b00e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 12 deletions

View File

@ -46,21 +46,21 @@ type
InternalError = 300 InternalError = 300
AutonatPeerInfo* = object AutonatPeerInfo* = object
id: Option[PeerId] id*: Option[PeerId]
addrs: seq[MultiAddress] addrs*: seq[MultiAddress]
AutonatDial* = object AutonatDial* = object
peerInfo: Option[AutonatPeerInfo] peerInfo*: Option[AutonatPeerInfo]
AutonatDialResponse* = object AutonatDialResponse* = object
status*: ResponseStatus status*: ResponseStatus
text*: Option[string] text*: Option[string]
ma*: Option[MultiAddress] ma*: Option[MultiAddress]
AutonatMsg = object AutonatMsg* = object
msgType: MsgType msgType*: MsgType
dial: Option[AutonatDial] dial*: Option[AutonatDial]
response: Option[AutonatDialResponse] response*: Option[AutonatDialResponse]
proc encode*(msg: AutonatMsg): ProtoBuffer = proc encode*(msg: AutonatMsg): ProtoBuffer =
result = initProtoBuffer() result = initProtoBuffer()
@ -120,7 +120,7 @@ proc encode*(r: AutonatDialResponse): ProtoBuffer =
result.write(3, bufferResponse.buffer) result.write(3, bufferResponse.buffer)
result.finish() result.finish()
proc decode(_: typedesc[AutonatMsg], buf: seq[byte]): Option[AutonatMsg] = proc decode*(_: typedesc[AutonatMsg], buf: seq[byte]): Option[AutonatMsg] =
var var
msgTypeOrd: uint32 msgTypeOrd: uint32
pbDial: ProtoBuffer pbDial: ProtoBuffer
@ -203,6 +203,7 @@ type
Autonat* = ref object of LPProtocol Autonat* = ref object of LPProtocol
sem: AsyncSemaphore sem: AsyncSemaphore
switch*: Switch switch*: Switch
dialTimeout: Duration
method dialMe*(a: Autonat, pid: PeerId, addrs: seq[MultiAddress] = newSeq[MultiAddress]()): method dialMe*(a: Autonat, pid: PeerId, addrs: seq[MultiAddress] = newSeq[MultiAddress]()):
Future[MultiAddress] {.base, async.} = Future[MultiAddress] {.base, async.} =
@ -240,7 +241,7 @@ method dialMe*(a: Autonat, pid: PeerId, addrs: seq[MultiAddress] = newSeq[MultiA
proc tryDial(a: Autonat, conn: Connection, addrs: seq[MultiAddress]) {.async.} = proc tryDial(a: Autonat, conn: Connection, addrs: seq[MultiAddress]) {.async.} =
try: try:
await a.sem.acquire() await a.sem.acquire()
let ma = await a.switch.dialer.tryDial(conn.peerId, addrs) let ma = await a.switch.dialer.tryDial(conn.peerId, addrs).wait(a.dialTimeout)
if ma.isSome: if ma.isSome:
await conn.sendResponseOk(ma.get()) await conn.sendResponseOk(ma.get())
else: else:
@ -298,8 +299,8 @@ proc handleDial(a: Autonat, conn: Connection, msg: AutonatMsg): Future[void] =
return conn.sendResponseError(DialRefused, "No dialable address") return conn.sendResponseError(DialRefused, "No dialable address")
return a.tryDial(conn, toSeq(addrs)) return a.tryDial(conn, toSeq(addrs))
proc new*(T: typedesc[Autonat], switch: Switch, semSize: int = 1): T = proc new*(T: typedesc[Autonat], switch: Switch, semSize: int = 1, dialTimeout = 15.seconds): T =
let autonat = T(switch: switch, sem: newAsyncSemaphore(semSize)) let autonat = T(switch: switch, sem: newAsyncSemaphore(semSize), dialTimeout: dialTimeout)
autonat.init() autonat.init()
autonat autonat

View File

@ -52,7 +52,7 @@ proc new*(
numPeersToAsk: int = 5, numPeersToAsk: int = 5,
maxQueueSize: int = 10, maxQueueSize: int = 10,
minConfidence: float = 0.3, minConfidence: float = 0.3,
dialTimeout = 5.seconds): T = dialTimeout = 30.seconds): T =
return T( return T(
scheduleInterval: scheduleInterval, scheduleInterval: scheduleInterval,
networkReachability: Unknown, networkReachability: Unknown,

View File

@ -2,6 +2,8 @@ import std/options
import chronos import chronos
import import
../libp2p/[ ../libp2p/[
transports/tcptransport,
upgrademngrs/upgrade,
builders, builders,
protocols/connectivity/autonat protocols/connectivity/autonat
], ],
@ -58,3 +60,30 @@ suite "Autonat":
expect AutonatUnreachableError: expect AutonatUnreachableError:
discard await Autonat.new(src).dialMe(dst.peerInfo.peerId, dst.peerInfo.addrs) discard await Autonat.new(src).dialMe(dst.peerInfo.peerId, dst.peerInfo.addrs)
await allFutures(src.stop(), dst.stop()) await allFutures(src.stop(), dst.stop())
asyncTest "Timeout is triggered in autonat handle":
let
src = newStandardSwitch()
dst = newStandardSwitch()
autonat = Autonat.new(dst, dialTimeout = 1.seconds)
doesNothingListener = TcpTransport.new(upgrade = Upgrade())
dst.mount(autonat)
await src.start()
await dst.start()
await doesNothingListener.start(@[MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()])
await src.connect(dst.peerInfo.peerId, dst.peerInfo.addrs)
let conn = await src.dial(dst.peerInfo.peerId, @[AutonatCodec])
let buffer = AutonatDial(peerInfo: some(AutonatPeerInfo(
id: some(src.peerInfo.peerId),
# we ask to be dialed in the does nothing listener instead
addrs: doesNothingListener.addrs
))).encode().buffer
await conn.writeLp(buffer)
let response = AutonatMsg.decode(await conn.readLp(1024)).get().response.get()
check:
response.status == DialError
response.text.get() == "Timeout exceeded!"
response.ma.isNone()
await allFutures(doesNothingListener.stop(), src.stop(), dst.stop())