Central telefónica IP - Facultad Regional San Nicolás

Anuncio
UNIVERSIDAD TECNOLOGICA NACIONAL
FACULTAD REGIONAL SAN NICOLAS
INGENIERIA EN ELECTRONICA
PROBLEMA DE INGENIERÍA
TECNICAS DIGITALES III
CENTRAL TELEFÓNICA IP EN MEMOR IA
COMPACT FLASH
Integrantes:
- Juan Carlos Priotti
- Martín Roberti
Docentes:
- Profesor: Felipe Poblete
- Auxiliar: Mariano González
AÑO 2008
Técnicas Digitales III – Problema de ingeniería
INDICE
OBJETIVOS DEL TRABAJO
3
MATERIAS INTEGRADAS
3
POSIBLES APLICACIONES
3
BIBLIOGRAFÍA
3
DESARROLLO
5
INTRODUCCIÓN
Voz sobre IP
ASTERISK PBX
CONCEPTOS DE CÁLCULO DE TRÁFICO
DIMENSIONAMIENTO DE HARDWARE Y ACCESO A INTERNET
TEORÍA DE FUNCIONAMIENTO
INSTALACIÓN DEL SISTEMA
5
5
6
9
12
13
14
CONSIDERACIONES SOBRE LOS COSTOS DE NUESTRA PBX
27
RESULTADOS DE LAS PRUEBAS
28
CONCLUSIONES
28
ANEXOS
29
1. FOTOS DE PANTALLAS
29
2. PROTOCOLO SIP
Una breve historia del protocolo SIP
Funciones del protocolo SIP
Componentes del protocolo SIP
Clientes:
Servidores:
Comandos del procotolo SIP
Un ejemplo típico de una sesión SIP
Formato de Solicitudes SIP
Formato de Respuesta de mensaje SIP
Tipos de respuesta SIP
Relación entre llamada, diálogo, transacción y mensajes
32
32
32
33
33
33
34
34
36
37
38
38
3. GUÍA DE INSTALACIÓN DE FreeBSD
41
4. LENGUAJE XML
Estructura de un documento XML
Modelos de contenido
XML Schemas (XSD)
Lenguaje de enlace XML (XLINK)
56
56
59
60
60
5. ADAPTADOR ANALÓGICO SISCO LINKSYS PAP2
61
6. ADVANTECH PCM 5820
61
7. LISTADOS DE PROGRAMAS
63
2
OBJETIVOS DEL TRABAJO
El objetivo del proyecto es crear una central telefónica basada en telefonía IP utilizando hardware
mínimo y de bajo coste, en nuestro caso hacemos uso de una placa madre industrial sin partes
móviles y de bajo consumo marca Advantech modelo PCM-5820. En lo que respecta a Software, se
utilizó el sistema operativo Open Source FreeBSD en su versión 7.1, los lenguajes de programación
PHP, XML y HTML, la plataforma Asterisk que es ni más ni menos que el núcleo de la central
telefónica IP, el servidor WEB Lighttpd, siendo todas estas herramientas open source.
MATERIAS INTEGRADAS



Informática II: Programación estructurada y modular.
Sistemas de Comunicaciones II: Telefonía, VoIP, tráfico, redes y protocolos.
Técnicas Digitales III: Programación en ensamblador, dispositivos de almacenamiento,
motherboards.
POSIBLES APLICACIONES

Central telefónica IP para empresas PYMES. En el caso de grandes empresas se debería
ampliar las capacidades de Hardware.
BIBLIOGRAFÍA

Sitios de Internet.
• Manual de FreeBSD - http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/
• Lighttpd web server - http://www.lighttpd.net/
• Asterisk - http://www.voip-info.org/wiki-Asterisk
• PHP - http://www.php.net/manual/en/
• HTML
• XML - http://es.wikipedia.org/wiki/XML
• Leyendo XML desde PHP - http://www.phpbsd.net/2007/02/09/leyendo-xml-desde-php-consimplexml/
• SimpleXML - http://php5.bitflux.org/phpconf2004/slide_36.php
• Compact Flash - http://www.pcengines.ch/cfwear.htm
• ATA (adaptador telefónico analógico) http://www.linksys.com/servlet/Satellite?c=L_CASupport_C2&childpagename=US%2FLayo
ut&cid=1169083352234&pagename=Linksys%2FCommon%2FVisitorWrapper
• SBC (Single Board Computer) PCM 5820 http://www.advantech.com/Support/detail_list.asp?model_id=PCM-5820

Libros, etc.
• The complete FreeBSD - http://www.lemis.com/grog/Documentation/CFBSD/book.pdf.gz
• Absolute FreeBSD, 2nd Edition -The Complete Guide to FreeBSD by Michael W. Lucas
November 2007, 744 pp. ISBN-10 1-59327-151-4 ISBN-13 978-1-59327-151-0
3
• Asterisk: The Future of Telephony, Second Edition Join the Open Source PBX Revolution
By Jim Van Meggelen, Jared Smith, Leif Madsen
August 2007
Pages: 602
ISBN 10: 0-596-51048-9 | ISBN 13: 9780596510480
4
DESARROLLO
INTRODUCCIÓN
El Avance constante en los desarrollos de computadoras han hecho que en la actualidad contemos
con dispositivos de varios GHz de velocidad en tamaños de menos de 3,5 pulgadas sin necesidad
de contar con soportes mecánicos voluminosos para refrigerarse ni dispositivos de almacenamiento
móviles, por lo que es común encontrar Motherboards de 3,5 pulgadas con soporte de
almacenamiento en memoria CF “Compact Flash”, placas ethernet, , conectores USB, puertos
series, salida a monitor y muchos otros dispositivos de I/O. Estos avances junto al continuo
desarrollo de software open source nos permiten desarrollar dispositivos de alta capacidad de
cómputo, altas prestaciones y gran estabilidad a un costo accesible.
En nuestro caso usaremos estas ventajas para desarrollar una central telefónica IP que corre bajo
el sistema operativo Unix Open Source FreeBSD todo embebido en una memoria Compact Flash
contando además con una interface Web de administración.
Voz sobre IP
Voz sobre Protocolo de Internet, también llamado Voz sobre IP, VoIP (por sus siglas en inglés),
es un grupo de recursos que hacen posible que la señal de voz viaje a través de Internet empleando
un protocolo IP (Internet Protocol). Esto significa que se envía la señal de voz en forma digital en
paquetes en lugar de enviarla (en forma digital o analógica) a través de circuitos utilizables sólo
para telefonía como una compañía telefónica convencional o PSTN (Public Switched Telephone
Network o Red Telefónica Pública Conmutada).
Los Protocolos que son usados para llevar las señales de voz sobre la red IP son comúnmente
referidos como protocolos de Voz sobre IP o protocolos IP, y entre ellos podemos mencionar al
protocolo SIP, H323, MGCP entre los más usados.
El tráfico de Voz sobre IP puede circular por cualquier red IP, incluyendo aquellas conectadas a
Internet, como por ejemplo redes de área local (LAN).
Es muy importante diferenciar entre Voz sobre IP (VoIP) y Telefonía sobre IP.


VoIP es el conjunto de normas, dispositivos, protocolos, en definitiva la tecnología que
permite la transmisión de la voz sobre el protocolo IP.
Telefonía sobre IP es el conjunto de nuevas funcionalidades de la telefonía, es decir, en lo
que se convierte la telefonía tradicional debido a los servicios que finalmente se pueden
llegar a ofrecer gracias a poder portar la voz sobre el protocolo IP en redes de datos.
Volvendo a los protocolos usados en Voz sobre IP, el protocolo SIP o Session Initiation Protocol
es el más usado en los últimos tiempos y ya es un estándar para comunicaciones en telefonía por IP.
Este protocolo fue desarrollado por por el IETF MMUSIC Working Group con la intención de ser
el estándar para la iniciación, modificación y finalización de sesiones interactivas de usuario donde
intervienen elementos multimedia como el video, voz, mensajería instantánea, juegos online y
realidad virtual.
5
La sintaxis de sus operaciones se asemeja a las de HTTP y SMTP, los protocolos utilizados en los
servicios de páginas Web y de distribución de e-mails respectivamente. Esta similitud es natural ya
que SIP fue diseñado para que la telefonía se vuelva un servicio más en la Internet.
En noviembre del año 2000, SIP fue aceptado como el protocolo de señalización de 3GPP y
elemento permanente de la arquitectura IMS (IP Multimedia Subsystem)
Para una introducción sobre el protocolo SIP ver el punto 1 del anexo.
ASTERISK PBX
Ya hemos visto que el protocolo SIP es el más usado para comunicaciones en telefonía IP, pero
hasta ahora no sabemos cómo vamos a poder usar ese protocolo de comunicación para llevar a cabo
nuestro proyecto. Podríamos decidir crear nuestro propio stack de SIP, pero eso sería una tarea que
llevaría mucho tiempo y necesitaríamos muchas horas hombre en programación, pruebas y
correcciones de errores, por lo que vemos que lo más acertado en el caso de desarrollos como estos
es usar software ya existente, que haya sido bien probado, que esté actualmente en producción y
que las licencias del mismo nos permitan hacer uso de éste y poder desarrollar y/o comercializar un
producto basado en este software. Todo lo anterior es posible gracias a la existencia de las
comunidades Open Source, que desarrollan y distribuyen software de gran calidad, con código
fuente incluido y bajo licencias muy abiertas que dan libertad a nuestros desarrollos. Entre los
programas que incluyen stack de sip y nos sirven como base para crear productos propios podemos
citar:





