6.1 KiB
Changelog
0.6.0 (unreleased)
-
client()now bounds each connect attempt at 10 seconds, the TLS handshake included, and reports one that expires as an ordinary connect failure, soreconnectretries it on its usual backoff. A connect previously waited the operating system out, around 130 s on Linux against a host that drops SYNs.connectTimeoutretunes the bound, andconnectTimeout: falserestores the old wait. -
Addresses, ids and every other text field on the wire are read and written as latin1. A
source_addrofKaffeépreviously reached the application asKaffei, because the codec wrote the octet and then masked bit 7 reading it back;destination_addr,system_id,message_id,password,service_typeand the C-Octet String TLVs were affected the same way. A character pastU+00FFin one of those fields is now refused, where it used to go out as its low octet.A server comparing
systemIdorpasswordcould be impersonated. Masking bit 7 folded 127 of the 255 non-zero octets onto a character a low octet also reaches, so the bind credentials yourauthenticatereceived were not unique to the octets the peer sent: one refused asadmincould bind as\xE1dminand match the same string. latin1 is one-to-one over the octets, so two different wire values no longer arrive as one. Read 0.5.0 bind logs for asystemIdyou did not issue.Check what you stored before you roll this out. Values your application persisted under 0.5.0 were read with bit 7 masked, so an address or a
message_idcarrying an octet above0x7Fis spelled differently now: a stored id will not match the receipt it belongs to, and a stored address will not match the sender it came from. Ids most SMSCs issue are digits or hex and are unaffected. -
A
U+0000inside a C-Octet String —source_addr,message_id,system_idand the rest — is refused. An Octet String carries a NULL as before. -
A non-finite number —
NaN,Infinity,-Infinity— is refused where a text field on the wire takes one.sendSms({ from: NaN })put the literal senderNaNon the wire and resolved as a successful send;message_id,source_addrand the string TLVs took such a number the same way. The call now resolves witherrnaming the field —from: Expected a finite number, got NaN— so a caller that reads onlysmsIdsmeets a failure it has not met before. A whole number in an address or an id still spells its digits, somessage_id: 123is unchanged. The integer fields name a refusedNaNtoo, where the refusal used to readnull. -
An
alert_notificationor anoutbindfrom the peer is logged and left unanswered, as SMPP 3.4 gives neither a response. Each one used to emitsessionError,"alert_notification" has no response command. -
maxOctetscharges each held segment 1000 octets beyond its own, 300 more per TLV on it, and 300 per occurrence of a repeatable one. Segments of empty fields or thousands of empty TLVs used to count as next to nothing, so a peer could hold far more than the cap. Raise amaxOctetsyou tuned low: it now holds several times fewer segments, and an incomplete message evicted over the cap is lost, since its segments were already answered. -
A message arriving while the application holds 1000 unanswered, or 64 MiB of them counted the way
maxOctetscounts segments, is refused withESME_RTHROTTLED(ESME_RX_T_APPNon a delivery), so the peer keeps it and retries. CallsendResp()on everysms, multipart included: 1000 left unanswered now stop inbound traffic for up to five minutes, where the oldest used to be dropped with a warning. -
A
submit_smsegment the reassembly buffer has no room for is refused withESME_RTHROTTLED, where it wasESME_RMSGQFUL. -
server()refuses amaxOctetsbelow 1 or not a whole number,Infinityincluded, like its other limits.server({ maxOctets: 0 })used to start and then refuse every multipart message. -
callback_num,callback_num_atag,callback_num_pres_ind,broadcast_area_identifierandbroadcast_error_status, the TLVs SMPP allows more than once in a PDU, keep every occurrence in wire order. A PDU carrying two of one used to keep only the last.Reading one of these now needs an index.
pduObj.tlvs.callback_num?.tagValueis aBuffer[]even where one arrived (anumber[]forcallback_num_pres_indandbroadcast_error_status), so aBuffer.isBuffer()ortypeofcheck written for 0.5.0 now reads it as absent. ReadtagValue[0]for the first occurrence.objToPdu(),session.send()andsession.sendReturn()take{ tagValue: [value] }for them and refuse a lone value before anything goes out. -
pduObj.tlvsand everytlvsinput are typed per tag, asTlvsandTlvInputs:receipted_message_idreads as astring,message_stateas anumber, and a value the tag cannot carry fails to compile. Annotate withTlvsorTlvInputswhere you wroteRecord<string, Tlv>orRecord<string, TlvInput>;TlvInputis gone.A TLV input is keyed by its name, or by its decimal id where the table names none, and a
tagIdthat disagrees with its key is refused. Write{ 5142: { tagValue } }for a vendor tag, not{ vendor: { tagId: 5142, … } };{ message_state: { tagId: 5, … } }used to go out as tag 5. A parsed PDU'stlvsstill relay as they are. A number for an octet TLV, vendor tags included, is refused, where it went out as its ASCII digits.A decimal key naming a tag the table knows,
{ 1063: … }, is refused in favour of the name, and so arealert_on_msg_deliveryandfailed_broadcast_area_identifierin favour ofalert_on_message_deliveryandbroadcast_area_identifier, the names they read back under. The two alternate names are gone fromtlvstoo, which is now typed byTlvName: index it with one. -
cmds.broadcast_sm_resp.tlvMapis removed; nothing read it.
0.5.0
The TypeScript rewrite. What a 0.4.0 consumer has to change is in MIGRATION.md.