Monday, September 17, 2012

Предача Clid при переводе звонка

Так получилось, что необходимость это сделать переросла из "было бы неплохо" до "надо сделать".
Начальные условия: телефоны делают transfer не средствами станции, а своими. Тот, кому звонят должен как-то увидеть, что звонок переводится.
Сделано для варианта вызова простым Dial, но с очередью проблем быть не должно, просто другая переменная.

Смысл такой: при ответе вызывается макрос, которые заносит номера пары звонящий/ответивший в базу. При завершении разговора эта запись стирается. При вызове ответившего по второй линии (что и делается при переводе) его номер заменяется на номер звонящего (можно с модификациями, типа Перевожу ХХХ).

При использовании очередей также можно использовать этот метод, но надо доработать  macro-StoreCLID на предмет анализа не DIALEDPEERNUMBER, а MEMBERINTERFACE, или, в в случае перехвата - BRIDGEPEER. Только предварительно их обработав типа
...
exten => s,n,Set(AnsweredPeer=${CUT(BRIDGEPEER,/,2)})
exten => s,n,Set(AnsweredPeer=${CUT(AnsweredPeer,-,1)})
...
...
exten => s,n,GoToIf($["${DIALEDPEERNUMBER}x" != "x"]?DPNPresent)
exten => s,n,Set(DIALEDPEERNUMBER=${CUT(MEMBERINTERFACE,/,2)})
exten => s,n(DPNPresent),n,NoOp("No DIALEDPEERNUMBER present...")
...
[macro-StoreCLID]

exten => s,1,NoOp(Answered is = ${DIALEDPEERNUMBER})
exten => s,n,Set(DB(CLIDT/${DIALEDPEERNUMBER})=${ExternalCLID})


[IncomingCallContext]
...
exten => s,n,Set(__ExternalCLID=${CALLERID(num)})
exten => s,n,Dial(${ALLOP},20,M(StoreCLID))
...
exten => h,1,NoOp(${DB_DELETE(CLIDT/${DIALEDPEERNUMBER})})

[InternalCallsContext]

exten => _X,1,Set(TransferredCLID=${DB_DELETE(CLIDT/${CALLERID(num)})})
exten => _X,n,GotoIf($[ "x${TransferredCLID}" = "x"]?ClearCall)
exten => _X,n,Set(CALLERID(num)=${TransferredCLID})
exten => _X,n(ClearCall),.....



При использовании очередей также можно использовать этот метод, но надо доработать  macro-StoreCLID на предмет анализа не только DIALEDPEERNUMBER, а MEMBERINTERFACE, или, в в случае перехвата - BRIDGEPEER. Только предварительно их обработав типа

...
exten => s,n,Set(AnsweredPeer=${CUT(BRIDGEPEER,/,2)})
exten => s,n,Set(AnsweredPeer=${CUT(AnsweredPeer,-,1)})

...
...
exten => s,n,GoToIf($["${DIALEDPEERNUMBER}x" != "x"]?DPNPresent)
exten => s,n,Set(DIALEDPEERNUMBER=${CUT(MEMBERINTERFACE,/,2)})

exten => s,n(DPNPresent),n,NoOp("No DIALEDPEERNUMBER present...")
...

Вообще таким образом можно получить номер ответившего пира в экстеншене h, что позволяет более правильно организовать записи.

Wednesday, August 22, 2012

VmWare vCenter Converter + info.owner ошибка

Начал переносить машины на новую виртуалку. Причем версия ESXi перешла с 3.5 на 5.0
При использовании VmWare vCenter Converter регулярно на последнем этапе получаю информацию про некорректный info.owner
Машина: WinXPPro SP3, не в домене
Как решать:
1. Установить Converter в режиме Client-Server
2. Завести отдельного пользователя с админскими правами
3. При запуске подключаться не к local server, а по ip + login/password, соответственно localhost, а логин и пароль - новосозданного пользователя.


