Skip to content

Commit 61929ae

Browse files
Improve rdv advertise (vacp2p#951)
Co-authored-by: Ludovic Chenut <ludovic@status.im>
1 parent 56599f5 commit 61929ae

File tree

5 files changed

+88
-12
lines changed

5 files changed

+88
-12
lines changed

libp2p/discovery/discoverymngr.nim

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,20 +122,15 @@ proc request*[T](dm: DiscoveryManager, value: T): DiscoveryQuery =
122122
pa.add(value)
123123
return dm.request(pa)
124124

125-
proc advertise*(dm: DiscoveryManager, pa: PeerAttributes) =
125+
proc advertise*[T](dm: DiscoveryManager, value: T) =
126126
for i in dm.interfaces:
127-
i.toAdvertise = pa
127+
i.toAdvertise.add(value)
128128
if i.advertiseLoop.isNil:
129129
i.advertisementUpdated = newAsyncEvent()
130130
i.advertiseLoop = i.advertise()
131131
else:
132132
i.advertisementUpdated.fire()
133133

134-
proc advertise*[T](dm: DiscoveryManager, value: T) =
135-
var pa: PeerAttributes
136-
pa.add(value)
137-
dm.advertise(pa)
138-
139134
template forEach*(query: DiscoveryQuery, code: untyped) =
140135
## Will execute `code` for each discovered peer. The
141136
## peer attritubtes are available through the variable

libp2p/discovery/rendezvousinterface.nim

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type
1919
rdv*: RendezVous
2020
timeToRequest: Duration
2121
timeToAdvertise: Duration
22+
ttl: Duration
2223

2324
RdvNamespace* = distinct string
2425

@@ -62,12 +63,16 @@ method advertise*(self: RendezVousInterface) {.async.} =
6263

6364
self.advertisementUpdated.clear()
6465
for toAdv in toAdvertise:
65-
await self.rdv.advertise(toAdv, self.timeToAdvertise)
66+
try:
67+
await self.rdv.advertise(toAdv, self.ttl)
68+
except CatchableError as error:
69+
debug "RendezVous advertise error: ", msg = error.msg
6670

6771
await sleepAsync(self.timeToAdvertise) or self.advertisementUpdated.wait()
6872

6973
proc new*(T: typedesc[RendezVousInterface],
7074
rdv: RendezVous,
7175
ttr: Duration = 1.minutes,
72-
tta: Duration = MinimumDuration): RendezVousInterface =
73-
T(rdv: rdv, timeToRequest: ttr, timeToAdvertise: tta)
76+
tta: Duration = 1.minutes,
77+
ttl: Duration = MinimumDuration): RendezVousInterface =
78+
T(rdv: rdv, timeToRequest: ttr, timeToAdvertise: tta, ttl: ttl)

libp2p/protocols/rendezvous.nim

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,16 +469,18 @@ proc advertisePeer(rdv: RendezVous,
469469
trace "Unexpected register response", peer, msgType = msgRecv.msgType
470470
elif msgRecv.registerResponse.tryGet().status != ResponseStatus.Ok:
471471
trace "Refuse to register", peer, response = msgRecv.registerResponse
472+
else:
473+
trace "Successfully registered", peer, response = msgRecv.registerResponse
472474
except CatchableError as exc:
473475
trace "exception in the advertise", error = exc.msg
474476
finally:
475477
rdv.sema.release()
476478
await rdv.sema.acquire()
477479
discard await advertiseWrap().withTimeout(5.seconds)
478480

479-
proc advertise*(rdv: RendezVous,
481+
method advertise*(rdv: RendezVous,
480482
ns: string,
481-
ttl: Duration = MinimumDuration) {.async.} =
483+
ttl: Duration = MinimumDuration) {.async, base.} =
482484
let sprBuff = rdv.switch.peerInfo.signedPeerRecord.encode().valueOr:
483485
raise newException(RendezVousError, "Wrong Signed Peer Record")
484486
if ns.len notin 1..255:

tests/testrendezvous.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import chronos
1414
import ../libp2p/[protocols/rendezvous,
1515
switch,
1616
builders,]
17+
import ../libp2p/discovery/[rendezvousinterface, discoverymngr]
1718
import ./helpers
1819

1920
proc createSwitch(rdv: RendezVous = RendezVous.new()): Switch =

tests/testrendezvousinterface.nim

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{.used.}
2+
3+
# Nim-Libp2p
4+
# Copyright (c) 2023 Status Research & Development GmbH
5+
# Licensed under either of
6+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
7+
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
8+
# at your option.
9+
# This file may not be copied, modified, or distributed except according to
10+
# those terms.
11+
12+
import sequtils, strutils
13+
import chronos
14+
import ../libp2p/[protocols/rendezvous,
15+
switch,
16+
builders,]
17+
import ../libp2p/discovery/[rendezvousinterface, discoverymngr]
18+
import ./helpers
19+
20+
proc createSwitch(rdv: RendezVous = RendezVous.new()): Switch =
21+
SwitchBuilder.new()
22+
.withRng(newRng())
23+
.withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ])
24+
.withTcpTransport()
25+
.withMplex()
26+
.withNoise()
27+
.withRendezVous(rdv)
28+
.build()
29+
30+
type
31+
MockRendezVous = ref object of RendezVous
32+
numAdvertiseNs1: int
33+
numAdvertiseNs2: int
34+
35+
MockErrorRendezVous = ref object of MockRendezVous
36+
37+
method advertise*(self: MockRendezVous, namespace: string, ttl: Duration) {.async.} =
38+
if namespace == "ns1":
39+
self.numAdvertiseNs1 += 1
40+
elif namespace == "ns2":
41+
self.numAdvertiseNs2 += 1
42+
# Forward the call to the actual implementation
43+
await procCall RendezVous(self).advertise(namespace, ttl)
44+
45+
method advertise*(self: MockErrorRendezVous, namespace: string, ttl: Duration) {.async.} =
46+
await procCall MockRendezVous(self).advertise(namespace, ttl)
47+
raise newException(CatchableError, "MockErrorRendezVous.advertise")
48+
49+
suite "RendezVous Interface":
50+
teardown:
51+
checkTrackers()
52+
53+
proc baseTimeToAdvertiseTest(rdv: MockRendezVous) {.async.} =
54+
let
55+
tta = 100.milliseconds
56+
ttl = 2.hours
57+
client = createSwitch(rdv)
58+
dm = DiscoveryManager()
59+
60+
await client.start()
61+
dm.add(RendezVousInterface.new(rdv = rdv, tta = tta, ttl = ttl))
62+
dm.advertise(RdvNamespace("ns1"))
63+
dm.advertise(RdvNamespace("ns2"))
64+
65+
checkExpiring: rdv.numAdvertiseNs1 >= 5
66+
checkExpiring: rdv.numAdvertiseNs2 >= 5
67+
await client.stop()
68+
69+
asyncTest "Check timeToAdvertise interval":
70+
await baseTimeToAdvertiseTest(MockRendezVous.new(newRng()))
71+
72+
asyncTest "Check timeToAdvertise interval when there is an error":
73+
await baseTimeToAdvertiseTest(MockErrorRendezVous.new(newRng()))

0 commit comments

Comments
 (0)