Sip Proxy - Pag34

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 122

INSTITUTO POLITECNICO NACIONAL

ESCUELA SUPERIOR DE INGENIERIA


MECANICA Y ELECTRICA

“Unidad Zacatenco”

INGENIERIA EN COMUNICACIONES Y ELECTRONICA

Desarrollo de un Software Proxy PBX de VoIP


con funciones de reporte de llamadas

TESIS

Que para obtener el título de


Ingeniero en Comunicaciones y Electrónica

Presentan:
Liliana Aguilar Hernández
Agustín Moreno Nájera

Asesores:
M. en C. Genaro Zavala Mejía
M. en C. Fernando Noya Chávez

Diciembre 2011
1
Índice General
Índice de figuras………………………….……………………….………………. 4
Índice de tablas…………………………………………………………..………... 6
Introducción……………………………………………………………………….. 7
Descripción…………………………………........................................................... 9
Justificación…………………………………………………………….................. 10
Objetivos………………………………………………………………………….. 10
Diagrama a bloques……………………………………………………………….. 11

Capítulo I Estado del arte …………………………………………………............ 12


1.1 PBX……………………………………………………………………. 12
1.1.1 Antecedentes………………………………………………. 12
1.1.2 Estado actual de los PBX………………………………...... 13

1.2 VoIP…………………………………………………………………… 15
1.2.1 Antecedentes de telefonía convencional…………………… 15
1.2.2 Estado actual de la Telefonía IP bajo la tecnología VoIP….. 17

Capítulo II Marco teórico …………………………………………………..... 20


2.1 PBX…………………………………………………………………… 20
2.1.1 Definición
2.1.2 IP PBX
2.1.2.1 Características ……………………………………… 21
2.1.2.2 Componentes y funcionamiento…………………….. 21

2.2 Proxy PBX ……………………………………………………………. 22


2.2.1 Definición Sistema Proxy………………………………….. 22
2.2.2 Funcionamiento……………………………………………. 23
2.2.3 Ventajas y desventajas del uso de un Proxy………………. 23
2.2.4 Proxy a nivel aplicación: Protocolo SIP………………….... 24

2.3 VoIP…………………………………………………………………..... 26
2.3.1 Introducción a la VoIP …………………………………….. 26
2.3.2 Definición………………………………………………..... 26
2.3.3 Implementación y funcionamiento…………………………. 27
2.3.4 Control de la comunicación…………………………………. 27
2.3.5 Parámetros VoIP……………………………………………. 28
1.2.5.1 Códec……………………………………………….. 28
1.2.5.2 Protocolos de señalización …………………………. 28
1.2.5.3 Protocolos de transporte de voz
y ancho de banda de la voz ………………………………… 29

2.3.6 Ventajas…………………………………………………….. 29

2.4 Protocolo SIP …………………………………………………………. 32


2.4.1 Definición …………………………………………………. 32
2.4.2 Conceptos básicos …………………………………………. 33
2.4.3 Mensajes SIP……………………………………………….. 36
2.4.4 Cabecera SIP……………………………………………….. 38

2.5 Protocolo RTP……………………………………………………... 39


2
2.5.1 Definición……………………………………………… 39
2.5.2 Encapsulamiento………………………………………. 40

Capítulo III Herramientas…………………………………………………... 42

3.1 Sockets …………………………………………………………………... 42


3.1.1 Sockets en C# ……………………………………………………. 42
3.1.2 Métodos de la clase socket……………………………………….. 43

3.2 Desarrollo .NET C#.................................................................................... 44


3.3 SDK SIP .NET…………………………………………………………… 47
3.3.1Descripcion…………………………………………………………. 47
3.4 Configuración objeto SIP Core………………………………….............. 53
3.5 Servidor TrixBoX……………………………………………………….. 54
3.6 Cliente Softphone………………………………………………………… 54
3.6.1 Descripción………………………………………………………. 54
3.6.2 X-lite……………………………………………………………… 55

Capítulo IV Desarrollo………………………………………………………. 59

4.1 Desarrollo de software de comunicación IP usando socket……… 59

4.2 Captura y análisis de Mensajes SIP…….…………………………. 64

4.2.1 Autentificación de Softphone en el PBX VoIP……... 64


4.2.2 Inicio y fin de una llamada VoIP……………………. 64

4.3 Desarrollo de Software Proxy basado en transacciones SIP………. 67

4.4 Desarrollo de Software Proxy para autentificar Softphone……….. 70

4.5 Desarrollo de Software Proxy para iniciar y finalizar una llamada…. 73

4.6 Desarrollo de Software Proxy para generar reportes de llamadas…. 75

Capítulo V Pruebas………………………………………………………… 76
5.1 Registro de teléfono SIP…………………………………………. 76
5.1.1 Resultados……………………………………………....... 77

5.2 Establecimiento y liberación de sesión SIP………………………...... 78


5.2.1 Resultados………………………………………………...... 80

5.3 Prueba Reporteador…………………………………………………… 81


5.3.1 Resultados…………………………………………………… 82

5.4 Resultados finales…...………………………………………………… 82

Conclusiones…………………………………………………………. 84

Glosario…..………………………………………………………....... 85
Anexos .………………………………………………………………. 86

Bibliografía…………………………………………………………… 122
3
Índice de figuras

Figura 1. ERICSSON PMBX 1A ………………………………………………. 12

Figura 2. Telefonía punto a punto mediante cables………………………..……. 15

Figura 3: Telefonía conectada a central…………………………………………. 16

Figura 4. Esquema de enrutado en un entorno SIP……………………………… 25

Figura 5. Esquema protocolos…………………………………………………… 26

Figura 6. Trama VoIP…………………………………………………………… 26

Figura 7. Ejemplo de llamada SIP (200 llama a 201)……………………………. 34

Figura 8. Ejemplo de llamada SIP con intermediarios (200 llama a 201)……… 34

Figura 9. Proceso de registro.................................................................................. 35

Figura 10. Registro completado............................................................................. 36

Figura 11. Encapsulamiento RTP........................................................................... 40

Figura 12. Proceso Cliente/Servidor....................................................................... 42

Figura 13: Arquitectura general de la Unidad SIP.NET API................................. 55

Figura 14. SIP Account Settings…………………………………………………. 56

Figura 15. Propiedades de configuración de una cuenta SIP…………………….. 57

Figura 16. Configuración de cliente SIP.................................................................. 57

Figura 17. SIP Accounts, cuenta configurada……………………………………. 58

Figura 18. Teléfono registrado y autenticado…………………………………….. 61

Figura 19. Interfaz de aplicación Servidor TCP………………………………….. 61

Figura 20. Interfaz de aplicación Cliente TCP…………………………………… 63

Figura 21: Analizador de tráfico en red, captura de mensajes SIP………………. 64

Figura 22: Trama de una petición REGISTER…………………………………... 65

4
Figura 23. Proceso de autenticación y registro de un UAC……………………… 66

Figura 24. Transacciones SIP mediante un Proxy……………………………….. 67

Figura 25. Diagrama de transacciones incluidas en el Proxy PBX……………… 68

Figura 26. Nodo perteneciente a la clase NodoListaSoftphone…………………. 71

Figura 27. Proceso de inicio y fin de llamada……………………………………. 73

Figura 28. Base de datos Reporteador……………………………………………. 75

Figura 29. Diagrama de registro de Softphone…………………………………... 76

Figura 30. Esquema SIP de registro y autenticación de Softphone………………. 77

Figura 31. Softphone registrado............................................................................... 77

Figura 32. Log de Tramas Register......................................................................... 78

Figura 33. Diagrama Establecimiento y liberación de sesión SIP………………... 79

Figura 34. Esquema SIP de inicio y fin de llamada………………………………. 79

Figura 35. Log de tramas inicio y fin de sesión………………………………….. 80

Figura 36. Softphone2……………………………………………………………. 80

Figura 37. Llamada establecida………………………………………………….. 81

Figura 38. Esquema PROXY PBX……………………………………………… 81

Figura 39.Prueba Reporteador…………………………………………………… 82

Figura 40. Aplicación PROXY PBX ……………………………………………... 82

Figura 41. Créditos………………………………………………………………… 83

5
Índice de tablas

Tabla 1. Ejemplos de direcciones SIP……………………………………………… 33

Tabla 2. Peticiones SIP…………………………………………………………….. 36

Tabla 3. Respuestas SIP…………………………………………………………… 37

Tabla 4. Conceptos generales……………………………………………………… 51

Índice Sección de Código

Sección de Código 1. Creación de aplicación Servidor TCP……………………….. 61

Sección de Código 2. Creación de aplicación Cliente TCP………………………… 62

Sección de Código 3. Creación de transacciones SIP………………………………. 69

Sección de Código 4. Definición de estructura de datos asignada a cada usuario dentro


de la red…………………………………………………………………………….. 71

Sección de código 5. Gestión de envío de trama INVITE a un usuario final……….. 74

6
Introducción

La telefonía de hoy en día, tal y como la hemos conocido siempre, está llegando a
su fin. La era de las nuevas tecnologías, con Internet a la cabeza, le están ganando terreno a
grandes consorcios tecnológicos que han permanecido invariables e intocables durante
mucho tiempo. El mundo de las comunicaciones por voz es uno de ellos.

Desde la invención del primer teléfono, se han venido produciendo cambios y


mejoras en los sistemas de telefonía que han permitido su expansión, llegando
prácticamente a todos los hogares y rincones del mundo.

No obstante en la actualidad, estos sistemas siguen basándose en tecnologías de


hace varias décadas, obsoletas y que no son óptimas en muchos sentidos. Por ejemplo, en el
uso de la línea telefónica cuando se establece una comunicación: se necesita que exista un
canal constantemente abierto o dedicado, con el consiguiente desperdicio de recursos que
pudieran ser mejor aprovechados. Hoy en día ya no es necesario dedicar un recurso por
completo para mantener una conversación. En la era de Internet, es posible que una
conversación telefónica se pueda mantener entre dos puntos cualesquiera, ocupando una
simple porción del espectro o ancho de banda de la conexión de área local o hacia Internet.
La voz se convierte en paquetes y pasa a denominarse Voz sobre IP o VoIP por sus siglas
en inglés (Voice over Internet Protocol).

Si la voz ya no viaja por un circuito dedicado y exclusivo, si no que ahora forma


parte de nuestras comunicaciones de datos, se consiguen otro de los beneficios de las
grandes tecnologías, la unificación. La voz y los datos viajan por la misma red, y no solo
eso, además son tratados y gestionados de forma conjunta y coordinada. Bajo estas
condiciones se obtiene un uso óptimo de los recursos.

Gracias al despliegue de nuevas redes de datos, se puede ofrecer ya una gran


cantidad de servicios al usuario final, con una calidad óptima y además de manera
centralizada: Televisión, Internet y por supuesto, voz. Es decir, ya no será necesario una
“línea telefónica” sino una línea de datos.

Dentro de este contexto, la Voz sobre IP está teniendo un auge vertiginoso.


Fundamentalmente, aquellos países que disponen y/o se están dotando de redes de última
generación, disponen de ventajas en uso y disfrute. Sin redes fiables que cuenten con un
gran caudal de ancho de banda, no es posible una migración seria y efectiva. Desde este
punto de vista, los países o comunidades que no tengan claro este concepto perderán el tren
digital y aumentarán aún más su déficit tecnológico (brecha digital).

7
La telefonía IP comenzó a principios de las décadas de los 90 1, aunque la mala
calidad de la voz y el impulso que en aquellos momentos estaba tomando la RDSI (Red
digital de servicios integrados) hicieron que no pasara de ser solo un experimento. Durante
esta década se produjo el auge de Internet, lo que hizo que todos los esfuerzos, tanto de las
empresas como de los operadores fueran dirigidos a potenciar su uso y las aplicaciones de
navegación Web y correo electrónico, fueron las que más éxito tuvieron, lo que junto al
despliegue de las redes móviles dejaron la voz relegada en un tercer plano.

Hasta hace muy poco el freno para el despliegue de la telefonía IP en el mercado lo


daba la propia tecnología: la calidad del sonido era bastante defectuosa, lo que disuadía a
utilizarla y seguía haciendo uso de la línea telefónica tradicional, a pesar de ser bastante
más caro, salvo a esa problemática el sistema se fue abriendo camino. Sus ventajas son
múltiples: es un servicio más barato, permite el uso de nomadismo – uso del mismo número
telefónico- en cualquier lugar y tiene capacidad multimedia. Además, la calidad del servicio
va en aumento, aproximándose a la de la telefonía convencional, con la que se permite la
interconexión.

En principio, todo apunta hacia el triunfo definitivo de la telefonía IP, tanto en el


segmento residencial como en el empresarial, pero esto solamente se producirá si existe una
oferta amplia, con calidad y que represente un costo inferior al de la telefonía convencional,
facilitando además los mismos servicios. Así pues, en un futuro no muy lejano, es
previsible suponer que casi toda la voz se transportará sobre IP, pero los usuarios no serán
conscientes de la tecnología que hay detrás sino que simplemente tendrán unas
comunicaciones mas económicas y una terminal multimedia para acceder a ellas, con total
movilidad, ya que al no depender de numeración geográfica podrán hacer y recibir sus
llamadas en cualquier lugar y momento.

En el plano empresaria, para lograr el enrutamiento de dichas llamadas telefónicas


de manera efectiva, es necesaria la implementación de un PBX (Private Branch Exchange),
utilizado para permitir la conexión de diversos teléfonos personales y así lograr la ejecución
de llamadas internas y la transmisión de llamadas externas.

Mantener redes de comunicación eficientes es prioritario dentro de una empresa, ya


que gracias a ellas es posible conocer las necesidades de los clientes, conocer los
ofrecimientos de los proveedores y mantener integrada a la organización. El conmutador
telefónico es parte de la infraestructura de telecomunicaciones que hace posible cumplir
con esa función de comunicación. Hace ya algunos año, era necesario un operador de
conmutador quien atendía las llamadas telefónicas entrantes que posteriormente canalizaba
con las personas indicadas dentro del establecimiento. Actualmente, se hace uso de diversas
funciones programables con capacidad para establecer la comunicación a través de un
número variable de líneas y así realizar el enlace de forma automática.

1
José Manuel Huidobro Moya, Tecnología IP y Telefonía VoIP, 2006.
8
Descripción

En base a los conocimientos de programación adquiridos en la carrera de Ingeniería


en Comunicaciones y Electrónica se implementará una aplicación Proxy PBX, basada en
una tecnología de nueva generación: VoIP. Esta aplicación permitirá capturar y procesar
mensajes SIP especificados en el RFC 3261, que estén implicados en una sesión telefónica,
esto con el fin de hacer un reporte de llamadas: Inicio de llamadas, duración de llamadas,
el número de extensiones telefónicas que intervienen en la llamada, etc.

El desarrollo de un software Proxy PBX estará basado en el entorno de


programación Visual Studio C# con la utilización de bibliotecas de sockets, desarrollado
para el Sistema Operativo Windows mediante su interfaz gráfica.

Para establecer la comunicación es necesario que exista un cliente y un servidor,


donde el servidor tendrá la función de un PBX y podrá almacenar y distribuir las peticiones
(llamadas) del cliente a toda la red local. El Proxy PBX es un elemento que se pondrá como
intermediario entre el servidor PBX y el cliente Softphone, con la intención de generar los
reportes de las llamadas.

Para lograr la comunicación entre el servidor y sus clientes, será necesario hacer uso
de diversos protocolos, mediante el modelo OSI. En la capa 1 (Física) se utilizará como
medio de transmisión cable UTP categoría 5 utilizado normalmente en redes LAN. En la
capa 2 (Enlace de datos) se requerirá un switch para concentrar todas las terminales
existentes conectadas al servidor. Siguiendo con la capa 3 (Red) se implementará el
protocolo IP y con esto se configurarán los clientes dentro de un dominio para ser visibles
por el servidor. Dentro de la capa 4 (Transporte) para que exista transmisión de datos se
hará uso del protocolo UDP basado en el envío de datagramas, el cual resulta de mayor
factibilidad para transmitir voz en tiempo real. Por último en la capa de aplicación el
protocolo SIP tomará un papel importante para lograr la comunicación y reconocimiento de
las aplicaciones entre cliente y servidor.

La aplicación Proxy PBX que se desarrollará en este trabajo, interviene en la capa 3 de


modelo OSI, ya que re define direcciones IP con el fin de alcanzar al servidor PBX,
manejara información de capa 4 con la intención de aceptar conexiones y enviar mensajes
SIP mediante el protocolo UDP, entre la aplicación cliente Softphone y la aplicación
servidor PBX y por último, modificara información de la capa de aplicación, es decir, del
mensaje SIP en su cabecera para dar a conocer información de localización de los
elementos que intervienen en la llamada SIP.

9
Justificación

Actualmente en México hay poco desarrollo de aplicaciones para el manejo de


VoIP, en lo que concierne a la telefonía IP: Softphone, PBX, Reporteador de llamadas y
Proxy´s.

Existen muchas aplicaciones para VoIP pero desarrolladas en el extranjero, las


aplicaciones que generan reportes de llamadas son a veces incompatibles entre diferentes
marcas, son caras y su soporte es en el país extranjero, lo que hace a este tipo de soporte
ineficiente.

Se puede adquirir un PBX IP basados en software gratuito, normalmente para


Linux, pero rara vez se pueden imprimir reportes.

Por otro lado, en México no se desarrollan aplicaciones en tecnologías que están


despuntando, como VoIP, e incluso adquiriendo gran popularidad, lo que nos deja en un
plano de atraso tecnológico.

Objetivos
Objetivo General:

Aplicar el lenguaje de programación C# para desarrollar un software Proxy PBX,


implementado en una red de área local que utiliza la tecnología VoIP.

Objetivos Particulares:

a) Aplicar los protocolos SIP, IP y UDP para lograr la transmisión y recepción de


la información para así manipular los datos según las necesidades del usuario.

b) Programar sockets dentro del entorno de programación Windows C# para el


desarrollo de una aplicación que nos permita gestionar las comunicaciones
dentro de una red.

c) Establecer comunicación entre nuestra aplicación y teléfonos basados en la


tecnología VoIP.

d) Diseñar una Interfaz Gráfica que permita la gestión de llamadas y el reporte de


las mismas.

10
Diagrama a bloques del proyecto y sus alcances

IP
SIP
Servidor de
Registro

UPD/RTP

PROXY PBX
UAC 1 VoIP PSTN
Reporteador Gateway

.
.
UAC 2
.
.
.
.

UAC
.

11
CAPITULO I. ESTADO DEL ARTE
1.1 PBX

1.1.1 Antecedentes

Una de las necesidades fundamentales de las empresas, es el mantener una


comunicación eficaz. Esta función actualmente es realizada por el sistema PBX (Private
Branch Exchange), es un dispositivo que permite la operación de una red telefónica privada
que es utilizada dentro de una empresa. Este sistema dispone de cierto número de líneas,
conecta las extensiones internas y al mismo tiempo las conecta con la red pública
conmutada, conocida también como PSTN (Public Switched Telephone Network).

En un inicio, se utilizaban centrales manuales de conmutación conocidas como


PMBX2 (Figura 1). Este término duro muy poco tiempo en el mercado y hace referencia a
época donde las llamadas eran transferidas de un circuito a otro manualmente, conectando
cables entre los abonados, este sistema era poco eficiente y tuvo principalmente 2
problemas que impulsaron su evolución.

El primero era que las operadoras podían escuchar las llamadas y la segunda causa fue el
error humano, ya que en ocasiones se enlazaban las llamadas a lugares equivocados. La
solución, realizar este procedimiento mediante maquinas automáticas.

Figura 1. ERICSSON PMBX 1A

2
Private Manual Branch Exchange
12
A partir de este punto, el avance de la telefonía, estuvo íntimamente ligado al
desarrollo de los sistemas de cómputo ya que, aunque los equipos que reemplazaban a los
PMBX todavía utilizaban tecnología convencional, su sistema central ya estaba basado en
una computadora. Gracias a este avance, se comenzaron a agregar funciones útiles tanto en
telefonía pública como en la telefonía corporativa y así, se obtenían cada vez más
beneficios, más funcionalidad, mayor capacidad y menor costo.

En el ámbito empresarial, es de suma importancia mantener comunicaciones


eficientes. El sistema PBX se desarrolló para proveer a las empresas de funciones
mejoradas, que no ofrecían las compañías de telefónicas, en la actualidad existen equipos
de conmutación que, de manera automática, registran las llamadas entrantes y salientes, la
duración de cada una de ellas y los números troncales y de enlace, entre otras
funcionalidades.

1.1.2 Estado actual de los PBX

Una de las tendencias más recientes en telefonía es la telefonía computarizada,


paralelo al desarrollo de sistemas telefónicos que transmiten la voz por medio de la red de
Internet. Estos llevan el nombre de VoIP PBX ó IP PBX.

Actualmente existen cuatro diferentes opciones de sistemas telefónicos:

PBX
Servicio de PBX Virtual
IP PBX
Servicio de IP PBX Virtual

Un IP PBX es un sistema telefónico basado en software que permite a un negocio


disfrutar de varias funcionalidades y servicios que son normalmente son muy difíciles y
costosos de implementar con las centralitas telefónicas PBX tradicionales.

En la actualidad el registro y direccionamiento de llamadas es administrado mediante


software, implementado bajo la tecnología VoIP, que de manera automática suprime el
trabajo de una operadora telefónica que registraba la duración de llamadas así como la
restricción hacia diversos usuarios.

Una la de las aplicaciones más conocidas para realizar este tipo de funciones es la
llamada Asterisk que fue creada en el año de 1999 por Mark Spencer de la empresa Digium
y donada a la comunidad con licencia libre tras lo cual se han recibido muchas
colaboraciones y mejoras por parte de muchos desarrolladores libres y empresas sin
solicitar nada a cambio.

13
Poco a poco, esta aplicación se ha convertido en la evolución de las tradicionales
centralitas analógicas y digitales permitiendo también la integración de la tecnología más
actual: VoIP. Asterisk ha sido un sistema de comunicaciones completo, avanzado y
económico en la actualidad.

Este sistema permite realizar labores que hasta el día de hoy lo llevaban realizando
sistemas extremadamente costosos y complicados.

Una de las ventajas más interesantes es su posibilidad como sistema híbrido, ya que
permite gestionar comunicaciones telefónicas tradicionales (analógicas, digitales, móviles,
etc.) como comunicaciones IP mediante el uso de los protocolos estándar de VoIP. A pesar
de las ventajas que nos ofrece Asterisk, presenta deficiencias en plataformas para Windows,
ya que carece de funcionalidades para generar reportes de llamadas. Dicha función, al ser
una pieza fundamental para un sistema PBX, el cliente se ve en la necesidad de adquirir
este complemento, lo cual incrementa costos debido al desarrollo y soporte técnico en el
extranjero.

14
1.2 VoIP

1.2.1 Antecedentes de la telefonía convencional

En sus inicios, el teléfono, consistía en un aparato con un altavoz y un micrófono,


unido mediante un cable con otro aparato semejante situado a cierta distancia (ver figura 2).
A través de dicho cable se enviaba y recibía la voz de cada uno de los extremos, lo que
permitió mantener conversaciones con personas situadas a distancia.

En la primera etapa (1878), cada terminal debía realizar la unión con los teléfonos
remotos mediante un cable, donde si no existía conexión en los dos extremos, era imposible
efectuar la comunicación. Eso provocó la aparición de múltiples cables tirados por las
ciudades uniendo teléfonos particulares.

Figura 2: Telefonía punto a punto mediante cables

En la segunda etapa (1891), una entidad global se encargó de gestionar los cables,
de modo que cada teléfono se unió a una central (ver figura 3). Cuando alguien deseaba
realizar una llamada, en la central se unían los cables de ambos teléfonos, lo que permitía
hablar con cualquier teléfono que estuviera conectado a la central, sin necesidad de
conectar un cable específico con cada teléfono. Para conseguir esto, se hizo necesaria la
identificación de cada teléfono mediante un número.

Al principio las centrales eran manuales. Era necesaria la existencia de un operador


que realizara la unión de los cables, a través de grandes paneles con múltiples nodos. Con el
tiempo, se inventó una central automática, que permitió acelerar el proceso.
Durante muchos años, conseguir la conexión telefónica llevaba mucho tiempo, en
ocasiones varias horas debido a la congestión dentro de un canal de comunicación.

