пятница, 12 декабря 2008 г.

FreeSWITCH, факсы

Итак, кое-что о факсах. Какими бы бурными темпами ни двигался интернет в каждый дом, факс остается весьма важным средством передачи документов. В протоколах VoIP этому моменту уделено внимание, специально для факсов создан протокол T.38.

Временное отсутствие T.38 в FreeSWITCH я не считаю большой проблемой - на сегодняшний день лучше всего передаются факсы при использовании кодека G.711. T.38 будет реализован в обозримом будущем, а пока я опишу то, что уже есть.
В FreeSWITCH был добавлен модуль mod_fax. Он предоставляет две функции - txfax и rxfax. На текущий момент поддерживается протокол T.30. Пример из wiki:

<extension name="fax">
<condition field="destination_number" expression="^fax$">
<action application="answer" />
<action application="playback" data="silence_stream://2000"/>
<action application="rxfax" data="/usr/local/freeswitch/fax/${caller_id_number}-${strftime(%Y-%m-%d-%H-%M-%S)}.tiff"/>
<action application="hangup"/>
</condition>
</extension>



Обнаружение передачи факса.

FreeSWITCH предоставляет специальную функцию для обнаружения тоновых сигналов в голосовом потоке - tone_detect.

<extension name="5555555">
<condition field="destination_number" expression="^(5555555)$"/>
<action application="tone_detect" data="fax 1100 r +5000 transfer fax XML default"/>
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="ivr" data="main"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="fax">
<condition field="destination_number" expression="^fax$">
<action application="answer" />
<action application="playback" data="silence_stream://2000"/>
<action application="rxfax" data="/usr/local/freeswitch/fax/${caller_id_number}-${strftime(%Y-%m-%d-%H-%M-%S)}.tiff"/>
<action application="hangup"/>
</condition>
</extension>



А можно поставить обнаружение на всю сессию:

<!-- continue="true" - означает, что надо продолжить выполнение номерного плана после этого пункта -->
<extension name="fax_tone_detect_permanent" continue="true">
<!-- ловим любые звонки, так как .* означает любое кол-во любых символов -->
<condition field="destination_number" expression="^.*$"/>
<!-- ставим обнаружение тона 1100 со стороны звонящего(r) бесконечное время(0)
В случае обнаружения тона передаем (transfer) на обработку в "default" номерной план
с номером "fax"-->
<action application="tone_detect" data="fax 1100 r 0 transfer fax XML default"/>
</condition>
</extension>


Таким образом прием факсов в FreeSWITCH организовать достаточно легко. Надеюсь реализация T.38 не заставит себя долго ждать.

Слабым местом пока остается поддержка кодеков. Все заинтересованные уже знакомы с патентной системой США - практически все дистрибутивы в нашей стране имеют "поддержку кодеков из коробки".
G.729, G.723, AMR сейчас поддерживаются только в режиме без перекодирования. То есть использовать с этими кодеками голосовую почту, голосовые меню, запись разговоров затруднительно.

Заколдованый круг - пока FreeSWITCH не поддерживает кодеки он не очень интересен у нас. А пока он не очень интересен - кодеки реализовывать некому.

воскресенье, 23 ноября 2008 г.

Google-группы по kerberos и Freeswitch

Я создал две новых google-группы для обсуждения вопросов, связанных с kerberos и freeswitch. Просьба все свои вопросы задавать там - формат комментариев к блогу не очень хорошо подходит для подобных обсуждений.


1. ru-kerberos
2. freswitch-ru

четверг, 13 ноября 2008 г.

plasma-mediacontroller

Почему то Am4rok, из Ubuntu 8.10, у меня не работает. Не разбирался, ведь те, кто следят за блогом, знают - теперь есть биндинги под python! Сделал себе свой велосипед - plasma-mediacontroller. Он конечно не так здорово смотрится, но главное он у меня работает.

Если кому то будет интересен, можно продолжить разработку. Сейчас он работает только с Amarok, но нет ничего сложного в добавлении поддержки практически любого медиаплеера. Ведь большинство из них реализует стандартный интерфейс DBus для медиаплееров.

Кому интересно - берите тут. В первой записи о plasma-python есть инструкции по установке плазмоида.

понедельник, 10 ноября 2008 г.

8.10, dkms, nvidia, btrfs

Итак, раз уж в рубунтнете поднялась мода описывать свой опыт по общению с разного вида "козлами" (у кого насколько переводческой фантазии хватит), присоединюсь к этому движению. Да, я тоже обновился до 8.10, чему очень рад. Собственно рад я в основном новой фишке - DKMS.

