= Skype for Asterisk Automation and User Interface = [[TOC]] [[Image(skype-asterisk.png,right)]] This product is contributed to the Asterisk Community by [http://pbxware.ru PBXWare.ru]. It is distributed under the GNU GPL. Asterisk Skype GUI is a lightweight product pluggable into any asterisk installation. Its purpose is to automate calls to/from Skype and provide easy to use WEB interface to manage skype callers. The product was inspired by [http://ssokol.blogspot.com/2009/09/automatic-asterisk-extensions-for-skype.html Steven Sokol], product manager at Digium. Skype for Asterisk channel license is available directly from [http://store.digium.com/productview.php?product_code=1SFA0001 Digium] or from [mailto:request@pbxware.ru?subject=SFA%20order us]. Screenshots:[[BR]] [[Image(accounts.png,10%)]] [[Image(modify_account.png,10%)]] [[Image(add_account.png,10%)]] == Features == * Easy to install. * Works with any any Asterisk version. * Ability to call Skype users by number extension. * Automatic generation of extensions for new skype callers. * Lightweight WEB 2.0 interface to manage Skype callers and corresponding accounts (written in [http://en.wikipedia.org/wiki/Lua_(programming_language) Lua]). == Installation == Installation is easy. The installation package comes with all dependencies included as sources. When you invoke install script it unpacks, compiles and installs all the deps to the specified directory. See below for deetails. === Dependencies === * System libs and headers: readline (readline-devel), libtool.(libtool) * SQLite3 and SQLite3 headers (sqlite3-devel) * unixODBC and SQLite3 ODBC driver * Asterisk :-) * WEB server to execure CGI: Nginx / Apache / Lighttp === Download Skype for Asterisk GUI === ==== Installation of pre-compiled packages ==== * For x32 platforms (ordinary PC) you should get file called ''asterisk-chan_skype-gui-0.1-x32-bin.tar.gz'' from the [http://forge.asterisk.org/gf/project/skype_chan_gui/frs/?action=index Asterisk Forge]. * For x64 pltaforms you should get file called ''asterisk-chan_skype-gui-0.1-x64-bin.tar.gz'' from the [http://forge.asterisk.org/gf/project/skype_chan_gui/frs/?action=index Asterisk Forge]. Unpack the downloaded archive to /var/www/skype/. If you use another target directory see config.lua and adjust path variables. The default configuration file assumes that product URL is /skype/ and it's located in /var/www/skype. See WEB server configuration section for details. ===== config.lua ===== {{{ prefixUrl="/skype" tmpDir = "/var/www/skype/cgi-bin/tmp" sessionsDir = "/var/www/skype/cgi-bin/sessions" dsn = "sqlite3://asterisk:df37hslkv@localhost/db/data.db" for _, path in ipairs{"/var/www/skype/lib/";"/var/www/skype/share/"} do package.cpath = (package.cpath or "?.so")..";"..path.."?.so" package.path = (package.path or "?.lua")..";"..path.."?.lua;"..path.."?/init.lua" end }}} ==== Installation from sources ==== If by any reason you cannot or don't want to use pre-compiled packages you can compile all from sources. Download ''asterisk-chan_skype-gui-0.1-src-tar.gz'' from the [http://forge.asterisk.org/gf/project/skype_chan_gui/frs/?action=index Asterisk Forge]. Save in temporary folder /tmp/ and unpack. Edit install.sh and change AST_USER/AST_GROUP to unix account under asterisk process runs and HTTP_GROUP to unix group HTTP server runs under (Asterisk and WEB server share database file). By default ''asterisk'' and ''apache'' are used. Next run the installation script passing the path to the WEB root folder as a parameter. Here we use /var/www/skype: {{{ snowflake tmp # snowflake tmp # tar zxf asterisk-chan_skype-gui-0.1-src.tar.gz snowflake tmp # cd asterisk-chan_skype-gui-0.1-src snowflake asterisk-chan_skype-gui-0.1-src # ./install.sh /var/www/skype Compiling Lua... Compiling Lua Datafilter... Compiling Lua Socket... Compiling Lua Posix... Compiling Lua SQL... Unpacking Luv... Unpacking Skype GUI... snowflake asterisk-chan_skype-gui-0.1 # }}} If everything is OK, let go to WEB server configuration. If you get any errors, please find in working directory the file called '''build.log''' and send it to us (tech(at)pbxware.ru) with subject "Skype for Asterisk GUI installation error". === Configure WEB server === ==== Virtual Server Configuration ==== We use the following configuration for apache HTTP server. We use virtualhost and HTTPS. You should change domain.com to your real domain name if you do the same. But you can adjust the following configuration file to meet your requirements (use directory and not virtual host, or do not use https or password authentication. See apache docs for details. ''Note! We set urlPrefix="" in config.lua, as skype gui locate at the root of WEB server.'' {{{ ServerName skype.domain.com DocumentRoot /var/www/skype/htdocs CustomLog /var/log/apache2/skype.domain.com-access.log combined ErrorLog /var/log/apache2/skype.domain.com-error.log LogLevel warn SSLEngine on SSLCertificateKeyFile /etc/apache2/ssl/server.key SSLCertificateFile /etc/apache2/ssl/server.crt ScriptAliasMatch ^/(?!(images/|js/|css/)) /var/www/skype/cgi-bin/index.lua/$1 Order deny,allow Allow from all Order deny,allow Allow from all AuthType basic AuthName "Skype configuration" AuthUserFile /var/www/skype/.htpasswd require valid-user }}} Add this to your apache /etc/apache2/vhosts.d/99_skype.domain.com.conf or another file depending on your environment. Now let create the password file: {{{ snowflake ~ # htpasswd -c /var/www/skype/.htpasswd admin New password: Re-type new password: Adding password for user admin snowflake ~ # }}} Reload apache and visit https://skype.domain.com/. Password prompt should appear and your should get in. Please not that we use https for security reasons. ==== Directory Configuration ==== More simple configuration without password on plain text HTTP 80 port: {{{ # We make an assumption that skype gui package is unpacked into /var/www/skype and WEB site URL is http://domain.com/skype/ ScriptAliasMatch ^/skype/(?!(images/|js/|css/)) /var/www/skype/cgi-bin/index.lua/$1 Order deny,allow Allow from all #AuthType basic #AuthName "Skype configuration" #AuthUserFile /var/www/skype/.htpasswd #require valid-user Alias /skype/ "/var/www/skype/htdocs/" Order deny,allow Allow from all }}} In the above example we have urlPrefix="/skype" set in cgi-bin/config.lua. === Asterisk === ==== ODBC ==== We use SQLite3 as database storage via res_ODBC. ===== /etc/unixODBC/odbcinst.ini ===== {{{ [SQLite3] Description=ODBC for SQLite3 Driver=/usr/lib/libsqlite3odbc.so Setup=/usr/lib/libsqlite3odbc.so Threading=2 }}} Driver path must be changed to the real libsqlite3odbc library. ===== /etc/unixODBC/odbc.ini ===== {{{ [SQLite3-skype] Description=SQLite3 Skype database Trace=Off TraceFile=stderr Driver=SQLite3 Database=/var/www/skype/cgi-bin/db/data.db }}} ===== /etc/asterisk/res_odbc.conf ===== {{{ [ENV] [skype] enabled => yes dsn => SQLite3-skype pre-connect => yes }}} ===== /etc/asterisk/func_odbc.conf ===== {{{ [SKYPE_EXT] dsn=skype readsql=SELECT exten FROM skypecontact WHERE skypeid='${SQL_ESC(${ARG1})}' [SKYPE_NAME] dsn=skype readsql=SELECT skypeid FROM skypecontact WHERE exten='${SQL_ESC(${ARG1})}' [SKYPE_MAX_EXT] dsn=skype readsql=SELECT MAX(exten) FROM skypecontact [SKYPE_ADD] dsn=skype writesql=INSERT INTO skypecontact (exten, skypeid, created, modified) VALUES ('${SQL_ESC(${VAL1})}', '${SQL_ESC(${VAL2})}', datetime('now','localtime'), datetime('now','localtime')) }}} === Skype === Skype accounts are configured in chan_skype.conf. Here is an example configuration: ==== chan_skype.conf ==== {{{ [general] engine_directory=/tmp/skype default_user=pbxware.ru bind_address=x.x.x.x bind_port=0 [pbxware.ru] secret=XXXXXXXXXXXXXXX context=skype-in exten=s disallow=all allow=ulaw direction=both auth_policy=accept }}} The most important settings are: * context - all calls from Skype are handled in skype-in; * exten - what extension to call in that context; === Dialplan === Add the following to your extensions.conf: {{{ ; Context for our users [from-internal] exten => _XXX,1,Macro(std-exten,${EXTEN}) exten => _XXXX,1,Goto(skype-out,${EXTEN},1) ; Here we define what we do with incoming calls from skype [from-skype] exten => s,1,Goto(menu-main,s,1) exten => _XXX,1,Goto(from-internal,${EXTEN},1) ; Context for outgoing skype calls [skype-out] exten => _XXXX,1,Set(DST=${EXTEN}) exten => _XXXX,2,Goto(s,1) exten => s,1,Set(skype_name=${ODBC_SKYPE_NAME(${DST})}) exten => s,n,ExecIf($["${skype_name}" = ""]|Hangup) exten => s,n,Dial(Skype/${skype_name}) ; Context for incoming Skype calls [skype-in] ; Save dialed exten exten => _X.,1,Set(DST=${EXTEN}) exten => _X.,2,Goto(s,1) ; If from skype comes start exten ;exten => s,1,ExecIf($["${DST}" = ""]|Set|DST=s); 1.4 version exten => s,1,ExecIf($["${DST}" = ""]?Set(DST=s)); 1.6 version ; Let see if we already have this account exten => s,n,Set(skype_name=${CALLERID(num)}) exten => s,n,Set(skype_ext=${ODBC_SKYPE_EXT(${skype_name})}) exten => s,n,GotoIf($["${skype_ext}" = ""]?not-found:found) ; Existing account found exten => s,n(found),NoOp(Found Skype ID ${skype_name} with exten ${skype_ext}) exten => s,n,Set(CALLERID(num)=${skype_ext}) exten => s,n,Set(CALLERID(name)=${skype_name}) exten => s,n,Goto(from-skype,${DST},1) ; New Skype account calling exten => s,n(not-found),Set(skype_ext=${ODBC_SKYPE_MAX_EXT()}); Get maximum extension number ;if database is empty we initialize 1-st exten 1000 ;exten => s,n,ExecIf($["${skype_ext}" = ""]|Set|skype_ext=1000); 1.4. version exten => s,n,ExecIf($["${skype_ext}" = ""]?Set(skype_ext=1000)); 1.6 version ; Add new record with next available exten ;exten => s,n,Set(ODBC_SKYPE_ADD()=$[${skype_ext}+1]\,${skype_name}); 1.4 version exten => s,n,Set(ODBC_SKYPE_ADD()=$[${skype_ext}+1],${skype_name}); 1.6 version exten => s,n,Set(CALLERID(num)=${skype_ext}+1) exten => s,n,Set(CALLERID(name)=${skype_name}) exten => s,n,Goto(from-skype,${DST},1) }}} '''NOTE! This is the dialplan configuration for Asterisk 1.6. For 1.4 branch you should comment 1.6 lines and uncomment 1.4! Otherwise Asterisk will complain on dialplan reload.''' === Reload Asterisk === {{{ CLI> reload }}} == Enjoy! == Now call your skype account and see how it works all together! Enjoy! If you need assistance or would like to request a feature do not hesitate to contact us (see Contact Us section). == Comments == Comments are welcome. [[AddComment]] == Troubleshooting == If anything foes wrong see build.log for details. Here we enumerate some issues we already met. === Filtering does not work or new skype accounts are not created === See folder permissions. Both asterisk and WEB server must have read/write access to database file cgi-bin/db/data.db. WEB server must also be able to read/write cgi-bin/sessions and cgi-bin/tmp folders. === Load res_odbc and func_odbc === {{{ snowflake*CLI> module load res_odbc.so [2009-12-10 11:50:47] WARNING[25757]: loader.c:711 load_resource: Module 'res_odbc.so' already exists. snowflake*CLI> module reload res_odbc.so [2009-12-10 11:50:51] -- Reloading module 'res_odbc.so' (ODBC Resource) [2009-12-10 11:50:51] == Parsing '/home/asterisk.pbxware/etc/asterisk/res_odbc.conf': [2009-12-10 11:50:51] Found snowflake*CLI> odbc show Name: skypeLI> DSN: SQLite3-skype }}} All is ok. If you see smth like: {{{ snowflake*CLI> module load res_odbc.so [2009-12-10 11:50:10] == Parsing '/home/asterisk.pbxware/etc/asterisk/res_odbc.conf': [2009-12-10 11:50:10] Found [2009-12-10 11:50:11] WARNING[25757]: res_odbc.c:562 odbc_obj_connect: res_odbc: Error SQLConnect=-1 errno=0 [unixODBC][Driver Manager]Can't open lib '/usr/lib64/libsqlite3odbc.so' : /usr/lib64/libsqlite3odbc [2009-12-10 11:50:11] WARNING[25757]: res_odbc.c:467 ast_odbc_request_obj: Failed to connect to skype }}} Then check your unixODBC SQLite3 installaiton. {{{ snowflake*CLI> module load func_odbc.so [2009-12-10 11:51:12] == Parsing '/home/asterisk.pbxware/etc/asterisk/func_odbc.conf': [2009-12-10 11:51:12] Found [2009-12-10 11:51:12] == Registered custom function ODBC_SKYPE_EXT [2009-12-10 11:51:12] == Registered custom function ODBC_SKYPE_MAX_EXT [2009-12-10 11:51:12] == Registered custom function ODBC_SKYPE_ADD [2009-12-10 11:51:12] == Registered custom function SQL_ESC [2009-12-10 11:51:12] Loaded func_odbc.so => (ODBC lookups) snowflake*CLI> snowflake*CLI> show func functions function snowflake*CLI> show function ODB ODBC_SKYPE_ADD ODBC_SKYPE_EXT ODBC_SKYPE_MAX_EXT snowflake*CLI> show function ODBC_SKYPE_ }}} You should check your modules.conf and see that there is no noload directived for ODBC related. === Skype channel === Check that everything is configured right: {{{ snowflake*CLI> skype show user pbxware.ru Skype User pbxware.ru: secret: XXXXXXXXXXXX context: skype-in exten: s accountcode: language: mohinterpret: mohsuggest: amaflags: Unknown direction: both buddy_autoadd: hints buddy_presence: yes debug: no auth_policy: accept codecs: ulaw snowflake*CLI> pbxware.ru: Logged In snowflake*CLI> }}} Our account is registered. === readline headers not found === If you get smth like: {{{ Compiling Lua... In file included from lua.h:16, from lua.c:15: luaconf.h:275:31: error: readline/readline.h: No such file or directory luaconf.h:276:30: error: readline/history.h: No such file or directory }}} then you do not have readline headers installed. On RPM based linux it is readline-devel package: yum install readline-devel. === Missing libtool === If you get the following: {{{ Compiling Lua... Compiling Lua Datafilter... cp: cannot stat `.libs/liblua-datafilter.so': No such file or directory Compiling Lua Socket... Compiling Lua Posix... Compiling Lua SQL... Unpacking Luv... Unpacking Skype GUI... }}} that means datafilter was not compiled. See build.log for details. In our case there was: {{{ CC> filter.lo make: libtool: Command not found make: * [filter.lo] Error 127 }}} Install libtool and repeat from the very beginning. == Contact Us == You can contact as by email tech(at)pbxware.ru for support of feature request.