15
Figura 3: Telefonía conectada a central

En cualquier caso, el hecho es que comenzaron a instalarse centrales en distintas


ciudades, que luego eran unidas entre sí. Gracias a eso, se pudieron realizar llamadas
interurbanas. Para lograrlo, la central origen debía unir el cable del teléfono que realizaba
la llamada con el cable que la unía con la central destino. Y ésta, a su vez, debía unir este
cable con el del teléfono destino. Para aprovechar el cableado, las uniones entre centrales se
multiplexaban, de modo que era posible llevar por el mismo cable más de una llamada.
Esto se lograba mediante multiplexación por división de frecuencia (FDM), donde,
mediante un sintonizador era posible seleccionar una determinada frecuencia emitida por la
central telefónica.

Durante mucho tiempo, toda la red telefónica fue analógica. La información


transmitida por los cables era una transformación directa de la voz en voltaje, que era lo
que se enviaba y recibía. En su camino desde el origen al destino, la señal atravesaba
diversos filtros analógicos, repetidores y amplificadores. Todos estos dispositivos (además
de los posibles problemas del cable o interferencia) provocaban la aparición de ruido en el
sonido que no podían ser eliminados fácilmente, y que originaban una baja calidad de
sonido en el otro extremo.

Con la aparición de la telefonía digital, la comunicación fue más eficiente. Mediante


el uso de conversores analógico/digital y digital/analógico, en lugar de enviar la voz
convertida en voltaje, se envía esa voz digitalizada. La señal transmitida puede seguir
sufriendo ruido e interferencia por culpa de problemas en el medio de transmisión. Pero
cuando llega a un punto intermedio de la red (central, repetidor, etc.) la señal original puede
ser restaurada completamente, eliminando el ruido de la conversación.

Progresivamente, las redes telefónicas de los distintos países se han ido


transformando en digitales, en lo que a conexión entre centrales se refiere. La conexión
entre los teléfonos y la central sigue siendo analógica, pero las centrales recogen la señal y
16
la digitalizan, por lo que no se acumula ruido en el sonido por culpa de la conexión entre
centrales.

Esto es posible únicamente gracias a la digitalización de la voz, que permite


almacenar partes de la conversación y mandarlas instantes después. Es posible dividir, por
ejemplo, cada conversación en secciones de milésimas de segundo que son enviadas a
través del cable en mucho menos tiempo aún, pudiendo aprovechar el mismo cable para
cientos de conversaciones.

Con el paso de los años, las nuevas tecnologías han adquirido un papel muy
importante dentro de las comunicaciones, como lo es la tecnología VoIP que da lugar a la
implementación de la telefonía IP que se viene abriendo paso frente a la telefonía
convencional.

1.2.2 Estado actual de la Telefonía IP bajo la tecnología VoIP

En la década de los 90, un grupo de personas perteneciente al entorno de la


investigación, tanto de instituciones educativas como empresariales, comenzaron a mostrar
cierto interés por transportar voz y video sobre redes IP, especialmente a través de intranets
corporativas e Internet. Esta tecnología es conocida hoy en día como VoIP y es el proceso
de dividir el audio y el video en pequeños fragmentos, transmitir dichos fragmentos a través
de una red IP y re ensamblar esos fragmentos en el destino final permitiendo de esta manera
que la gente pueda comunicarse.

La idea de la VoIP no es nueva, ya que hay patentes y publicaciones de


investigaciones que datan de varias décadas. La VoIP ha tomado un papel central en la
autopista de la información (o Internet) para que la red pueda interconectar cada hogar y
cada negocio a través de una red de conmutación de paquetes. Fue la posibilidad de un
despliegue masivo de Internet la que volvió a reabrir el interés en la VoIP a partir de esos
años.
En 1995, una pequeña compañía llamada Vacoltec anunció el lanzamiento del
primer teléfono software para Internet. Este software era únicamente útil para entablar una
comunicación de PC a PC y para ello necesitaba hacer uso de diversos requisitos hardware
tales como micrófono, altavoces, tarjeta de sonido y módem. Básicamente el
funcionamiento de este software es igual al de hoy en día, transformar la señal de voz en
paquetes IP una vez comprimida. Sin embargo, esta alternativa a la comunicación
telefónica tradicional fue comercialmente un fracaso ya que las conexiones a Internet que
se disponían ofrecían un ancho de banda muy escaso.

Durante los años siguientes, la tecnología asociada a las redes de datos y las
comunicaciones continuó mejorando, para ser en 1998 cuando se dieron definitivamente los
primeros pasos desde un punto de vista comercial. En este año diversas compañías lanzaron
al mercado adaptadores que permitían hacer uso de los teléfonos tradicionales en un
entorno VoIP. Ello facilitó el acercamiento a los clientes a la hora de poder hacer uso de la
17
tecnología VoIP, por lo que algunas empresas importantes se lanzaron al mercado
ofreciendo productos y servicios relacionados con esta tecnología. Durante el año 1998 la
tecnología VoIP alcanzaba ya el 1% del tráfico total de voz: su carrera había comenzado.

En 19993, compañías dedicadas a las redes de datos tales como CISCO crearon las
primeras plataformas destinadas a empresas capaces de tratar con tráfico VoIP. Esto supuso
un nuevo impulso a la VoIP ya que comenzó a implantarse en muchas empresas. La
consecuencia directa fue que la VoIP alcanzara en el año 2000 más del 3% del tráfico total
de voz.

Las redes de datos siguieron mejorando en años venideros, y alrededor del año 2005
ya era fácil para cualquier persona de países desarrollados conseguir una conexión a
Internet que cumpliera los requisitos mínimos para ofrecer una buena calidad de voz y una
comunicación fiable a través de VoIP, reduciendo al mínimo las posibles interrupciones
que se pudieran producir durante la conversación.

Esto supuso otro gran impulso a la VoIP y provocó que al día de hoy existan
muchas soluciones que hacen uso de esta tecnología. Un ejemplo claro es Asterisk, una
centralita telefónica de software libre que se distribuye bajo licencia GPL. Este producto,
soportado comercialmente por Digium, se ha convertido en pocos años en una de las
soluciones IP más extendidas en diversos ámbitos, como el empresarial o el educativo. Otro
ejemplo destacable de producto VoIP es Skype, que fue creado por dos jóvenes
universitarios en el año 2003. A diferencia de Asterisk, Skype hace uso de un protocolo
privado que no está basado en un estándar, lo que a largo plazo se piensa que limitará a sus
usuarios. Al día de hoy Skype se puede emplear en multitud de plataformas y su uso se
encuentra también ampliamente extendido.

De un modo u otro, a finales del año 2008 se esperaba que el negocio relacionado
con la VoIP llegara a la impresionante cifra de 5000 millones de dólares. El bajo costo de
las llamadas a distancia y las nuevas funcionalidades que se están implementando son sólo
dos de los alicientes que están provocando esta revolución.

Aunque VoIP puede definirse abreviada como una tecnología que aprovecha el
protocolo TCP/IP para ofrecer conversaciones de voz, lo cierto es que es mucho más que
esto. VoIP puede ser usada para reemplazar la telefonía tradicional en un entorno
empresarial, en un pequeño negocio o en una casa, o simplemente para añadir ventajas a un
sistema de telefonía tradicional.

3
José Manuel Huidobro Moya, Tecnología IP y Telefonía VoIP, 2006
18
El proceso de convergencia ha seguido un camino pausado. No es sencillo invertir
en nuevos equipos o infraestructura como lo demanda el actual ritmo de crecimiento en
materia de TICs, por tanto se tiende a seguir un modelo híbrido donde conviven PBX
tradicionales y PBX habilitados con soporte para redes IP. Hoy en día la industria de las
telecomunicaciones ha decidido apostar fuerte por una plataforma común sobre el
Protocolo de Internet aunque, como hemos mencionado anteriormente, ha decidido hacerlo
con visión de largo plazo. Para muchas organizaciones, incluyendo instituciones de
educación, la convergencia significa la oportunidad de fusionar las aplicaciones existentes
con nuevas herramientas de comunicación y nuevos modelos de transmisión de la
información cuyas posibilidades son infinitas.

En este rubro, México ocupa uno de los primeros lugares a nivel América Latina en
el uso de la telefonía IP. Cada vez, más organizaciones están optando por los beneficios de
la convergencia al mundo IP. El mercado de la telefonía por Internet ha crecido
constantemente en los últimos años y seguirá con esta tendencia en el futuro próximo.

Las ventajas que la convergencia plantea se vislumbran prometedoras. Aún no hay


una idea clara del impacto que esta tecnología de convergencia puede tener no sólo en los
modelos de negocios actuales sino en otros campos como lo es el sector educativo y de
investigación. Quien domine el lenguaje de las comunicaciones por Internet tendrá un vasto
mundo de oportunidades no solo de desarrollo profesional sino también personal.

19
CAPÍTULO II. MARCO TEÓRICO

2.1 PBX

2.1.1 Definición

Una central privada automática de conmutación para aplicaciones telefónicas,


denominado generalmente PABX (Private Automatic Branch Exchange) o, últimamente,
solo PBX ya que se entiende que todas son automáticas, es un equipo que tiene control por
software y proporciona funciones de conmutación a los usuarios a ella conectados. El PBX
permite conmutar las llamadas internas sin necesidad de acceder a la red pública de
conmutación.

A continuación se explica el significado del acrónimo PABX:

 Private. Debido a que este tipo de sistemas e instalaciones tienen un uso privado
cuyos servicios no se encuentran disponibles desde otras redes de telefonía de
acceso público.
 Automatic. Se refiere al modo de conmutación que desde hace ya mucho tiempo
es automático para todos los equipos por lo que normalmente en vez de decir
PABX se dice PBX.
 Branch. Sugiere que los equipos conectados a estas redes privadas se comportan
en realidad como una ramificación de las grandes redes de acceso público.
 Exchange. Debido a que estos sistemas permiten intercambiar información, es su
caso esta información son sobre todo llamadas telefónicas.

2.1.2 IP PBX

Actualmente existe una gran diversidad de modelos de centrales telefónicas: centrales


con mayor o menor número de extensiones para pequeñas o grandes empresas, de más o
menos prestaciones, con mayor o menor funcionalidad, totalmente analógicas, semi-
digitales, completamente digitales, híbridas o completamente IP.

Un PBX IP, es un equipo telefónico diseñado para ofrecer servicios de comunicación de


voz y/o video a través de las redes de datos mediante tecnología VoIP e interactuar con la
red PSTN, tanto RTB, como RDSI y móvil.

Para disponer de las funciones de una centralita telefónica IP PBX se tienen varias
opciones: IP PBX basada en hardware, IP PBX basada en software, IP Centrex y PBX
híbrida con soporte VoIP.

20
2.1.2.1 Características

Una centralita telefónica IP PBX permite comunicación de voz y/o video a través de
las redes de datos, utilizando tecnología VoIP así como interactuar con las líneas
telefónicas convencionales PSTN o RTC (Red Telefónica Conmutada), tanto analógicas
RTB (Red Telefónica Básica) como digitales RDSI (Red Digital de Servicios Integrados) y
móviles GSM/GPRS/UMTS.

Una centralita telefónica IP PBX trabaja internamente con el protocolo IP, utilizando
infraestructuras de comunicaciones de datos basadas en IP, como Internet, LAN (Local
Area Network, Red de área local), WLAN (Wireless LAN, Wireless Local Area Network,
Red de área local inalámbrica) y WAN (Wide Area Network, Red de área amplia).

Una IP PBX puede tener las siguientes características, de acuerdo a su funcionamiento:

 IP PBX hardware: la centralita existe como dispositivo físico de hardware.


Normalmente, cada uno de estos tipos se basa en un hardware específico con su
propio procesador integrado que les permite soportar y manejar sus características
específicas de señalización.

 IP PBX software (también llamada Soft IP PBX): la centralita consiste en un


sistema de software.

 IP Centrex (también llamado Virtual IP PBX o Hosted IP PBX): la compañía


telefónica proporciona virtualmente el servicio simulado de IP PBX.

 PBX con soporte VoIP (también llamada PBX híbrida): la mayoría de PBX
tradicionales pueden disponer de las funciones de una centralita IP PBX conectando
módulos donde se incorpora la tecnología VoIP.

2.1.2.2 Componentes y funcionamiento

A continuación, se describen los principales componentes de una centralita telefónica


IP PBX y su funcionamiento:

La centralita telefónica IP PBX es el núcleo del sistema de comunicación telefónica de la


empresa, esta se conecta a la red LAN, que debe disponer de suficiente ancho de banda para
el transporte de datos, voz y video.

Los teléfonos IP, así como los teléfonos IP DECT, se conectan en la LAN y se registran en
la centralita telefónica IP PBX.

21
Las PC’s de la red, tanto con conexión cableada como Wi-Fi, pueden acceder a la centralita
telefónica IP PBX a través de la LAN, realizando llamadas mediante Softphones
registrados en el IP PBX.

Un gateway VoIP o ATA (Analog Telephone Adapter), permite conectar con equipos
estándar, como teléfonos analógicos, faxes o teléfonos inalámbricos DECT.

La telefonía VoIP permite extender la red telefónica privada a través de Internet, integrando
de ese modo oficinas remotas en la infraestructura de comunicaciones de la empresa. Los
usuarios acceden a los servicios que proporciona la centralita PBX IP a través de diversos
dispositivos, entre los cuales se encuentran los teléfonos IP, Softphones, Fax, mensajería
instantánea, sistemas de videoconferencia, dispositivos móviles, etc.

2.2 Proxy PBX

2.2.1 Definición de un Sistema Proxy

Un sistema proxy proporciona acceso a Internet a un solo anfitrión, o a un número


pequeño de anfitriones, aunque parece que lo proporciona a todos. Los anfitriones que si
tiene acceso actúan como proxy para las máquinas que no lo tienen, haciendo lo que estas
últimas quieren que se haga.

Un servidor proxy para un protocolo o para un conjunto de protocolos determinados


se ejecuta en un anfitrión con doble a acceso o con un anfitrión bastión: algún anfitrión con
el que pueda establecer comunicación con el usuario, que pueda, a su vez, comunicarse con
el mundo exterior. El programa cliente del usuario se comunica (“habla”) con este servidor
proxy en lugar de hacerlo directamente con el servidor “real” que está en Internet. El
servidor proxy evalúa solicitudes del cliente y decide cuales pasar y cuáles no. Si una
petición es aprobada, el servidor proxy habla con el servidor real en nombre del cliente (de
ahí el término “proxy”, que significa representante en español) y procede a transmitir las
solicitudes del cliente al verdadero servidor y a transmitir las respuestas de éste de nuevo al
cliente.

Para el usuario, hablar con el servidor proxy es como hablar directamente con el verdadero
servidor. En cuanto a éste último, habla con un usuario en el anfitrión que ejecuta el
servidor proxy; no sabe que el usuario en realidad está en otro lugar.

Un sistema proxy no requiere de hardware especial, aunque si de un software especial para


la mayoría de los servicios.

22
2.2.2 Funcionamiento

Los detalles de cómo funciona un proxy varían de un servicio a otro. Algunos servicios
proporcionan un proxy fácil o automáticamente; para esos servicios, un proxy se instala al
realizar cambios de configuración a los servidores normales. Sin embargo, para la mayoría
de los servicios la instalación de un proxy requiere de un software apropiado para servidor
proxy del lado del servidor. De lado del cliente, necesita uno de los siguientes:

Software cliente personalizado

Con este enfoque, el software debe saber cómo ponerse en contacto con el servidor proxy
en lugar de con el verdadero servidor cuando un usuario hace una solicitud, y cómo decirle
al servidor proxy con cual servidor real conectarse.

Procedimientos personalizados de usuario

Con este enfoque, el usuario utiliza el software cliente estándar para hablar con el servidor
proxy y le dice que se conecte con el verdadero servidor, en lugar de conectarse con el
verdadero servidor directamente.

2.2.3 Ventajas y desventajas del uso de un Proxy

 Ventajas

Los servicios Proxy son buenos para la contabilidad del sistema

Debido a que los servidores Proxy comprenden el protocolo de niveles inferiores, permiten
que se lleve la contabilidad del sistema de una forma muy efectiva.

 Desventajas

Los servicios Proxy podrían requerir servidores diferentes para cada servicio

Quizá necesite un servidor Proxy para cada protocolo, por que el servidor Proxy
debe comprender el protocolo para determinar que permite y que no, y para hacerse pasar
como cliente ante el verdadero servidor y como el verdadero servidor ante el cliente proxy.
Coleccionar, instalar y configurar todos estos servidores puede requerir mucho trabajo.

Los productos y la paquetería difieren mucho en cuanto a la facilidad con la que


pueden ser configurados, pero facilitar las cosas en un lugar puede hacerlas más difíciles en
otros. Por ejemplo, los servidores fáciles de configurar por lo general están limitados en
flexibilidad; son fáciles de configurar porque hacen ciertas suposiciones sobre cómo
piensan que van a ser utilizados, que puede o no ser lo correcto o apropiado para su sitio.

23
2.2.4 Proxy a nivel de aplicación: Protocolo SIP

Un proxy a nivel de aplicación es el que sabe sobre la aplicación específica para la


cual está proporcionando servicios proxy; comprende e interpreta los comandos en el
protocolo de la aplicación. Por otro lado, un proxy a nivel de circuito es el que crea un
circuito entre el cliente y el servidor sin interpretar el protocolo de la aplicación.

Aunque “a nivel de aplicación” y “a nivel de circuito” son términos utilizados a


menudo, con mayor frecuencia distinguimos entre los servidores proxy “dedicados y
“genéricos”. Un servidor proxy dedicado es el que sirve a un solo protocolo; un servidor
proxy genérico es el que sirve a varios protocolos.

Dentro de la arquitectura de VoIP, es necesario el uso de ciertos elementos que


permitan ordenar el tráfico telefónico y a la vez poner en contacto a los diferentes usuarios
de las redes implicadas.

Tal y como trabajan los routers con los datos en general, recibiendo y enviando
peticiones desde y hacia otras maquinas, los diferentes protocolos IP necesitan igualmente
que alguien o algo encamine sus peticiones hacia los usuarios finales, a fin de establecer
una conversación. Esta tarea la realiza un servidor proxy o enrutador, encargándose de rutar
la señalización hacia los sitios adecuados en función de las indicaciones pertinentes que
cada protocolo implementa.

En este contexto, un Proxy SIP, es una entidad intermediaria que actúa como un
servidor y un cliente con el propósito de hacer peticiones en nombre de otros clientes. Un
servidor proxy principalmente juega el papel de enrutamiento, lo que significa que su
trabajo es asegurarse de que una solicitud se envía a otra entidad "más cercana" a los
dirigidos del usuario. Los proxys son también útiles para la aplicación de la política (por
ejemplo, asegurarse de que un usuario se le permite hacer una llamada). Un Proxy
interpreta, y si es necesario, reescribe partes específicas de un mensaje de solicitud antes de
enviarlo.

De esta forma, los Proxy´s se clasifican en 2, de la siguiente manera:

 Stateful Proxy: Es una entidad lógica que mantiene el estado de las transacciones
durante el procesamiento de las peticiones. Permite división de una petición en
varias, con la finalidad de la localización en paralelo de la llamada y obtener la
mejor respuesta para enviarla al usuario que realizó la llamada.

 Stateless Proxy: Una entidad lógica que no mantiene el estado de las transacciones
durante el procesamiento de las peticiones, únicamente reenvían mensajes.

24
Los Proxy’s SIP, son elementos que enrutan peticiones SIP al agente de usuario
servidores y las respuestas SIP a los agentes de usuario clientes. La solicitud puede
atravesar varios Proxy´s en su camino a un UAS. Cada uno hará en el enrutamiento, la
modificación de la solicitud antes de enviarlo a la siguiente elemento. Las respuestas
recorrerá el mismo conjunto de Proxy´s que la solicitud atravesó, en el orden inverso.

Al ser un proxy es una función lógica para un elemento de SIP. Cuando una solicitud
de llega, un elemento que puede desempeñar el papel de un primer indicador decide si es
necesario responder a la solicitud por su propia cuenta. Por ejemplo, la solicitud puede ser
incorrecta o el elemento puede necesitar credenciales del cliente antes de actuar como un
proxy. El elemento puede responder con cualquier código de error apropiado. Al responder
directamente a una solicitud, la elemento es el papel de un UAS.

Figura 4. Esquema de enrutado en un entorno SIP

25
2.3 TECNOLOGÍA VoIP

2.3.1 Introducción a la VoIP

Tradicionalmente, las redes de área local se vienen utilizando para la transmisión de


datos, pero conforme las aplicaciones tienden a ser multimedia y los sistemas de
comunicaciones en vez de ser elementos independientes y aislados para atender un
determinado tipo de comunicación, son servidores de un conjunto más complejo, se tiende
a transmitir cualquier tipo de información sobre los medios existentes. Así, sobre la LAN
corporativa y sobre Internet, unos medios extendidos por la mayor parte de las empresas,
mediante la adopción de ciertos estándares y la incorporación de algunos elementos, es
posible enviar voz y vídeo, con la gran ventaja y ahorro que supone el utilizar la
infraestructura existente.

Sin embargo y mientras que los datos no son sensibles al retardo, a la alteración del
orden en que llegan los paquetes, o la pérdida de alguno de ellos, ya que en el extremo
lejano se reconstruyen, la voz y la imagen necesitan transmitirse en tiempo real, siendo
especialmente sensibles a cualquier alteración que se pueda dar en sus características.
Requieren por tanto de redes que ofrezcan un alto grado de servicio y garanticen el ancho
de banda necesario

2.3.2 Definición

VoIP (Voice Over Internet Protocol) es la posibilidad de enviar paquetes de voz en


tiempo real, conjuntando técnicas y tecnologías que nos permiten, digitalizar la voz y
acondicionarla para que pueda ser transmitida a través de redes de datos basadas en el
protocolo de Internet (IP). VoIP es un grupo de recursos que permiten utilizar las redes IP
para aplicaciones de voz, tales como telefonía, teleconferencias, etc.

Lo que permite tener conversaciones con personas a través de la red, en lugar de


utilizar la telefonía tradicional. La principal ventaja de VoIP es la reducción de costos en
las llamadas realizadas.

2.3.3 Implementación y funcionamiento de telefonía IP

La telefonía IP reúne la transmisión de voz y de datos, lo que posibilita la


utilización de las redes informáticas para efectuar llamadas telefónicas. Además, ésta
tecnología al desarrollar una única red encargada de cursar todo tipo de comunicación, ya
sea de voz, datos o video, se denomina red convergente o red multiservicios.

La telefonía IP surge como una alternativa a la telefonía tradicional, brindando


nuevos servicios al cliente y una serie de beneficios económicos y tecnológicos con
características especiales como:
26
a) Interoperabilidad con las redes telefónicas actuales: Donde se dispone de dos tipos
de Interconexión a la red de telefonía pública, desde una central telefónica IP y
directamente desde una tradicional.

b) Calidad de Servicio Garantizada a través de una red de alta velocidad:


En Telefonía IP el concepto de calidad incluye aspectos como:
- Red de alta disponibilidad que ofrece hasta de un 99,99% de recursos.
- Calidad de voz garantizada (bajos indicadores de errores, de retardo, de
eco, etc.)

c) Servicios de Valor Agregado: como el actual prepago, y nuevos servicios como la


mensajería unificada.

Este modo de telefonía hace uso de un tipo especial de teléfono denominado


Softphone, es un software que hace una simulación de teléfono convencional por
computadora. Es decir, permite usar la computadora para hacer llamadas a otros Softphones
o a otros teléfonos convencionales usando un VSP.
Normalmente, un Softphone es parte de un entorno Voz sobre IP y puede estar basado en el
estándar SIP/H.323 o ser privativo.

2.3.4 Control de la comunicación

Al igual que ocurre en cualquier red, las redes de voz sobre paquetes requieren de
una serie de normas que especifican las funcionalidades y servicios que este tipo de redes
deben proveer en todas y cada una de sus dimensiones. Estas normas son los protocolos, y
un aspecto muy importante es que tengan carácter abierto y que sean internacionalmente
aceptados con el fin de garantizar la interoperabilidad entre productos de distintos
fabricantes, facilitando la elección de los usuarios y disminuyendo los precios de los
equipos al fabricarse estos en mayor escala.

