Monday, November 14, 2016

Friday, April 1, 2016

Installing SIP SIMPLE Client SDK on Debian 8

Few words, that missed from official wiki at AG Projects site about installing from repos.

You need also to add jessie-backports repos to your sources.list
deb http://ftp.debian.org/debian jessie-backports main
Than -
apt-get update
apt-get -t jessie-backports install python-otr
apt-get install python-sipsimple
apt-get install sipclients

That's it :) All thanks goes to Saúl Ibarra Corretgé from AG Project.

Monday, March 14, 2016

Telecom and VoIP for non-specialists. Part 1.

Hello to all!
One of mine friends suggests me to start a series of articles about telecom, PBXes and other stuff I work with. For a non-telecom boys and girls. So, why not?

And I’d like to start with a disclaimer. All you will read here is not «last and final truth». It’s just mine point of view on things I work with. I work mostly with SMB market, so if you come and ask something about large distributed call-centres with tons of queues and agents, and reports… I know basics of telecom and using this knowledge I can answer how to build this. But honestly - I like to be more close to ground. Reason - you speak to people more, than to machines. And all this «bloody enterprise» things make me feel like a hamster in a ball. Endless reports, numbers, conversions… Boring. Much more interesting to work with SMB. And easier, of course. And - no possible to work for something really heavy all alone. That’s may be the real reason. So, back to disclaimer, all here is my own opinion. Can be right, can be wrong, but based on experience. If you think I’m wrong somewhere - you’re welcome to comments :) Also, english - is not my native, so there would be errors, but hope, everybody can catch main idea.

Let’s start than with little dive-in.
History of telecom starts earlier, than history of computers and IT. And for many years computers and telecom industry was close, but really not the same, like nowadays. They have separate standards, separate networks, different ideology.
And ok, let’s narrow a bit our field of view and talk about PBX’es. What PBX is? Normally you see a phone on your work desk or home. You know, if you dial a number, you can talk to person you’ve dialed. But how your phone is connected to other’s? It’s done via PBX.
First PBX’es was actually alive girls who manually switches wires from one jack to another. Actually, «jack» connector is from these times. Later girls were replaced by electrical mechanics. If you are old enough or live in some god’s forgotten place with telephone, you can remember disk phones or when you push buttons on your phones, you can hear «ticks» depends on digit dialed. That is actually commands to PBX mechanism.
Next big era is fully digital. You may heard ISDN abbreviation. That’s it. Still alive and well. But, modern system use 10-20% of this standard. ISDN was designed not only a voice carrying network, but data also. But, for data it was really expensive and data was moved to other networks. That’s why sometimes ISDN is decoded as It Still Does Nothing ;)

That’s it for now. Muse had left me. In next part we will talk about nowadays.

Monday, January 25, 2016

FusionPBX(Freeswitch) HA sync gateways across servers

There was a little task to do.
Assume, we have several FusionPBX in HA (shared database incl. runtime data is on). On "master managing" server we add a gateway to external profile. To add them on other servers we have to go to each server and push rescan on external profile. Eh... To lazy for this.
We will use script, that will subscribe to CUSTOM sofia::gateway_add and gateway_delete event and run sofia profile external rescan over other servers.
We will do this over xmlrpc, so no need to add ssh keys or so.

"Slave" servers:

  • Go to Advanced -> Modules and enable XML RPC module
  • Go to Advanced -> Settings on each "slave" server and put common data for XMLRPC connection, like username, pass and port
  • Restart mod_xml_rpc on each "slave" server
"Master" server
  • Create files /usr/local/freeswitch/scripts/app/gateway_states/resources/gateway_states_add.lua and /usr/local/freeswitch/scripts/app/gateway_states/resources/gateway_states_delete.lua
(I can't get add and delete event work from a single file)
  • gateway_states_add.lua
--description
--monitor custom sofia:gateway_* event and run sofia profile external rescan over other servers
--protect xmlrpc using a firewall on the server to limit access by ip address

--iptables
-- /sbin/iptables -I INPUT -j ACCEPT -p tcp --dport 8080 -s x.x.x.x/32

--define the servers running freeswitch do not include local
servers = {}
x = 0;
servers[x] = {}
servers[x]['username'] = "freeswitch";
servers[x]['password'] = "work";
servers[x]['hostname'] = "10.0.0.2";
servers[x]['port'] = "8080";
x = x + 1;
servers[x] = {}
servers[x]['username'] = "freeswitch";
servers[x]['password'] = "work";
servers[x]['hostname'] = "10.0.0.3";
servers[x]['port'] = "8080";
--x = x + 1;
--servers[x] = {}
--servers[x]['username'] = "ccc";
--servers[x]['password'] = "xxxxx";
--servers[x]['hostname'] = "127.0.0.3";
--servers[x]['port'] = "8080";

--subscribe to the events
--events = freeswitch.EventConsumer("all");
events = freeswitch.EventConsumer("CUSTOM", "sofia::gateway_add");
        -- events = freeswitch.EventConsumer("CUSTOM", "sofia::gateway_delete");
        -- Modify line above to get gateway_states_delete.lua
--prepare the api object
api = freeswitch.API();

--get the events
for event in (function() return events:pop(1) end) do
api_command_argument = "profile%20external%20rescan";
  -- event_gateway = event:getHeader("Gateway");
  -- api_command_argument = "profile%20external%20killgw%20"..event_gateway;
  -- Modify line above to get gateway_states_delete.lua
for key,row in pairs(servers) do
url = [[http://]]..row.username..[[:]]..row.password..[[@]]..row.hostname..[[:]]..row.port..[[/webapi/sofia?]]..api_command_argument;
response = api:execute("curl", url);
freeswitch.consoleLog("INFO", "[notice] ".. url .. " "..response.."\n");
end
end



  • Modify /usr/local/freeswitch/conf/autoload_configs/lua.conf.xml

    <param name="startup-script" value="app/gateway_states/resources/gateway_states_add.lua"/>
    <param name="startup-script" value="app/gateway_states/resources/gateway_states_delete.lua"/>


  • Restart "master" server. At this point, every gateway add or delete will trigger an event, that will go across all our servers and command them pull new config from common database.

This script was modified from memcache.lua, that flushes memcaches over all Fusion servers.

Tuesday, January 12, 2016

Sngrep. I'm happy to found it.

Really best tool to analyze SIP traffic in console.

Also, not to forget about sipgrep.
Yep, very short post, but really - no more complex tshark or pcap with downloading :)

Saturday, November 21, 2015

FreeSwitch G.729

It's exists!
Only A, but normally it's enough.
https://github.com/xadhoom/mod_bcg729

Point: don't forget to modify Makefile with correct FreeSwitch paths.
Usually
FS_INCLUDES=/usr/local/freeswitch/include
FS_MODULES=/usr/local/freeswitch/mod

Little update: can't get it work on 1.6 in VmWare environment. 

Update 2:
Due to forum a bit update for FusionPBX:

apt-get install build-essential automake gcc git libtool pkg-config libfreeswitch-dev

FS_INCLUDES=/usr/include/freeswitch

FS_MODULES=/usr/lib/freeswitch/mod

Tuesday, October 27, 2015

Handling Austrian (and maybe German and Swiss) DID numbers with extensions at A2Billing

In Austria still using classic ISDN dialing rules. So, if your company have number 431234567, and your internal number is 101 you can dial 431234567101 from any phone and get to extension 101 without any crappy IVR's.
Causes several problems with dialing rules, but make life much more comfortable.
So, the problem is how to handle those DID's in A2Billing, cause this soft uses only exact matches.
Solution - use MySQL patterns in DID fields directly.

So, now DID in A2Billing will looks like
 431234567%
 yes with "%" sign at the end.
Also, for VoIP destination was made a quick modification, that allows to use variables in dialstring.
So, destination will be like
SIP/<YourSipUser>/%did%.
At %did% A2billing will automatically place original DID(extension)

Patch is below
diff -Naur AGI/a2billing.php agi-bin/a2billing.php
--- AGI/a2billing.php 2015-02-27 15:42:38.000000000 +0100
+++ agi-bin/a2billing.php 2015-10-27 13:17:49.000000000 +0100
@@ -643,7 +643,8 @@
             " aleg_carrier_initblock_offp, aleg_carrier_increment_offp, aleg_retail_initblock_offp, aleg_retail_increment_offp ".
             " FROM cc_did, cc_did_destination, cc_card ".
             " WHERE id_cc_did=cc_did.id AND cc_card.status=1 AND cc_card.id=id_cc_card AND cc_did_destination.activated=1 ".
-            " AND cc_did.activated=1 AND did='$mydnid' ".
+            //" AND cc_did.activated=1 AND did='$mydnid' ".
+            " AND cc_did.activated=1 AND '$mydnid' LIKE did ". // Added to Austrian DID handling
             " AND cc_did.startingdate<= CURRENT_TIMESTAMP AND (cc_did.expirationdate > CURRENT_TIMESTAMP OR cc_did.expirationdate IS NULL ".
             " AND cc_did_destination.validated=1";
         if ($A2B->config["database"]['dbtype'] != "postgres") {
diff -Naur AGI/lib/Class.A2Billing.php agi-bin/lib/Class.A2Billing.php
--- AGI/lib/Class.A2Billing.php 2015-02-27 15:42:38.000000000 +0100
+++ agi-bin/lib/Class.A2Billing.php 2015-10-27 11:26:36.000000000 +0100
@@ -1324,6 +1324,8 @@
                     $dialparams = str_replace("%timeout%", min($time2call * 1000, $max_long), $dialparams);
                     $dialparams = str_replace("%timeoutsec%", min($time2call, $max_long), $dialparams);
                     $dialstr = $inst_listdestination[4] . $dialparams;
+    // Added support for %did% variable
+    $dialstr = str_replace("%did%", $this->orig_ext, $dialstr);

                     $this->debug(DEBUG, $agi, __FILE__, __LINE__, "[A2Billing] DID call friend: Dialing '$dialstr' Friend.\n");