Il maledetto formato PDU

Premessina: In ufficio avevamo (e per quel che ne so ce l’abbiamo tuttora, solo che io ho cambiato ufficio) un simpatico sistema di invio automatizzato di SMS di allarme, che gira su due PC con Linux, ciascuno dei quali gestisce due modem GSM. 

Vabbè… dicevamo: Questo giocattolino inizialmente usava gnokii come software di invio e ricezione sms. Ora, gnokii aveva qualche leggerissimissimo problemino con

  • sms concatenati
  • qualche modello di modem GSM non nokia
  • sms con richieste particolari al centro servizi

E naturalmente, come Murphy comanda, queste tre caratteristiche comparivano contemporaneamente nel nostro sistemino, ragion per cui gnokii era inadeguato. Inoltre al nostro sistemista serviva un log un po’ particolare per rilevare il regolare funzionamento del demone e qualche funzioncina aggiuntiva, per cui mi sono cuccato (volontariamente, sia chiaro. Quelle poche volte che c’è da scrivere codice per gestire hardware, io mi ci butto a pesce) il divertente compito di scrivere un software che facesse le stesse funzioni di gnokii, compatibile con i suoi database, e con le nuove funzionalità richieste.

Il colloquio con i modem non era un problema, rispondono ai normali comandi AT+, scrivo da anni roba che dialoga con i modem per cui nessun tipo di difficoltà (oddio… sempre se escludiamo qualche piccola vaccata dei nostri modem Siemens, tipo rispondere OK anche quando il comando è andato in errore)

Meno semplice è stato capire che diavolo dovevo trasmettere.

In poche parole, per trasmettere un normale sms con un modem GSM, è sufficiente la seguente sequenza:

 

AT+CMGF=1 attiva il formato “testo semplice” nell’invio di sms
AT+CMGS=xxxxxxxxxxx invio SMS al numero xxxxxxxxxxx secondo piano di numerazione nazionale (quindi senza 0039 o +39)
testo_del_messaggio ^Z deve essere minore o uguale a 160 caratteri. Il modem NON è in grado di concatenare per conto suo.

 

A questo punto il modem risponderà con un +CMGS=nnn dove nnn è un numero progressivo assegnato dal modem stesso (e di cui non ci interessa niente) se l’sms è stato inviato con successo, oppure un CMx ERROR: yyy se ci sono stati degli errori.
Tutto semplice e lineare. Ci sono un sacco di altre opzioni del comando AT+CMGS, principalmente legate al piano di numerazione, ma non importa. La sequenza qua sopra FUNZIONA E BASTA.

Quanto scritto sopra relativamente agli sms semplici, si trova addirittura googlando at+cmgs sms e sentendosi fortunati. Ci sono in rete migliaia di esempi, e persino sui manuali dei modem GSM come i Wavecom, o dei telefoni con modem come il vecchissimo Ericsson 888 o dei più recenti nokia.

MA…

…il bello viene quando si comincia a cercare informazioni per l’invio di sms concatenati (AKA long sms, AKA linked sms, AKA concatenated sms, AKA multipart sms, AKA multipart short messages, AKA almeno un’altra decina di modi diversi di chiamarli. Provate ad impostare una ricerca decente, se vi riesce!)

Eh già. Perchè dopo che avete ravanato per delle ore, finendo per farvi venire a nausea le o di gooooooooogle, scoprite (per caso, naturalmente, dopo che il modem ai vostri tentativi risponde con l’equivalente numerico di “comando non implementato, fottiti”) che l’invio degli sms concatenati non si può fare in modo testo semplice, ma richiede l’utilizzo di un particolare formato dati chiamato PDU (Packet Data Unit).
In poche parole, si deve comporre questo PDU che verrà inviato così com’è al centro servizi. Questo pacchetto ha un formato ben definito, e contiene tutte le informazioni necessarie al centro servizi per inoltrare correttamente il vostro bel sms.

Fortunatamente, lo standard (!!!) GSM è ben documentato, e un bel giretto sul sito ETSI mi permette di scaricare un sacco di cosette carine ed utili tra cui:

GSM 07.05 Use of Data Terminal Equipment – Data Circuit terminating Equipment (DTE – DCE) interface for Short Message Service (SMS) and Cell Broadcast Service (CBS)
GSM 03.40 Technical realization of the Short Message Service (SMS)
GSM 03.38 Alphabets and language-specific information
Dopo la lettura di tutto ‘sto malloppo, decido che mi serve un esempio pratico. Altra ricerchina(questa volta è stata un po’ più veloce, per fortuna) e finisco su http://www.dreamfabric.com/sms/ (sito purtroppo morto)

E qui, cominciano i primi amletici dubbi.

The following example shows how to send the message “hellohello” in the PDU mode from a Nokia 6110.
AT+CMGF=0 //Set PDU mode
AT+CMGS=23 //Send message, 23 octets (excluding the two initial zeros)
0011000B916407281553F80000AA0AE8329BFD4697D9EC37<ctrl-z>

?? E perchè escludere dalla lunghezza del pacchetto i due zeri iniziali ??

Più avanti nella pagina si dice che

Length of SMSC information. Here the length is 0, which means that the SMSC stored in the phone should be used. Note: This octet is optional. On some phones this octet should be omitted! (Using the SMSC stored in phone is thus implicit)