Una vez justificada la necesidad de protocolos, el paso siguiente es determinar que


ámbitos de las redes de voz sobre paquetes deben estandarizarse. Para ello, se analizara a
detalle los pasos implicados en el establecimiento de una llamada.

En las redes telefónicas convencionales, una llamada consta de tres fases:


establecimiento, comunicación y desconexión. Durante el establecimiento se reservan los
recursos necesarios para que, en la fase de comunicación, la información pueda fluir
libremente entre los dos extremos (cliente y servidor). Finalmente, en la desconexión se
liberan los recursos que, previamente, se habían reservado y se pasa la información
necesaria al servidor para que determine la tarifa de dichos recursos. Este esquema continúa
siendo válido aunque con algunos cambios, para las redes de voz sobre paquetes. En estos
casos, tradicionalmente, se han venido distinguiendo tres grandes grupos de protocolos (ver
figura 5), que pueden ir bien sobre TCP y/o UDP, y ambos sobre IP.
27
2.3.5 Parámetros VoIP

Uno de los principales problemas a los que se enfrentan tanto VoIP como todas las
aplicaciones que se integran al protocolo IP, es el garantizar la calidad de servicio sobre
Internet, ya que puede tener limitaciones de ancho de banda en la ruta y por lo tanto no
existe un aprovechamiento óptimo de los recursos que nos provee la red mundial de la
Internet.

2.3.5.1 Códec

La voz ha de codificarse para poder ser transmitida por la red IP. Para ello se hace
uso de códecs que garanticen la codificación y compresión del audio o del video para su
posterior decodificación y descompresión antes de poder generar un sonido o imagen
utilizable. Según el Códec utilizado en la transmisión, se utilizará más o menos ancho de
banda. La cantidad de ancho de banda utilizada suele ser directamente proporcional a la
calidad de los datos transmitidos.

Entre los códecs utilizados en VoIP encontramos los G.711, G.723.1 y el G.729
(especificados por la ITU-T). Estos Códecs tienen este tamaño en su señalización:
 G.711: bit-rate de 56 o 64 Kbps.
 G.722: bit-rate de 48, 56 o 64 Kbps.
 G.723: bit-rate de 5,3 o 6,4 Kbps.
 G.728: bit-rate de 16 Kbps.
 G.729: bit-rate de 8 o 13 Kbps.

2.3.5.2 Protocolos de señalización

El objetivo es establecer un canal de comunicaciones a través del cual fluya la información


de usuario y liberar el anal cuando finalice la comunicación. Para ello, debe existir un
dialogo entre los componentes de la red y entre la red y las terminales de usuario. Son
protocolos de señalización el H.323, SIP y MGCP.

28
2.3.5.3 Protocolos de transporte de voz y ancho de banda de la voz

Son las normas que definen como debe realizarse la comunicación entre los extremos por
un canal de comunicaciones previamente establecido. Los protocolos de transporte más
empleados son RTCP, RTP, UDP y TCP.

Figura 5. Esquema protocolos.

Encapsulamiento de una trama VoIP

Una vez que la llamada ha sido establecida, la voz será digitalizada y entonces
transmitida a través de la red en tramas IP. Las muestras de voz son primero encapsuladas
en RTP (Protocolo de Transporte en tiempo Real) y luego en UDP o TCP antes de ser
transmitidas en una trama IP. La siguiente figura muestra un ejemplo de una trama VoIP
sobre una red LAN y WAN.

Figura 6. Trama VoIP

29
2.3.6 Ventajas

VoIP tiene también algunas desventajas, sin embargo, las ventajas que puede
aportar superan claramente a éstas. A continuación se mencionan algunos de los beneficios
asociados al uso de VoIP y se ve cómo podría mejorar la comunicación por voz:

 Ahorrar Dinero. En una línea RTC, tiempo significa dinero. VoIP emplea Internet
como medio de transporte, donde el único costo que se tiene es la factura mensual
de Internet a tu proveedor de servicio o ISP. Hoy en día el servicio de Internet más
común es una ADSL que se puede emplear de forma ilimitada y conlleva a un costo
fijo al mes. De esta forma, si el ADSL tiene una velocidad razonable, podrá hablar a
través de VoIP con una buena calidad de llamada y el coste seguirá siendo siempre
el mismo.

 Más de dos personas. En una línea de teléfono convencional, únicamente dos


personas pueden hablar al mismo tiempo. Con VoIP, se puede configurar una
conferencia que permite a un grupo de personas comunicarse en tiempo real. VoIP
comprime los paquetes durante la transmisión, algo que provoca que se pueda
transmitir una cantidad mayor de datos. Como resultado, se pueden establecer más
llamadas a través de una única línea de acceso.

 Hardware y software baratos. El único hardware adicional además de una


computadora y conexión a Internet será una tarjeta de sonido, unos altavoces y un
micrófono. Todo este material hasta hoy en día bastante barato. Existen diferentes
paquetes de software descargables desde Internet que emplean VoIP y que sirven
para establecer comunicaciones por voz, algunos con ciertas restricciones, teniendo
que invertir en licencias para habilitar llamadas a cualquier parte del mundo. Lo que
se debe tomar en cuenta es que para comenzar a emplear VoIP no es necesario un
teléfono con todo el equipamiento asociado a este, algo que podría resultar más
caro. Además en la mayoría de los casos no será necesario hacer nuevas
instalaciones de cableado telefónico, ya que VoIP se integra con la red de datos
existente en la gran mayoría de empresas y hogares.

 Prestaciones abundantes, interesantes y útiles. Usar VoIP también significa


beneficiarse de sus prestaciones abundantes, que pueden hacer la experiencia de
emplear VoIP mucho más rica y sofisticada, tanto en el hogar como en el trabajo.
En general, ofrece un mayor equipamiento para la gestión de llamadas. Se podrá,
por ejemplo, hacer llamadas en cualquier lugar del mundo a cualquier destino del
mundo únicamente empleando una cuenta VoIP. De esta forma, la VoIP pasar a ser
un servicio tan portable como el e-mail, es decir, no limita la movilidad del
abonado. Otras prestaciones que ofrece VoIP son el reconocimiento de llamada,
posibilidad de crear números virtuales o el contestador automático, por poner
algunos ejemplos.

 Más que voz. A estar basada en una red de paquetes, VoIP puede manejar también
otros tipos de datos además de la voz: podríamos transmitir imágenes, video o texto
30
a la vez que la voz. De esta forma, se puede hablar con alguien a la vez que se le
envían archivos o incluso a la vez que se le observa a través de una webcam.

 Uso más eficiente de ancho de banda. Se sabe que el 50% de una conversación de
voz es silencio. VoIP rellena estos espacios de silencio con datos de forma que el
ancho de banda de los canales de comunicación no sean desaprovechados. La
compresión y la posibilidad de eliminar la redundancia cuando se transmite voz
serán también factores que elevarán la eficiencia de uso del ancho de banda de la
conexión.

 Esquema de red flexible. La red que encontramos bajo VoIP no necesita tener un
esquema o topología en concreto. Esto hace posible que una organización pueda
hacer uso de la potencia de las tecnologías que elijan, como ATM, SONET o
Ethernet.
Cuando empleamos VoIP, la complejidad de la red inherente en las conexiones
RTC es eliminada, creándose una infraestructura flexible que puede soportar
muchos tipos de comunicación. El sistema estará más estandarizado, requerirá
menos equipamiento y su tolerancia a fallos será mayor.

 Teletrabajo. Si trabajas en una organización que emplea una intranet o extranet,


todavía se podrá acceder a una oficina de trabajo desde casa a través de VoIP. Se
puede convertir el hogar en una parte de la oficina y usar remotamente la voz, el fax
o los servicios de datos del lugar de trabajo a través de la intranet de la oficina. La
naturaleza portátil de la tecnología VoIP está provocando que gane popularidad, ya
que proporciona una gran cantidad de comodidades impensables hace unos años. La
portabilidad tanto de hardware como de servicios se está convirtiendo cada día más
normal, y en ese contexto VoIP encaja perfectamente.

 Fax sobre IP. Los problemas de los servicios de fax sobre RTC son el alto costo que
conllevan para largas distancias, la atenuación de la calidad en las señales
analógicas y la incompatibilidad entre algunas máquinas cuando se comunican. La
transmisión por fax en tiempo real sobre VoIP simplemente utiliza una interfaz de
fax para convertir los datos en paquetes y asegura que éstos serán entregados
completamente y de forma segura.
Otra ventaja de este sistema es que ni siquiera se necesitará una maquina fax para
enviar y recibir fax.

 Desarrollo de software más productivo. VoIP puede combinar diferentes tipos de


datos, enrutándolos y señalizándolos de forma muy flexible y robusta. Como
resultado de esto, los desarrolladores de aplicaciones de red encontrarán más fácil
crear y desplegar aplicaciones que realicen comunicaciones de datos empleando
VoIP. Además, la posibilidad de implementar VoIP en navegadores web y
servidores proporciona un aspecto de gran provecho tanto productivo como
competitivo a esta tecnología.

31
2.4 Protocolo de aplicación SIP

2.4.1 Definición

El protocolo SIP es un protocolo de señalización a nivel de aplicación encargado de


la iniciación, modificación y terminación de sesiones multimedia, las cuales se llevan a
cabo de manera interactiva. Por sesiones multimedia se refiere a aplicaciones de mensajería
instantánea, aplicaciones de video, audio, conferencias y aplicaciones similares.

SIP se definió en el RFC 2543 en marzo de 1999 por el grupo de trabajo MMSC
perteneciente a la IEFT. En junio del 2002, el IETF publicó una nueva revisión del SIP con
el RFC 3261.

El protocolo SIP posee 4 características que lo hacen muy recomendable para


cumplir esta función:

 Localización del usuario. SIP posee la capacidad de poder conocer en todo


momento la localización de los usuarios. De esta manera no importa en qué lugar se
encuentre un determinado usuario. En definitiva la movilidad de los usuarios no se
ve limitada

 Negociación de los parámetros. Posibilidad de negociar los parámetros necesarios


para la comunicación: puertos para el tráfico SIP así como el tráfico Media,
direcciones IP para el tráfico Media, códec, etc.

 Disponibilidad del usuario. SIP permite determinar si un determinado usuario está


disponible o no para establecer una comunicación.

 Gestión de la comunicación. Permite la modificación, transferencia, finalización de


la sesión activa. Además informa del estado de la comunicación que se encuentra en
progreso.

El protocolo SIP es una parte de una arquitectura multimedia, ya que la única


finalidad es la de gestionar las sesiones multimedia: iniciarlas, modificarlas, finalizarlas,
etc. Sin embargo, se integra perfectamente con otros protocolos como RVSP, RTP o RTSP.
Gracias al protocolo SDP se puede formar una completa arquitectura multimedia.

32
´

2.5.1 Conceptos básicos

El protocolo es similar al HTTP por la forma en que funciona (protocolo basado en


texto) y es similar a SMTP en la forma en la que se especifican las direcciones SIP.

Las direcciones SIP identifican a un usuario de un determinado dominio. A estas


direcciones SIP habitualmente se les llama URI (Uniform Resource Identifier). Una URI se
puede especificar de las siguientes maneras:

sip:usuario@dominio[:port]
sip:usuario@direcciónIP[:port]

El dominio representa el nombre del proxy SIP que conoce la dirección IP del
terminal identificado por el usuario de dicho dominio. El puerto por defecto para SIP es
5060, aunque es posible especificar otros adicionales si es necesario.

En la tabla 1 se pueden ver algunos ejemplos de direcciones SIP.

Descripción Dirección SIP


Usuario “200” perteneciente al dominio “esime.ipn.mx” [email protected]
Usuario “200” perteneciente al dominio con dirección IP [email protected]
192.168.1.120

Tabla 1. Ejemplos de direcciones SIP

Nota: en la nomenclatura usuario@direcciónIP, la dirección puede referirse a la IP del


usuario, en un momento determinado, o a su dominio.

Es por tanto posible hacer uso de una dirección IP si no disponemos de un dominio


registrado para este propósito.

2.5.3 Elementos SIP

Para una comunicación SIP es necesaria la intervención de varios elementos, donde


cada uno desempeña su papel. Los elementos de la comunicación son:

Los agentes de usuario (User agent), o de manera abreviada UA, manejan la señalización
SIP. Se pueden dividir en dos categorías:

33
 User agent client (UAC). Es un elemento que realiza peticiones SIP y acepta
respuestas SIP provenientes de UAS. Un ejemplo de UAC es un teléfono VoIP ya
que realiza peticiones SIP.

 User agent server (UAS). Es el elemento encargado de aceptar las peticiones SIP
realizadas por el UAC y enviar a este la respuesta conveniente. Un teléfono VoIP
también es un ejemplo de UAS, ya que acepta peticiones de inicio de comunicación
enviadas por otro teléfono UAC.

Figura 7. Ejemplo de llamada SIP (200 llama a 201).

Los intermediarios necesarios para que la comunicación entre dos UA sea posible:

 Servidor Proxy. Es el elemento encargado de reenviar las peticiones SIP


provenientes de un UAC al UAS destino que corresponde, así como de encaminar
las respuestas de UAS destino del UAC origen. Podemos hacer una similitud con el
encaminamiento que realizan los router con los paquetes a nivel IP, es decir, sería
como el encargado de enrutar los paquetes SIP. Para enrutar, lo que hace es una
traducción de la dirección destino dada de la forma usuario@dominio a la forma
usuario@direcciónIP donde dirección IP es la dirección IP que tiene en ese
momento el teléfono de destino.

Figura 8. Ejemplo de llamada SIP con intermediarios (200 llama a 201)


34
En la figura 8 se observa la función más importante de un proxy SIP, la de enrutar
los mensajes SIP estableciendo así la señalización SIP pertinente.

 Registrar-location server. Acepta las peticiones de registro de los UAC,


guardando toda la información referente a la localización física del UAC, para que
si posteriormente llega una petición con destino el UAC, sea posible localizarlo.
En el ejemplo de la figura 9, para que 200 llame al usuario 201 es necesario que
previamente ambos teléfonos se hayan registrado en servidor de registro. Esto es
necesariamente así porque el proxy SIP necesita conocer la dirección IP del teléfono
201 para enviarle la petición de inicio de conversación y del mismo modo necesita
la dirección IP del teléfono 200 para que pueda enrutarle las respuestas SIP
generadas por el teléfono 201.

Servidor Proxy
Servidor registro - localización

[email protected]  192.168.1.200
[email protected]  192.169.1.201

Figura 9. Proceso de registro

Una vez que los teléfonos se han registrado dentro de servidor, estos pueden
entonces realizar y recibir llamadas entre sí ya que el proxy SIP conoce sus direcciones IP
físicas/reales (mediante consultas). Habitualmente, el proxy SIP y el servidor de “registro-
localización” se encuentran juntos en el mismo software por lo general. Con esto, la
llamada será realizada con éxito.

 Redirect Server. Su funcionamiento es similar al servidor proxy anterior, con la


diferencia que cuando este resuelve la dirección, esto es, realiza la traducción,

35
informa al UAC que realizó la petición SIP para que sea este mismo el que la envíe
hacia el UA destino. Un servidor de redirección actúa realmente como un UAS.

Figura 10. Registro completado

 Back – to – back user agent (B2BUA). Es una entidad intermediaria que procesa
peticiones SIP entrantes comportándose como un UAS, y responde a estas actuando
como un UAC regenerando por completo la petición SIP entrante en una nueva
petición SIP que va a ser enviada.

2.4.5 Mensajes SIP

El dialogo entre clientes y los servidores SIP se basa en el intercambio de mensajes


de texto. Estos mensajes se clasifican en 2, Peticiones y respuestas.

Los mensajes de petición son enviados por las entidades cliente a las entidades servidor.
Generalmente toda petición tiene asociada una respuesta del servidor, excepto el ACK que
no requiere respuesta. Toda respuesta SIP tiene asociado un código numérico que indica el
resultado del intento de servir la aplicación del cliente.

Petición SIP Descripción


INVITE Es la petición SIP que se envía a un usuario cuando queremos
establecer con él comunicación, en este caso una llamada.
ACK Esta petición es enviada por el usuario origen que envió la petición
INVITE para hacer saber al usuario destino que su respuesta OK ha
sido recibida. Es el momento en que ambos pueden empezar a enviar
tráfico Media.
BYE Para finalizar la conexión, la comunicación entre los dos usuarios
36
establecida anteriormente con INVITE.
CANCEL Se utiliza para cancelar una petición, por ejemplo INVITE, que se
encuentra en progreso. Por ejemplo si el teléfono destino está sonando
pero aún no ha sido descolgado y el teléfono origen cuelga, se envía un
CANCEL a diferencia de un BYE que se enviará si el teléfono destino
hubiera sido descolgado previamente y por tanto la comunicación
establecida unos instantes.
OPTIONS Un UA puede enviar peticiones OPTIONS a un UAS para solicitar
cierta información sobre este.
REGISTER Un UAC envía peticiones REGISTER a un servidor de registro-
localización para informar de la posición actual en la que se encuentra
en un momento determinado. Esto hace posible que el UAC pueda ser
localizado haciendo uso de su misma dirección user@dominio sin
importar donde el UAC se encuentre físicamente.

Tabla 2. Peticiones SIP

Respuesta SIP Descripción


1xx Indican el estado temporal de la comunicación.
2xx Informan del éxito de una petición SIP.
3xx Informan que la petición SIP ha de ser reenviada a otro UAS.
4xx Indican errores en el cliente SIP.
5xx Corresponden a errores en el servidor SIP.
6xx Informan de errores generales.

Tabla 3. Respuestas SIP

Cabecera SIP

Las cabeceras que aparecen en los mensajes SIP dependen del tipo de mensaje y de los
parámetros necesarios en cada uno de ellos. Se indican a continuación los campos mas
frecuentes con su significado:

 Accept – Contact: Especifica a que URI debe reenviar el proxy la petición.


 Allow – Events: Lista los eventos soportados.
 Call- ID: Identifica unívocamente.
 Contact: Transporta una URI que identifica el recurso solicitado o al recurso
llamante.
 Content-Encoding: Indica el tipo de codificación aplicada al cuerpo del mensaje.
 Content-Length: Indiga la longitud en octetos, del cuerpo del mensaje.

37
 Content –Type: Indica el tipo de flujo de información transportada en el cuerpo del
mensaje.
 CSeq: Identifica unívocamente transacciones dentro de un dialogo.
 Event: Indica subscripción o notificación a un evento.
 From: Indica el origen de la solicitud.
 Max-Forwards: Limita el número de saltos en un método
 Reason: Indica la razón de finalización de la sesión.
 Refer-To: Contiene el URI o URL referenciado.
 Referred-By: Contiene información sobre el emisor de un mensaje de tipo REFER.
 Reject-Contact: Indica el URI al que el proxy no puede hacer llegar la petición.
 Require: Contiene la enumeración de características que debe soportar un servidor.
 Subject: Indica el asunto de la sesión multimedia.
 To: Inndica el receptor de la petición.
 Via: Se utiliza para grabar la ruta seguida por la petición para utilizarla en la
respuesta.

38
2.5 Protocolo RTP

2.5.1 Definición

PROTOCOLO DE TRANSPORTE EN TIEMPO REAL. RTP

RTP (Real- Time Transport Protocol) es el estándar que define las comunicaciones
de audio y video en tiempo real sobre redes IP, asumiendo, por tanto, la existencia de
pérdidas y retardos y la posibilidad de variación dinámica de las características de la red en
el transcurso de la comunicación. Suministra funciones de transporte extremo a extremo y
ofrece servicios tales como identificación del tipo de carga, numeración de secuencia,
timestamping, etc. No garantiza la entrega de tráfico en tiempo real pero sí suministra los
recursos para que éste se entregue de manera sincronizada. Como su nombre indica, está
orientado a la transmisión de información en tiempo real, como la voz o video.
Las aplicaciones interactivas en tiempo real, incluidas la telefonía IP y la videoconferencia,
prometen controlar gran parte del crecimiento futuro de Internet. Por tanto, organismos de
estandarización como IETF e ITU han estado ocupados durante muchos años en el
establecimiento de estándares para esta clase de aplicaciones. Disponiendo de los
estándares apropiados para las aplicaciones interactivas en tiempo real, empresas
independientes podrán crear nuevos y convincentes productos que interoperen entre sí.

2.5.2 Funcionamiento

Dentro de un proceso de comunicación en tiempo real, el lado emisor de una


aplicación multimedia añade campos de cabecera a los fragmentos de audio/video antes de
pasarlos a la capa de transporte. Estos campos de cabecera incluyen números de secuencia
y marcas de tiempo. Dado que la mayoría de las aplicaciones multimedia de red pueden
hacer uso de los números de secuencia y de las marcas de tiempo (TTL), es conveniente
disponer de una estructura de paquete estandarizada que incluya campos para los datos de
audio/video, los números de secuencia y las marcas de tiempo, así como otros campos
potencialmente útiles. RTP, definido en el documento RFC 3550, es este estándar. RTP
puede emplearse para transportar formatos comunes como PCM, GSM y MP3 para sonido
y MPEG H. 263 para video. Actualmente RTP disfruta de una amplia implementación en
centenares de productos y prototipos de investigación. Además es complementario de otros
importantes protocolos interactivos de tiempo real, como SIP y H.323.

Normalmente, RTP se ejecuta sobre UDP. El lado del emisor encapsula un fragmento
multimedia dentro de un paquete RTP, luego encapsula ese paquete en un segmento UDP y
después pasa el segmento a IP. El lado del receptor extrae el paquete RTP del segmento
UDP, a continuación extrae el fragmento multimedia del paquete RTP y lo pasa al
reproductor multimedia para su decodificación y procesamiento.

39
2.5.3 Encapsulamiento

Cada paquete RTP incluye una cabecera fija y puede incluir también campos de cabecera
adicionales, específicos de la aplicación. La figura ilustra la cabecera fija. Los primeros
doce octetos están siempre presentes y se componen de los siguientes campos:

 Versión (2 bits): la versión actual es 2.

 Relleno (1 bit): indica si los octetos de relleno aparecen al final de la carga útil. Si
es así, el último octeto de la carga útil incluye una cuenta del número de octetos de
relleno. El relleno se utiliza si la aplicación requiere que la carga útil sea un número
entero, múltiplo de alguna longitud, por ejemplo 32 bits.

 Extensión (1 bit): si se establece, la cabecera fija viene seguida por exactamente una
cabecera de extensión, la cual se emplea para ampliaciones experimentales de RTP.

 Cuenta CSRC (4 bits): el número de identificadores CSRC que siguen a ala


cabecera fija.

0 4 8 9 16 31
V P X CC M Tipo de carga Número de secuencia
útil
Marca de Tiempo
Indicador de fuente de sincronización (SSRC)
Identificador de fuente de contribución (CSRC)
.
.
.
Identificador de fuente de contribución (CSRC)

Figura 11. Encapsulamiento RTP

V = Versión
P = Relleno
X = Extensión
CC = Cuenta CSRC
M = Marcador

40
 Marcador (1 bit): la interpretación del bit marcador depende del tipo de carga útil,
normalmente se utiliza para indicar un punto señalado en el flujo de datos.
 Tipo de carga útil (7 bits): identifica el formato de la carga útil RTP, que va a
continuación de la cabecera.
 Número de secuencia (16 bits): permite la detección de pérdidas y la secuenciación
de paquetes en una serie de paquetes que tengan la mima marca de tiempo.
 Marca de tiempo (32 bits): corresponde al instante de generación del primer octeto
de datos de la carga útil. Las unidades de tiempo de este campo dependen del tipo
de carga útil. Los valores han de ser generados desde un reloj local situado en la
fuente.
 Identificador de fuente de sincronización: un valor generado aleatoriamente que
indica de manera exclusiva cual es la fuente dentro de una sesión.
 Identificador de fuente de contribución: identifica una fuente que contribuye con o
añade datos a la carga útil. Este tipo de identificadores son suministrados por un
mezclador.

41
Capítulo III Herramientas

