Lavoro su sistemi embedded, così frequentemente, mi viene richiesto di implementare i protocolli. Quando faccio questo mi piace fare dei bei livelli puliti.
Tuttavia, questo diventa difficile dove i campi utilizzati da diversi livelli sono condivisi.
Mi piace pensare che i livelli offrano un certo numero di servizi seguendo lo spirito del modello OSI:
Framing
1. Inizia byte / sequenza (SOF)
2. lunghezza del pacchetto / messaggio
3. integrità del messaggio (CRC, xor checksum)
Rete
4. Fonte / Destinazione
Applicazioni
5. Tipo comando / risposta (come interpretare il carico utile).
(Mi rendo conto che questo non è il modello ISO, ma ottieni il punto che spero.)
A volte il protocollo esiste su un collegamento punto-punto (socket RS232 o tcp), quindi non esiste alcun concetto di origine e destinazione.
In genere avrei un livello software per ciascuno di: Framing, Network e Application. Il livello è in genere un byte di elaborazione della macchina di stato, o frame o pacchetti. Nella parte superiore, vi è un punto di aggancio per la funzionalità specifica dell'applicazione.
Tipicamente quando un pacchetto si sposta sullo stack e i layer vengono rimossi, passo semplicemente un puntatore al successivo ambito interno. Primo puntatore a SOF, quindi puntatore ai campi di rete e infine un puntatore al payload dell'applicazione.
Man mano che i campi vengono analizzati, vengono aggiunti a una struttura specifica per il livello che la produce. (Una struttura con un nome come: Frame, Pacchetto, Messaggio / Comando / Risposta) Ogni struttura ha un puntatore al buffer del pacchetto.
In alto posso deallocare la struttura chiamando gratuitamente su ogni livello fino a quando in basso un puntatore è disponibile per liberare. (o tornare a un pool)
La domanda è: come posso gestire in modo pulito i casi in cui i campi hanno un duplice uso o sono campi di bit in un byte. (il nibble superiore è la lunghezza del payload, il nibble più basso è il tipo di pacchetto, ecc ...)
Un esempio di questo è un semplice formato di pacchetto come questo:
<SOF> <CMD> <command specific payload> <CRC>
In questo caso la lunghezza del pacchetto è implicita dal codice di comando. Quindi il campo CMD (un singolo byte in questo caso) è condiviso tra il framing e i livelli dell'applicazione.
Penso che in questo caso il livello di framing abbia una tabella di ricerca per il comando di lunghezza e passa un puntatore al campo CMD fino al livello applicazione per la gestione in una struttura.