= 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 [[../ModuloRencode|modulo rencode]]) nome-funzione e parametri.
<
>
Lato server è sufficiente che le funzioni abbiano il nome in [[../ElencoRemotableFunctions|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 [[../ElencoRemotableFunctions|remotable_funcs]], che di norma è la stessa istanza di {{{NtkNode}}} che fa da collante tra i vari moduli (vedi la [[../ClasseNtkNode|classe NtkNode]]).
<
>
Si istanzia un {{{RPCDispatcher}}} e poi sta in ascolto su un socket "stackless-wrapped" (vedi il [[../ModuloMicrosock|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 [[../UsoDelModuloRPCInNetsukuku|come viene usato il modulo rpc in Netsukuku]].