Некоторое время у меня задурил драйвер Nvidia - я особо не разбирался конечно, и с налету решить не удалось - вместо модуля nvidia_new, который новой версии, грузился старый nvidia. В 8.10 эту часть работы с модулями заменили на DKMS.

Итак, а что это? А это такая система автоматической сборки модуля под ваше ядро. Предположим поставили вы себе 2.6.28, а DKMS тут как тут - тут же соберет модуль и установит его под новое ядро. То есть думать о том, что вы там такого стороннего в ядро напихали, каждый раз совершенно не надо.

И тут у нашего повествования этакий плавный переход. Связующее звено у двух повествований все тот же DKMS. Я экспериментировал с Btrfs, а так как это новая файловая система, планируемая (авторами, когда нибудь : )) ) к включению в ядро, и вообще чтобы корень на нее помещать, то представляет собой она собственно модуль ядра. А модулями ядра у нас теперь ведает - DKMS.

Итак, чтобы вы тоже приобщились к 21 веку, и познали прелесть COW (copy-on-write) систем, дам вам указание верного пути, то есть dkms.conf.
Стягиваем исходники модуля ядра и кладем их в /usr/src/btrfs-0.16 (ну вот такая вот у нас текущая версия). В том же каталоге создаем dkms.conf следующего содержания:

MAKE[0]=make
BUILT_MODULE_NAME[0]=btrfs
DEST_MODULE_LOCATION[0]="/kernel/fs/btrfs"
PACKAGE_NAME="btrfs"
PACKAGE_VERSION="0.16"
CLEAN="make clean"
AUTOINSTALL="yes"


Далее следует серия команд для запуска модуля в работу:

root:host~# dkms add -m btrfs -v 0.16
root@rni-15:~# dkms add -m btrfs -v 0.16

Creating symlink /var/lib/dkms/btrfs/0.16/source ->
/usr/src/btrfs-0.16

DKMS: add Completed.
root:host~#
root:host~# dkms build -m btrfs -v 0.16

Kernel preparation unnecessary for this kernel. Skipping...

Building module:
cleaning build area....
make KERNELRELEASE=2.6.27-7-generic............
cleaning build area....

DKMS: build Completed.

root:host~# dkms install -m btrfs -v 0.16
Running module version sanity check.

btrfs.ko:
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/2.6.27-7-generic/updates/dkms/

depmod........

DKMS: install Completed.

root:host~# modprobe btrfs

Отлично, теперь скачайте утилиты для работы с btrfs и посмотрите, что вам может дать эта система. А может она вам дать снимки, тома, контрольную сумму всех блоков, raid различных уровней и многое другое. Работает гораздо живее zfs которая на fuse. Но не стоит пока размещать на ней /home or /.

Кстати о снимках, если вы пересилите себя, и доберетесь до самого первого поста этого блога, то увидите там бесподобную идею поставить /etc/ под контроль версий. Идея умерла с того момента, как я познакомился с концепциями zfs и btrfs - это наше файловое будущее.

Подробности, одни из, тут.

четверг, 30 октября 2008 г.

Мой первый плазмоид

Я поклонник KDE и python. С удивлением я, как и многие другие, смотрел на KDE 4.0. После вылизанного 3.5 это было конечно страшно. Особенно мне не хватало kicker и его "кикоидов". Но время идет, проект продолжает развиваться невзирая на возню анонимов на веб просторах, и теперь наконец то есть привязки plasma для python, а значит теперь я сам себе автор плазмоидов.

Мой первый плазмоид страшно кособок, но тем не менее показателен. Итак, по устоявшейся традиции среди Qt-шников, будем делать свой браузер. Правда этот, удивительный своей неординарностью, экземпляр, мы встроим прямо в рабочий стол.

Этот код просто вставьте в командную строку, он создаст структуру каталогов, файлы, соберет пакет, и установит его для текущего пользователя.


mkdir -p wwwv/contents/code
cd wwwv
cat > metadata.desktop << EOF
[Desktop Entry]
Encoding=UTF-8
Name=WWW viewer
Type=Service
ServiceTypes=Plasma/Applet
X-Plasma-API=python
Icon=chronometer

X-KDE-PluginInfo-Author=Mikhail Krivushin
X-KDE-PluginInfo-Email=mkrivushin@yandex.ru
X-KDE-PluginInfo-Name=plasma-wwwv
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://deepwalker.blogspot.com
X-KDE-PluginInfo-Category=Tests
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
EOF

cat > contents/code/main.py << EOF
#! /usr/bin/python

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtWebKit
from PyKDE4.kdecore import *
from PyKDE4.kdeui import *
from PyKDE4.plasma import Plasma
import plasma

class PyWWWvApplet(plasma.Applet):
def __init__(self,parent,args=None):
plasma.Applet.__init__(self,parent)

