ZCD - Dettagli Tecnici
Contents
ZCD
La libreria di basso livello.
ZCD usa JsonGlib. Chi usa ZCD non necessita di saperlo. E' stata realizzata una testsuite che verifica di potersi linkare a ZCD senza conoscere JsonGlib.
ZCD viene "inizializzata" con alcune chiamate.
Il metodo tcp_listen avvia una tasklet che si mette in ascolto su un dato indirizzo e una data porta TCP.
Il metodo udp_listen avvia una tasklet che si mette in ascolto su una data interfaccia di rete e una data porta UDP, su qualsiasi indirizzo (cioè in grado di ricevere pacchetti inviati in broadcast sul segmento di rete collegato alla interfaccia passata).
- ...
In seguito si può richiedere a ZCD di effettuare una chiamata a metodo remoto invocando questi metodi:
Il metodo tcp_client crea e ritorna una istanza di TcpClient.
Con i metodi dell'oggetto TcpClient si effettua una chiamata con il protocollo TCP.
- ...
tcp_listen
Il metodo tcp_listen avvia una tasklet che ascolta e gestisce le connessioni TCP provenienti dall'esterno.
cosa riceve
I dati che vengono passati sono:
- La porta TCP e l'indirizzo.
- Nota: se la porta è sopra 1024 non sono richiesti privilegi.
- Nota: si può ascoltare (in diverse tasklet) sulla stessa porta con indirizzi diversi.
- Un delegato che ZCD potrà usare alla ricezione di una connessione per ottenere, se opportuno, un "dispatcher" a cui passare il messaggio per l'esecuzione.
- Un delegato che la tasklet in ascolto potrà usare in caso di errore prima di terminare.
Il delegato per tcp_listen da usare alla ricezione di una connessione è nella forma di una implementazione dell'interfaccia IZcdTcpDelegate. Il suo metodo:
IZcdTcpRequestHandler get_new_handler()
crea una istanza dell'interfaccia IZcdTcpRequestHandler apposita per gestire una connessione. I metodi di quest'ultima sono:
void set_method_name(string)
void add_argument(string)
void set_caller_info(TcpCallerInfo)
IZcdDispatcher? get_dispatcher()
L'interfaccia IZcdDispatcher è implementata da un oggetto che verrà istanziato alla chiamata di get_dispatcher. I suoi metodi sono:
string execute()
Il delegato per tcp_listen da usare in caso di errore nella listen o nella accept è nella forma di una implementazione dell'interfaccia IZcdTcpAcceptErrorHandler. I suoi metodi sono:
void error_handler(Error e)
cosa fa la tasklet che gestisce il socket in ascolto
La tasklet avviata dal metodo tcp_listen apre un socket TCP e si mette in ascolto sulla porta e l'indirizzo specificati. In caso di errore nella listen lo passa al metodo error_handler.
Quando riceve una connessione chiama get_new_handler e passa l'istanza di IZcdTcpRequestHandler ad una nuova tasklet per gestire la connessione. In caso di errore nella accept lo passa al metodo error_handler.
quali messaggi passano attraverso una connessione TCP
Le richieste che arrivano da queste connessioni sono chiamate a metodi remoti, ognuna inclusa in un albero JSON.
Poiché sarebbe complicato (la libreria JsonGlib non lo supporta) leggere uno stream di bytes fino ad ottenere esattamente un valido albero JSON, si conviene che nelle comunicazioni in TCP tra end-points della libreria ZCD i primi 4 byte trasmessi indicano la lunghezza totale in bytes del successivo messaggio. Dopo il messaggio, se la connessione non viene chiusa (dal client) è possibile che venga trasmesso un successivo blocco di 4 byte e un successivo messaggio.
Se il messaggio ricevuto prevede una risposta, questa sarà trasmessa nella stessa connessione, sempre con la convenzione dei 4 byte di lunghezza. Si conviene quindi che, quando un client trasmette un messaggio che prevede una risposta, fino a che la risposta non è stata completamente ricevuta il client non usi la stessa connessione per trasmettere altri messaggi. Può, invece, aprirne immediatamente una nuova.
cosa fa la tasklet che gestisce una connessione
La tasklet legge i 4 bytes che indicano la lunghezza del messaggio e poi legge il numero di bytes indicato. Se la connessione si chiude prima la tasklet termina.
Alla fine verifica di avere letto una stringa contenente un valido albero JSON. Tale JSON la libreria ZCD è in grado di interpretarlo, quindi la tasklet ne estrae le seguenti informazioni:
- Una stringa con il nome del metodo remoto.
- Un array di nodi JSON che saranno passati (in altrettante singole stringhe) al dispatcher come argomenti del metodo.
- Un booleano che dice se è prevista una risposta.
Di seguito la tasklet:
Prepara una istanza di TcpCallerInfo con le informazioni che è in grado di ottenere sulla connessione in corso, cioè l'indirizzo IP del client remoto e il proprio indirizzo IP dove è stato contattato.
Chiama il metodo set_method_name sulla sua istanza di IZcdTcpRequestHandler. Si assume che l'oggetto memorizzi il nome del metodo.
Chiama (quante volte necessario) il metodo add_argument sulla sua istanza di IZcdTcpRequestHandler. Si assume che l'oggetto memorizzi gli argomenti da passare al metodo.
Chiama il metodo set_caller_info sulla sua istanza di IZcdTcpRequestHandler. Si assume che l'oggetto memorizzi l'istanza di TcpCallerInfo.
Chiama il metodo get_dispatcher sulla sua istanza di IZcdTcpRequestHandler.
- L'oggetto IZcdTcpRequestHandler a questo punto è in grado di stabilire se il messaggio è da processare. In questo caso ritorna una istanza apposita di IZcdDispatcher. Altrimenti ritorna null.
- In ogni caso l'oggetto IZcdTcpRequestHandler resetta le sue impostazioni. Infatti l'eventuale oggetto restituito ha memorizzato le informazioni per l'esecuzione del metodo.
Se il risultato è null il messaggio va ignorato. La tasklet chiude la connessione e termina.
- Se il messaggio dichiarava di NON voler ricevere una risposta qui viene avviata una nuova tasklet che fa le seguenti operazioni. Altrimenti le seguenti operazioni sono svolte dalla stessa tasklet:
La tasklet chiama il metodo execute sull'istanza di IZcdDispatcher ottenuta.
- L'oggetto IZcdDispatcher deserializza gli argomenti. Esegue il metodo e ottiene il risultato (o l'eccezione). Serializza il risultato e lo restituisce come stringa JSON.
- Questa istanza è di una classe fornita da MOD-RPC, quindi conosce le classi degli argomenti da passare e le eventuali eccezioni previste dal metodo.
- La tasklet ora verifica che il contenuto sia un valido JSON. Può abortire il programma se non lo è.
- Se il messaggio dichiarava di voler ricevere una risposta:
- Trasmette il contenuto (dopo i 4 bytes che ne indicano la lunghezza) al socket mittente.
- Ascolta altre richieste.
tcp_client
Per ridurre l'overhead di una connessione TCP, un client può stabilire una connessione TCP con un server ed utilizzarla per diversi messaggi. Questo metodo restituisce un'istanza di TcpClient che rappresenta una connessione con il server indicato.
cosa riceve
Il metodo tcp_client riceve:
- L'indirizzo IP e la porta TCP del server da contattare.
L'oggetto TcpClient che viene restituito memorizza queste informazioni. Inoltre esso incapsula un socket con il quale verrà stabilita la connessione. Ma la connessione non viene inizialmente aperta.
TcpClient
Ogni istanza di TcpClient lavora con il socket che incapsula. Tale oggetto può essere acceduto da diverse tasklet che lavorano in contemporanea, ma come abbiamo detto non è possibile usare la stessa connessione contemporaneamente per due operazioni. L'oggetto fornirà al suo utilizzatore questi metodi:
bool is_queue_empty - Verificare se la connessione è immediatamente disponibile per avviare una operazione (non ci sono altre operazioni in corso o accodate).
string? enqueue_call - Accodare una operazione.
- A questo metodo sono passati:
- La stringa con il nome del metodo da chiamare.
- Un array di stringhe in formato JSON, una per ogni argomento del metodo.
- Un booleano per indicare se si attende una risposta.
- Se la coda è vuota, questo metodo avvia una operazione nella connessione. Altrimenti accoda l'operazione, garantendo la sequenzialità delle operazioni accodate. In ogni caso, il metodo non ritorna fino a quando non ha eseguito l'operazione, cioè inviato il messaggio e ricevuto, se previsto, la risposta. La risposta (una stringa in formato JSON) viene poi restituita dal metodo.
- Se questo metodo viene chiamato immediatamente dopo aver verificato che la connessione è disponibile (con il metodo precedente) si è certi che l'operazione in realtà non viene accodata, ma immediatamente avviata.
Di norma il client esegue queste operazioni. Per prima cosa crea una istanza di TcpClient con il metodo tcp_client di ZCD e la memorizza per usarla in futuro. Quando vuole effettuare una chiamata non urgente chiama direttamente il metodo enqueue_call sull'istanza che aveva memorizzata. Quando vuole effettuare una chiamata urgente chiama il metodo is_queue_empty e se è vuota chiama immediatamente il metodo enqueue_call ; se invece non è vuota crea una nuova istanza di TcpClient con il metodo tcp_client di ZCD, la sostituisce alla precedente e chiama su di essa il metodo enqueue_call .
Quando una operazione viene avviata, se la connessione non è aperta viene aperta. L'oggetto non può venire distrutto (ci saranno riferimenti ad esso) fino a quando ci sono operazioni accodate o in corso. Quando l'oggetto viene distrutto (rimossi tutti i riferimenti), se la connessione è aperta viene chiusa.
come procede una operazione
Se la connessione non era aperta il TcpClient si occupa di aprirla.
Il TcpClient costruisce un JSON dove scrive:
- Il nome del metodo.
- Un array di nodi JSON. Ogni stringa JSON dei parametri viene parsata per costruire l'albero JSON e poi il nodo radice viene aggiunto a questo array.
- Il booleano per indicare se si attende una risposta.
Dal JSON il TcpClient produce una stringa e la trasmette alla connessione, preceduta da 4 bytes che ne indicano la lunghezza.
Se bisogna attendere una risposta, il TcpClient la attende dalla stessa connessione, leggendola come sempre: prima 4 bytes e poi il numero di bytes riportati. La stringa ricevuta deve essere un valido JSON.
Se durante queste operazioni (cioè tra l'inizio della trasmissione del messaggio e la fine della ricezione della risposta) si verifica un errore imprevisto (ad esempio la connessione è chiusa) il socket viene scartato e sostituito con un nuovo socket costruito con gli stessi dati del precedente (indirizzo IP e porta TCP) non ancora connesso. Poi l'operazione in corso restituisce una eccezione ZCDError. Le altre operazioni, che eventualmente erano state accodate in precedenza, potranno essere avviate e di conseguenza una nuova connessione verrà tentata.
udp_listen
Il metodo udp_listen avvia una tasklet che ascolta e gestisce le connessioni UDP provenienti dall'esterno. I dati che vengono passati sono:
- La porta UDP e l'interfaccia di rete.
- Verificare: se la porta è sopra 1024, per ascoltare pacchetti in broadcast sono richiesti privilegi?
- Un delegato che ZCD potrà usare alla ricezione di un 'messaggio completo' per ottenere, se opportuno, un "dispatcher" a cui passare il messaggio per l'esecuzione.
MOD-RPC
La libreria di livello intermedio può essere realizzata con il tool rpc-design partendo da una descrizione delle interfacce degli oggetti remoti. In questo caso la libreria che si ottiene avrà le caratteristiche che vengono ora descritte.
File di descrizione
La descrizione delle interfacce degli oggetti remoti viene preparata dallo sviluppatore in un formato apposito detto RPC-IDL in un file interfaces.rpcidl . Tale formato prevede la presenza di una classe radice, chiamata root-dispatcher . Questa ha un numero di membri che rappresentano ognuno un oggetto remoto che implementa un particolare modulo dell'applicazione. Ogni oggetto remoto ha un numero di metodi remoti.
Lato server
La libreria fornisce una interfaccia skeleton per la classe radice e una per ogni modulo membro.
Fornisce inoltre una interfaccia per il delegato da usare per reperire l'istanza della classe radice.
Facciamo un esempio. Il file interfaces.rpcidl presenta la classe radice "NodeManager node_manager". Ha un membro "InfoManager info_manager". Questo ha il metodo "string get_name()". La libreria prodotta da rpc-design fornirà queste interfacce:
ModRpc.IInfoManagerSkeleton.
- Prevede il metodo astratto:
string get_name(ModRpc.CallerInfo? caller=null).
ModRpc.INodeManagerSkeleton.
- Prevede il metodo astratto:
ModRpc.IInfoManagerSkeleton info_manager_getter().
ModRpc.IRpcDelegate.
- Prevede il metodo astratto:
ModRpc.INodeManagerSkeleton? get_node_manager(ModRpc.CallerInfo caller).
Nota 1: Tutti i metodi remoti nell'interfaccia skeleton ricevono un argomento aggiuntivo ModRpc.CallerInfo che contiene alcune informazioni sul richiedente. Il contenuto varia a seconda del metodo usato per inviare il messaggio (Tcp, Unicast, Broadcast).
Nota 2: L'interfaccia IRpcDelegate ha un metodo per ogni root-dispatcher. Inizialmente supportiamo un solo root-dispatcher e quindi un solo metodo. Se ci fossero più root-dispatcher per ogni richiesta che si riceve lato server la prima parte del nome del metodo remoto starebbe ad indicare il root-dispatcher da usare; sarebbe compito della libreria MOD-RPC prendere questo prefisso e scegliere il metodo di IRpcDelegate da chiamare.
L'applicazione APP che voglia essere in grado di fare da server dovrà fornire attraverso il delegato un'oggetto per l'interfaccia radice e da questo la libreria sarà in grado di reperire l'oggetto che rappresenta un modulo e chiamare su quest'ultimo un metodo remoto.
Quando si inizializza il MOD-RPC per fare da server, fra le altre cose, vengono avviate delle tasklet che stanno in ascolto su particolari messaggi dalla rete. Ci sono 2 tipologie di tasklet per i 3 tipi di messaggi che supporta ZCD.
Tasklet che ascoltano i messaggi TCP destinati alla porta port del proprio indirizzo my_addr , oppure di qualsiasi indirizzo IPv4 dell'host.
Tasklet che ascoltano i messaggi UDP destinati alla porta port di qualsiasi indirizzo (in broadcast ) ricevuti tramite l'interfaccia di rete my_nic .
Questa tipologia di tasklet è poi in grado di distinguere richieste Unicast da richieste Broadcast .
Ad esempio si può avviare una tasklet che ascolta i messaggi TCP per qualsiasi indirizzo dell'host + una tasklet che ascolta i messaggi UDP sulla interfaccia "eth0" + una tasklet che ascolta i messaggi sulla interfaccia "wlan0", e così via.
Le due tipologie di tasklet descritte sopra producono due diversi tipi di oggetti CallerInfo: la prima per ogni connessione produce una istanza di ModRpc.TcpCallerInfo, la seconda per ogni messaggio ricevuto produce o una istanza di ModRpc.UnicastCallerInfo oppure di ModRpc.BroadcastCallerInfo.
Per ognuna di queste tasklet in ascolto, l'applicazione APP ha inizialmente fornito un delegato dlg che è una istanza di ModRpc.IRpcDelegate.
I metodi che avviano queste tasklet sono:
void ModRpc.tcp_listen(ModRpc.IRpcDelegate dlg, uint16 port, string? my_addr = null);
- ...
Supponiamo ora che una di queste tasklet ha ricevuto un messaggio, composto dal nome del metodo e dai suoi argomenti. Inoltre ha composto il CallerInfo caller .
Continuando con l'esempio precedente, la libreria MOD-RPC chiama "INodeManagerSkeleton? root = dlg.get_node_manager(caller);". Questo metodo del delegato riceve a parametro il CallerInfo e l'istanza di delegato fornita da APP decide in base a questo caller se restituire una certa istanza dell'interfaccia skeleton del root-dispatcher.
Ricevuto il root-dispatcher è compito della libreria MOD-RPC esaminare il nome del metodo, individuare il percorso da fare (es: root.info_manager.get_name), deserializzare gli argomenti, chiamare il metodo, ottenere l'esito (il valore di ritorno o catchare le eccezioni) serializzarlo e restituirlo attraverso la rete al chiamante.
Se durante la deserializzazione degli argomenti si riscontra un problema (ad esempio non sono del tipo previsto dalla signature del metodo, oppure un oggetto è di una classe sconosciuta al programma, oppure un oggetto viene deserializzato ma non contiene tutte le proprietà requisito della sua classe) la libreria MOD-RPC non richiama affatto il metodo, invece serializza e restituisce una eccezione DeserializeError.
Lato client
Per l'applicazione APP che voglia essere in grado di fare da client, invece, la libreria MOD-RPC fornisce una interfaccia stub per la classe radice e una per ogni modulo membro. La libreria fornisce alcune funzioni all'applicazione per ottenere una istanza dello stub radice, una funzione per ogni modalità di invio del messaggio. Utilizzando il file interfaces.rpcidl riportato nell'esempio precedente le interfacce prodotte sono:
- IInfoManagerStub
- Prevede il metodo astratto:
string get_name() throws StubError, DeserializeError.
- INodeManagerStub.
- Prevede il metodo astratto:
- IInfoManagerStub info_manager_getter().
Le funzioni sono:
- INodeManagerStub get_node_manager_tcp_client(...)
- INodeManagerStub get_node_manager_unicast(...)
- INodeManagerStub get_node_manager_broadcast(...)
I metodi remoti che possono essere chiamati su uno stub prevedono tutti due possibili eccezioni oltre alle altre eventualmente descritte nel file interfaces.rpcidl. Una è StubError; può essere lanciata dalla libreria nel nodo locale per segnalare un errore nella fase di trasmissione del messaggio o ricezione della risposta. L'altra è DeserializeError; può essere trasmessa (in forma serializzata) come risposta dalla libreria nel nodo remoto se ha riscontrato problemi nel deserializzare gli argomenti che il nodo locale ha passato; oppure può essere lanciata dalla libreria nel nodo locale per segnalare un problema nel deserializzare il valore di ritorno.
Le classi stub fornite dalla libreria MOD-RPC hanno il compito di serializzare gli argomenti, inviare il messaggio attraverso la rete, ricevere la risposta (valore di ritorno o eccezione), deserializzarla e restituirla.
Serializzazione e deserializzazione di argomenti, valori di ritorno e eccezioni
Come detto nell'analisi funzionale, la libreria MOD-RPC ha il compito di:
- Lato client (nello stub) serializzare ogni argomento di una chiamata a metodo remoto in una stringa che rappresenta un valido albero JSON.
- Lato server (nello skeleton) deserializzare ogni stringa ricevuta nel relativo argomento.
- Lato server serializzare l'esito di una chiamata (può essere il valore di ritorno o una eccezione dichiarata nella signature) in una stringa che rappresenta un valido albero JSON.
- Lato client deserializzare l'esito, distinguendo se si tratta del valore di ritorno o di una eccezione.
La libreria MOD-RPC prodotta con il tool rpc-design si avvale della libreria JsonGlib per generare e leggere stringhe JSON.
La classe stub conosce la signature del metodo, quindi per ogni argomento ha il valore e il tipo atteso. Avendo ricevuto la chiamata come un normale metodo di una classe Vala, ha già fatto un controllo sulla validità degli argomenti.
Per gli argomenti del metodo remoto, ogni albero JSON ha per radice un oggetto con un singolo membro chiamato "argument". Il suo valore è un nodo JSON. Vediamo in dettaglio per ogni possibile situazione cosa contiene tale nodo.
Se il tipo atteso è null-able e il valore è null, qualsiasi sia il tipo, il nodo è un nodo NULL .
Se il tipo atteso è int64 il nodo è un nodo VALUE impostabile con set_int di JsonGlib. In questo caso rientra anche un tipo che si possa castare a int64 senza perdere informazioni. In questo caso rientra anche un tipo null-able, sapendo ormai che il valore effettivo non è null.
Se il tipo atteso è double il nodo è un nodo VALUE impostabile con set_double di JsonGlib. In questo caso rientra anche un tipo che si possa castare a double senza perdere informazioni. In questo caso rientra anche un tipo null-able, sapendo ormai che il valore effettivo non è null.
Se il tipo atteso è boolean il nodo è un nodo VALUE impostabile con set_boolean di JsonGlib. In questo caso rientra anche un tipo null-able, sapendo ormai che il valore effettivo non è null.
Se il tipo atteso è string il nodo è un nodo VALUE impostabile con set_string di JsonGlib. In questo caso rientra anche un tipo null-able, sapendo ormai che il valore effettivo non è null.
Se il tipo atteso è binario, cioè un "uint8[]", il nodo è un nodo VALUE impostabile con set_string di JsonGlib. In questo caso rientra anche un "uint8[]?", sapendo ormai che il valore effettivo non è null. La stringa che rappresenta l'array di bytes è ottenuta codificando in Base64.
Se il tipo atteso è una istanza di una classe che deriva da GLib.Object il nodo è un nodo OBJECT . In questo caso rientra anche una interfaccia che richiede Object. In questo caso rientra anche un tipo null-able, sapendo ormai che il valore effettivo non è null.
In questo nodo OBJECT abbiamo 2 membri, uno chiamato "typename" e l'altro "value". Nel membro typename viene messo un nodo VALUE di tipo stringa con il nome del tipo dell'oggetto obj che si ottiene con "obj.get_type().name()". Nel membro value viene messo un nodo che è la serializzazione dell'oggetto obj che si ottiene con "Json.gobject_serialize(obj)".
Rimandiamo alla documentazione di JsonGlib per capire cosa contiene il nodo che si ottiene con questa serializzazione. Brevemente diciamo solo che in generale è un nodo OBJECT con tanti membri quante sono le properties che sono nell'oggetto serializzato; se una property è a sua volta un oggetto questo è serializzato ricorsivamente; se la classe dell'oggetto serializzato implementa l'interfaccia Json.Serializable allora ha maggior controllo sul nodo che viene prodotto.
Se il tipo atteso è una lista Gee.List il nodo è un nodo ARRAY i cui elementi sono tutti dello stesso tipo. In questo caso rientra anche un tipo null-able, sapendo ormai che il valore effettivo non è null.
Gli elementi di questo nodo ARRAY sono nodi (non alberi) trattati ognuno come sarebbe trattato il nodo di un singolo argomento.
Altri tipi di argomento non sono supportati direttamente dal codice prodotto da rpc-design. Lo sviluppatore potrà sviluppare per essi una classe che implementi l'interfaccia ModRpc.Serializable e sia in grado di serializzare e deserializzare le informazioni necessarie.
Lo skeleton riceve la stringa JSON di un argomento dalla libreria ZCD. Essa ha già verificato che questa rappresenti un valido albero JSON. Se questo requisito non è soddisfatto è quindi lecito che la libreria MOD-RPC abortisca il programma.
deserializzazione
Ogni volta che si deserializza un Json.Node dobbiamo sapere quale classe dovrà essere costruita con esso, cioè il suo Type. Il Node che rappresenta l'oggetto parametro o return-value può contenere un null , oppure un tipo base, oppure un array, oppure un oggetto composto di 2 nodi membri: "typename" e "value".
Vediamo il caso OBJECT . Il suo membro "typename" è un nodo VALUE che contiene la stringa typename con cui ottenere il Type.
La libreria MOD-RPC esegue "Type type = Type.from_name(typename);". Se la classe non esiste e stava deserializzando un argomento nel server, allora trasmette un DeserializeError; se invece era in fase di deserializzazione del risultato nel client, lancia l'eccezione DeserializeError.
Dopo la libreria MOD-RPC verifica che il tipo type sia quello atteso (o un suo derivato). Altrimenti trasmette (o lancia, come detto sopra) un DeserializeError.
Il membro "value" è il vero node da passare alla deserializzazione. La libreria MOD-RPC esegue "GLib.Object obj = Json.gobject_deserialize(type, node);". Questa chiamata, potrebbe apparire strano, non prevede alcun tipo di eccezione.
Come detto in precedenza, rimandiamo alla documentazione di JsonGlib per dettagli su come questa deserializzazione avviene. Diciamo solo che la libreria istanzia il tipo indicato e cerca di valorizzare le property che riconosce sia nell'albero JSON sia nell'oggetto istanziato. Ma se ci sono properties nell'oggetto che non sono menzionate nel JSON semplicemente le lascia con il loro valore di default; e se ci sono membri nel JSON che non sono presenti nell'oggetto semplicemente li ignora. Per questo la libreria MOD-RPC fornisce, come misura di ulteriore verifica, una interfaccia ModRpc.Serializable.
Quindi, se il tipo type implementa l'interfaccia ModRpc.Serializable, allora la libreria richiama sull'oggetto appena deserializzato il metodo "bool check_serialization()" di tale interfaccia. In tale metodo l'oggetto verifica che tutte le property necessarie (dette property requisito) siano state correttamente valorizzate. Altrimenti (se ritorna false) la libreria MOD-RPC trasmette (o lancia, come detto sopra) un DeserializeError.
Specifiche di trasmissione e ricezione
Modo TCP
Il metodo per ottenere uno stub "get_node_manager_tcp_client(...)" prevede questi parametri:
- Indirizzo IP del destinatario.
- Porta TCP del destinatario.
Lato server, alla ricezione di una connessione, viene valorizzato un oggetto TcpCallerInfo che contiene:
- Indirizzo IP del nodo corrente che è stato usato come destinazione.
- Indirizzo IP del mittente.
Modo Unicast
Il metodo per ottenere uno stub "get_node_manager_unicast(...)" prevede questi parametri:
- Nome dell'interfaccia di rete per la trasmimssione.
- Porta UDP della trasmissione.
- Identificativo UnicastID del destinatario.
Lato server, alla ricezione di un messaggio, viene valorizzato un oggetto UnicastCallerInfo che contiene:
- Nome dell'interfaccia di rete dove il messaggio è stato rilevato.
- Indirizzo IP del mittente.
- Oggetto UnicastID indicato nel messaggio.
Modo Broadcast
Il metodo per ottenere uno stub "get_node_manager_broadcast(...)" prevede questi parametri:
- Nome dell'interfaccia di rete per la trasmimssione.
- Porta UDP della trasmissione.
- Identificativo BroadcastID dei destinatari.
Lato server, alla ricezione di un messaggio, viene valorizzato un oggetto BroadcastCallerInfo che contiene:
- Nome dell'interfaccia di rete dove il messaggio è stato rilevato.
- Indirizzo IP del mittente.
- Oggetto BroadcastID indicato nel messaggio.
APP
La applicazione di alto livello.