⇤ ← Revision 1 as of 2016-02-20 17:42:32
Size: 9439
Comment:
|
← Revision 2 as of 2016-02-25 17:20:30 ⇥
Size: 10754
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 44: | Line 44: |
* Se ''dev'' è valorizzato, subito controlla che esista un arco reale formato su ''dev'' con ''peer_address''. Altrimenti restituisce subito null. Questo per evitare di rispondere più volte ad un solo messaggio ricevuto in unicast via UDP. * '''caso a.''' ''unicast_id'' è un IdentityAwareUnicastID. Neighborhood estrapola il ''NodeID identity_aware_unicast_id''. . In questo caso anche ''source_id'' è un IdentityAwareSourceID. Neighborhood estrapola il ''NodeID identity_aware_source_id''. . Chiama il metodo ''get_identity_skeleton(identity_aware_source_id, identity_aware_unicast_id, peer_address, dev)'' che gli è stato fornito dal suo utilizzatore. . L'utilizzatore del modulo, che conosce le ''identità'' del nodo e gli ''archi-identità'' che li collegano ad altri nodi, restituisce, se esiste, lo skeleton relativo alla ''identità identity_aware_unicast_id'', ma solo se questa è collegata tramite un ''arco-identità'' alla ''identità identity_aware_source_id''. Altrimenti null. . Inoltre deve trattarsi di un ''arco-identità'' che si appoggia all'arco reale formato con ''peer_address''. * '''caso b.''' ''unicast_id'' è un WholeNodeUnicastID. Neighborhood estrapola il ''NeighborhoodNodeID whole_node_unicast_id''. . In questo caso anche ''source_id'' è un WholeNodeSourceID. Neighborhood estrapola il ''NeighborhoodNodeID whole_node_source_id''. |
* '''caso 0.''' ''unicast_id'' è un NoArcWholeNodeUnicastID. In questo particolare caso, l'oggetto contiene il NeighborhoodNodeID e il MAC address del destinatario; bisogna verificare che il NeighborhoodNodeID sia il nostro e che il MAC corrisponda all'interfaccia indicata da ''dev'', che in questo caso deve essere valorizzato. Se questi requisiti sono soddisfatti va restituita l'istanza ''node_skeleton''. Altrimenti null. * '''caso a.''' ''unicast_id'' è un IdentityAwareUnicastID. . In questo caso ''source_id'' deve essere un IdentityAwareSourceID. Altrimenti restituisce subito null. . In questo caso ''dev'' non deve essere valorizzato. Altrimenti restituisce subito null. . Neighborhood estrapola da ''unicast_id'' il ''NodeID identity_aware_unicast_id''. Se non è possibile, restituisce subito null. . Neighborhood estrapola da ''source_id'' il ''NodeID identity_aware_source_id''. Se non è possibile, restituisce subito null. . Chiama il metodo ''get_identity_skeleton(identity_aware_source_id, identity_aware_unicast_id, peer_address)'' che gli è stato fornito dal suo utilizzatore. . L'utilizzatore del modulo, che conosce le ''identità'' del nodo e gli ''archi-identità'' che li collegano ad altri nodi, restituisce, se esiste, lo skeleton relativo alla ''identità identity_aware_unicast_id'', ma solo se questa è collegata tramite un ''arco-identità'' alla ''identità identity_aware_source_id''. Inoltre deve trattarsi di un ''arco-identità'' che si appoggia all'arco reale formato con ''peer_address''. Altrimenti null. * '''caso b.''' ''unicast_id'' è un WholeNodeUnicastID. . In questo caso ''source_id'' deve essere un WholeNodeSourceID. Altrimenti restituisce subito null. . In questo caso ''dev'' non deve essere valorizzato. Altrimenti restituisce subito null. . Neighborhood estrapola da ''source_id'' il ''NeighborhoodNodeID whole_node_source_id''. Se non è possibile, restituisce subito null. |
Line 53: | Line 57: |
. Se ''whole_node_unicast_id'' è il NeighborhoodNodeID del nodo corrente, se inoltre è stato formato un arco con ''whole_node_source_id'', se infine tale arco riporta come indirizzo IP ''peer_address'' allora va restituita l'istanza ''node_skeleton''. Altrimenti null. | . Se è stato formato un arco con ''whole_node_source_id'', se infine tale arco riporta come indirizzo IP ''peer_address'' allora va restituita l'istanza ''node_skeleton''. Altrimenti null. |
Line 56: | Line 60: |
* '''caso a.''' ''broadcast_id'' è un IdentityAwareBroadcastID. Neighborhood estrapola la ''Gee.List<NodeID> identity_aware_broadcast_set''. . In questo caso anche ''source_id'' è un IdentityAwareSourceID. Neighborhood estrapola il ''NodeID identity_aware_source_id''. |
* '''caso 0.''' ''broadcast_id'' è un EveryWholeNodeBroadcastID. In questo particolare caso, qualsiasi sia l'interfaccia da cui riceve il messaggio e i dati di provenienza, il nodo deve ricevere una lista con l'istanza ''node_skeleton''. Tale skeleton sarà certamente usato per un metodo remoto sul modulo Neighborhood. * Se non è il caso '''0''', subito controlla che esista un arco reale ''i'' formato su ''dev'' con ''peer_address''. Altrimenti restituisce subito una lista vuota. * '''caso a.''' ''broadcast_id'' è un IdentityAwareBroadcastID. . In questo caso ''source_id'' deve essere un IdentityAwareSourceID. Altrimenti restituisce subito lista vuota. . Neighborhood estrapola da ''broadcast_id'' la ''Gee.List<NodeID> identity_aware_broadcast_set''. Se non è possibile, restituisce subito lista vuota. . Neighborhood estrapola da ''source_id'' il ''NodeID identity_aware_source_id''. Se non è possibile, restituisce subito lista vuota. |
Line 60: | Line 68: |
* '''caso b.''' ''broadcast_id'' è un WholeNodeBroadcastID. Neighborhood estrapola la ''Gee.List<NeighborhoodNodeID> whole_node_broadcast_set''. . In questo caso anche ''source_id'' è un WholeNodeSourceID. Neighborhood estrapola il ''NeighborhoodNodeID whole_node_source_id''. . Se ''whole_node_broadcast_set'' contiene il NeighborhoodNodeID del nodo corrente, se inoltre è stato formato un arco con ''whole_node_source_id'', se infine tale arco è stato formato proprio su ''dev'' con ''peer_address'' allora va restituita una lista con l'istanza ''node_skeleton''. Altrimenti lista vuota. |
* '''caso b.''' ''broadcast_id'' è un WholeNodeBroadcastID. . In questo caso ''source_id'' deve essere un WholeNodeSourceID. Altrimenti restituisce subito lista vuota. . Neighborhood estrapola da ''broadcast_id'' la ''Gee.List<NeighborhoodNodeID> whole_node_broadcast_set''. Se non è possibile, restituisce subito lista vuota. . Neighborhood estrapola da ''source_id'' il ''NeighborhoodNodeID whole_node_source_id''. Se non è possibile, restituisce subito lista vuota. . Se ''whole_node_broadcast_set'' contiene il NeighborhoodNodeID del nodo corrente, se inoltre l'arco reale ''i'' è stato formato proprio con ''whole_node_source_id'', allora va restituita una lista con l'istanza ''node_skeleton''. Altrimenti lista vuota. |
Modulo Neighborhood - Chiamate Lato Server
Contents
In questo documento vediamo passo passo come una applicazione debba usare il modulo Neighborhood per gestire gli aspetti "lato server" delle chiamate a metodi remoti.
Applicazione basata su MOD-RPC prodotta con "rpcdesign"
Supponiamo che con il tool rpcdesign abbiamo prodotto una libreria di livello intermedio (MOD-RPC) con le classi nel namespace "Netsukuku" che fornisce il root-dispatcher "AddressManager addr". Come sappiamo MOD-RPC si appoggia sulla libreria ZCD.
Poi viene costruita una APP che si appoggia su MOD-RPC. La APP contiene al suo interno il modulo Neighborhood.
La APP avvia sia un listener TCP sia uno UDP con i metodi della libreria MOD-RPC. Essi si avviano in una tasklet e richiamano i relativi listener della libreria ZCD.
Individuare il (o i) corretto root-dispatcher da invocare
Un messaggio viene recepito da uno dei listener nella libreria ZCD.
ZCD prepara un zcd.CallerInfo e chiama un metodo di un delegato fornito da MOD-RPC.
MOD-RPC prepara un Netsukuku.CallerInfo, che può essere una istanza di:
caso 1. TcpclientCallerInfo.
caso 2. UnicastCallerInfo.
caso 3. BroadcastCallerInfo.
Poi MOD-RPC chiama un metodo (get_addr_set) di un delegato Netsukuku.IRpcDelegate, la cui implementazione è fornita dalla APP.
La APP in questo metodo scompone il CallerInfo in:
caso 1. Una stringa peer_address, una stringa my_address, una istanza di ISourceID source_id e una istanza di IUnicastID unicast_id.
caso 2. Una stringa peer_address, una stringa dev, una istanza di ISourceID source_id e una istanza di IUnicastID unicast_id.
caso 3. Una stringa peer_address, una stringa dev, una istanza di ISourceID source_id e una istanza di IBroadcastID broadcast_id.
Poi la APP a seconda dei casi:
caso 1. Prepara una lista vuota di IAddressManagerSkeleton.
Chiama Neighborhood.get_dispatcher(source_id, unicast_id, peer_address, null). Se questo restituisce una istanza la aggiunge alla lista.
- Restituisce la lista.
caso 2. Prepara una lista vuota di IAddressManagerSkeleton.
Chiama Neighborhood.get_dispatcher(source_id, unicast_id, peer_address, dev). Se questo restituisce una istanza la aggiunge alla lista.
- Restituisce la lista.
caso 3. Restituisce la lista di IAddressManagerSkeleton ottenuta con la chiamata Neighborhood.get_dispatcher_set(source_id, broadcast_id, peer_address, dev).
Infine MOD-RPC riceve un set (forse vuoto) di root-dispatcher su cui invocare un metodo remoto. Sa come proseguire.
Vediamo cosa è avvenuto nel metodo chiamato sul modulo Neighborhood.
Nel caso del metodo IAddressManagerSkeleton? get_dispatcher(ISourceID source_id, IUnicastID unicast_id, string peer_address, string? dev):
caso 0. unicast_id è un NoArcWholeNodeUnicastID. In questo particolare caso, l'oggetto contiene il NeighborhoodNodeID e il MAC address del destinatario; bisogna verificare che il NeighborhoodNodeID sia il nostro e che il MAC corrisponda all'interfaccia indicata da dev, che in questo caso deve essere valorizzato. Se questi requisiti sono soddisfatti va restituita l'istanza node_skeleton. Altrimenti null.
caso a. unicast_id è un IdentityAwareUnicastID.
In questo caso source_id deve essere un IdentityAwareSourceID. Altrimenti restituisce subito null.
In questo caso dev non deve essere valorizzato. Altrimenti restituisce subito null.
Neighborhood estrapola da unicast_id il NodeID identity_aware_unicast_id. Se non è possibile, restituisce subito null.
Neighborhood estrapola da source_id il NodeID identity_aware_source_id. Se non è possibile, restituisce subito null.
Chiama il metodo get_identity_skeleton(identity_aware_source_id, identity_aware_unicast_id, peer_address) che gli è stato fornito dal suo utilizzatore.
L'utilizzatore del modulo, che conosce le identità del nodo e gli archi-identità che li collegano ad altri nodi, restituisce, se esiste, lo skeleton relativo alla identità identity_aware_unicast_id, ma solo se questa è collegata tramite un arco-identità alla identità identity_aware_source_id. Inoltre deve trattarsi di un arco-identità che si appoggia all'arco reale formato con peer_address. Altrimenti null.
caso b. unicast_id è un WholeNodeUnicastID.
In questo caso source_id deve essere un WholeNodeSourceID. Altrimenti restituisce subito null.
In questo caso dev non deve essere valorizzato. Altrimenti restituisce subito null.
Neighborhood estrapola da source_id il NeighborhoodNodeID whole_node_source_id. Se non è possibile, restituisce subito null.
Per gestire le chiamate ai moduli di nodo, l'utilizzatore ha inizialmente fornito al modulo Neighborhood l'istanza node_skeleton. Infatti il modulo Neighborhood è autonomamente in grado di decidere se restituire o meno quella istanza nel suo metodo get_dispatcher.
Se è stato formato un arco con whole_node_source_id, se infine tale arco riporta come indirizzo IP peer_address allora va restituita l'istanza node_skeleton. Altrimenti null.
Nel caso del metodo Gee.List<IAddressManagerSkeleton> get_dispatcher_set(ISourceID source_id, IBroadcastID broadcast_id, string peer_address, string dev):
caso 0. broadcast_id è un EveryWholeNodeBroadcastID. In questo particolare caso, qualsiasi sia l'interfaccia da cui riceve il messaggio e i dati di provenienza, il nodo deve ricevere una lista con l'istanza node_skeleton. Tale skeleton sarà certamente usato per un metodo remoto sul modulo Neighborhood.
Se non è il caso 0, subito controlla che esista un arco reale i formato su dev con peer_address. Altrimenti restituisce subito una lista vuota.
caso a. broadcast_id è un IdentityAwareBroadcastID.
In questo caso source_id deve essere un IdentityAwareSourceID. Altrimenti restituisce subito lista vuota.
Neighborhood estrapola da broadcast_id la Gee.List<NodeID> identity_aware_broadcast_set. Se non è possibile, restituisce subito lista vuota.
Neighborhood estrapola da source_id il NodeID identity_aware_source_id. Se non è possibile, restituisce subito lista vuota.
Chiama il metodo get_identity_skeleton_set(identity_aware_source_id, identity_aware_broadcast_set, peer_address, dev) che gli è stato fornito dal suo utilizzatore.
L'utilizzatore del modulo restituisce una lista con gli skeleton relativi alle sue identità che sono incluse in identity_aware_broadcast_set, ma solo quelle che sono collegate tramite un arco-identità alla identità identity_aware_source_id e tale arco-identità si appoggia all'arco reale formato su dev con peer_address.
caso b. broadcast_id è un WholeNodeBroadcastID.
In questo caso source_id deve essere un WholeNodeSourceID. Altrimenti restituisce subito lista vuota.
Neighborhood estrapola da broadcast_id la Gee.List<NeighborhoodNodeID> whole_node_broadcast_set. Se non è possibile, restituisce subito lista vuota.
Neighborhood estrapola da source_id il NeighborhoodNodeID whole_node_source_id. Se non è possibile, restituisce subito lista vuota.
Se whole_node_broadcast_set contiene il NeighborhoodNodeID del nodo corrente, se inoltre l'arco reale i è stato formato proprio con whole_node_source_id, allora va restituita una lista con l'istanza node_skeleton. Altrimenti lista vuota.
Interpretare l'arco da cui arriva la chiamata
Ora vediamo come l'implementatore dello skeleton, fornito dalla APP, nel metodo remoto che è stato invocato è in grado di interpretare l'oggetto CallerInfo, sempre avvalendosi del modulo Neighborhood, per individuare l'arco (arco-nodo o arco-identità) da cui ha ricevuto il messaggio. Questa operazione ha senso solo se il metodo remoto sa di essere stato invocato da un diretto vicino.
Il modulo che implementa il metodo remoto chiamato, passa il CallerInfo all'utilizzatore del modulo, che è anche l'utilizzatore del modulo Neighborhood. Questi è in grado di scomporre il CallerInfo in un ISourceID source_id e una stringa my_address o dev. Se la chiamata è arrivata con il protocollo TCP abbiamo la stringa my_address la quale (almeno per i metodi remoti chiamati sui diretti vicini) è sempre l'indirizzo di scheda assegnato dal modulo Neighborhood all'interfaccia di rete reale. In base alle sue conoscenze l'utilizzatore del modulo Neighborhood è in grado di associare alla stringa my_address una univoca stringa dev.
Se il modulo interessato è un modulo di nodo, l'utilizzatore chiama il metodo di Neighborhood get_node_arc(source_id, dev). Se il metodo get_node_arc restituisce un INeighborhoodArc, l'utilizzatore è poi in grado di associarlo ad un oggetto che il modulo interessato conosce come arco-nodo.
Se il metodo get_node_arc restituisce null, anche l'utilizzatore restituirà null. In teoria questo caso si può verificare solo se un arco-nodo prima valido (altrimenti il metodo remoto non doveva essere affatto invocato) è stato rimosso pochi istanti prima. In questo caso l'esecuzione del metodo andrebbe "probabilmente" interrotta, ma questo è di pertinenza del codice che implementa il metodo remoto.
Se il modulo interessato è un modulo di identità, allora il modulo ha passato all'utilizzatore del modulo Neighborhood anche la sua istanza. In questo modo questi sa individuare quale sia il NodeID dell'identità del nodo corrente interessata, chiamiamola identity_aware_my_id. Poi l'utilizzatore chiama il metodo di Neighborhood get_identity(source_id) e ottiene il NodeID dell'identità del mittente, chiamiamola identity_aware_peer_id. Avendo anche il nome dell'interfaccia di rete reale su cui è arrivato il messaggio, con le sue associazioni l'utilizzatore del modulo Neighborhood è in grado di identificare un oggetto (ad esempio un IQspnArc) che il modulo interessato conosce come arco-identità.
Se un arco-identità prima valido (altrimenti il metodo remoto non doveva essere affatto invocato) è stato rimosso pochi istanti prima, adesso l'utilizzatore del modulo non lo trova nelle sue associazioni e restituisce null. In questo caso l'esecuzione del metodo andrebbe "probabilmente" interrotta, ma questo è di pertinenza del codice che implementa il metodo remoto.