Friday, April 27, 2012

Учим PHP + Asterisk = Автообзвон

Ввиду некоего стопора в изучении Астериска приходится копать исключительно вглубь. На этот раз мои кривые руки дошли до php.
А так как не раз спрашивали функцию, и вообще это еще тот холивар, то я решил написать систему автозвонилки да так, чтобы из браузера можно было юзать.
Скажу сразу, это первый проект на php, который я пишу. Поэтому говнокод неизбежен.
Также скажу, что использовать его  в продакшене - убийство. Ибо код не факт, что отлажен, так еще и звонит пока только по очереди, никакой мультилинейности. Может, будет потом.


Также небольшой дисклеймер:
Делалось для себя, как учебный проект, поэтому с документацией и комментами плохо. Спамерство - зло, поэтому особо расписывать принципы не буду, в коде все понятно.

Говнокод

upd: Версия 0.02 Добавил мультилинейность. Теперь можно спамить в 30 потоков.

Tuesday, April 24, 2012

Замена r8169 на r8168 или глюки сетевых карт на Linux

Суть в чем - есть сервак с 2мя гигабитными карточками 
Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 02).
Нагрузка - порядка 2000 звонков в сутки, в пиковые часы - 10-15 одновременных звонков (alaw). Вроде и немного, просто на нем же лежит FTP на который складываются записи. Так вот, повадился сервер этот пропадать из сети, причем в логах - все отлично, но просто не пингуется и все. Периодичность - где-то раз в 2-3 дня. Помогает только перезагрузка, но при этом локально на консоль попасть можно.
Проблема оказалась известной, просто как-то на сетевую обратили внимание не сразу, искали другие причины. А проблема в кривости реализации драйвера r8169. Падает он под большими нагрузками. Совет один - заменить его на r8168.


Проверить, какой драйвер используется можно через 


lsmod

А заменять его на Debian 6.0 так:

aptitude install build-essential linux-headers-`uname -r`
 
Потом получить исходный код:
http://download.hetzner.de/drivers/r8168-8.028.00.tar.bz2
http://code.google.com/p/r8168/
 
tar xjf r8168-8.ХХХ.00.tar.bz2
cd r8168-8.ХХХ.00
make all
 
depmod -a
echo "blacklist r8169" >> /etc/modprobe.d/blacklist.conf
echo "r8168" >> /etc/initramfs-tools/modules
update-initramfs -v -u -k `uname -r`
 
reboot 

Monday, March 12, 2012

Система совместной работы PHProjekt

Возникла проблема учета оборудования, которое находится в ремонте, тесте... Да и вообще чтобы сотрудники были в курсе, что вообще происходит на работе. А то тех. отдел в своем соку, менеджеры в своем, а потом куча криков, что кому и когда обещал. Такая себе корпоративная записная книжка.

До этого пользовались phpcollab, но она как-то с русским не особо. Точнее, дружит, но не utf8. Смотрел еще на некоторые, на тот же Microsoft Project, но нужно было веб-ориентированное.

В общем, выбор пал на PHProjekt. На данный момент стабильная версия 6.0.6, ее и поставил на отдельной виртуалке.

В принципе, все это описано в руководстве и на сайте, но как-то все в разных местах.

Система - Debian Lenny 6.0

Собсно, ставим все необходимое:

# apt-get install mysql-server mysql-client apache2 php5 libapache2-mod-php5 php5 php5-mysql php5-gd php5-ps php5-cgi zlibc

Создаем базу и пользователя для MySQL:

# mysql -u root -p
      mysql> CREATE DATABASE phprojekt;
      mysql> GRANT ALL PRIVILEGES ON phprojekt.* TO 'phprojekt'@'localhost'
      mysql> IDENTIFIED BY 'password' WITH GRANT OPTION;

Создаем каталог для некоторых данных :) Туда сохраняются файлы, кэш:

