2022-07-01 18:19:57 +00:00
|
|
|
# Nim-LibP2P
|
2024-03-05 07:06:27 +00:00
|
|
|
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
2022-07-01 18:19:57 +00:00
|
|
|
# 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.
|
2021-01-20 17:28:32 +00:00
|
|
|
|
2023-06-07 11:12:49 +00:00
|
|
|
{.push raises: [].}
|
2021-05-21 16:27:01 +00:00
|
|
|
|
2023-05-18 08:24:17 +00:00
|
|
|
import std/sequtils
|
2021-01-20 17:28:32 +00:00
|
|
|
import pkg/[chronos, chronicles, metrics]
|
|
|
|
|
|
|
|
import ../upgrademngrs/upgrade,
|
|
|
|
../muxers/muxer
|
|
|
|
|
|
|
|
export Upgrade
|
|
|
|
|
2021-05-21 16:27:01 +00:00
|
|
|
logScope:
|
|
|
|
topics = "libp2p muxedupgrade"
|
|
|
|
|
2021-01-20 17:28:32 +00:00
|
|
|
type
|
|
|
|
MuxedUpgrade* = ref object of Upgrade
|
2022-07-22 10:54:09 +00:00
|
|
|
muxers*: seq[MuxerProvider]
|
2021-01-20 17:28:32 +00:00
|
|
|
streamHandler*: StreamHandler
|
|
|
|
|
2024-03-21 07:19:57 +00:00
|
|
|
func getMuxerByCodec(
|
|
|
|
self: MuxedUpgrade, muxerName: string): Opt[MuxerProvider] =
|
|
|
|
if muxerName.len == 0 or muxerName == "na":
|
|
|
|
return Opt.none(MuxerProvider)
|
2022-07-22 10:54:09 +00:00
|
|
|
for m in self.muxers:
|
2023-03-08 11:30:19 +00:00
|
|
|
if muxerName == m.codec:
|
2024-03-21 07:19:57 +00:00
|
|
|
return Opt.some(m)
|
|
|
|
Opt.none(MuxerProvider)
|
2022-07-22 10:54:09 +00:00
|
|
|
|
2024-03-21 07:19:57 +00:00
|
|
|
proc mux(
|
2024-03-05 07:06:27 +00:00
|
|
|
self: MuxedUpgrade,
|
2024-03-21 07:19:57 +00:00
|
|
|
conn: Connection
|
|
|
|
): Future[Opt[Muxer]] {.async: (raises: [
|
|
|
|
CancelledError, LPStreamError, MultiStreamError]).} =
|
2023-03-08 11:30:19 +00:00
|
|
|
## mux connection
|
2021-01-20 17:28:32 +00:00
|
|
|
trace "Muxing connection", conn
|
2021-03-18 15:20:36 +00:00
|
|
|
if self.muxers.len == 0:
|
2021-01-20 17:28:32 +00:00
|
|
|
warn "no muxers registered, skipping upgrade flow", conn
|
2024-03-21 07:19:57 +00:00
|
|
|
return Opt.none(Muxer)
|
|
|
|
|
|
|
|
let
|
|
|
|
muxerName =
|
|
|
|
case conn.dir
|
|
|
|
of Direction.Out:
|
|
|
|
await self.ms.select(conn, self.muxers.mapIt(it.codec))
|
|
|
|
of Direction.In:
|
|
|
|
await MultistreamSelect.handle(conn, self.muxers.mapIt(it.codec))
|
|
|
|
muxerProvider = self.getMuxerByCodec(muxerName).valueOr:
|
|
|
|
debug "no muxer available, early exit", conn, muxerName
|
|
|
|
return Opt.none(Muxer)
|
2021-01-20 17:28:32 +00:00
|
|
|
|
|
|
|
trace "Found a muxer", conn, muxerName
|
|
|
|
|
|
|
|
# create new muxer for connection
|
2024-03-21 07:19:57 +00:00
|
|
|
let muxer = muxerProvider.newMuxer(conn)
|
2021-01-20 17:28:32 +00:00
|
|
|
|
|
|
|
# install stream handler
|
2021-03-18 15:20:36 +00:00
|
|
|
muxer.streamHandler = self.streamHandler
|
2023-03-08 11:30:19 +00:00
|
|
|
muxer.handler = muxer.handle()
|
2024-03-21 07:19:57 +00:00
|
|
|
Opt.some(muxer)
|
2021-01-20 17:28:32 +00:00
|
|
|
|
2023-04-14 14:23:19 +00:00
|
|
|
method upgrade*(
|
2024-03-05 07:06:27 +00:00
|
|
|
self: MuxedUpgrade,
|
|
|
|
conn: Connection,
|
2024-03-21 07:19:57 +00:00
|
|
|
peerId: Opt[PeerId]
|
|
|
|
): Future[Muxer] {.async: (raises: [CancelledError, LPError]).} =
|
2023-11-29 16:38:47 +00:00
|
|
|
trace "Upgrading connection", conn, direction = conn.dir
|
2021-01-20 17:28:32 +00:00
|
|
|
|
2024-03-21 07:19:57 +00:00
|
|
|
let sconn = await self.secure(conn, peerId) # secure the connection
|
2024-03-05 07:06:27 +00:00
|
|
|
if sconn == nil:
|
2024-03-21 07:19:57 +00:00
|
|
|
raise (ref UpgradeFailedError)(msg:
|
2021-01-20 17:28:32 +00:00
|
|
|
"unable to secure connection, stopping upgrade")
|
|
|
|
|
2024-03-21 07:19:57 +00:00
|
|
|
let muxer = (await self.mux(sconn)).valueOr: # mux it if possible
|
|
|
|
raise (ref UpgradeFailedError)(msg:
|
2021-01-20 17:28:32 +00:00
|
|
|
"a muxer is required for outgoing connections")
|
|
|
|
|
2021-09-08 09:07:46 +00:00
|
|
|
when defined(libp2p_agents_metrics):
|
|
|
|
conn.shortAgent = muxer.connection.shortAgent
|
|
|
|
|
|
|
|
if sconn.closed():
|
2021-01-20 17:28:32 +00:00
|
|
|
await sconn.close()
|
2024-03-21 07:19:57 +00:00
|
|
|
raise (ref UpgradeFailedError)(msg:
|
2021-01-20 17:28:32 +00:00
|
|
|
"Connection closed or missing peer info, stopping upgrade")
|
|
|
|
|
2023-11-29 16:38:47 +00:00
|
|
|
trace "Upgraded connection", conn, sconn, direction = conn.dir
|
2024-03-21 07:19:57 +00:00
|
|
|
muxer
|
2021-01-20 17:28:32 +00:00
|
|
|
|
2021-10-25 08:26:32 +00:00
|
|
|
proc new*(
|
2024-03-05 07:06:27 +00:00
|
|
|
T: type MuxedUpgrade,
|
|
|
|
muxers: seq[MuxerProvider],
|
|
|
|
secureManagers: openArray[Secure] = [],
|
|
|
|
ms: MultistreamSelect): T =
|
2021-01-20 17:28:32 +00:00
|
|
|
let upgrader = T(
|
|
|
|
muxers: muxers,
|
|
|
|
secureManagers: @secureManagers,
|
|
|
|
ms: ms)
|
|
|
|
|
2024-03-05 07:06:27 +00:00
|
|
|
upgrader.streamHandler = proc(conn: Connection) {.async: (raises: []).} =
|
2021-05-25 17:05:50 +00:00
|
|
|
trace "Starting stream handler", conn
|
|
|
|
try:
|
|
|
|
await upgrader.ms.handle(conn) # handle incoming connection
|
|
|
|
except CancelledError as exc:
|
2024-03-05 07:06:27 +00:00
|
|
|
return
|
2021-05-25 17:05:50 +00:00
|
|
|
finally:
|
|
|
|
await conn.closeWithEOF()
|
|
|
|
trace "Stream handler done", conn
|
2021-01-20 17:28:32 +00:00
|
|
|
|
|
|
|
return upgrader
|