Let the session own its bind state, written by bound() alone #42
+2
-1
@@ -77,7 +77,8 @@
|
|||||||
- `session.boundAs` and `session.peerInterfaceVersion` are read-only, and `session.loggedIn` is
|
- `session.boundAs` and `session.peerInterfaceVersion` are read-only, and `session.loggedIn` is
|
||||||
removed: read `session.boundAs !== undefined`. A session you wire yourself records the bind it
|
removed: read `session.boundAs !== undefined`. A session you wire yourself records the bind it
|
||||||
accepted or had accepted with `session.bound(bindType, declaredVersion)`, which returns `err` for a
|
accepted or had accepted with `session.bound(bindType, declaredVersion)`, which returns `err` for a
|
||||||
bind type or version it cannot record; an assignment to either field now throws a `TypeError`.
|
bind type or version it cannot record. An assignment to either field does not compile in
|
||||||
|
TypeScript, and throws a `TypeError` in strict-mode JavaScript, which every module is.
|
||||||
|
|
||||||
## 0.5.0
|
## 0.5.0
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -36,8 +36,9 @@ shape is the same, connect, send, listen for delivery reports, with callbacks re
|
|||||||
Write `alert_on_message_delivery` and `broadcast_area_identifier`, the names they read back
|
Write `alert_on_message_delivery` and `broadcast_area_identifier`, the names they read back
|
||||||
under, for `alert_on_msg_delivery` and `failed_broadcast_area_identifier`, which are gone from
|
under, for `alert_on_msg_delivery` and `failed_broadcast_area_identifier`, which are gone from
|
||||||
`tlvs` too.
|
`tlvs` too.
|
||||||
- **`session.loggedIn` is gone**: read `session.boundAs !== undefined`. A session you construct
|
- **`session.loggedIn` and the `loggedIn` event are gone.** `client()` resolves once bound,
|
||||||
yourself records a bind with `session.bound()`.
|
`session.boundAs !== undefined` says a bind happened, and `disconnected`/`reconnected` say whether
|
||||||
|
the link is up now. A session you construct yourself records a bind with `session.bound()`.
|
||||||
- **The `error` event is `sessionError`**, and `serverError` on the server handle.
|
- **The `error` event is `sessionError`**, and `serverError` on the server handle.
|
||||||
- **`log`** takes any object with `debug`, `error`, `info`, `verbose` and `warn` methods instead of
|
- **`log`** takes any object with `debug`, `error`, `info`, `verbose` and `warn` methods instead of
|
||||||
a `larvitutils` one, and is silent by default: [README](README.md#logging).
|
a `larvitutils` one, and is silent by default: [README](README.md#logging).
|
||||||
|
|||||||
@@ -424,10 +424,13 @@ const { err, pduObj } = await session.send({
|
|||||||
- `peerInterfaceVersion`: the version the peer declared, `0x00` if none, `undefined` before any bind.
|
- `peerInterfaceVersion`: the version the peer declared, `0x00` if none, `undefined` before any bind.
|
||||||
- `bindAllows(cmdName)` and `boundAs`: what the bind direction carries: [Bind direction](#bind-direction).
|
- `bindAllows(cmdName)` and `boundAs`: what the bind direction carries: [Bind direction](#bind-direction).
|
||||||
- `boundAs` and `peerInterfaceVersion` are read-only, and hold through a reconnect's gap until the
|
- `boundAs` and `peerInterfaceVersion` are read-only, and hold through a reconnect's gap until the
|
||||||
next `bound()`.
|
link binds again.
|
||||||
- `bound(bindType, declaredVersion)`: how a session you construct yourself records a bind, whichever
|
- `bound(bindType, declaredVersion)`: how a session you construct yourself records a bind, whichever
|
||||||
end accepted it, on every link it binds. `declaredVersion` is 0-255, or `undefined` where the peer
|
end accepted it, on every link it binds. `bindType` is `receiver`, `transceiver` or `transmitter`;
|
||||||
declared none; anything else, or an unknown `bindType`, returns `err` and records nothing.
|
`declaredVersion` is 0-255, or `undefined` where the peer declared none. Anything else returns `err`
|
||||||
|
and records nothing.
|
||||||
|
- An ESME records the bind from its `bind_resp`, in `reconnect.onConnected` on every rebind:
|
||||||
|
`session.bound('transmitter', pduObj.tlvs.sc_interface_version?.tagValue)`.
|
||||||
|
|
||||||
## Receiving in depth
|
## Receiving in depth
|
||||||
|
|
||||||
@@ -545,8 +548,8 @@ if (err) throw err;
|
|||||||
the link. Guard on the command name, as above, and a failing hook costs only its own request.
|
the link. Guard on the command name, as above, and a failing hook costs only its own request.
|
||||||
- A `Session` you construct yourself takes the same hook as a session option, and that is where a
|
- A `Session` you construct yourself takes the same hook as a session option, and that is where a
|
||||||
peer's bind gets accepted, since a hand-wired session has no bind handling of its own: call
|
peer's bind gets accepted, since a hand-wired session has no bind handling of its own: call
|
||||||
`session.bound(bindType, pduObj.params.interface_version)` before answering it, and refuse the bind
|
`session.bound(pduObj.cmdName.slice('bind_'.length), pduObj.params.interface_version)` before
|
||||||
with `ESME_RBINDFAIL` where that returns `err`.
|
answering it, and refuse the bind with `ESME_RBINDFAIL` where that returns `err`.
|
||||||
|
|
||||||
**`sendDlr()`** takes `SCHEDULED`, `ENROUTE`, `DELIVERED`, `EXPIRED`, `DELETED`, `UNDELIVERABLE`,
|
**`sendDlr()`** takes `SCHEDULED`, `ENROUTE`, `DELIVERED`, `EXPIRED`, `DELETED`, `UNDELIVERABLE`,
|
||||||
`ACCEPTED`, `UNKNOWN`, `REJECTED` or `SKIPPED`. The first two go out as intermediate delivery
|
`ACCEPTED`, `UNKNOWN`, `REJECTED` or `SKIPPED`. The first two go out as intermediate delivery
|
||||||
|
|||||||
@@ -123,6 +123,10 @@ export const undeclaredInterfaceVersion = 0x00;
|
|||||||
|
|
||||||
export type SessionBind = { as: BindType; peerVersion: number };
|
export type SessionBind = { as: BindType; peerVersion: number };
|
||||||
|
|
||||||
|
function quoted(value: unknown): string {
|
||||||
|
return typeof value === 'string' ? JSON.stringify(value) : namedValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
function isBindType(value: unknown): value is BindType {
|
function isBindType(value: unknown): value is BindType {
|
||||||
return typeof value === 'string' && bindTypeFromCommand(`bind_${value}`) !== undefined;
|
return typeof value === 'string' && bindTypeFromCommand(`bind_${value}`) !== undefined;
|
||||||
}
|
}
|
||||||
@@ -130,13 +134,13 @@ function isBindType(value: unknown): value is BindType {
|
|||||||
/** A bind as `Session.bound()` records it: undefined declares no version, which is pre-3.4. */
|
/** A bind as `Session.bound()` records it: undefined declares no version, which is pre-3.4. */
|
||||||
export function checkedBind(bindType: unknown, declaredVersion: unknown): Result<{ bind: SessionBind }> {
|
export function checkedBind(bindType: unknown, declaredVersion: unknown): Result<{ bind: SessionBind }> {
|
||||||
if (!isBindType(bindType)) {
|
if (!isBindType(bindType)) {
|
||||||
return { err: new Error(`bindType must be receiver, transceiver or transmitter, got ${namedValue(bindType)}`) };
|
return { err: new Error(`bindType must be receiver, transceiver or transmitter, the bind command's name without "bind_", got ${quoted(bindType)}`) };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaredVersion === undefined) return { bind: { as: bindType, peerVersion: undeclaredInterfaceVersion } };
|
if (declaredVersion === undefined) return { bind: { as: bindType, peerVersion: undeclaredInterfaceVersion } };
|
||||||
|
|
||||||
if (typeof declaredVersion !== 'number' || !Number.isInteger(declaredVersion) || declaredVersion < 0 || declaredVersion > 0xFF) {
|
if (typeof declaredVersion !== 'number' || !Number.isInteger(declaredVersion) || declaredVersion < 0 || declaredVersion > 0xFF) {
|
||||||
return { err: new Error(`declaredVersion must be 0-255, or undefined where the peer declared none, got ${namedValue(declaredVersion)}`) };
|
return { err: new Error(`declaredVersion must be an integer 0-255, the interface_version param or the sc_interface_version TLV's tagValue, or undefined where the peer declared none, got ${quoted(declaredVersion)}`) };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { bind: { as: bindType, peerVersion: declaredVersion } };
|
return { bind: { as: bindType, peerVersion: declaredVersion } };
|
||||||
|
|||||||
+1
-1
@@ -162,7 +162,7 @@ export class Session extends EventEmitter<SessionEvents> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Records a bind this link accepted or had accepted, until the next one. */
|
/** Records a bind this link accepted or had accepted, until the next one. */
|
||||||
bound(bindType: BindType, declaredVersion: unknown): VoidResult {
|
bound(bindType: string, declaredVersion: unknown): VoidResult {
|
||||||
const checked = checkedBind(bindType, declaredVersion);
|
const checked = checkedBind(bindType, declaredVersion);
|
||||||
|
|
||||||
if (!checked.err) this.bind = checked.bind;
|
if (!checked.err) this.bind = checked.bind;
|
||||||
|
|||||||
Reference in New Issue
Block a user