# chmod -R 0755 /var/www
# mkdir /srv/private/phprojekt
#chmod -R 0770 /srv/private/phprojekt/

Копируем phprojekt в папку и запускаем в браузере настройку.

Теперь к некоторой настройке: настраиваем оповещение через мыло. Я завел специальный ящик на ЖМыле, чтобы было проще фильтры настраивать.

/var/www/configuration.php

mailTransport = 0

smtpAuth     = "login"
smtpUser     = "@gmail.com"
smtpPassword = ""
; You may specify SSL and Port, if the SMTP server of your choice requires them.
smtpSsl      = "tls"
smtpPort     = "587"

front.notificationEnabledByDefault = true


Вот, собственно и все. Дальше чисто вопрос настроек. Я прибил диаграммы Гранта (ну не нужны они мне), оставил по самому минимуму. Зато теперь если кто-то что-то делает, об этом сразу узнают все участвующие в проекте люди.

Система простая, как угол дома. Вопрос в привыкании, да и уведомления очень приятны. Хотя и часть проектов по привычке в ГуглоДоках ведется.

В случае всяческого ремонта - очень полезно. Не звонить в техотдел и не вспоминать, кто, что, когда, и починил ли вообще....

Friday, July 8, 2011

Transparent Squid + LightSquid на отдельной машине.

Появилась задачка, посмотреть куда же ходят любимые сотрудники вместо работы, ну и увеличить скорость загрузки фишек и прочих айфанов. Но при этом не менять структуру сети и не прописывать прокси в браузере.
Решение - Squid в режиме прозрачности и LightSquid для отчетов. Крутиться это все добро будет на виртуалке. Поставим туда Debian 6.

1. Поднимаем Squid

apt-get install squid

На данный момент в репозитариях лежит 2.7 версия, что меня вполне устроила.

/etc/squid/squid.conf

acl all src all
acl localhost src 127.0.0.1/32
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32
acl localnet src адрес локальной сети

http_access allow localhost
http_access allow localnet

icp_access allow localnet
icp_access deny all

http_port 3128 transparent

hierarchy_stoplist cgi-bin ?

cache_dir ufs /var/spool/squid 80000 16 256

access_log /var/log/squid/access.log squid

refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880
refresh_pattern .

acl shoutcast rep_header X-HTTP09-First-Line ^ICY.[0-9]
upgrade_http0.9 deny shoutcast

acl apache rep_header Server ^Apache
broken_vary_encoding allow apache

extension_methods REPORT MERGE MKACTIVITY CHECKOUT

hosts_file /etc/hosts

memory_pools_limit 768 MB

coredump_dir /var/spool/squid

2. Настраиваем правила.
Мне повезло, у меня роутер, который позволяет вводить команды напрямую.

Router part:
iptables -t mangle -A PREROUTING -j ACCEPT -p tcp --dport 80 -s адрес Squid
iptables -t mangle -A PREROUTING -j MARK --set-mark 3 -p tcp --dport 80
ip rule add fwmark 3 table 2
ip route add default via адрес Squid dev интерфейс lan table 2

Я до конца не разобрался в этих командах, честно - просто брал примеры из документации. Плюс - при такой схеме сохраняются IP адреса машин, сделавших запрос.
В таком случае все запросы на 80-й порт будут перенаправляться на 80-й порт нашего Squid. В таком случае на squid тоже надо сделать перенаправление:

Squid part:
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128

Перезапускаем Squid и роутер. После этого все должно работать. Проверить - просто просмотреть файл /var/log/squid/access.log на наличие записей.

3. Настраиваем отчеты:

apt-get install lighttpd

/etc/lighttpd/lighttpd.conf

server.modules = (
"mod_access",
"mod_alias",
"mod_compress",
"mod_redirect",
"mod_cgi"
# "mod_rewrite",
)
server.port = 8080
server.document-root = "/var/www"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "www-data"
server.groupname = "www-data"

