From b26e4fd256eccbd11cb5b64ae26e8f09b2065c72 Mon Sep 17 00:00:00 2001 From: Marin Karamihalev <marin.karamihalev@iopsys.eu> Date: Mon, 23 Jan 2023 09:34:18 +0100 Subject: [PATCH] comply to notify resp rules --- src/commands/common/notify.ts | 12 +++++++----- src/commands/recipes/subscribe.ts | 14 +++++++------- src/configurations/build.ts | 7 ++++--- src/types.ts | 22 ++++++++++++++++++++-- src/util.ts | 15 +++++++++++---- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/commands/common/notify.ts b/src/commands/common/notify.ts index ceadbbb..cc9b133 100644 --- a/src/commands/common/notify.ts +++ b/src/commands/common/notify.ts @@ -10,8 +10,8 @@ const decode: DecodeFn = (msg) => { const parent = util.searchParent(msg, "subscriptionId"); if (parent) { const id = parent.subscriptionId; - const relField = Object.keys(parent).find((k) => - k !== "subscriptionId" && k !== "sendResp" + const relField = Object.keys(parent).find( + (k) => k !== "subscriptionId" && k !== "sendResp" ); return id && relField ? [parseInfo(relField, msg), id, null] @@ -20,7 +20,7 @@ const decode: DecodeFn = (msg) => { return [null]; }; -const encode: EncodeFn = ({ paths }) => ({ +const encode: EncodeFn = ({ sendResp, subscriptionId, ...rest }) => ({ lookup: "Msg", header: { msgId: util.uniq("NOTIFY@"), @@ -31,8 +31,10 @@ const encode: EncodeFn = ({ paths }) => ({ lookup: "Body", request: { lookup: "Request", - get: { - paramPaths: Array.isArray(paths) ? paths : [paths], + notify: { + subscriptionId, + sendResp, + ...rest, }, }, }, diff --git a/src/commands/recipes/subscribe.ts b/src/commands/recipes/subscribe.ts index 412cb98..7d4c67c 100644 --- a/src/commands/recipes/subscribe.ts +++ b/src/commands/recipes/subscribe.ts @@ -1,4 +1,4 @@ -import { MakeFn, SubscribeRecipe } from "../../types"; +import { CallbackOptions, MakeFn, SubscribeRecipe } from "../../types"; import { uniq } from "../util"; const subscriptionPath = "Device.LocalAgent.Subscription."; @@ -23,12 +23,12 @@ const make: MakeFn = }, }); - const respond = opts?.forceNoResponse - ? () => {} - : () => call("NOTIFY_RESP", { subscriptionId: id }); - const clear = on(id, (...args) => { - respond(); - callback(...args); + // from https://usp.technology/specification/07-index-messages.html#sec:responses-and-retry + + const respond = () => call("NOTIFY_RESP", { subscriptionId: id }); + const clear = on(id, (msg, fullMsg, opts) => { + opts?.sendResp && respond(); + callback(msg, fullMsg); }); return () => { clear(); diff --git a/src/configurations/build.ts b/src/configurations/build.ts index 0b4ba79..5605265 100644 --- a/src/configurations/build.ts +++ b/src/configurations/build.ts @@ -15,7 +15,7 @@ import { BuildConnectionFn, USPVersion, } from "../types"; -import { knownUSPVersions, makeCallbackRouter, makeRouter } from "../util"; +import { knownUSPVersions, makeCallbackRouter, makeRouter, parseCallbackOptions } from "../util"; const defaultPublishEndpoint = "/usp/endpoint"; const defaultSubscribeEndpoint = "/usp/controller"; @@ -187,9 +187,10 @@ const buildConnect: BuildConnectionFn = } const cbs = callbackRouter.get(id); + const callbackOptions = parseCallbackOptions(parsedMsg) cbs.forEach((cb) => { - if (message) cb(message, parsedMsg); - else if (err) cb(err, parsedMsg); + if (callbackOptions) cb(message || err || "", parsedMsg, callbackOptions) + else cb(message || err || "", parsedMsg) }); } }); diff --git a/src/types.ts b/src/types.ts index 612c5b6..cdad800 100644 --- a/src/types.ts +++ b/src/types.ts @@ -240,6 +240,7 @@ export type PbRequestCommand = | PbRequestCommandSupport | PbRequestCommandInstance | PbRequestCommandSupportProto + | PbRequestCommandNotify | PbRequestCommandNotifyResp; export interface SuportedCommandOpts { @@ -266,6 +267,14 @@ export type PbRequestCommandNotifyResp = { }; }; +export type PbRequestCommandNotify = { + notify: { + subscriptionId: string; + sendResp: boolean; + [key: string]: unknown; + }; +}; + export type PbRequestCommandSupportProto = { getSupportedProtocol: { controllerSupportedProtocolVersions: string; @@ -615,7 +624,6 @@ export interface SubscriptionOptions { id?: string; notif: NotifType; retry?: boolean; - forceNoResponse?: boolean; reference: string | string[]; } @@ -726,10 +734,20 @@ export type EncodeArgs = { export type OnIdent = string | RegExp; +export type CallbackOptions = { + sendResp: boolean +} + +export type OnCallback = ( + msg: Response, + fullMsg?: Record<string, any>, + opts?: CallbackOptions +) => void; + export type EncodeFn = (args: Record<string, any>) => PbRequestMessage; export type CallArgs = Record<string, any>; export type ClearFn = () => void; -export type OnFn = (ident: OnIdent, callback: SubscriptionCallback) => ClearFn; +export type OnFn = (ident: OnIdent, callback: OnCallback) => ClearFn; export type MakeFn = (call: CallFn, on: OnFn) => Command; export type MakeRecipeFn = (call: CallFn) => Recipe; export type CommandTrigger = { diff --git a/src/util.ts b/src/util.ts index c1fbfc5..318d87e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,4 +1,5 @@ -import { CommandType, OnIdent, SubscriptionCallback } from "./types"; +import { search } from "./commands/util"; +import { CallbackOptions, CommandType, OnCallback, OnIdent, SubscriptionCallback } from "./types"; /** * Makes a router for storing resolve/reject for a message @@ -24,19 +25,25 @@ const satisfies = (id: OnIdent, matches: string): boolean => export const makeCallbackRouter = () => { const routes = new Map< string, - { callback: SubscriptionCallback; ident: OnIdent } + { callback: OnCallback; ident: OnIdent } >(); return { - get: (id: string): SubscriptionCallback[] => { + get: (id: string): OnCallback[] => { return Array.from(routes.values()) .filter(({ ident }) => satisfies(ident, id)) .map((v) => v.callback); }, - add: (ident: OnIdent, callback: SubscriptionCallback) => { + add: (ident: OnIdent, callback: OnCallback) => { routes.set(toId(ident), { callback, ident }); }, del: (id: OnIdent) => routes.delete(toId(id)), }; }; +export const parseCallbackOptions = (msg: Record<string, any>): CallbackOptions | null => { + const sendResp = search(msg, "sendResp") + if (typeof sendResp === "boolean") return { sendResp } + return null +} + export const knownUSPVersions = ["1.0", "1.1", "1.2"] as const; -- GitLab