3.1 Sockets

Se denomina socket a un punto de comunicación a través del cual un proceso puede


comunicarse con otro. Los procesos que intercambian información a través de sockets
pueden encontrarse en sistemas diferentes.

3.1.1 Sockets en C#

El entorno de programación C#, proporciona un extenso conjunto de métodos y


propiedades para las comunicaciones en red. Dentro de este, se incluye la biblioteca de
clases “sockets” que permite realizar transferencias de datos síncronos y asíncronos
mediante cualquiera de los protocolos de comunicación.

La clase sockets sigue el modelo de nomenclatura de .NET Framework, proporciona


un extenso conjunto de métodos y propiedades para las comunicaciones en red y permite
realizar transferencias de datos síncronos y asíncronos mediante cualquiera de los
protocolos de comunicación.

Esta comunicación se basa en un esquema donde interactuan cliente y servidor,


haciendo uso de diferentes funciones como se muestra en la figura 12.

Figura 12. Proceso Cliente/Servidor

42
3.1.2 Métodos clase socket

 Bind ( )

Asocia un «nombre» a un socket, es decir, asocia una dirección IP y un puerto al


socket. Normalmente se usará bind en los siguientes casos:

 Para asociar una dirección y un puerto a un servidor, de tal manera que los
clientes sepan en donde encontrar este servicio.

 Un cliente que establezca comunicaciones no orientadas a conexión asociara un


nombre al socket para poder recibir las respuestas a los datagramas que envíe un
servidor.

 Listen ( )

 Se debe llamar tras haber obtenido un descriptor de socket y haberle asignado


un nombre con Bind ( ).

 Tras llamar a listen ( ) para comunicaciones orientadas a conexión, se ejecuta la


función Accept ( ).

 Accept ( )

 Nos permite aceptar una conexión realizada por un cliente a un servidor


orientado a conexión. Esta función tomara la primera conexión que este en la cola
de espera a la cual se hace referencia en el segundo parámetro de la función listen( )
y nos devuelve un descriptor del socket a través del cual poder hacer uso de dicha
conexión.

 Connect ( )

 Permite a un proceso cliente comenzar el proceso de conexión a un proceso


servidor.

 Normalmente la función connect ( ) será invocada por un cliente que quiere


conectarse a un servidor a través de un protocolo orientado a conexión, en este caso
provocara un intercambio de mensajes entre el sistema local y remoto que
culminara en el establecimiento de una conexión o con la devolución de un código
de error.

Cada uno de estos procesos (Un proceso cliente y un proceso servidor) se encuentra
en un extremo de la comunicación, considerándose un socket como la abstracción de este
extremo.

43
3.2 Desarrollo .NET C#

El avance de las herramientas de programación y los dispositivos electrónicos para el


consumidor ha creado nuevos requerimientos. La integración de componentes de software
de diversos lenguajes fue difícil y los problemas de instalación eran comunes, ya que las
nuevas versiones de los componentes compartidos eran incompatibles con el software
anterior.

Como resultado de la popularidad de los dispositivos electrónicos móviles y las


aplicaciones web, los usuarios ya no están restringidos sólo a las computadoras de
escritorio si no que se adquirió una nueva necesidad: software accesible para todos y que
estuviera disponible a través de casi cualquier tipo de dispositivo. Para satisfacer esta
necesidad, Microsoft anuncio el lenguaje de programación C#, este lenguaje esta pensado
para la plataforma .NET como un lenguaje que le permitiera a las programadores migrar
con facilidad hacia .NET. C# tiene sus raíces en C, C++ y Java; adapta las mejores
características de cada uno de estos lenguajes y agrega nuevas características propias.

C# está orientado a objetos y contiene una Biblioteca de Clases que consta de


componentes preconstruidos que permiten desarrollar aplicaciones con rapidez. C# es
adecuado para el desarrollo de aplicaciones demandantes, en especial para l, crear las
aplicaciones populares basadas en la Web actual.

La plataforma .NET es la infraestructura sobre la cual pueden distribuirse aplicaciones


basadas en web a una gran variedad de dispositivos, móviles, teléfonos celulares,
computadoras de escritorio, etc. La plataforma ofrece un nuevo modelo de desarrollo de
software que permite crear aplicaciones en distintos lenguajes de programación, de manera
que se comuniquen entre sí.

C# es un lenguaje de programación visual, controlado por eventos, en el cual se crean


programas mediante el uso de un Entorno de Desarrollo Integrado (IDE). Con un IDE, se
puede desarrollar, crear, ejecutar, probar y depurar programas en C# de manera
conveniente, con lo cual se reduce el tiempo requerido para producir un programa funcional
en una fracción del tiempo que se llevaría si no se utilizara un IDE. La plataforma .NET
permite la interoperabilidad de los lenguajes.

La arquitectura .NET puede existir en varias plataformas, no solo en los sistemas


basados en Microsoft Windows, con lo que extiende la portabilidad de los programas.NET.
Un ejemplo es Mono, un proyecto de software libre de Novell. Otro ejemplo es .NET
Portable de DotGNU.

44
Un componente clave de la arquitectura .NET son los servicios Web, que son
componentes de software reutilizables que pueden usarse a través de Internet. Los clientes y
otras aplicaciones pueden usar los servicios Web como bloques de construcción
reutilizables.

La estrategia de .NET extiende el concepto de reutilización de software hasta Internet,


con lo cual permite que los programadores y las compañías se concentren es sus
especialidades sin tener que implementar cada componente de cada aplicación.

C# es un lenguaje orientado a objetos con seguridad en el tratamiento de tipos, que es a


la vez sencillo y potente y permite a los programadores crear una gran variedad de
aplicaciones. Combinado con .NET Framework, Visual C# permite la creación de
aplicaciones para Windows, servicios Web, herramientas de base de datos, componentes,
controles y mucho más.

Entre las aplicaciones que pueden crearse con C#, están:

 Aplicaciones Web ASP.NET. Describe la utilización del editor de código de C#


en Visual Web Developer para crear aplicaciones Web con páginas de código
subyacente en C#.

 Aplicaciones de Windows Forms. Describe cómo utilizar los formularios


Windows Forms para crear aplicaciones para Windows.

 Aplicaciones de consola. Explica cómo crear aplicaciones que no requieren una


interfaz de usuario gráfica.

 Obtener acceso y mostrar datos. Describe cómo interactuar con bases de datos.

 Aplicaciones móviles e incrustadas. Describe cómo crear aplicaciones para


Smart Device, dispositivos incrustados y dispositivos móviles.

 Crear y obtener acceso a servicios Web. Describe cómo interactuar con


servicios Web XML.

 Crear componentes. Describe la creación de controles de usuario y otros


componentes para .NET Framework.

 Desarrollo en la plataforma Office. Describe la utilización de Visual Studio


Tools para Office para crear documentos inteligentes.

 Desarrollo empresarial. Describe el desarrollo de aplicaciones para SQL Server,


Microsoft Exchange Server, etc.

45
 Programación en Tablet PC. Describe el desarrollo de aplicaciones basadas en
tinta para Tablet PC.

 Audio, vídeo, juegos y gráficos. Describe la utilización de Windows Media y


DirectX para código administrado.

 Crear Starter Kits. Describe cómo crear Starter Kits para ayudar a otros a
ponerse rápidamente en marcha con su código de ejemplo.

Para el desarrollo de nuestra aplicación, emplearemos una Aplicacion de Windows Forms.

Un aplicación Windows es un programa que se ejecuta dentro de un sistema operativo


Windows (Windows 2000, Windows XP, Windows 7, por ejemplo.) y por lo general tiene
una interfaz grafica de usuario (GUI): la parte visual del programa con la que interactúa el
usuario.

Las aplicaciones Windows Form, son aquellas basadas en ventanas y controles comunes de
Windows que se ejecutan en local. En la plataforma .NET el espacio de nombres que ofrece
las clases necesarias para construir aplicaciones de escritorio bajo Windows se denomina
Windows Forms. Este es también el nombre genérico que se le otorga ahora este tipo de
programas basados en ventanas.

Los formularios Windows Forms son la tecnología que se utiliza en Visual C# para crear
aplicaciones para clientes inteligentes basadas en Windows que se ejecutan en .NET
Framework. Cuando crea un proyecto de aplicación para Windows, está creando una
aplicación basada en formularios Windows Forms. Utilizará el Diseñador de Windows
Forms para crear la interfaz de usuario y tendrá acceso a otras funciones de diseño y tiempo
de ejecución:

a. Implementación ClickOnce.

b. Compatibilidad enriquecida de bases de datos con el control DataGridView.

c. Barras de herramientas y otros elementos de interfaz de usuario que pueden tener el


aspecto y comportamiento de Microsoft Windows XP, Microsoft Office o Microsoft
Internet Explorer.

46
El modelo de evento de .NET Framework se basa en la existencia de un delegado de
eventos que conecte un evento a su controlador. Para provocar un evento, se
requieren dos elementos:

 Delegado que identifica el método que proporciona la respuesta al evento.

 Clase que contiene los datos de eventos.

El delegado es un tipo que define una firma, es decir, el tipo del valor devuelto y los
tipos de lista de parámetros de un método. Se puede utilizar el tipo de delegado para
declarar una variable que puede hacer referencia a cualquier método con la misma
firma que el delegado.

La firma estándar de un delegado del controlador de eventos define un método que


no devuelve ningún valor, cuyo primer parámetro es del tipo Object y hace
referencia a la instancia que provoca el evento y cuyo segundo parámetro se deriva
del tipo EventArgs y contiene los datos de evento. Si el evento no genera los datos
de evento, el segundo parámetro simplemente es una instancia de EventArgs. De lo
contrario, el segundo parámetro es un tipo personalizado derivado de EventArgs y
proporciona los campos o las propiedades necesarias para contener los datos de
evento.

EventHandler es un delegado predefinido que representa específicamente un


método controlador para un evento que no genera datos. Si su evento genera datos,
debe suministrar su propio tipo de datos de evento personalizado y crear un
delegado donde el tipo del segundo parámetro sea el tipo personalizado o utilizar la
clase de delegado genérico EventHandler y sustituir el tipo personalizado por el
parámetro de tipo genérico.

Para asociar el evento al método que lo controlará, hay que agregar una instancia
del delegado al evento. Siempre que se produce el evento, se llama al controlador de
eventos, a menos que se quite el delegado.

3.3 SDK SIP.NET4

3.3.1 Descripción

El uso del SDK SIP.NET está orientado al desarrollo de aplicaciones y servicios


basados en el protocolo SIP. Las aplicaciones están dirigidas al diseño de Clientes y
Servidores SIP, soportadas por cualquier lenguaje .NET. Para cuestiones particulares del
proyecto, se utilizará el lenguaje de desarrollo C# .NET.

El SDK proporciona al desarrollador características compatibles con .NET. Para su correcto


funcionamiento es necesario ser incorporado al componente .NET VSS (Virtual Execution
System) y al Framework. Los productos desarrollados con SDK SIP.NET soportan Mono y
CLR Microsoft. Del mismo modo proporciona un conjunto de clases que permiten el

4
Desarrollado por la empresa Konnetic
47
manejo de entidades y elementos que componen el protocolo SIP, dejando como resultado
una biblioteca de clases muy potente para el desarrollo de aplicaciones orientadas a
Software SIP.

El código fuente está escrito en su totalidad sobre Microsoft .NET 2.0 Framework, y corre
en sus versiones 2.0, 3.0, 3.5 y 4.0.
Muchos de los requisitos y demandas para el desarrollo de aplicaciones SIP han dejado que
la biblioteca de clases SIP.NET permita al desarrollador enfocarse en el diseño de
algoritmos orientados a la programación a alto nivel. Pero al mismo tiempo, sigue
permitiendo configuraciones y control de flujo sobre los mensajes SIP a bajo nivel basado
en eventos. Dando como resultado una pila SIP que contiene todas las funciones y servicios
necesarios para el desarrollo estructurado de aplicaciones.

La biblioteca proporciona funciones avanzadas de gestión para multi-hilo de conexión


diseñado para llevar de manera eficiente los entornos de hardware multi-procesador y
multi-núcleo, para lograr alto rendimiento en los procesadores actuales. También permite
un modelo de comunicación fiable mediante el apoyo TCP (Transmisión Control Protocol),
o provee la autenticación y el cifrado mediante el uso de TLS (Transport Layer Security), o
bien permite un mayor rendimiento mediante el uso de UDP (User Datagram Protocol).
Los métodos SIP soportados en la biblioteca incluyen REGISTER, INVITE, OPTIONS,
ACK, BYE, CANCEL, INFO, UPDATE y MESSAGE.

Los SIP URI’s son una parte compleja e importante del protocolo SIP. El SDK SIP.NET
proporciona un tipo de mecanismo seguro para los elementos URI’s derivado de las
bibliotecas de clases System.Uri , System.Uri.Parser y System.Uri.Builder.
Un entorno SIP consiste en un número de entidades conectadas. Estas incluyen, UA (User
Agent), Proxy Server, Registrar Server, Redirect Server y B2BUA (Back-to-Back-User
Agent). Mediante la biblioteca de clases SIP.NET se obtienen las herramientas necesarias
para el desarrollo de este tipo de entidades, así como para implementarlas dentro de alguna
entidad comercial ya desarrollada y existente en el mercado.

En el desarrollo de un cliente y un servidor SIP, es necesario el envío de paquetes de datos,


tomando gran importancia su construcción, encapsulamiento y envío. Para esto la biblioteca
permite la implementación de dichos procesos, asegurando el cumplimiento del estándar
para el protocolo SIP. Por otro lado, se busca que dichas aplicaciones cumplan con la
capacidad de recibir peticiones previamente generadas, en este proceso, la biblioteca
cumple un papel importante para el reconocimiento y análisis de diversas peticiones, y así
realizar acciones en función de lo recibido.

Las peticiones y respuestas generadas y procesadas, están basadas en el documento RFC


3261, que tiene como función estandarizar el desarrollo de aplicaciones basadas en el
protocolo SIP.

La biblioteca acepta y codifica nuevos parámetros de mensaje que no aparecen en la


especificación de mensajes conocidos para la biblioteca, tales como métodos, códigos de
respuesta, extensiones de campos de cabecera (Extension Header Fields) y parámetros de
cabecera. Permite el análisis de mensajes entrantes mediante un motor poderoso DFA
(Deterministic Finite Automaton) para gestionar todo el análisis de cabeceras.
48
La pila SIP puede autenticar cualquier petición SIP utilizando el esquema de autenticación
en conformidad con la especificación en el estándar del protocolo SIP. Tanto la
autenticación cliente como la autenticación Servidor son soportadas dentro de la biblioteca.
La biblioteca SIP se ejecuta en un modo internamente multiprocesos, presentado
singlethreaded o multithreaded. Se utilizan los mecanismos de sincronización para asegurar
seguridad en multithreading a nivel de objetos individuales, tales como cuadros de diálogo
y transacciones, así como grupo de objetos en la capa de transporte.

La configuración de la pila SIP permite incluir los siguientes grupos de parámetros:

 Propiedades por defecto de mensajes SIP


 Limites de mensaje SIP.
 Parámetros de red.
 Valores de temporizadores.
 Incluir valores para localizar servidores Proxys.
 Entre otros.

En la siguiente tabla se muestran los nombres de RFC’s que están incorporados


directamente a la biblioteca SIP.NET. Otros protocolos como TLS no están incluidos
debido a que forman parte de la base .NET Framework y no están incluidos. La tabla
muestra en la primera columna el número de RFC, seguido por el nombre del protocolo, y
finalmente indicando la funcionalidad que carece la biblioteca para implementar dicho
protocolo.

RFC PROTOCOLO FALTA FUNCIONALIDAD

RFC 4566 Session Description Protocol Ninguna

RFC 4320 Actions Addressing Identified Ninguna


Issues
with SIP's Non-INVITE
Transaction
RFC 3596 DNS Extension to Support IP Ninguna
Version 6
RFC 3498 SIP Extension for Instant Ninguna
Messaging
RFC 3581 An Extension to SIP for Ninguna
Symmetric
Response Routing
RFC 3311 SIP UPDATE Method Ninguna

RFC 3264 An Offer/Answer Model with the Ninguna


Session Description Protocol
RFC 3263 Locating SIP Servers Section 4.1: NAPTR/SRV
records being verified against
TLS certificates.
49
Section 4.4: Consideration for
stateless proxies.
RFC 3261 Session Initiation Protocol Section 8.2.7: Stateless UAS
Behaviour
Section 8.3: Redirect Server
Section 10.3: Processing
REGISTER
requests in a registrar
Section 13.2.2: Dialog creation
from multiple 2xx responses
Section 16: Proxy Behaviour
Section 23: S/MIME
RFC 2976 SIP INFO Method Ninguna

RFC 2782 A DNS RR for Specifying the Ninguna


Location of Services (DNS SRV)
RFC 2617 HTTP Authentication: Basic and Ninguna
Digest Access Authentication
RFC 2119 The Naming Authority Pointer Ninguna
(NAPTR) DNS Resource Record
RFC 4475 SIP Torture Test Messages Ninguna

ETSI Conformance Test Specification Proxy, Registrar, Redirect, aún


for SIP no se prueba su funcionalidad.

Tabla 4. Conceptos generales.

Dentro del SDK SIP .NET existen términos que conceptualizan los procesos existentes en
una aplicación orientada a SIP. A continuación se describen algunos de ellos.
 Connection. Se sabe que una conexión es una asociación entre dos puntos finales
que lleva paquetes de datos a través de una red. Cada punto final se representa por
una dirección IP y un puerto, en SIP este concepto es referido como un flujo, en la
unidad SIP .NET API (Figura n), una conexión puede utilizar TLS, TCP o UDP
dentro de la capa de transporte.
La unidad SIP .NET API admite dos tipos de conexiones: entrada y salida. Una
conexión de entrada esta a la escucha de paquetes entrantes en un extremo local
asignado. Las conexiones de salida inician las transmisiones en un extremo local
asignado. Las conexiones de salida suelen utilizar un número de puerto efímero, y
posteriormente, escuchar en ese puerto las respuestas.

50
Figura 13: Arquitectura general de la Unidad SIP.NET API

 Destination Tuple. Una tupla de destino contiene la información necesaria para


conectarse a un dispositivo de red remoto. Es formado por la dirección IP del
dispositivo remoto, el puerto remoto para escuchar y el protocolo de transporte. Los
clientes pueden utilizar el servicio de bibliotecas DNS para resolver direcciones,
puertos y transportes, o puede enviar mensajes directamente a través de una tupla de
destino contenida en el objeto DestinationTuple.
 Dialog. Un dialogo representa una relación SIP punto a punto entre dos o más
clientes de usuario que persiste durante algún tiempo. Es análogo a una
conversación o a una llamada, y algunas veces se refieren a él como tal. Una sesión
es típicamente asociada a un dialogo.
 Header Field. Un campo de cabecera es un componente del mensaje cabecera SIP.
Un campo de cabecera puede aparecer con una o más filas de campo de cabecera.
Las filas de encabezado consisten en un nombre de campo de cabecera y cero o más
valores de campo de cabecera. Múltiples valores de campo de cabecera en una
determinada fila se separan por coma. Algunos campos de cabecera únicamente
pueden tener un simple valor de campo, y como resultado, siempre aparecen como
una fila simple de campo de cabecera.
 Outbound Proxy. Un proxy que recibe peticiones de un cliente, existe aunque su
dirección IP no pertenezca a la dirección IP del servidor resuelta por el campo
Request-URI. Por lo general, un agente de usuario se configura manualmente con
un proxy de salida, o puede conocer uno a través de protocolos de configuración
automático.
51
La sección de configuración ProxyServers permite a la aplicación cliente configurar
el valor por defecto de salida de ProxyServers para los mensajes de petición.
Mecanismos alternos están disponibles para proporcionar servicios de proxy,
incluyendo en el SipCore. Más adelante se explicará el funcionamiento de un objeto
SipCore.
Los servidores proxy son utilizados por el procesador de mensajes salientes para
crearle una ruta al mensaje (a menos que un campo de cabecera route ya esté
presente). El procesador calcula la dirección remota del mensaje de acuerdo al RFC
3261 y RFC 3263 y tiene en cuenta la existencia de servidores proxy de salida, los
campos de cabecera Route y loose routing rules.
Existe una configuración independiente para servidores proxy seguros que se
configuran como rutas de salida para todas las transmisiones seguras. Solo los
servidores proxy con seguridad SIP URI se permiten para transmisiones seguras.
 Route Set. Un conjunto de rutas es una colección URI’s ordenadas o SIP URI que
representa una lista de nodos en la red (por lo general proxys) que necesitan ser
atravesados cuando se envía una petición particular. Un conjunto de rutas pueden
ser aprendidas a través de campos de cabecera como Record-Route, o pueden ser
configurados manualmente.
 Session. Una sesión proporciona el canal de control en el que un cliente de usuario
puede invitar a otro a participar en alguna actividad o intercambio de descripciones
media requeridos para establecer una comunicación multimedia.
 Sip Transaction. SIP es un protocolo basado en transacciones. Las interacciones
entre los elementos de la red se llevarán a cabo en intercambios de mensajes
independientes (Message Exchange Patterns). Una transacción SIP consta de una
sola petición y todas las respuestas a esta. Se encuentran dos categorías de
transacciones: las que inician con una petición INVITE (INVITE Transactions), y
los que no lo son (Generic Transactions).

La unidad SIP .NET API se basa en ciertos recursos externos para su operación. Estos
recursos deben estar disponibles en tiempo de ejecución y los permisos de control de acceso
se deben establecer a fin de que acceda a ellos el subproceso (thread) en ejecución. Los
recursos incluyen:
 Sockets. La biblioteca SIP .NET es una biblioteca en red y requiere un acceso
ilimitado a sockets dentro de ella.
 Archivo IO. La biblioteca SIP.NET debe tener permisos para leer el fichero de
configuración y cualquier otro archivo enlazado dinámicamente.

La Unidad SIP.NET API hace un uso extensivo de hilos (Threads). La biblioteca utiliza llamadas
asíncronas cuando sea posible. El trabajo con hilos se utiliza para invocar la aplicación encargada
de la devolución de llamadas y algunos eventos colocados en subprocesos independientes donde
las respuestas son demandadas.

52
3.4 Configuración objeto SIP Core

El objeto SIP Core es la fachada de la biblioteca SIP.NET (a veces llamado una clase
agregada). Expone importantes eventos, puede controlar los métodos y comportamientos
más significativos de la biblioteca, así como establecer la configuración del sistema y otros
recursos utilizados. El núcleo SIP representado por el objeto SIP Core también se encarga
de la inicialización y terminación de las diferentes capas. El núcleo SIP proporciona un
modelo de eventos que controlan el proceso de entrada y los mensajes salientes, el
procesamiento subsecuente de fallos en la capa de transporte, así como la autenticación y el
estado de datos.

La inicialización de un objeto SIP Core describe diferentes etapas. A continuación se


muestran detalladamente cada una de ellas:

 Creación. Antes de realizar cualquier actividad relacionada con SIP, es necesario


crear e inicializar un objeto SIP Core. En este proceso se lleva a cabo lo siguiente:
o Inicializa un nuevo objeto SipTransportLayer.
o Inicializa un nuevo objeto SipTransactionStateManager.
o Inicializa un nuevo objeto HttpDigestClientAuthenticationManager.
o Analizar cualquier configuración de aplicación (archivo .conf).
o Validar la licencia. 5
o Deserealiza el objeto SipConfiguration.

 Disposición. El objeto SIP Core expone un método finalizador encargado de liberar


recursos no administrados y realiza otras operaciones de limpieza antes de que la
conexión sea llamada por el recolector de basura.

 Propiedades.
o LocalAddressPort. Utilizado por el MessageTransmitter para especificar el
campo de cabecera Via, que para fines de la aplicación será el punto final
donde los mensajes serán devueltos, especificando estos parámetros en la
propiedad “Sentby”. Una aplicación puede proporcionar un nombre de
dominio completo o una dirección IP, si este campo está vacío, el valor por
defecto será la dirección IP local.
o Transport Layer. La propiedad SipTransportLayer se encarga de gestionar la
transmisión de mensajes hacia y desde la red en nombre del objeto SIP Core
reservado en memoria.
o Sip Transaction State. La propiedad SipTransactionStateManager se encarga
de la gestión del estado transaccional y de diálogo, en nombre del objeto SIP
Core.

