четверг, 12 марта 2009 г.

Создание сервера видеоконференций на базе OpenMCU и GnuGK (voip gatekeeper openmcu linux)

http://www.opennet.ru/base/net/openmcu_gnugk.txt.html

Введение

Эта статья призвана немного восполнить пробел практически полного отсутствия
информации о проекте OpenMCU на русском языке. Пару раз эта тема проскакивала здесь
на opennet.ru и на форуме ixbt.com и, собственно, из этих источников я и узнал
о существовании OpenMCU :) А вот, как его все-таки использовать,
информации было крайне мало и она была неполная. На английском языке ее,
по-моему, также не густо, лучшее, что я нашел, было в зарубежных списках
рассылки, опубликованных на http://osdir.com/ml/telephony.openh323.general/ ,
небольшом мануале на openmcu (man openmcu) и сайте, посвященном GnuGK http://www.gnugk.org/,
который, в отличие от OpenMCU, куда лучше документирован.
Буду очень благодарен за любые замечания и улучшения.

Дистрибутив:
Я использовал Linux OpenSUSE 10.3, версия ядра 2.6.22.5-31

Версии пакетов:
openmcu-2.2.0-104 (сервер видеоконференций, использующий протокол H323)
gnugk-2.2.5-65 (H323 Gatekeeper)
Используемые библиотеки:
openh323-1.19.0.1-106
pwlib-1.10.7-61

Процесс установки описывать не буду, никаких трудностей в нем нет, положим,
все необходимое уже установлено.

По поводу того, что такое протокол H323, привратник, MCU и т.д.
можно почитать, например, Здесь
и Здесь

Как все это работает?
Клиент регистрируется у привратника (GnuGK) под именем, скажем, nm1. Затем набирает
код выхода на openmcu, например, "02" и привратник соединяет его с сервером видеоконференций (OpenMCU),
где nm1 ждет остальных участников. Все остальные попадают на конференцию точно так же.
Для всех собравшихся используется default room - комната видеоконференции по умолчанию.
Привратник не является обязательным компонентом, но дает удобную возможность использовать
короткие символьные имена вместо ip-адресов. Так, все зарегестрировшиеся у привратника могут
также вызывать друг друга по имени, например, клиент зарегестрировавшийся, как nm2 может вызвать nm1
по его имени и организовать с ним видеообщение на 2 участников (point-to-point).
Тогда openmcu не используется.

Конфигурация GnuGK:
/etc/gnugk.ini

[Gatekeeper::Main]
FourtyTwo=42
Name=GNU_Gk
;EndpointSuffix=_gnugk
Home=127.0.0.1
StatusTraceLevel=2
UseBroadcastListener=0
TimestampFormat=ISO8601
EndpointSignalPort=1721
EncryptAllPasswords=0
UseMulticastListener=0
StatusPort=7000 #Порт мониторинга

SignalCallId=1

[GkStatus::Auth] #Здесь задаются правила доступа к
#мониторингу GnuGK
rule=explicit #Доступ осуществляется на основе ip
192.168.2.106=allow #Хост с которого можно мониторить GnuGK
Shutdown=allow #Разрешено отключать gnugk в мониторинге

#Самое важное:
#Описываем постоянные точки подключения, то есть те, которые будут
#постоянно храниться в регистрационной таблице привратника

[RasSrv::PermanentEndpoints]
127.0.0.1:1720=mcu;02 #наш mcu

[RasSrv::GWPrefixes]
mcu=02 #префикс выхода на него

#Остальное можно не трогать
[RasSrv::RRQFeatures]
AcceptEndpointIdentifier=1
AcceptGatewayPrefixes=1
OverwriteEPOnSameAddress=1
IRQPollCount=0

[RasSrv::ARQFeatures]
CallUnregisteredEndpoints=0
ArjReasonRouteCallToGatekeeper=0

[RoutedMode]
GKRouted=1
H245Routed=1
CallSignalPort=1721
AcceptNeighborCalls=1
AcceptUnregisteredCalls=1
RemoveH245AddressOnTunneling=0
RemoveCallOnDRQ=1
DropCallsByReleaseComplete=1
SendReleaseCompleteOnDRQ=1
SupportNATedEndpoints=1
TranslateFacility=1

[Proxy]
Enable=1
ProxyForNAT=1
RTPPortRange=1024-65535

[RoutingPolicy]
00=explicit,internal
02=internal,explicit
Default=explicit,internal,numberanalysis

[CallTable]
GenerateNBCDR=0
GenerateUCCDR=1

[Gatekeeper::Auth]
FileIPAuth=optional;RRQ
SQLPasswordAuth=required;RRQ
SQLAuth=required;ARQ,Setup

