Tie the refusal to the link, not to the hold, so a released message is refused too
This commit is contained in:
+2
-2
@@ -120,8 +120,8 @@ export class DlrMerger {
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.groups.takeAll();
|
||||
this.spent.takeAll();
|
||||
this.groups.clear();
|
||||
this.spent.clear();
|
||||
}
|
||||
|
||||
/** Drops every group past its deadline. Runs before each collect and on its own timer. */
|
||||
|
||||
@@ -58,14 +58,9 @@ export class ExpiringGroups<T> {
|
||||
this.idle();
|
||||
}
|
||||
|
||||
/** Removes every group and hands them over. */
|
||||
takeAll(): [string, T][] {
|
||||
const taken: [string, T][] = [...this.entries].map(([key, entry]) => [key, entry.group]);
|
||||
|
||||
clear(): void {
|
||||
this.entries.clear();
|
||||
this.idle();
|
||||
|
||||
return taken;
|
||||
}
|
||||
|
||||
/** Removes every group past its deadline and hands them over. */
|
||||
|
||||
+1
-10
@@ -20,7 +20,6 @@ function keyOf(pduObjs: PduObject[]): string | undefined {
|
||||
|
||||
/** The messages handed to the application that it has not answered yet, held by their segments. */
|
||||
export class HeldMessages {
|
||||
private readonly droppedWithLink = new WeakSet<PduObject[]>();
|
||||
private readonly held: ExpiringGroups<PduObject[]>;
|
||||
private readonly idleWaiters = new IdleWaiters();
|
||||
private readonly log: SmppLog;
|
||||
@@ -65,11 +64,6 @@ export class HeldMessages {
|
||||
return key !== undefined && this.held.get(key) === pduObjs;
|
||||
}
|
||||
|
||||
/** Whether this message's link went before it was answered, so no answer of ours correlates. */
|
||||
lostLink(pduObjs: PduObject[]): boolean {
|
||||
return this.droppedWithLink.has(pduObjs);
|
||||
}
|
||||
|
||||
release(pduObjs: PduObject[]): void {
|
||||
const key = keyOf(pduObjs);
|
||||
|
||||
@@ -82,10 +76,7 @@ export class HeldMessages {
|
||||
|
||||
/** Drops every message: their segments went with the link, so no answer of ours correlates now. */
|
||||
clear(): void {
|
||||
for (const [, pduObjs] of this.held.takeAll()) {
|
||||
this.droppedWithLink.add(pduObjs);
|
||||
}
|
||||
|
||||
this.held.clear();
|
||||
this.idleWaiters.settle();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ export class IncomingRequests {
|
||||
private readonly session: Session;
|
||||
private readonly smsIdFormat: SmsIdFormat;
|
||||
private readonly systemId: string;
|
||||
/** Bumped when a link goes, so a message from an earlier one knows its answer cannot correlate. */
|
||||
private linkGeneration = 0;
|
||||
|
||||
constructor(options: IncomingRequestsOptions) {
|
||||
this.dlrMerger = options.dlrMerger;
|
||||
@@ -96,6 +98,7 @@ export class IncomingRequests {
|
||||
|
||||
/** Drops the segments of every message that never became whole, and of every one still held. */
|
||||
clear(): void {
|
||||
this.linkGeneration++;
|
||||
this.held.clear();
|
||||
this.reassembler.clear();
|
||||
}
|
||||
@@ -163,6 +166,8 @@ export class IncomingRequests {
|
||||
|
||||
if (!first) return;
|
||||
|
||||
const generation = this.linkGeneration;
|
||||
|
||||
const sms = createSms({
|
||||
from: paramText(first.params.source_addr),
|
||||
message: decodeSegments(pduObjs),
|
||||
@@ -170,7 +175,7 @@ export class IncomingRequests {
|
||||
session: this.session,
|
||||
to: paramText(first.params.destination_addr),
|
||||
}, {
|
||||
lostLink: () => this.held.lostLink(pduObjs),
|
||||
lostLink: () => this.linkGeneration !== generation,
|
||||
// A turn later, so a listener sending its receipt straight after the response still holds.
|
||||
onAnswered: () => { setImmediate(() => { this.held.release(pduObjs); }); },
|
||||
// Past the refusal only while a drain is still waiting for this message; an ordinary send after.
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ export class Reassembler {
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.groups.takeAll();
|
||||
this.groups.clear();
|
||||
this.octets = 0;
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -54,7 +54,6 @@ export type SmsInput = {
|
||||
|
||||
/** What the session's incoming side gives a message so it can be answered and accounted for. */
|
||||
export type SmsHandlers = {
|
||||
/** Whether the link this message arrived on is gone, so no answer of ours correlates. */
|
||||
lostLink: () => boolean;
|
||||
onAnswered: () => void;
|
||||
send: (input: PduObjectInput) => Promise<Result<{ pduObj: PduObject }>>;
|
||||
@@ -107,13 +106,13 @@ async function sendResp(
|
||||
return { err: new Error('smsId must not be empty') };
|
||||
}
|
||||
|
||||
if (options.smsId !== undefined) answered.smsId = options.smsId;
|
||||
|
||||
// A response carries the sequence number it was asked on, which the next link knows nothing about.
|
||||
if (lostLink()) {
|
||||
return { err: new Error('The link this message arrived on is gone, so nothing would correlate the response') };
|
||||
}
|
||||
|
||||
if (options.smsId !== undefined) answered.smsId = options.smsId;
|
||||
|
||||
const results = await Promise.all(sms.pduObjs.map((pduObj, index) => sms.session.sendReturn(
|
||||
pduObj,
|
||||
options.status ?? 'ESME_ROK',
|
||||
|
||||
Reference in New Issue
Block a user