Chrysostomos Nanakos fe8a3e6625
refactor(dht-proxy): unify ResponseStatus+ErrorKind into single LookupCode enum (#1473)
Signed-off-by: Chrysostomos Nanakos <chris@include.gr>
2026-06-24 19:49:02 +00:00

112 lines
3.2 KiB
Nim

## Logos Storage
## Copyright (c) 2026 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.
{.push raises: [].}
import pkg/chronos
import pkg/libp2p
import pkg/libp2p/cid
import pkg/libp2p/routing_record
import ../discovery
import ../logutils
import ./protocol
export protocol
logScope:
topics = "storage dht-proxy server"
type DhtProxyProtocol* = ref object of LPProtocol
discovery*: Discovery
inFlight: int
maxInFlight: int
proc handleFindProviders(
self: DhtProxyProtocol, queryBytes: seq[byte]
): Future[LookupResponse] {.async: (raises: [CancelledError]).} =
let
cid = Cid.init(queryBytes).valueOr:
warn "Invalid CID in lookup request"
return LookupResponse(code: LookupCode.ErrInvalidCid)
providers = (await self.discovery.findDirect(cid)).valueOr:
warn "Direct lookup failed", cid, err = error.msg
return LookupResponse(code: LookupCode.ErrInternal)
if providers.len == 0:
return LookupResponse(code: LookupCode.NotFound)
var encoded = newSeqOfCap[seq[byte]](providers.len)
for spr in providers:
let bytes = spr.encode().valueOr:
warn "Failed to encode SignedPeerRecord", err = error
continue
encoded.add(bytes)
if encoded.len == 0:
return LookupResponse(code: LookupCode.ErrInternal)
let packed = packProviders(encoded, MaxLookupResponseBytes).valueOr:
return LookupResponse(code: error)
LookupResponse(code: LookupCode.Ok, providers: packed)
proc handleLookupRequest(
self: DhtProxyProtocol, conn: Connection
) {.async: (raises: [CancelledError]).} =
try:
if self.inFlight >= self.maxInFlight:
debug "DHT proxy at capacity, replying ErrTooBusy",
inFlight = self.inFlight, max = self.maxInFlight
await conn.writeLp(LookupResponse(code: LookupCode.ErrTooBusy).encode())
return
inc self.inFlight
defer:
dec self.inFlight
let
reqBytes = await conn.readLp(MaxLookupRequestBytes)
req = LookupRequest.decode(reqBytes).valueOr:
warn "Failed to decode lookup request"
await conn.writeLp(LookupResponse(code: LookupCode.ErrDecodeFailed).encode())
return
let resp =
case req.queryType
of FindProviders:
await self.handleFindProviders(req.queryBytes)
await conn.writeLp(resp.encode())
except CancelledError as exc:
raise exc
except LPStreamError as exc:
warn "Stream error", err = exc.msg
except CatchableError as exc:
warn "Handler error", err = exc.msg
proc new*(
T: type DhtProxyProtocol,
discovery: Discovery,
maxInFlight: int = DefaultMaxInFlightLookups,
): DhtProxyProtocol =
let self = DhtProxyProtocol(discovery: discovery, maxInFlight: maxInFlight)
proc handler(
conn: Connection, proto: string
): Future[void] {.async: (raises: [CancelledError]).} =
try:
await self.handleLookupRequest(conn)
finally:
await noCancel conn.close()
self.handler = handler
self.codec = DhtProxyCodec
return self