Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

Fase 1: El Nodo de Control

Última Actualización: 24 de Febrero de 2000 - Jueves

Aunque el objetivo final es implementar un esquema distribuido, para acelerar el nacimiento de la red se ha empezado por utilizar un esquema centralizado empleando las facilidades proporcionadas por los servidores IRCd de Undernet.

En estos momentos los nodos de control son:

  • OLIMPO: Este es el nodo principal de la red
  • ORACULO: Nodo secundario y de pruebas

Las operaciones que cubren esos nodos son:

  1. Control de clonos: La red sólo permite dos conexiones por IP
  2. Control de OP: Permite dar y quitar OP en los canales
  3. Control de las Bases de Datos Distribuidas: Puerta de entrada para las BDD de clonos, nicks, opers, IPs virtuales, etc.


Fase 2: Nodo Modular

Fase 3: Nodo Multitarea


Historia

  • 10/Ene/00 Versión 31

    • Añadido comando "dbdel", que borra una base de datos en un nodo determinado.

    • Añadido un script para dar de baja las I-Lines que ya no se utilizan, dado que Olimpo sólo las caduca cuando se realizan conexiones desde ellas. El script inicia una conexión a la red como "nodo", y va introduciendo usuarios cuya IP ha caducado ya, para que Olimpo los dé de baja en su base de datos y en la base de datos distribuída de clones de la red.

  • 07/Ene/00 Versión 30

    • Eliminado el "hack" necesario para adelantar la caducidad de los clones y que las ilines expirasen antes de nochebuena.

    • Un servidor "JUPE" se propaga con una distancia de 2, en vez de uno, porque está virtualmente detrás de Olimpo.

    • Olimpo responde a los "PING" de otros nodos de la red, ya que hay nodos que pueden usar esto para controlar el LAG. Añadir esta funcionalidad me dio trabajo porque la sintaxis del comando es diferente de lo normal. Es:
      :nodo_origen PING nodo_origen :nodo_destino
      :nodo_origen PONG nodo_origen nodo_destino

      Como ventaja adicional, también se responde a PING para aquellos servidores que están por detrás de nosotros (JUPE).

    • Se ha solucionado una divergencia entre stats y history, ya que cuando entraba un usuario nuevo se llamaba a la rutina de cálculo de históricos ANTES de haber incrementado el contador de usuarios.

    • Olimpo informa adecuadamente del fin de su burst, así como confirma el fin del burst de su uplink.

    • Añadido el comando DBQ, que sondea a toda la red sobre sus versiones de BDD. El parámetro de DBQ es la base de datos a sondear.

  • 15/Dic/99 Versión 29

    • Al activar las ilines, también se acepta el sufijo m (minutos).

    • Si entra un usuario cuyo permiso de clones ha caducado, borra ese permiso de clones y propaga una baja por la red.

    • Si una Iline tiene una expiración menor de 15 días, envía al usuario, cuando se conecta, un mensaje informándole de este hecho y urgiéndole a que renueve sus ilines.

    • Cuando se dá de alta una iline con una expiración de CERO (o negativa), se indica "sin expiración", no que expira en 1970.

    • Cuando se produce una expiración, guarda acta de ella en el log.

    • Intercepto las señales en las aplicaciones ilines_alta e ilines_lista para que si se corta su ejecución, no dejen bloqueada la base de datos.

    • Me hago un par de scripts para sacar los clones que se están empleando en un momento dado, a partir de un volcado de la base de datos "online" de Olimpo.

  • 01/Dic/99 Versión 28

    Esta versión ha estado funcionando durante 13 días sin problemas, mientras se desplegaba la pasarela de pagos y las páginas de información sobre la contratación de clones.

  • 01/Dic/99 Versión 27

    • Intercepto un buen número de señales en Olimpo, intentando que si llega alguna el proceso pueda terminar de forma ordenada.

      No implemento esa funcionalidad en el resto de herramientas porque en cuanto se puedan gestionar los clones directamente online, sobrarán o se utilizarán muy de vez en cuando.

      De todas formas, si se queda algún bloqueo perdido por ahí, lo más sencillo es parar todos los procesos y borrar las cachés "__db.xxx". Claro que, como no estamos trabajando con transacciones, todo lo que podemos hacer es rezar para que la base de datos no se haya corrompido.

      También se puede utilizar la herramienta db_recover, que se supone que hace esto mismo y tiene en cuenta la posible existencia de transacciones, etc.

    • Como medida de seguridad, necesitamos un resguardo de todas las operaciones realizadas sobre la base de datos (al menos las operaciones que nos interesen) en ASCII. Podemos utilizar sencillamente el archivo de logs de acceso al servidor, como último recurso.

    • A veces Olimpo tarda unos segundos en resolver el nombre de su peer. Imprimimos un mensaje para que, al menos, sepamos que no se ha colgado.

    • ¡¡¡Ya se pueden dar de alta y de baja ilines!!!.

      Quedan por pulir muchos detalles, eso sí.

    • El alta de ilines ya imprime los nonce.

    • La baja también muestra el nonce, como última palabra de la cadena de entrada.

    • Si el último carácter del tiempo de expiración es una "d" considera que la expiración es en días desde el instante actual. Si no, la expiración son segundos desde 1970 (epoch).

  • 01/Dic/99 Versión 26

    Inicio una migración a DB como sustituto a la GDBM.

    • El primer paso es descargar la última versión de la librería (3.0.55).

    • Reescribo los programas de apoyo para utilizar la nueva librería.

      Para poder enlazarla tengo que hacer equilibrios en el Makefile.

      Los programas mueren al hacer open sobre la base de datos. No me sirve de nada el estudiar programas antiguos como sendmail porque emplean la interfaz antigua. Prácticamente copiando los ejemplos del manual tampoco llego a nada.

      Tras varias horas de investigar el tema, estudiar el funcionamiento interno de la librería DB, etc, encuentro por fin el problema: El GCC 2.95.2 genera stores de 64bits cuando se invoca memset, y UltraSparc I requiere que dichos accesos estén alineados a 64 bits. No obstante la librería sólo los alinea a 32 bits.

      El problema es del compilador (o de su librería estándar) ya que si, por ejemplo, estamos trabajando con cadenas con alineamiento arbitrario, un memset puede matar el programa por problemas de alineamiento.

      Haciendo pruebas en mis propios programas veo que típicamente memset es una invocación de una rutina externa. Sólo se generan este tipo de movimientos de datos cuando el tipo de datos al que apunta el puntero se alinea de forma natural a 64bits (por ejemplo, estructuras).

      Informo del asunto a los autores de la librería DB y en la lista de correo del GCC/EGCS.

    • Con mi parche las cosas parece que ya funcionan... Pero no puedo crear subbases de datos dentro de un único fichero. El error que me sale es muy raro: "not owner", siendo una base de datos de nueva creación. Si no defino un environment, funciona a la perfección. Obviamente tengo que configurar algo en el environment, pero no veo nada que sea obvio. El problema es que si no uso environment me quedo sin cosas como los interbloqueos. De momento, entonces, me voy a olvidar del tema del subbases de datos.

    • Ahora el problema es la utilidad de listado; devuelve un par de registros y da un error de "Not enough space", previa impresión de un registro con contenido pero con una clave que empieza en cero (aunque no mide cero bytes).

      Vaya... No debemos hacer free del contenido de clave y contenido, al contrario que pasa con GDBM. Eso es configurable. Le paso la rutina "malloc()" del resto de la aplicación, y le digo que queremos hacer gestión explícita de memoria.

    • Migro la gestión de memoria al proceso que introduce registros en la base de datos.

    • Cierro también el environment cuando termino de usar una base de datos y no voy a usar otra. ARGGG!!!!. El hacer eso me mata el servidor. Por tanto, mantengo el environment abierto constantemente, aunque se cierre su base de datos.

  • 30/Nov/99 Versión 25

    • Olimpo propaga un "SETTIME" cada vez que entra un nuevo nodo en la red, pero sólo si es un J10, no un P10.

    • En modo "develop" no debe guardarse la lista de clones que van entrando. Esto ya estaba programado, pero se ha cambiado el código para ser más claro.

    • Coge el número de clones por defecto de la base de datos GDBM, no de un valor estático en tiempo de compilación.

    • Los comandos nickregister, nickforbid y nickdrop son de uso exclusivo mío.

    • Si un IRCop o un helper invocan un comando para el que no tienen privilegios, les sale un mensaje de aviso. A un usuario normal no le sale nada, para evitar ataques.

    • En un servidor Olimpo compilado sin soporte de BDD de nicks, los comandos asociados no aparecían en la ayuda, pero podían ser invocados.

    • Definido soporte de I-lines en tiempo de compilación, mediante ALLOW_ILINE_REGISTRATION.

    • Por alguna razón desconocida, un gdbm_delete borra el registro, pero en cuanto se cierra la base de datos vuelve a existir, aunque la base de datos se ha abierto claramente como SYNC, que se supone compromete los cambios a disco inmediatamente.

      Uso la herramienta truss y compruebo que la base de datos se va leyendo en memoria a medida que se va accediendo a ella, sin usar mmap. A medida que se va leyendo, lo único que queda visible son los bloqueos sobre el fichero. La duda ahora es... Si la base de datos no se cierra, ¿cómo se tiene acceso a las actualizaciones de otros programas sobre ella?.

      La respuesta es, parece ser, ninguna.

      Por lo que se ve, debe realizarse caching de la apertura de la base de datos, ya que cualquier registro leído no se sincroniza con lo que puedan estar haciendo otros procesos. Podría ser debido al acceso de escritura en la base de datos, ya que se supone que es exclusivo, aunque con la nueva versión de la librería ya no tiene por qué ser así. Si un proceso de escritura tiene acceso exclusivo a la base de datos, el hacer caching de los registros que se leen es correcto, ya que no pueden ser modificados a menos que se cierre primero la base de datos.

      La solución parece ser, por tanto, el abrir y cerrar la base de datos en cada acceso, con la consiguiente sobrecarga (un sistema operativo decente no debería tener mucha sobrecarga, ya que se usa la memoria como caché de disco).

      No obstante esto no explica el hecho de que un proceso haga una modificación en un registro, y que dicha modificación se "pierda" cuando se mata el proceso... A menos que el no cerrar la base de datos COMPLETAMENTE mediante gdbm_close intente dejarla en un estado consistente, deshaciendo posibles cambios. Pero no, porque todos los cambios se comprometen a disco, y cuando se mata el programa se guarda el "profiling" y nada más.

      Estudio someramente el código de la librería gdbm y parece que estoy en lo cierto respecto al caching. Pero sigue sin explicarse el que se "deshagan los cambios".

      De momento voy a quitar el caching de apertura de la base de datos, para que cada nueva consulta sea una nueva sesión. Ello debería eliminar el caching de registros leídos, aún a costa de perder eficiencia.

      Eliminar este caching de sesiones supone una carga inmensa en el servidor, sobre todo cuando el servidor se conecta a la red.

      De todas formas sin el caching parece que todo va bien (aunque muy lento). Los registros se borran a la primera y permanecen aún cuando se abandona el programa.

      La más inteligente parece el mantener el sistema de caching, pero canalizar todas las peticiones a esa base de datos a través de un único descriptor. Ello supone crear un módulo aparte, de gestión GDBM.

      Como prueba de concepto sencillamente voy a abrir una sesión global a nivel de un proceso.

      Bien, ahora cuando borro un registro, la siguiente búsqueda mata el servidor con una excepción, en al siguiente búsqueda de iline. Como solución de compromiso, cuando realizo un borrado, cierro la base de datos y la vuelvo a abrir.

      Era un error de programación, pero lo dejo así de todas maneras, que parece más "coherente".

      A pesar de todos estos cambios, parece que sigue fallando de vez en cuando, sobre todo porque dice que ha borrado y no lo ha borrado aún, etc.

    • Por lo que parece, la forma "buena" de hacerlo es emplear la librería DB.

  • 30/Nov/99 Versión 24

    • Ya no lee el archivo "ilines.db" al arrancar el programa (o al hacer un "reload"), ya que ahora trabaja con una GDBM.

    • Se elimina dicha información del volcado de la base de datos interna, ya que ahora no existe.

    • Eliminado el comando "ilines", que ya no tiene sentido, sobre todo porque esa información está disponible en todos y cada uno de los servidores de la red usando el comando "dbq".

    • En el comando "stats" ya no se lista información sobre las ilines.

    • Tras 12 horas de funcionamiento del sistema, ilines_lista falla porque no es capaz de encontrar una clave. Da la impresión de que se corrompe la base de datos. Por otra parte, la dirección en la que falla es una de las que se encuentran duplicadas en nuestro archivo de ilines (hay dos docenas de IPs duplicadas). Podría tener algo que ver.

      Regenerando el fichero de ilines de nuevo soluciona el problema pero, obviamente, no es solución, sobre todo si algún día vamos a pasar del archivo de texto en plan "backup".

      Lo más extraño es que la clave que devuelve un "nextkey" mide 22 bytes, cuando la cadena mide sólo 19 (incluyendo el '\0'). Pero el problema no es ese, sino que al hacer un "fetch" de dicha clave, no la encuentra, ¡¡y nos la acaba de dar en "nextkey"!!.

      Si vuelve a ocurrir, habrá que blindar "ilines_lista" para que simplemente se salte estas claves problemáticas. Con suerte aparecerán dos registos; uno con la clave correcta y otro con la clave correcta.

    • En el comando "stats" se visualiza también el estado de la base de datos de clones.

    • Lee el archivo histórico sólo cuando se arranca Olimpo, no cada vez que el servidor se une a la red.

    • Cada vez que Olimpo se une a la red, resetea los contadores de las bases de datos distribuídas, ya que tomará sus nuevos valores de la red.

    • Olimpo toma como referencia de contadores de las bases de datos tanto lo que le llega por la red cuando se produce el join como lo que él mismo lee cuando propaga bases de datos nuevas.

    • Para evitar propagar información incorrecta si alguna base de datos se corrompe, Olimpo fuerza a que los registros que se propagan se correspondan a la base de datos que se está leyendo en cada momento, independientemente del contenido del propio fichero.

    • Aunque sólo se visualizan las bases de datos de nicks y de ilines, Olimpo lleva el control de TODAS ellas.

    • Olimpo actualiza correctamente sus contadores de bases de datos cuando ve un nuevo registro por la red.

  • 29/Nov/99 Versión 23

    • Definimos privilegios de acceso potencialmente diferentes comando por comando. De esta forma será posible que un helper tenga acceso a determinados comandos, y de que sólo algunos usuarios concretos, no todos los IRCops, tengan acceso al sistema de altas de clones, por ejemplo.

    • Definimos un modo "develop", en la que el servidor no almacena NADA en ningún fichero, ni realiza los KILLs por clones. De esta forma podemos realizar modificaciones y depuraciones pudiendo convivir perfectamente con el servidor en servicio.

      Definir el símbolo "DEVELOP" al compilar el código, supone:

      • No se envía el contenido de "squit.raw" cuando se produce un split.

      • No se matan conexiones por superar sus límites de clones. Por tanto, tampoco se guardan los kills, que no se producen, en disco.

      • No se almacenan en disco los archivos históricos.

      • se almacena en disco los logs de acceso al servidor, se leen los archivos históricos, se leen las ilines y se propagan las bases de datos cuando se produce el join. También se realiza un volcado de las Bases de Datos internas si así se solicita. Asimismo, se actualiza la información de última conexión para los clones, posible gracias a mecanismos de arbitraje de acceso a la BD.

    • Se trabaja con una base de datos GDBM en disco para gestionar los clones. El formato de dicha BD es el siguiente:

      • clave: La IP directa o inversa, incluyendo el '\0' final.

      • contenido:

        • 4 bytes en formato red, con la fecha de alta del registro.

        • 4 bytes en formato red, con la fecha de expiración del registro.

        • 4 bytes en formato red, con la fecha de último acceso a ese registro.

        • Una cadena en formato libre conteniendo un texto arbitrario, con el '\0' final. La cadena debe empezar con un número, que será el número de clones permitidos para esa IP.

    • Mantengo la base de datos de clones abierta constantemente, para evitar la carga que supone el abrirla y cerrarla todo el rato (importante en caso de join). El arbitraje de acceso se realiza mediante llamadas fcntl, para bloquear el fichero de forma rápida y temporal.

    • Corregido un bug en la grabación del archivo histórico cuando se recargaba una versión vieja. Ese error podría dejar al programa en un bucle infinito.

    • Corregido un bug en la lectura del archivo histórico, si existían varias líneas referidas al mismo intervalo temporal (minuto). Ello es posible si se para y arranca Olimpo varias veces durante un intervalo de tiempo muy corto. Este error dejaba a Olimpo en un bucle infinito.

  • 05/Nov/99 Versión 22

    • Para dar una imagen homogenea, utilizo el programa "indent".

    • Amplío el búffer histórico de 7 a 10 días.

    • Sisco me pide que muestre también, hora a hora y durante 7 días a la semana (mínimo), el número de conexiones que se producen, no el número máximo de usuarios simultaneos. Lo programo para 10 días.

    • Almaceno los datos de conexiones en disco, para poder visualizarlos luego con otros paquetes. Se guarda un registro por minuto: fecha ascii del pico de usuarios dentro de ese minuto, timestamp de ese instante, valor de pico de usuarios y número de conexiones en la red. Las dos informaciones de tiempo son equivalentes, pero una es para uso humano y la otra es para que la usen programas, como el propio Olimpo.

    • Cuando Olimpo arranca, recupera el archivo histórico de disco, teniendo en cuenta lo siguiente:

      • Si hay huecos entre registros (caída prolongada del servicio), mantiene esos huecos en el histórico interno, para no falsear los datos que proporciona en history.

      • En stats se indica el pico de usuarios y su fecha, pero la información de conexiones se empieza a contar desde el inicio de Olimpo, a pesar de que en history tengamos 10 días de históricos.

      La gran ventaja de este esquema es que se puede modificar Olimpo y lanzarlo de nuevo, sin perder los informes históricos.

    • Parece que la tabla histórica sobreestima el número de conexiones en la red. Analicemos un poco la situación...

      El problema es que estábamos contando como conexiones nuevas también los cambios de nicks y los cambios de modos de usuario. Solucionado. Ahora los dos contadores de conexiones deberían coincidir.

    • La última revisión de Olimpo contabiliza también como conexiones aquellas que van a ser rechazadas por superar el límite de clones asignado a su IP.

  • 26/Oct/99 Versión 21

    • Creo un script que actualiza una Base de Datos en el mismo formato que usa el propio servidor de IRC. Los datos los obtiene de las modificaciones en el fichero de texto ilines.db, ejecutando el script ilines.

    • Cuando el servidor establece una conexión o se realiza un reload, manda todas las Bases de Datos enteras al otro extremo de la conexión. El otro extremo se encargará ya de ignorar los registros con número de serie inferior al suyo propio.

    • Añado un sistema de control de versiones en los fuentes, coordinado por CVS.

    • Olimpo controla el número de usuarios conectados simultaneamente a la red, en todo momento, así como su valor (e instante) de pico.

    • Olimpo no empezaba a contar los usuarios desde cero cuando se cortaba el enlace con su HUB (aunque sí cuando el split era de cualquier otro nodo).

    • Añado el comando history, que proporciona picos de conexiones simultaneas de usuarios en bloques de 24 horas (una semana en total), usando el valor máximo de cada grupo de 24 horas.

    • Corrijo un bug en la recolección de datos históricos. Se recogían datos a cada conexión, no minuto a minuto.

    • Si transcurre más de un minuto entre dos conexiones sucesivas, los intervalos de 24 horas van derivando poco a poco (aunque siguen siendo correctas).

  • 14/Oct/99 Versión 20

    • Cuando se listan los usuarios con el comando users, al lado de cada nodo aparece su número de nodo.

    • El recolector de entropía de la red sólo recogía 32 bits de entropía. Ahora recoge 64 bits, como debe ser. El problema estaba en la rotación de un número con signo. Se pasa a unsigned y se obtienen los 64 bits de entropía deseados.

    • Se añaden los parámetros de compilación VERBOSE_CLONES, que lista por pantalla las conexiones con clones, a medida que se producen, y VERBOSE_CLONES_KILL, que lista los KILLs que genera Olimpo.

    • En config.h se añaden los posibles defines LOG_CLONES y LOG_CLONES_KILL.

    • Los nicks que empiezan por ":" dan problemas, y no son nicks válidos. Olimpo sencillamente los ignora. No se aceptan nicks que empiecen por ":", tabulador, espacio o comillas.

    • Por petición popular, nickregister permite especificar una clave no aleatoria. Actualización de su ayuda.

    • Por petición popular, nickregister acepta también claves ya cifradas, si miden exactamente 13 caracteres y el primer carácter es ":". Actualización de su ayuda.

  • 26/Jul/99 Versión 19

    • Se puede hacer "Jupe" aunque no se tenga U-line en la red.

    • Corregido un bug que mataba a Olimpo cuando se ejecutaba un "jupe". Fue introducido al cambiar el sistema de base de datos. Este comando no fue probado en su momento.

    • Cuando se solicita un listado de I-lines, si nos pasamos de una longitud máxima, corta el listado y avisa del "flood". Configurable en config.h.

    • Aunque Olimpo ya resincroniza la red cada 4 horas o cuando conecta, he añadido un comando "settime" para que pueda hacerse en cualquier momento, sin tener que esperar al timeout de 4 horas y sin hacerle un "squit".

    • Se añade el comando "users", que indica cuántos usuarios están conectados en la red, así como su distribución por nodos.

    • Implementación de nicks equivalentes, usando la tabla "tolower" del propio servidor IRC.

    • Mejorada la compilación mediante una reestructuración del fichero Makefile. Ahora se gestionan dependencias de forma automática, etc. La generación de dependencias implica que el conpilador debe rastrear los fuentes con los "-D", etc., correctos.

    • Se ha añadido el comando "nickregister", gracias al cual es posible registrar un usuario en la base de datos distribuída. Esta posibilidad está sujeta a un #define en config.h.

      A la hora de alimentar el generador de números aleatorios para generar las claves, se tiene en cuenta toda la entropía posible: todo lo que se va recibiendo por la red, la hora de cada comando recibido, etc. Todo eso se mezcla con la salida de un generador pseudoaleatorio, inicializado con la hora de lanzamiento del bot. Esa hora no es tiempo real, sino el resultado del "gethrtime()" que da el tiempo en nanosegundos, con una precisión de 64 bits.

      De esta forma el generador de números aleatorios conseguidos es de buena calidad. Al menos siempre que su invocación sea espaciada y la red tenga un tráfico elevado (situaciones ambas muy normales en una red de IRC).

    • Implementado el comando "nickforbid", que registra un nick con una clave aleatoria, la propaga con una marca distintiva y no te dice cuál es la clave :-).

    • Implementado el comando "nickdrop", que dá de baja un nick en la base de datos distribuída.

  • 14/Abr/99 Versión 18

    • Todos los comandos invocables por el usuario envían un mensaje de confirmación para que se sepa que han sido procesados.

    • Se implementa el comando "help".

    • Cuando se introduce un comando desconocido, se muestra una indicación de ello y los pasos a seguir para obtener ayuda.

    • Lo anterior se ha eliminado, ya que se producen bucles con "Nick", en los que un bot se manda al otro "Comando desconocido".

    • Hace log en "kill.log" cada vez que se realiza un Kill por clones. Ello permite realizar un análisis posterior para detectar proxies abiertos, cibercafés que superan sus clones, etc.

    • Cada vez que entra un usuario a través de una IP con permiso para clones, lo almacena en "clones.log". De esta forma podemos comprobar las I-Lines que se están utilizando. Si se han configurado 999 clones o más para esa IP, no se listan, ya que se supone que son IPs especiales.

  • 25/Mar/99 Versión 17

    • Se ha fijado un máximo en el valor de back-off admisible entre conexiones de dos minutos, ajustable en config.h.

    • Añadido el comando "reload", para recargar de disco las bases de datos internas (I-Lines) sin necesidad de provocar un squit.

    • Olimpo soporta el protocolo de base de datos distribuída. Durante el Join, Olimpo envía al otro lado del enlace un número de serie de la base de datos igual al que le llega, para que el HUB abra su flujo de DB hacia Olimpo, y así poder ver cambios en la base de datos de otros nodos. Olimpo no manda un "J" hasta que no lo recibe del otro extremo.

      • "B", "Q" y "q" se ignoran.
      • "J" toma nota del numero de serie remoto.
      • Cualquier otro registro iguala las versiones de la base de datos.

      Se amplía stats para que muestre la versión de la base de datos que existe en su HUB inmediato. Cuando el otro extremo no soporta base de datos distribuída, el valor es -1.

    • Posibilidad de proteger determinados Nicks si no acceden desde determinada IP. Para ello Olimpo:

      • Si hay un split en la red, cualquiera, introduce los nicks protegidos, con el TimeStamp superior al del services. De esta forma ocupa los nicks. Si los nicks están presentes o entran luego, ganará su TimeStamp.
      • Los nicks protegidos también se introducen en el Join inicial.
      • Si los nicks protegidos caen por Kill o Quit, Olimpo no hace nada.

      Los nicks a proteger se ponen en el fichero "squit.raw", siguiendo la sintáxis del protocolo P10 servidor-servidor, en cuanto a NICK. Las líneas del fichero se leen por orden y se envían al HUB tal cual, sin ningún procesado o interpretación. Ello implica, por tanto, que hay que tener cuidado con cosas como el inyectar nuevos usuarios a través de un número de nodo que no nos corresponde, o usar un NumNick en uso. Además, los comandos RAW pueden matar fácilmente el HUB.

      Dado que el fichero se lee cada vez que hay un Squit, hay que tener cuidado para que no haya un squit EN MEDIO de una modificación del fichero. Esto puede ser CATASTRóFICO.

      Para poder introducir nuevos NICKS he tenido que modificar la Numeric NickMask, pasando de "??" a "D]". Por lo que veo, este valor indica el máximo número de nicks que maneja un nodo, hasta un máximo de 4096. He configurado Olimpo para que soporte 1+64*3+63=256 nicks.

      Es importante que:

      • El contenido de squit.raw debe ser correcto, ya que va en ello la estabilidad de la red.
      • El TimeStamp inyectado debe ser superior al del service, pero inferior al tiempo de la red. Muy inferior.
      • Ojo con repetir el NumNick en diferentes nicks.
      • Para que gane el service, es necesario que el UserID y/o la IP sean diferentes entre sus usuarios y los introducidos por Olimpo.
      • Antes de enviar al usuario hay que enviar un quit para él, ya que si ya lo hemos introducido, la siguiente introducción lo mata por nick collide y se mueren ambos.

      Existe una ventana de desprotección de los nicks, en función del lag de la red. Es inevitable.

  • 24/Feb/99 Versión 16

    • Corregido un bug en la identificación de los mensajes dirigidos al nodo.

    • Corregido un bug en la identificación de los canales, a la hora de invocar comandos sobre ellos (por ejemplo, pasar OP usando a Olimpo).

    • Corregido un bug al detectar cambios de modo de un canal.

    • Se ha detectado un "bug" en los servidores de IRC que hace que el join de Olimpo a un canal puede provocar un desynch del mismo. Ya se ha advertido a los desarrolladores. Se ha sustituido el join por un create con el timestamp fijado a la fecha actual, para evitar quitar OP a los usuarios ya presentes en el canal.

    • Se han introducido los usuarios en una estructura HASH. De esta forma se elimina completamente la vieja estructura de datos lineal. El consumo de CPU medio se situaba en torno al 1.6%. Ahora debemos verificar que el consumo actual es mucho menor.

    • Se han definido también dos tablas auxiliares más. En total tenemos:

      • Nick Numérico -> Usuario
      • IP -> (nada)
      • Nick -> Nick Numérico

    • Se ha solucionado un bug que hacía que Olimpo no detectase la caída de la conexión si coincidía mientras estaba escribiendo.

    • Se ha incrementado el número de datos que se visualizan con un "stats": estado de las tablas Hash de usuarios.

    • Con los cambios hechos en las estructuras de memoria, se ha eliminado completamente el pool único (estructura de datos lineal), con la consiguiente necesidad de realizar recogidas de basuras. Todas las nuevas estructuras son estructuras HASH.

    • Se ha cambiado la sencilla rutina HASH que se estaba utilizando por la rutina empleada en ELF. Su distribución estadística es mucho mejor.

    • Mientras no se implementa la equivalencia de Nicks, se suponen equivalentes dos nicks si y sólo si tolower(nick1)=tolower(nick2).

  • 28/Ene/99 Versión 15

    • Añadido el comando "stats", que muestra diversas estadísticas: Usuarios, servidores, tiempo en servicio, CPU consumida, memoria ocupada y el tamaño y calidad de las diversas tablas hash.

    • Eliminado el comando "userstats", que ya está incluido en el anterior.

    • La lectura del socket se realiza ahora en bloques de 1024 bytes, en vez de realizarse de carácter en carácter. Ello reduce enormemente el consumo de CPU. Esta mejora es posible porque, aunque read es una llamada bloqueante, los servidores utilizan entre sí el flag Push al final de cada ráfaga, y el read regresa con lo que haya, sin esperar a llenar el buffer.

  • 28/Ene/99 Versión 14

    • Para no agotar la paciencia en el canal de operadores de la red, Olimpo no muestra la información de recogida de basuras en el canal.

    • La rutina de hashing se ha hecho genérica para que pueda realizar el hashing de cualquiera de los campos del registro que le pasamos. El campo a procesar es uno de los parámetros.

    • Las listas se han hecho iguales para todo tipo de registros, de forma que su manipulación sea independiente del tipo de contenido que almacenen.

    • Se ha añadido la posibilidad de borrar registros hash, como primer paso para utilizar dichas estructuras de forma general.

    • Se ha movido la estructura de servidores a una tabla hash de 16 elementos. Este cambio supone numerosísimas modificaciones en el código.

  • 21/Ene/99 Versión 13

    • Añadido algo de colorido en los mensajes generados por el bot.

    • En vez de llamar a time() en cada carácter leído, se lee en cada línea que se recibe. Esa llamada era responsable del 11.19% de CPU consumida. Ahora sólo ocupa el 0.2%.

    • Genera unos logs con un registro por línea, en vez de un registro en tres líneas.

    • Un /links muestra ahora también la fecha de esta versión del bot.

    • Añadida una rutina para borrar la base de datos, para mejorar el encapsulamiento de datos.

    • Las rutinas de recorrido de la base de datos aceptan NULL como "Empieza desde el principio".

    • Todo el recorrido de la base de datos se realiza dentro del módulo db de forma que cualquier cambio en su estructura se limite a dicho módulo.

    • Se han reprogramado completamente las rutinas relativas a ilines, responsables del 11.3% de la CPU consumida. Paso a utilizar una tabla hash de 16 bolsillos. Como efecto secundario, se elimina su impacto en la recogida de basuras, en la búsqueda del número de conexiones simultaneas desde una misma IP, etc. Ahora sólo ocupa el 0.1% de la CPU consumida.

    • Dado que con los cambios efectuados en la gestión de ilines no es preciso marcarlas en la base de datos (tienen sus propias estructuras de datos), se elimina la marcación "I".

    • Cuando se hace un ilines al bot, ahora se permite también un parámetro opcional indicando una subcadena a mostrar. Sólo se visualizarán las ilines que contengan esa subcadena.

    • Olimpo ocupa 1348 líneas de código C.

  • 19/Ene/99 Versión 12

    • Para poder disponer de un código único que se pueda compilar para ESNET y para IRC-Hispano, se mueven todos los detalles de configuración a un fichero externo llamado config.h.

    • Se mueven todos los comandos del bot a su rutina correspondiente, por sencillez y para poder realizar un profiling efectivo.

    • En los cambios de modo sólo se consideraba canal si empezaba por "#". Ahora se considera canal si empieza por "#", "&" o "+".

    • Añadido el comando profile, que almacena en un fichero los datos de profiling del código sin necesidad de matar al proceso.

  • 18/Ene/99 Versión 11

    Con la reconfiguración de IRC-Hispano, Olimpo pasa a controlar los clones en dicha red. Ello hace necesarias numerosas modificaciones en el código, ya que muchos valores ESNET están "cableados" y es preciso moverlos a ficheros de configuración externos.

    Una de mis mayores sorpresas ha sido el poco consumo de memoria y de CPU que ha supuesto el uso de este pseudoservidor, considerando las estructuras de datos tan primitivas que estamos utilizando. Salvo en los Splits/Joins, el consumo de CPU es muy bajo, no llegando al 10% en los picos de ocupación de la red.

    Las modificaciones efectuadas al código nativo ESNET han sido:

    • Aumento del tamaño permitido de la base de datos, de 128Kbytes a 1Mbyte. Con el uso actual de IRC-Hispano, y las estructuras de datos que estamos empleando en este momento, ello supone capacidad para más de 17.242 usuarios.

    • En Esnet el bot se llama Olimpo y el nodo olimpo.esnet.org. En IRC-Hispano se llaman, respectivamente, Sux y black.hole.

    • El Bot entra en el canal #opers y publica en dicho canal los resultados de las recogidas de basura.

    • Corregido un bug que hacía que los usuarios que eran matados con kill por un nodo externo no se borrasen de la base de datos, con lo que ello supone de control de clones, ocupación de memoria, etc.

    • Cuando se mata a un usuario por clones, en el mensaje se indica también su IP o DNS Inverso si lo tiene.

    • Cuando un usuario borraba un modo que no tenía activo, el servidor moría.

    • Añadido el comando die.

    • Añadido el comando userstats.

    • Añadido el comando dump.


  • 23/Oct/98
    Se crea una librería que contiene todas las rutinas de gestión de la base de datos en memoria.

    En este momento se gestiona todo dentro de un bloque de memoria. Es un sistema muy sencillo.

    Se puede compilar el código con make.

  • 09/Jul/98 Versión 1.5
    Se envía un SETTIME cada cuatro horas, además de en el connect inicial.

    Se hace log de los comandos enviados por IRCops en "olimpo.log".

    Añadido el comando "jupe" para jupear servidores. El efecto es instantaneo. Si el olimpo se relanza o se hace squit, se pierde.

    Los mensajes que no van específicamente dirigidos a OLIMPO (por ejemplo, mensajes globales) se ignoran.

    Cambiamos la identificador numérico de Olimpo de "0" a "A", que se corresponde con el nodo 0. De otra forma surgiría una colisión con el nodo "0" cuando la red se amplíe.

    Derivado del anterior: el bot Olimpo pasa de "091" a "AAA".

  • 08/Jul/98 Versión 1.4
    Con la fractura de mi brazo derecho y el tema de registro de nicks y demás no he tenido mucho tiempo para ponerme con Olimpo.

    Completado el tema de ilines.db. Almacena lo siguiente:

    1. La letra "I" (I-Line)
    2. IP/host
    3. Número de clones
    4. Comentarios

    Añadido el comando "ilines" para listar las I-Lines activas.

  • 09/Ene/98 Versión 1.3+
    Cada vez que entra Oraculo genera un SETTIME.

  • 04/Dic/97 Versión 1.3
    La recogida de basuras genera un "WALLOPS".

    Se genera recogida de basuras cuando:

    1. La memoria se llena
    2. El 25% de la memoria ocupada es basura y se intenta almacenar un nuevo registro.

  • 04/Dic/97 Versión 1.2
    Almacena información sobre los servidores, para poder responder a un squit sin necesitar un SQUIT/CONNECT propio. Cada registro consta de:

    1. La letra "S" (Servidor)
    2. Clave de identificación del servidor del que cuelga
    3. Clave de identificación del servidor
    4. Nombre del servidor

    Cuando hay un SQUIT, se dan de baja todos los servidores que colgaban de esa máquina y todos los usuarios que cuelgan de esos servidores.

    ATENCION: Solo se guarda la primera letra del identificador

  • 28/Nov/97 Versión 1.11
    Se ha cambiado el nombre de "oraculo" a "olimpo", tanto para el bot como para el nodo.
    La busqueda de nick se ha hecho case insensible.

  • 27/Nov/97 Versión 1.1
    Comandos de control disponibles para IRCops:

    • op #canal nick
    • deop #canal nick

    Para ello creo un "bot virtual" llamado "oraculo".

  • 27/Nov/97 Versión 1.01
    Si hay lag o a la vuelta de un split, es posible que en la ráfaga inicial se transfiera un clono ilegal, que este nodo se lo cargue, y que luego lleguen modos y demás comandos sobre él. Hay que hacer que si no se encuentra a un usuario en la base de datos, el comando se ignore.

  • 27/Nov/97 Versión 1.0
    Control de clonos. Almacena lo siguiente:

    1. La letra "U" (usuario)
    2. Dirección IP o Hostname
    3. Nick Actual
    4. Identificador comprimido
    5. Modos del usuario
    6. Máquina a la que se conecta ese usuario
    7. Timestamp

    Cada campo se separa con espacios, y cada registro con un '\0'.

    • Con NICK de server se comprueban clonos y se crea una nueva entrada
    • Con QUIT, se elimina la entrada
    • Con KILL, se elimina la entrada
    • Con SQUIT, se eliminan todas las entradas de HOSTs y NICKS que están afectados por el split
    • Con NICK de usuario, actualiza nick
    • Con MODE de usuario, actualiza modos

    En estos momentos un SQUIT de un nodo fuerza un SQUIT/JOIN de ORACULO, de forma que actualiza datos de forma automática. Si eso se ve en la red, lo cambio luego.

  • 26/Nov/97 Versión 0.0
    Simplemente conecta y mantiene la conexión.



Python Zope ©1997-2000 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS