Il modulo microsock

Trasmissione dati tra due socket

La trasmissione di dati tra due socket connessi con il protocollo TCP avviene in Netsukuku con l'uso dei metodi send, sendall e recv. Per la precisione quando viene chiamato un metodo remoto (vedi Chiamate a metodi remoti):

Quando si richiama il metodo send di un microsock.dispatcher questo memorizza il messaggio da inviare in coda al buffer nel suo membro sendBuffer e fa subito ritorno al chiamante, segnalando di aver trasmesso tutti i bytes richiesti.
La presenza di dati in questo buffer fa sì che il metodo writable restituisca True. Questo a sua volta, come detto sopra, fa sì che asyncore.poll, periodicamente e solo quando la trasmissione non risulterebbe bloccante, richiami il metodo handle_write_event che a sua volta richiama handle_write overridato nella classe microsock.dispatcher.
Il metodo microsock.dispatcher.handle_write richiama il metodo asyncore.dispatcher.send sulla classe base, non più quello overridato. Questo effetua l'invio di un certo numero di bytes senza bloccare il processo e restituisce il numero di bytes trasmessi. Il metodo microsock.dispatcher.handle_write di seguito toglie dal buffer i bytes già inviati e fa ritorno.

Abbiamo detto che il metodo microsock.dispatcher.send fa subito ritorno segnalando la trasmissione di tutti i bytes richiesti. In realtà la trasmissione avviene in seguito.
Se si vuole essere sicuri che la trasmissione sia già avvenuta si chiama il metodo microsock.dispatcher.sendall. Questo metodo fa ritorno solo quando il buffer nel suo membro sendBuffer è completamente svuotato.
Per attendere questo evento effettua un loop in cui intervalla il test alla schedulazione degli altri microthread con micro_block. TODO: Il loop in questione è in effetti un busy-wait. C'è un qualche motivo per cui qui non aggiungiamo un time.sleep(0.001) ?

Per quanto riguarda la ricezione di dati, il metodo readable di un microsock.dispatcher, ereditato tal quale dalla asyncore.dispatcher, restituisce sempre True. Questo a sua volta, come detto sopra, fa sì che asyncore.poll, periodicamente e solo quando ci sono dei dati disponibili per la lettura, richiami il metodo handle_read_event che a sua volta richiama handle_read overridato nella classe microsock.dispatcher.
Il metodo microsock.dispatcher.handle_read richiama il metodo recv di asyncore.dispatcher, non quello overridato da microsock.dispatcher. Questo richiama il metodo recv sul socket reale che leggerà un massimo di maxreceivebuf bytes senza bloccarsi. Questi dati vengono inviati come messaggio sul Channel memorizzato sul membro recvChannel.
Siccome il Channel è stato istanziato con micro_send = True questa trasmissione sullo stackless.channel avviene in realtà su un altro microthread, lasciando così immediatamente libero di continuare il microthread che richiama periodicamente la asyncore.poll.
In questo modo si ottiene che i dati sono in attesa, senza bloccare gli altri microthread, di essere letti dallo pseudo socket.
Da notare che finora non abbiamo parlato del metodo recv overridato nella classe microsock.dispatcher. Infatti il meccanismo sopra descritto consente la lettura di un certo numero di bytes (quanto il valore corrente di maxreceivebuf) dal socket ogni qualvolta che siano presenti, anche se il microthread che sta "gestendo" l'oggetto stacklesssocket non sta al momento eseguendo una chiamata a recv. Da notare anche che il valore di maxreceivebuf cambia in base al valore della precedente chiamata al metodo recv della classe microsock.dispatcher, che non è detto che corrisponda alla attuale lettura -- apparentemente non era questo l'intento dello sviluppatore.
TODO: che senso ha un tale comportamento? Mi pare possa essere fonte di diverse problematiche. Perché non leggiamo dal socket solo dopo che è stato chiamato recv e al massimo un numero di bytes tali da soddisfare la chiamata?

Il metodo recv overridato nella classe microsock.dispatcher non fa altro che ricevere i dati dal Channel memorizzato sul membro recvChannel. Tutti i bytes che vi trova li mette nel buffer readBufferString. Poi ne restituisce al massimo quanti richiesti dal chiamante.
Per la precisione, prima di tutto il metodo guarda se nel buffer readBufferString ci sono già un numero di bytes da soddisfare del tutto il chiamante. Altrimenti si possono verificare 2 casi:

Alla fine, da quello che ha a disposizione sul buffer, rimuove e restituisce al chiamante al massimo n bytes, quanti richiesti.

La trasmissione di dati tra due socket connessi con il protocollo UDP in modalità broadcast avviene in Netsukuku con l'uso dei metodi sendto e recvfrom. Per la precisione quando viene chiamato un metodo remoto (vedi Chiamate a metodi remoti):