Sessions
Typed request events and SMSC-side operations on SmppServerSession.
Every accepted connection is an SmppServerSession, delivered via the server's
session event. It emits a typed event per inbound request command and exposes the
SMSC-side operations.
Handling requests
server.on("session", (session) => {
session.on("submit_sm", async (pdu) => {
const id = await enqueue(pdu);
await session.respond(pdu, { messageId: id });
});
session.on("query_sm", async (pdu) => {
const state = await lookup(pdu.messageId);
await session.respond(pdu, { messageId: pdu.messageId, messageState: state });
});
session.on("data_sm", async (pdu) => { /* … */ });
});respond(pdu, fields?) builds the matching _resp with the request's sequence number.
Reject with a status instead of fields:
await session.respond(pdu, { commandStatus: CommandStatus.ESME_RINVDSTADR });Available request events: submit_sm, data_sm, submit_multi, query_sm,
cancel_sm, replace_sm, broadcast_sm, query_broadcast_sm,
cancel_broadcast_sm, plus lifecycle events bound, unbound, stateChange,
pdu, unknownPdu, error, close. (enquire_link and unbind are handled for
you.)
Reassembling multipart submissions
Clients may split long messages across several submit_sm PDUs. Use the core
reassembler:
import { MessageReassembler } from "@better-smpp/core";
server.on("session", (session) => {
const reassembler = new MessageReassembler();
session.on("submit_sm", async (pdu) => {
await session.respond(pdu, { messageId: nextId() });
const message = reassembler.add(pdu);
if (message) {
// message.message is the complete text across all segments
await route(message);
}
});
});Delivering to the client
Sessions bound as receiver or transceiver can be pushed messages and receipts:
// Mobile-originated message:
await session.deliverSm({
sourceAddr: "46709771337",
destinationAddr: session.systemId!,
shortMessage: "hello from a handset",
});
// Delivery receipt:
await session.deliverSm({
sourceAddr: destination,
destinationAddr: source,
esmClass: 0x04,
receiptedMessageId: id,
messageState: 2,
shortMessage: `id:${id} sub:001 dlvrd:001 stat:DELIVRD err:000 text:`,
});deliverSm resolves with the client's deliver_sm_resp (and rejects with
SmppCommandError if the client refuses). Also available: dataSm,
alertNotification, outbind, and the raw escape hatches session.request(pdu) /
session.send(pdu) for custom commands.
Configure windowSize on the server to bound in-flight deliveries per session, and
enquireLink to detect dead clients.
Session context
session.systemId; // bound system_id
session.mode; // "transmitter" | "receiver" | "transceiver"
session.sessionState; // SessionState (server's perspective)
session.remoteAddress; // client IP — PROXY protocol source when present
session.remotePort;
session.proxyAddress; // the load balancer, when PROXY protocol was used
session.secure; // TLS?
session.connection; // the underlying SmppConnection (advanced)Teardown: session.close() (graceful) or session.destroy(). Closed sessions leave
server.sessions automatically.