Asterisk
SER
OpenSER
Yate
FreePBX
Nosotros optamos por Asterisk, ya que es de por sí una PBX IP muy completa con muchos años
de desarrollo, estabilidad y una gran comunidad de desarrolladores y empresas que usan esta
plataforma, lo que hace que ante cualquier duda sobre su configuración y solución de problemas
tengamos la posibilidad de encontrar la solución de forma muy simple.
Asterisk posee además de soporte SIP, soporte para otros protocolos de comunicación como ser
H.323, Skinny (Cisco), IAX (Inter Asterisk Exchange), jabber, MGCP (Media Gateway Control
Protocol), Soporte para placas de telefonía estándart (ZAP), transcodificación para llamadas usando
diferentes códigos (G.711u, G.711a, G.729, Speex, ILBC, GSM, etc). Tampoco podemos dejar de
lado la extensa lista de servicios PBX que nos ofrece como ser: creación de IVR (Interactive Voice
Response), Grabación de llamadas, creación dial plans, voicemail y voice2email, call parking,
transferencia de llamadas, reenvío de llamadas y muchos otros servicios más que interesantes que
quedan sólo limitados a la imaginación y conocimiento de las opciones de configuración de esta
PBX IP.
En lo referente a la configuración de Asterisk, nosotros nos enfocaremos en solamente dos
archivos de configuración; extensions.conf y sip.con.
Extensions.conf es el archivo que nos dice qué hacer cuando llega una llamada a nuestra PBX, o
qué hacer en caso de querer hacer una llamada con algún teléfono conectado a nuestra central
telefónica.
Un ejemplo de extensions.conf es el siguiente:
6
[general]
static=yes
writeprotect=no
[sip_users]
exten
exten
exten
exten
exten
=>
=>
=>
=>
=>
_2XX,1,Dial(SIP/${EXTEN},10)
_2XX,2,Voicemail(u${EXTEN}@default)
_2XX,3,Hangup()
_2XX,102,Voicemail(b${EXTEN}@default)
_2XX,103,Hangup
exten => 115,1,Playback(vm-extension)
exten => 115,2,SayDigits(${CALLERID(num)})
exten => 115,3,Hangup()
exten => 300,1,Answer()
exten => 300,2,Echo()
exten => 300,3,Hangup()
exten => 999,1,VoicemailMain(${CALLERID(num)})
exten => 999,2,Hangup()
exten => _00X.,1,Dial(SIP/${EXTEN}@provider,60)
exten => _00X.,2,Hangup()
exten => _X!,1,Playback(invalid)
exten => _X!,2,Hangup()
Donde tenemos tenemos un contexto general para configuraciones que afectan a todos los demás
contextos y un contecto sip_users, que en este caso lo usamos para generar la lógica de nuestro Dial
Plan.
Como vemos, para cualquier llamada que empiece con 2 y tenga 3 dígitos (_2XX) la llamada va a
ser dirigida a un usuario SIP con el mismo número marcado. En cado que la llamada falle por
usuario desconectado o busy se conectará automáticamente al voicemail del usuario.
Si llamamos al 115, lo que escucharemos será la PBX que nos repetirá el número de nuestro
internos, cosa que usamos para saber si tenemos algún problema con el teléfono IP.
También tenemos una funcion Echo() cuando llamamos a la extensión 300, que lo que hace es
repetir lo que digamos con un cierto retardo (eco), de esta manera sabemos si la comunicación es
bidireccional.
Llamando al 999 podemos acceder el menú del voicemail, que nos pedirá el password de nuestra
cuenta (crada por la interface web) y desde ahí podremos oir los mensajes almacenados que
hayamos recibido.
Para las llamadas que empiecen con 00 la PBX direccionará la llamada al proveedor de servicios
de telefonía que tenemos configurado en nuestra plataforma.
Por último, para cualquier número que sea marcado y que no haya habido coincidencia (_X!) la
pbx reproducirá un mensaje de audio diciendo que el número es inválido.
Sip.conf es el archivo que define la configuración del soporte SIP y es donde tenemos las cuentas
de usuarios SIP creadas en el sistema.
Un ejemplo de archivo sip.conf puede ser el siguiente:
[general]
context=default
bindaddr=0.0.0.0
7
srvlookup=yes
disallow=all
allow=alaw
allow=ulaw
allow=gsm
[100]
username=100
secret=100
callerid=100
type=friend
host=dynamic
context=sip_users
dtmfmode=rfc2833
insecure=port
canreinvite=yes
nat=yes
[200]
username=200
secret=200
callerid=200
type=friend
host=dynamic
context=sip_users
dtmfmode=rfc2833
insecure=port
canreinvite=yes
nat=yes
En esta configuración vemos que en la parte [general] definimos el compartamiento del protocolo
SIP a nivel servidor, donde decimos que el contexto por defecto es llamado “default”, el protocolo
SIP va a ser levantado en todas las IP's disponibles en el sistema (0.0.0.0), se va a poder usar DNS
SRV y habilitamos sólo los codecs G.711a, G.711u. Y GSM.
En la segunda parte del archivo de configuración definimos los usuarios o terminadores que
reconocemos para poder conectarnos. Los usuarios son teléfonos IP que se registrarán en nuestra
plataforma, mientras que los terminadores son servicios provistos por empresas que nos dan la
posibilidad de conectarnos a telefonía pública y hacer llamadas a cualquier lugar del mundo a
precios extremadamente bajos ya que la larga distancia se trafica por Internet y/o poder asignar a
nuestra cental telefónica un número DID (Direct Inward Dialing) que no es otra cosa que tener un
número de telefonía pública asignado a nuestra central telefónica, sin la necesidad de contratar un
servicios con nuestro proveedor local de telefonía, esto último nos permite poseer un número de
teléfono que puede ser numeración local o numeración de cualquier lugar del mundo (si son
provistos por el proveedor).
Aquí vemos que tenemos dos usuarios SIP 100 y 200, donde tienen como contraseña el número
100 y 200 respectivamente. También especificamos el callerid igual a los números de teléfono
también tenemos que son cuentas del tipo “friend”, es decir que pueden hacer y recibir llamadas (las
otras son user y peer que solamente reciben o hacen llamadas respectivamente). Otros parámetros
que definimos son host, donde al especificar que sea dynamic decimos que el IP puede ser un IP
cualquiera y no uno fijo, también definimos el contexto al que va a “caer” la llamada en el dialplan
(este contexto se define en el archivo extensions.conf). Definimos el modo que usaremos para el
DTMF (Dual Tone Multi Frequency) sea acorde a la RFC2833, también especificamos si el cliente
puede hacer reinvites, que son INVITES siguientes a establecerse la llamada y sirven para evitar
tener que pasar el tráfico de audio por la PBX, y que este camino se establezca entre los end points
8
(teléfonos IP). El último parámetro es nat=yes, que configura la cuenta para tener soporte NAT,
esto es muy necesario para los clientes que están detrás de routers que hacen NAT, ya que sin este
soporte las llamadas salen con audio unidireccional.
Como vemos, con sólo modificar dos archivos ya estamos con posibilidades de configurar nuestra
cental telefónica IP para poder hacer llamadas entre teléfonos IP y con destinos a telefonía pública
(PSTN), por lo que debemos ahora encontrar una forma de poder hacer esto y aplicar estos cambios.
Esto último lo podemos hacer mediante el uso de un lenguaje de programación como ser PHP,
que permite crear una interface web para administrar la configuración de nuestra plataforma,
permitiendo modificar los archivos de configuración y aplicando estos cambios en Asterisk. Todo
esto lo podemos ver en detalles en el listado de programas al final del informe.
CONCEPTOS DE CÁLCULO DE TRÁFICO
Muchas veces el simple hecho de tener funcionando una centrar telefónica no nos asegura que
podamos realizar llamadas en el momento deseado, ya que existe la posibilidad que no hayamos
tenido en cuenta la cantidad de llamadas que va a traficar la misma y por esto no haber
dimensionado en forma correcta las líneas externas disponibles.
Para dimensionar las líneas externas correctamente debemos conocer un poco sobre la teoría
estadística usada para el cálculo de los volúmenes de tráfico en telefonía, esto es el número de
Erlang y las fórmulas propuestas por este ingeniero danés.
El Erlang es una unidad adimensional utilizada en telefonía como una medida estadística del
volumen de tráfico.
El tráfico de un Erlang corresponde a un recurso utilizado de forma continua, o dos canales
utilizados al 50%, y así sucesivamente. Por ejemplo, si una oficina tiene dos operadores de teléfono
y ambos están ocupados durante todo el tiempo, esto representa dos Erlangs de tráfico, o si un canal
de radio está ocupado durante treinta minutos en una hora se dice que soporta un tráfico de 0.5
Erlangs.
De forma alternativa, un Erlang puede ser considerado como "multiplicador de utilización" por
unidad de tiempo, así un uso del 100% corresponde a 1 Erlang, una utilización de 200% son 2
Erlangs, y así sucesivamente. Por ejemplo, si el uso total del móvil en un área por hora es de 180
minutos, esto representa 180/60 = 3 Erlangs. En general, si la tasa de llamadas entrantes es de λ por
unidad de tiempo y la duración media de una llamada es h, entonces el tráfico A en Erlangs es:
A = λh
Esto puede ser usado para determinar si un sistema está sobredimensionado o se queda corto
(tiene demasiados o muy pocos recursos asignados. Por ejemplo, el tráfico medido sobre muchas
horas de ocupación puede ser usado para un T1 o un E1 para determinar cuántas líneas (troncales)
debieran de utilizarse durante las horas de mayor ocupación.
El tráfico medido en Erlangs es usado para calcular el nivel de servicio (GOS). Hay diferentes
fórmulas para calcular el tráfico entre ellos, Erlang B, Erlang C y la fórmula de Engset. Esto será
discutido a continuación, y cada uno puede ser derivado como un caso espacial de Procesos de
tiempo continuo de Markov conocido como birth-death process.
Fórmula Erlang B
La fórmula de Erlang B asume una población infinita de orígenes (como usuarios de telefonía), la
cual ofrece tráfico en conjunto a N servidores (como líneas en un grupo de troncales).
9
La tasa de llegadas de nuevas llamadas (tasa de nacimiento) es igual a λ y es constante, no
depende del número de recursos activos, porque se asume que el total de recursos es infinito. La
tasa de abandono (tasa de mortandad) es igual al número de llamadas en progreso dividida por h, la
media del tiempo de llamadas en espera. La fórmula calcula la probabilidad de bloqueo en una
pérdida del sistema, si un requerimiento no es atendido inmediatamente cuando trata de utilizar un
recurso, y este es abortado.
Por lo tanto no son encolados. El bloqueo ocurre cuando hay un nuevo requerimiento de recursos,
pero todos los servidores ya están ocupados. La fórmula asume que el tráfico que es bloqueado se
libera inmediatamente.
A continuación se muestra cómo puede ser expresado recursivamente, en una forma que es usada
para calcular tablas de la fórmula de Erlang B:
donde:
* B es la probabilidad de bloqueo
* N es el número de recursos como servidores o circuitos en un grupo
* A = λh es la cantidad de tráfico entrante expresado en Erlangs
La fórmula Erlang B se aplica a los sistemas con pérdidas, tales como sistemas telefónicos tanto
fijos como móviles, que no ofrecen almacenamiento de llamadas (es decir, no permiten dejar la
llamada "en espera"), y no se pretende que lo hagan. Se asume que las llegadas de llamadas pueden
ser modeladas por un proceso de Poisson, pero es válida para cualquier distribución estadística de
tiempos entre llamadas.
Erlang B también es una herramienta para dimensionar tráfico entre centrales de conmutación de
voz.
Fórmula Erlang C
La Fórmula de Erlang C también asume una infinita población de fuentes, las cuales ofrecen en
conjunto, un trafico de A Erlangs hacia N servidores. Sin embargo, si todos los servidores están
ocupados cuando una petición llega de una fuente, la petición es introducido en la cola. Un sin fin
de números de peticiones podrían ir a la cola en este modo simultáneamente. Esta formula calcula la
probabilidad de la cola ofrecido en el trafico, asumiendo que las llamadas que fueron bloqueadas se
quedaran en el sistema hasta que se pueda atender. Esta formula es usada para determinar la
cantidad de agentes o representantes de clientes, que necesitará en un Call Center para después
saber la probabilidad en la cola.
10
Donde:
* A es la intensidad total del trafico ofrecido en unidades de Erlangs.
* N es la cantidad de servidores [número de troncales].
* PW es la probabilidad de que un cliente tenga que esperar para ser atendido.
Se asume que las llamadas entrantes puede ser modeladas usando una distribución de Poisson y
que el tiempo de espera de las llamadas son descriptas por una distribución exponencial negativa.
Fórmula Engset
La fórmula Engset, así llamada por T. O. Engset, está relacionada pero funciona con una
población finita de S orígenes en lugar de la población infinita de orígenes que asume Erlang:
Esto puede ser expresado recursivamente del siguiente modo, en una forma que es usada para
calcular las tablas de la fórmula Engset:
donde:
* E es la probabilidad de bloqueo
* A es el tráfico en Erlangs generado por cada origen cuando está desocupado
* S es el número de orígenes
* N es el número de servidores
De nuevo, se asume que las llamadas que llegan pueden ser modeladas por una distribución
Poisson y que los tiempos de espera son descriptos por una distribución exponencial negativa. Sin
embargo, debido a que hay un número finito de servidores, la tasa de llegada de las nuevas llamadas
11
decrece a medida que nuevos orígenes (como abonados telefónicos) se vuelven ocupados y por lo
tanto no pueden originar nuevas llamadas. Cuando N = S, la fórmula se reduces a una distribución
binomial.
Teniendo en cuenta esta teoría de tráfico, nosotros podríamos dimensionar en forma correcta la
cantidad de líneas salientes que necesitaríamos en caso de usar nuestra PBX para dar servicios de
call center por ejemplo. Cuando hablamos de dimensionamiento en un caso así estamos hablando de
las líneas telefónicas a contratar (E1 en caso de Argentina) y del hardware a utilizar que soporte
estas líneas (voip gateway). En nuestro proyecto al enviar las llamadas por un proveedor de
servicios voip, estamos acotados más por el tráfico que dicho proveedor pueda darnos (cantidad de
llamadas simultáneas), al ancho de banda que nos esté dando el proveedor de Internet y al hardware
usado en la central telefónica.
* En caso de necesitar cálculos rápidos existen infinidad de recursos en la red que aplican la teoría
de tráfico en una forma simple ej: http://www.erlang.com/calculator/
DIMENSIONAMIENTO DE HARDWARE Y ACCESO A INTERNET
Como hemos hablado en el punto anterior, además de las líneas salientes disponibles deberemos
tener en cuenta el hardware usado y el ancho de banda de nuestro acceso a Intenet.
En el caso de tener que dimensionar el hardware de una central telefónica IP, deberemos tener en
cuenta los siguientes puntos:








Tipos de teléfonos que planeamos usar (analógicos, SIP, Skinny, H.323, MGCP)
Cantidad de teléfonos que operaremos
Cantidad de líneas externas
Tipo de líneas externas (nalog, BRI, PRI, T1, VoIP)
Cantidad de llamadas concurrentes internas/externas
Haremos transcodificación?
Tipos de servicios a brindar (Cancelación de eco, voicemail, colas de conferencia, call
center, grabación de llamadas, IVRs, text to speech, reconocimiento de habla)
Tipo de versión de asterisk instalado
No existe una fórmula para calcular las llamadas que nuestro sistema soportará antes de verse
superado, pero existen muchas experiencias e información sobre los límites que podemos esperar.
Si tomamos en cuenta la versión de Asterisk usada, sabemos que la versión 1.2 comienza a tener
problemas cuando el tráfico está alrededor de 220 llamadas concurrentes SIP. La versión 1.4 puede
soportar aproximadamente el doble de su antecesora, mientras que la 1.6 supera en un factor de 3 o
4 a la versión 1.4.
En cuanto a la velocidad y cantidad de memoria RAM, podemos decir que para CPUs de poca
velocidad Asterisk necesita de aproximadamente 30Mhz de cpu por cada llamada concurrente. En
nuestro proyecto usamos un micro 586 de 300 Mhz por lo que podemos decir que no deberíamos
tener problemas en traficar hasta 10 llamadas SIP simultáneas. En caso de CPUs de velocidades
media como ser 1Ghz (>256MB RAM), estamos en valores menores a 100 llamadas simultáneas.
Finalmente si nuestro hardware posee un micro de varios Ghz de velocidad, más de un núcleo y
suficiente memoria (> 1GB) podemos llegar a tener entre 200 y 350 llamadas concurrentes.
Todos los números antes explicados pueden variar y ser menores si usamos transcodificación en
las llamadas, es decir que recibimos una llamadas con un codec por ejemplo G.711 y
12
transcodificamos en G.729, esto debido a que necesitamos usar CPU extra para procesar el audio y
comprimir el mismo con los algoritmos que ofrece cada codec, cosa que no sucede si usamos el
mismo codec, ya que el audio es transferido directamente sin usar algoritmo alguno para
transcodificar.
En cuando al dimensionamiento del enlace a Internet, debemos tener en cuenta la cantidad de
llamadas simultáneas y los codecs usados para las misma, ya que cada codec comprime el audio en
forma diferente y usa mayor o menor ancho de banda. Para los codecs más comunes tenemos:







GSM - 13 Kbps, 20ms frame size
iLBC - 15Kbps,20ms frame size: 13.3 Kbps, 30ms frame size
ITU G.711 - 64 Kbps (ley u y a)
ITU G.723.1 - 5.3/6.3 Kbps, 30ms frame size
ITU G.726 - 16/24/32/40 Kbps
ITU G.729 - 8 Kbps, 10ms frame size
Speex - 2.15 a 44.2 Kbps
TEORÍA DE FUNCIONAMIENTO
La figura 4 muestra un esquema elemental del sistema desarrollado
Fig 4: Esquema general del proyecto
En el esquema de la figura 4 vemos que la IP PBX está representada como una motherboard SBC
(Single Board Computer) y está conectada a nuestra red local detrás de nuestro router que nos
13
conecta a Internet. El mismo lado del router tenemos nuestros teléfonos IP o adaptadores
telefónicos analógicos (ATA) que adaptan nuestros teléfonos analógicos para que trabajen como
teléfonos IP. También podemos tener computadoras con algún software con soporte SIP (softphone)
y poder usar estas computadoras como teléfonos IP.
Nuestros teléfonos, sean estos IP, computadoras con softphone o adaptadores analógicos van a
tener que registrarse en nuestra IP PBX, luego de lo cual podrán hacer llamadas entre ellos, pasando
todo el tráfico telefónico a través de nuestra red local. En caso de necesitar usar el teléfono desde un
lugar remoto (otro país por ejemplo), ésto lo podremos hacer registrando nuestro teléfono IP en la
IP pública de nuestra PBX, para lo cual debemos tener configurado nuestro router para enviar todo
el tráfico que llega a nuestro router a nuestra IP PBX(forward de los puertos).
En caso de necesitar hacer llamadas a PSTN (Public Switched Telephone Network), esto lo
podríamos hacer añadiendo un aparato llamado Gateway, que haría la translación de IP a telefonía,
o sino de una forma más simple (como lo hacemos nosotros), contratando un servicio de telefonía
IP a algún proveedor, los que nos dan, además de un número telefónico para recibir llamadas,
terminación de llamadas a todo el mundo a un precio muy bajo (aprox 10 veces menos para
llamadas internacionales).
INSTALACIÓN DEL SISTEMA
A continuación indicamos los pasos seguidos en orden para la instalación del sistema
1. Instalación de FreeBSD en una estación de trabajo
2. Creación de la imagen a descargar en la CF (Compact Flash) con TinyBSD
3. modificar la imagen con las configuraciones a medida (acceso a internet, instalación de
servidor web, lenguaje php, asterisk, mpeg123, librerías, copiar interfaz web)
4. Copiar imagen en memoria compact flash
A continuación pasamos a describir cada una de estas operaciones.
Instalación del sistema operativo base (FreeBSD)
1.1 General
Para poder desarrollar nuestra aplicación y crear una imagen que podamos luego copiar a la
memoria flash, debemos tener un sistema base, desde donde trabajaremos para crear la misma. Este
sistema base debe poseer todas las herramientas necesarias de desarrollo y también el código fuente
tanto de las aplicaciones a instalar como así también del kernel del sistema operativo. Usaremos
FreeBSD, que es un unix open source de mucho uso en este tipo de aplicaciones industriales
"embedded" ya que es extremadamente estable y además presenta una licencia mucho más abierta
que otros sistemas operativos open source. Esta diferencia hace que podamos desarrollar nuestra
aplicación, venderla y si no nos conviene no estamos obligados a entregar el código fuente, cosa
que con licencias GNU o GPL no sucede.
La instalación del Sistema Operativo FreeBSD se resume en los siguientes pasos:




Bajar imagen de CD desde ftp.freebsd.org y copiar en CD.
Arrancar instalación con el CD.
Crear partición en disco para la instalación.
Crear subparticiones.
14



Elegir tipo de instalación (X-Developer + KERNEL Developer) e instalar el sistema
operativo.
Configurar interfaz de red y servicios.
Finalizar instalación y arrancar nuevo sistema.
1.2 Modificación del código fuente del SO para superar problemas de compatibilidad
Debido a diferencias en la arquitectura de los microprocesadores Geode fabricados por National
(GX1) ciertas modificaciones deben ser hechas en el código fuente del sistema operativo.
Pasamos a detallar las modificaciones a realizar:
1. Usar el chip 8254 en lugar del Registro TSC (Time Stamp Counter) como clock. Si el registro
TSC es usado, el clock será muy lento en al menos un factor de 10. Esto hace que todo lo que use
un tsleep() se cuelgue, resultando en un sistema casi imposible de usar.
En el archivo:
/usr/src/sys/i386/isa/clock.c
Al final de la rutinA startrtclock(), reemplazar este código:
init_TSC();
}
Por este código:
/* init_TSC(); */
}
2. Modificar generic_bcopy() para usar byte-moves en vez de long-moves. En FreeBSD la rutina
generic_bcopy() usa una instrucción rep movsl. La dirección inicial pasada a generic_bcopy() es a
veces "non-long-alined". Esto debería funcionar, pero las plataformas GX1 se cuelgan.
En el archivo:
/usr/src/sys/i386/i386/support.s
Reemplazar este código:
ENTRY(generic_bcopy)
pushl
%esi
pushl
%edi
movl
12(%esp),%esi
movl
16(%esp),%edi
movl
20(%esp),%ecx
movl
subl
cmpl
jb
%edi,%eax
%esi,%eax
%ecx,%eax
1f
/* overlapping && src < dst? */
15
shrl
cld
rep
movsl
$2,%ecx
/* copy by 32-bit words */
/* nope, copy forwards */
movl
andl
20(%esp),%ecx
$3,%ecx
/* any bytes left? */
rep
movsb
popl
popl
ret
%edi
%esi
Por este nuevo código:
ENTRY(generic_bcopy)
pushl
%esi
pushl
%edi
movl
12(%esp),%esi
movl
16(%esp),%edi
movl
20(%esp),%ecx
movl
subl
cmpl
jb
%edi,%eax
%esi,%eax
%ecx,%eax
1f
shrl
cld
rep
movsl
$2,%ecx
movl
andl
20(%esp),%ecx
$3,%ecx
/* overlapping && src < dst? */
#if 0
/* copy by 32-bit words */
/* nope, copy forwards */
/* any bytes left? */
#else
cld
/* BRM */
#endif
rep
movsb
popl
popl
ret
%edi
%esi
Lo que esto hace es eliminar un intento de usar un lazo de optimización (lazo de instrucción de
movimiento de palabra). En su lugar, la cadena de caracteres es simplemente copiada usando la
instrucción de movimiento de bytes que normalmente manipula los bytes en la última palabra.
Este arreglo se necesita debido a una llamada en el archivo:
/usr/src/sys/dev/syscons/scvtb.c
16
La rutina sc_vtb_copy() llama a bcopy_toio() en una dirección impar cuando los bytes que
conforman la memoria de video están siendo rápidamente movidos o copiados en memoria luego de
un backspace, generando una penalidad.
3. Remover el uso de la interrupción INT 15/AX=E820h BIOS trap del modo VM86. Esta trampa
(trap) determina el tamaño de la memoria física y la disposición. FreeBSD usa esta
interrupción para dimensionar la memoria física, pero usa un esquema anterior si el trap falla. Esta
interrupción en la plataforma GX1 genera una falla de paginado fatal.
En el archivo:
/usr/src/sys/i386/i386/machdep.c
En la rutina getmemsize(), reemplazar este código:
i = vm86_datacall(0x15, &vmf, &vmc );
Por este nuevo código:
#if 0
i = vm86_datacall(0x15, &vmf, &vmc );
#else
i = 1;
#endif
Esto elimina el intento de usar la interrupción INT 15/E820.
2. Creación de la imagen con TinyBSD
Una vez instalado FreeBSD, usamos el sript tinyBSD que es el que nos permite crear la imagen
con un sistema operativo FreeBSD reducido más todas las aplicaciones necesarias. Este script viene
instalado por defecto en el sistema operativo.
Para comenzar lo primero que debemos conocer es la especificación técnica de la memoria flash
que es donde vamos a guardar la imagen que después será usada como si fuera un disco rígido por
la SBC.
Comencemos, lo primero es identificar el nombre de dispositivo que el sistema asigna a la
memoria CF, para ello tecleamos en el prompt del sistema el siguiente comando y le damos enter,
# dmesg
Cuando introducimos la memoria flash se despliega el siguiente mensaje
Dec
rev
Dec
bus
Dec
Dec
11 12:49:18 laptop
2.00/2.0a, addr 4>
11 12:49:18 laptop
uhub4
11 12:49:19 laptop
11 12:49:19 laptop
kernel: umass1: <Generic USB Storage Device, class 0/0,
on uhub4
root: Unknown USB device: vendor 0x0aec product 0x3260
kernel: da1 at umass-sim1 bus 1 target 0 lun 0
kernel: da1: <Generic USB Storage-CFC I20A> Removable
17
Direct Access SCSI-0 device
Dec 11 12:49:19 laptop kernel: da1: 40.000MB/s transfers
Dec 11 12:49:19 laptop kernel: da1: 122MB (250368 512 byte sectors: 64H 32S/T
122C)
Lo mismo podemos hacer con el comando
# tail –f /var/log/messages
obteniéndose el mismo mensaje.
El comando “tail” nos muestra los mensajes de syslog, que es un demonio (programa corriendo en
background) cuya función es mostrar los “log” del sistema, -f le indica al comando que lea la cola
de mensajes en forma continua.
Resaltamos con fondo de color amarillo sobre el mensaje los datos correspondientes a la memoria
CF, allí se puede ver que al dispositivo se le asignó el nombre “da1”, que es un dispositivo de
almacenamiento con una tasa de transferencia de 40 MB por segundos, con una capacidad de 122
MB distribuidos en 250368 sectores de 512 bytes, 64 cabezas, 122 cilindros y 32 sectores por pista
(sectors per track). También podemos ejecutar el siguiente comando
# diskinfo –v/dev/da1
El cual nos da una manera más clara de ver las especificaciones de la compact flash, tal como se
muestra:
/dev/da1
512
128188416
250368
122
64
32
#
#
#
#
#
#
sectorsize
mediasize in bytes (122M)
mediasize in sectors
Cylinders according to firmware.
Heads according to firmware.
Sectors according to firmware.
El paso siguiente es definir el archivo de configuración del kernel del sistema operativo llamado
TINYBSD y localizado en el directorio /usr/src/tools/tools/tinybsd/conf/default. Este archivo nos
permite especificar el soporte de dispositivos que tendrá nuestro kernel como ser placas de red,
soporte para puertos serie/paralelo, placas wireless, etc.
Como sólo nos interesa tener soporte para dispositivos que estén presentes en nuestra placa
madre, procedimos a eliminar el soporte para pcmcia, floppy disk, placas wireless, placas Ethernet
no presentes, intefaces tunnel, gif, ppp, soporte usb, etc. Al eliminar el soporte que no deseamos
usar hacemos que el kernel sea más chico y ocupe menos memoria, influyendo esto en la velocidad
del sistema y también en la memoria disponible para nuestro sistema.
El archivo TiNYBSD quedará de esta manera:
machine
cpu
ident
i386
I586_CPU
TINYBSD
# To statically compile in device wiring instead of /boot/device.hints
#hints
"GENERIC.hints"
# Default places to look for devices.
options
SCHED_4BSD
# 4BSD scheduler
18
options
INET
# InterNETworking
options
FFS
# Berkeley Fast Filesystem
options
SOFTUPDATES
# Enable FFS soft updates support
options
UFS_ACL
# Support for access control lists
options
UFS_DIRHASH
# Improve performance on big directories
options
MD_ROOT
# MD is a potential root device
options
NFSCLIENT
# Network Filesystem Client
options
NFSSERVER
# Network Filesystem Server
options
NFS_ROOT
# NFS usable as /, requires NFSCLIENT
options
MSDOSFS
# MSDOS Filesystem
options
CD9660
# ISO 9660 Filesystem
options
PROCFS
# Process filesystem (requires PSEUDOFS)
options
PSEUDOFS
# Pseudo-filesystem framework
options
GEOM_PART_GPT
# GUID Partition Tables.
options
COMPAT_43
# Compatible with BSD 4.3 [KEEP THIS!]
options
COMPAT_FREEBSD4
# Compatible with FreeBSD4
options
SYSVSHM
# SYSV-style shared memory
options
SYSVMSG
# SYSV-style message queues
options
SYSVSEM
# SYSV-style semaphores
options
_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options
KBD_INSTALL_CDEV
# install a CDEV entry in /dev
options
AHC_REG_PRETTY_PRINT # Print register bitfields in debug
options
ADAPTIVE_GIANT
# Giant mutex is adaptive.
device
apic
# I/O APIC
device
eisa
device
pci
# ATA and ATAPI devices
device
ata
device
atadisk
# ATA disk drives
device
atapist
# ATAPI tape drives
options
ATA_STATIC_ID # Static device numbering
# atkbdc0 controls both the keyboard and the PS/2 mouse
device
atkbdc
# AT keyboard controller
device
atkbd
# AT keyboard
device
psm
# PS/2 mouse
device
vga
# VGA video card driver
# syscons is the default console driver, resembling an SCO console
device
sc
# Add suspend/resume support for the i8254.
device
pmtimer
# Serial (COM) ports
device
sio
# 8250, 16[45]50 based serial ports
# PCI Ethernet NICs that use the common MII bus controller code.
# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
device
miibus
# MII bus support
device
rl
# RealTek 8129/8139
# Pseudo devices.
device
loop
# Network loopback
device
random
# Entropy device
device
ether
# Ethernet support
19
device
pty
# Pseudo-ttys (telnet etc)
device
md
# Memory "disks"
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
# Note that 'bpf' is required for DHCP.
device
bpf
# Berkeley packet filter
Ya teniendo las especificaciones técnicas y el archivo de configuración del kernel, lo que sigue es
ejecutar el script tinyBSD pasándole los parámetros tal como se muestra:
# /usr/src/tools/tools/tinybsd/tinybsd sectors=512 heads=64 spt=32 conf=default
Esto generará el archivo imagen tinybsd.bin en el directorio /usr/src/tools/tools/tinybsd/ el cual
incluirá el kernel del sistema operativo, el sistema de archivos, comandos básicos y drivers
necesarios para poder arrancar con el mismo desde la memoria compact flash especificada en la
creación de la imagen.
3. Modificación y configuración de la imagen creada en el punto 2
3.1 Configuración del sistema operativo
Ya teniendo la imagen creada con el sistema operativo en ella, debemos poder acceder a esta y
configurar los archivos de inicio del sistema. Para poder acceder a la imagen, podemos montar la
misma en el directorio /mnt de la siguiente forma:
# mdconfig -a -t vnode
# mount /dev/md0a /mnt
-f
/usr/src/tools/tools/tinybsd/tinybsd.bin
-u
0
luego editar y salvar los siguientes archivos:
# vi /etc/rc.conf
hostname="embedded"
sendmail_enable="NONE"
sshd_enable="YES"
usbd_enable="NO"
inetd_enable="NO"
portmap_enable="NO"
update_motd="NO"
varmfs="YES"
populate_var="YES"
varsize="8192"
tmpmfs="YES"
ifconfig_rl0="inet 192.168.1.100
defaultrouter="192.168.1.1"
lighttpd_enable="YES"
netmask 255.255.255.0"
asterisk_enable="YES"
noip_enable="YES"
Con estas opciones deshabilitamos los servicios que no queremos usar, configuramos la creación de
/var y /tmp en memoria RAM con los tamaños indicados, configuramos la IP y puerta de enlace y
definimos asterisk y lighttpd para que se inicien junto al sistema.
20
# ee /etc/resolv.conf
nameserver
200.69.193.1
En resolv.conf definimos el IP del DNS que usaremos para resolver los nombres de dominio.
3.2 Instalación y configuración lighttpd y asterisk
Para poder instalar el servidor web y la IP PBX en nuestra m
i agen de memoria, primero
procederemos a instalar estos programas en nuestra computadora base, y luego copiaremos uno a
uno los archivos de cada instalación a la imagen de nuestra memoria, que está montada en /mnt.
Para instalar los programas usaremos los ports del sistema:
#
#
#
#
#
#
cd /usr/ports/www/lighttpd
make install clean
cd /usr/ports/lang/php5
make install clean
cd /usr/ports/net/asterisk
make install clean
Ya con los programas instalados en el sistema base debemos averiguar cuales son los archivos que
fueron instalados y copiarlos a nuestra imagen:
pkg_info -qxL asterisk
/usr/local/man/man8/asterisk.8.gz
/usr/local/man/man8/astgenkey.8.gz
/usr/local/man/man8/autosupport.8.gz
/usr/local/man/man8/safe_asterisk.8.gz
/usr/local/etc/asterisk/adsi.conf-dist
/usr/local/etc/asterisk/adtranvofr.conf-dist
/usr/local/etc/asterisk/agents.conf-dist
/usr/local/etc/asterisk/alarmreceiver.conf-dist
/usr/local/etc/asterisk/alsa.conf-dist
/usr/local/etc/asterisk/asterisk.adsi-dist
...
...
..
Lo que nos dará una lista muy larga de archivos. Para no tener que copiar uno a uno los archivos, lo
que hacemos es crear un script que lo hace por nosotros, pero antes debemos tener la ubicación de
cada archivo en un archivo de texto que será leido por el script.
pkg_info -qxL asterisk > ./archivos.txt
pkg_info -qxL php5 >> ./archivos.txt
pkg_info -qxL lighttpd >> ./archivos.txt
El script que crearemos se llamará copiar_archivos.sh
# vi copiar_archivos.sh
#!/bin/sh
cat ./archivos.txt | while read line
do
cp $line /mnt$line
21
echo $line
done
Le damos permisos de ejecución y los ejecutamos.
#chmod +x copiar_archivos.sh
# ./copiar_archivos.sh
Luego que se hayan terminado de copiar los archivos de los programas en la imagen, debemos
copiar las librerías que necesitan estos programas para funcionar. Para saber cuales son las librerías
usamos el comando ldd
# ldd /usr/local/sbin/lighttpd
/usr/local/sbin/lighttpd:
libpcre.so.0 => /usr/local/lib/libpcre.so.0 (0x280a3000)
libssl.so.5 => /usr/lib/libssl.so.5 (0x280ca000)
libcrypto.so.5 => /lib/libcrypto.so.5 (0x2810b000)
libc.so.7 => /lib/libc.so.7 (0x28264000)
# cp /usr/local/lib/libpcre.so.0 /mnt/usr/local/lib/libpcre.so.0
# cp /usr/lib/libssl.so.5 /mnt/usr/lib/libssl.so.5
# cp /lib/libcrypto.so.5 /mnt/lib/libcrypto.so.5
# ldd /usr/local/sbin/asterisk
/usr/local/sbin/asterisk:
libncurses.so.7 => /lib/libncurses.so.7 (0x2814e000)
libm.so.5 => /lib/libm.so.5 (0x2818d000)
libcrypto.so.5 => /lib/libcrypto.so.5 (0x281a2000)
libthr.so.3 => /lib/libthr.so.3 (0x282fb000)
libc.so.7 => /lib/libc.so.7 (0x2830e000)
#
#
#
#
#
cp
cp
cp
cp
cp
/lib/libncurses.so.7 /mnt/lib/libncurses.so.7
/lib/libm.so.5 /mnt/lib/libm.so.5
/lib/libcrypto.so.5 /mnt/lib/libcrypto.so.5
/lib/libthr.so.3 /mnt/lib/libthr.so.3
/lib/libc.so.7 /mnt/lib/libc.so.7
# ldd /usr/local/bin/php
/usr/local/bin/php:
libcrypt.so.4 => /lib/libcrypt.so.4 (0x282a4000)
libm.so.5 => /lib/libm.so.5 (0x282bd000)
libxml2.so.5 => /usr/local/lib/libxml2.so.5 (0x282d2000)
libz.so.4 => /lib/libz.so.4 (0x283f5000)
libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x28407000)
libc.so.7 => /lib/libc.so.7 (0x284fc000)
#
#
#
#
#
#
cp
cp
cp
cp
cp
cp
/lib/libcrypt.so.4 /mnt/lib/libcrypt.so.4
/lib/libm.so.5 /mnt/lib/libm.so.5
/usr/local/lib/libxml2.so.5 /mnt/usr/local/lib/libxml2.so.5
/lib/libz.so.4 /mnt/lib/libz.so.4
/usr/local/lib/libiconv.so.3 /mnt/usr/local/lib/libiconv.so.3
/lib/libc.so.7 /mnt/lib/libc.so.7
Algo que además debemos copiar a la imagen en el archivo de configuración del SSHD para poder
luego acceder a la PBX por medio de SSH (Secure Shell):
22
#cp /etc/ssh/sshd_config /etc/ssh/sshd_config
Editamos luego este archivo y le agregamos la opción para poder entrar al sistema como root en
forma remota:
#vi /mnt/etc/ssh/sshd_config
permitrootlogin = yes
Luego debemos modificar el archivo de inicio del servidor Lighttpd:
#vi
usr/local/etc/lighttpd.conf
y agregamos:
{{{
server.modules = (
"mod_fastcgi",
)
esto también:
fastcgi.server = ( ".php" => ((
"bin-path" => "/usr/local/bin/php-cgi",
"socket" => "/tmp/php.socket"
)))
Y esto:
"max-procs" => 1,
Esto último habilita un sólo proceso para correr, lo que es bueno ya que tenemos sólo 128 MB de
memoria y debemos cuidar la misma que luego será utilizada por los procesos de la PBX.
Luego agregamos esta línea en /usr/local/etc/php.ini:
#vi /usr/local/etc/php.ini
cgi.fix_pathinfo = 1
}}}
y establecemos límites de memoria máximos en 10MB (128 MB por defecto), límites para post en
1MB y limite de archivo para subir en 1MB. Sino vamos a estar asignando muchos recursos que no
serán utilizados por el servidor web, ya que sólo tendrá un usuario a la vez conectado cuando haya
que hacer cambios en la configuración y nosotros deseamos tener la mayor cantidad de memoria
disponible para la PBX.
Asterisk por defecto corre como usuario root, y el servidor lighttpd corre como usuario www, por
lo que debemos hacer ciertos cambios en la configuración de asterisk para permitir ser
comandado/modificado por medio de la interface web. Estos cambios se detallan a continuación:
chmod 666 /usr/local/etc/asterisk/*
23
Con esto le damos permisos completo de lectura y escritura a los archivos de configuración de
Asterisk (así la interface puede modificar los archivos).
En /usr/local/etc/rc.d/asterisk agregamos:
command_args="-U www"
esto es para que levante los servicios con el usuario www.
Luego cambiamos permisos a los archivos de Asterisk
chown -R www /usr/local/etc/asterisk
chown -R www /usr/local/lib/asterisk/modules
chown -R www /usr/local/share/asterisk
El directorio /var, que es usado por los programas para escribir logs y guardar archivos como ser
el PID del proceso debe ser creado al inicio, no es creado completamente. La instalación básica de
TinyBSD no contempla eso, por lo que nosotros debemos hacernos cargo de eso copiando
/etc/mtree/BSD.var.dist a la imagen de memoria:
# cp /etc/mtree/BSD.var.dist /mnt/etc/mtree/BSD.var.dist
y luego modificándolo para crear directorios necesitados por Asterisk
run
named
..
ppp
..
asterisk
..
spool
lock
..
asterisk
..
uname=bind gname=bind
gname=network mode=0770
uname=www
uname=uucp gname=dialer mode=0775
uname=www
Luego en /usr/local/etc/asterisk/asterisk.conf no debemos olvidar de cambiar astrundir => /var/run
por astrundir => /var/run/asterisk, que es donde sí va a poder escribir su PID al iniciar.
Como nuestro asterisk va a estar detrás de un router, y no va a tener IP pública, nos podremos
encontrar con el problema que el servidor del proveedor del servicio de telefonía no sepa cuál es
nuestro IP, ya que Asterisk va a estar enviando los mensajes SIP con el IP provado nuestro. Esto lo
podemos arreglar configurando asterisk para reescribir los mensajes SIP antes de enviarlos al
proveedor de terminación, y para esto último debemos saber nuestro IP siempre que conectemos
24
nuestra PBX en la red local. Como puede ser muy engorroso actualizar asterisk siempre son el IP
público de momento decidimos usar un nombre de dominio que se actualice automáticamente con
los datos entregados por la PBX. Hay muchos servicios gratis de este tipo como ser DynDNS, NOIP, etc.
Nosotros nos decidimos por NO-IP debido a la simplicidad de instalación y que su cliente está
hecho en lenguaje C, y usa sólo una librería estándard como dependencia.
Para instalar NO-IP en el sistema base hacemos lo siguiente:
#cd /usr/ports/dns/noip
#make install
#make conf
Con make conf creamos la configuración, en la que deberemos proveer el nombre de usuario y
password con el que nos registeamos en la página de NO-IP(http://www.no-ip.com/) y luego
copiamos los archivos a la imagen montada en /mnt
# pkg_info -qxL noip
/usr/local/bin/noip2
/usr/local/share/doc/noip/README.FIRST
/usr/local/share/doc/noip/COPYING
/usr/local/etc/rc.d/noip
#cp /usr/local/bin/noip2 /mnt/usr/local/bin/noip2
#cp /usr/local/etc/rc.d/noip /mnt/usr/local/etc/rc.d/noip
#cp /usr/local/etc/no-ip2.conf /mnt/usr/local/etc/no-ip2.conf
Luego editamos el archivo de configuración /mnt/usr/local/etc/no-ip2.conf y especificamos que
root para iniciar el servicio en vez del usuario noip, ya que este último no está presente en la imagen
del sistema.
3.3 Instalación de la interfaz web
Ya teniendo los archivos de los programas completamente copiados en la imagen, sólo nos queda
copiar la interface web a la image:
#cp -rv ./tecnicas3 /usr/local/www/
cambiamos permisos para que nuestro servidor web no tenga problemas en leer los archivos que
componen la interface:
#chown -R www /usr/local/www/
4 copiado de imagen de disco en compact flash
Ya con los programas y la interface web instalados en la imagen, debemos desmontar la misma y
luego copiarla a la memoria. Para copiar una imagen no podemos usar el comando cp, ya que la
imagen no es un archivo simple, sino que es una imagen que debe ser copiada sector en la memoria,
lo que sería similar a copiar una imagen de CD a un compact disk, para esto último usamos el
comando “dd”
25
# dd if=/usr/src/tools/tools/tinybsd/tinybsd.bin of=/dev/da1
Siendo /dev/da1 la compact flash reconocida en el sistema. Luego de copiar la imagen, sólo nos
queda conectar la compact flash al conector de la placa SBC e iniciar el sistema. Si todo salió bien,
podremos acceder a nuestra interfaz en http://192.168.0.100/tecnicas3/ entrando con un user admin
y contraseña “password”. Desde la interface web podremos crear cuentas y luego apuntando
nuestros teléfonos al IP de la PBX, registrarnos y hacer llamadas.
26
CONSIDERACIONES SOBRE LOS COSTOS DE NUESTRA PBX
Para nuestro proyecto hemos optado por usar una placa SBC de bajo consumo de 3.5 pulgadas de
tamano y conector compact flash. El uso de esta placa no es al azar, sino que hemos tenido en
cuenta el uso que le daremos al la IP PBX, la necesidad de usar una memoria compact flash en vez
de un disco rígido y el bajo consumo de nuestro equipo. Podriamos haber usado una simple PC
doméstica, de mayor velocidad, pero a la hora de proyectar una aplicación industrial como ser esta
PBX IP, debemos tener en cuenta el bajo consumo de la misma, con el consiguiente poco
calentamiento de los componentes, y la no necesidad de contar con partes moviles para refrigerar la
misma, lo que nos da mayor estabilidad en el tiempo y a la vez nos permite poder emplazar la
misma en ambientes cerrados y también con particulas en el aire. En un ambiente industrial
como el que citamos no sería posible tener mucha estabilidad usando hardware con partes moviles
como ser ventiladores para el microprocesador y discos rígidos, ya que estos últimos son muy
vulnerables a las vibraciones.
En lo referentes al precio del hardware, tenemos diversos fabricantes de placas madre y
adaptadores SIP, pero recomendamos los siguientes:
Hardware
SBC
SBC
SBC
ATA
ATA
Fabricante
PC Engines
Soekris
Advantech
Linksys
Grandstream
Sitio Web
www.pcengines.ch
www.soekris.com
www.advantech.com
www.linksys.com
www.grandstream.com
Precios
USD 120
USD 180
USD 230
USD 70
USD 50
Si consideramos que cada uno de los adaptadores telefónicos tienen un costo entre 50 70 dolares y
presentan 2 bocas telefónicas podemos establecer un costo de entre 25 y 35 dólares por boca, lo que
sumado al precio de los aparatos telefónicos de calidad intermedia (aprox USD30) nos da un costo
total de entre 55 y 65 dólares.
Para la construcción de la central telefónica tenemos los siguientes costos:
SBC PC Engines (http://www.pcengines.ch/alix3c1.htm)
Compact Flash 1GB (http://www.pcengines.ch/cf1024dp.htm)
Caja (http://www.pcengines.ch/box2c.htm)
Adaptador 18V (http://www.pcengines.ch/ac18veur.htm)
USD 101
USD 6
USD 7
USD 6
Costo total PBX
USD 120
Costo importación (aprox 50%) + envio
Costo total PBX en Argentina
Costo Teléfono + boca (Linksys)
USD 70
USD 190
USD 65
Costo Tocal PBX + 10 bocas
USD 840
27
RESULTADOS DE LAS PRUEBAS
Las pruebas de funcionamiento fueron hechas un adaptador telefónico-analógico Linksys PAP2 y
usando Xlite como softphone (www.xten.com) en una PC, que se registraron como usuarios 100 y
101 y pudieron realizar llamadas entre ellos con excelente calidad de audio. Las pruebas de
Voicemail fueron también exitosas, siendo estas hechas al llamar a alguno de los usuarios y no
atender las llamadas. Los mensajes pudieron ser escuchados discando 999 y entrando la clave de
acceso.
Para llamadas salientes por medio de un proveedor de telefonía usamos una cuenta con VoIP
Buster (www.voipbuster.com), y pudimos realizar llamadas a telefonía pública también con muy
buena calidad.
CONCLUSIONES
Habiendo trabajado en la creación de algo tan útil y versátil como lo es una central telefónica IP
en un tiempo razonable y con tan pocos recursos económicos, nos damos cuenta de la importancia
que tiene a nivel educativo y tecnológico el uso de software “open source”, el cuál nos abre nuevos
horizontes en el desarrollos de aplicaciones, nos brinda la posibilidad de crear productos de mucha
calidad y a la vez innovadores, y nos permite estar actualizados en lo que respecta a nuevas
tecnologías que ya están a prueba y en producción, de las que casi no se han escrito libros.
Creemos que estas nuevas tecnologías “open source” deben ser incluidas en las materias
integradoras que componen la carrera de Ingeniería Electrónica y que se debe dar mucho empuje a
que los futuros Ingenieros tengan conocimiento en programación, unix y sistemas “Embebidos” ya
que estos componen gran parte de los equipamientos modernos y existe una gran demanda a nivel
nacional e internacional de estos conocimientos, los que a la larga influyen en forma muy positiva
al crecimiento de la industria nacional y a la mejora en el posicionamiento de nuestro país en el
grupo de los países productores de tecnología.
28
ANEXOS
1. FOTOS DE PANTALLAS
A continuación mostramos las imágenes de las pantallas de la central telefónica. La figura 5
muestra la pantalla donde accedemos a la central telefónica IP por medio de un Usuario y una
Contraseña.
Usuario: admin.
Contraseña: password
Fig 5. Pantalla de autenticación de usuario
Una vez que nos hemos logueado, aparece la pantalla principal de la central tal como vemos en la
figura 6
Fig 6. Pantalla general de la central telefónica IP
29
Cuando hacemos clic en el menú “Cuentas – Crear”, aparece la ventana que se muestra en la figura
7
Fig 7. Ventana de creación de cuenta.
30
Otra ventana importante es la que se muestra en la figura 8, que corresponde al menú
configuración
Fig 8. Pantalla de configuración
Por último, en la figura 9, mostramos la pantalla que visualiza el registro o historial de llamadas
en la central, cuando hacemos clic en el menú “llamadas”
Fig 9. Historial de llamadas
31
2. PROTOCOLO SIP
Una breve historia del protocolo SIP
Inicialmente sólo el sistema telefónico tradicional fue el principal medio para transmitir mensajes,
Sin embargo, con el advenimiento de la Internet, se consideró la necesidad se fabricar un sistema
que conecte a personas a lo largo de la red basada en IP. Diferentes comunidades presentaron
diferentes soluciones, pero la solución presentada por IETF (Internet Engineering Task Force) fue
finalmente aceptado como uno más general. Sin embargo, el desarrollo del protocolo SIP en la IETF
no fue un un proceso de un solo paso.
Febrero 1996
Borradores iniciales se produjeron en forma de:
Session Invitation Protocol (SIP) – M.Handley, E.Schooler
Simple Conference Invitation Protocol (SCIP) – H.Schulzrinne
La intención original de SIP fue crear un mecanismo para invitar a gente en gran escala a
conferencias multipunto sobre el Backbone Multicast de Internet (Mbone). En esta etapa, la
telefonía IP en realidad no existía. El primer proyecto se conoce como "draft-ietf-mmusic-sip-00".
Incluía sólo un tipo de solicitud, que fue una petición de llamada. (¿Se pregunta qué está haciendo
la música en SIP? Bueno, es un acrónimo de Multiparty Multimedia Session Control. Las personas
de IETF locos por la música después de todo.)
Diciembre 1996
Una nueva versión de "draft-ietf-mmusic-sip-01" se propuso como una modificación de la SIP-0.
Sin embargo todavía no tenía la forma de SIP, tal como lo conocemos ahora.
Enero 1999
La IETF publicó el proyecto llamado "draft-ietf-mmusic-sip-12", el cual contiene las 6 peticiones
que SIP tiene hoy en día.
Marzo 1999
SIP RFC 2543 publicado como un estándar.
Fue modificado más para llegar a la más moderna versión RFC 3261.
Funciones del protocolo SIP
SIP se limita sólo al inicio, modificación y terminación de sesiones. Sirve a cuatro grandes
propósitos:



SIP permite el establecimiento de la ubicación del usuario (es decir, la traducción de un
nombre de usuario a su actual dirección de red).
SIP ofrece la función de negociación a fin de que todos los participantes en una sesión
pueden ponerse de acuerdo en las características soportadas entre ellos.
SIP es un mecanismo de gestión de llamadas - por ejemplo, añadiendo, disminuyendo, o
transfiriendo participantes.
32

SIP permite cambiar las características de un período de sesiones mientras se encuentra en
progreso.
Todas las otras funciones se realizan con otros protocolos.
Este hecho, significa que SIP no es un protocolo de descripción de sesiones, y que SIP no hace
control de conferencias. SIP no es un protocolo de reserva de recursos y no tiene nada que ver con
la calidad del servicio (QoS). SIP puede trabajar en un marco con otros protocolos para asegurarse
de que estas funciones se realizan - SIP, pero no hacerlo. SIP puede funcionar con SOAP, HTTP,
XML, VXML, WSDL, UDDI, SDP y otros. Todo el mundo tiene un papel que jugar!
Con todo lo dicho, SIP es aún uno de los más importantes protocolos. Mejor aprender acerca de
los componentes SIP.
Componentes del protocolo SIP
Las entidades que interactúan en un escenario SIP son llamados User Agents (UA)
Los User Agents puede operar en dos modos -

User Agent Client (UAC) : Genera y envía las solicitudes a los servidores.
User Agent Server (UAS) : Recibe las solicitudes, procesa estas solicitudes y genera las
respuestas.
Nota: Un solo UA puede funcionar como ambos.
Clientes:
En general, asociamos el concepto de los clientes a los usuarios finales, es decir, las aplicaciones
se ejecutan en los sistemas utilizados por las personas. Puede ser un softphone corriendo en una PC
o un dispositivo de mensajería en el teléfono IP. Éste genera una solicitud cuando intenta llamar a
otra persona a través de la red y envía la petición a un servidor (generalmente un servidor proxy).
Vamos a ir a través del formato de las solicitudes y los servidores proxy en mayor detalle más
adelante.
Servidores:
Los servidores son, en general, parte de la red. Ellos poseen un conjunto predefinido de reglas
para manejar las solicitudes enviadas por los clientes.
Los servidores pueden ser de varios tipos -


Servidor proxy: Estos son el tipo más común de servidor en un entorno SIP. Cuando una
petición se genera, la dirección exacta del destinatario no se sabe de antemano. Por lo tanto,
el cliente envía la petición a un servidor proxy. El servidor en nombre del cliente (como si
dando un proxy para ello) remite la solicitud a otro servidor proxy o el propio receptor.
Redirect Server: Un redirect server redirige el pedido de vuelta al cliente indicando que el
cliente necesita intentar por una ruta diferente para llegar al destinatario. En general, ocurre
cuando un destinatario se ha movido de su posición original ya sea en forma temporal o
permanente.
Registrar: Uno de los principales puestos de trabajo de los servidores es para detectar la
ubicación de un usuario en una red. Para saber la ubicación de los usuarios, éstos tienen que
registrar sus ubicaciones (IP y puerto) en un servidor Registrar. Los usuarios de vez en
cuando actualizan su registro de ubicación (por el envío de un tipo especial de mensaje) a un
servidor Registrar.
33

Location Server: Las direcciones registradas en un Registro se almacenan en un Location
Server.
Ahora que los componentes están listos, tenemos los comandos SIP para hacer que funcionen.
Comandos del procotolo SIP
 INVITE : Invita a un usuario a una llamada

ACK : (Acknowledgement) el acuse de recibo se utiliza para facilitar el intercambio de
mensajes fiables para las invitaciones.

BYE :Finaliza una conexión entre los usuarios

CANCEL :Finaliza una solicitud, o de búsqueda, para un usuario. Se utiliza si un cliente
envía un INVITE y luego cambia su decisión de llamar al destinatario.

OPTIONS :solicita información a un servidor acerca de sus capacidades.

REGISTER :Registra la ubicación actual de un usuario.

INFO : Se utiliza para señalización a mitad de sesiones.
Un ejemplo típico de una sesión SIP
Señalización SIP sigue el paradigma de servidor-cliente, tal como se utiliza ampliamente en la
Internet por protocolos como HTTP o SMTP. La siguiente figura presenta un típico intercambio de
solicitudes y respuestas. Tenga en cuenta que es sólo un caso típico y no incluye todos los casos
posibles.
Antes de la comprensión de los métodos, en primer lugar se debe entender el diagrama. El User1
utiliza su softphone para llegar al teléfono SIP del User2. Servidor1 y Servidor2 ayudan a
configurar las sesiones en nombre de los usuarios. Este acuerdo común de los proxies y los usuarios
finales se llama "SIP trapezoidal", como se muestra por la línea punteada. Los mensajes aparecen
verticalmente en el orden en que aparecen, es decir, el mensaje en la parte superior (INVITE M1) es
primero seguido por otros. La dirección de las flechas muestra el remitente y el destinatario de cada
mensaje. Cada mensaje contiene un número de 3-dígitos seguido de un nombre y cada uno tiene la
etiqueta 'M' y un número de serie. El número de 3-dígitos es el código numérico de los mensajes
asociados comprendido fácilmente por las máquinas. Los usuarios humanos utilizan el nombre para
identificar el mensaje.
34
Fig 1.
La operación comienza con el User1 enviando una solicitud de INVITE al User2. Pero User1 no
conoce la ubicación exacta de User2 en la red IP, así que pasa la solicitud a servidor1. El Servidor1
en nombre de User1 envía una solicitud de INVITE a User2 al server2. Se envía una respuesta
TRYING a User1 informando que está tratando de llegar a User2. La respuesta podría haber sido
diferente, pero vamos a discutir los otros tipos de respuestas más tarde. Si se está preguntando cómo
servidor1 sabe que tiene que enviar la solicitud a server2, lo veremos más adelante cuando veamos
el proceso de registración.
Al recibir un INVITE M2 de server1, server2 funciona de manera similar como servidor1. Éste
reenvía una petición de INVITE a User2 (Nota: Aquí server2 sabe la ubicación de User2. Si no
supiera la ubicación, reenviaría la petición a otro servidor proxy. Por lo tanto, una petición de
INVITE pueden viajar a través de varios servidores proxy antes de llegar al destinatario ). Después
de la transmisión del INVITE M3, server2 envía una respuesta TRYING al servidor1.
El teléfono SIP, en la recepción de la petición INVITE, comienza a sonar (ring) informando al
User2 que la petición de llamada ha llegado. Se envía una señal de respuesta RINGING al server2
que llega a usuario1 a través de servidor1. Por lo tanto, el User1 recibe una confirmación que el
User2 ha recibido la solicitud de INVITE.
User2 en este momento tiene la opción de aceptar o rechazar la llamada. Supongamos que decide
aceptarla. Tan pronto como se acepta la llamada, una respuesta 200 OK es enviada por el teléfono al
server2. Recordando la ruta del INVITE llega al usuario1. El softphone del User1 envía un mensaje
de ACK para confirmar la configuración de la lamada.
l
Este 3-way-handshaking
(INVITE+OK+ACK) es usado para el inicio de una llamada fiable. Tenga en cuenta que el mensaje
de ACK no está utilizando los proxies para llegar a User2 ya que User1 por ahora sabe la ubicación
exacta de User2.
Una vez que la conexión ha sido establecida, la “media” fluye entre los dos extremos. El tráfico
media es controlado a través de protocolos diferentes a SIP por ejemplo RTP (Realtime
Transmission Protocol).
Cuando una de las partes en la sesión decide desconectar, (User2 en este caso) envía un mensaje
BYE a la otra parte. La otra parte envía un mensaje de 200 OK para confirmar la terminación de la
sesión.
35
Formato de Solicitudes SIP
Ya hemos visto que las solicitudes son enviadas por los clientes a servidores. Ahora vamos a
discutir lo que realmente contienen las solicitudes. El siguiente es el formato de una solicitud
INVITE enviada por User1.
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP pc33.server1.com;branch=z9hG4bK776asdhds Max-Forwards: 70
To: user2 <sip:[email protected]>
From: user1 <sip:[email protected]>;tag=1928301774
Call-ID: [email protected]
CSeq: 314159 INVITE
Contact: <sip:[email protected]>
Content-Type: application/sdp
Content-Length: 142
---- User1 Message Body Not Shown ---La primera línea del texto-mensaje codificado se llama Request Line. Identifica que el mensaje es
una petición.
Request-Line
Method SP Request-URI SP SIP-Version CRLF
[SP = single-space & CRLF=Carriage Return + Line Feed
Aquí el method es INVITE, request uri-es "[email protected]" y SIP versión 2.
Las siguientes líneas son un conjunto de campos de cabecera.

Via:
Contiene la dirección local de User1, es decir, pc33.server1.com donde está a la espera de
las respuestas por venir.

Max-Forward:
Se utiliza para limitar el número de saltos que esta petición se puede tomar antes de llegar al
destinatario. Es decrementado por uno en cada salto ya que es necesario evitar que la
solicitud viaje en forma indefinida en caso de que sea atrapada en un bucle.

To:
Contiene un nombre para mostrar "User2" y un SIP o SIPS URI <[email protected]>

From:
También contiene un nombre para mostrar "User1" y un SIP o ISPS URI
<[email protected]>. También contiene una etiqueta que es una secuencia pseudoaleatoria insertada por la aplicación SIP que funciona como un identificador de la persona
que llama en el cuadro de diálogo.

Call-ID:
Se trata de un identificador único global de la llamada generada como la combinación de
una cadena pseudo-aleatorio y el uso de la direc
ción IP del softphone
El Call-ID es único para una llamada. Una llamada puede contener varios diálogos. Cada diálogo se
36
identifican de forma única por una combinación de From, To and Call-ID.

CSeq:
Contiene un entero y un nombre de método. Cuando una transacción se inicia, el primer
mensaje es Cseq aleatorio. Después de esto, se incrementa por uno con cada nuevo mensaje.
It is used to detect non-delivery of a message or out-of-order delivery of messages. Se utiliza
para detectar la no entrega de un mensaje o entrega de los mensajes fuera de orden.

Contact:
Contiene un SIP o SIPS URI que es una ruta directa a User1. Contiene un nombre de
usuario y un nombre de dominio completo (FQDN). También puede tener una dirección IP.
El campo Via campo se utiliza para enviar la respuesta a la solicitud. El Campo contact se
utiliza para enviar las solicitudes futuras. Esa es la razón por la que la respuesta 200 OK de
User2 va a User1 a través de los proxies. Pero cuando User2 genera una petición BYE (una
nueva solicitud y no una respuesta a INVITE), ésta va directamente a User1 sin pasar por
los proxies.

Content-Type:
Contiene una descripción del cuerpo del mensaje (no se muestra).

Content-Length:
Se trata de un octeto (byte) que es la cuenta del tamaño del cuerpo del mensaje.
La cabecera puede contener otros campos de cabecera también. Sin embargo esos campos son
opcionales. Tenga en cuenta que el cuerpo del mensaje no se muestra aquí. El cuerpo se utiliza para
transmitir información acerca de la sesion de media escrita en la sesión Session Description
Protocol (SDP).
Formato de Respuesta de mensaje SIP
Así es como será la respuesta del SIP User2:
SIP/2.0 200 OK
Via: SIP/2.0/UDP site4.server2.com;branch=z9hG4bKnashds8;received=192.0.2.3
Via: SIP/2.0/UDP site3.server1.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2
Via: SIP/2.0/UDP pc33.server1.com;branch=z9hG4bK776asdhds;received=192.0.2.1
To: user2 <sip:[email protected]>;tag=a6c85cf
From: user1 <sip:[email protected]>;tag=1928301774
Call-ID: [email protected]
CSeq: 314159 INVITE
Contact: <sip:[email protected]>
Content-Type: application/sdp
Content-Length: 131
---- User2 Message Body Not Shown ----
Status Line
La primera línea en una respuesta se llama Status Code
SIP-Version SP Status-Code SP Reason-Phrase CRLF
37
[SP = single-space & CRLF=Carriage Return + Line Feed ]
Aquí la versión SIP es 2.0, el Status Code es 200 y Reason Phrase es OK.
Los campos de cabecera que siguen la línea de estado son similares a las de una solicitud. Sólo
mencionaremos las diferencias

Via:
Hay más de un campo Via. Esto se debe a que cada uno de los elementos a través de los
cuales las peticiones de INVITE han pasado ha añadido su identidad en el campo Via. Tres
campos son añadidos por softphone de User1, server1 el primer servidor proxy y el segundo
proxy server2. La respuesta reconstruye el camino de la INVITE utilizando los campos Via.
En su camino de regreso, cada uno de los elementos elimina el campo Via correspondiente
antes de transmitirla de vuelta a la persona que llama.

To:
Tenga en cuenta que el campo ahora contiene una etiqueta. Esta etiqueta se utiliza para
representar al destinatario de la llamada en un diálogo.

Contact:
Contiene la dirección exacta de User2. Por lo tanto User1 no tiene la necesidad de utilizar
servidores proxy para encontrar a User2 en el futuro.
Es una respuesta 2xx. Sin embargo las respuestas pueden ser differnet en función de situaciones
particulares.
Tipos de respuesta SIP
El primer dígito del Status-Code define la categoría de respuesta. Así, cualquier respuesta de entre
100 y 199 se denomina como un respuesta "1xx" y así se hace para cualquier otro tipo. SIP/2.0
permite seis tipos de respuesta y son similares a las de HTTP.






1xx: Provisional -- solicitud recibida, continúa el proceso de solicitud.
2xx: Success -- la acción se ha recibido, comprendido y aceptado.
3xx: Redirection -- se necesitan tomar ciertas acciones para completar la solicitud.
4xx: Client Error -- la solicitud contiene sintaxis mala o no puede cumplirse en este
servidor;
5xx: Server Error -- el servidor no puede cumplir con una solicitud aparentemente válida
6xx: Global Failure -- la solicitud no puede cumplirse en cualquier servidor.
Si uno se recibe una respuesta con un Status Code de la forma yxx que no es comprendido por la
parte receptora, ésta trata la respuesta como una respuesta y00 es decir, si un cliente recibe una
respuesta desconocida 345, la va a tratar como una respuesta 300. Un desconocido 1xx es tratado
como 183 (Session in Progress). Por lo tanto, cada UA debe saber cómo reaccionar ante 100,183,
200, 300, 400, 500 y 600.
En SIP se habla de las llamadas, diálogos, transacciones y mensajes. Lo siguiente página se aclara
su interrelación.
Relación entre llamada, diálogo, transacción y mensajes
Los mensajes son los distintos cuerpos de texto intercambiados entre un servidor y un cliente.
38
Puede haber dos tipos de mensajes. : solicitudes y respuestas.
Transacción se produce entre un cliente y un servidor e incluye todos los mensajes desde la
primera solicitud enviada desde el cliente al servidor, hasta una respuesta final (no 1xx) enviada
desde el servidor al cliente. Si la solicitudes un INVITE y la respuesta final no es un 2xx, la
transacción también incluye un ACK a la respuesta. El ACK para una respuesta 2xx a una solicitud
INVITE es una transacción por separado.
Dialogo es una relación SIP peer-to-peer entre dos UAS que persiste durante algún tiempo. Un
diálogo es identificado por un call-ID, una etiqueta local y una etiqueta remota. Un diálogo solía ser
mencionado como una “pierna de llamada”.
Una llamada comprende todos los diálogos involucrados. Es lo mismo que una sesión.
La siguiente figura explica la relación en forma más clara.
Fig 2. (RINGING es una respuesta 1xx y OK es una respuesta 2xx)
Una llamada puede tener conexiones a un número de destinatarios a la vez formando una serie de
diálogos. Todos estos diálogos hacen una sola llamada.
39
REGISTRACIÓN EN SIP
Viendo una típica sesión SIP vemos que la persona que llama no sabe la dirección del destinatario
inicialmente. Los servidores proxy hacen el trabajo de averiguar la ubicación exacta del
destinatario. Lo que realmente sucede es que cada usuario registra su ubicación actual en un
servidor de registro (REGISTRAR). La aplicación envía un mensaje llamado REGISTER
informando al servidor su ubicación actual. El Registrar almacena esta relación (entre el usuario y
su dirección actual) en un “location server” y éste es utilizado por otros servidores proxy para
localizar al usuario.
Fig 3.
El usuario yy utiliza la IP 195.31.65.152 como su ubicación actual y la registra con el servidor.
Esto realmente ayuda a la movilidad de los usuarios. Digamos que hay una aplicación de
mensajería, y que se puede acceder desde diferentes computadoras. Tan pronto como entramos en
una sesión con un nombre de usuario, la aplicación REGISTER (Registra)el nombre de usuario con
la IP de ese equipo. El campo 'Expire' refleja la duración para la cual el registro será válido, por lo
tanto los usuarios deben refrescar sus registraciones de vez en cuando.
Tenga en cuenta que la diferencia entre un servidor proxy y un registro o un servidor de ubicación
a menudo es lógica. Físicamente pueden ser situados en la misma máquina.
40
3. GUÍA DE INSTALACIÓN DE FreeBSD
Como primer paso para la instalación debemos bajar la imagen de CD del instalador de FreeBSD
desde:
ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/ISO-IMAGES/7.1/
La imagen que bajemos puede ser la que permite bootear solamente y que no posea los archivos
de instalación (aprox 40MB de tamaño), lo permite que la descarga sea bien rápida y que podemos
empezar a trabajar casi al instante, pero por otro lado, al momento de instalar el sistema operativo
deberemos poseer conexión a internet para que el instalador descargue dichos archivos. Por todo
esto recomendamos bajar el disco 1 de instalación, ya que éste poseen todo lo necesario para
instalar un entorno de desarrollo.
Luego de bajar la imagen debemos copiar la misma a un CD, tarea que puede realizarse con el
comando cdrecord desde Linux o sino usando el Nero Burning Room desde Windows.
Ya con la imagen creada, debemos configurar la PC para poder iniciar la instalación desde el CD,
esto último lo realizamos desde la BIOS. Luego de este último paso procedemos a iniciar la
instalación del sistema operativo "booteando" el CD de instalación.
La primera imagen que nos aparecerá será la siguiente:
Fig 1. Pantalla de inicio en la instalación de FreeBSD
Debemos elegir la opción 1, que es la por defecto. Luego nos irán apareciendo menúes con las
opciones de instalación que detallamos paso a paso:
41
Fig 2. Opciones de Instalación: País
En este primer menú elegimos el país donde nos encontramos, lo que nos deja configurar la
distribución del teclado y demás configuraciones regionales.
Fig 3. Opciones de instalación: Modo de Instalación
42
Este es el menú principal de la instalación, y nos deja elegir tanto el modo de instalación como
reparar una instalación existente, particionar discos, hacer una actualización del sistema y muchas
cosas más.
Fig 4. Opciones de instalación, tipo de instalación.
Nosotros elegiremos Standard, que nos dejará instalar el sistema con un simple ayudante que nos
guiará paso a paso.
Fig 5. Opciones de Instalación: Selección de unidad de instalación
43
El primer paso luego de seleccionar Standard es elegir el disco sobre el que trabajaremos en la
instalación.
Fig 6. Opciones de instalación: configuración de particiones
Luego nos mostrará las particiones existentes y el tipo de éstas. Nosotros deberemos crear una
partición primaria (sólo podemos tener 4 en total) y en caso de no tener espacio podremos eliminar
alguna partición existente que no usemos.
Fig 7. Opciones de instalación: configuración de particiones
44
Luego de hacer lugar eliminando particiones que no usamos (D = Delete Slice) procedemos a
crear una partición del tipo FreeBSD (tipo 165) con el tamaño adecuado (recomendamos >= 10GB
para entornos de desarrollo). Especificando 20G por ejemplo, crearemos una partición de 20GB.
Luego presionando la tecla Q salimos del menú y pasamos al siguiente.
Fig 8. Opciones de instalación: sector de arranque.
En este menú elegimos "Install the FreeBSD Boot Manager" en caso de tener otros sistemas
operativos instalados en el mismo sistema. En caso que vayamos a tener sólo FreeBSD corriendo,
elegimos Install a estándar MBR. Si ya tuviéramos otro boor loader, elegimos la opción 3, que deja
el MBR sin modificar.
45
Fig 9. Opciones de instalación: selección de unidad de instalación
Seleccionamos el disco donde se instalará el Boot Loader.
Fig 10. Opciones de instalación: Configuración de particiones
46
Y luego entraremos al menú donde deberemos crear sub particiones dentro de la partición
FreeBSD ya creada, con sus respectivos puntos de montaje. Lo mas simple es decirle al instalador
que las cree automáticamente presionando la A, pero como nuestro entorno es de desarrollo y no
necesitamos crear particiones para los archivos de usuarios ya que nuestro sistema no trabaja como
servidor, lo que nos puede convenir es crear sólo 2 particiones, una del tipo "swap" que tenga el
doble del tamaño de la memoria RAM y otra del tipo "file system" que ocupe el espacio sobrante y
que tenga punto de montaje en el directorio raíz (/)
Fig 11. Opciones de Instalación: configuración de particiones
Otro de los casos es crear las particiones a mano como vemos en el gráfico, donde hemos creado
una partición raíz (/) de 512MB, una partición swap de 512MB, una partición /var de 512MB y una
/usr de mas de 6GB. Tener particiones limitadas en tamaño nos ayuda a que si por ejemplo los logs,
que se almacenan en /var/log crezcan son control, no llenen la partición principal (/) donde está
instalado el kernel y demás comandos esenciales para el funcionamiento del SO.
47
Fig 12. Opciones de instalación: componentes a instalar.
En el siguiente paso deberemos elegir el tipo de distribución a instalar. Como nosotros
necesitamos crear un sistema usando el código fuente del kernel y aplicaciones, deberemos elegir
Developer o X-Developer (incluye X Windows). Luego se nos presentará un menú donde elegimos
instalar los Ports, que son scripts de instalaciones remotas automáticas.
User Confirmation Requested
Would you like to install the FreeBSD ports collection?
This will give you ready access to over 19,000 ported software packages, at a cost of around
445 MB of disk space when "clean" and possibly much more than that if a lot of the distribution
tarballs are loaded (unless you have the extra CDs from a FreeBSD CD/DVD distribution
available and can mount it on /cdrom, in which case this is far less of a problem).
The Ports Collection is a ery
v
valuable resource and well worth having
on your /usr partition, so it is advisable to say Yes to this option..
For more information on the Ports Collection & the latest ports,
visit:
http://www.FreeBSD.org/ports
[ Yes ]
No
48
Fig 13. Opciones de instalación: Ubicación del archivo de instalación.
Ahora elegimos desde dónde queremos instalar FreeBSD. SI bajamos el disco1 de instalación
elegimos CD/DVD. Si bajamos el disco bootonly, deberemos instalar desde ftp u otro medio remoto
como ser http.
User Confirmation Requested
Last Chance! Are you SURE you want to continue the installation?
If you're running this on a disk with data you wish to save then WE
STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before proceeding!
We can take no responsibility for lost disk contents!
[ Yes ] No
Luego confirmamos que inicie la instalación y esperamos que termine.
Message
Congratulations! You now have FreeBSD installed on your system.
We will now move on to the final configuration questions.
For any option you do not wish to configure, simply select No.
If you wish to re-enter this utility after the system is up, you may
do so by typing: /usr/sbin/sysinstall.
49
[ OK ]
[ Press enter or space ]
Luego de terminar la instalación el instalador nos irá pidiendo que configuremos diferentes
servicios.
User Confirmation Requested
Would you like to configure any Ethernet or SLIP/PPP network devices?
[ Yes ] No
Fig 14. Opciones de instalación: configuración de la placa de red.
Configuramos la conexión ethernet para poder tener conectividad a Internet.
User Confirmation Requested
Do you want to try IPv6 configuration of the interface?
Yes [ No ]
50
User Confirmation Requested
Do you want to try DHCP configuration of the interface?
Yes [ No ]
Fig 15. Opciones de instalación: configuración de IP.
Lo más simple es usar DHCP para no tener que configurar la IP en forma manual.
User Confirmation Requested
Do you want this machine to function as a network gateway?
[ Yes ]
No
Elegimos que no deseamos que el SO trabaje como gateway (no hacemos re router de red)
User Confirmation Requested
Do you want to configure inetd and the network services that it provides?
Yes [ No ]
No aceptamos configurar inetd (Internet Daemon) ya que nuestra pc no será un server.
51
User Confirmation Requested
Would you like to enable SSH login?
Yes
[ No ]
Aceptamos instalar el server SSH para poder conectarnos remotamente a nuestra pc (siempre es
bueno el acceso remoto)
User Confirmation Requested
Do you want to have anonymous FTP access to this machine?
Yes [ No ]
No instalamos acceso remoto a ftp (no hace falta)
User Confirmation Requested
Do you want to configure this machine as an NFS server?
Yes [ No ]
Tampoco NFS server (Network File System)
User Confirmation Requested
Do you want to configure this machine as an NFS client?
Yes [ No ]
Tampoco NFS Client
User Confirmation Requested
Would you like to customize your system console settings?
[ Yes ] No
No necesitamos configurar los seteos del sistema
User Confirmation Requested
Would you like to set this machine's time zone now?
[ Yes ] No
52
Fig 16. Opciones de instalación: configuración del uso horario.
User Confirmation Requested
Would you like to enable Linux binary compatibility?
[ Yes ] No
No necesitamos compatibilidad Linux, ya que compilaremos todo desde código fuente (no
usaremos binarios precompilados para linux)
User Confirmation Requested
Does this system have a PS/2, serial, or bus mouse?
[ Yes ] No
User Confirmation Requested
Podemos configurar si tenemos algún Mouse conectado.
The FreeBSD package collection is a collection of hundreds of
ready-to-run applications, from text editors to games to WEB servers
and more. Would you like to browse the collection now?
[ Yes ] No
No necesitamos instalar programas precompilados por ahora
User Confirmation Requested
Would you like to add any initial user accounts to the system? Adding
53
at least one account for yourself at this stage is suggested since
working as the "root" user is dangerous (it is easy to do things which
adversely affect the entire system).
[ Yes ] No
Aquí podemos agregar algún user al sistema, si no lo hacemos, usaremos root, que es el
administrador del sistema.
Message
Now you must set the system manager's password.
This is the password you'll use to log in as "root".
[ OK ]
[ Press enter or space ]
New password:
Retype new password :
Aquí creamos una contraseña para root
User Confirmation Requested
Visit the general configuration menu for a chance to set any last options?
Yes [ No ]
Como ya no tenemos más nada que instalar, optamos por salir tal como se ve en la figura 17
54
Fig 17. Fin de la instalación
Aparece la siguiente pregunta:
Are you sure you wish to exit?
Pulsamos en “Yes”
[ Yes ] No
El sistema se reiniciará y nos pide que estemos seguros de haber sacado cualquier CD/DVD de la
lectora, de esta manera se evi
ta que arranque de nuevo el in
stalador del SO.
Luego de arrancar el sistema nos va a pedir el username y contraseña, que son root y la clave que
hemos creado con anterioridad. Con estos pasos ya estaremos listos para
empezar con el desarrollo de nuestro sistema embebido.
55
4. LENGUAJE XML
Historia
XML proviene de un lenguaje inventado por IBM en los años setenta, llamado GML (Generalized
Markup Language), que surgió por la necesidad que tenía la empresa de almacenar grandes
cantidades de información. Este lenguaje gustó a la ISO, por lo que en 1986 trabajaron para
normalizarlo, creando SGML (Standard Generalized Markup Language), capaz de adaptarse a un
gran abanico de problemas. A partir de él se han creado otros sistemas para almacenar información.
En el año 1989 Tim Berners Lee creó la web, y junto con ella el lenguaje HTML. Este lenguaje se
definió en el marco de SGML y fue de lejos la aplicación más conocida de este estándar. Los
navegadores web sin embargo siempre han puesto pocas exigencias al código HTML que
interpretan y así las páginas web son caóticas y no cumplen con la sintaxis. Estas páginas web
dependen fuertemente de una forma específica de lidiar con los errores y las ambigüedades, lo que
hace a las páginas más frágiles y a los navegadores más complejos.
Otra limitación de SGML es que cada documento pertenece a un vocabulario fijo, establecido por el
DTD. No se pueden combinar elementos de diferentes vocabularios. Asimismo es imposible para un
intérprete (por ejemplo un navegador) analizar el documento sin tener conocimiento de su
gramática (del DTD). Por ejemplo, el navegador sabe que antes de una etiqueta <div> debe haberse
cerrado cualquier <p> previamente abierto. Los navegadores resolvieron esto incluyendo lógica
ad-hoc para el HTML, en vez de incluir un analizador genérico. Ambas opciones, de todos modos,
son muy complejas para los navegadores. Se buscó entonces definir un subconjunto del SGML que
permita:
 Mezclar elementos de diferentes lenguajes. Es decir que los lenguajes sean extensibles.
 La creación de analizadores simples, sin ninguna lógica especial para cada lenguaje.
 Empezar de cero y hacer hincapié en que no se acepte nunca un documento con errores de
sintaxis.
Para hacer esto XML deja de lado muchas características de SGML que estaban pensadas para
facilitar la escritura manual de documentos. XML en cambio está orientado a hacer las cosas más
sencillas para los programas automáticos que necesiten interpretar el documento.
Ventajas del XML
 Es extensible: Después de diseñado y puesto en producción, es posible extender XML con
la adición de nuevas etiquetas, de modo que se pueda continuar utilizando sin complicación
alguna.
 El analizador es un componente estándar, no es necesario crear un analizador específico
para cada versión de lenguaje XML. Esto posibilita el empleo de cualquiera de los
analizadores disponibles. De esta manera se evitan bugs y se acelera el desarrollo de
aplicaciones.
 Si un tercero decide usar un documento creado en XML, es sencillo entender su estructura y
procesarla. Mejora la compatibilidad entre aplicaciones.
Estructura de un documento XML
La tecnología XML busca dar solución al problema de expresar información estructurada de la
56
manera más abstracta y reutilizable posible. Que la información sea estructurada quiere decir que se
compone de partes bien definidas, y que esas partes se componen a su vez de otras partes. Entonces
se tiene un árbol de pedazos de información. Ejemplos son un tema musical, que se compone de
compases, que están formados a su vez por notas. Estas partes se llaman elementos, y se las señala
mediante etiquetas.
Una etiqueta consiste en una marca hecha en el documento, que señala una porción de éste como un
elemento. Un pedazo de información con un sentido claro y definido. Las etiquetas tienen la forma
<nombre>, donde nombre es el nombre del elemento que se está señalando.
A continuación se muestra un ejemplo para entender la estructura de un documento XML:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE Edit_Mensaje SYSTEM "Lista_datos_mensaje.dtd"
[<!ELEMENT Edit_Mensaje (Mensaje)*>]>
<Edit_Mensaje>
<Mensaje>
<Remitente>
<Nombre>Nombre del remitente</Nombre>
<Mail> Correo del remitente </Mail>
</Remitente>
<Destinatario>
<Nombre>Nombre del destinatario</Nombre>
<Mail>Correo del destinatario</Mail>
</Destinatario>
<Texto>
<Asunto>
Este es mi documento con
no contiene atributos ni
</Asunto>
<Parrafo>
Este es mi documento con
no contiene atributos ni
</Parrafo>
una estructura muy sencilla
entidades....
una estructura muy sencilla
entidades....
</Texto>
</Mensaje>
</Edit_Mensaje>
Aquí está el ejemplo de código del DTD del documento "Edit_Mensaje":
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- Este es el DTD de Edit_Mensaje -->
<!ELEMENT Mensaje (Remitente,
<!ELEMENT Remitente
<!ELEMENT
<!ELEMENT
Destinatario, Texto)*>
(Nombre, Mail)>
Nombre (#PCDATA)>
Mail
(#PCDATA)>
<!ELEMENT Destinatario (Nombre, Mail)>
<!ELEMENT Nombre (#PCDATA)>
<!ELEMENT Mail
(#PCDATA)>
57
<!ELEMENT Texto (Parrafo)>
<!ELEMENT Asunto (#PCDATA)>
<!ELEMENT Parrafo (#PCDATA)>
Documentos XML bien formados
Los documentos denominados como "bien formados" (del inglés well formed) son aquellos que
cumplen con todas las definiciones básicas de formato y pueden, por lo tanto, analizarse
correctamente por cualquier analizador sintáctico (parser) que cumpla con la norma. Se separa esto
del concepto de validez que se explica más adelante.

Los documentos han de seguir una estructura estrictamente jerárquica con lo que respecta
a las etiquetas que delimitan sus elementos. Una etiqueta debe estar correctamente incluida
en otra, es decir, las etiquetas deben estar correctamente anidadas. Los elementos con
contenido deben estar correctamente cerrados.

Los documentos XML sólo permiten un elemento raíz del que todos los demás sean parte, es
decir, solo pueden tener un elemento inicial.

Los valores atributos en XML siempre deben estar encerrados entre comillas simples o
dobles.

El XML es sensible a mayúsculas y minúsculas. Existe un conjunto de caracteres llamados
espacios en blanco (espacios, tabuladores, retornos de carro, saltos de línea) que los
procesadores XML tratan de forma diferente en el marcado XML.

Es necesario asignar nombres a las estructuras, tipos de elementos, entidades, elementos
particulares, etc. En XML los nombres tienen alguna característica en común.
Las construcciones como etiquetas, referencias de entidad y declaraciones se denominan marcas;
son partes del documento que el procesador XML espera entender. El resto del documento entre
marcas son los datos "entendibles" por las personas. Partes de un documento XML.
Un documento XML está formado por el prólogo y por el cuerpo del documento.
Prólogo
Aunque no es obligatorio, los documentos XML pueden empezar con unas líneas que describen la
versión XML, el tipo de documento y otras cosas.
El prólogo contiene:

Una declaración XML. Es la sentencia que declara al documento como un documento
XML.

Una declaración de tipo de documento. Enlaza el documento con su DTD (definición de
tipo de documento), o el DTD puede estar incluido en la propia declaración o ambas
cosas al mismo tiempo.

Uno o más comentarios e instrucciones de procesamiento.
Cuerpo
A diferencia del prólogo, el cuerpo no es opcional en un documento XML, el cuerpo debe contener
un y solo un elemento raíz, característica indispensable también para que el documento esté bien
58
formado.
Elementos
Los elementos XML pueden tener contenido (más elementos, caracteres o ambos), o bien ser
elementos vacíos.
Atributos
Los elementos pueden tener atributos, que son una manera de incorporar características o
propiedades a los elementos de un documento. Deben ir entre comillas.
Entidades predefinidas
Entidades para representar caracteres especiales para que, de esta forma, no sean interpretados
como marcado en el procesador XML.
Secciones CDATA
Es una construcción en XML para especificar datos utilizando cualquier carácter sin que se
interprete como marcado XML. Solo se utiliza en los atributos. No confundir con 2(#PCDATA) que
es para los elementos. Permite que caracteres especiales no rompan la estructura. Ej:
<![CDATA[
contenido especial: áéíóúñ& ]]>
Comentarios
Comentarios a modo informativo para el programador que han de ser ignorados por el procesador.
Los comentarios en XML tienen el siguiente formato:
<!--- Esto es un comentario --->
<!-- Otro comentario -->
Validez
Que un documento esté "bien formado" solamente se refiere a su estructura sintáctica básica, es
decir, que se componga de elementos, atributos y comentarios como XML especifica que se
escriban. Ahora bien, cada aplicación de XML, es decir, cada lenguaje definido con esta tecnología,
necesitará especificar cuál es exactamente la relación que debe verificarse entre los distintos
elementos presentes en el documento.
Esta relación entre elementos se especifica en un documento externo o definición (expresada
como DTD (Document Type Definition = Definición de Tipo de Documento) o comoXSchema).
Crear una definición equivale a crear un nuevo lenguaje de marcado, para una aplicación específica.
Document type definition (DTD)
La DTD define los tipos de elementos, atributos y entidades permitidas, y puede expresar algunas
limitaciones para combinarlos. Los documentos XML que se ajustan a su DTD son denominados
válidos. Los elementos deben ajustarse a un tipo de documento declarado en una DTD para que el
documento sea considerado como válido.
Modelos de contenido
Un modelo de contenido es un patrón que establece los subelementos aceptados, y el orden en
que se aceptan.
59
Declaraciones de lista de atributos
Los atributos se usan para añadir información adicional a los elementos de un documento.
Tipos de atributos



AtributosCDATA y NMTOKEN
Atributos enumerados y notaciones
Atributos ID y IDREF
Declaración de entidades
XML hace referencia a objetos que no deben ser analizados sintácticamente según las reglas
XML, mediante el uso de entidades. Las entidades pueden ser:
 Internas o externas
 Analizadas o no analizadas
 Generales o parametrizadas
Espacios de nombres
Los espacion de nombres XML permiten separar semánticamente los elementos que forman un
documento XML.
XML Schemas (XSD)
Un Schema es algo similar a un DTD. Define qué elementos puede contener un documento XML,
cómo están organizados y qué atributos y de qué tipo pueden tener sus elementos.
Ventajas de los Schemas frente a los DTDs



Usan sintaxis de XML, al contrario que los DTDs.
Permiten especificar los tipos de datos.
Son extensibles.
Herramientas para trabajar con documentos XML
De hecho cualquier procesador de texto, que sea capaz de producir archivos txt es capaz de
generar XML, aunque en los entornos de desarrollo comoEclipse o Visual Studio, se facilita, ya que
reconoce los formatos y ayuda a generar un XML bien formado.
Lenguajes creados usando XML
Extensible Stylesheet Language (XSL)
EL Lenguaje de Hoja de Estilo Extensible (eXtensible Stylesheet Language, XLS) es una familia
de lenguajes que permiten describir como los archivos codificados en xml serán formateados (para
mostrarlos) o transformados. Hay tres lenguajes en esta familia: XSL Transformations (XSLT), XSL
Formatting Objects (XSL-FO)y XML Path Language.
Lenguaje de enlace XML (XLINK)
Xlink es una aplicación XML que intenta superar las limitaciones que tienen los enlaces de
hipertexto en HTML. Es una especificación que todavía está en desarrollo.
60
5. ADAPTADOR ANALÓGICO SISCO LINKSYS PAP2
http://www.linksys.com/servlet/Satellite?childpagename=US%2FLayout&packedargs=c%3DL_Pro
duct_C2%26cid%3D1117044308483%26site%3DUS&pagename=Linksys%2FCommon%2FVisito
rWrapper
6. ADVANTECH PCM 5820
Fig 1. SBC (Single Board Computer)
61
Fig 2. SBC vista lado TOP
Fig 3. SBC vista lado bottom
62
7. LISTADOS DE PROGRAMAS
sip.xml
<?xml version="1.0" ?>
<configuracion>
<sip_general>
<param1>[general]</param1>
<param2>context=default</param2>
<param3>bindaddr=0.0.0.0</param3>
<param4>srvlookup=yes</param4>
<param5>disallow=all</param5>
<param6>allow=alaw</param6>
<param7>allow=ulaw</param7>
<param8>allow=gsm</param8>
<param9>externip=tecnicas3.servehttp.com</param9>
<param10>localnet=10.0.0.0/255.255.255.0</param10>
<param11>register => tecnicas3:[email protected]</param11>
</sip_general>
<sip_provider>
<param1>[provider]</param1>
<param2>type=peer</param2>
<param3>host=sip1.voipbuster.com</param3>
<param4>username=tecnicas3</param4>
<param5>fromuser=tecnicas3</param5>
<param6>secret=xxxxxxx</param6>
</sip_provider>
<sip_user id="200">
<username>200</username>
<secret>200</secret>
<callerid>200</callerid>
<type>friend</type>
<host>dynamic</host>
<context>sip_users</context>
<dtmfmode>rfc2833</dtmfmode>
<insecure>port</insecure>
<canreinvite>yes</canreinvite>
<nat>yes</nat>
<mailbox>200</mailbox>
</sip_user>
</configuracion>
63
voicemail.xml
<?xml version="1.0" ?>
<configuracion>
<vm_general>
<param1>[general]</param1>
<param2>format=wav49|gsm|wav</param2>
<param3>serveremail=IPPBX</param3>
<param4>attach=yes</param4>
<param5>skipms=3000</param5>
<param6>maxsilence=10</param6>
<param7>silencethreshold=128</param7>
<param8>maxlogins=3</param8>
<param9>emaildateformat=%A, %B %d, %Y at %r</param9>
<param10>sendvoicemail=yes</param10>
<param11>[default]</param11>
</vm_general>
<vm_user id="100">
<username>100</username>
<secret>100</secret>
<name>Juan</name>
<email>[email protected]</email>
</vm_user>
Index.html
<html>
<body>
<style>
form {
width: 50%;
margin: auto;
text-align: left; }
</style>
<form action="login.php" method="post">
<H3>IP PBX login</H3>
<p>Username: <input type="text" name="username" /></p>
<p>Password :<input type="password" name="password" /></p>
<p><input type="submit" value="Login" /></p>
</form>
</body>
</html>
Index_error.html
<html>
<body>
<style>
form {
width: 50%;
64
margin: auto;
text-align: left; }
</style>
<form action="login.php" method="post">
<H3>IP PBX login</H3>
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="Login" /></p><br />
<H4>El nombre de usuario o el password son incorrectos!</H4>
</form>
</body>
</html>
login.php
<?
session_start();
$username = $_POST["username"];
$password = $_POST["password"];
$e = ERROR;
if ( $password == "password" && $username == "admin" )
{
$e = OK;
}
else
$e = ERROR;
if
{
($e == OK)
$_SESSION['logged'] = 1;
$url = "ippbx.php";
}
else
{
session_destroy();
$url = "index_error.html";
}
header("location:$url");
?>
config/sidebar.inc
<style>
form {
width: 50%;
margin: 5%;
text-align: right; }
div {
width: 20%;
height: 500%;
float:left;
}
</style>
<div>
65
<img src = "images/telefono.jpeg"><br/><br />
<a href = "ippbx.php?page=create_account"<img src="images/ccrear.png"></a><br>
<a href = "ippbx.php?page=edit_account"<img src="images/ceditar.png"></a><br>
<a href = "ippbx.php?page=delete_account"<img src="images/cborrar.png"></a><br>
<a href = "ippbx.php?page=create_voicemail"<img src="images/vcrear.png"></a><br>
<a href = "ippbx.php?page=edit_voicemail"<img src="images/veditar.png"></a><br>
<a href = "ippbx.php?page=delete_voicemail"<img
src="images/vborrar.png"></a><br>
<a href = "ippbx.php?page=list_calls"<img src="images/llamadas.png"></a><br>
<a href = "ippbx.php?page=edit_config"<img
src="images/configuracion.png"></a><br>
<a href = "ippbx.php?page=apply_changes"<img src="images/aplicar.png"></a><br>
<a href = "ippbx.php?page=logout"<img src="images/salir.png"></a><br>
</div>
ippbx.php
<?php
session_start();
?>
<html>
<body>
<?php
if(!isset($_SESSION['logged']) && $_SESSION['logged']!=1){
session_destroy();
} else {
include('config/sidebar.inc');
switch ($_GET['page']) {
case 'create_account':
include('create_account.html');
break;
case 'edit_account':
include('edit_account.php');
break;
case 'delete_account':
include('delete_account.php');
break;
case 'create_voicemail':
include('create_voicemail.html');
break;
case 'edit_voicemail':
include('edit_voicemail.php');
break;
case 'delete_voicemail':
include('delete_voicemail.php');
break;
case 'list_calls':
include('list_calls.php');
break;
case 'edit_config':
include('edit_config.php');
break;
case 'apply_changes':
include('apply_changes.php');
break;
case 'logout':
include('logout.php');
66
break;
default:
?>
<H3>IP PBX:</H3><br />
Utilice los menúes de para crear, editar y eliminar cuentas de usuario y de
voicemail, <br />
listar llamadas, modificar archivos de configuración y aplicar cambios.<br />
<?php
break;
};
}
?>
</body>
</html>
create_account.html
<html>
<body>
<H3>Creación de cuentas</H3>
<form action="create_account.php" method="post">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="text" name="secret" /></p>
<p>CallerID: <input type="text" name="callerid" /></p>
<p>Host: <input type="text" name="host" value="dynamic"/></p>
<p>Context: <input type="text" name="context"
value="sip_users"/></p>
<p>DTMF Mode: <select name="dtmfmode">
<option value=rfc2833>rfc2833</option>";
<option value=inband>inband</option>";
<option value=info>info</option>";
<option value=auto>auto</option>";
</select></p>
<p>Insecure: <select name="insecure">
<option value=port>port</option>";
<option value=invite>invite</option>";
<option value=port,invite>port,invite</option>";
</select></p>
<p>CanReinvite: <select name="canreinvite">
<option value=yes>yes</option>";
<option value=no>no</option>";
</select></p>
<p>Nat: <select name="nat">
<option value=yes>yes</option>";
<option value=no>no</option>";
</select></p>
<p><input type="submit" /></p>
</form>
</body>
</html>
create_account.php
67
<?php
include('config/sidebar.inc');
$username=$_POST['username'];
$secret=$_POST['secret'];
$callerid=$_POST['callerid'];
$host=$_POST['host'];
$context=$_POST['context'];
$dtmfmode=$_POST['dtmfmode'];
$insecure=$_POST['insecure'];
$canreinvite=$_POST['canreinvite'];
$nat=$_POST['nat'];
$stringData="";
$destination_xml='/usr/local/etc/asterisk/sip.xml';
$destination_txt='/usr/local/etc/asterisk/sip.conf';
$existe="0";
$error1="0";
$error2="0";
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
//
print_r($xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
//existe la cuenta a crear?
foreach ($xml->sip_user as $sip_user) {
if ($sip_user["id"]=="$username"){
$existe="1";
break;
}
}
//si no existe, la creamos
if ($existe=="0") {
$new_user=$xml->addChild('sip_user');
$new_user->addAttribute('id', $username);
$new_user->addChild('username', $username);
$new_user->addChild('secret', $secret);
$new_user->addChild('callerid', $callerid);
$new_user->addChild('type', 'friend');
$new_user->addChild('host', $host);
$new_user->addChild('context', $context);
$new_user->addChild('dtmfmode', $dtmfmode);
$new_user->addChild('insecure', $insecure);
$new_user->addChild('canreinvite', $canreinvite);
$new_user->addChild('nat', $nat);
$new_user->addChild('mailbox', $username);
//escribimos el archivo xml a disco
$rs=write_file($destination_xml, $xml->asXML());
if ( $rs ) {
$error1="0";
}
else {
$error1="1";
}
//Leemos del XML la configuracion [General]
$param1=$xml->sip_general->param1;
68
$param2=$xml->sip_general->param2;
$param3=$xml->sip_general->param3;
$param4=$xml->sip_general->param4;
$param5=$xml->sip_general->param5;
$param6=$xml->sip_general->param6;
$param7=$xml->sip_general->param7;
$param8=$xml->sip_general->param8;
$param9=$xml->sip_general->param9;
$param10=$xml->sip_general->param10;
$param11=$xml->sip_general->param11;
$provparam1=$xml->sip_provider->param1;
$provparam2=$xml->sip_provider->param2;
$provparam3=$xml->sip_provider->param3;
$provparam4=$xml->sip_provider->param4;
$provparam5=$xml->sip_provider->param5;
$provparam6=$xml->sip_provider->param6;
//creamos un string a partir de los parametros que obtenemos del archivo XML
$stringData=$stringData .
"$param1\n$param2\n$param3\n$param4\n$param5\n$param6\n$param7\n$param8\n$param9
\n$param10\n$param11\n\n$provparam1\n$provparam2\n$provparam3\n$provparam4\n$pro
vparam5\n$provparam6\n\n";
foreach ($xml->sip_user
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
}
as
.
.
.
.
.
.
.
.
.
.
.
.
$sip_user) {
"[" . $sip_user->username . "]\n";
"username=" . $sip_user->username . "\n";
"secret=" . $sip_user->secret . "\n";
"callerid=" . $sip_user->callerid . "\n";
"type=" . $sip_user->type . "\n";
"host=" . $sip_user->host . "\n";
"context=" . $sip_user->context . "\n";
"dtmfmode=" . $sip_user->dtmfmode . "\n";
"insecure=" . $sip_user->insecure . "\n";
"canreinvite=" . $sip_user->canreinvite . "\n";
"nat=" . $sip_user->nat . "\n";
"mailbox=" . $sip_user->mailbox . "\n\n";
//escribimos en disco el archivo de texto sip.conf
$rs=write_file($destination_txt, $stringData);
if ( $rs ) {
$error2="0";
}
else {
$error2="1";
}
}
//mostramos en la pagina web los errores que hayamos obtenido
if ($existe=="1")
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>Error. La
cuenta ya existe.</b></font><br />';
else {
if ($error1=="1" && $error2=="1")
echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Error al intentar crear el archivo de configuración.</b></font><br
/>';
else
69
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>La
cuenta ha sido creada exitosamente.</b></font><br />';
}
//funcion que escribe archivos en disco
function write_file($filename, $contents) {
if ($fp=fopen($filename, "w")) {
fputs($fp, $contents, strlen($contents));
fclose($fp);
return 1;
}
else { return 0; }
}
?>
edit_account.php
<html>
<body>
<?php
$username= $_POST['username'];
$destination_xml='/usr/local/etc/asterisk/sip.xml';
if (is_string($username)) {
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else exit('No se puede abrir el archivo $destination_xml');
//buscamos la cuenta a crear
foreach ($xml->sip_user as $sip_user) {
if ($sip_user["id"]=="$username"){
$username=$sip_user->username;
$secret=$sip_user->secret;
$callerid=$sip_user->callerid;
$host=$sip_user->host;
$context=$sip_user->context;
$dtmf=$sip_user->dtmf;
$insecure=$sip_user->insecure;
$canreinvite=$sip_user->canreinvite;
$nat=$sip_user->nat;
break;
}
}
//acá mostramos los formularios para edicion
include('config/sidebar.inc');
?>
<H3>Edición de cuentas</H3>
<form action="edit_account_action.php" method="post">
<p>Username: <input type="text" name="username"
value="<?=$username?>"/></p>
<p>Password: <input type="text" name="secret"
value="<?=$secret?>"/></p>
70
<p>CallerID: <input type="text" name="callerid"
value="<?=$callerid?>"/></p>
<p>Host: <input type="text" name="host" value="<?=$host?>"/></p>
<p>Context: <input type="text" name="context"
value="<?=$context?>"/></p>
<p>DTMF Mode: <select name="dtmfmode">
<option value=rfc2833>rfc2833</option>";
<option value=inband>inband</option>";
<option value=info>info</option>";
<option value=auto>auto</option>";
</select></p>
<p>Insecure: <select name="insecure">
<option value=port>port</option>";
<option value=invite>invite</option>";
<option value=port,invite>port,invite</option>";
</select></p>
<p>CanReinvite: <select name="canreinvite">
<option value=yes>yes</option>";
<option value=no>no</option>";
</select></p>
<p>Nat: <select name="nat">
<option value=yes>yes</option>";
<option value=no>no</option>";
</select></p>
<p><input type="submit" /></p>
</form>
<!->
<?
}
<H4><meta http-equiv="Refresh" content="0; url=edit_account.php"> </H4> --
else {
?>
<H3>Edición de cuentas</H3>
<form action="edit_account.php" method="post">
<p>Username: <select name="username">
<option "selected" value="0">Usuario</option>
<?php
//cargamos y leemos las cuentas creadas en el XML y despues las mostramos como
opciones de formulario
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else exit('No se puede abrir el archivo $destination_xml');
foreach ($xml->sip_user as $sip_user) {
echo "<option value=\"$sip_user->username\">$sip_user->username</option>";
}
?>
</select></p>
<p><input type="submit" /></p>
</form>
<?
}
?>
71
</body>
</html>
edit_account_action.php
<?php
include('config/sidebar.inc');
$username=$_POST['username'];
$secret=$_POST['secret'];
$callerid=$_POST['callerid'];
$host=$_POST['host'];
$context=$_POST['context'];
$dtmfmode=$_POST['dtmfmode'];
$insecure=$_POST['insecure'];
$canreinvite=$_POST['canreinvite'];
$nat=$_POST['nat'];
$stringData="";
$destination_xml='/usr/local/etc/asterisk/sip.xml';
$destination_txt='/usr/local/etc/asterisk/sip.conf';
$existe="0";
$error1="0";
$error2="0";
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
//
print_r($xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
//buscamos la cuenta a modificar
foreach ($xml->sip_user as $sip_user) {
if ($sip_user["id"]=="$username"){
$sip_user->username=$username;
$sip_user->secret=$secret;
$sip_user->callerid=$callerid;
$sip_user->host=$host;
$sip_user->context=$context;
$sip_user->dtmf=$dtmf;
$sip_user->insecure=$insecure;
$sip_user->canreinvite=$canreinvite;
$sip_user->nat=$nat;
$sip_user->mailbox=$username;
break;
}
}
//escribimos el archivo xml a disco
$rs=write_file($destination_xml, $xml->asXML());
if ( $rs ) {
$error1="0";
}
else {
$error1="1";
}
//Leemos del XML la configuracion [General]
$param1=$xml->sip_general->param1;
72
$param2=$xml->sip_general->param2;
$param3=$xml->sip_general->param3;
$param4=$xml->sip_general->param4;
$param5=$xml->sip_general->param5;
$param6=$xml->sip_general->param6;
$param7=$xml->sip_general->param7;
$param8=$xml->sip_general->param8;
$provparam1=$xml->sip_provider->param1;
$provparam2=$xml->sip_provider->param2;
$provparam3=$xml->sip_provider->param3;
$provparam4=$xml->sip_provider->param4;
$provparam5=$xml->sip_provider->param5;
$provparam6=$xml->sip_provider->param6;
//creamos un string a partir de los parametros que obtenemos del archivo XML
$stringData=$stringData .
"$param1\n$param2\n$param3\n$param4\n$param5\n$param6\n$param7\n$param8\n$param9
\n$param10\n$param11\n\n$provparam1\n$provparam2\n$provparam3\n$provparam4\n$pro
vparam5\n$provparam6\n\n";
foreach ($xml->sip_user
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
}
as
.
.
.
.
.
.
.
.
.
.
.
.
$sip_user) {
"[" . $sip_user->username . "]\n";
"username=" . $sip_user->username . "\n";
"secret=" . $sip_user->secret . "\n";
"callerid=" . $sip_user->callerid . "\n";
"type=" . $sip_user->type. "\n";
"host=" . $sip_user->host . "\n";
"context=" . $sip_user->context. "\n";
"dtmfmode=" . $sip_user->dtmfmode . "\n";
"insecure=" . $sip_user->insecure . "\n";
"canreinvite=" . $sip_user->canreinvite. "\n";
"nat=" . $sip_user->nat. "\n";
"mailbox=" . $sip_user->mailbox . "\n\n";
//escribimos en disco el archivo de texto sip.conf
$rs=write_file($destination_txt, $stringData);
if ( $rs ) {
$error2="0";
}
else {
$error2="1";
}
//mostramos en la pagina web los errores que hayamos obtenido
if ($error1=="1" && $error2=="1")
echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Error al intentar crear el archivo de configuración.</b></font><br
/>';
else
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>La
cuenta ha sido editada exitosamente.</b></font><br />';
//funcion que escribe archivos en disco
function write_file($filename, $contents) {
if ($fp=fopen($filename, "w")) {
fputs($fp, $contents, strlen($contents));
fclose($fp);
return 1;
73
}
else { return 0; }
}
?>
delete_account.php
<html>
<body>
<H3>Eliminación de cuentas</H3>
<form action="delete_account_action.php" method="post">
<p>Username: <select name="username">
<option "selected" value="0">Usuario</option>
<?php
$destination_xml='/usr/local/etc/asterisk/sip.xml';
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
foreach ($xml->sip_user as $sip_user) {
echo "<option value=\"$sip_user->username\">$sip_user->username</option>";
}
?>
</select></p>
<p><input type="submit" /></p>
</form>
</body>
</html>
delete_account_action.php
<?php
include('config/sidebar.inc');
$username=$_POST['username'];
$stringData="";
$destination_xml='/usr/local/etc/asterisk/sip.xml';
$destination_txt='/usr/local/etc/asterisk/sip.conf';
$existe="0";
$error1="0";
$error2="0";
$posicion="0";
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
//buscamos la posicion del usuario a eliminar
foreach ($xml->sip_user as $sip_user) {
if ($sip_user["id"]=="$username"){
74
$existe="1";
break;
}
$posicion++;
}
if ($existe=="1") {
//creamos un documento DOM a partir del documento XML
$doc=new DOMDocument();
$doc->load($destination_xml);
//buscamos el nodo a eliminar y lo eliminamos
$node=$doc->getElementsByTagName("sip_user")->item($posicion);
$doc->getElementsByTagName("configuracion")->item(0)->removeChild($node);
//importamos desde DOM a XML
$xml=simplexml_import_dom($doc);
//guardamos el archivo xml en disco
$rs=write_file($destination_xml, $xml->asXML());
if ( $rs ) {
$error1="0";
}
else {
$error1="1";
}
//Leemos del XML la configuracion [General]
$param1=$xml->sip_general->param1;
$param2=$xml->sip_general->param2;
$param3=$xml->sip_general->param3;
$param4=$xml->sip_general->param4;
$param5=$xml->sip_general->param5;
$param6=$xml->sip_general->param6;
$param7=$xml->sip_general->param7;
$param8=$xml->sip_general->param8;
$param9=$xml->sip_general->param9;
$param10=$xml->sip_general->param10;
$param11=$xml->sip_general->param11;
$provparam1=$xml->sip_provider->param1;
$provparam2=$xml->sip_provider->param2;
$provparam3=$xml->sip_provider->param3;
$provparam4=$xml->sip_provider->param4;
$provparam5=$xml->sip_provider->param5;
$provparam6=$xml->sip_provider->param6;
//creamos un string a partir de los parametros que obtenemos del archivo XML
$stringData=$stringData .
"$param1\n$param2\n$param3\n$param4\n$param5\n$param6\n$param7\n$param8\n$param9
\n$param10\n$param11\n\n$provparam1\n$provparam2\n$provparam3\n$provparam4\n$pro
vparam5\n$provparam6\n\n";
foreach ($xml->sip_user
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
$stringData=$stringData
as
.
.
.
.
.
.
.
.
.
.
$sip_user) {
"[" . $sip_user->username . "]\n";
"username=" . $sip_user->username . "\n";
"secret=" . $sip_user->secret . "\n";
"callerid=" . $sip_user->callerid . "\n";
"type=" . $sip_user->type. "\n";
"host=" . $sip_user->host . "\n";
"context=" . $sip_user->context. "\n";
"dtmfmode=" . $sip_user->dtmfmode . "\n";
"insecure=" . $sip_user->insecure . "\n";
"canreinvite=" . $sip_user->canreinvite. "\n";
75
$stringData=$stringData .
}
"nat=" . $sip_user->nat. "\n\n";
//escribimos en disco el archivo de texto sip.conf
$rs=write_file($destination_txt, $stringData);
if ( $rs ) {
$error2="0";
}
else {
$error2="1";
}
}
//mostramos en la pagina web los errores que hayamos obtenido
if ($existe=="0")
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>Error. La
cuenta no existe.</b></font><br />';
else {
if ($error1=="1" && $error2=="1")
echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Error al intentar crear el archivo de configuración.</b></font><br
/>';
else
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>La
cuenta ha sido eliminada exitosamente.</b></font><br />';
}
//funcion que escribe archivos en disco
function write_file($filename, $contents) {
if ($fp=fopen($filename, "w")) {
fputs($fp, $contents, strlen($contents));
fclose($fp);
return 1;
}
else { return 0; }
}
?>
create_voicemail.html
<html>
<body>
<H3>Creación de Voicemail</H3>
<form action="create_voicemail.php" method="post">
<p>Cuenta: <input type="text" name="username" /></p>
<p>Password: <input type="text" name="secret" /></p>
<p>Nombre: <input type="text" name="name" /></p>
<p>Email: <input type="text" name="email"/></p>
<p><input type="submit" /></p>
</form>
</body>
</html>
76
create_voicemail.php
<?php
include('config/sidebar.inc');
$username=$_POST['username'];
$secret=$_POST['secret'];
$name=$_POST['name'];
$email=$_POST['email'];
$stringData="";
$destination_xml='/usr/local/etc/asterisk/voicemail.xml';
$destination_txt='/usr/local/etc/asterisk/voicemail.conf';
$existe="0";
$error1="0";
$error2="0";
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
//
print_r($xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
//existe la cuenta a crear?
foreach ($xml->vm_user as $vm_user) {
if ($vm_user["id"]=="$username"){
$existe="1";
break;
}
}
//si no existe, la creamos
if ($existe=="0") {
$new_user=$xml->addChild('vm_user');
$new_user->addAttribute('id', $username);
$new_user->addChild('username', $username);
$new_user->addChild('secret', $secret);
$new_user->addChild('name', $name);
$new_user->addChild('email', $email);
//escribimos el archivo xml a disco
$rs=write_file($destination_xml, $xml->asXML());
if ( $rs ) {
$error1="0";
}
else {
$error1="1";
}
//Leemos del XML la configuracion [General]
$param1=$xml->vm_general->param1;
$param2=$xml->vm_general->param2;
$param3=$xml->vm_general->param3;
$param4=$xml->vm_general->param4;
$param5=$xml->vm_general->param5;
$param6=$xml->vm_general->param6;
$param7=$xml->vm_general->param7;
$param8=$xml->vm_general->param8;
$param9=$xml->vm_general->param9;
$param10=$xml->vm_general->param10;
$param11=$xml->vm_general->param11;
77
//creamos un string a partir de los parametros que obtenemos del archivo XML
$stringData=$stringData .
"$param1\n$param2\n$param3\n$param4\n$param5\n$param6\n$param7\n$param8\n$param9
\n$param10\n\n$param11\n";
foreach ($xml->vm_user as $vm_user) {
$stringData=$stringData . $vm_user->username . " => " . $vm_user->secret . "," .
$vm_user->name . "," . $vm_user->email . "\n";
}
//escribimos en disco el archivo de texto sip.conf
$rs=write_file($destination_txt, $stringData);
if ( $rs ) {
$error2="0";
}
else {
$error2="1";
}
}
//mostramos en la pagina web los errores que hayamos obtenido
if ($existe=="1")
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>Error. La
cuenta ya existe.</b></font><br />';
else {
if ($error1=="1" && $error2=="1")
echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Error al intentar crear el archivo de configuración.</b></font><br
/>';
else
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>La
cuenta ha sido creada exitosamente.</b></font><br />';
}
//funcion que escribe archivos en disco
function write_file($filename, $contents) {
if ($fp=fopen($filename, "w")) {
fputs($fp, $contents, strlen($contents));
fclose($fp);
return 1;
}
else { return 0; }
}
?>
edit_voicemail.php
<html>
<body>
<?php
$username= $_POST['username'];
$destination_xml='/usr/local/etc/asterisk/voicemail.xml';
if (is_string($username)) {
78
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else exit('No se puede abrir el archivo $destination_xml');
//buscamos la cuenta a crear
foreach ($xml->vm_user as $vm_user) {
if ($vm_user["id"]=="$username"){
$username=$vm_user->username;
$secret=$vm_user->secret;
$name=$vm_user->name;
$email=$vm_user->email;
break;
}
}
//acá mostramos los formularios para edicion
include('config/sidebar.inc');
?>
<H3>Edición de Voicemail</H3>
<form action="edit_voicemail_action.php" method="post">
<p>Cuenta: <input type="text" name="username"
value="<?=$username?>"/></p>
<p>Password: <input type="text" name="secret"
value="<?=$secret?>"/></p>
<p>Nombre: <input type="text" name="name"
value="<?=$name?>"/></p>
<p>Email: <input type="text" name="email"
value="<?=$email?>"/></p>
<p><input type="submit" /></p>
</form>
<!--->
<?
}
<H4><meta http-equiv="Refresh" content="0; url=edit_voicemail.php"> </H4>
else {
?>
<H3>Edición de Voicemail</H3>
<form action="edit_voicemail.php" method="post">
<p>Cuenta: <select name="username">
<option "selected" value="0">Voicemail</option>
<?php
//cargamos y leemos las cuentas creadas en el XML y despues las mostramos como
opciones de formulario
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else exit('No se puede abrir el archivo $destination_xml');
foreach ($xml->vm_user as $vm_user) {
echo "<option value=\"$vm_user->username\">$vm_user->username</option>";
}
?>
79
</select></p>
<p><input type="submit" /></p>
</form>
<?
}
?>
</body>
</html>
edit_voicemail_action.php
<?php
include('config/sidebar.inc');
$username=$_POST['username'];
$secret=$_POST['secret'];
$name=$_POST['name'];
$email=$_POST['email'];
$stringData="";
$destination_xml='/usr/local/etc/asterisk/voicemail.xml';
$destination_txt='/usr/local/etc/asterisk/voicemail.conf';
$existe="0";
$error1="0";
$error2="0";
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
//
print_r($xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
//buscamos la cuenta a modificar
foreach ($xml->vm_user as $vm_user) {
if ($vm_user["id"]=="$username"){
$vm_user->username=$username;
$vm_user->secret=$secret;
$vm_user->name=$name;
$vm_user->email=$email;
break;
}
}
//escribimos el archivo xml a disco
$rs=write_file($destination_xml, $xml->asXML());
if ( $rs ) {
$error1="0";
}
else {
$error1="1";
}
//Leemos del XML la configuracion [General]
$param1=$xml->vm_general->param1;
$param2=$xml->vm_general->param2;
$param3=$xml->vm_general->param3;
$param4=$xml->vm_general->param4;
$param5=$xml->vm_general->param5;
$param6=$xml->vm_general->param6;
80
$param7=$xml->vm_general->param7;
$param8=$xml->vm_general->param8;
$param9=$xml->vm_general->param9;
$param10=$xml->vm_general->param10;
$param11=$xml->vm_general->param11;
//creamos un string a partir de los parametros que obtenemos del archivo XML
$stringData=$stringData .
"$param1\n$param2\n$param3\n$param4\n$param5\n$param6\n$param7\n$param8\n$param9
\n$param10\n\n$param11\n";
foreach ($xml->vm_user as $vm_user) {
$stringData=$stringData . $vm_user->username . " => " . $vm_user->secret . "," .
$vm_user->name . "," . $vm_user->email . "\n";
}
//escribimos en disco el archivo de texto vm.conf
$rs=write_file($destination_txt, $stringData);
if ( $rs ) {
$error2="0";
}
else {
$error2="1";
}
//mostramos en la pagina web los errores que hayamos obtenido
if ($error1=="1" && $error2=="1")
echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Error al intentar crear el archivo de configuración.</b></font><br
/>';
else
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>La
cuenta ha sido editada exitosamente.</b></font><br />';
//funcion que escribe archivos en disco
function write_file($filename, $contents) {
if ($fp=fopen($filename, "w")) {
fputs($fp, $contents, strlen($contents));
fclose($fp);
return 1;
}
else { return 0; }
}
?>
delete_voicemail.php
<html>
<body>
<H3>Eliminación de Voicemail</H3>
<form action="delete_voicemail_action.php" method="post">
<p>Cuenta: <select name="username">
<option "selected" value="0">Voicemail</option>
<?php
$destination_xml='/usr/local/etc/asterisk/voicemail.xml';
81
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
foreach ($xml->vm_user as $vm_user) {
echo "<option value=\"$vm_user->username\">$vm_user->username</option>";
}
?>
</select></p>
<p><input type="submit" /></p>
</form>
</body>
</html>
delete_voicemail_action.php
<?php
include('config/sidebar.inc');
$username=$_POST['username'];
$stringData="";
$destination_xml='/usr/local/etc/asterisk/voicemail.xml';
$destination_txt='/usr/local/etc/asterisk/voicemail.conf';
$existe="0";
$error1="0";
$error2="0";
$posicion="0";
//cargamos el archivo de configuracion xml
if (file_exists($destination_xml)) {
$xml=simplexml_load_file($destination_xml);
} else {
exit('No se puede abrir el archivo $destination_xml');
}
//buscamos la posicion del usuario a eliminar
foreach ($xml->vm_user as $vm_user) {
if ($vm_user["id"]=="$username"){
$existe="1";
break;
}
$posicion++;
}
if ($existe=="1") {
//creamos un documento DOM a partir del documento XML
$doc=new DOMDocument();
$doc->load($destination_xml);
//buscamos el nodo a eliminar y lo eliminamos
$node=$doc->getElementsByTagName("vm_user")->item($posicion);
$doc->getElementsByTagName("configuracion")->item(0)->removeChild($node);
//importamos desde DOM a XML
$xml=simplexml_import_dom($doc);
//guardamos el archivo xml en disco
$rs=write_file($destination_xml, $xml->asXML());
if ( $rs ) {
$error1="0";
}
82
else {
$error1="1";
}
//Leemos del XML la configuracion [General]
$param1=$xml->vm_general->param1;
$param2=$xml->vm_general->param2;
$param3=$xml->vm_general->param3;
$param4=$xml->vm_general->param4;
$param5=$xml->vm_general->param5;
$param6=$xml->vm_general->param6;
$param7=$xml->vm_general->param7;
$param8=$xml->vm_general->param8;
$param9=$xml->vm_general->param9;
$param10=$xml->vm_general->param10;
$param11=$xml->vm_general->param11;
//creamos un string a partir de los parametros que obtenemos del archivo XML
$stringData=$stringData .
"$param1\n$param2\n$param3\n$param4\n$param5\n$param6\n$param7\n$param8\n$param9
\n$param10\n\n$param11\n";
foreach ($xml->vm_user as $vm_user) {
$stringData=$stringData . $vm_user->username . " => " . $vm_user->secret . "," .
$vm_user->name . "," . $vm_user->email . "\n";
}
//escribimos en disco el archivo de texto vm.conf
$rs=write_file($destination_txt, $stringData);
if ( $rs ) {
$error2="0";
}
else {
$error2="1";
}
}
//mostramos en la pagina web los errores que hayamos obtenido
if ($existe=="0")
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>Error. La
cuenta no existe.</b></font><br />';
else {
if ($error1=="1" && $error2=="1")
echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Error al intentar crear el archivo de configuración.</b></font><br
/>';
else
echo '<font face="Arial, Helvetica, sans-serif" size="2"><b>La
cuenta ha sido eliminada exitosamente.</b></font><br />';
}
//funcion que escribe archivos en disco
function write_file($filename, $contents) {
if ($fp=fopen($filename, "w")) {
fputs($fp, $contents, strlen($contents));
fclose($fp);
return 1;
}
else { return 0; }
83
}
?>
list_calls.php
<html>
<body>
<H3>Listado de llamadas</H3>
<?php
$destination = "/var/log/asterisk/cdr-csv/Master.csv";
print "<p><b>CDRs desde el ultimo reset del sistema:</b><br />";
print "<table
border=2><tr><th>Fecha<th>Usuario<th>Destino<th>Duracion(seg)<th>Estado:\n";
if (file_exists($destination)) {
$file = fopen($destination, "r");
while (!feof($file) ) {
$line = fgetcsv($file, 1024);
print "<tr><td>" . $line[10];
print "<td>" . $line[1];
print "<td>" . $line[2];
print "<td>" . $line[13];
print "<td>" . $line[14];
print "\n";
}
print "</table>\n";
fclose($file);
}
?>
</body>
</html>
edit_config.php
<?php
$texto=$_POST['texto'];
$archivo=$_POST['archivo'];
$config_files="/usr/local/etc/asterisk/config_files.txt";
if (is_string($texto))
{
$myFile = "/usr/local/etc/asterisk/$archivo";
$fh = fopen($myFile, 'w');
fwrite($fh, $texto);
fclose($fh);
?>
<H4><meta http-equiv="Refresh" content="0;
url=ippbx.php?page=edit_config"> </H4>
<?
}
else {
// se seleccionó un archivo a editar?
if (is_string($archivo))
{
$myFile = "/usr/local/etc/asterisk/$archivo";
$fh = fopen($myFile, 'r');
84
$theData = fread($fh, filesize($myFile));
fclose($fh);
include('config/sidebar.inc');
?>
<html>
<head>
<title>Edicion de archivos de configuración</title>
</head>
<body>
<H3>Modificar y guardar archivo</H3>
<form action="edit_config.php" method="post">
<strong><?=$archivo?>:</strong><br />
<input type=hidden name="archivo" value="<?=$archivo?>">
<textarea name="texto" rows="20" cols="40">
<?=$theData?></textarea>
<br />
<input type="submit" value="Submit" />
</form>
<?
}
else {
//mostramos las opciones de archivos a editar
?>
<H3>Seleccione el archivo a editar</H3>
<form action="edit_config.php" method="post">
Archivo de configuración: <select name="archivo">
<?
$config=file($config_files);
foreach ($config as $linea) {
echo "<option value=$linea>$linea</option>";
}
?>
<option value=config_files.txt>config_files.txt</option>
</select>
<p><input type="submit" /></p>
</form>
<?
}
}
?>
</body>
</html>
apply_changes.php
<html>
<body>
<?php
system('/usr/local/sbin/asterisk -rx reload', $retval);
if ($retval == 0) echo '<font face="Arial, Helvetica, sans-serif"
size="2"><b>Cambios aplicados exitosamente.</b></font><br />';
85
else echo "Falló la aplicación de los cambios";
?>
</body>
</html>
logout.php
<?php
session_destroy();
?>
<html>
<meta http-equiv="Refresh" content="0; url=index.html">
</html>
86
Descargar