- Tabelle standard: Tabella server: SERVER(PK) - PORTA - NETWORK - NICKNAME - PASSWORD - Idea: si selezionano tutti i network e un server alla volta si tenta di connettersia quella network. Se c'è una password ci si identifica al nickserv con quella password per quella rete (ev. ghost eccetera) Tabella canali: NETWORK(PK) - CANALE(PK) - (PASSWORD?) - OP Una volta connessi ad una network si entra in tutti i canali specificati per quella network,eventualmente fornendo una password per entrare. Se AUTOOP è a vero e ci si e' identificati per quella rete allora si chiede a chanserv di oppare su quel canale. Tabella moduli: MODULO(PK) Tabella moduli attivi: ID(PK) - NETWORK - MODULO Tabella moduli attivi sui canali: ID (PK) - NETWORK - CANALE - MODULO Indicano quali moduli (.pm? non c'è bisogno di dynaloader!) sono disponibili, e quali sono da attivare per ciascun canale. Se un modulo viene attivato viene inserito nell'apposita tabella, se viene disattivato viene rimosso da questa tabella. Il tutto anche a runtime. I moduli relativi a canali (quote, log, ...) vengono messi anche loro nella loro tabella. Ciascun modulo ha poi la sua tabella con le sue cose. Evitiamo di mischiare quante piu' cose possibile. Queste due tabelle servono al core per fornire l'oggetto di connessione. ---------- - File di configurazione contenente: -> DB Server (host, user, password, tipo) -> PID File del processo principale -> $sarcazzi ---------- - Struttura: Si avvia il processo principale, che legge il file di configurazione (do $config?) e controlla il PID (ps + /proc/$pid/cmdline). Se e` tutto a posto fa le seguenti cose: 1) connettersi al db server (o muore, così il problema della conn. al db si leva SUBITO di mezzo) 2) prendere la lista dei moduli e avviare un metodo di "inizializzazione" per ogni modulo (evitiamo scherzetti a runtime nei figli, e magari fa utile per qualche modulo tipo logging) 3) prendere la lista dei server con una query per network 4) creare un oggetto "connessione" con dentro - lista dei server:porte - nickname - password - (network?) 5) forkare e dare al figlio l'oggetto connessione e i dati del db (oggetto db?) 6) scriversi il PID del figlio da qualche parte 7) ripetere tutto dal punto 2 finchè non ha fatto tanti figli quanti networks A questo punto non muore ma rimane in attesa della eventuale morte dei figli. SIGCHLD non deve essere ignorato ma gestito, e lo stato di uscita dei figli deve essere usato per propagare errori o schifezze simili. In altre parole, se per esempio un figlio muore perchè non riesce a connettersi o viene ucciso dal server, esce con un certo stato per cui il padre non muore - e nemmeno gli altri "fratelli" connessi ad altre network! Se invece un admin dice a un figlio di buttare giu' tutto allora il figlio esce con un codice particolare, il padre lo vede e uccide tutti gli altri suoi figli, e così via, in modo da uccidere tutti e far uscire tutti. A questo punto la struttura dei processi è: orazio(padre) |--oraziuccio (con l'oggetto "connessione al network 1") |--oraziuccio .................................... 2 +--oraziuccio .................................... N Ciascun figlio invoca un metodo dell'oggetto connessione il quale farà connettere ogni figlio al suo network, e lo identifichera` al nickserv, in maniera trasparente per il figlio stesso. Se il metodo uscirà positivamente, la connessione è andata a buon fine, altrimenti no (server giu', auth non riuscita, ecc.). A questo punto ciascun figlio avrà il suo oggetto (connesso), sul quale invocherà un metodo di lettura read(), il quale restituirà ogni linea di input da parte del server FORMATTATA OPPORTUNAMENTE, per.es. infilata in un hash. :peppe!~pippo@telecaz.it PRIVMSG #porcodio :ehi scemo di un bot!\r\n verrà infilata in qualcosa tipo %hash = { "type" => 0 "nick" => "peppe", "ident" => "~pippo", "host" => "pappo", "command" => "PRIVMSG", "dest" => "#porcodio", "params" => "ehi scemo di un bot!" ... } direttamente dall'oggetto di connessione. "type" puo' essere usato per distinguere righe da parte di utenti da righe da parte del server, chessò. Una volta ottenuto quest'hash, il figlio forka a sua volta (di nuovo, segnandosi il PID del figlio e non ignorando il SIGCHLD), dando al figlio l'hash e i dati del db(oggetto db?). Il figlio creerà una connessione al db e prenderà la lista dei moduli attivi e di quelli relativi al canale a cui e` diretto il messaggio (se è diretto a un canale). A questo punto per ogni modulo trovato eseguirà un certo metodo run() passando l'hash ottenuto e la connessione al db (non i parametri d'accesso). Ciascun modulo farà il suo lavoro, eventualmente usando altre tabelle o altre risorse (presenti o meno sul db di cui comunque ha la connessione aperta). L'esecuzione dei singoli metodi run() di ogni modulo puo' essere sequenziale o parallela, ma poi per TANTI moduli si rischia un fork bombing, considerando che comunque ogni blocco di run() dei moduli viene eseguita in un figlio separato non ci dovrebbero essere troppi problemi...