5
Para el correcto funcionamiento es necesario el uso de una licencia con costo adicional.
53
o ClientCertificates. La transmisión de mensajes TLS requiere que los clientes
proporcionen un certificado para el servidor y establecer una autenticación
mutua. La propiedad ClientCertificates se copia directamente a la propiedad
SipTransportLayer.
o MultiHeaderFormat. El valor de esta propiedad indica si la biblioteca SIP
debe separar múltiples valores de encabezados en las líneas que sean
posibles.

3.5 Trixbox

Como parte de herramienta principal para otorgar el servicio de un PBX, se tomó la


infraestructura que ofrece Trixbox6, una distribución de Linux basada en CentOS, que
otorgará señalización necesaria para registro y autenticación de usuarios SIP dentro de la
red. Colocada e instalada dentro de una maquina virtual para maximizar el uso de una
misma tarjeta de red para el Proxy PBX desarrollado y el PBX de VoIP.

3.6 Cliente Softphone

Para que se puedan mantener una conversación telefónica se necesitan terminales


que puedan procesar la voz humana, transformándola en impulsos eléctricos que son
enviados por la red RTC. Hoy en día, con la llegada de la telefonía IP, la voz es
codificada/decodificada mediante conversores analógicos/digitales y posteriormente (ya
digital) paquetizada y lista para ser enviada por redes Ethernet (u otro tipo de redes IP)
mediante TCP/IP.

3.6.3 Descripción

Los Softphones son teléfonos implementados por software, son programas informáticos que
simulan las funcionalidades de un teléfono convencional, pero ayudados de dos periféricos
habituales: micrófono y auriculares; estos últimos dispositivos, conectados a una
computadora, permiten que la voz pueda ser tratada por el Softphone y así, ser
transformada en paquetes IP.

Un Softphones, proporciona a un dispositivo que no sea un teléfono, como una


computadora o una PDA, las funcionalidades de un teléfono VoIP. Para que esto sea
posible, no es necesario que el dispositivo en cuestión sea muy potente. Simplemente se
necesita un equipo de audio adecuado y alguna forma de conectarse a una red TCP/IP.

Además de las típicas características de un teléfono, los Softphones incorporan


diversas funcionalidades avanzadas, muy presentes en el ámbito de la VoIP, como son
videoconferencia, chat, grabación, multilínea, etc.

6
Distribución de Asterisk basado Software libre
54
Se pueden encontrar modelos que funcionen bajo diferentes protocolos, aunque el mas
usado es el SIP. Entre ellos el más popular es el X-lite, aunque también existen muchos
otros que presentan buenas funcionalidades.

La ventaja principal de un Softphone sobre un teléfono VoIP, es el costo. En muchas


empresas de debe instalar como mínimo, un teléfono y una computadora en cada escritorio.
Si pudiéramos quitar el teléfono se produciría un ahorro considerable. Además, hay una
gran cantidad de Softphones y la mayoría de sistemas operativos ya vienen con alguno
instalado por defecto.

3.6.4 X-lite

X-Lite fue desarrollado por CounterPath, y es el principal Softphone libre SIP del mercado
disponible para la transferencia directa.

Configuración del Softphone X-lite, se lleva a cabo de la siguiente manera:

1. Una vez instalado el Softphone (por ser software libre puede ser descargado de la
página del fabricante CounterPath), se procede a hacer la configuración pertinente.
2. Seleccionamos “SIP Account Settings” y aparecerá la pantalla de la figura 14,
oprima “Add”.

Figura 14. SIP Account Settings

Para agregar una cuenta SIP se deben introducir ciertos parámetros como se muestra en la
figura 15.

55
Figura 15. Propiedades de configuración de una cuenta SIP

a) Display Name: El Display Name es un identificador de nombre de usuario.

b) User name: El username es un identificador, de tipo numérico, proporcionado por el


servidor para el control de acceso

c) Password: Es la contraseña de acceso asociada al username.

d) Authorization user name: Utilizado para verificar la autentificación del usuario


dentro del PBX.

e) Domain: Es identificado por una dirección IP o un nombre registrado en un servidor


de nombres de dominio (DNS) e indica el dominio al que pertenece el cliente.

En la opción de elegir un dominio proxy, se presentan tres diferentes modos de selección de


dominio (Figura 16), la primera opción “domain” consiste en seleccionar un servidor proxy
implícito en el mismo nombre de dominio donde fue registrado el teléfono, en este caso
expresado mediante la dirección IP 1.1.1.10. La segunda opción ”proxy” corresponde a un
nombre de dominio expresado fuera del servidor donde fue registrado el teléfono,
asociando una dirección IP a este campo. Para fines del proyecto, la dirección IP 1.1.1.1
corresponderá al Proxy PBX desarrollado. Por último, la tercera opción “target domain” es
la opción por default cuando no cuenta con un servicio proxy.

56
Figura 16. Configuración de cliente SIP

Una vez configurados estos parámetros, oprimimos “Aceptar” y regresaremos a la ventana


“SIP Accounts” y aparecerá la cuenta que acabamos de configurar (Figura 17). Para
finalizar, haremos click en el boton “Close”.

Figura 17. SIP Accounts, cuenta configurada

Una vez realizado este proceso, el Softphone X-lite está listo para realizar y recibir
llamadas (Figura 18).

57
Figura 18. Teléfono registrado y autenticado

58
Capítulo IV Desarrollo

Una vez reunidas las herramientas necesarias para realizar el Proxy PBX, se inicia
el desarrollo de una aplicación basada en un entorno orientado a Windows, que llevará el
control y gestión de los procesos necesarios para el registro y subscripción de clientes SIP
así como la iniciación y finalización de llamadas SIP.

Tomando en cuenta que para el envío de paquetes a nivel de transporte existen dos
enfoques principales necesarios para la comunicación entre aplicaciones, se encuentran las
orientadas a conexión y no orientadas a conexión. En las comunicaciones orientadas a
conexión, se establece una conexión que se mantiene durante el tiempo que dure la sesión.
Los servicios sin conexión no garantizan confiabilidad, los datos pueden tomar rutas
distintas dentro del sistema, llegar después o no llegar.

Los principales protocolos para el transporte de datos son: Protocolo de control de


transmisión (TCP) orientado a conexión y el Protocolo de datagramas de usuarios (UDP)
no orientado a conexión.

Para fines de esta aplicación, emplearemos el protocolo UDP. Las llamadas que
cursan sobre una red de datos no requieren de la garantía de transmisión confiable de un
extremo a otro, ya que en una conversación telefónica no es necesaria la retransmisión de
voz. UDP incurre en una mínima sobrecarga, necesaria para la comunicación entre
aplicaciones, además de reducir el tráfico debido a la ausencia de intercambio,
retransmisiones, etc.

Aplicaciones como audio y video en tiempo real pueden tolerar la pérdida ocasional
de datagramas, cuando esto sucede se produce una pequeña pausa en el audio o video que
se esté reproduciendo.

4.1 Desarrollo de software de comunicación IP usando socket

Como un primer acercamiento a la programación de aplicaciones cliente-servidor, se


realizaron una aplicación cliente y una aplicación servidor, en el entorno de programación
Visual C# .NET, utilizando la biblioteca de clases “Sockets” con el espacio de nombres
System.Net.Sockets, utilizando el protocolo TCP.

Para la aplicación servidor, se utiliza un objeto de tipo TcpListener que tiene la capacidad
de esperar solicitudes de conexión, a este objeto se le asocia un número de puerto y una
dirección IP especifica, representada por un objeto de la clase IPAddress, del espacio de
nombres System.Net.

El servidor escucha de forma indefinida, hasta que un cliente trata de conectarse con el, el
servidor crea una conexión con el cliente cuando este le envía una solicitud de conexión.

