13.08.2009

Red5+ openfire + Jetty + mjsip = red5phone

Вот и настал день, когда я познакомился с Red5 на деле. Никогда не думал, что это произойдет 12 августа 2009 года. Сказать откровенно, эта технология заинтересовала меня пару месяцев назад, и я даже делал дежурные лукапы в википедии насчет того, что же это такое. Еще тогда я понял что это что-то нереально крутое, но поскольку не было необходимости эти технологии применять, то я благополучно оставил их в покое.

И вот необходимость в этих технологиях пришла. Началось с того, что мне потребовалось "завести" флешовый софтфон, по образу и подобию flaphone, про который я уже как-то упоминал в этом блоге. Было очень интересно разобраться, что же это такое, флешовый телефон, как он может работать, на каких принципах построена его работа.

Сначала я не подозревал ничего загадочного и свято верил в то, что на флеше можно писать SIP user agent-ов... Даже предполагал о существовании какой-то реализцации SIP стека, портированного под адобовский Action Script.

Но не тут-то было. Еще по опыту программирования на Swift 3D я знал, что флеш (точнее, flex) - настолько тупой язык, что не умеет делать ничего кроме анимации и проигрывания аудио (т.е. видео ролик - формат flv это он и есть), плюс работа с клавиатурой и мышью. Как же видеоролик может работать как SIP soft phone?

Разгадка оказалась гениальная.

Начну с небольшой теории. Флеш - это клиент RTMP, т.е. потребитель стримингового аудио и видео, которое в простейшем случае просто хранится на сервере, льется в флеш клиента и таким образом получается та самая анимация во флеш-роликах.
Так вот. для того, чтобы флеш работал как SIP телефон, необходим Flash Server, или RTMP сервер. Red5 это и есть Flash Server.

Red5 написан на Java. Он сидит на компе-сервере, рядом с ним сидит сервлет-контейнер Jetty, который фактически является не чем иным, как веб-сервером, способным у себя на сервере исполнять Java-сервлеты.
Вот эта дружная парочка Red5 + Jetty может жить как сама по себе (это называется standalone Red5 server), либо они могут паратизировать внутри openfire.
Openfire это XMPP сервер (т.е. Jabber-сервер), но для него существует плагин Red5.

Итак, гремучая смесь openfire + red5 + Jetty сидит на сервере, она написана на Java, требует себе Java SE JDK 1.6, и также внутри red5 зашит mjsip - опен-сорсовый java-вский SIP стек.
Вот и разгадка головоломки. За SIP соединение с телефонным сервером отвечает mjsip стек внутри Java-вского приложения Red5 (кстати, он стоит как web service на Jetty). Red5 занимается перепаковкой RTP пакетов с payload (со звуком или видео) в протокол RTMP и стримит эти данные на флешовый "телефон" в клиентском браузере. В обе стороны от флеша до red5 и обратно ходят управляющие сообщения, которые на стороне red5 преобразуются в SIP сообщения.
Таким образом, все флешовые софт-телефоны, на самом-то деле, живут внутри red5 на стороне сервера, а на клиентской стороне висят только их флешовые анимашки.

Ну а теперь к практическому занятию. Давайте соединим FreeSWITCH и флешовый телефон. Для этого нам потребуется такие компоненты (ставить в указанном порядке):
1) FreeSWITCH в поставляемой по дефолту настройке
2) Java SE JDK 1.6 последняя. На момент написания поста была последняя Update 16, скачиваем и ставим: http://java.sun.com/javase/downloads/index.jsp
3) openfire. С ним все проще, т.к. внутри него уже есть Jetty и поэтому отдельный веб-сервер (Jetty, Tomcat или JBoss) и отдельный Red5 сервер ставить не надо. Скачиваем и ставим последнюю версию openfire отсюда: http://www.igniterealtime.org/projects/openfire/index.jsp. На момент написания поста последняя версия была 3.6.4.
4) Red5 openfire plugin: Скачиваем с сайта http://www.igniterealtime.org/projects/openfire/plugins-beta.jsp. Он помечен как beta, вот прямая ссылка. Скачиваем этот файл и подкладываем его в папку "C:\Program Files\Openfire\plugins\"

