7.0 KiB
7.0 KiB
Migrating from larvitsmpp 0.4.0
@larvit/smpp 1.0.0 succeeds larvitsmpp 0.4.0. The
shape is the same, connect, send, listen for delivery reports, with callbacks replaced by promises.
API changes
- The package is
@larvit/smppand ESM only.require()no longer works. - Callbacks are gone.
client,server,sendSms,sendResp,sendDlr,unbindandsession.closeare promises resolving to a result with an optionalerr. Nothing rejects. Awaitclose(), or the socket outlives the call. server()resolves once, when it is listening, with a handle carryingclose(),portand asessionevent. It no longer calls back once per connection.- The id a message is answered with goes to
sendResp({ smsId }).sms.smsIdis read-only: the id the segments were answered with, the idsendResp()was given, or the generated UUID v7. Assigning to it throws aTypeError, since modules are strict mode. smsIdsfromsendSms()is(string | undefined)[], one entry per segment, positional withpduObjs,undefinedwhere the SMSC took the segment without naming an id.checkuserpassisauthenticate, takes{ password, session, systemId, systemType }and returnsfalseor{ userData }.- Renamed options:
enqLinkTiming→enquireLinkInterval, servertimeout→idleTimeout. larvitsmpp.utilsis gone. Its contents are named exports:bitCount,decodeMessage,encodeMessage,objToPdu,pduReturn,pduToObj,smppDate,smppTime,splitMessage. The codec is synchronous and returns{ err, pduObj }/{ err, buffer }.pduObj.isResp()is the standaloneisResp(pduObj).pduObj.cmdStatusisundefinedfor a status code the library does not know, with the raw number inpduObj.cmdStatusId.defs.filtersis gone. It was declared on every command and TLV and never invoked. SMPP time formatting, the one part worth keeping, issmppTime.DATAGRAM,FORWARDandSTORE_FORWARDmoved fromconsts.ESM_CLASStoconsts.MESSAGING_MODE, which also namesSMSC_DEFAULT. They are bits 1-0 ofesm_class, not whole values of it. Read them from the new group, or passmessagingModetosendSms(). A staleconsts.ESM_CLASS.STORE_FORWARDreadsundefined, which OR-s into anesm_classcarrying no mode.- The
errorevent issessionError, andserverErroron the server handle. logtakes any object withdebug,error,info,verboseandwarnmethods instead of alarvitutilsone, and is silent by default: README.consts.ENCODING.ASCIIis gone; the same entry isconsts.ENCODING.IA5, the other name SMPP 3.4 5.2.19 gives 0x01.dataCodingByEncodingis the alphabetsendSms()writes, which is 0x00.
Behaviour that changed on the wire
0.4.0 had protocol defects. Fixing them changes the bytes on the wire, so remove any workaround you have for these:
- Every multipart segment was one character short (152 GSM characters instead of 153, 66 UCS2 instead of 67), so long messages were split into more segments than necessary, each one billed.
- LATIN1 (
data_coding0x03) was silently decoded as ASCII, corrupting the message. - Delivery receipt dates were a month off, and the status field read
UNDELIVERABLEwhere the spec defines the 7-characterUNDELIV. - Every receipt went out as
esm_class0x04, the report of a message's final state. A receipt for a transient state,sendDlr('ENROUTE'), is now marked 0x20, the intermediate delivery notification. flash: truediscarded UCS2, mangling flash messages with non-GSM characters, and put the GSM alphabet on a Latin-1 message that has nodata_codingat all; that pair is refused now. Inbound, only adata_codingof exactly 0x10 counted as flash, so a flash UCS2 message and the whole 0xF0 coding group arrived as ordinary messages.- A GSM 03.38 message declared
data_coding0x01, which SMPP 3.4 5.2.19 defines as IA5, so$and@reached a peer honouring the field as STX and NUL. It goes out as 0x00, the SMSC default alphabet, and so does a receiptsendDlr()writes. Latin-1 and UCS2 stay at 0x03 and 0x08, and an inbound 0x01 is still read as GSM 03.38. - The multipart reference counter was shared by every session in the process.
tls: truenever performed a handshake, so the connection was not encrypted.- Alphanumeric senders were sent with TON 1 (international) instead of TON 5.
- Delivery receipts carrying only the standard receipt text, with no TLVs, what Kannel and several other SMSCs send, were rejected outright. They are parsed now.
- A message whose last octet was
0x00was allocated one octet short whilesm_lengthreported the full length, so it went out corrupt. In UCS2 that is any message ending in a character like 一 (U+4E00), routine for CJK text. - Every response carried a
message_id,deliver_sm_respincluded, where SMPP 3.4 4.6.2 makes that field unused and NULL. Jasmin closes the connection on one. Answering an inbound message now puts nothing in it, andsms.smsIdis the local handle it always was. - Binary TLVs (
message_payload,network_error_code,callback_numand the rest) were parsed into a hex string and written back as the ASCII of that string, so every round trip corrupted them. They areBuffers in both directions now; drop any hex encoding of your own. - A body carried in the
message_payloadTLV was ignored, so the message arrived empty, and adata_smwas answeredESME_RINVCMDID, so a receipt thrown on one was lost silently. Both reach the application now: a receipt asdlr, answered for you, and a message assmsfor you to answer. - A long message segmented by the
sar_msg_ref_num,sar_total_segmentsandsar_segment_seqnumTLVs rather than a user data header was never reassembled, so each segment arrived as its own message. Both spellings reassemble now. - Short or malformed PDUs threw out of the codec instead of being reported as a parse failure.
- A PDU whose optional parameters do not end exactly on
command_lengthis refused withESME_RINVTLVSTREAMand dropped, where 0.4.0 kept the TLVs it had read and ignored the octets left over, losing thereceipted_message_idthat makes a receipt a receipt. The refusal reachessessionErroras aPduRefusedErrorwithreasontlvs. - Binds declare
interface_version0x34. 0.4.0 declared 0x00, which tells the SMSC the ESME speaks SMPP 3.3 or earlier, and a spec-following SMSC then withholds every optional parameter, the TLVs delivery receipts are carried in included. - A response reporting a failure carries no body, as the spec defines. 0.4.0 filled the body with
empty defaults, so a refused
submit_sm_respwent out with an emptymessage_ida caller could mistake for a real one. submit_multiwas missing itssm_lengthfield, so itsshort_messagenever round-tripped.
The corrected framing is cross-checked against node-smpp, an independent implementation, in both directions and over a live session.