59
1 public void EjecutarServidor()
2 {
3 TcpListener oyente;
4 int contador = 1;
5
6 //espera la conexion de un cliente y muestra el texto que envía el cliente
7 try
8 { //crea TcpListener
9 IPAddress local = IPAddress.Parse("1.1.1.1");
10 oyente = new TcpListener(local, 50000);
11
12 //TcpListener espera la solicitud de conexion
13 oyente.Start();
14
15 //establece la conexion con base a la solicitud del cliente
16 while (true)
17 {
18 MostrarMensaje("Esperando Conexión\r\n");
19
20 //acepta una conexion entrante
21 conexion = oyente.AcceptSocket();
22
23 //crea objeto NetworkStream asociado con el socket
24 socketStream = new NetworkStream(conexion);
25
26 //crea objetos para transferir datos a través de un flujo
27 escritor = new BinaryWriter(socketStream);
28 lector = new BinaryReader(socketStream);
29
30 MostrarMensaje("Conexión " + contador + " recibida\r\n");
31
32 //Informa al cliente que la conexión fue existosa
33 escritor.Write("SERVIDOR>> Conexión Existosa");
34
35
36 DeshabilitarEntrada(false); //habilita la entrada de datos del cliente
37
38 string larespuesta = "";
39
40 //Lee los datos de cadena que envía el cliente
41
42 do
43 {
44 try
45 {
46 //lee la cadena que envía el cliente
47 larespuesta = lector.ReadString();
48
49 //muestra el mensaje
50 MostrarMensaje("\r\n" + larespuesta);
51 }//fin de try
52 catch (Exception)
53 {
54 //maneja la excepción si hay error al leer los datos
55 MostrarMensaje("\r\n Error al leer los datos delcliente\r\n");
56 break;
57 }//fin de catch
58 } while (larespuesta != "CLIENTE>>TERMINAR" &&
60
59 conexion.Connected);
60
61 MostrarMensaje("\r\nEl Cliente terminó la comunicación\r\n");
62
63 //Se cierra la comunicación
64 escritor.Close();
65 lector.Close();
66 socketStream.Close();
67 conexion.Close();
68
69 DeshabilitarEntrada(true); //Deshabilita la entrada de datos
70 del cliente entradaTextBox
71 contador++;
72 }//fin de while
73 }//fin de try

Sección de Código 1. Creación de aplicación Servidor TCP

Figura 19. Interfaz de aplicación Servidor TCP

61
Por otro lado, para la aplicación cliente, es necesario crear un objeto de la clase TcpClient
(espacio de nombres System.Net.Sockets) para realizar la conexión con el servidor. La
conexión se establece al llamar al método Connect de TcpClient.

1 public void EjecutarCliente()


2 {
3 TcpClient Cliente;
4 try
5 {
6 MostrarMensaje("Tratando de conectar\r\n");
7 Cliente = new TcpClient();
8 Cliente.Connect("148.204.36.11", 50000);
9 salida = Cliente.GetStream();
10 escritor = new BinaryWriter(salida);
11 lector = new BinaryReader(salida);
12 MostrarMensaje("\r\n SE RECIBIERON FLUJOS DE E/S \r\n");
13 DeshabilitarSalida(false);
14 do
15 {
16 try
17 {
18 mensaje = lector.ReadString();
19 MostrarMensaje("\r\n" + mensaje);
20 }
21 catch (Exception)
22 {
23 System.Environment.Exit(System.Environment.ExitCode);
24 }
25 }
26 while (mensaje != "SERVIDOR>>TERMINAR");
27 escritor.Close();
28 lector.Close();
29 salida.Close();
30 Cliente.Close();
31 Application.Exit();
32 }
33 catch (Exception error)
34 {
35 MessageBox.Show(error.ToString(), "Error en la conexion",
36 MessageBoxButtons.OK, MessageBoxIcon.Error);
37 System.Environment.Exit(System.Environment.ExitCode);
38 }
39 }

Sección de código 2. Creación de aplicación Cliente TCP

En la seccion de código 2, se muestra el proceso de comunicación basado en socket TCP,


donde se crea una instancia de tipo TCPClient encargada del envío y recepción de datos. El
proceso se inicia con la conexión a un servidor localizado con la dirección IP
“148.204.36.11” y un puerto de escucha en el 5000, posteriormente se crean dos instancias
de tipo BinaryWriter para leer datos recibidos y escribir datos para ser enviados.

62
La condición de paro necesaria para el fín de la comunicación, estará controlada por la
cadena “SERVIDOR>>TERMINAR”. En ese momento se liberan recursos y se finaliza el
proceso Socket.

Figura 20. Interfaz de aplicación Cliente TCP

63
4.2 Captura y análisis de Mensajes SIP

Como parte del análisis de protocolos en red, se utilizó una herramienta orientada al
monitoreo de tráfico en la red7, la siguiente imagen es captado mediante un sniffer de
código abierto encargado de capturar los paquetes SIP utilizado en el proceso de
comunicación entre Softphone – Proxy y Proxy – PBX.

Figura 21: Analizador de tráfico en red, captura de mensajes SIP.

En la figura 21 se muestra la captura de un mensaje SIP utilizado para el monitoreo de


registro y subscripción de un cliente Softphone, observando los campos de cabecera
incluidos dentro de un paquete. Los paquetes de datos están presentes en uno o varios de
los procesos en la comunicación existente con la aplicación Proxy PBX, siendo de gran
importancia el reconocimiento y procesamiento de paquetes SIP.

4.1.1 Autentificación de Softphone en el PBX VoIP

Para el proceso de autenticación de un Softphone, se incluyen diferentes procesos


necesarios para que dicho teléfono quede integrado en un Servidor de registro, y
posteriormente tenga la capacidad de enviar y recibir llamadas, mediante el enrutamiento
realizado por el Proxy PBX.

Como se menciono anteriormente existen peticiones y respuestas que forman parte del
proceso de comunicación Cliente - Servidor y Cliente – Cliente. Para el caso de la
autenticación de un teléfono IP basado en Software o cualquier teléfono soportado por la
tecnología VoIP, se hace referencia a las siguientes peticiones y respuestas SIP.

7
Analizador de tráfico distribuido por The Wireshark Team.
64
Como primer proceso de autenticación, es necesario que un cliente se encuentre alojado en
un servidor de registro, proporcionándole un nombre de usuario, contraseña y un nombre de
autorización para iniciar sesión.

Para que el cliente tenga una localización física es necesario que envíe estos parámetros a
través de la trama REGISTER, esperando una contestación satisfactoria mediante una
respuesta OK con 1 Binding llamado así al proceso de conexión entre Cliente- Servidor.

En la siguiente figura se muestra la trama para la petición REGISTER, que inicialmente se


envía cada vez que un teléfono inicia comunicación en red.

Figura 22: Trama de una petición REGISTER

La funcionalidad del Proxy PBX durante este proceso, es decidir el rumbo de la trama,
esperando la localización física del usuario mediante un servidor de registro. Obteniendo
así, la captación de todo el tráfico, y esperando un enrutamiento adecuado hacia el destino
final asociándole una dirección IP y un puerto para futuras conexiones.

65
El proceso de autenticación y registro se muestra en el siguiente diagrama (Figura 23).

Figura 23. Proceso de autenticación y registro de un UAC.

El inicio de localización de un usuario dentro de la red se ejecuta mediante el envío de una


trama REGISTER. El proxy PBX mediante el objeto SIP CORE, será el encargado de
procesar y enrutar todos los paquetes de datos, ejecutando como primer proceso la
transmisión de la trama REGISTER al Servidor de Registro. Seguido de una contestación
de Unauthorized debido a la falta de credenciales para autentificación dentro del PBX.

El cliente Softphone envía nuevamente una trama REGISTER incluyendo las credenciales
necesarias para ser registrado y autenticado. Al llegar dichos parámetros al PBX envía una
respuesta de estado completo OK (1 Binding) indicando al cliente su localización física y
registro. Al ser registrado satisfactoriamente, el PBX necesita conocer información acerca
de la capacidad del cliente para soportar ciertos servicios y funcionalidades necesarias para
el proceso de comunicación, para esto el PBX envía una trama OPTIONS incluyendo estos
parámetros, retransmitiendo las veces que sean necesarias para conocer el estado del cliente
Softphone.

Siguiendo con el proceso de registro, el cliente solicita al PBX una subscripción, iniciando
este proceso con el envío de una trama SUBSCRIBE, que incluirá los parámetros que
requiere el cliente para entrar en un estado de suscripción. Siguiendo la misma
metodología, el PBX solicita sus credenciales para completar el proceso, y aquí
nuevamente el Proxy PBX encamina los datos hasta el cliente. Una vez solicitadas al
cliente las credenciales de suscripción, retransmite la trama SUBSCRIBE incluyendo los
parámetros solicitados y concluyendo con estado completo OK.

66
Finalmente el PBX envía una trama NOTIFY que indica un estado de notificación,
necesaria para que el cliente conozca su ubicación y propiedades con las que fue registrado
suscrito.

Al concluir el proceso de autenticación como propósito general, el Proxy PBX almacenará


los valores de nombre de usuario, Display Name, dirección IP, Puerto y campo Vía para el
reconocimiento de usuarios registrados y así tener un control en el enrutamiento y
procesamiento de peticiones y respuestas relacionadas con cada usuario.

4.3 Desarrollo de Software Proxy basado en transacciones SIP

El protocolo SIP está orientado a transacciones, es decir, en las interacciones entre


los componentes tienen lugar en una serie de intercambios de mensajes independientes.
Concretamente una transacción SIP consta de una única solicitud y las respuestas a esta
solicitud, pueden ser provisionales y o definitivas.

Las transacciones tienen un cliente y un servidor. El lado del cliente se conoce como
una transacción cliente y del lado del servidor como una transacción servidor. La
operación cliente envía la solicitud, y la transacción servidor envía la respuesta.

Las transacciones cliente y servidor son funciones lógicas que están incrustadas en
cualquier número de elementos. En concreto, existen dentro de los agentes de usuario y los
servidores Proxy de estado.

En el ejemplo de la figura 248, un UAC ejecuta la transacción cliente, y su


Proxy de salida (outbound) ejecuta la transacción servidor. En el Proxy de salida también se
ejecuta una transacción cliente, la cual envía la solicitud a la transacción servidor del Proxy
de entrada (inbound). Ese proxy también ejecuta una transacción cliente, que a su vez envía
la solicitud a la transacción servidor en la UAS.

Figura 24. Transacciones SIP mediante un Proxy

Dentro de la biblioteca de clases explicada en la sección 3.3, es posible crear objetos de tipo
SIP Core, capaces de generar eventos de tipo Server Transaction y Client Transaction,
estos eventos son útiles en el momento que se requiere procesar solicitudes y respuestas
para enrutarlas y así lograr comunicación entre Clientes y Servidores.

Con base a lo anterior, se tiene el siguiente diagrama general de transacciones incluidas en


el desarrollo del proyecto (Fig 25).

8
RFC 3261 SIP: Session Initiation Protocol, Seccion 17, pag. 122.
67
Figura 25. Diagrama de transacciones incluidas en el Proxy PBX

68
Las siguientes líneas de código, ejecutan las transacciones que serán útiles para el
proceso de comunicación mediante el Proxy PBX, con el evento ProxyPBX_Load se carga
dentro del proyecto el método general para realizar las transacciones necesarias que
ayudarán al funcionamiento del Proxy PBX.
1 private void ProxyPBX_Load(object sender, EventArgs e)
2 {
3 EjecutarTransaction();
4 }
5
6 public void EjecutarTransaction()
7 {
8 CoreServerT = new SipCore();
9 System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
10 CoreServerT.LocalAddressPort = new IPDomainPort(localAddress, 5060);
11 CoreServerT.StartListening(new IPEndPoint(localAddress, 5060),
12 TransportProtocol.Udp);
13 CoreServerT.ServerTransactionCreated += new
14 EventHandler<TransactionEventArgs>(OnServerTransactionCreated);
15 }
16
17 private void OnServerTransactionCreated(object sender, TransactionEventArgs e)
18 {
19 ServerTransaction trans = (ServerTransaction)e.Transaction;
20 if (trans.OriginalRequest.Method == SipMethod.Register)
21 {
22 CoreClientT = null;
23 CoreClientT = new SipCore();
24 System.Net.IPAddress localAddress =
25 System.Net.IPAddress.Parse("1.1.1.1");
26 CoreClientT.LocalAddressPort = new IPDomainPort(new
27 IPEndPoint(localAddress, 5060));
28
29 SipRequest RegisterRequest = e.Transaction.OriginalRequest;
30 RegisterRequest.RemoveHeader("Via");
31 ViaHeaderField FieldVia = new ViaHeaderField(new
32 IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
33 FieldVia.Branch = ViaHeaderField.NewBranch();
34 FieldVia.ProtocolName = "UDP";
35 FieldVia.ProtocolVersion = "2.0";
36 FieldVia.SentBy = new
37 IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060);
38 RegisterRequest.AddHeader(FieldVia);
39 ClientTransaction transaction =
40 SipTransaction.CreateClientTransaction(RegisterRequest, CoreClientT,
41 true);
42 RegisterRequest.SetTransaction(transaction);
43 RegisterRequest.ResponseReceived += new
44 EventHandler<ResponseReceivedEventArgs>(OnRegisterResponseReceived);
45 CoreClientT.SendRequest(RegisterRequest);
46 }
47
48 if (trans.OriginalRequest.Method == SipMethod.Subscribe)
49 {
50 CoreClientT = null;
51 CoreClientT = new SipCore();
52 System.Net.IPAddress localAddress =
53 System.Net.IPAddress.Parse("1.1.1.1");

69
54 CoreClientT.LocalAddressPort = new IPDomainPort(new
55 IPEndPoint(localAddress, 5060));
56
57 SipRequest SubscribeRequest = e.Transaction.OriginalRequest;
58 SubscribeRequest.RemoveHeader("Via");
59 ViaHeaderField FieldVia = new ViaHeaderField(new
60 IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
61 FieldVia.Branch = ViaHeaderField.NewBranch();
62 FieldVia.ProtocolName = "UDP";
63 FieldVia.ProtocolVersion = "2.0";
64 FieldVia.SentBy = new
65 IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060);
66 SubscribeRequest.AddHeader(FieldVia);
67 ClientTransaction transaction =
68 SipTransaction.CreateClientTransaction(SubscribeRequest, CoreClientT,
69 true);
70 SubscribeRequest.SetTransaction(transaction);
71 SubscribeRequest.ResponseReceived += new
72 EventHandler<ResponseReceivedEventArgs>
73 (SubscribeRequest_ResponseReceived);
74 CoreClientT.SendRequest(SubscribeRequest);
75 }

Sección de Código 3. Creación de transacciones SIP

4.4 Desarrollo de software Proxy para autenticar Softphone

Una de las funciones principales de la aplicación Proxy PBX, es la autenticación de


usuarios (Softphone) y el registro de éstos dentro de la red y así mismo, su localización
mediante el envío de paquetes de datos, para esto el Software Proxy manipulará, en función
de peticiones y respuestas, la señalización necesaria para proporcionar un registro exitoso
mediante su identificación en un Servidor de Registro.

Para este propósito, se hace uso de la extensa variedad de clases contenidas en el SDK para
protocolo SIP (sección 3.3). Entre ellas la clase principal SIP CORE que generará los
procesos necesarios para el procesamiento de múltiples peticiones y respuestas. Dentro de
esta misma clase, se permite el envío de paquetes definidos para cada propósito, teniendo la
tarea de construir tramas para los métodos solicitados. Por otro lado, tomando respuestas
asociadas a una petición será necesario el manejo de datos de una manera estructurada,
utilizando listas enlazadas se almacenarán parámetros necesarios para la gestión de la
comunicación.

70
En la siguiente figura se muestra la estructura general de un nodo incluido en una
lista necesaria para la asociación entre peticiones y respuestas relacionadas con un UAC.

Anterior DisplayName Username DireccionIP Puerto Via Siguiente

Figura 26. Nodo perteneciente a la clase NodoListaSoftphone

Dentro de este nodo será necesario actualizar los parámetros en tiempo de ejecución en
función de las peticiones y respuestas asociadas con cada UAC. Para la declaración de
instancias dentro de la clase NodoListaSoftphone, se construyó la siguiente estructura,
mostrada en la figura Sección de código 4:

1 public class NodoListaSoftphone


2 {
3 public NodoListaSoftphone anterior;
4 public string DisplayName;
5 public string Username;
6 public string DireccionIP;
7 public string Puerto;
8 public string Via;
9 public NodoListaSoftphone siguiente;
10 public NodoListaSoftphone(string DisplayName, string Username, string
11 DireccionIP, string Puerto, string Via)
12 : this(null, DisplayName, Username, DireccionIP, Puerto, Via, null)
13 { }
14 public NodoListaSoftphone(NodoListaSoftphone anterior, string
15 DisplayName, string Username, string DireccionIP, string Puerto, string
16 Via, NodoListaSoftphone siguiente)
17 {
18 this.anterior = anterior;
19 this.DisplayName = DisplayName;
20 this.Username = Username;
21 this.DireccionIP = DireccionIP;
22 this.Puerto = Puerto;
23 this.Via = Via;
24 this.siguiente = siguiente;
25 }
26 public NodoListaSoftphone ANTERIOR
27 {
28 get { return anterior; }
29 set { anterior = value; }
30 }
31 public string DISPLAYNAME
32 {
33 get { return DisplayName; }
34 set { DisplayName = value; }
35 }
36 public string USERNAME
37 {
38 get { return Username; }

71
39 set { Username = value; }
40 }
41 public string DIRECCIONIP
42 {
43 get { return DireccionIP; }
44 set { DireccionIP = value; }
45 }
46 public string PUERTO
47 {
48 get { return Puerto; }
49 set { Puerto = value; }
50 }
51 public string VIA
52 {
53 get { return Via; }
54 set { Via = value; }
55 }
56 public NodoListaSoftphone SIGUIENTE
57 {
58 get { return siguiente; }
59 set { siguiente = value; }
60 }
61 }

Sección de Código 4: Definición de estructura de datos asignada a cada usuario dentro de


la red

La clase NodoListaSoftphone, es considerada una clase autoreferenciada, ya que contiene


miembros de referencia que hacen referencia a un objeto del mismo tipo de clase. En las
líneas de código 3 y 9 de la sección 4, se definen las referencias anterior y siguiente. Los
miembros anterior y siguiente hacen referencia a un objeto de tipo NodoListaSoftphone,
observando la declaración de un objeto del mismo tipo, de ahí el término de clase
autoreferenciada.

Dentro de esta clase también contiene los miembros necesarios para el control de
enrutamiento de peticiones y respuestas. Para ello se definen las propiedades DisplayName,
Username, DireccionIP, Puerto y Vía.

La propiedad DisplayName define el nombre de usuario utilizado para identificar a un


teléfono a nivel de usuario, que será utilizada para el control de acceso a un registro de
usuarios en tiempo real.

La propiedad Username define un identificador de usuario proporcionado por el PBX para


hacer única la localización de un teléfono dentro de la red IP.

La propiedad DireccionIP define una dirección lógica IPv4 utilizada para la identificación
única a nivel de capa de red para cada teléfono, con esta propiedad el Proxy PBX, en
función de peticiones o respuestas, elegirá el destino adecuado.

La propiedad Puerto define un valor asociado a un cliente a nivel de capa de transporte, por
el se envían las peticiones iniciales y se espera que ahí sean contestadas con el fin de evitar
la pérdida de datos. Para el propósito en particular del proyecto, cada cliente Softphone

72
dispone de un rango de puertos efímeros disponibles para la comunicación, definidos en el
protocolo UDP.

Por último, se define la propiedad Vía que contendrá el campo de cabecera existente en la
trama SIP, que será actualizado junto con las demás propiedades cada que inicie una nueva
petición el UAC.

4.5 Desarrollo de software proxy para iniciar y finalizar una llamada.

Una vez registrados los clientes con el PBX a través del Proxy PBX, se inicia el proceso de
comunicación a través de la trama INVITE, donde un cliente solicita establecer sesión con
un usuario final, para esto, la aplicación desarrollada será capaz de verificar si el usuario
final se encuentra en disponibilidad de aceptar una llamada, o en otro caso, verificar si
existe o no el usuario final.

El procesamiento de la trama INVITE se lleva a cabo en un proceso interno de la aplicación


Proxy PBX, donde recibe la petición inicial, verifica el usuario final y toma la decisión de
enrutarla o denegarla. En la figura 27 se muestra el proceso de inicio y fin de sesión basado
en transacciones SIP.

Figura 27. Proceso de inicio y fin de llamada.

El cliente Softphone1 Xlite inicia la sesión enviando una trama INVITE al objeto SIP
CORE que será el encargado de enrutar las llamadas a un destino final, la aplicación Proxy
PBX internamente trabaja con un objeto de este tipo para iniciar las transacciones
necesarias y localizar dentro de la red al Softphone Xlite. La ejecución de este proceso
estará en función de las peticiones realizadas al objeto SIP CORE tomando como parámetro
principal que el método recibido dentro de la petición está relacionado con el método SIP
INVITE. En la sección de código 5 se explica el reconocimiento del método para este
proceso y la ejecución de envío y recepción de tramas relacionadas con el inicio de sesión.

73
1 if (trans.OriginalRequest.Method == SipMethod.Invite)
2 {
3 InviteServerTransaction InviteTrans =
4 (InviteServerTransaction)e.Transaction;
5 CoreClientT = null;
6 CoreClientT = new SipCore();
7 System.Net.IPAddress localAddress =
8 System.Net.IPAddress.Parse("1.1.1.1");
9 CoreClientT.LocalAddressPort = new IPDomainPort(new
10 IPEndPoint(localAddress, 5060));
11 string CampoVia;
12 string IP;
13 string Puerto;
14 CampoVia = trans.OriginalRequest.ViaHeaders.ToString();
15 char[] sep = { ' ', ':', ';' };
16 string[] part = CampoVia.Split(sep);
17 IP = part[3];
18 Puerto = part[4];
19 string dname;
20 string username;
21 char[] tok = { '"', '"', ':', '@' };
22 string from = trans.OriginalRequest.From.ToString();
23 string[] part2 = from.Split(tok);
24 dname = part2[2];
25 username = part2[4];
26 listaCliente.Insertar(dname, username, IP, Puerto, Via);
27 listaRegistro.Insertar(username, IP, Puerto);
28 char[] tok2 = { ':', '@' };
29 string To = trans.OriginalRequest.RequestUri.AbsoluteUri.ToString();
30 string[] part3 = To.Split(tok);
31 string usernameDestino = part3[1];
32 string callIDpar = trans.OriginalRequest.CallId.ToString();
33 string[] parametros = listaRegistro.Buscar(usernameDestino);
34 string DNDestino = trans.OriginalRequest.To.DisplayName.ToString();
35 string Fecha = DateTime.Now.Date.ToString();
36
37 SipResponse RingingResponse = new
38 SipResponse(InviteTrans.OriginalRequest, SipStatusCode.Ringing);
39 System.Net.IPAddress RemoteAddress = System.Net.IPAddress.Parse(IP);
40 DestinationTuple destination = new DestinationTuple(new
41 IPEndPoint(RemoteAddress, int.Parse(Puerto)), TransportProtocol.Udp);
42 CoreServerT.SendResponseDirect(RingingResponse, destination);
43 listaReportes.Insertar(callIDpar, dname, username, IP, DNDestino,
44 usernameDestino, parametros[1], Fecha);
45
46 InviteRequest Invite = new InviteRequest();
47 ViaHeaderField FieldVia = new ViaHeaderField(new
48 IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
49 FieldVia.Branch = ViaHeaderField.NewBranch();
50 FieldVia.ProtocolName = "UDP";
51 FieldVia.ProtocolVersion = "2.0";
52 FieldVia.SentBy = new
53 IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060);
54 Invite.AddHeader(FieldVia);

Sección de código 5. Gestión de envío de trama INVITE a un usuario final.

74
Para que un cliente destino localice el usuario fuente, será necesario que el Proxy PBX
envíe la señalización necesaria para el inicio de sesión, como se muestra en la sección de
código 4, el objeto SIP CORE hace un criterio de análisis para determinar si la transacción
Servidor reconoce un método de tipo INVITE, si esta condición se cumple, envía como
respuesta inmediata una trama de procedimiento 180 (RINGING), que será llevada a un
estado de completo con un OK para indicar que la sesión fue aceptada por el cliente
destino.

4.6 Desarrollo de software Proxy PBX para generar reportes de llamadas.

Para generar el Reporteador de llamadas dentro de la red, se utilizó una base de


datos conectada al servidor Microsoft SQL Server 2008.

La base de datos consiste en una tabla que almacenará en tiempo real, las llamadas
cursan sobre la red. En la siguiente figura, se muestra la tabla que se creó con los campos
pertinentes para realizar el reporte de llamadas.

Figura 28. Base de datos Reporteador

Los campos que se tomaron en consideración, para generar el reporte son:


DisplayNameOrigen, UserNameOrigen, IPOrigen, DisplayNameDestino,
UserNameDestino, IPDestino, HoraInicio, HoraFin, Duracion y Fecha.

Esta tabla, fue creada en el control de usuario DATAGRIDVIEW para mostrar en


pantalla los datos de los usuarios y las llamadas que han realizado. El DATAGRIDVIEW va
llenando sus registros en tiempo de ejecución y posteriormente los guarda en una base de
datos alojada dentro del proyecto. Una vez almacenada la tabla, se podrán hacer consultas
para generar los reportes de llamadas de acuerdo a las diferentes necesidades del
administrador.

75
Capítulo V Pruebas

5.1 Registro de teléfono SIP

Objetivo

El objetivo de esta prueba, es el establecer el registro de un cliente Softphone a través de su


autenticación con el software PROXY PBX y éste a su vez, con el servidor de registro
situado dentro del IP PBX.

Figura 29. Diagrama de registro de Softphone

El procedimiento a seguir para el registro y autenticación del un cliente Softphone dentro


de la red, esta indicado en la figura 30. Para realizar dicha autenticación, el Softphone
utiliza el método REGISTER para indicarle al PROXY PBX su dirección SIP.

76
Figura 30. Esquema SIP de registro y autenticación de Softphone

5.1.1 Resultados

Como resultado a esta primera etapa de la realización del proyecto, se obtuvo el cliente
Softphone XLite, registrado con el nombre de usuario 40 (figura 31).

Figura 31. Softphone registrado

77
De esta forma, también se capturo información del usuario registrado a través del Log de
Tramas (Figura 32).

Figura 32. Log de Tramas Register

5.2 Establecimiento y liberación de sesión SIP

Objetivo

El objetivo de esta etapa, es el establecer una sesión SIP entre dos clientes
Softphone que iniciaran y terminaran una llamada telefónica. El cliente Softphone 1 con
dirección SIP URI [email protected], realiza una llamada al cliente Softphone 2 con SIP URI
[email protected], en la figura 33 se muestra el diagrama Establecimiento y liberación de sesión
SIP.

El mensaje de establecimiento de llamada SIP INVITE es emitido por el que llama al


PROXY PBX, éste identifica la localización del que esta llamado (dirección IP) y encamina
la llamada a su destino. El mensaje INVITE contiene distintos campos de cabecera
obligatorios, entre los cuales están la dirección SIP URI de quien llama “From”, la
dirección SIP URI de quien recibe la llamada “To”, el identificador de la llamada “Call-
ID”, el numero de secuencia “Cseq”, un numero máximo de saltos “max-forwards”.
El campo de cabecera “Via” esta actualizado por todas las entidades que participan en el
enrutamiento de la llamada, esto asegura que la respuesta seguirá el mismo camino que el
requerimiento.

78
Por otra parte, el método SIP INVITE contiene el protocolo SDP (Session Description
Protocol), que esta encargado de definir las características media que el que inicia la
llamada necesita para realizarla.

Figura 33. Diagrama Establecimiento y liberación de sesión SIP

En la siguiente figura, se muestra a detalle el procedimiento del envío de mensajes SIP


entre los UAC, pasando por la entidad PROXY PBX para el inicio y fin de la sesión.

Figura 34. Esquema SIP de inicio y fin de llamada.

79
5.2.1 Resultados

Como resultado a esta prueba, se obtuvo mediante el Log de Tramas información de origen
y destino de la llamada, direcciones IP, puertos utilizados, entre otros campos (Figura 35).

Figura 35. Log de tramas inicio y fin de sesión.

La figura 36 muestra el cliente Softphone2 recibiendo la llamada del Softphone1, donde se


despliega su Username (40) así como el Displayname (Liliana).

80
Figura 36. Softphone2 Figura 37. Llamada establecida

5.3 Prueba Reporteador

Objetivo

Como parte final del proyecto, se implemento un servicio de reportes de llamada,


donde se registra quienes establecieron comunicación dentro de la red, hora de inicio y fin
de la llamada, así como la duración de la misma.

Figura 38. Esquema PROXY PBX

81
5.3.1 Resultados

Figura 39.Prueba Reporteador

5.4 Resultados finales

Figura 40. Aplicación PROXY PBX

82
Figura 41. Créditos

83
Conclusiones

El desarrollo de software basado en normas o estándares, permite conocer a fondo el


funcionamiento de protocolos como en este caso: El protocolo SIP para VoIP. Se
comprendió a fondo como las aplicaciones de red con las que el usuario trabaja, interactúan
con los diversos protocolos que forman el modelo TCP/IP. Para programar aplicaciones de
red, es necesario conocer formatos de flujo de tráfico y eventos que se disparan en función
del tráfico de red. Programar protocolos de la capa de aplicación, nos permite desarrollar
software adaptado a las necesidades de una empresa.

Los alcances de este proyecto y algunas de las mejoras que podrían hacerse es la
extensión de las funciones del Proxy PBX IP para ser reportes de llamadas de la PSTN, así
como la implementación de restricciones de las llamadas, distribuir permisos y llevar un
control más preciso del tráfico de llamadas de la red.

Después de realizar las pruebas necesarias, se cumplieron los objetivos planteados


al inicio del proyecto y se logró la creación de una herramienta muy importante de uso
empresarial, basada en un protocolo (SIP) estandarizado por una organización internacional
como lo es la IETF, ya que de esta forma, se podría llegar a una homologación con otras
aplicaciones basadas en este estándar.

84
Glosario

Códec. Software, hardware o una combinación de ambos, capaz de transformar un archivo,


un flujo de datos o una señal. Los códecs pueden codificar el flujo o la señal y recuperarlo o
descifrarlo del mismo modo para la reproducción o la manipulación en un formato más
apropiado para estas operaciones.

PBX. Private Branch Exchange, Una PBX se encarga de establecer conexiones entre
terminales de una misma empresa, o de hacer que se cursen llamadas al exterior. Hace que
las extensiones tengan acceso desde el exterior, desde el interior, y ellas a su vez tengan
acceso también a otras extensiones y a una línea externa.

Proxy. El servidor proxy como en la mayoría de los casos actúa como un intermediario que
de un UAC a los UAS, o bien, otras UACs. Un Servidor Proxy puede ser utilizado para
encaminar las comunicaciones SIP, también se puede utilizar para la localización de una
identidad SIP.

PSTN. Public Switched Telephone Network, es una red con conmutación de circuitos
tradicional optimizada para comunicaciones de voz en tiempo real. Cuando llama a alguien,
cierra un conmutador al marcar y establece así un circuito con el receptor de la llamada.

SIP. Session Initiation Protocol. Es un protocolo estandarizado por la Internet Engineering


Task Force (IETF) para iniciar, modificar y terminar una sesión de usuario interactiva que
implica elementos multimedia.

Socket. Es un método para la comunicación entre un programa del cliente y un programa


del servidor en una red. Un socket se define como el punto final en una conexión. Los
sockets se crean y se utilizan con un sistema de peticiones o de llamadas de función a veces
llamados interfaz de programación de aplicación de sockets.

Softphone. Es un software que simula un telefono en una PC y permite hacer llamadas


VoIP sin necesidad de tener un telefono IP físico. Es decir, convierte la PC en un Telefono
IP para hacer llamadas a otros softphones (de PC a PC) o a otros teléfonos convencionales
usando un Operador de Telefonia IP (de PC a Telefonos).

UAC. User agent client, es una aplicación que inicia hasta seis posibles peticiones SIP a un
UAS .Las seis peticiones formuladas por la UAC son: INVITE, ACK, OPTIONS, BYE,
CANCEL y REGISTER.

UAS. UAS es el servidor que aloja la aplicación encargada de recibir las solicitudes SIP de
un UAC, y en la recepción devuelve una respuesta a la solicitud de nuevo a la UAC. La
UAS puede emitir respuestas múltiples a la UAC, no necesariamente una sola respuesta. La
comunicación entre UAC y UAS es cliente / servidor y (peer-to-peer).

VoIP. Es la abreviación en inglés de Voice over IP (Voz sobre IP o voz sobre protocolo de
Internet), y se usa para identificar la tecnología detrás de comunicaciones usando voz y vídeo
a través de Internet.
85
Anexo I

Código
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Konnetic.Signalling.Sip;
using Konnetic.Signalling.Sdp;
using Konnetic.Net.Transport;

namespace ProxyPBX
{
public partial class ProxyPBX : Form
{
private delegate void UpdateTextCallback(string text);
private DateTime Hora;
private DateTime Fecha;
private string HoraC;
private string FechaC;
private SipCore CoreServerT = null;
private SipCore CoreClientT = null;
private SipCore CoreServerTOptions = null;
private SipCore CoreServerTNotify = null;
string CampoViaRegister;
string CampoViaOptions;
string CampoViaSubscribe;
string CampoViaNotify;
string CampoViaInvite;
ListaSoftphone listaCliente = new ListaSoftphone();
ListaTrixBox listaServidor = new ListaTrixBox();
ListaRegistro listaRegistro = new ListaRegistro();
ListaReportes listaReportes = new ListaReportes();

86
ListaCallID listaCallID = new ListaCallID();
private Panel buttonPanel = new Panel();
private DataGridView ReporteadorDataGridView = new DataGridView();
private Button addNewRowButton = new Button();
private Button deleteRowButton = new Button();

public ProxyPBX()
{
InitializeComponent();
}

private void ProxyPBX_Load_1(object sender, EventArgs e)


{
EjecutarTransaction();
DisDataGridView();
AReporteadorDataGridView();
}

public void EjecutarTransaction()


{
CoreServerT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreServerT.LocalAddressPort = new IPDomainPort(localAddress, 5060);
CoreServerT.StartListening(new IPEndPoint(localAddress, 5060),
TransportProtocol.Udp);

CoreServerT.ServerTransactionCreated += new
EventHandler<TransactionEventArgs>(OnServerTransactionCreated);
}

private void OnServerTransactionCreated(object sender, TransactionEventArgs e)


{
ServerTransaction trans = (ServerTransaction)e.Transac
if (trans.OriginalRequest.Method == SipMethod.Register)
{
CoreClientT = null;
CoreClientT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreClientT.LocalAddressPort = new IPDomainPort(new
IPEndPoint(localAddress, 5060));

string CampoVia;
string IP;
string Puerto;
string dname;
string username;
CampoVia = trans.OriginalRequest.ViaHeaders.ToString();
char[] sep = { ' ', ':', ';' };
87
string[] part = CampoVia.Split(sep);
char[] tok = { '"', '"', ':', '@' };
string from = trans.OriginalRequest.From.ToString();
string[] part2 = from.Split(tok);
IP = part[3];
Puerto = part[4];
dname = part2[2];
username = part2[4];
listaCliente.Insertar(dname, username, IP, Puerto, CampoVia);
listaRegistro.Insertar(username, IP, Puerto);
Append("");
Append("Trama REGISTER");
Append("Campo Via: " + CampoVia);
Append("Username: " + username);
Append("Displayname: " + dname);
Append("Dirección IP: " + IP);
Append("Puerto: " + Puerto);
SipRequest RegisterRequest = e.Transaction.OriginalRequest;
if (RegisterRequest.AuthorizationHeaders != null)
{
Append("Credenciales: " + RegisterRequest.AuthorizationHeaders.ToString());
}
RegisterRequest.RemoveHeader("Via");
ViaHeaderField FieldVia = new ViaHeaderField(new
IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));

FieldVia.Branch = ViaHeaderField.NewBranch();
FieldVia.ProtocolName = "UDP";
FieldVia.ProtocolVersion = "2.0";
FieldVia.SentBy = new IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060);
RegisterRequest.AddHeader(FieldVia);
ClientTransaction transaction =
SipTransaction.CreateClientTransaction(RegisterRequest, CoreClientT, true);

RegisterRequest.SetTransaction(transaction);
RegisterRequest.ResponseReceived += new
EventHandler<ResponseReceivedEventArgs>(OnRegisterResponseReceived);
CoreClientT.SendRequest(RegisterRequest);
}

if (trans.OriginalRequest.Method == SipMethod.Subscribe)

{
CoreClientT = null;
CoreClientT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreClientT.LocalAddressPort = new IPDomainPort(new
IPEndPoint(localAddress, 5060));
88
string CampoVia;
string IP;
string Puerto;
CampoVia = trans.OriginalRequest.ViaHeaders.ToString();
char[] sep = { ' ', ':', ';' };
string[] part = CampoVia.Split(sep);
IP = part[3];
Puerto = part[4];
string Via = trans.OriginalRequest.ViaHeaders.ToString();
string dname;
string username;
char[] tok = { '"', '"', ':', '@' };
string from = trans.OriginalRequest.From.ToString();
string[] part2 = from.Split(tok);
dname = part2[2];
username = part2[4];
listaCliente.Insertar(dname, username, IP, Puerto, Via);
listaRegistro.Insertar(username, IP, Puerto);
Append("");
Append("Trama SUBSCRIBE");
Append("Campo Via: " + CampoVia);
Append("Username: " + username);
Append("Displayname: " + dname);
Append("Dirección IP: " + IP);
Append("Puerto: " + Puerto);
SipRequest SubscribeRequest = e.Transaction.OriginalRequest;
if (SubscribeRequest.AuthorizationHeaders != null)
{
Append("Credenciales: " +
SubscribeRequest.AuthorizationHeaders.ToString());
}
SubscribeRequest.RemoveHeader("Via");
ViaHeaderField FieldVia = new ViaHeaderField(new
IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
FieldVia.Branch = ViaHeaderField.NewBranch();
FieldVia.ProtocolName = "UDP";
FieldVia.ProtocolVersion = "2.0";
FieldVia.SentBy = new IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"),
5060);
SubscribeRequest.AddHeader(FieldVia);
ClientTransaction transaction =
SipTransaction.CreateClientTransaction(SubscribeRequest, CoreClientT, true);
SubscribeRequest.SetTransaction(transaction);
SubscribeRequest.ResponseReceived += new

89
EventHandler<ResponseReceivedEventArgs>(SubscribeRequest_ResponseReceived);
CoreClientT.SendRequest(SubscribeRequest);
}

if (e.Transaction.OriginalRequest.Method == SipMethod.Invite)
{
InviteServerTransaction InviteTrans = (InviteServerTransaction)e.Transaction;
CoreClientT = null;
CoreClientT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreClientT.LocalAddressPort = new IPDomainPort(new
IPEndPoint(localAddress, 5060));
string CampoVia;
string IP;
string Puerto;
CampoVia = trans.OriginalRequest.ViaHeaders.ToString();
char[] sep = { ' ', ':', ';' };
string[] part = CampoVia.Split(sep);
IP = part[3];
Puerto = part[4];
string dname;
string username;
char[] tok = { '"', '"', ':', '@' };
string from = trans.OriginalRequest.From.ToString();
string[] part2 = from.Split(tok);
dname = part2[2];
username = part2[4];
listaCliente.Insertar(dname, username, IP, Puerto, CampoVia);
listaRegistro.Insertar(username, IP, Puerto);
Append("");
Append("TRAMA: INVITE");
Append("USUARIO FUENTE:");
Append("Campo Via: " + CampoVia);
Append("Username: " + username);
Append("Displayname: " + dname);
Append("Dirección IP: " + IP);
Append("Puerto: " + Puerto);

char[] tok2 = { ':', '@' };


string To = trans.OriginalRequest.RequestUri.AbsoluteUri.ToString();
Append("Campo To: " + To);
string[] part3 = To.Split(tok);
string usernameDestino = part3[1];
string callIDpar = trans.OriginalRequest.CallId.ToString();
string[] parametros = listaRegistro.Buscar(usernameDestino);
string DNDestino = trans.OriginalRequest.To.DisplayName.ToString();
string Fecha = DateTime.Now.Date.ToString("d MMM yyyy");
string HoraInicio = DateTime.Now.ToString("hh:mm:ss:f");
90
Append("USUARIO DESTINO:");
Append("Username: " + usernameDestino);
Append("Displayename: " + DNDestino);
Append("Dirección IP: " + parametros[1]);
Append("Puerto: " + parametros[2]);
Append("CallID: "+ trans.OriginalRequest.CallId.ToString());
Append("Fecha: " + Fecha);
Append("Hora Inicio: " + HoraInicio);
Append(InviteTrans.OriginalRequest.ToString());

if (parametros != null)
{
listaReportes.Insertar(dname, username, IP, DNDestino, usernameDestino,
parametros[1], HoraInicio, Fecha);

SipUriBuilder UriTo = new SipUriBuilder();


UriTo.UserName = parametros[0];
UriTo.Host = parametros[1];
UriTo.Port = int.Parse(parametros[2]);
//Envio de respuesta Ringing para situar al usuario inicial en un estado de
procedimiento
SipResponse RingingResponse = new
SipResponse(InviteTrans.OriginalRequest, SipStatusCode.Ringing);

System.Net.IPAddress RemoteAddress = System.Net.IPAddress.Parse(IP);


DestinationTuple destination = new DestinationTuple(new

IPEndPoint(RemoteAddress, int.Parse(Puerto)), TransportProtocol.Udp);


CoreServerT.SendResponseDirect(RingingResponse, destination);

InviteRequest Invite = new InviteRequest(UriTo.SipUri);

ViaHeaderField FieldVia = new ViaHeaderField(new


IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
FieldVia.Branch = ViaHeaderField.NewBranch();
FieldVia.ProtocolName = "UDP";
FieldVia.ProtocolVersion = "2.0";
FieldVia.SentBy = new IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"),
5060);
Invite.AddHeader(FieldVia);
Invite.MaxForwards = trans.OriginalRequest.MaxForwards;
Invite.From = InviteTrans.OriginalRequest.From;
Invite.From.RecreateTag();
Invite.To = new ToHeaderField(UriTo.SipUri);
Invite.ContactHeaders.Add(trans.OriginalRequest.ContactHeaders[0]);
CallIdHeaderField callID = new CallIdHeaderField();
callID.RecreateCallId("1.1.1.1");
91
Invite.CallId = callID;
CSeqHeaderField Cseq = new CSeqHeaderField(SipMethod.Invite);
Cseq.NextSequence();
Invite.CSeq = Cseq;
UserAgentHeaderField UserAg = new UserAgentHeaderField("ESIME Proxy
PBX v1.0");
Invite.Date = new DateHeaderField(DateTime.Now);
for (int c = 0; c < trans.OriginalRequest.AllowHeaders.Count; c++)
{
Invite.AllowHeaders.Add(trans.OriginalRequest.AllowHeaders[c]);
}
for (int c = 0; c < trans.OriginalRequest.SupportedHeaders.Count; c++)
{
Invite.SupportedHeaders.Add(trans.OriginalRequest.SupportedHeaders[c]);
}
Invite.ContentType = trans.OriginalRequest.ContentType;
Invite.Body = trans.OriginalRequest.Body;
listaCallID.Insertar(callIDpar, username, usernameDestino);
System.Net.IPAddress RemoteAddressInvite =
System.Net.IPAddress.Parse(parametros[1].ToString());
DestinationTuple destinationInvite = new DestinationTuple(new
IPEndPoint(RemoteAddressInvite, int.Parse(parametros[2])), TransportProtocol.Udp);
Invite.ResponseReceived += new
EventHandler<ResponseReceivedEventArgs>(invite_ResponseReceived);
CoreClientT.SendRequestDirect(Invite, destinationInvite);
}
else
{
SipResponse AnywhereResponse = new
SipResponse(InviteTrans.OriginalRequest, SipStatusCode.DoesNotExistAnywhere);
System.Net.IPAddress RemoteAddressAnywhereResponse =
System.Net.IPAddress.Parse(IP);
Append("ESTADO: FALLIDO");
Append("USUARIO NO ENCONTRADO");
DestinationTuple destinationAnywhereResponse = new DestinationTuple(new
IPEndPoint(RemoteAddressAnywhereResponse, int.Parse(Puerto)),
TransportProtocol.Udp);
CoreServerT.SendResponseDirect(AnywhereResponse,
destinationAnywhereResponse);
}
}

if (trans.OriginalRequest.Method == SipMethod.Bye)
{
//Response ByeResponse = Servidor.SendResponseOK(e.Request);
//Servidor.Bye(ByeResponse);
}
}
92
private void OnRegisterResponseReceived(object sender,
ResponseReceivedEventArgs e)
{
int port;
if (e.Response.StatusClass == SipStatusClass.Successful)
{
Append("ESTADO: " + "REGISTER OK===");
char[] tok = { '=', ' ' };
string via = e.Response.ViaHeaders.ToString();
string[] part = via.Split(tok);
port = int.Parse(part[5]);
string dname;
string username;
char[] tok2 = { '"', '"', ':', '@' };
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dname = part2[2];
username = part2[4];
string[] parametros = listaCliente.Buscar(dname, username);
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametros[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametros[3])), TransportProtocol.Udp);
CampoViaRegister = parametros[4];
SipResponse RespRegisterServerT = e.Response;
RespRegisterServerT.RemoveHeader("Via");
RespRegisterServerT.ViaHeaders.Add(CampoViaRegister);
CoreServerT.SendResponseDirect(RespRegisterServerT, destination);
listaCliente.Eliminar(dname, username);
CoreServerTOptions = null;
CoreServerTOptions = new SipCore();
CoreServerTOptions.StartListening(new
IPEndPoint(System.Net.IPAddress.Parse("1.1.1.1"), port), TransportProtocol.Udp);
CoreServerTOptions.ServerTransactionCreated += new
EventHandler<TransactionEventArgs>(CoreServerTOptions_NewPort);
}
else
{
Append("ESTADO: " + "REGISTER "+ e.Response.StatusLine.ToString());
string dname;
string username;
char[] tok2 = { '"', '"', ':', '@' };
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dname = part2[2];
username = part2[4];
string[] parametros = listaCliente.Buscar(dname, username);
93
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametros[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametros[3])), TransportProtocol.Udp);
CampoViaRegister = parametros[4];
SipResponse RespRegisterServerT = e.Response;
RespRegisterServerT.RemoveHeader("Via");
RespRegisterServerT.ViaHeaders.Add(CampoViaRegister);
CoreServerT.SendResponseDirect(RespRegisterServerT, destination);
listaCliente.Eliminar(dname, username);
}
}
private void CoreServerTOptions_NewPort(object sender, TransactionEventArgs e)
{
ServerTransaction trans = (ServerTransaction)e.Transaction;
if (trans.OriginalRequest.Method == SipMethod.Options)
{
CoreClientT = null;
CoreClientT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreClientT.LocalAddressPort = new IPDomainPort(new
IPEndPoint(localAddress, 5060));

string IP;
string Puerto;
string Via = trans.OriginalRequest.ViaHeaders.ToString();
string username;
char[] tok = { ':', '@', ':', ';' };
string to = trans.OriginalRequest.To.Uri.ToString();
string[] part2 = to.Split(tok);
username = part2[1];
IP = part2[2];
Puerto = part2[3];
listaServidor.Insertar(username, IP, Puerto, Via);
SipRequest OptionsRequest = e.Transaction.OriginalRequest;
OptionsRequest.RemoveHeader("Via");
ViaHeaderField FieldVia = new ViaHeaderField(new
IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
FieldVia.Branch = ViaHeaderField.NewBranch();
FieldVia.ProtocolName = "UDP";
FieldVia.ProtocolVersion = "2.0";
FieldVia.SentBy = new IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"),
5060);
OptionsRequest.AddHeader(FieldVia);
ClientTransaction transaction =
SipTransaction.CreateClientTransaction(OptionsRequest, CoreClientT, true);
OptionsRequest.SetTransaction(transaction);

94
OptionsRequest.ResponseReceived += new
EventHandler<ResponseReceivedEventArgs>(OptionsRequest_ResponseReceived);
System.Net.IPAddress RemoteAddress = System.Net.IPAddress.Parse(IP);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(Puerto)), TransportProtocol.Udp);
CoreClientT.SendRequestDirect(OptionsRequest, destination);
}
}
private void OptionsRequest_ResponseReceived(object sender,
ResponseReceivedEventArgs e)
{
Append("TRAMA: OPTIONS");
Append("ESTADO: COMPLETADO");
string username;
char[] tok2 = { '"', '"', ':', '@' };
string to = e.Response.To.Uri.ToString();
string[] part2 = to.Split(tok2);
username = part2[1];
string[] parametros = listaServidor.Buscar(username);
CampoViaOptions = parametros[3];

SipResponse RespOptionsServerT = e.Response;


Append(e.Response.ViaHeaders.ToString());
RespOptionsServerT.RemoveHeader("Via");
RespOptionsServerT.ViaHeaders.Add(CampoViaOptions);
System.Net.IPAddress RemoteAddress = System.Net.IPAddress.Parse("1.1.1.10");
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, 5060), TransportProtocol.Udp);
CoreServerT.SendResponseDirect(RespOptionsServerT, destination);
listaServidor.Eliminar(username);
}
private void SubscribeRequest_ResponseReceived(object sender,
ResponseReceivedEventArgs e)
{
int port;
if (e.Response.StatusClass == SipStatusClass.Successful)
{
Append("ESTADO: SUBSCRIBE OK");
char[] tok = { '=', ' ' };
string via = e.Response.ViaHeaders.ToString();
string[] part = via.Split(tok);
port = int.Parse(part[5]);
string dname;
string username;
char[] tok2 = { '"', '"', ':', '@' };
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dname = part2[2];
95
username = part2[4];
string[] parametros = listaCliente.Buscar(dname, username);
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametros[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametros[3])), TransportProtocol.Udp);
CampoViaSubscribe = parametros[4];