В интернете еще ссылаются на некий загадочный sip.zip, который уже из многих мест, где он лежал, удален. Практика показывает, что без этого файла все работает: весьма вероятно, плагин red5 уже содержит в себе эту функциональность.

Далее запускаем openfire, заходим на страницу его администрирования и прощелкиваем все пункты кнопкой Далее. Тут важно именно щелкать эти кнопки по-порядку, а не пропускать некоторые - иначе openfire (точнее Jetty) вылетает в server failure.
После прощелкивания админки все готово к работе. Сформируется такой адрес для Red5: http://localhost:7070/red5/. Вот на этот адрес и надо зайти из браузера.

Все. Мы увидели в веб-страничке flash softphone, который надо зарегистрировать на FreeSWITCH и можно будет делать звонки.

Но! тут один нюанс: в этом софтфоне (он называется red5phone) бага, он не умеет авторизовываться, если пароль не пустой. Поэтому надо сделать пустой пароль для вашего внутреннего номера:
"C:\Program Files\FreeSWITCH\conf\directory\default\1000.xml"




Потом запускаем FreeSWITCH, прописываем в red5phone такие параметры:

Здесь IP-адрес - это адрес, на котором установлен FreeSWITCH, и voila!

Можно звонить! Вот показан пример как я с обычного софтфона звоню на флешфон:


Насчет глючности Red5Phone - радует что для него доступны исходные коды. Счастье есть :)

Follow-up касательно сообщения из первого поста про flaphone: "пока не разобрался, почему flaphone не может коннектиться к моему телефонному серверу".
Все теперь понятно, почему: потому что чтобы flaphone звонил, ему тоже нужен RTMP сервер! И поэтому он жестко завязан в коде на свой родной Netconnector URL своего RTMP сервера.
Кстати, flaphone сначала использовал именно Red5 в качестве RTMP сервера, потом они перешли на коммерческий продукт Wowza, а сейчас и вовсе сами написали свою реализацию RTMP сервера.

22.07.2009

Соединяем Yate + FreeSWITCH

Задача: соединить две телефонные сети, одну на базе Yate, вторую на базе FreeSWITCH, воедино, чтобы пользователи могли через "восьмерку" звонить из одной сети в другую.

Начальные условия: пусть у нас Yate будет установлен по адресу 192.168.3.220, а сервер FreeSWITCH - по адресу 192.168.3.217.
На стороне FreeSWITCH номер телефона 1019 используется для входящего транка с Yate. При этом CLID звонящего подменяется на строку "From Yate".

Решение:
На стороне Yate:

acctfile.conf
[freeswitch]
enabled=yes
protocol=sip
username=1019
description=freeswitch account
authname=1019
password=1234
number=1019
domain=192.168.3.217
registrar=192.168.3.217:5060


Yate должен быть принудительно авторизорван на FreeSWITCH с использованием этого кода, поскольку FreeSWITCH по умолчанию не пускает к себе юзеров из чужого домена.

regexroute.conf:
^8\(.*\)$=sip/sip:\1;line=freeswitch;caller=From Yate

Здесь все, что написано после слова freeswitch, можно удалить, и тогда CLID будет передаваться настоящий, равный внутреннему номеру абонента в сети Yate.

На стороне FreeSWITCH:

dialplan/default/yate.xml:
<extension name="yate_extens">
<condition field="destination_number" expression="^8(\d+)$">
<action application="set" data="hangup_after_bridge=true"/>
<action application="bridge" data="sofia/external/$1@192.168.3.220"/>
<action application="hangup"/>
</condition>
</extension>
Оказалось это совсем не сложно.

17.07.2009

Мой workflow для high quality car audio