[Gatekeeper::Acct]
SQLAcct=required;start,update,stop


Подробное описание каждого из параметров можно найти на http://www.gnugk.org/gnugk-manual.html

Работу GnuGK можно мониторить подключившись к серверу на 7000 порт.
Например, мой сервер - 192.168.3.2

telnet 192.168.3.2 7000

Version:
Gatekeeper(GNU) Version(2.2.5) Ext(pthreads=1,radius=1,mysql=0,pgsql=0,firebird=0,large_fd
set=0,crypto/ssl=1) Build(Sep 25 2007, 22:47:36) Sys(Linux i686 2.6.22.5-31-default)
GkStatus: Version(2.0) Ext()
Toolkit: Version(1.0) Ext(basic)
Startup: Thu, 26 Feb 2009 14:09:41 +0600 Running: 0 days 23:41:38;


Конфигурация OpenMCU

OpenMCU по умолчанию хранит свой конфиг в

~/.pwlib_config/openmcu.ini


Поначалу конфига нет в этой директории, чтобы он появился, можно
подключиться к openmcu через веб-интерфейс (про это - ниже), заполнить
необходимые поля, нажать Accept и конфиг будет создан.

[Parameters]
Username=mcu
Password=******* #Пароль здесь указывать не надо, это
#можно сделать через веб-интерфейс, а здесь хранится только хэш
Log Level=4
HTTP Certificate=server.pem
HTTP Port=1420
Gatekeeper Mode=No gatekeeper #Не использовать регистрацию у
#привратника
#Далее идут различные параметры, связанные с обслуживанием
#видеоконференции,
#можно все оставить, как есть, все нормально работает с дефолтовыми
#параметрами
Interface Array Size=0
Enable video=True
Video frame rate=10
Video quality=10
Default room=room101
Room time limit=0
Connecting WAV File=/usr/sbin/connecting.wav
Entering WAV File=/usr/sbin/entering.wav
Leaving WAV File=/usr/sbin/leaving.wav
Call log filename=/var/log/openmcu/opemcu.log
Force split screen video=False


Для описания этих параметров читайте man на openmcu.

Как уже говорилось, настраивать openmcu можно также через web-интерфейс.
Для этого нужно набрать в браузере https://your-MCU-ip:1420/

Доступны следующие опции:
* Parameters
* MCU Status
* Invite user to conference

С помощью Parametrs можно производить настройку сервера
В MCU status можно мониторить его текущее состояние. Очень полезная вещь!
Invite user to conference - отправить пользователю приглашение на конференцию
(не понял, как это должно работать:))

Для отладки сервисов можно использовать команды

gnugk -c имя_конфига -ttt (trace - расширенный вывод данных)
openmcu -i имя_конфига -cx (запускать как обычную программу с выводом данных на экран)


Чтобы сервисы автоматически запускались при старте, надо создать их стартовые скрипты и
положить их (в зависимости от дистрибутива) в /etc/rc.d/ или /etc/init.d/

Сами скрипты тоже могут отличаться в зависимости от используемого дистрибутива.
Вообще-то эти скрипты обычно идут вместе с пакетом (или архивом с исходниками)
программы, но для openmcu он отсутствовал, а для gnugk я немного
изменил строчку запуска

startproc $OPENGK_BIN -c /etc/gnugk.ini -o /var/log/gnugk/gnugk.log -t


Скрипт для запуска openMCU я на скорую руку слепил из шаблона для стартовых
скриптов /etc/init.d/skeleton


#!/bin/sh
#
#
# /etc/init.d/openmcu
#
### BEGIN INIT INFO
# Provides: openMCU
# Required-Start: $network $syslog $remote_fs
# Should-Start: $time ypbind smtp
# Required-Stop: $syslog $remote_fs
# Should-Stop: $time ypbind smtp
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Short-Description: OpenMCU
# Description: Start openMCU
### END INIT INFO
#

FOO_BIN="/usr/sbin/openmcu -d"
MCU_BIN="/usr/sbin/openmcu"

test -x $MCU_BIN || { echo "$MCU_BIN not installed";
if [ "$1" = "stop" ]; then exit 0;
else exit 5; fi; }

. /etc/rc.status

# Reset status of this service
rc_reset

case "$1" in
start)
echo -n "Starting OpenMCU "
## Start daemon with startproc(8). If this fails
## the return value is set appropriately by startproc.
/sbin/startproc $FOO_BIN

# Remember status and be verbose
rc_status -v
;;
stop)
echo -n "Shutting down OpenMCU"
## Stop daemon with killproc(8) and if this fails
## killproc sets the return value according to LSB.

