shkolakz.ru 1 ... 11 12 13 14 15

3.5.Búsquedas DNS en SIP


SIP es un protocolo que maneja direcciones SIP (aunque suene redundante) para localizar servidores, servicios y usuarios; como ya hemos visto, estas direcciones poseen un campo denominado 'hostport' que nos informa acerca del lugar al que tenemos que mandar las peticiones y las respuestas, según sea cada caso. Por ejemplo, si conociésemos la dirección SIP de un usuario y quisiéramos iniciar una sesión contra su agente, un examen cuidadoso de su dirección y un par de búsquedas DNS desembocarán en la localización de una dirección IP y un puerto: no sabremos si se trata de la dirección IP de su servidor proxy ó si directamente es la de su agente. Tampoco nos importa porque el modo de operación es el mismo. En esta pregunta no vamos a entrar en decidir qué paquete tiene que ir a qué sitio en cada momento. Únicamente vamos a relatar cómo conseguir una dirección IP, un puerto y un protocolo de nivel de transporte a partir de una dirección SIP.


La descripción ABNF de dicho campo 'hostport' de una SIP-URI (ó dirección SIP) es la siguiente:


Tabla 12: Descripción ABNF de una SIP-URI

hostport = host [ ":" port ]


host = hostname | Ipv4address | Ipv6reference

port = 1*DIGIT


hostname = *( domainlabel "." ) toplabel [ "." ]

domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum

toplabel = alpha | alpha *( alphanum | "-" ) alphanum


Ipv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT

Ipv6reference = "[" IPv6address "]"

Ipv6address = hexpart [ ":" IPv4address ]

hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]

hexseq = hex4 *( ":" hex4)

hex4 = 1*4HEX

Como se puede observar, el campo 'hostport' estará compuesto de un campo 'host' obligatorio y un campo 'port' opcional. Si el puerto no se especifica, asumiremos el 5060 para el protocolo de transporte que se especifique en el campo 'transport-param' de la misma SIP-URI (UDP, TCP, SCTP, TLS ú otro definido por el usuario). Por defecto se asume UDP.



El campo 'host' podrá ser un nombre de máquina, una dirección Ipv4 ó una dirección Ipv6. Nuestro agente únicamente funciona sobre Ipv4, por lo que la última posibilidad no se contempla. Si el campo 'host' fuese una dirección Ipv4 no sería necesaria ninguna búsqueda DNS porque ya tendríamos el protocolo de transporte, la dirección IP y el puerto.


Las búsquedas DNS entran en juego cuando el campo 'host' es un 'hostname'. Para estas búsquedas DNS se usan los registros SRV. Concretamente, el identificador de servicio para dichos registros referidos a SIP es "_sip". El algoritmo completo que se aplica es el siguiente:



  1. Si el campo 'host' es una dirección IP numérica (ya sea IPv4 ó IPv6), el cliente accederá al servidor mediante dicha dirección y a través del puerto especificado en la SIP-URI. Si no se especifica ninguno, se usará el 5060.


Si la SIP-URI especifica un protocolo de transporte, se deberá usar ése. Si no se concreta ninguno, primero se deberá probar con UDP. Si nuestro agente no soportase UDP ó soportase otros protocolos de transporte adicionalmente pero no hay respuesta a la transacción en UDP, la forma en la que se prueben éstos estará sujeta únicamente a la consideración del usuario.


Como hemos asumido que 'host' es una dirección IP, saltaríamos los restantes pasos, pues ya tendríamos la terna IP, puerto y protocolo.

  1. Si el campo 'host' no es una IP, realizaremos una búsqueda DNS (preguntando por los registros SRV asociados al campo 'hostname' para el servicio "_sip") por cada protocolo de transporte soportado por nuestro agente. Es decir, nosotros contamos con la cadena 'hostname' que queremos traducir a una dirección IP. Debemos buscar en los registros SRV del servicio "_sip" para UDP, TCP, SCTP,... etc. y obtendremos la dirección de la máquina que atiende a las peticiones SIP en el dominio especificado para cada protocolo de transporte.



Ordenando las respuestas y seleccionando el protocolo (por ejemplo "_sip._udp" ó "_sip._tcp") obtendremos el nombre de la máquina encargada y un puerto. Sólo si en la SIP-URI no hay especificado un puerto usaremos éste.


Generalmente las respuestas a las peticiones por los registros SRV contienen nombres de máquina que es necesario traducir. Para ello pasaremos al tercer punto. También pasaremos si no hay ningún registro SRV asociado.


  1. Si no existe ningún registro SRV para el campo 'hostname' ó existiéndolo, el servidor aparece referenciado con un nombre de máquina, deberemos traducir esa cadena a una dirección IP mediante una consulta al DNS usando los registros A (para IPv4) ó AAAA (para Ipv6). Con este último paso conseguiremos al final traducir el campo 'hostname' a una dirección IP.


En nuestro proyecto las búsquedas DNS las realizan objetos de la clase 'SUA_Dns', los cuales sólo pueden obtener traducciones asociadas a UDP como protocolo de transporte, ya que nuestro agente únicamente usa UDP (por lo tanto únicamente realiza búsquedas "_sip._udp.hostname").


Como parámetros para la búsqueda únicamente deberemos pasarle un objeto del tipo 'SUA_Address' que encapsula el comportamiento de una dirección SIP ó SIP-URI. El resultado obtenido será un objeto 'QHostAddress' que representa una dirección IPv4 y un entero con el puerto. Siempre asumiremos en nuestro caso UDP como protocolo de transporte.


Sin embargo, la particularidad de los objetos 'SUA_Dns' es que pueden realizar búsquedas tanto síncronas como asíncronas:


  • Búsquedas Síncronas: son búsquedas bloqueantes, implementadas como funciones miembro estáticas que pueden ser llamadas sin tener que instanciar un objeto 'SUA_Dns'. Hacen uso de la librería libresolv.so y tienen la ventaja de su fácil manejo y de la relativa linealidad que infieren en el código llamante. Su desventaja: bloquean al hilo llamante durante un periodo de tiempo que puede llegar a ser muy largo, incluso de decenas de segundos.


  • Búsquedas Asíncronas: se trata de búsquedas no bloqueantes, que son configuradas primero mediante una SIP-URI y que posteriormente puestas a trabajar. El control retorna inmediatamente al código llamante, por lo que son tremendamente útiles para aplicaciones gráficas o cuando no podemos tener un hilo bloqueado durante mucho tiempo. Para realizar las búsquedas en sí no usan libresolv.so como las anteriores, sino objetos proporcionados por las librerías Qt. La forma que tienen para devolver los valores obtenidos (entero con el puerto y objeto 'QHostAddress' con la dirección) es mediante el sistema 'signal/slot' de Qt, que posibilita la generación de una señal Qt por el objeto que ha terminado la búsqueda, para que se ejecute el 'slot' previamente configurado. Se trata de un mecanismo similar al de los eventos, pero que sólo funciona en un mismo hilo, por lo que habrá que extremar las precauciones. La desventaja que presentan es que su uso no es tan directo como las síncronas, porque es necesario configurar el slot, y el código pierde linealidad.




<< предыдущая страница   следующая страница >>