Последнее время я коллекционирую и слушаю только lossless музыку (в формате APE или FLAC), при этом предпочитаю рипать аудио диск целиком, получая в результате два файла (*.APE и *.CUE). Конвертация звука в APE делается автоматически, на лету во время рипа, если в системе установлен Monkey's Audio и Exact Audio Copy должным образом настроен.
Вот в таком виде я и слушаю музыку на компьютере:
используя для этого Winamp с плагином CUE Player, который, для целей отображения в трек-листе Winamp-а, разбивает этот имадж диска на треки согласно информации в CUE файле. Очень удобно.

Но, когда дело доходит до прослушивания музыки не на компьютере, а в машине, на обычной CD-MP3 автомагнитоле, то приходится специально для магнитолы делать mp3-шки из этих lossless рипов. Вот как я их делаю:

1) Распаковываю APE файл в WAV, используя консольную утилиту от Monkey's Audio, потом редактирую CUE файл, заменяя в нем подстроку "ape" на "wav". Эти действия делаются автоматически при запуске вот этого батничка в каталоге, показанном на скриншоте выше.

--- файл ape2wav.bat ---

@echo off

if "%1%" == "GO" (

FOR /F "usebackq tokens=*" %%j IN (%2) DO (
FOR /F "usebackq tokens=1,2 delims=." %%k IN ('%%j') DO (
FOR /F "usebackq tokens=1,3 delims=" %%m IN ('%%k') DO (
FOR /F "usebackq tokens=1 delims=e" %%o IN ('%%l') DO (
if "%%o" == "ap" (
echo 1 > equal
echo %%m.wav" WAVE
)
)
)
)
if NOT EXIST equal (
echo %%j
) else del equal
)
) else (

IF EXIST unpacked del /Q unpacked
mkdir unpacked > nul 2>&1

FOR %%i IN (*.ape) do (
mac "%%i" "unpacked\%%~ni.wav" -d
copy "%%~ni.cue" "unpacked\" > nul 2>&1
)

cd unpacked

FOR %%i IN (*.cue) do (
call ape2wav.bat GO "%%i" > "%%~pni.tmp"
del "%%i"
ren "%%~pni.tmp" "%%i"
)
)
--- end ---

В этом коде есть бага, которую пока руки не доходят пофиксить: если в имени файла, упомянутом внутри CUE файла, есть точка (не считая точки перед расширением), то этот алгоритм не может заменить расширение ape на wav. Если ее зафиксить, то объем кода возрастет еще, хотя и сейчас видно, какое это извращение - писать на чистом batch языке алгоритмы поиска и замены подстрок в файлах.

2) В Exact Audio Copy выбираю меню "разделить WAV-файл согласно Cue Sheet"->"с зазорами"
3) Ну и собственно финал: кодирую в MP3 с максимальным качеством:

-- wav2mp3.bat --

for /R %%i in (*.wav) do (
cd "%%~di%%~pi"
lame --alt-preset extreme "%%~nxi" "%%~ni.mp3"
del "%%~nxi"
)
-- end --

В этом шаге используется LAME для кодированя в MP3, причем с экстремальным пресетом - это наилучший по качеству способ сжатия аудио данных с переменным битрейтом.

P.S. Люблю программировать батнички под Windows :) Такие извращения порой получаются, особенно если делать какую-то нетривиальную задачу, изящно выглядящую на perl/sed/awk. В этом примере переменная "%%~di%%~pi" это цветочки :)

P.P.S. Для полного щастья осталось научиться из скрипта вызывать функцию разбития большого WAV на куски согласно информации в CUE файле - тогда вся операция будет состоять из запуска одного скрипта.

13.07.2009

Fixed: HHCTRL 1903 Event Logger

Наконец-то поймал того зверя за яйца, кто вываливает мне в системный журнал каждые полчаса вот такие вот события:

Ссылка, приведенная в описании этого эвента, говорит ни много ни мало о том, что "MS05-026: Уязвимость в элементе управления HTML Help делает возможным удаленный запуск программного кода". В результате я стал security concerned и стал искать, кто же это меня хачит на моем домашнем ноутбуке.
На ноуте стоит WinXP SP3 со всеми последними апдейтами. Установлен DoctorWeb 5 с последними базами. Запускаю полное сканирование всех дисков в максимальных настройках эвристики - ничего не находит.
Окей, скачиваю широко известную в узких кругах программу SpyBot S&D - она также ничего не находит. Пробую искать троянов программой Ad-Aware, она тоже ничего страшного не находит. Иду, скачиваю демо-версию (на месяц) антивируса Касперского.
Касперский действительно находит кое-что, но это оказалось не помогло:
- сообщил мне что мой плеер Winamp (который я обновлял пару недель назад) - имеет страшную уязвимость и заставил проапгрейдиться на последнюю версию 5.56.
- vmware 5.5, из-под которой я запускаю Linux, тоже оказалось с уязвимостью
- Самый неожиданный результат сканирования касперским: оказывается, одна из программ от Adobe (Adobe Bridge) тащит с собой старую версию Adobe flash player plugin, в котором есть уязвимость. При этом Adobe Updater обновляет Flash player plugin в системных путях, но не обновляет в папке с Adobe Bridge (!) - жесть, кто вообще тестировал Adobe Updater?

Но и касперский ничего не находит. И тут я вспомнил про замечательную программу procmon.exe от компании sysinternals, которая у меня много лет входит в список любимых системных утилит. Скачал последнюю версию и обнаружил потрясающую связь с вот этим постом, взглянув на то, кто же автор этой программы. Никогда не запоминал фамилии, поэтому раньше Русинович и sysinternals/procmon у меня никогда не ассоциировались.

Итак, что же нам сказал Procmon? А он нам совершенно недвусмысленно сказал, что этот OCX контрол пытается раз в полчаса использовать не кто иной, как сам Dr.Web (!) - точнее, DrWebUpW.exe, модуль, который обновляет антивирусные базы доктора веба:



Пипец! Сам антивирус регулярно создает опасные ситуации, во время которых исполняются уязвимые части кода, которые могут привести к security issues!
На кой ляд доктор веб, при обновлении своих баз, использует эту библиотеку, которая позволяет использовать справку к программе в формате CHM?
При этом, перед тем как загрузить эту библиотеку и вызвать из нее функцию (уж не HtmlHelp() ли?), Доктор веб проверяет, не приаттачен ли к событию загрузки этой библиотеки дебаггер (!):
проверяется на существование вот этот ключ реестра:
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\hhctrl.ocx

Кажется, вот зачем апдейтер доктора веба постоянно лезет в реестр и проверяет этот ключик при выкачивании обновлений:
Evil can be done with the Image File Execution Options key. Malware can install themselves as the "debugger" for a frequently-run program (such as Explorer) and thereby inject themselves into the execution sequence.
(короче говоря, хочет быть уверенным, что скачанный файл с базами не перехвачен и не подменен вирусом... Только я ума не приложу, как можно с помощью hhctrl.ocx выкачивать апдейты из интернета..).

В процессе разборок было выяснено, что вот такой вот эксплоит на базе HHCTRL (сохранить отмеченное как sp2rc.htm в файл) доктором вебом с последними базами не опознается как опасный (вообще DrWeb не реагирует!), тогда как касперский его ловит сразу же. Касперский рулит.
Кстати, даже движок этого блога не допускает приведения текста этого эксплоита непосредственно в тексте записи (наверное тоже догадывается что этот код вредоносный).

Итак, что мы имеем? По непонятным причинам Dr.Web использует hhctrl.ocx (CLSID ADB880A6-D8FF-11CF-9377-00AA003B7A11) для того, чтобы скачивать апдейты. При этом случается неизвестная ошибка 1903 с модуле hhctrl, что подозрительно. Также мы знаем, что именно этот модуль hhctrl, будучи внедренным в html (который, возможно, скачивается в качестве апдейтов и потом парсится), позволяет закоспромизить систему...

01.07.2009

Debian 5.0.0 kernel failure


