Integrate dns resolving (#615)

* integrate dns

* give hostname to transport dial

* add hostname test

* switched to websock master

* Add dnsaddr dial test w multiple transports
This commit is contained in:
Tanguy 2021-11-08 13:02:03 +01:00 committed by GitHub
parent e787fc35a6
commit c92125a1a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 228 additions and 140 deletions

View File

@ -16,7 +16,7 @@ requires "nim >= 1.2.0",
"metrics", "metrics",
"secp256k1", "secp256k1",
"stew#head", "stew#head",
"https://github.com/status-im/nim-websock" "websock"
proc runTest(filename: string, verify: bool = true, sign: bool = true, proc runTest(filename: string, verify: bool = true, sign: bool = true,
moreoptions: string = "") = moreoptions: string = "") =

View File

@ -20,6 +20,7 @@ import dial,
connmanager, connmanager,
stream/connection, stream/connection,
transports/transport, transports/transport,
nameresolving/nameresolver,
errors errors
export dial, errors export dial, errors
@ -41,6 +42,7 @@ type
connManager: ConnManager connManager: ConnManager
dialLock: Table[PeerID, AsyncLock] dialLock: Table[PeerID, AsyncLock]
transports: seq[Transport] transports: seq[Transport]
nameResolver: NameResolver
proc dialAndUpgrade( proc dialAndUpgrade(
self: Dialer, self: Dialer,
@ -49,58 +51,63 @@ proc dialAndUpgrade(
Future[Connection] {.async.} = Future[Connection] {.async.} =
debug "Dialing peer", peerId debug "Dialing peer", peerId
# Avoid "cannot be captured as it would violate memory safety" errors in Nim-1.4.x. for address in addrs: # for each address
var let
transport: Transport hostname = address.getHostname()
address: MultiAddress resolvedAddresses =
if isNil(self.nameResolver): @[address]
else: await self.nameResolver.resolveMAddress(address)
for t in self.transports: # for each transport for a in resolvedAddresses: # for each resolved address
transport = t for transport in self.transports: # for each transport
for a in addrs: # for each address if transport.handles(a): # check if it can dial it
address = a trace "Dialing address", address = $a, peerId, hostname
if t.handles(a): # check if it can dial it let dialed = try:
trace "Dialing address", address = $a, peerId libp2p_total_dial_attempts.inc()
let dialed = try: # await a connection slot when the total
libp2p_total_dial_attempts.inc() # connection count is equal to `maxConns`
# await a connection slot when the total #
# connection count is equal to `maxConns` # Need to copy to avoid "cannot be captured" errors in Nim-1.4.x.
await self.connManager.trackOutgoingConn( let
() => transport.dial(address) transportCopy = transport
) addressCopy = a
except TooManyConnectionsError as exc: await self.connManager.trackOutgoingConn(
trace "Connection limit reached!" () => transportCopy.dial(hostname, addressCopy)
raise exc )
except CancelledError as exc: except TooManyConnectionsError as exc:
debug "Dialing canceled", msg = exc.msg, peerId trace "Connection limit reached!"
raise exc raise exc
except CatchableError as exc: except CancelledError as exc:
debug "Dialing failed", msg = exc.msg, peerId debug "Dialing canceled", msg = exc.msg, peerId
libp2p_failed_dials.inc() raise exc
continue # Try the next address except CatchableError as exc:
debug "Dialing failed", msg = exc.msg, peerId
libp2p_failed_dials.inc()
continue # Try the next address
# make sure to assign the peer to the connection # make sure to assign the peer to the connection
dialed.peerId = peerId dialed.peerId = peerId
# also keep track of the connection's bottom unsafe transport direction # also keep track of the connection's bottom unsafe transport direction
# required by gossipsub scoring # required by gossipsub scoring
dialed.transportDir = Direction.Out dialed.transportDir = Direction.Out
libp2p_successful_dials.inc() libp2p_successful_dials.inc()
let conn = try: let conn = try:
await transport.upgradeOutgoing(dialed) await transport.upgradeOutgoing(dialed)
except CatchableError as exc: except CatchableError as exc:
# If we failed to establish the connection through one transport, # If we failed to establish the connection through one transport,
# we won't succeeded through another - no use in trying again # we won't succeeded through another - no use in trying again
await dialed.close() await dialed.close()
debug "Upgrade failed", msg = exc.msg, peerId debug "Upgrade failed", msg = exc.msg, peerId
if exc isnot CancelledError: if exc isnot CancelledError:
libp2p_failed_upgrades_outgoing.inc() libp2p_failed_upgrades_outgoing.inc()
raise exc raise exc
doAssert not isNil(conn), "connection died after upgradeOutgoing" doAssert not isNil(conn), "connection died after upgradeOutgoing"
debug "Dial successful", conn, peerId = conn.peerId debug "Dial successful", conn, peerId = conn.peerId
return conn return conn
proc internalConnect( proc internalConnect(
self: Dialer, self: Dialer,
@ -234,9 +241,11 @@ proc new*(
localPeerId: PeerId, localPeerId: PeerId,
connManager: ConnManager, connManager: ConnManager,
transports: seq[Transport], transports: seq[Transport],
ms: MultistreamSelect): Dialer = ms: MultistreamSelect,
nameResolver: NameResolver = nil): Dialer =
T(localPeerId: localPeerId, T(localPeerId: localPeerId,
connManager: connManager, connManager: connManager,
transports: transports, transports: transports,
ms: ms) ms: ms,
nameResolver: nameResolver)

View File

@ -40,12 +40,10 @@ method resolveIp*(
doAssert(false, "Not implemented!") doAssert(false, "Not implemented!")
proc getHostname(ma: MultiAddress): string = proc getHostname*(ma: MultiAddress): string =
var dnsbuf = newSeq[byte](256) let firstPart = ($ma[0].get()).split('/')
if firstPart.len > 1: firstPart[2]
let dnsLen = ma[0].get().protoArgument(dnsbuf).get() else: ""
dnsbuf.setLen(dnsLen)
return string.fromBytes(dnsbuf)
proc resolveDnsAddress( proc resolveDnsAddress(
self: NameResolver, self: NameResolver,
@ -122,27 +120,26 @@ proc resolveDnsAddr(
return result return result
proc resolveMAddresses*( proc resolveMAddress*(
self: NameResolver, self: NameResolver,
addrs: seq[MultiAddress]): Future[seq[MultiAddress]] {.async.} = address: MultiAddress): Future[seq[MultiAddress]] {.async.} =
var res = initOrderedSet[MultiAddress]() var res = initOrderedSet[MultiAddress]()
for address in addrs: if not DNS.matchPartial(address):
if not DNS.matchPartial(address): res.incl(address)
res.incl(address) else:
else: let code = address[0].get().protoCode().get()
let code = address[0].get().protoCode().get() let seq = case code:
let seq = case code: of multiCodec("dns"):
of multiCodec("dns"): await self.resolveDnsAddress(address)
await self.resolveDnsAddress(address) of multiCodec("dns4"):
of multiCodec("dns4"): await self.resolveDnsAddress(address, Domain.AF_INET)
await self.resolveDnsAddress(address, Domain.AF_INET) of multiCodec("dns6"):
of multiCodec("dns6"): await self.resolveDnsAddress(address, Domain.AF_INET6)
await self.resolveDnsAddress(address, Domain.AF_INET6) of multiCodec("dnsaddr"):
of multiCodec("dnsaddr"): await self.resolveDnsAddr(address)
await self.resolveDnsAddr(address) else:
else: @[address]
@[address] for ad in seq:
for ad in seq: res.incl(ad)
res.incl(ad)
return res.toSeq return res.toSeq

View File

@ -273,7 +273,7 @@ proc newSwitch*(peerInfo: PeerInfo,
transports: transports, transports: transports,
connManager: connManager, connManager: connManager,
peerStore: PeerStore.new(), peerStore: PeerStore.new(),
dialer: Dialer.new(peerInfo.peerId, connManager, transports, ms), dialer: Dialer.new(peerInfo.peerId, connManager, transports, ms, nameResolver),
nameResolver: nameResolver) nameResolver: nameResolver)
switch.connManager.peerStore = switch.peerStore switch.connManager.peerStore = switch.peerStore

View File

@ -199,6 +199,7 @@ method accept*(self: TcpTransport): Future[Connection] {.async, gcsafe.} =
method dial*( method dial*(
self: TcpTransport, self: TcpTransport,
hostname: string,
address: MultiAddress): Future[Connection] {.async, gcsafe.} = address: MultiAddress): Future[Connection] {.async, gcsafe.} =
## dial a peer ## dial a peer
## ##

View File

@ -60,12 +60,18 @@ method accept*(self: Transport): Future[Connection]
method dial*( method dial*(
self: Transport, self: Transport,
hostname: string,
address: MultiAddress): Future[Connection] {.base, gcsafe.} = address: MultiAddress): Future[Connection] {.base, gcsafe.} =
## dial a peer ## dial a peer
## ##
doAssert(false, "Not implemented!") doAssert(false, "Not implemented!")
proc dial*(
self: Transport,
address: MultiAddress): Future[Connection] {.gcsafe.} =
self.dial("", address)
method upgradeIncoming*( method upgradeIncoming*(
self: Transport, self: Transport,
conn: Connection): Future[void] {.base, gcsafe.} = conn: Connection): Future[void] {.base, gcsafe.} =

View File

@ -207,6 +207,7 @@ method accept*(self: WsTransport): Future[Connection] {.async, gcsafe.} =
method dial*( method dial*(
self: WsTransport, self: WsTransport,
hostname: string,
address: MultiAddress): Future[Connection] {.async, gcsafe.} = address: MultiAddress): Future[Connection] {.async, gcsafe.} =
## dial a peer ## dial a peer
## ##
@ -219,6 +220,7 @@ method dial*(
address.initTAddress().tryGet(), address.initTAddress().tryGet(),
"", "",
secure = secure, secure = secure,
hostName = hostname,
flags = self.tlsFlags) flags = self.tlsFlags)
return await self.connHandler(transp, Direction.Out) return await self.connHandler(transp, Direction.Out)

View File

@ -59,7 +59,7 @@ suite "Name resolving":
var resolver {.threadvar.}: MockResolver var resolver {.threadvar.}: MockResolver
proc testOne(input: string, output: seq[Multiaddress]): bool = proc testOne(input: string, output: seq[Multiaddress]): bool =
let resolved = waitFor resolver.resolveMAddresses(@[Multiaddress.init(input).tryGet()]) let resolved = waitFor resolver.resolveMAddress(Multiaddress.init(input).tryGet())
if resolved != output: if resolved != output:
echo "Expected ", output echo "Expected ", output
echo "Got ", resolved echo "Got ", resolved
@ -90,18 +90,6 @@ suite "Name resolving":
check testOne("/ip6/::1/tcp/0", "/ip6/::1/tcp/0") check testOne("/ip6/::1/tcp/0", "/ip6/::1/tcp/0")
asyncTest "test multiple resolve":
resolver.ipResponses[("localhost", false)] = @["127.0.0.1"]
resolver.ipResponses[("localhost", true)] = @["::1"]
let resolved = waitFor resolver.resolveMAddresses(@[
Multiaddress.init("/dns/localhost/udp/0").tryGet(),
Multiaddress.init("/dns4/localhost/udp/0").tryGet(),
Multiaddress.init("/dns6/localhost/udp/0").tryGet(),
])
check resolved == @[Multiaddress.init("/ip4/127.0.0.1/udp/0").tryGet(), Multiaddress.init("/ip6/::1/udp/0").tryGet()]
asyncTest "dnsaddr recursive test": asyncTest "dnsaddr recursive test":
resolver.txtResponses["_dnsaddr.bootstrap.libp2p.io"] = @[ resolver.txtResponses["_dnsaddr.bootstrap.libp2p.io"] = @[
"dnsaddr=/dnsaddr/sjc-1.bootstrap.libp2p.io/tcp/4001/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", "dnsaddr=/dnsaddr/sjc-1.bootstrap.libp2p.io/tcp/4001/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",

View File

@ -21,7 +21,8 @@ import ../libp2p/[errors,
nameresolving/nameresolver, nameresolving/nameresolver,
nameresolving/mockresolver, nameresolving/mockresolver,
stream/chronosstream, stream/chronosstream,
transports/tcptransport] transports/tcptransport,
transports/wstransport]
import ./helpers import ./helpers
const const
@ -463,7 +464,7 @@ suite "Switch":
let switch1 = newStandardSwitch() let switch1 = newStandardSwitch()
let rng = newRng() let rng = crypto.newRng()
# use same private keys to emulate two connection from same peer # use same private keys to emulate two connection from same peer
let privKey = PrivateKey.random(rng[]).tryGet() let privKey = PrivateKey.random(rng[]).tryGet()
let switch2 = newStandardSwitch( let switch2 = newStandardSwitch(
@ -530,7 +531,7 @@ suite "Switch":
asyncTest "e2e should allow dropping peer from connection events": asyncTest "e2e should allow dropping peer from connection events":
var awaiters: seq[Future[void]] var awaiters: seq[Future[void]]
let rng = newRng() let rng = crypto.newRng()
# use same private keys to emulate two connection from same peer # use same private keys to emulate two connection from same peer
let let
privateKey = PrivateKey.random(rng[]).tryGet() privateKey = PrivateKey.random(rng[]).tryGet()
@ -573,7 +574,7 @@ suite "Switch":
asyncTest "e2e should allow dropping multiple connections for peer from connection events": asyncTest "e2e should allow dropping multiple connections for peer from connection events":
var awaiters: seq[Future[void]] var awaiters: seq[Future[void]]
let rng = newRng() let rng = crypto.newRng()
# use same private keys to emulate two connection from same peer # use same private keys to emulate two connection from same peer
let let
privateKey = PrivateKey.random(rng[]).tryGet() privateKey = PrivateKey.random(rng[]).tryGet()
@ -901,5 +902,79 @@ suite "Switch":
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet() switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet()
switch2.peerStore.addressBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.addrs.toHashSet() switch2.peerStore.addressBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.addrs.toHashSet()
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet() switch1.peerStore.protoBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.protocols.toHashSet()
switch2.peerStore.addressBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.addrs.toHashSet() switch2.peerStore.protoBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.protocols.toHashSet()
asyncTest "e2e dial dns4 address":
var awaiters: seq[Future[void]]
let resolver = MockResolver.new()
resolver.ipResponses[("localhost", false)] = @["127.0.0.1"]
resolver.ipResponses[("localhost", true)] = @["::1"]
let
srcSwitch = newStandardSwitch(nameResolver = resolver)
destSwitch = newStandardSwitch()
awaiters.add(await destSwitch.start())
awaiters.add(await srcSwitch.start())
await allFuturesThrowing(awaiters)
let testAddr = MultiAddress.init("/dns4/localhost/").tryGet() &
destSwitch.peerInfo.addrs[0][1].tryGet()
await srcSwitch.connect(destSwitch.peerInfo.peerId, @[testAddr])
check srcSwitch.isConnected(destSwitch.peerInfo.peerId)
await destSwitch.stop()
await srcSwitch.stop()
asyncTest "e2e dial dnsaddr with multiple transports":
var awaiters: seq[Future[void]]
let resolver = MockResolver.new()
let
wsAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0/ws").tryGet()
tcpAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet()
srcTcpSwitch = newStandardSwitch(nameResolver = resolver)
srcWsSwitch =
SwitchBuilder.new()
.withAddress(wsAddress)
.withRng(crypto.newRng())
.withMplex()
.withTransport(proc (upgr: Upgrade): Transport = WsTransport.new(upgr))
.withNameResolver(resolver)
.withNoise()
.build()
destSwitch =
SwitchBuilder.new()
.withAddresses(@[tcpAddress, wsAddress])
.withRng(crypto.newRng())
.withMplex()
.withTransport(proc (upgr: Upgrade): Transport = WsTransport.new(upgr))
.withTcpTransport()
.withNoise()
.build()
awaiters.add(await destSwitch.start())
awaiters.add(await srcTcpSwitch.start())
awaiters.add(await srcWsSwitch.start())
await allFuturesThrowing(awaiters)
resolver.txtResponses["_dnsaddr.test.io"] = @[
"dnsaddr=/ip4/127.0.0.1" & $destSwitch.peerInfo.addrs[1][1].tryGet() & "/ws",
"dnsaddr=/ip4/127.0.0.1" & $destSwitch.peerInfo.addrs[0][1].tryGet()
]
let testAddr = MultiAddress.init("/dnsaddr/test.io/").tryGet()
await srcTcpSwitch.connect(destSwitch.peerInfo.peerId, @[testAddr])
check srcTcpSwitch.isConnected(destSwitch.peerInfo.peerId)
await srcWsSwitch.connect(destSwitch.peerInfo.peerId, @[testAddr])
check srcWsSwitch.isConnected(destSwitch.peerInfo.peerId)
await destSwitch.stop()
await srcWsSwitch.stop()
await srcTcpSwitch.stop()

View File

@ -15,56 +15,39 @@ import ./helpers, ./commontransport
const const
SecureKey* = """ SecureKey* = """
-----BEGIN PRIVATE KEY----- -----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdNv0SX02aeZ4/ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAP0yH7F7FtGunC91
Yc+p/Kwd5UVOHlpmK7/TVC/kcjFbdoUuKNn8pnX/fyhgSKpUYut+te7YRiZhqlaL IPkU+u8B4gdxiwYW0J3PrixtB1Xz3e4dfjwQqhIJlG6BxQ4myCxmSPjxP/eOOYp+
EZKjfy8GBZwXZnJCevFkTvGTTebXXExLIsLGfJqKeLAdFCQkX8wV3jV1DT5JLV+D 8/+A9nikbnc7H3OV8fNJhsSmPu8j8W2FsNVJzJnUQaE2yimrFR8NnvQ4MKvMBSgb
5+HWaiiBr38gsl4ZbfyedTF40JvzokCmcdlx9bpzX1j/b84L/zSwUyyEcgp5G28F lHTLbP1aAFp+K6KPPE7pkRMUdlqFAgMBAAECgYBl0eli4yALFI/kmdK3uBMtWHGA
Jh5TnxAeDHJpOVjr8XMb/xoNqiDF6NwF96hvOZC14mZ1TxxW5bUzXprsy0l52pmh Es4YlcYxIFpnrTS9AQPnhN7F4uGxvT5+rhsDlN780+lWixXxRLWpF2KiBkeW8ayT
dN3Crz11+t2h519hRKHxT6/l5pTx/+dApXiP6hMV04CQJNnas3NyRxTDR9dNel+3 kPeWvpSy6z+4LXw633ZLfCO1r6brpqSXNWxA0q7IgzYQEfMpnkaQrE3PVP5xkmTT
+wD7/PRTAgMBAAECggEBAJuXPEbegxMKog7gYoE9S6oaqchySc0sJyCjBPL2ANsg k159ev138J23VfNgRQJBAP768qHOCnplKIe69SVUWlsQ5nnnybDBMq2YVATbombz
JRZV38cnh0hhNDh2MfxqGd7Bd6wbYQjvZ88iiRm+WW+ARcby4MnimtxHNNYwFvG0 KD57iufzBgND1clIEEuC6PK2C5gzTk4HZQioJ/juOFcCQQD+NVlb1HLoK7rHXZFO
qt0BffqqftfkMYfV0x8coAJUdFtvy+DoQstsxhlJ3uTaJtrZLD/GlmjMWzXSX0Vy Tg3O+bwRZdo67J4pt//ijF7tLlZU/q6Kp9wHrXe1yhRV+Tow0BzBVHkc5eUM0/n7
FXiLDO7/LoSjsjaf4e4aLofIyLJS3H1T+5cr/d2mdpRzkeWkxShODsK4cRLOlZ5I cOqDAkAedrECb/GEig17mfSsDxX0h2Jh8jWArrR1VRvEsNEIZ8jJHk2MRNbVEQe7
pz4Wm2770DTbiYph8ixl/CnmYn6T7V0F5VYujALknipUBeQY4e/A9vrQ/pvqJV+W 0qZPv0ZBqUpdVtPmMq/5hs2vyhZlAkEA1cZ1fCUf8KD9tLS6AnjfYeRgRN07dXwQ
JjFUne6Rxg/lJjh8vNJp2bK1ZbzpwmZLaZIoEz8t/qECgYEAzvCCA48uQPaurSQ3 0hKbTKAxIBJspZN7orzg60/0sNrc2SP6zJvm4qowI54tTelhexMNEwJBAOZz72xn
cvHDhcVwYmEaH8MW8aIW/5l8XJK60GsUHPFhEsfD/ObI5PJJ9aOqgabpRHkvD4ZY EFUXKYQBbetiejnBBzFYmdA/QKmZ7kbQfDBOwG9wDPFmvnNSvSZws/bP1zcM95rq
a8QJBxCy6UeogUeKvGks8VQ34SZXLimmgrL9Mlljv0v9PloEkVYbztYyX4GVO0ov NABr5ec1FxuJa/8=
3oH+hKO+/MclzNDyeXZx3Vv4K+UCgYEAwnyb7tqp7fRqm/8EymIZV5pa0p6h609p
EhCBi9ii6d/ewEjsBhs7bPDBO4PO9ylvOvryYZH1hVbQja2anOCBjO8dAHRHWM86
964TFriywBQkYxp6dsB8nUjLBDza2xAM3m+OGi9/ATuhEAe5sXp/fZL3tkfSaOXI
A7Gzro+kS9cCgYEAtKScSfEeBlWQa9H2mV9UN5z/mtF61YkeqTW+b8cTGVh4vWEL
wKww+gzqGAV6Duk2CLijKeSDMmO64gl7fC83VjSMiTklbhz+jbQeKFhFI0Sty71N
/j+y6NXBTgdOfLRl0lzhj2/JrzdWBtie6tR9UloCaXSKmb04PTFY+kvDWsUCgYBR
krJUnKJpi/qrM2tu93Zpp/QwIxkG+We4i/PKFDNApQVo4S0d4o4qQ1DJBZ/pSxe8
RUUkZ3PzWVZgFlCjPAcadbBUYHEMbt7sw7Z98ToIFmqspo53AIVD8yQzwtKIz1KW
eXPAx+sdOUV008ivCBIxOVNswPMfzED4S7Bxpw3iQQKBgGJhct2nBsgu0l2/wzh9
tpKbalW1RllgptNQzjuBEZMTvPF0L+7BE09/exKtt4N9s3yAzi8o6Qo7RHX5djVc
SNgafV4jj7jt2Ilh6KOy9dshtLoEkS1NmiqfVe2go2auXZdyGm+I2yzKWdKGDO0J
diTtYf1sA0PgNXdSyDC03TZl
-----END PRIVATE KEY----- -----END PRIVATE KEY-----
""" """
SecureCert* = """ SecureCert* = """
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUe9fr78Dz9PedQ5Sq0uluMWQhX9wwDQYJKoZIhvcNAQEL MIICjDCCAfWgAwIBAgIURjeiJmkNbBVktqXvnXh44DKx364wDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCSU4xEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM BQAwVzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTAzMTcwOTMzMzZaFw0zMTAz GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UEAwwHd3MudGVzdDAgFw0y
MTUwOTMzMzZaMEUxCzAJBgNVBAYTAklOMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw MTA5MTQxMTU2NTZaGA8yMDgyMDgzMDExNTY1NlowVzELMAkGA1UEBhMCQVUxEzAR
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
AQUAA4IBDwAwggEKAoIBAQCdNv0SX02aeZ4/Yc+p/Kwd5UVOHlpmK7/TVC/kcjFb IEx0ZDEQMA4GA1UEAwwHd3MudGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
doUuKNn8pnX/fyhgSKpUYut+te7YRiZhqlaLEZKjfy8GBZwXZnJCevFkTvGTTebX gYEA/TIfsXsW0a6cL3Ug+RT67wHiB3GLBhbQnc+uLG0HVfPd7h1+PBCqEgmUboHF
XExLIsLGfJqKeLAdFCQkX8wV3jV1DT5JLV+D5+HWaiiBr38gsl4ZbfyedTF40Jvz DibILGZI+PE/9445in7z/4D2eKRudzsfc5Xx80mGxKY+7yPxbYWw1UnMmdRBoTbK
okCmcdlx9bpzX1j/b84L/zSwUyyEcgp5G28FJh5TnxAeDHJpOVjr8XMb/xoNqiDF KasVHw2e9Dgwq8wFKBuUdMts/VoAWn4roo88TumRExR2WoUCAwEAAaNTMFEwHQYD
6NwF96hvOZC14mZ1TxxW5bUzXprsy0l52pmhdN3Crz11+t2h519hRKHxT6/l5pTx VR0OBBYEFHaV2ief8/Que1wxcZ8ACfdW7NUNMB8GA1UdIwQYMBaAFHaV2ief8/Qu
/+dApXiP6hMV04CQJNnas3NyRxTDR9dNel+3+wD7/PRTAgMBAAGjUzBRMB0GA1Ud e1wxcZ8ACfdW7NUNMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEA
DgQWBBRkSY1AkGUpVNxG5fYocfgFODtQmTAfBgNVHSMEGDAWgBRkSY1AkGUpVNxG XvDtaDLShrjS9huhRVoEdUtoBdhonmFpV3HXqRs7NdTuUWooXiph9a66GVSIfUCR
5fYocfgFODtQmTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBt iEaNOKF6OM0n7GLSDIrBeIWAxL9Ra/dFFwCxl+9wxg8yyzEJDBkAhXkrfp2b4Sx6
D71VH7F8GOQXITFXCrHwEq1Fx3ScuSnL04NJrXw/e9huzLVQOchAYp/EIn4x2utN wdK6xU2VOAxI0GUzwzjcyNl7RDFA3ayFaGl+9+oppWM=
S31dt94wvi/IysOVbR1LatYNF5kKgGj2Wc6DH0PswBMk8R1G8QMeCz+hCjf1VDHe
AAW1x2q20rJAvUrT6cRBQqeiMzQj0OaJbvfnd2hu0/d0DFkcuGVgBa2zlbG5rbdU
Jnq7MQfSaZHd0uBgiKkS+Zw6XaYfWfByCAGSnUqRdOChiJ2stFVLvu+9oQ+PJjJt
Er1u9bKTUyeuYpqXr2BP9dqphwu8R4NFVUg6DIRpMFMsybaL7KAd4hD22RXCvc0m
uLu7KODi+eW62MHqs4N2
-----END CERTIFICATE----- -----END CERTIFICATE-----
""" """
@ -86,3 +69,30 @@ suite "WebSocket transport":
TLSCertificate.init(SecureCert), TLSCertificate.init(SecureCert),
{TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName}), {TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName}),
"/ip4/0.0.0.0/tcp/0/wss") "/ip4/0.0.0.0/tcp/0/wss")
asyncTest "Hostname verification":
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0/wss").tryGet()
let transport1 = WsTransport.new(Upgrade(), TLSPrivateKey.init(SecureKey), TLSCertificate.init(SecureCert), {TLSFlags.NoVerifyHost})
await transport1.start(ma)
proc acceptHandler() {.async, gcsafe.} =
while true:
let conn = await transport1.accept()
if not isNil(conn):
await conn.close()
let handlerWait = acceptHandler()
# ws.test is in certificate
let conn = await transport1.dial("ws.test", transport1.ma)
await conn.close()
try:
let conn = await transport1.dial("ws.wronghostname", transport1.ma)
check false
except CatchableError as exc:
check true
await handlerWait.cancelAndWait()
await transport1.stop()