Refuse a maxOctets below 1 at startup, like the other limits #24
@@ -35,6 +35,8 @@
|
|||||||
- An `alert_notification` or an `outbind` from the peer is logged and left unanswered, as SMPP 3.4
|
- 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
|
gives neither a response. Each one used to emit `sessionError`, `"alert_notification" has no
|
||||||
response command`.
|
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
|
## 0.5.0
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ export type Collected =
|
|||||||
whole?: PduObject[] | undefined;
|
whole?: PduObject[] | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultMaxOctets = 64 * 1024 * 1024;
|
export const defaultMaxOctets = 64 * 1024 * 1024;
|
||||||
|
|
||||||
type Group = {
|
type Group = {
|
||||||
octets: number;
|
octets: number;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import type { SmsIdFormat } from './sms-id.ts';
|
|||||||
import type { Sms } from './sms.ts';
|
import type { Sms } from './sms.ts';
|
||||||
import type { Socket } from 'node:net';
|
import type { Socket } from 'node:net';
|
||||||
import { backoffDefaults } from './reconnect-loop.ts';
|
import { backoffDefaults } from './reconnect-loop.ts';
|
||||||
|
import { defaultMaxOctets } from './reassembly.ts';
|
||||||
import { isSmsIdNotation, smsIdNotations, smsIdPlaces } from './sms-id.ts';
|
import { isSmsIdNotation, smsIdNotations, smsIdPlaces } from './sms-id.ts';
|
||||||
import { namedValue } from './error-from.ts';
|
import { namedValue } from './error-from.ts';
|
||||||
|
|
||||||
@@ -160,6 +161,7 @@ export function checkSessionOptions(options: CheckableOptions): VoidResult {
|
|||||||
function limitsOf(options: CheckableOptions): [string, number, number][] {
|
function limitsOf(options: CheckableOptions): [string, number, number][] {
|
||||||
return [
|
return [
|
||||||
['idleTimeout', options.idleTimeout ?? 0, 0],
|
['idleTimeout', options.idleTimeout ?? 0, 0],
|
||||||
|
['maxOctets', options.maxOctets ?? defaultMaxOctets, 1],
|
||||||
['maxOutstanding', options.maxOutstanding ?? defaults.maxOutstanding, 1],
|
['maxOutstanding', options.maxOutstanding ?? defaults.maxOutstanding, 1],
|
||||||
['maxReassembly', options.maxReassembly ?? defaults.maxReassembly, 1],
|
['maxReassembly', options.maxReassembly ?? defaults.maxReassembly, 1],
|
||||||
['reassemblyTimeout', options.reassemblyTimeout ?? defaults.reassemblyTimeout, 0],
|
['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. */
|
/** Not an option: the one spelling is inside reconnect, and this is where the other is refused. */
|
||||||
fromStart?: unknown;
|
fromStart?: unknown;
|
||||||
idleTimeout?: number | undefined;
|
idleTimeout?: number | undefined;
|
||||||
|
maxOctets?: number | undefined;
|
||||||
maxOutstanding?: number | undefined;
|
maxOutstanding?: number | undefined;
|
||||||
maxReassembly?: number | undefined;
|
maxReassembly?: number | undefined;
|
||||||
reassemblyTimeout?: number | undefined;
|
reassemblyTimeout?: number | undefined;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { DlrMerger } from '../src/dlr-merger.ts';
|
|||||||
import { PduFramer } from '../src/pdu-framer.ts';
|
import { PduFramer } from '../src/pdu-framer.ts';
|
||||||
import { ReconnectLoop } from '../src/reconnect-loop.ts';
|
import { ReconnectLoop } from '../src/reconnect-loop.ts';
|
||||||
import { Session, bindCommands } from '../src/session.ts';
|
import { Session, bindCommands } from '../src/session.ts';
|
||||||
|
import { checkSessionOptions } from '../src/session-options.ts';
|
||||||
import { client } from '../src/client.ts';
|
import { client } from '../src/client.ts';
|
||||||
import { closeAfter, closeListenerAfter } from './teardown.ts';
|
import { closeAfter, closeListenerAfter } from './teardown.ts';
|
||||||
import { consts } from '../src/defs/constants.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/);
|
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 () => {
|
test('returns an error rather than rejecting on an impossible port', async () => {
|
||||||
const listening = await server({ port: 70_000 });
|
const listening = await server({ port: 70_000 });
|
||||||
|
|
||||||
|
|||||||
@@ -189,12 +189,6 @@ and is also what the panel ranked hardest — two methods, one answer.
|
|||||||
|
|
||||||
### Correctness, ahead of everything below
|
### 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
|
- [ ] **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`,
|
declare `multiple: true` (`callback_num`, `callback_num_atag`, `callback_num_pres_ind`,
|
||||||
`broadcast_area_identifier`, `broadcast_error_status`) and nothing reads it; `parseTlvs()` keys
|
`broadcast_area_identifier`, `broadcast_error_status`) and nothing reads it; `parseTlvs()` keys
|
||||||
|
|||||||
Reference in New Issue
Block a user