mirror of https://github.com/vacp2p/nim-libp2p.git
Connect is able to force a new connection (#849)
This commit is contained in:
parent
ca19f8fdbf
commit
4ace70d53b
|
@ -27,7 +27,8 @@ method connect*(
|
||||||
self: Dial,
|
self: Dial,
|
||||||
peerId: PeerId,
|
peerId: PeerId,
|
||||||
addrs: seq[MultiAddress],
|
addrs: seq[MultiAddress],
|
||||||
forceDial = false) {.async, base.} =
|
forceDial = false,
|
||||||
|
reuseConnection = true) {.async, base.} =
|
||||||
## connect remote peer without negotiating
|
## connect remote peer without negotiating
|
||||||
## a protocol
|
## a protocol
|
||||||
##
|
##
|
||||||
|
|
|
@ -147,25 +147,11 @@ proc dialAndUpgrade(
|
||||||
if not isNil(result):
|
if not isNil(result):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
proc internalConnect(
|
proc tryReusingConnection(self: Dialer, peerId: PeerId): Future[Opt[Connection]] {.async.} =
|
||||||
self: Dialer,
|
var conn = self.connManager.selectConn(peerId)
|
||||||
peerId: Opt[PeerId],
|
if conn == nil:
|
||||||
addrs: seq[MultiAddress],
|
return Opt.none(Connection)
|
||||||
forceDial: bool):
|
|
||||||
Future[Connection] {.async.} =
|
|
||||||
if Opt.some(self.localPeerId) == peerId:
|
|
||||||
raise newException(CatchableError, "can't dial self!")
|
|
||||||
|
|
||||||
# Ensure there's only one in-flight attempt per peer
|
|
||||||
let lock = self.dialLock.mgetOrPut(peerId.get(default(PeerId)), newAsyncLock())
|
|
||||||
try:
|
|
||||||
await lock.acquire()
|
|
||||||
|
|
||||||
# Check if we have a connection already and try to reuse it
|
|
||||||
var conn =
|
|
||||||
if peerId.isSome: self.connManager.selectConn(peerId.get())
|
|
||||||
else: nil
|
|
||||||
if conn != nil:
|
|
||||||
if conn.atEof or conn.closed:
|
if conn.atEof or conn.closed:
|
||||||
# This connection should already have been removed from the connection
|
# This connection should already have been removed from the connection
|
||||||
# manager - it's essentially a bug that we end up here - we'll fail
|
# manager - it's essentially a bug that we end up here - we'll fail
|
||||||
|
@ -175,10 +161,30 @@ proc internalConnect(
|
||||||
raise newException(DialFailedError, "Zombie connection encountered")
|
raise newException(DialFailedError, "Zombie connection encountered")
|
||||||
|
|
||||||
trace "Reusing existing connection", conn, direction = $conn.dir
|
trace "Reusing existing connection", conn, direction = $conn.dir
|
||||||
return conn
|
return Opt.some(conn)
|
||||||
|
|
||||||
|
proc internalConnect(
|
||||||
|
self: Dialer,
|
||||||
|
peerId: Opt[PeerId],
|
||||||
|
addrs: seq[MultiAddress],
|
||||||
|
forceDial: bool,
|
||||||
|
reuseConnection = true):
|
||||||
|
Future[Connection] {.async.} =
|
||||||
|
if Opt.some(self.localPeerId) == peerId:
|
||||||
|
raise newException(CatchableError, "can't dial self!")
|
||||||
|
|
||||||
|
# Ensure there's only one in-flight attempt per peer
|
||||||
|
let lock = self.dialLock.mgetOrPut(peerId.get(default(PeerId)), newAsyncLock())
|
||||||
|
try:
|
||||||
|
await lock.acquire()
|
||||||
|
|
||||||
|
if peerId.isSome and reuseConnection:
|
||||||
|
let connOpt = await self.tryReusingConnection(peerId.get())
|
||||||
|
if connOpt.isSome:
|
||||||
|
return connOpt.get()
|
||||||
|
|
||||||
let slot = self.connManager.getOutgoingSlot(forceDial)
|
let slot = self.connManager.getOutgoingSlot(forceDial)
|
||||||
conn =
|
let conn =
|
||||||
try:
|
try:
|
||||||
await self.dialAndUpgrade(peerId, addrs)
|
await self.dialAndUpgrade(peerId, addrs)
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
|
@ -207,15 +213,16 @@ method connect*(
|
||||||
self: Dialer,
|
self: Dialer,
|
||||||
peerId: PeerId,
|
peerId: PeerId,
|
||||||
addrs: seq[MultiAddress],
|
addrs: seq[MultiAddress],
|
||||||
forceDial = false) {.async.} =
|
forceDial = false,
|
||||||
|
reuseConnection = true) {.async.} =
|
||||||
## connect remote peer without negotiating
|
## connect remote peer without negotiating
|
||||||
## a protocol
|
## a protocol
|
||||||
##
|
##
|
||||||
|
|
||||||
if self.connManager.connCount(peerId) > 0:
|
if self.connManager.connCount(peerId) > 0 and reuseConnection:
|
||||||
return
|
return
|
||||||
|
|
||||||
discard await self.internalConnect(Opt.some(peerId), addrs, forceDial)
|
discard await self.internalConnect(Opt.some(peerId), addrs, forceDial, reuseConnection)
|
||||||
|
|
||||||
method connect*(
|
method connect*(
|
||||||
self: Dialer,
|
self: Dialer,
|
||||||
|
|
|
@ -148,10 +148,11 @@ method connect*(
|
||||||
s: Switch,
|
s: Switch,
|
||||||
peerId: PeerId,
|
peerId: PeerId,
|
||||||
addrs: seq[MultiAddress],
|
addrs: seq[MultiAddress],
|
||||||
forceDial = false): Future[void] {.public.} =
|
forceDial = false,
|
||||||
|
reuseConnection = true): Future[void] {.public.} =
|
||||||
## Connects to a peer without opening a stream to it
|
## Connects to a peer without opening a stream to it
|
||||||
|
|
||||||
s.dialer.connect(peerId, addrs, forceDial)
|
s.dialer.connect(peerId, addrs, forceDial, reuseConnection)
|
||||||
|
|
||||||
method connect*(
|
method connect*(
|
||||||
s: Switch,
|
s: Switch,
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Nim-LibP2P
|
||||||
|
# Copyright (c) 2023 Status Research & Development GmbH
|
||||||
|
# Licensed under either of
|
||||||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||||
|
# at your option.
|
||||||
|
# This file may not be copied, modified, or distributed except according to
|
||||||
|
# those terms.
|
||||||
|
|
||||||
|
import std/options
|
||||||
|
import chronos
|
||||||
|
import unittest2
|
||||||
|
import ../libp2p/[builders,
|
||||||
|
switch]
|
||||||
|
import ./helpers
|
||||||
|
|
||||||
|
suite "Dialer":
|
||||||
|
teardown:
|
||||||
|
checkTrackers()
|
||||||
|
|
||||||
|
asyncTest "Connect forces a new connection":
|
||||||
|
|
||||||
|
let
|
||||||
|
src = newStandardSwitch()
|
||||||
|
dst = newStandardSwitch()
|
||||||
|
|
||||||
|
await dst.start()
|
||||||
|
|
||||||
|
await src.connect(dst.peerInfo.peerId, dst.peerInfo.addrs)
|
||||||
|
check src.connManager.connCount(dst.peerInfo.peerId) == 1
|
||||||
|
|
||||||
|
await src.connect(dst.peerInfo.peerId, dst.peerInfo.addrs)
|
||||||
|
check src.connManager.connCount(dst.peerInfo.peerId) == 1
|
||||||
|
|
||||||
|
await src.connect(dst.peerInfo.peerId, dst.peerInfo.addrs, true, false)
|
||||||
|
check src.connManager.connCount(dst.peerInfo.peerId) == 2
|
||||||
|
|
||||||
|
await allFutures(src.stop(), dst.stop())
|
Loading…
Reference in New Issue