[IRC-DEV] detalle del túnel

Oscar J Garcia oscar at intercom-redes.es
Fri Mar 16 20:35:29 CET 2001


Realmente todo empezó como un proxy, ya que mi objetivo era implementar recepción y envío de DCC transparente al usuario, pero
poco a poco se está convirtiendo en un túnel, en el que se transmite TODA la información a través de un único socket.

He aquí un pequeño fragmento de un archivo de cabecera:


/* ESTRUCTURA minitrama_t:
 canal: Canal de datos (cliente) Queda limitado
    a sólo 256 clientes (conexiones bidireccionales).
 longitud: Número de datos a transmitir.
 datos: Datos del cliente a transmitir.
*/
typedef struct {
 uchar canal;
 ushort lontitug;
 char *datos;
 } minitrama_t;


Con esto, lo que conseguimos es diferenciar los "canales" de comunicación unos de otros cuando se transmiten por el socket (antes
de ser comprimidos).


/* ESTRUCTURA trama_t:
 tipo:  Tipo de compresión/servicio.
 datos: Datos a transmitir.
*/
typedef struct {
 uchar tipo;
 char *datos;
 } trama_t;


Con esto defino el tipo de trama que se envía: si queremos hacer una conexión, cerrarlar, verificar conexión cerrada, verificar
conexión abierta o simplemente, transmitir datos ya comprimidos (en ese caso, el "tipo" indica tb que tipo de compresión se ha
usado, para algo que quería implementar, que era comprimir con varios algoritmos, y transmitir con el que mejor compresión dé por
trama, a costa de una mayor carga de la ya muy sufrida CPU).


/* ESTRUCTURA buffer_t:
 usado: Bytes usados del buffer.
 datos: Datos del buffer.
*/
typedef struct {
 ushort usado;
 char buffer[MAXBUFFER];
 } buffer_t;


Esto define el buffer de salida (antes de ser comprimido y preparado para ser enviado). Se trata de un buffer de 32K.

El funcionamiento es sencillo. Recibo datos por cada uno de los sockets de los clientes hasta que el buffer pasa de los 16K
(supongamos 20K), entonces, si sobran de los 32K, los dejamos para el siguiente buffer, en caso contrario, cerramos el buffer, lo
comprimimos y enviamos usando la trama anterior.

Para evitar crear un lag elevado (porque tarde mucho tiempo en llenarse el buffer. y por lo tanto, tarde por ejemplo 30 segundos
en llenarse y transmitirse) antes usaba una variable con el tiempo transcurrido desde la anterior transmisión, desbloqueaba el
select con un alarm a 1 segundo, y si habian pasado mas de 3 segundos, enviaba la trama. Lo último que he estado modificando ha
sido implementar una idea de JCEA: usar el propio timeout modificando las propiedades del socket. Esto simplifica el código en
cuanto a la manera de salir de un select largo, pero aún continúo usando la hora para verificar si he de enviar lo que llevo de
buffer si aún no lo he llenado.

Lo que aún me queda por implementar es:

typedef struct {
 char nick[12];
 char ident[12];
 char host[128];
 } nick_t;

Esto ya es de un programa experimental aparte (no quiero arriesgarme a dejar fuera de servicio el otro sin probar este antes por
separado).
El objetivo es minimizar la información redundante que se envía por internet, es decir: eliminar los privados dentro del mismo
ciber (eso lo haré cuando lo integre en el anterior programa) pero ante todo (eso es lo que intento hacer por ahora): En vez de
enviar los nicks y su host en cada privado, etc... sólo mandamos un descriptor de 16 bit (podemos hacer una caché de 64K nicks, lo
cual es MUY aceptable, se puede reducir a 100 nicks por ejemplo, pero si los clientes se comunican con excesivos nicks, acabará
por haber demasiados cache-miss, de modo que interesa una cache alta).

Quiero implementar comprobacion de host e ident para evitar que si éste cambia, se vea el anterior, etc... (nefasto para hacer
bans, etc... a IPs antiguas no actualizadas si alguien se guia por la ip del privado en vez de por la ip del whois).

Quizás mi problema es que no tengo marcados unos objetivos iniciales y por eso no paro de avanzar con mas ideas antes de dejar
acabadas del todo las anteriores, vamos, que no me he planificado bien este proyecto.

Lo dicho, en cuanto tenga algo medio acabado (este último programa me va a medias y el primero prácticamente lo he abandonado) os
mando a todos el código completo (también de paso un poco comentado, no se si sería legible sin ellos ;).

Si alguien tiene una idea de como orientarlo mejor, que me lo comunique. No dispongo de mucho tiempo, pero para mis hobbies saco
tiempo de donde no lo hay ;)

Un saludo y buen fin de semana a todos.




More information about the IRC-Dev mailing list