SipResponse RespSubscribeServerT = e.Response;


RespSubscribeServerT.RemoveHeader("Via");
RespSubscribeServerT.ViaHeaders.Add(CampoViaSubscribe);
CoreServerT.SendResponseDirect(RespSubscribeServerT, destination);
listaCliente.Eliminar(dname, username);
CoreServerTNotify = null;
CoreServerTNotify = new SipCore();
CoreServerTNotify.StartListening(new
IPEndPoint(System.Net.IPAddress.Parse("1.1.1.1"), port), TransportProtocol.Udp);
CoreServerTNotify.ServerTransactionCreated += new
EventHandler<TransactionEventArgs>(CoreServerTNotify_NewPort);

}
if (e.Response.StatusCodeNumber == 401)
{
Append("ESTADO: SUBSCRIBE UNAUTHORIZED");
string dname;
string username;
char[] tok2 = { '"', '"', ':', '@' };
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dname = part2[2];
username = part2[4];
string[] parametros = listaCliente.Buscar(dname, username);
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametros[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametros[3])), TransportProtocol.Udp);
CampoViaSubscribe = parametros[4];
SipResponse RespSubscribeServerT = e.Response;
RespSubscribeServerT.RemoveHeader("Via");
RespSubscribeServerT.ViaHeaders.Add(CampoViaSubscribe);
CoreServerT.SendResponseDirect(RespSubscribeServerT, destination);
listaCliente.Eliminar(dname, username);
}
}

private void CoreServerTNotify_NewPort(object sender, TransactionEventArgs e)


{
ServerTransaction trans = (ServerTransaction)e.Transaction;
96
if (e.Transaction.OriginalRequest.Method == SipMethod.Notify)
{
CoreClientT = null;
CoreClientT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreClientT.LocalAddressPort = new IPDomainPort(new
IPEndPoint(localAddress, 5060));

string IP;
string Puerto;
string Via = trans.OriginalRequest.ViaHeaders.ToString();
string username;
char[] tok = { ':', '@', ':', ';' };
string to = trans.OriginalRequest.RequestUri.AbsoluteUri.ToString();
string[] part2 = to.Split(tok);
username = part2[1];
IP = part2[2];
Puerto = part2[3];
listaServidor.Insertar(username, IP, Puerto, Via);
SipRequest NotifyRequest = e.Transaction.OriginalRequest;
NotifyRequest.RemoveHeader("Via");
ViaHeaderField FieldVia = new ViaHeaderField(new
IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
FieldVia.Branch = ViaHeaderField.NewBranch();
FieldVia.ProtocolName = "UDP";
FieldVia.ProtocolVersion = "2.0";
FieldVia.SentBy = new IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"),
5060);
NotifyRequest.AddHeader(FieldVia);
ClientTransaction transaction =
SipTransaction.CreateClientTransaction(NotifyRequest, CoreClientT, true);
NotifyRequest.SetTransaction(transaction);
System.Net.IPAddress RemoteAddress = System.Net.IPAddress.Parse(IP);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(Puerto)), TransportProtocol.Udp);
NotifyRequest.ResponseReceived += new
EventHandler<ResponseReceivedEventArgs>(NotifyRequest_ResponseReceived);
CoreClientT.SendRequestDirect(NotifyRequest, destination);
}
}
private void NotifyRequest_ResponseReceived(object sender,
ResponseReceivedEventArgs e)
{
Append("TRAMA: NOTIFY");
Append("ESTADO: COMPLETADO");
string IP;
string username;
char[] tok2 = { '"', '"', ':', '@' };
97
string to = e.Response.To.Uri.ToString();
string[] part2 = to.Split(tok2);
username = part2[1];
IP = part2[2];
string[] parametros = listaServidor.Buscar(username);
CampoViaNotify = parametros[3];

SipResponse RespNotifyServerT = e.Response;


RespNotifyServerT.RemoveHeader("Via");
RespNotifyServerT.ViaHeaders.Add(CampoViaNotify);
System.Net.IPAddress RemoteAddress = System.Net.IPAddress.Parse("1.1.1.10");
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, 5060), TransportProtocol.Udp);
CoreServerT.SendResponseDirect(RespNotifyServerT, destination);
listaServidor.Eliminar(username);
}
private void invite_ResponseReceived(object sender, ResponseReceivedEventArgs e)
{
if (e.Response.StatusCodeNumber == 401)
{
Append("===INVITE UNAUTHORIZED===");
string dname;
string username;
char[] tok2 = { '"', '"', ':', '@' };
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dname = part2[2];
username = part2[4];
string[] parametros = listaCliente.Buscar(dname, username);
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametros[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametros[3])), TransportProtocol.Udp);
CampoViaSubscribe = parametros[4];
SipResponse RespSubscribeServerT = e.Response;
RespSubscribeServerT.RemoveHeader("Via");
RespSubscribeServerT.ViaHeaders.Add(CampoViaSubscribe);
CoreServerT.SendResponseDirect(RespSubscribeServerT, destination);
listaCliente.Eliminar(dname, username);
}
else
{
Append("LLAMADA EN PROCESO: ");
Append("ESTADO: "+ e.Response.StatusLine.ToString());
Append(e.Response.ToString());
string dname;
string username;
char[] tok2 = { '"', '"', ':', '@' };
98
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dname = part2[2];
username = part2[4];
string rport;
char[] tok = { '=', ';' };
string ViaResponse = e.Response.ViaHeaders.ToString();
string[] part = ViaResponse.Split(tok);
rport = part[2];
string FromRinging = e.Response.From.Uri.ToString();
char[] tokFromRing = { ':', '@' };
string[] part4 = FromRinging.Split(tokFromRing);
string usernameOrigen = part4[1];
string ToRinging = e.Response.To.Uri.ToString();
char[] tokToRing = { ':', '@' };
string[] part3 = ToRinging.Split(tokToRing);
string usernameDestino = part3[1];
string[] parametros = listaCliente.Buscar(dname, username);
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametros[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametros[3])), TransportProtocol.Udp);
CampoViaInvite = parametros[4];

SipResponse RespInviteServerT = new SipResponse(SipStatusCode.Ringing);


RespInviteServerT.ViaHeaders.Add(CampoViaInvite);
FromHeaderField FromHeader = new FromHeaderField(e.Response.From.Uri);
FromHeader.DisplayName = e.Response.From.DisplayName;
FromHeader.RecreateTag();
RespInviteServerT.From = FromHeader;
ToHeaderField ToHeader = new ToHeaderField(e.Response.To.Uri);
ToHeader.DisplayName = e.Response.To.DisplayName;
ToHeader.RecreateTag();
RespInviteServerT.To = ToHeader;
string CallIDres = listaCallID.Buscar(usernameOrigen, usernameDestino);
RespInviteServerT.CallId = CallIDres;
CSeqHeaderField CseqRinging = new CSeqHeaderField(SipMethod.Invite);
CseqRinging.NextSequence();
UserAgentHeaderField UserAgRing = new UserAgentHeaderField("ESIME
Proxy PBX v1.0");
RespInviteServerT.UserAgent = UserAgRing;
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Invite));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Ack));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Options));

