Refuse a maxOctets below 1 at startup, like the other limits #24

Merged
lilleman merged 2 commits from range-check-max-octets into main 2026-09-24 00:08:19 +02:00
5 changed files with 16 additions and 7 deletions
+2
View File
@@ -35,6 +35,8 @@
- An `alert_notification` or an `outbind` from the peer is logged and left unanswered, as SMPP 3.4
gives neither a response. Each one used to emit `sessionError`, `"alert_notification" has no
response command`.
- `server()` refuses a `maxOctets` below 1 or not a whole number, `Infinity` included, like its
other limits. `server({ maxOctets: 0 })` used to start and then refuse every multipart message.
## 0.5.0
+1 -1
View File
@@ -43,7 +43,7 @@ export type Collected =
whole?: PduObject[] | undefined;
};
const defaultMaxOctets = 64 * 1024 * 1024;
export const defaultMaxOctets = 64 * 1024 * 1024;
type Group = {
octets: number;
+3
View File
@@ -9,6 +9,7 @@ import type { SmsIdFormat } from './sms-id.ts';
import type { Sms } from './sms.ts';
import type { Socket } from 'node:net';
import { backoffDefaults } from './reconnect-loop.ts';
import { defaultMaxOctets } from './reassembly.ts';
import { isSmsIdNotation, smsIdNotations, smsIdPlaces } from './sms-id.ts';
import { namedValue } from './error-from.ts';
@@ -160,6 +161,7 @@ export function checkSessionOptions(options: CheckableOptions): VoidResult {
function limitsOf(options: CheckableOptions): [string, number, number][] {
return [
['idleTimeout', options.idleTimeout ?? 0, 0],
['maxOctets', options.maxOctets ?? defaultMaxOctets, 1],
['maxOutstanding', options.maxOutstanding ?? defaults.maxOutstanding, 1],
['maxReassembly', options.maxReassembly ?? defaults.maxReassembly, 1],
['reassemblyTimeout', options.reassemblyTimeout ?? defaults.reassemblyTimeout, 0],
@@ -268,6 +270,7 @@ export type CheckableOptions = {
/** Not an option: the one spelling is inside reconnect, and this is where the other is refused. */
fromStart?: unknown;
idleTimeout?: number | undefined;
maxOctets?: number | undefined;
maxOutstanding?: number | undefined;
maxReassembly?: number | undefined;
reassemblyTimeout?: number | undefined;
+10
View File
@@ -12,6 +12,7 @@ import { DlrMerger } from '../src/dlr-merger.ts';
import { PduFramer } from '../src/pdu-framer.ts';
import { ReconnectLoop } from '../src/reconnect-loop.ts';
import { Session, bindCommands } from '../src/session.ts';
import { checkSessionOptions } from '../src/session-options.ts';
import { client } from '../src/client.ts';
import { closeAfter, closeListenerAfter } from './teardown.ts';
import { consts } from '../src/defs/constants.ts';
@@ -2688,6 +2689,15 @@ describe('option validation', () => {
assert.match(hookRefused.err?.message ?? '', /onRequest must be a function/);
});
test('refuses a reassembly octet cap below 1 at startup', async () => {
const listening = await server({ maxOctets: 0, port: 0 });
if (listening.server) await listening.server.close();
assert.match(listening.err?.message ?? '', /maxOctets must be 1 or more, got 0/);
assert.match(checkSessionOptions({ maxOctets: Infinity }).err?.message ?? '', /maxOctets must be 1 or more, got Infinity/);
});
test('returns an error rather than rejecting on an impossible port', async () => {
const listening = await server({ port: 70_000 });
-6
View File
@@ -189,12 +189,6 @@ and is also what the panel ranked hardest — two methods, one answer.
### Correctness, ahead of everything below
- [ ] **Range-check `maxOctets` with its five siblings.** `limitsOf()` in `session-options.ts`
covers `idleTimeout`, `maxOutstanding`, `maxReassembly`, `reassemblyTimeout`, `responseTimeout`
and `shutdownTimeout`; `maxOctets` is documented, consumed by `Reassembler`, and absent from
both that list and `CheckableOptions`. `server({ maxOctets: 0 })` starts, then refuses every
multipart message and reports each as lost traffic.
- [ ] **Read `multiple` in `parseTlvs()` and `writeTlvs()`, or delete it and `tlvMap`.** Five TLVs
declare `multiple: true` (`callback_num`, `callback_num_atag`, `callback_num_pres_ind`,
`broadcast_area_identifier`, `broadcast_error_status`) and nothing reads it; `parseTlvs()` keys