Il modulo RPC
class RPCDispatcher(object)
Un'istanza della classe RPCDispatcher fornisce il metodo marshalled_dispatch(data) per richiamare le funzioni definite remotable sulla base di un blob (arrivato via rete) che codifica (tramite rencode - vedi il modulo rencode) nome-funzione e parametri.
Lato server è sufficiente che le funzioni abbiano il nome in remotable_funcs (in una classe di cui sono metodo)
MicroTCPServer(...)
La microfunc di modulo MicroTCPServer viene richiamata passando la cosidetta root_instance, cioè la classe con le remotable_funcs, che di norma è la stessa istanza di NtkNode che fa da collante tra i vari moduli (vedi la classe NtkNode).
Si istanzia un RPCDispatcher e poi sta in ascolto su un socket "stackless-wrapped" (vedi il modulo microsock per le operazioni di I/O in ambiente stackless), di default bindato alla porta 269 e non associato ad una specifica interfaccia di rete. Per ogni connessione che riceve richiama la microfunc micro_stream_request_handler e subito torna in ascolto.
Questa microfunc a) popola la classe CallerInfo con i dati del chiamante, b) legge dal socket il messaggio in un blob con _data_unpack_from_stream_socket, c) richiama la marshalled_dispatch del RPCDispatcher passando il blob e il CallerInfo, d) rinvia al socket la risposta ottenuta dal RPCDispatcher inpacchettandola con _data_pack.
MicroTCPServer è una microfunc, quindi si avvia in un microthread e resta sempre in vita. Viene però fornito un metodo stop_tcp_servers nel modulo RPC che permette di fermare il server.
class FakeRmt()
E' una classe che permette di chiamare una RPC con una sintassi identica alla chiamata di un metodo locale.
Ad esempio remote_instance.mymethod1.mymethod2.func(p1, p2, p3)
invece di remote_instance.rmt('mymethod1.method2.func', (p1, p2, p3))
In realtà il metodo rmt va implementato in una derivata di questa classe, con in esso la effettiva chiamata RPC.
class TCPClient(FakeRmt)
Semplice classe client che eredita da FakeRmt. Si usa tipo:
a = TCPClient('192.168.1.1',8888)
ret = a.rpc_call('nomefunc', (1,))
ret = a.nomefunc(1)
Alla chiamata di un metodo, si collega al MicroTCPServer remoto, invia in un blob il nome del metodo e gli argomenti, aspetta la risposta in un blob dal host remoto e la decodifica (la risposta può essere anche una eccezione). Poi il metodo termina restituendo la risposta al chiamante.
MicroUDPServer(...)
Le microfunc micro_dgram_request_handler e MicroUDPServer sono le analoghe di micro_stream_request_handler e MicroTCPServer in versione UDP broadcast.
Diversamente dalla MicroTCPServer, la MicroUDPServer viene richiamata n volte, una per ogni interfaccia di rete.
La MicroUDPServer viene richiamata passando la root_instance e l'interfaccia di rete. Si istanzia un RPCDispatcher e poi riceve i pacchetti (recvfrom(8192)) da un socket "stackless-wrapped" di tipo datagram, di default bindato alla porta 269 e associato alla specifica interfaccia di rete. Con ogni pacchetto che riceve richiama la microfunc micro_dgram_request_handler e subito torna in ascolto.
Questa microfunc a) popola la classe CallerInfo con i dati del chiamante, b) decodifica il pacchetto con _data_unpack_from_buffer, c) richiama la marshalled_dispatch del RPCDispatcher passando il blob e il CallerInfo.
MicroUDPServer è una microfunc, quindi ogni sua chiamata (una per interfaccia di rete) si avvia in un microthread e resta sempre in vita. Viene però fornito un metodo stop_udp_servers nel modulo RPC che permette di fermare tutti i servers udp avviati.
class BcastClient(FakeRmt)
Semplice classe client analoga di TCPClient in versione UDP broadcast.
La classe BcastClient si usa tipo:
a = BcastClient() # si può passare un elenco di interfacce
a.nomeFunc(3,2) # nulla viene ritornato
Alla chiamata di un metodo, si prepara un messaggio codificando in un blob il nome del metodo e gli argomenti.
Il messaggio è inviato in broadcast via tutte le interfacce di rete (o quelle richieste). Non si attende una risposta ma si fa subito ritorno al chiamante.
La versione broadcast (UDP) del rpc funziona solo per messaggi inferiori a 8 kB (when packed)
Vedi anche come viene usato il modulo rpc in Netsukuku.