index-file.names = ( "index.php", "index.html",
"index.htm", "default.htm",
" index.lighttpd.html","index.cgi" )

url.access-deny = ( "~", ".inc" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

include_shell "/usr/share/lighttpd/use-ipv6.pl"

dir-listing.encoding = "utf-8"
server.dir-listing = "enable"

compress.cache-dir = "/var/cache/lighttpd/compress/"
compress.filetype = ( "application/x-javascript", "text/css", "text/html", "text/plain" )

include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"

#### CGI module
cgi.assign = ( ".pl" => "/usr/bin/perl",
".cgi" => "/usr/bin/perl" )

Скачиваем и настраиваем LightSquid по его инструкции, благо, она очень простая.

Только не забудьте поправить пути в lightsquid.cfg.

Перезапускаем lighttpd и получаем страничку с отчетами на порту 8080.

Tuesday, March 1, 2011

Немного подправленный Asterisk n-way call

Было найдено тут.

Немного копипасты:

http://www.voip-info.org/wiki/view/Asterisk+n-way+call+HOWTO
Надо просто немного подправить скрипт..
теперь инициатор собирает конференцию (и не вываливается!!!), все кто есть в конференции тоже могут приглашать народ, если остается один человек - ему играется музыка ождания и он может начать приглашать людей!

в extensions.conf
[default]
exten => _XXX,1,Set(DYNAMIC_FEATURES=nway-start)
exten => _XXX,n,Dial(SIP/${EXTEN})

[dynamic-nway]
exten => _XXX,1,Answer
exten => _XXX,n,Set(CONFNO=${EXTEN})
exten => _XXX,n,Set(MEETME_EXIT_CONTEXT=dynamic-nway-invite)
exten => _XXX,n,Set(DYNAMIC_FEATURES=)
exten => _XXX,n,MeetMe(${CONFNO},pdMX)
exten => _XXX,n,Hangup

[dynamic-nway-invite]
exten => 0,1,Read(DEST,dial,,i)
exten => 0,n,Set(DYNAMIC_FEATURES=nway-inv#nway-noinv)
exten => 0,n,Dial(Local/${DEST}@dynamic-nway-dest,,g)
exten => 0,n,Set(DYNAMIC_FEATURES=)
exten => 0,n,Goto(dynamic-nway,${CONFNO},1)
exten => i,1,Goto(dynamic-nway,${CONFNO},1)

[dynamic-nway-dest]
exten => _XXX,1,Dial(SIP/${EXTEN})

[macro-nway-start]
exten => s,1,Set(CONFNO=${FindFreeConf()})
exten => s,n,ChannelRedirect(${BRIDGEPEER},dynamic-nway,${CONFNO},1)
exten => s,n,Read(DEST,dial,,i)
exten => s,n,Set(DYNAMIC_FEATURES=nway-inv#nway-noinv)
exten => s,n,Dial(Local/${DEST}@dynamic-nway-dest) #УБИРАЕМ ОПЦИЮ "g"!!!!
#exten => s,n,Set(DYNAMIC_FEATURES=) #коментим, ибо не работает
#exten => s,n,Goto(dynamic-nway,${CONFNO},1) #коментим, ибо не работает

[macro-nway-ok]
exten => s,1,ChannelRedirect(${BRIDGEPEER},dynamic-nway,${CONFNO},1)
exten => s,2,Set(DYNAMIC_FEATURES=) # добавляем
exten => s,3,Goto(dynamic-nway,${CONFNO},1) # добавляем

[macro-nway-notok]
exten => s,1,SoftHangup(${BRIDGEPEER})
exten => s,2,Set(DYNAMIC_FEATURES=) # добавляем
exten => s,3,Goto(dynamic-nway,${CONFNO},1) # добавляем


ну и в features.conf все, как в ссылке:
[applicationmap]
nway-start => *0,caller,Macro,nway-start
nway-inv => **,caller,Macro,nway-ok
nway-noinv => *#,caller,Macro,nway-notok