99
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Cancel));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Bye));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Refer));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Subscribe));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Notify));
RespInviteServerT.AllowHeaders.Add(new
AllowHeaderField(SipMethod.Info));
RespInviteServerT.SupportedHeaders.Add("replaces");
RespInviteServerT.SupportedHeaders.Add("timer");
SipUri URIRing = e.Response.To.Uri;
ContactHeaderField contact = new ContactHeaderField(URIRing);
RespInviteServerT.ContactHeaders.Add(contact);
CoreServerT.SendResponseDirect(RespInviteServerT, destination);
CoreClientT.StartListening(new
IPEndPoint(System.Net.IPAddress.Parse("1.1.1.1"), int.Parse(rport)),
TransportProtocol.Udp);
CoreClientT.ResponseReceived+=new
EventHandler<ResponseReceivedEventArgs>(CoreClientT_ResponseReceived);
}

}
private void CoreClientT_ResponseReceived(object sender,
ResponseReceivedEventArgs e)
{
if (e.Response.StatusClass == SipStatusClass.Successful)
{
Append("ESTADO: INVITE OK");
Append("SESION ESTABLECIDA");
//listaReportes.Mostrar();
Append(e.Response.ToString());
CoreClientT = null;
CoreClientT = new SipCore();
System.Net.IPAddress localAddress = System.Net.IPAddress.Parse("1.1.1.1");
CoreClientT.LocalAddressPort = new IPDomainPort(new
IPEndPoint(localAddress, 5060));
string usernameTo;
char[] tok = { ':', ':', '@' };
string to = e.Response.To.ToString();
string[] part1 = to.Split(tok);
usernameTo = part1[2];
string[] parametrosTo = listaRegistro.Buscar(usernameTo);

AckRequest Confirmacion = new AckRequest();


100
ViaHeaderField FieldVia = new ViaHeaderField(new
IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"), 5060));
FieldVia.Branch = ViaHeaderField.NewBranch();
FieldVia.ProtocolName = "UDP";
FieldVia.ProtocolVersion = "2.0";
FieldVia.SentBy = new IPDomainPort(System.Net.IPAddress.Parse("1.1.1.1"),
5060);
Confirmacion.AddHeader(FieldVia);
SipUriBuilder UriTo = new SipUriBuilder();
UriTo.UserName = parametrosTo[0];
UriTo.Host = parametrosTo[1];
UriTo.Port = int.Parse(parametrosTo[2]);
RequestLine ReqLine = new RequestLine(UriTo.SipUri, SipMethod.Ack);
Confirmacion.RequestLine = ReqLine;
Confirmacion.MaxForwards = "70";
Confirmacion.From = e.Response.From;
Confirmacion.To = e.Response.To;
SipUri URI = e.Response.From.Uri;
ContactHeaderField contact = new ContactHeaderField(URI);
Confirmacion.ContactHeaders.Add(contact);
Confirmacion.CallId = e.Response.CallId;
CSeqHeaderField CseqACK = new CSeqHeaderField(SipMethod.Ack);
CseqACK.NextSequence();
Confirmacion.CSeq = CseqACK;
UserAgentHeaderField UserAg = new UserAgentHeaderField("ESIME Proxy
PBX v1.0");
Confirmacion.UserAgent = UserAg;
System.Net.IPAddress RemoteAddressTo =
System.Net.IPAddress.Parse(parametrosTo[1]);
DestinationTuple destinationTo = new DestinationTuple(new
IPEndPoint(RemoteAddressTo, int.Parse(parametrosTo[2])), TransportProtocol.Udp);
CoreClientT.SendRequestDirect(Confirmacion, destinationTo);

string dnameFrom;
string usernameFrom;
char[] tok2 = { '"', '"', ':', '@' };
string from = e.Response.From.ToString();
string[] part2 = from.Split(tok2);
dnameFrom = part2[2];
usernameFrom = part2[4];
string[] parametrosFrom = listaCliente.Buscar(dnameFrom, usernameFrom);
System.Net.IPAddress RemoteAddress =
System.Net.IPAddress.Parse(parametrosFrom[2]);
DestinationTuple destination = new DestinationTuple(new
IPEndPoint(RemoteAddress, int.Parse(parametrosFrom[3])), TransportProtocol.Udp);
CampoViaInvite = parametrosFrom[4];

SipResponse RespInviteServerT = new SipResponse(SipStatusCode.Ok);


101
RespInviteServerT.ViaHeaders.Add(CampoViaInvite);
FromHeaderField FromHeader = new FromHeaderField(e.Response.From.Uri);
FromHeader.DisplayName = e.Response.From.DisplayName;
FromHeader.RecreateTag();
RespInviteServerT.From = FromHeader;
ToHeaderField ToHeader = new ToHeaderField(e.Response.To.Uri);
ToHeader.DisplayName = e.Response.To.DisplayName;
ToHeader.RecreateTag();
RespInviteServerT.To = ToHeader;
string CallidVuelta = listaCallID.Buscar(usernameFrom, usernameTo);//CALL
ID DEVUELTO
RespInviteServerT.CallId = CallidVuelta;
CSeqHeaderField CseqOK = new CSeqHeaderField(SipMethod.Invite);
CseqOK.NextSequence();
UserAgentHeaderField UserAgOK = new UserAgentHeaderField("ESIME Proxy
PBX v1.0");
RespInviteServerT.UserAgent = UserAgOK;
for (int c = 0; c < e.Response.AllowHeaders.Count; c++)
{
RespInviteServerT.AllowHeaders.Add(e.Response.AllowHeaders[c]);
}
for (int c = 0; c < e.Response.SupportedHeaders.Count; c++)
{
RespInviteServerT.SupportedHeaders.Add(e.Response.SupportedHeaders[c]);
}
SipUri URIOK = e.Response.To.Uri;
ContactHeaderField contactOK = new ContactHeaderField(URIOK);
RespInviteServerT.ContactHeaders.Add(contactOK);
RespInviteServerT.ContentType = e.Response.ContentType;
RespInviteServerT.Body = e.Response.Body;
CoreServerT.SendResponseDirect(RespInviteServerT, destination);
listaCliente.Eliminar(dnameFrom, usernameFrom);
//listaCallID.Eliminar(dnameFrom,
}
}
public void Append(string text)
{
BeginInvoke(new UpdateTextCallback(AppendText), new object[] { text });
}

private void AppendText(string text)


{
mostrarTextBox2.AppendText("\r\n" + text);
}

public class NodoListaSoftphone


{
public NodoListaSoftphone anterior;
102
public string DisplayName;
public string Username;
public string DireccionIP;
public string Puerto;
public string Via;
public NodoListaSoftphone siguiente;
public NodoListaSoftphone(string DisplayName, string Username, string
DireccionIP, string Puerto, string Via)
: this(null, DisplayName, Username, DireccionIP, Puerto, Via, null) { }
public NodoListaSoftphone(NodoListaSoftphone anterior, string DisplayName,
string Username, string DireccionIP, string Puerto, string Via, NodoListaSoftphone
siguiente)
{
this.anterior = anterior;
this.DisplayName = DisplayName;
this.Username = Username;
this.DireccionIP = DireccionIP;
this.Puerto = Puerto;
this.Via = Via;
this.siguiente = siguiente;
}
public NodoListaSoftphone ANTERIOR
{
get { return anterior; }
set { anterior = value; }
}
public string DISPLAYNAME
{
get { return DisplayName; }
set { DisplayName = value; }
}
public string USERNAME
{
get { return Username; }
set { Username = value; }
}
public string DIRECCIONIP
{
get { return DireccionIP; }
set { DireccionIP = value; }
}
public string PUERTO
{
get { return Puerto; }
set { Puerto = value; }
}
public string VIA
{
103
get { return Via; }
set { Via = value; }
}
public NodoListaSoftphone SIGUIENTE
{
get { return siguiente; }
set { siguiente = value; }
}
}

public class ListaSoftphone


{
private NodoListaSoftphone primerNodo;
private NodoListaSoftphone ultimoNodo;
public ListaSoftphone()
{
primerNodo = ultimoNodo = null;
}
public void Insertar(string DisplayName, string Username, string DireccionIP,
string Puerto, string Via)
{
if (primerNodo == null)
{
primerNodo = ultimoNodo = new NodoListaSoftphone(DisplayName,
Username, DireccionIP, Puerto, Via);
}
else
{
primerNodo.ANTERIOR = primerNodo = new NodoListaSoftphone(null,
DisplayName, Username, DireccionIP, Puerto, Via, primerNodo);
}
}
public void Eliminar(string DisplayName, string Username)
{
NodoListaSoftphone Actual = primerNodo;
do
{
if ((Actual.DisplayName == DisplayName) && (Actual.Username ==
Username))
{
if (Actual == ultimoNodo)
{
primerNodo = ultimoNodo = null;
break;
}
if (Actual.ANTERIOR == null)
{
Actual.SIGUIENTE.ANTERIOR = null;
104
primerNodo = Actual.SIGUIENTE;
break;
}
if (Actual.ANTERIOR != null)
{
Actual.ANTERIOR.SIGUIENTE = Actual.SIGUIENTE;
Actual.SIGUIENTE.ANTERIOR = Actual.ANTERIOR;
break;
}
}
if (Actual == ultimoNodo)
{
break;
}
Actual = Actual.SIGUIENTE;
} while (Actual != null);
}
public string[] Buscar(string DisplayName, string Username)
{
NodoListaSoftphone Actual = primerNodo;
string[] parametros = new string[5];
bool existe = false;
do
{
if ((Actual.DISPLAYNAME == DisplayName) && (Actual.USERNAME ==
Username))
{
existe = true;
break;
}
if (Actual == ultimoNodo)
{
if ((Actual.DISPLAYNAME == DisplayName) && (Actual.USERNAME
== Username))
{
existe = true;
break;
}
else { break; }
}
Actual = Actual.SIGUIENTE;
} while (Actual != null);
if (existe == true)
{
parametros[0] = Actual.DISPLAYNAME;
parametros[1] = Actual.USERNAME;
parametros[2] = Actual.DIRECCIONIP;
parametros[3] = Actual.PUERTO;
105
parametros[4] = Actual.VIA;
return parametros;
}
else
{
parametros = null;
return parametros;
}
}
public bool ListaVacia()
{
return primerNodo == null;
}
}

public class NodoListaTrixBox


{
public NodoListaTrixBox anterior;
public string Username;
public string DireccionIP;
public string Puerto;
public string Via;
public NodoListaTrixBox siguiente;
public NodoListaTrixBox(string Username, string DireccionIP, string Puerto, string
Via)
: this(null, Username, DireccionIP, Puerto, Via, null) { }
public NodoListaTrixBox(NodoListaTrixBox anterior, string Username, string
DireccionIP, string Puerto, string Via, NodoListaTrixBox siguiente)
{
this.anterior = anterior;
this.Username = Username;
this.DireccionIP = DireccionIP;
this.Puerto = Puerto;
this.Via = Via;
this.siguiente = siguiente;
}
public NodoListaTrixBox ANTERIOR
{
get { return anterior; }
set { anterior = value; }
}
public string USERNAME
{
get { return Username; }
set { Username = value; }
}
public string DIRECCIONIP
{
106
get { return DireccionIP; }
set { DireccionIP = value; }
}
public string PUERTO
{
get { return Puerto; }
set { Puerto = value; }
}
public string VIA
{
get { return Via; }
set { Via = value; }
}
public NodoListaTrixBox SIGUIENTE
{
get { return siguiente; }
set { siguiente = value; }
}
}

public class ListaTrixBox


{
private NodoListaTrixBox primerNodo;
private NodoListaTrixBox ultimoNodo;
public ListaTrixBox()
{
primerNodo = ultimoNodo = null;
}
public void Insertar(string Username, string DireccionIP, string Puerto, string Via)
{
if (ListaVacia())
{
primerNodo = ultimoNodo = new NodoListaTrixBox(Username, DireccionIP,
Puerto, Via);
}
else
{
primerNodo.ANTERIOR = primerNodo = new NodoListaTrixBox(null,
Username, DireccionIP, Puerto, Via, primerNodo);
}
}
public void Eliminar(string Username)
{
NodoListaTrixBox Actual = primerNodo;
do
{
if (Actual.USERNAME == Username)
{
107
if (Actual == ultimoNodo)
{
primerNodo = ultimoNodo = null;
break;
}
if (Actual.ANTERIOR == null)
{
primerNodo = Actual.SIGUIENTE;
break;
}
if(Actual.ANTERIOR != null)
{
Actual.ANTERIOR.SIGUIENTE = Actual.SIGUIENTE;
Actual.SIGUIENTE.ANTERIOR = Actual.ANTERIOR;
break;
}
}
if (Actual == ultimoNodo) { break; }
Actual = Actual.SIGUIENTE;
} while (Actual != null);
}
public string[] Buscar(string Username)
{
NodoListaTrixBox Actual = primerNodo;
string[] parametros = new string[4];
bool existe = false;
do
{
if (Actual.USERNAME == Username)
{
existe = true;
break;
}
if (Actual == ultimoNodo)
{
if (Actual.USERNAME == Username)
{
existe = true;
break;
}
else { break; }
}
Actual = Actual.SIGUIENTE;
} while (Actual != null);
if (existe == true)
{
parametros[0] = Actual.Username;
parametros[1] = Actual.DireccionIP;
108
parametros[2] = Actual.Puerto;
parametros[3] = Actual.Via;
return parametros;
}
else
{
parametros = null;
return parametros;
}
}
public bool ListaVacia()
{
return primerNodo == null;
}
}

public class NodoListaRegistro


{
public NodoListaRegistro anterior;
public string Username;
public string DireccionIP;
public string Puerto;
public NodoListaRegistro siguiente;
public NodoListaRegistro(string Username, string DireccionIP, string Puerto)
: this(null, Username, DireccionIP, Puerto, null) { }
public NodoListaRegistro(NodoListaRegistro anterior, string Username, string
DireccionIP, string Puerto, NodoListaRegistro siguiente)
{
this.anterior = anterior;
this.Username = Username;
this.DireccionIP = DireccionIP;
this.Puerto = Puerto;
this.siguiente = siguiente;
}
public NodoListaRegistro ANTERIOR
{
get { return anterior; }
set { anterior = value; }
}
public string USERNAME
{
get { return Username; }
set { Username = value; }
}
public string DIRECCIONIP
{
get { return DireccionIP; }
set { DireccionIP = value; }
109
}
public string PUERTO
{
get { return Puerto; }
set { Puerto = value; }
}
public NodoListaRegistro SIGUIENTE
{
get { return siguiente; }
set { siguiente = value; }
}
}

public class ListaRegistro


{
private NodoListaRegistro primerNodoRegistro;
private NodoListaRegistro ultimoNodoRegistro;
public ListaRegistro()
{
primerNodoRegistro = ultimoNodoRegistro = null;
}
public void Insertar(string Username, string DireccionIP, string Puerto)
{
bool existe = false;
if (ListaVacia())
{
primerNodoRegistro = ultimoNodoRegistro = new
NodoListaRegistro(Username, DireccionIP, Puerto);
}
else
{
NodoListaRegistro ActualRegistro = primerNodoRegistro;
do
{
if (ActualRegistro.USERNAME == Username)
{
ActualRegistro.DIRECCIONIP = DireccionIP;
ActualRegistro.PUERTO = Puerto;
existe = true;
break;
}
if (ActualRegistro == ultimoNodoRegistro) { break; }
ActualRegistro = ActualRegistro.SIGUIENTE;
} while (ActualRegistro != null);
if (existe == false)
{
primerNodoRegistro.ANTERIOR = primerNodoRegistro = new
NodoListaRegistro(null, Username, DireccionIP, Puerto, primerNodoRegistro);
110
}
}
}

public string[] Buscar(string Username)


{
bool existe = false;
NodoListaRegistro Actual = primerNodoRegistro;
string[] parametros = new string[3];
do
{
if (Actual.USERNAME == Username)
{
existe = true;
break;
}
if (Actual == ultimoNodoRegistro) { break; }
Actual = Actual.siguiente;
} while (Actual != null);
if (existe == true)
{
parametros[0] = Actual.USERNAME;
parametros[1] = Actual.DIRECCIONIP;
parametros[2] = Actual.PUERTO;
return parametros;
}
else
{
parametros = null;
return parametros;
}

}
public bool ListaVacia()
{
return primerNodoRegistro == null;
}
}

class NodoListaReportes
{
NodoListaReportes anterior;
public string DisplayNameOrigen;
public string UserNameOrigen;
public string IPOrigen;
public string DisplayNameDestino;
public string UserNameDestino;
public string IPDestino;
111
public string HoraInicio;
public string HoraFin;
public string Duracion;
public string Fecha;
NodoListaReportes siguiente;
public NodoListaReportes(string DisplayNameOrigen, string UserNameOrigen,
string IPOrigen, string DisplayNameDestino, string UserNameDestino, string IPDestino,
string HoraInicio, string Fecha)
: this(null, DisplayNameOrigen, UserNameOrigen, IPOrigen,
DisplayNameDestino, UserNameDestino, IPDestino, HoraInicio, null, null, Fecha, null) { }
public NodoListaReportes(NodoListaReportes anterior, string DisplayNameOrigen,
string UserNameOrigen, string IPOrigen, string DisplayNameDestino, string
UserNameDestino, string IPDestino, string HoraInicio, string HoraFin, string Duracion,
string Fecha, NodoListaReportes siguiente)
{
this.anterior = anterior;
this.DisplayNameOrigen = DisplayNameOrigen;
this.UserNameOrigen = UserNameOrigen;
this.IPOrigen = IPOrigen;
this.DisplayNameDestino = DisplayNameDestino;
this.UserNameDestino = UserNameDestino;
this.IPDestino = IPDestino;
this.HoraInicio = HoraInicio;
this.HoraFin = HoraFin;
this.Duracion = Duracion;
this.Fecha = Fecha;
this.siguiente = siguiente;
}
public NodoListaReportes ANTERIOR
{
get { return anterior; }
set { anterior = value; }
}

public string DISPLAYNAMEORIGEN


{
get { return DisplayNameOrigen; }
set { DisplayNameOrigen = value; }
}
public string USERNAMEORIGEN
{
get { return UserNameOrigen; }
set { UserNameOrigen = value; }
}
public string IPORIGEN
{
get { return IPOrigen; }
set { IPOrigen = value; }
112
}
public string DISPLAYNAMEDESTINO
{
get { return DisplayNameDestino; }
set { DisplayNameDestino = value; }
}
public string USERNAMEDESTINO
{
get { return UserNameDestino; }
set { UserNameDestino = value; }
}
public string IPDESTINO
{
get { return IPDestino; }
set { IPDestino = value; }
}
public string HORAINICIO
{
get { return HoraInicio; }
set { HoraInicio = value; }
}
public string HORAFIN
{
get { return HoraFin; }
set { HoraFin = value; }
}
public string DURACION
{
get { return Duracion; }
set { Duracion = value; }
}
public string FECHA
{
get { return Fecha; }
set { Fecha = value; }
}
public NodoListaReportes SIGUIENTE
{
get { return siguiente; }
set { siguiente = value; }
}
}

public class ListaReportes


{
private NodoListaReportes primerNodoReportes;
private NodoListaReportes ultimoNodoReportes;
public ListaReportes()
113
{
primerNodoReportes = ultimoNodoReportes = null;
}
public void Insertar(string DisplayNameOrigen, string UserNameOrigen, string
IPOrigen, string DisplayNameDestino, string UserNameDestino, string IPDestino, string
HoraInicio, string Fecha)
{
if (ListaVacia())
{
primerNodoReportes = ultimoNodoReportes = new
NodoListaReportes(DisplayNameOrigen, UserNameOrigen, IPOrigen,
DisplayNameDestino, UserNameDestino, IPDestino, HoraInicio, Fecha);
}
else
{
primerNodoReportes.ANTERIOR = primerNodoReportes = new
NodoListaReportes(null, DisplayNameOrigen, UserNameOrigen, IPOrigen,
DisplayNameDestino, UserNameDestino, IPDestino, HoraInicio, null, null, Fecha,
primerNodoReportes);

}
}

/* public void Mostrar()


{
NodoListaReportes Actual = primerNodoReportes;
string[] parametros = new string[10];
do
{
parametros[0] = Actual.DisplayNameOrigen;
parametros[1] = Actual.USERNAMEORIGEN;
parametros[2] = Actual.IPORIGEN;
parametros[3] = Actual.DISPLAYNAMEDESTINO;
parametros[4] = Actual.USERNAMEDESTINO;
parametros[5] = Actual.IPDESTINO;
parametros[6] = Actual.HORAINICIO;
parametros[7] = Actual.HORAFIN;
parametros[8] = Actual.DURACION;
parametros[9] = Actual.FECHA;
ProxyPBX objeto = new ProxyPBX();
objeto.AReporteadorDataGridView(parametros);
Actual = Actual.SIGUIENTE;
} while (Actual != null);
}
*/
public bool ListaVacia()
{
return primerNodoReportes == null;
114
}
}

class NodoListaCallID
{
NodoListaCallID anterior;
public string CallID;
public string usernameOrigen;
public string usernameDestino;
NodoListaCallID siguiente;
public NodoListaCallID(string CallId, string usernameOrigen, string
usernameDestino)
: this(null, CallId, usernameOrigen, usernameDestino, null) { }
public NodoListaCallID(NodoListaCallID anterior, string CallID, string
usernameOrigen, string usernameDestino, NodoListaCallID siguiente)
{
this.anterior = anterior;
this.CallID = CallID;
this.usernameOrigen = usernameOrigen;
this.usernameDestino = usernameDestino;
this.siguiente = siguiente;
}
public NodoListaCallID ANTERIOR
{
get { return anterior; }
set { anterior = value; }
}
public string CALLID
{
get { return CallID; }
set { CallID = value; }
}
public string USERNAMEORIGEN
{
get { return usernameOrigen; }
set { usernameOrigen = value; }
}
public string USERNAMEDESTINO
{
get { return usernameDestino; }
set { usernameDestino = value; }
}
public NodoListaCallID SIGUIENTE
{
get { return siguiente; }
set { siguiente = value; }
}
}
115
public class ListaCallID
{
private NodoListaCallID primerNodoCALLID;
private NodoListaCallID ultimoNodoCALLID;
public ListaCallID()
{
primerNodoCALLID = ultimoNodoCALLID = null;
}
public void Insertar(string CallId, string usernameOrigen, string usernameDestino)
{
if (ListaVacia())
{
primerNodoCALLID = ultimoNodoCALLID = new NodoListaCallID(CallId,
usernameOrigen, usernameDestino);
}
else
{
primerNodoCALLID.ANTERIOR = primerNodoCALLID = new
NodoListaCallID(null, CallId, usernameOrigen, usernameDestino, primerNodoCALLID);

}
}
public string Buscar(string usernameOrigen, string usernameDestino)
{
NodoListaCallID Actual = primerNodoCALLID;
bool existe = false;
string identificador;
do
{
if ((Actual.USERNAMEORIGEN == usernameOrigen) &&
(Actual.USERNAMEDESTINO == usernameDestino))
{
existe = true;
break;
}
if (Actual == ultimoNodoCALLID) { break; }
Actual = Actual.SIGUIENTE;
} while (Actual != null);
if (existe == true)
{
identificador = Actual.CALLID;
return identificador;
}
else
{
identificador = null;
return identificador;
116
}
}

public void Eliminar(string usernameOrigen, string usernameDestino)


{
NodoListaCallID Actual = primerNodoCALLID;
do
{
if ((Actual.USERNAMEORIGEN == usernameOrigen) &&
(Actual.USERNAMEDESTINO == usernameDestino))
{
if (Actual == ultimoNodoCALLID)
{
primerNodoCALLID = ultimoNodoCALLID = null;
break;
}
if (Actual.ANTERIOR == null)
{
primerNodoCALLID = Actual.SIGUIENTE;
break;
}
if(Actual.ANTERIOR != null)
{
Actual.ANTERIOR.SIGUIENTE = Actual.SIGUIENTE;
Actual.SIGUIENTE.ANTERIOR = Actual.ANTERIOR;
break;
}
}
if (Actual == ultimoNodoCALLID) { break; }
Actual = Actual.SIGUIENTE;
} while (Actual != null);
}
public bool ListaVacia()
{
return primerNodoCALLID == null;
}

private void timer1_Tick(object sender, EventArgs e)


{
labelHora.Text = DateTime.Now.ToString("hh:mm:ss");
labelFecha.Text = DateTime.Now.Date.ToString();
}

private void button1_Click(object sender, EventArgs e)


{

117
}

private void dataGridView1_CellFormatting(object sender,


System.Windows.Forms.DataGridViewCellFormattingEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Reporteador")
{
if (e != null)
{
if (e.Value != null)
{
try
{
e.Value = DateTime.Parse(e.Value.ToString())
.ToLongDateString();
e.FormattingApplied = true;
}
catch (FormatException)
{
MessageBox.Show("{0} Dato no valido e.", e.Value.ToString());
}
}
}
}
}

public void DisDataGridView()


{

dataGridView1.ColumnCount = 10;
//dataGridView1.ColumnHeadersDefaultCellStyle.BackColor = Color.Navy;
//dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
dataGridView1.ColumnHeadersDefaultCellStyle.Font = new
Font(ReporteadorDataGridView.Font, FontStyle.Bold);

dataGridView1.Name = "ReporteadorDataGridView";
//dataGridView1.Location = new Point(15, 426);
//dataGridView1.Size = new Size(15, 426);
//dataGridView1.AutoSizeRowsMode =
DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders;
//dataGridView1.ColumnHeadersBorderStyle =
DataGridViewHeaderBorderStyle.Single;
//dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.Single;
//dataGridView1.GridColor = Color.Black;
//dataGridView1.RowHeadersVisible = false;

118
dataGridView1.Columns[0].Name = "DisplayNameOrigen";
dataGridView1.Columns[1].Name = "UserNameOrigen";
dataGridView1.Columns[2].Name = "IPOrigen";
dataGridView1.Columns[3].Name = "DisplayNameDestino";
dataGridView1.Columns[4].Name = "UserNameDestino";
dataGridView1.Columns[5].Name = "IPDestino";
dataGridView1.Columns[6].Name = "HoraInicio";
dataGridView1.Columns[7].Name = "HoraFin";
dataGridView1.Columns[8].Name = "Duracion";
dataGridView1.Columns[9].Name = "Fecha";
//dataGridView1.Columns[9].DefaultCellStyle.Font = new
Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Italic);

//dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
//dataGridView1.MultiSelect = false;
//dataGridView1.Dock = DockStyle.Fill;

//dataGridView1.CellFormatting += new
DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);
}

public void AReporteadorDataGridView()


//string [] parametros)
{

/* if (parametros != null)
{
string[] row1 = { parametros[0], parametros[1], parametros[2], parametros[3],
parametros[4], parametros[5], parametros[6], parametros[7], parametros[8], parametros[9]
};
dataGridView1.Rows.Add(row1);
}

*/

//string[] usn = new string[10];


string usn0 = "Liliana";
string usn1 = "Lilian";
string usn2 = "Lilia";
string usn3 = "Lili";
string usn4 = "Lil";
string usn5 = "Li";
DateTime usn6 = DateTime.Parse("02:00:00");
DateTime usn7 = DateTime.Parse("02:00:00");
DateTime usn8 = DateTime.Parse("02:00:00");
DateTime usn9 = DateTime.Parse("22/11/2011");

// for (int i = 0; i < 10; i++)


119
//{
string[] row1 = { "Agustin", "10", "1.1.1.2", "Liliana", "20", "1.1.1.3", "02:20:00",
"02:22:00", "00:02:00", "11/22/2011" };
// string[] row0 = { usn0.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
// string[] row1 = { usn1.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
string[] row2 = { usn2.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
string[] row3 = { usn3.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
// string[] row4 = { usn4.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
// string[] row5 = { usn5.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
// string[] row6 = { usn6.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
// string[] row7 = { usn4.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
// string[] row8 = { usn5.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
//string[] row9 = { usn6.ToString(), "20", "1.1.1.3", "Agustin", "10", "1.1.1.2",
"02:00:00", "02:01:00", "02:00:00", "11/22/1968" };
//string[] row2 = { "Paola", "30", "1.1.1.4", "Liliana", "20", "1.1.1.3", "03:00:00",
"03:10:00", "00:10:00", "11/22/2011" };
// string[] row3 = { "Agustin", "10", "1.1.1.2", "Paola", "30", "1.1.1.4",
"02:00:07", "02:00:00", "02:00:00", "11/22/1968" };
// string[] row3 = { "Liliana", "20", "1.1.1.3", "Paola", "30", "1.1.1.4", "01:53:00",
"01:56:00", "00:03:00", "11/22/2011" };

dataGridView1.Rows.Add(row1);
dataGridView1.Rows.Add(row2);
dataGridView1.Rows.Add(row3);
// }

private void button2_Click_1(object sender, EventArgs e)


{
SqlConnection conn = new SqlConnection("Data
Source=.\\SQLEXPRESS;AttachDbFilename=C:\\Users\\Agustin\\Desktop\\PBX-
Server\\PBX\\PBX\\DBRep.mdf;Integrated Security=True;User Instance=True");
conn.Open();
SqlDataReader myReader = null;

SqlCommand ComandoSql = new SqlCommand();


//"INSERT INTO Tr"+ ReporteadorDataGridView.Rows[0].Cells[0]);
120
ComandoSql.Parameters.Add("@usn0",SqlDbType.NVarChar);
ComandoSql.Parameters.Add("@usn1", SqlDbType.NVarChar);
ComandoSql.Parameters.Add("@usn2", SqlDbType.NVarChar);
ComandoSql.Parameters.Add("@usn3", SqlDbType.NVarChar);
ComandoSql.Parameters.Add("@usn4", SqlDbType.NVarChar);
ComandoSql.Parameters.Add("@usn5", SqlDbType.NVarChar);
ComandoSql.Parameters.Add("@usn6", SqlDbType.Time);
ComandoSql.Parameters.Add("@usn7", SqlDbType.Time);
ComandoSql.Parameters.Add("@usn8", SqlDbType.Time);
ComandoSql.Parameters.Add("@usn9", SqlDbType.Date);

ComandoSql.CommandText = "INSERT INTO Tr (DisplayNameOrigen,


UserNameOrigen,IPOrigen,DisplayNameDestino,UserNameDestino,IPDestino,HoraInicio,
HoraFin,Duracion,Fecha) VALUES
(@usn0,@usn1,@usn2,@usn3,@usn4,@usn5,@usn6,@usn7,@usn8,@usn9)";

ComandoSql.Connection = conn;
ComandoSql.ExecuteNonQuery();
conn.Close();
}

private void buttonX2_Click(object sender, EventArgs e)


{
Creditos firma = new Creditos();
firma.Show();
}

private void buttonX3_Click(object sender, EventArgs e)


{
Close();
}

121
Bibliografía

[1] Huidobro Moya José Manuel, TECNOLOGIA VOIP Y TELEFONIA IP: LA


TELEFONIA POR INTERNET, Creaciones Copyright, 2006.

[2] Andrew S. Tanenbaum, REDES DE COMPUTADORAS, Prentice-Hall, 1998.

[3] RFC 3261 SIP: Session Initiation Protocol.

[4] Deitel, Harvey, CÓMO PROGRAMAR EN C#, Pearson Educación, 2007.

[5] Gómez, Julio y Gil, Francisco, VoIP y Asterisk, RA-MA Editorial,2008.

122

También podría gustarte