Oh cazzo. E meno male che è uno standard!!! Uno dovrebbe conoscere il tipo di apparecchio collegato e discriminare di conseguenza??? Naaaa! Non ci posso credere! Tanto più che negli standard non si parla proprio della facoltatività di quel parametro! Ma nonostante questo, uno dei due modelli di modem che ho testato dà errore se c’è quel parametro, e l’altro invece dà errore se non c’è (però il conteggio dei bytes della lunghezza del PDU lo comprende!)

…se chi ben comincia è a metà dell’opera, io sono nella merda…

Vi risparmio i due giorni di tragedie che ho passato per districarmi in mezzo alle specifiche, che IMHO sono fatte solo per chi sa già alla perfezione quello che dovrebbe cercare. Sappiate solo che dopo un tottone di ore di panico, sono finalmente riuscito a districare il formato del PDU necessario per l’invio di un sms più lungo di 160 caratteri.

Chi è capitato su questa pagina proprio cercando informazioni su come inviare un SMS multipart in formato PDU, me lo faccia sapere con un commento nel guestbook e provvederò quando ne avrò il tempo a scrivere un documento tecnico vero e proprio sul formato PDU. Questa pagina è solo un mio personale mugugno :-) 

Dicevamo: dopo aver compreso il formato, mi sono sorti tutta un’altra serie di dubbi, questa volta sulla sanità mentale di chi ha steso ‘ste specifiche. Perchè, per carità, io sono storto di mio, ma certe cose proprio non le comprendo, se dal punto di vista logico non hanno senso.

Alcuni esempi? Ok …

Il primo parametro (quello riferito al famoso “00” nell’esempio di prima, fa parte dell’identificazione del centro servizi, che è composto nel seguente modo:

XXyyZZZZZZZZZZZZ

XX è il numero di bytes… pardon… di OTTETTI (perchè i telecomici parlano in nnTETTI … ottetti, settetti, comprese le mezze misure tipo i semi-ottetti… sigh!) del numero del centro servizi, ESCLUSO (?!?) l’ottetto successivo (yy). yy è il piano di numerazione usato per identificare il numero (ad esempio 0x91 significa numerazione internazionale) ZZZZZZZZZZZZ è il numero di telefono in semi-ottetti (BCD, per i comuni mortali)… ma con i nybbles (semi-ottetti!) INVERTITI!
In altre parole, se scrivo 07917283010010F5, intendo dire che il numero del mio centro servizi (che da ora in avanti chiamerà col suo nome breve cioè SMSC) è lungo 0x07 ottetti, che il suo piano di numerazione è 0x91 e che il suo numero è +27381000015. E quella F? Oh beh … è un riempitivo. E perchè nel numero di ottetti non viene incluso il byte relativo al piano di numerazione, che è a tutti gli effetti parte del numero? Boh! Misteri.

Ora, il formato PDU è fatto per compattare il più possibile le informazioni in modo da far transitare sulla rete meno dati possibili. E questi mi mettono un riempitivo che butta via 4bit così? Mah … vabbè tiriamo avanti.

Subito dopo, ci sono alcuni dati per identificare il tipo di PDU, e poi il numero di telefono del destinatario.

Se state pensando che il formato di questo numero è uguale a quello dell’SMSC, beh … illusi!

La sua struttura è sempre

XXyyZZZZZZZZZZZZ

ma XX questa volta è la lunghezza espressa in SEMI-OTTETTI. Ma PERCHE’ due formati diversi per lo stesso tipo di dato????? Beh magati un vantaggio ce l’ha: essendo il numero fisico di cifre del numero, almeno non serve più il riempitivo! Sbagliato, naturalmente. XX può essere dispari, ma la lunghezza di ZZZZZZZZZZZZ deve essere un numero pari di cifre, e quindi la F riempitiva compare anche qua! Misteri della fede…

Ma il capolavoro più bello è il payload: il contenuto dell’sms!

L’alfabeto standard degli sms è a 7 bit. Il che mi sta benissimo. Mi sta un po’ meno bene il fatto che secondo l’alfabeto standard non c’è modo di fare le accentate maiuscole diverse dalla E con accento grave, mentre ci sono tutti i caratteri più inutili di questo mondo, ma fa lo stesso.

Per questioni di spazio, i 7 bit vengono “compressi” negli ottetti in modo da usare tutti i bit possibili. Opinabile lo schema di divisione e accodamento dei vari bit, ad occhio credo sia stata fatta in modo da facilitare la ricostruzione in fase di ricezione, considerando che lo stream di bit è trasmesso in forma seriale sulla rete. Ma visto che i microprocessori c’erano anche nei primissimi telefoni GSM, potevano anche fare di meglio. Ma fin qui è ancora tutto ok.

Il bello viene quando si richiedono funzioni aggiuntive al SMSC. Per fare questo, in testa al payload (la cui lunghezza, vi ricordo, è misurata in SETTETTI) bisogna aggiungere un UDH (User Data Header) il quale però E’ CODIFICATO E MISURATO A BYTES. Ma, per motivi di compatibilità con i vecchi apparecchi, che non gestivano gli UDH (compatibilità vuol dire che sui vecchi apparecchi comparirà in testa al messaggio una serie di schifezze!)invece che intervenire implementando un nuovo tipo di messaggio, la genialata è stata quella di aggiungere la lunghezza dello UDH alla lunghezza del payload come se fosse stato spedito in settetti (quindi un header di 7 bytes verrà misurato come 8 settetti), riempire i bit rimanenti fino ad un “confine” tra un settetto e l’altro, e poi proseguire con l’invio del payload normale!

Sono semplicemente sconcertato…

Speak Your Mind

*