/sbin/killproc -TERM $MCU_BIN

# Remember status and be verbose
rc_status -v
;;
try-restart|condrestart)
## Do a restart only if the service was active before.
## Note: try-restart is now part of LSB (as of 1.9).
## RH has a similar command named condrestart.
if test "$1" = "condrestart"; then
echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
fi
$0 status
if test $? = 0; then
$0 restart
else
rc_reset # Not running is not a failure.
fi
# Remember status and be quiet
rc_status
;;
restart)
## Stop the service and regardless of whether it was
## running or not, start it again.
$0 stop
$0 start

# Remember status and be quiet
rc_status
;;
force-reload)
## Signal the daemon to reload its config. Most daemons
## do this on signal 1 (SIGHUP).
## If it does not support it, restart the service if it
## is running.

echo -n "Reload service OpenMCU "
## if it supports it:
/sbin/killproc -HUP $FOO_BIN
rc_status -v

## Otherwise:
#$0 try-restart
#rc_status
;;
reload)
## Like force-reload, but if daemon does not support
## signaling, do nothing (!)

# If it supports signaling:
echo -n "Reload service OpenMCU "
/sbin/killproc -HUP $FOO_BIN
rc_status -v

## Otherwise if it does not support reload:
#rc_failed 3
#rc_status -v
;;
status)
echo -n "Checking for service OpenMCU "

# NOTE: checkproc returns LSB compliant status values.
/sbin/checkproc $MCU_BIN
# NOTE: rc_status knows that we called this init script with
# "status" option and adapts its messages accordingly.
rc_status -v
;;
probe)

esac
rc_exit




Не забудьте назначить скриптам права на выполнение.

Собственно, теперь надо положить соответсвующие ссылки на скрипты в rcN.d,
то есть для соответствующих уровней запуска.
Я предпочитаю делать это программой chkconfig

chkconfig openmcu on
chkconfig gnugk on


Теперь все готово для запуска сервисов.

service gnugk start
service openmcu start


В настройках NetMeeting надо выставить Сервис-Параметры - Расширенный вызов-
Использовать привратника для вызовов и Регистрация моей учетной записи
(имя учетной записи).
После активации параметров в правом нижнем углу у него должен появиться значок
"Есть регистрация у привратника". Теперь набираем наш префикс выхода (02) и
попадаем на сервер OpenMCU, на экране будет виден соответствующий логотип.
Все остальные участники, также регистрируясь у привратника и набирая 02, будут
попадать на нашу конференцию.

Но тут возникает один интересный вопрос. Получается, что наш сервер будет
обслуживать одновременно только одну видеоконференцию, ту, что в default room.
А как сделать так, чтобы на одном сервере MCU одновременно проводить несколько
параллельных конференций?

Именно для этого и используется разделение конференций по комнатам.
К сожалению, NetMeeting не умеет указывать при вызове желаемую комнату для
конференции и может попадать только на default room, если она задана.
Поэтому организовывать различные комнаты мы будем, используя различные префиксы
выхода на MCU в gnugk.

Например, так:
/etc/gnugk.ini

[RasSrv::GWPrefixes]
#Комната 00
mcu=00
#Комната 11
mcu=11
#Комната 22
mcu=22


Таким образом, при наборе соответствующих префиксов, клиент будет попадать в
различные комнаты. Например, при наборе 00, openmcu создаст комнату 00, в
которую и попадет клиент. Остальным участникам конференции также можно выбирать
нужную комнату, набирая нужный префикс.
Другим способом выбора комнаты является явное указание ее в запросе следующим
образом:

"room_name@server_name"


NetMeeting эту возможность не поддерживает, поэтому можно использовать другого
h323 клиента, например, несколько хороших клиентов перечислены здесь:
http://www.gnugk.org/h323-endpoint.html

В этом случае, можно не использовать регистрацию у привратника, а сразу набирать
выход на openmcu в адресной строке, например, набираем example@192.168.3.2
и попадаем на наш openmcu. Аналогично другие клиенты могут указывать свои
комнаты, отличные от example и участвовать в отдельной конференции.

Заключение

Число комнат, по идее, ограничено только аппаратными ресурсами вашего сервера.
Что касается того, сколько максимально участников может одновременно участвовать
в одной видеоконференции, то я использовал конференции лишь до 4-х
участников включительно и могу сказать только, что это работает. Что
касается большего числа участников, то единственную информацию, которую мне
удалось найти на этот счет была на http://www.e-bizone.com/e_chinabo_03.htm
(но,к сожалению, не было возможности проверить, так что за что купил,
за то и продаю)

You hear the audio from the other users, but only see the video from the
four users actively talking.

1 комментарий: