2022-11-04 09:52:27 +00:00
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
else:
|
|
|
|
{.push raises: [].}
|
2022-08-02 23:47:42 +00:00
|
|
|
|
|
|
|
import
|
2024-03-15 23:08:47 +00:00
|
|
|
std/options, stew/results, stew/byteutils, chronicles, chronos, metrics, bearssl/rand
|
2022-08-02 23:47:42 +00:00
|
|
|
import
|
2024-01-30 12:28:21 +00:00
|
|
|
../node/peer_manager/peer_manager,
|
2023-04-19 11:29:23 +00:00
|
|
|
../waku_core,
|
2024-01-30 12:28:21 +00:00
|
|
|
./common,
|
2022-08-02 23:47:42 +00:00
|
|
|
./rpc,
|
2022-10-25 12:55:31 +00:00
|
|
|
./rpc_codec,
|
2024-04-15 13:28:35 +00:00
|
|
|
./protocol_metrics,
|
|
|
|
../common/ratelimit,
|
|
|
|
../common/waku_service_metrics
|
|
|
|
|
|
|
|
export ratelimit
|
2024-03-15 23:08:47 +00:00
|
|
|
|
2022-08-02 23:47:42 +00:00
|
|
|
logScope:
|
2022-11-03 15:36:24 +00:00
|
|
|
topics = "waku lightpush"
|
2022-08-02 23:47:42 +00:00
|
|
|
|
2024-01-30 12:28:21 +00:00
|
|
|
type WakuLightPush* = ref object of LPProtocol
|
2024-03-15 23:08:47 +00:00
|
|
|
rng*: ref rand.HmacDrbgContext
|
|
|
|
peerManager*: PeerManager
|
|
|
|
pushHandler*: PushMessageHandler
|
2024-04-15 13:28:35 +00:00
|
|
|
requestRateLimiter*: Option[TokenBucket]
|
2022-08-02 23:47:42 +00:00
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
proc handleRequest*(
|
|
|
|
wl: WakuLightPush, peerId: PeerId, buffer: seq[byte]
|
|
|
|
): Future[PushRPC] {.async.} =
|
2023-10-09 14:38:23 +00:00
|
|
|
let reqDecodeRes = PushRPC.decode(buffer)
|
|
|
|
var
|
2024-03-15 23:08:47 +00:00
|
|
|
isSuccess = false
|
|
|
|
pushResponseInfo = ""
|
|
|
|
requestId = ""
|
2023-10-09 14:38:23 +00:00
|
|
|
|
|
|
|
if reqDecodeRes.isErr():
|
|
|
|
pushResponseInfo = decodeRpcFailure & ": " & $reqDecodeRes.error
|
|
|
|
elif reqDecodeRes.get().request.isNone():
|
|
|
|
pushResponseInfo = emptyRequestBodyFailure
|
|
|
|
else:
|
2024-03-15 23:08:47 +00:00
|
|
|
let pushRpcRequest = reqDecodeRes.get()
|
2023-10-09 14:38:23 +00:00
|
|
|
|
|
|
|
requestId = pushRpcRequest.requestId
|
2022-10-25 12:55:31 +00:00
|
|
|
|
|
|
|
let
|
2023-10-09 14:38:23 +00:00
|
|
|
request = pushRpcRequest.request
|
2022-08-02 23:47:42 +00:00
|
|
|
|
2023-10-09 14:38:23 +00:00
|
|
|
pubSubTopic = request.get().pubSubTopic
|
|
|
|
message = request.get().message
|
|
|
|
waku_lightpush_messages.inc(labelValues = ["PushRequest"])
|
2024-06-10 13:56:55 +00:00
|
|
|
notice "lightpush request",
|
|
|
|
peer_id = peerId,
|
2024-03-15 23:08:47 +00:00
|
|
|
requestId = requestId,
|
|
|
|
pubsubTopic = pubsubTopic,
|
2024-06-10 13:56:55 +00:00
|
|
|
msg_hash = pubsubTopic.computeMessageHash(message).to0xHex()
|
2024-03-15 23:08:47 +00:00
|
|
|
|
2023-10-09 14:38:23 +00:00
|
|
|
let handleRes = await wl.pushHandler(peerId, pubsubTopic, message)
|
|
|
|
isSuccess = handleRes.isOk()
|
|
|
|
pushResponseInfo = (if isSuccess: "OK" else: handleRes.error)
|
|
|
|
|
2024-05-09 18:07:49 +00:00
|
|
|
if not isSuccess:
|
2023-10-09 14:38:23 +00:00
|
|
|
waku_lightpush_errors.inc(labelValues = [pushResponseInfo])
|
2024-03-15 23:08:47 +00:00
|
|
|
error "failed to push message", error = pushResponseInfo
|
2023-10-09 14:38:23 +00:00
|
|
|
let response = PushResponse(isSuccess: isSuccess, info: some(pushResponseInfo))
|
|
|
|
let rpc = PushRPC(requestId: requestId, response: some(response))
|
|
|
|
return rpc
|
|
|
|
|
2024-03-04 14:31:37 +00:00
|
|
|
proc initProtocolHandler(wl: WakuLightPush) =
|
2023-10-09 14:38:23 +00:00
|
|
|
proc handle(conn: Connection, proto: string) {.async.} =
|
2024-05-09 18:07:49 +00:00
|
|
|
var rpc: PushRPC
|
|
|
|
wl.requestRateLimiter.checkUsageLimit(WakuLightPushCodec, conn):
|
|
|
|
let buffer = await conn.readLp(DefaultMaxRpcSize)
|
|
|
|
|
|
|
|
waku_service_inbound_network_bytes.inc(
|
|
|
|
amount = buffer.len().int64, labelValues = [WakuLightPushCodec]
|
|
|
|
)
|
|
|
|
|
|
|
|
rpc = await handleRequest(wl, conn.peerId, buffer)
|
|
|
|
do:
|
|
|
|
debug "lightpush request rejected due rate limit exceeded",
|
|
|
|
peerId = conn.peerId, limit = $wl.requestRateLimiter
|
|
|
|
|
|
|
|
rpc = static(
|
|
|
|
PushRPC(
|
|
|
|
## We will not copy and decode RPC buffer from stream only for requestId
|
|
|
|
## in reject case as it is comparably too expensive and opens possible
|
|
|
|
## attack surface
|
|
|
|
requestId: "N/A",
|
|
|
|
response:
|
|
|
|
some(PushResponse(isSuccess: false, info: some(TooManyRequestsMessage))),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2023-10-09 14:38:23 +00:00
|
|
|
await conn.writeLp(rpc.encode().buffer)
|
2024-03-15 23:08:47 +00:00
|
|
|
|
2024-05-09 18:07:49 +00:00
|
|
|
## For lightpush might not worth to measure outgoing trafic as it is only
|
|
|
|
## small respones about success/failure
|
|
|
|
|
2022-08-02 23:47:42 +00:00
|
|
|
wl.handler = handle
|
|
|
|
wl.codec = WakuLightPushCodec
|
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
proc new*(
|
|
|
|
T: type WakuLightPush,
|
|
|
|
peerManager: PeerManager,
|
|
|
|
rng: ref rand.HmacDrbgContext,
|
|
|
|
pushHandler: PushMessageHandler,
|
2024-04-15 13:28:35 +00:00
|
|
|
rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](),
|
2024-03-15 23:08:47 +00:00
|
|
|
): T =
|
2024-04-15 13:28:35 +00:00
|
|
|
let wl = WakuLightPush(
|
|
|
|
rng: rng,
|
|
|
|
peerManager: peerManager,
|
|
|
|
pushHandler: pushHandler,
|
|
|
|
requestRateLimiter: newTokenBucket(rateLimitSetting),
|
|
|
|
)
|
2022-10-25 12:55:31 +00:00
|
|
|
wl.initProtocolHandler()
|
2024-06-13 17:10:00 +00:00
|
|
|
return wl
|