Document answeredOnArrival for client receivers and onRequest refusal (#85)

* Document answeredOnArrival for client receivers and onRequest refusal

* Apply stability review: correct the onRequest bind claim and teardown order
This commit is contained in:
2026-09-06 06:30:18 +02:00
committed by GitHub
parent 184d1dc7af
commit 4194816d6b
3 changed files with 125 additions and 12 deletions
+80 -4
View File
@@ -1,15 +1,18 @@
import assert from 'node:assert/strict';
import net from 'node:net';
import test, { describe } from 'node:test';
import type { Dlr } from '../src/dlr.ts';
import type { Session } from '../src/session.ts';
import type { PduObject } from '../src/pdu.ts';
import type { Sms } from '../src/sms.ts';
import type { SmppLog } from '../src/log.ts';
import type { SmppServer } from '../src/server.ts';
import type { TestContext } from 'node:test';
import { PduFramer } from '../src/pdu-framer.ts';
import { PduRefusedError } from '../src/pdu-refusal.ts';
import { objToPdu } from '../src/pdu.ts';
import { Session } from '../src/session.ts';
import { client } from '../src/client.ts';
import { closeAfter } from './teardown.ts';
import { closeAfter, closeListenerAfter } from './teardown.ts';
import { isCommand, objToPdu, pduToObj } from '../src/pdu.ts';
import { server } from '../src/server.ts';
function once<T>(register: (resolve: (value: T) => void) => void): Promise<T> {
@@ -218,9 +221,17 @@ describe('README: Server', () => {
closeAfter(t, smpp);
let answeredOnArrival: boolean | undefined;
smpp.on('session', session => {
session.on('sms', async sms => {
await sms.sendResp();
answeredOnArrival = sms.answeredOnArrival;
if (sms.answeredOnArrival) {
await sms.sendResp(); // multipart: only releases the shutdown drain
} else {
await sms.sendResp(); // ESME_ROK with a generated id
}
if (sms.dlr) {
await sms.sendDlr();
@@ -250,6 +261,71 @@ describe('README: Server', () => {
assert.equal(sent.err, undefined);
assert.equal((await reported).statusMsg, 'DELIVERED');
assert.equal(answeredOnArrival, false);
});
test('refusing a submission at onRequest, before this library would answer it', async t => {
const knownRecipients = new Set(['46709771337']);
const accepted: net.Socket[] = [];
const listener = net.createServer(sock => {
accepted.push(sock);
const session = new Session({
onRequest: async (bound, pduObj) => {
if (!isCommand(pduObj, 'submit_sm') || knownRecipients.has(pduObj.params.destination_addr)) {
return false;
}
await bound.sendReturn(pduObj, 'ESME_RINVDSTADR');
return true;
},
sock,
});
session.linkEnd = 'smsc';
closeAfter(t, session);
});
closeListenerAfter(t, listener, accepted);
await new Promise<void>(resolve => { listener.listen(0, resolve); });
const address = listener.address();
const port = typeof address === 'object' && address !== null ? address.port : 0;
const peer = net.connect({ port });
t.after(() => { peer.destroy(); });
const framer = new PduFramer();
const refused = once<PduObject>(resolve => {
peer.on('data', chunk => {
framer.push(chunk);
for (const pdu of framer.next().pdus ?? []) {
const { pduObj } = pduToObj(pdu);
if (pduObj) resolve(pduObj);
}
});
});
await once<true>(resolve => { peer.once('connect', () => { resolve(true); }); });
const { buffer } = objToPdu({
cmdName: 'submit_sm',
params: {
destination_addr: '46700000000',
short_message: 'Hello world',
source_addr: '46701113311',
},
seqNr: 1,
});
assert.ok(buffer);
peer.write(buffer);
assert.equal((await refused).cmdStatus, 'ESME_RINVDSTADR');
});
});