self.url = None
self.clicked = QPoint()

def init(self):
KGlobal.locale().insertCatalog("www")

self.setHasConfigurationInterface(False)
self.setAspectRatioMode(Plasma.IgnoreAspectRatio)

self.dialog = None

self.theme = Plasma.Svg(self)
self.theme.setImagePath("widgets/background")
self.theme.setContainsMultipleImages(False)
self.theme.resize(self.size())

self.webview = Plasma.WebContent()
self.mlayout = QGraphicsLinearLayout(Qt.Vertical)
self.eline = Plasma.LineEdit()
self.mlayout.addItem(self.eline)
self.mlayout.addItem(self.webview)
self.setLayout(self.mlayout)

self.connect(self.eline,SIGNAL('returnPressed()'),self.open_page)

self.webview.setUrl(KUrl('http://127.0.0.1/'))
self.webview.update()

def open_page(self):
page = self.eline.text()
#print "Go to %s"%page
self.webview.setUrl(KUrl(page))
self.webview.update()

def shape(self):
if self.theme.hasElement("hint-square-clock"):
return plasma.Applet.shape(self)
path = QPainterPath()
path.addEllipse(self.boundingRect().adjusted(-2, -2, 2, 2))
return path


def constraintsEvent(self, constraints):
if constraints & Plasma.SizeConstraint:
self.resize(self.size())

def CreateApplet(parent):
return PyWWWvApplet(parent)
EOF

zip -r ../wwwv.zip .

plasmapkg -i wwwv.zip


Конечно же надо поставить соответствующие привязки. Так как я уже на 8.10, то просто сделал aptitude install python-plasma.

Далее располагайте плазмоид на рабочем столе и удивляйтесь мощи моего гения. Теперь же я, пожалуй, отправлюсь спать. А вы, дорогие мои, утомляйте неутомимый google бесчисленными запросами - "plasma python qt webkit" в поисках ответа на вопрос - а как же сделать, чтобы оно использовало прокси?

среда, 1 октября 2008 г.

FreeSWITCH, кластеризация

Вопрос был задан в одном из комментариев - поддерживает ли FS кластеризацию? Этот краткий пост будет ответом.

Да, в FS это заложено изначально. Если вы прочитаете историю его создания, то там написано, что автору кластеризация требовалась. Поэтому в архитектуре FS такие возможности заложены.

Всю информацию FS хранит в БД, к которой осуществляется доступ через ODBC. Конфигурацию FS может забирать через xml_curl. Таким образом все данные и настройки легко распределяются на несколько серверов.

среда, 17 сентября 2008 г.

FreeSWITCH+Django

FreeSWITCH предоставляет замечательный механизм - xml_curl. Этот модуль может забирать номерной план, пользователей и даже конфигурацию через http запросы.
Работает весьма просто, например так:

# cat /opt/freeswitch/conf/autoload_configs/xml_curl.conf.xml
<configuration name="xml_curl.conf" description="cURL XML Gateway">
<bindings>
<binding name="fs2web_user_fetcher">
<param name="gateway-url" value="http://localhost:8000/get/user/" bindings="directory">
</binding>
</bindings>
</configuration>


# cat /opt/freeswitch/conf/autoload_configs/modules.conf.xml
...
<load module="mod_xml_curl"/>
...



Теперь FS будет слать тонну информации методом POST на web сервер по указаному адресу и ждать в ответ описание пользователя в стандартном xml:


~$ wget http://127.0.0.1:8000/get/user/?sip_auth_username=3000 -O -
--23:36:28-- http://127.0.0.1:8000/get/user/?sip_auth_username=3000
=> `-'
Устанавливается соединение с 127.0.0.1:8000... соединились.
Запрос HTTP послан, ожидание ответа... 200 OK
Длина: нет информации [text/html]

[<=> ] 0 --.--K/s
<document type="freeswitch/xml">
<section name="directory">
<domain name="">
<user id="3000" mailbox="3000">
<params>
<param name="password" value="1234"/>
<param name="vm-password" value="3000"/>
</params>
<variables>
<variable name="accountcode" value="3000"/>
<variable name="user_context" value="public"/>
<variable name="effective_caller_id_name" value="Mihail Krivushin"/>
<variable name="effective_caller_id_number" value="3000"/>
</variables>
</user>
</domain>
</section>
</document>
[ <=> ] 608 --.--K/s

23:36:29 (1.91 MB/s) - `-' сохранён [608]



Ну и напоследок, мне кажется не совсем бесполезная ссылка на пример готового сервера на Django. Клонируйте, и затем поправьте settings.py. Пользователей можно заводить через стандартный административный интерфейс Django. Администратор - "admin", пароль - "kuku".