Name the option a refused address came from, and the data a 0.5.0 consumer stored
Mirror / push (push) Successful in 4s
Test / lint (pull_request) Successful in 20s
Test / test (18) (pull_request) Successful in 35s
Test / test (20) (pull_request) Successful in 30s
Test / test (22) (pull_request) Successful in 29s
Test / test (24) (pull_request) Successful in 29s
Test / test (26) (pull_request) Successful in 30s

This commit is contained in:
2026-09-21 08:14:08 +02:00
parent f870b7530f
commit dc690b912f
6 changed files with 56 additions and 20 deletions
+6 -3
View File
@@ -1,4 +1,5 @@
import type { Result, VoidResult } from '../result.ts';
import { unencodableText } from './encodings.ts';
export type DestAddress =
| { dest_addr_npi: number; dest_addr_ton: number; destination_addr: string }
@@ -84,11 +85,11 @@ function pastLatin1(text: string): { err: Error } | undefined {
if (index === -1) return undefined;
const code = (text.codePointAt(index) ?? 0).toString(16).toUpperCase().padStart(4, '0');
const char = String.fromCodePoint(text.codePointAt(index) ?? 0);
return {
err: new Error(
`Character U+${code} at index ${String(index)} is past latin1, which every text field on the wire is written in`,
`latin1 cannot carry ${unencodableText({ char, index })}, and every text field on the wire is written in it; strip or transliterate it`,
),
};
}
@@ -113,7 +114,9 @@ function wantCstringText(value: ParamValue): Result<{ text: string }> {
if (index === -1) return { text };
return {
err: new Error(`U+0000 at index ${String(index)} would end the C-Octet String there`),
err: new Error(
`U+0000 at index ${String(index)} would end the C-Octet String there, so the peer would read every field behind it shifted`,
),
};
}
+16 -1
View File
@@ -7,10 +7,10 @@ import type { SmppLog } from './log.ts';
import type { SmsIdNotation } from './sms-id.ts';
import { UnansweredError } from './unanswered-error.ts';
import { consts, defaultMessagingMode, isMessagingMode, isSubmitMessagingMode, submitMessagingModes } from './defs/constants.ts';
import { cstring, paramText } from './defs/types.ts';
import { dataCodingByEncoding, detect, encodingNames, isEncodingName, unencodable, unencodableText } from './defs/encodings.ts';
import { namedValue } from './error-from.ts';
import { normaliseSmsId } from './sms-id.ts';
import { paramText } from './defs/types.ts';
import { maxSegments, smppTime, splitMessage } from './message.ts';
export type SendSmsOptions = {
@@ -211,8 +211,23 @@ function checkFlash(encoding: EncodingName, flash: boolean): Error | undefined {
return new Error('flash has no Latin-1 spelling: a message class carries GSM 7-bit, 8-bit data or UCS2, and 8-bit data is not text a handset will display, so send it as UCS2 or drop flash');
}
/** Asked of the wire type itself, so the codec cannot refuse an address this let through. */
function checkAddresses(sms: SendSmsInput): Error | undefined {
for (const option of ['from', 'to'] as const) {
const { err } = cstring.size(sms[option]);
if (err) return new Error(`${option}: ${err.message}`);
}
return undefined;
}
/** Every option a send can be refused for, so nothing is built for a message that will not go. */
function checkOptions(sms: SendSmsInput): Result<CheckedOptions> {
const unwritable = checkAddresses(sms);
if (unwritable) return { err: unwritable };
const mode = checkMessagingMode(sms.messagingMode, sms.dlr === true);
if (mode.err) return { err: mode.err };