Мой Debian 5.0.0, работающий под VmWare, после загрузки оконного менеджера показывает вот такую вот картинку. Версия ядра, идущая в комплекте с этим дистрибутивом - 2.6.26. Эта картинка ни на что не влияет - система работает как ни в чем ни бывало. Отправил этот упс разработчикам, нажав на кнопку Yes. Надо будет ради интереса посмотреть в dmesg на предмет того, что там было не так.
Скачал исходники ядра 2.6.30, пересобрал с абсолютно идентичным конфигом (как и для 2.6.26), ядро поставилось и этот kernel oops больше не появляется, наступило щастье :)
Надо будет еще раз пересобрать ядро, включив в нем оптимизацию под Pentium M (процессор хост-машины), и еще надо отключить SMP, ибо у меня не многопроцессорная система. Ядро из дистрибутива идет с поддержкой SMP, что совершенно лишнее.

UPD: Посмотрел, что пишет dmesg:

[ 0.000000] WARNING: strange, CPU MTRRs all blank?
[ 0.000000] ------------[ cut here ]------------
[ 0.000000] WARNING: at arch/x86/kernel/cpu/mtrr/main.c:696 mtrr_trim_uncached_memory+0x178/0x183()
[ 0.000000] Modules linked in:
[ 0.000000] Pid: 0, comm: swapper Not tainted 2.6.26-1-686 #1
[ 0.000000] [] warn_on_slowpath+0x40/0x66
[ 0.000000] [] _spin_lock_irqsave+0x16/0x2f
[ 0.000000] [] _spin_unlock_irqrestore+0xd/0x10
[ 0.000000] [] release_console_sem+0x173/0x18c
[ 0.000000] [] vprintk+0x2d2/0x2de
[ 0.000000] [] mtrr_wrmsr+0xf/0x2e
[ 0.000000] [] printk+0x14/0x18
[ 0.000000] [] mtrr_trim_uncached_memory+0x178/0x183
[ 0.000000] [] setup_arch+0x254/0x6bb
[ 0.000000] [] printk+0x14/0x18
[ 0.000000] [] start_kernel+0x62/0x2d7
[ 0.000000] =======================
[ 0.000000] ---[ end trace 4eaa2a86a8e2da22 ]---

По информации kerneloops.org, эта проблема (BIOS bug (often in VMWare) where the MTRR's are set up incorrectly or not at all) на втором месте по частоте воспроизведения.
Ссылка на отправленный мной упс разработчикам: вот.
Но у меня этой проблемы уже нет в новом ядре.

30.06.2009

Сотовый телефон как FXO gateway

Вот тут написаны интересные вещи: как настроить астериск так, чтобы он мог звонить "наружу" через сотовый телефон, подключенный к нему по блютуфу.
Эта технология открывает неограниченные возможности в deployment решений на базе астериска - можно поднять телефонный сервер с выходом на межгород даже там, где нет PSTN - лишь бы сотовый мог поймать какую-нибудь сеть.

Для создания второго FXO порта придется использовать еще один USB Bluetooth адаптер, поскольку телефоны не могут вешаться все на один блютуф.

Таким образом можно и дома поднять телефонный сервер с IVR, присоединив свой собственный сотовый к астериску. Причем совершенно бесплатно! Уже хочу :)

29.06.2009

Смешались в кучу кони, люди

Показательная статья:

И еще об одной тенденции. в последнее время много говорят о программных IP-УАТС с открытым исходным кодом (open source). Самая известная из них – система Asterisk, но есть и масса других: ASTLinux, FreePBX, Trixbox, Freeswitch, Call Weaver… Однако надо четко понимать, что к бесплатному софту придется покупать еще платы, например для подключения телефонов и выхода в ТфОП. Собрать такой конструктор можно и самому – было бы время... И все-таки, на мой взгляд, системы типа Asterisk еще сыроваты для применения в качестве серьезных корпоративных решений. Им недостает проверенных средств отказоустойчивости и управляемости, что очень важно для солидных заказчиков.


Пока пишутся такие статьи - будет хлеб у нас :) Слова выделены мной.
(В перечислении с типом "программные IP-УАТС с открытым исходным кодом" присутствуют: операционная система и две веб-морды, которые не являются IP-УАТС. Показателен так же пассаж про "надо покупать платы" и "конструктор").