4. Requisiti lato server (Server-Side Requirements)
4.1. Richiesta (Request)
Una richiesta GET con un'Opzione Observe impostata a 0 (registra) richiede al server non solo di restituire una rappresentazione attuale della risorsa di destinazione, ma anche di aggiungere il client all'elenco degli osservatori di quella risorsa. In caso di successo, il server restituisce una rappresentazione attuale della risorsa e DEVE mantenere questa rappresentazione aggiornata (come descritto nella Sezione 1.3) finché il client è nell'elenco degli osservatori.
La voce nell'elenco degli osservatori è identificata dall'endpoint del client e dal token specificato dal client nella richiesta. Se una voce con una coppia endpoint/token corrispondente è già presente nell'elenco (il che, ad esempio, accade quando il client desidera rafforzare il suo interesse in una risorsa), il server NON DEVE aggiungere una nuova voce ma DEVE sostituire o aggiornare quella esistente.
Un server che non è in grado o non vuole aggiungere una nuova voce all'elenco degli osservatori di una risorsa PUÒ ignorare silenziosamente la richiesta di registrazione ed elaborare la richiesta GET come al solito. La risposta risultante NON DEVE includere un'Opzione Observe, la cui assenza segnala al client che non sarà notificato dei cambiamenti alla risorsa e, ad esempio, deve invece interrogare la risorsa per il suo stato.
Se l'Opzione Observe in una richiesta GET è impostata a 1 (cancellare), allora il server DEVE rimuovere qualsiasi voce esistente con una coppia endpoint/token corrispondente dall'elenco degli osservatori ed elaborare la richiesta GET come al solito. La risposta risultante NON DEVE includere un'Opzione Observe.
4.2. Notifiche (Notifications)
Un client viene notificato dei cambiamenti dello stato della risorsa da risposte aggiuntive inviate dal server in risposta alla richiesta GET. Ogni tale risposta di notifica (inclusa la risposta iniziale) DEVE riecheggiare il token specificato dal client nella richiesta GET. Se ci sono più voci nell'elenco degli osservatori, l'ordine in cui i client vengono notificati non è definito; il server è libero di utilizzare qualsiasi metodo per determinare l'ordine.
Una notifica DOVREBBE avere un codice di risposta 2.05 (Content) o 2.03 (Valid). Tuttavia, nel caso in cui lo stato di una risorsa cambi in un modo che causerebbe a una normale richiesta GET in quel momento di restituire una risposta non-2.xx (ad esempio, quando la risorsa viene eliminata), il server DOVREBBE notificare il client inviando una notifica con un codice di risposta appropriato (come 4.04 Not Found) e successivamente DEVE rimuovere la voce associata dall'elenco degli osservatori della risorsa.
Il Content-Format specificato in una notifica 2.xx DEVE essere lo stesso di quello utilizzato nella risposta iniziale alla richiesta GET. Se il server non è in grado di continuare a inviare notifiche in questo formato, DOVREBBE inviare una notifica con un codice di risposta 4.06 (Not Acceptable) e successivamente DEVE rimuovere la voce associata dall'elenco degli osservatori della risorsa.
Una notifica 2.xx DEVE includere un'Opzione Observe con un numero di sequenza come specificato nella Sezione 4.4 di seguito; una notifica non-2.xx NON DEVE includere un'Opzione Observe.
4.3. Caching
Poiché le notifiche sono solo risposte aggiuntive inviate dal server in risposta a una richiesta GET, sono soggette al caching come definito nella Sezione 5.6 di RFC 7252 [RFC7252].
4.3.1. Freschezza (Freshness)
Dopo aver restituito la risposta iniziale, il server DEVE mantenere lo stato della risorsa osservato dal client il più strettamente sincronizzato possibile con lo stato effettivo della risorsa.
Poiché non si può evitare di essere a volte non sincronizzati, il server DEVE indicare per ogni rappresentazione un'età fino alla quale è accettabile che lo stato osservato e lo stato effettivo siano incoerenti. Questa età dipende dall'applicazione e DEVE essere specificata nelle notifiche utilizzando l'Opzione Max-Age.
Quando la risorsa non cambia e il client ha una rappresentazione attuale, il server non ha bisogno di inviare una notifica. Tuttavia, se il client non riceve una notifica, il client non può dire se lo stato osservato e lo stato effettivo sono ancora sincronizzati. Pertanto, quando l'età dell'ultima notifica diventa maggiore del suo Max-Age indicato, il client non ha più una rappresentazione utilizzabile dello stato della risorsa. Il server PUÒ voler prevenire ciò inviando una nuova notifica con la rappresentazione invariata e un nuovo Max-Age appena prima che il Max-Age indicato in precedenza scada.
4.3.2. Convalida (Validation)
Un client può includere un set di tag di entità nella sua richiesta utilizzando l'Opzione ETag. Quando una risorsa osservata cambia il suo stato e il server di origine sta per inviare una notifica 2.05 (Content), allora ogni volta che quella notifica ha un tag di entità nel set di tag di entità specificato dal client, il server PUÒ inviare invece una risposta 2.03 (Valid) con un'Opzione ETag appropriata.
4.4. Riordino (Reordering)
Poiché i messaggi possono essere riordinati, il client ha bisogno di un modo per determinare se una notifica è arrivata più tardi di una notifica più recente. A questo scopo, il server DEVE impostare il valore dell'Opzione Observe di ogni notifica che invia ai 24 bit meno significativi di un numero di sequenza strettamente crescente. Il numero di sequenza PUÒ iniziare a qualsiasi valore e NON DEVE aumentare così velocemente da aumentare di oltre 2^23 in meno di 256 secondi.
Il numero di sequenza selezionato per una notifica DEVE essere maggiore di quello di qualsiasi notifica precedente inviata allo stesso client con lo stesso token per la stessa risorsa. Il valore dell'Opzione Observe DEVE essere attuale al momento della trasmissione; se una notifica viene ritrasmessa, il server DEVE aggiornare il valore dell'opzione al numero di sequenza che è attuale in quel momento prima della ritrasmissione.
Nota di implementazione: Un'implementazione semplice che soddisfa i requisiti è ottenere un timestamp da un orologio locale. Il numero di sequenza è quindi il timestamp in tick, dove 1 tick = (256 secondi)/(2^23) = 30,52 microsecondi. Non è necessario che l'orologio rifletta l'ora/data corrente.
Un'altra implementazione valida è memorizzare una variabile intera senza segno a 24 bit per risorsa e incrementare questa variabile ogni volta che la risorsa subisce un cambiamento di stato (a condizione che la risorsa cambi il suo stato meno di 2^23 volte nei primi 256 secondi dopo ogni cambiamento di stato). Ciò rimuove la necessità di aggiornare il valore dell'Opzione Observe alla ritrasmissione quando lo stato della risorsa non è cambiato.
Nota di progettazione: La scelta di un valore di opzione a 24 bit e un intervallo di tempo di 256 secondi consente teoricamente un tasso di notifica fino a 65536 notifiche al secondo. I nodi vincolati hanno spesso orologi piuttosto imprecisi, tuttavia, e le imprecisioni del lato client e server possono annullarsi o sommarsi in effetti. Pertanto, il tasso di notifica massimo è ridotto a 32768 notifiche al secondo. Questo è ancora ben oltre l'obiettivo di progettazione noto più alto di circa 1 kHz (la maggior parte delle applicazioni CoAP sarà di diversi ordini di grandezza inferiore a quello) ma consente imprecisioni totali dell'orologio fino a -50/+100%.
4.5. Trasmissione (Transmission)
Una notifica può essere inviata in un messaggio confermabile o non confermabile. Il tipo di messaggio utilizzato dipende tipicamente dall'applicazione e può essere determinato dal server per ogni notifica individualmente.
Ad esempio, per risorse che cambiano in modo in qualche modo prevedibile o regolare, le notifiche possono essere inviate in messaggi non confermabili; per risorse che cambiano raramente, le notifiche possono essere inviate in messaggi confermabili. Il server può combinare questi due approcci a seconda della frequenza dei cambiamenti di stato e dell'importanza delle singole notifiche.
Un server PUÒ scegliere di saltare l'invio di una notifica se sa che invierà presto un'altra notifica, ad esempio, quando lo stato di una risorsa cambia frequentemente. PUÒ anche scegliere di inviare più di una notifica per lo stesso stato della risorsa. Tuttavia, soprattutto, il server DEVE garantire che un client nell'elenco degli osservatori di una risorsa osservi alla fine l'ultimo stato se la risorsa non subisce un nuovo cambiamento di stato.
Ad esempio, quando i cambiamenti di stato si verificano a raffiche, il server può saltare alcune notifiche, inviare le notifiche in messaggi non confermabili e assicurarsi che il client osservi l'ultimo cambiamento di stato ripetendo l'ultima notifica in un messaggio confermabile quando la raffica è finita.
Il riconoscimento del client di una notifica confermabile segnala che il client è interessato a ricevere ulteriori notifiche. Se un client rifiuta una notifica confermabile o non confermabile con un messaggio Reset, o se l'ultimo tentativo di ritrasmettere una notifica confermabile scade, allora il client è considerato non più interessato e il server DEVE rimuovere la voce associata dall'elenco degli osservatori.
Nota di implementazione: Per elaborare correttamente un messaggio Reset che rifiuta una notifica non confermabile, un server deve ricordare gli ID messaggio delle notifiche non confermabili che invia. Ciò può essere impegnativo per un server con risorse vincolate. Tuttavia, poiché i messaggi Reset sono trasmessi in modo inaffidabile, il client deve essere preparato nel caso in cui i messaggi Reset non siano ricevuti dal server. Pertanto, un server può sempre fingere che un messaggio Reset che rifiuta una notifica non confermabile sia andato perso.
Se un server fa questo, potrebbe accelerare la cancellazione inviando le seguenti notifiche a quel client in messaggi confermabili.
Un server che trasmette notifiche principalmente in messaggi non confermabili DEVE inviare una notifica in un messaggio confermabile invece di un messaggio non confermabile almeno ogni 24 ore. Ciò impedisce a un client che è andato via o non è più interessato di rimanere nell'elenco degli osservatori indefinitamente.
4.5.1. Controllo della congestione (Congestion Control)
Il controllo di base della congestione per CoAP è fornito dal meccanismo di back-off esponenziale nella Sezione 4.2 di RFC 7252 [RFC7252] e dalle limitazioni nella Sezione 4.7 di RFC 7252 [RFC7252]. Tuttavia, CoAP pone la responsabilità del controllo della congestione per semplici interazioni richiesta/risposta solo sui client: la trasmissione della richiesta con limitazione della velocità controlla implicitamente la trasmissione delle risposte. Quando una singola richiesta produce un numero potenzialmente infinito di notifiche, è necessario porre una responsabilità aggiuntiva sul server.
Per non causare congestione, i server DEVONO limitare rigorosamente il numero di notifiche/risposte in sospeso simultanee che trasmettono a un dato client a NSTART (1 per impostazione predefinita; vedere Sezione 4.7 di RFC 7252 [RFC7252]). Una notifica/risposta in sospeso è un messaggio confermabile per il quale non è stato ancora ricevuto un riconoscimento e il cui ultimo tentativo di ritrasmissione non è ancora scaduto o un messaggio non confermabile per il quale il tempo di attesa che risulta dalle seguenti regole di limitazione della velocità non è ancora trascorso.
Il server NON DOVREBBE inviare più di una notifica non confermabile per tempo di andata e ritorno (RTT) a un client in media. Se il server non può mantenere una stima RTT per un client, NON DOVREBBE inviare più di una notifica non confermabile ogni 3 secondi e DOVREBBE utilizzare una velocità ancora meno aggressiva quando possibile (vedere anche Sezione 3.1.2 di RFC 5405 [RFC5405]).
Ulteriori ottimizzazioni e considerazioni sul controllo della congestione sono previste in futuro con meccanismi avanzati di controllo della congestione CoAP.
4.5.2. Trasmissione avanzata (Advanced Transmission)
Lo stato di una risorsa osservata può cambiare mentre il numero di notifiche/risposte in sospeso simultanee a un client nell'elenco degli osservatori è maggiore o uguale a NSTART. In questo caso, il server non può notificare immediatamente il client del nuovo stato della risorsa ma deve attendere che una notifica/risposta in sospeso sia completata per prima.
Se esiste una notifica/risposta in sospeso che il server trasmette al client e che riguarda la risorsa modificata, allora è desiderabile che il server smetta di lavorare per ottenere la rappresentazione del vecchio stato della risorsa al client e inizi invece a trasmettere la rappresentazione attuale al client, in modo che lo stato della risorsa osservato dal client rimanga più strettamente sincronizzato con lo stato effettivo sul server.
A questo scopo, il server PUÒ ottimizzare il processo di trasmissione interrompendo la trasmissione della vecchia notifica (ma non prima che il tentativo di trasmissione corrente sia completato) e iniziando una nuova trasmissione per la nuova notifica (ma con il timer di ritrasmissione e il contatore della trasmissione interrotta mantenuti).
Più in dettaglio, un server PUÒ sostituire una trasmissione in sospeso che riguarda un'osservazione come segue: