[IRC-DEV] Re: Raw 401 en ocasiones no devuelve el nick (no me refiero a nosuch server)

Ruben Cardenal rubenc at arrakis.es
Wed Sep 11 12:10:06 CEST 2002


Hola,

 >>  Veamos que dice el código de este caso: s_user.c, funcion m_message()
 >>
 >>       else if (MyUser(sptr) || Protocol(cptr) < 10)
 >
 >
 > Esto tiene toda la pinta de ser una comprobación OR para el protocolo que en
 > este caso nada afecta a lo se está comentado, es una comprobación previa
 > basada en protocolos (server sptr y client cptr) y no en la inexistencia en
 > sí de los nicknames.

  Te explicaré el funcionamiento de m_message por encima. Por cierto, si 
piensas seguir en esta linea de participación en la lista comentando un código 
que no entiendes, te aconsejo que te documentes algo, pues vas a meter mucho 
la pata pues sptr JAMAS se usa para referirse a una conexion de un servidor. 
Igual te piensas que la 's' de 'sptr' es por "server"...

  A este respecto, te dire que hay ciertas convenciones en cuanto al nombre 
que se le dan a las variables segun el uso que se vaya a hacer de ellas. Las 
tienes al principio de s_user.c, y las adjunto aqui para mayor claridad:

/*
  * m_functions execute protocol messages on this server:
  *
  *    cptr    is always NON-NULL, pointing to a *LOCAL* client
  *            structure (with an open socket connected!). This
  *            identifies the physical socket where the message
  *            originated (or which caused the m_function to be
  *            executed--some m_functions may call others...).
  *
  *    sptr    is the source of the message, defined by the
  *            prefix part of the message if present. If not
  *            or prefix not found, then sptr==cptr.
  *
  *            (!IsServer(cptr)) => (cptr == sptr), because
  *            prefixes are taken *only* from servers...
  *
  *            (IsServer(cptr))
  *                    (sptr == cptr) => the message didn't
  *                    have the prefix.
  *
  *                    (sptr != cptr && IsServer(sptr) means
  *                    the prefix specified servername. (?)
  *
  *                    (sptr != cptr && !IsServer(sptr) means
  *                    that message originated from a remote
  *                    user (not local).
  *
  *            combining
  *
  *            (!IsServer(sptr)) means that, sptr can safely
  *            taken as defining the target structure of the
  *            message in this server.
  *
  *    *Always* true (if 'parse' and others are working correct):
  *
  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
  *
  *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
  *            *cannot* be a local connection, unless it's
  *            actually cptr!). [MyConnect(x) should probably
  *            be defined as (x == x->from) --msa ]
  *
  *    parc    number of variable parameter strings (if zero,
  *            parv is allowed to be NULL)
  *
  *    parv    a NULL terminated list of parameter pointers,
  *
  *                    parv[0], sender (prefix string), if not present
  *                            this points to an empty string.
  *                    parv[1]...parv[parc-1]
  *                            pointers to additional parameters
  *                    parv[parc] == NULL, *always*
  *
  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
  *                    non-NULL pointers.
  */

  Bueno, vamos a lo que interesa :)

  A m_message se le pasan varios parámetros, entre ellos, y para lo que nos 
interesa:

  - *sptr -> Origen del mensaje.
  - *cptr -> Origen fisico del mensaje.
  - *parv[] -> Lista de destinatarios y el mensaje.

  Basicamente, a la funciona hace esto:

  a) Comprobar si el mensaje es un PRIVMSG o un NOTICE.
  b) Comprobar si el numero de parámetros es correcto (osea, que como minimo 
has especificado un destinatario y un mensaje)
  c) Despues, hay un bucle for que va recorriendo la lista de parámetros 
pillando los destinatarios que hay entre comas (en caso de haber varios). Cada 
destinatario de esos lo mete en una variabale llamada 'nick'
  d) Para cada destinatario (y explicaré solo hasta el caso que nos interesa, 
si quieres saber como va el resto, te lees el código), primero mira que sea:
    1) Un canal: 'if (IsChannelName(nick))' (Linea 2044) Lo procesa...
    2) Un nick. Basicamente, dire que lo que se hace es buscar un cliente con 
'FindUser(nick)' y guardarlo en acptr. En caso contrario, acptr es NULL
  e) Si el resultado es un nick válido 'if (acptr)', lo procesa desde la línea 
2072 hasta la línea 2115. Entre esas lineas, lo que hace (y por este orden) es 
comprobar que el nick destino no esté +R, y despues, si el nick origen (sptr) 
no está silenciado por el nick destino (acptr), cosa que hace en la linea 2085 
con 'if (!is_silenced(sptr, acptr))', es que si el nick destino está away, te 
manda su away, y luego le manda el mensaje.
  f) Ahora, llegamos a la parte interesante, la que dice eso de...

       else if (MyUser(sptr) || Protocol(cptr) < 10)
         sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
       else
         sendto_one(sptr,
             ":%s %d %s * :Target left IRC. Failed to deliver: [%.50s]",
             me.name, ERR_NOSUCHNICK, sptr->name, parv[parc - 1]);
       continue;

  Si te paras a leer el codigo, veras que ese 'else if' corresponde al 'if 
(acptr)' anterior, osea, que NO es un cliente válido.

  con 'MyUser(sptr)' comprobamos que el origen del mensaje sea LOCAL, y con 
'Protocol(cptr) < 10)' miramos si hemos de mandar el nick (para servidores P9) 
o el numeric (servidores P10). Entonces si el origen del mensaje no es local 
(!MyUser(sptr)) ni llega desde un servidor P10 !(Protocol(cptr) < 10), tenemos 
el caso de que el target ha salido de la red ANTES de que se le pudiera 
entregar el mensaje.

  Luego la función sigue procesando un par de casos más, pero como dije antes, 
para eso, te miras el código, no vamos a explicar ahora en esta lista el 
funcionamiento interno de todo el código :)

  Si no comprendes esto, es que no sabes como funciona el ircd por dentro, asi 
que te aconsejo que te bajes uno, y estudies el código. Y si no tienes tiempo 
para bajartelo ni estudiarlo, no hagas comentarios gratuitos de un código que 
desconoces, pues lo unico que consigues es confundir a los que leen esta lista 
y quieren aprender algo.

 > Cuando dispongas de tiempo yo particularmente no entiendo esto. Si obtengo
 > un error de target no disponible, por su abandono de sesión, saber el nick a
 > quien se lo iba a enviar es tan simple como ver a quién le he enviado el
 > mensaje que no ha llegado. No se... no lo entiendo :/

  Entre mi explicación anterior y otro mensaje que envié a la lista, queda 
bien explicado el por qué de este caso, y por qué se procesa así.

  Saludos,

NiKoLaS




More information about the IRC-Dev mailing list