Author Topic: Routing a call, using a database ( register.conf / PHP ) Over 2 different Lines  (Read 10454 times)

jamie

  • Newbie
  • *
  • Posts: 38
    • View Profile
Hi!

Please could I ask for a little help?


My Objective:

To route an incoming call using a database with a fork to two or more different registered 'lines' (accounts) and/or Registered SIP users
Everything is done from a database utilising register.conf
 

I've created a PostgreSQL prepared statement to return a single row with any columns we require. Eg location, line, callername etc etc


Routing to say a registered SIP user or an account (line) individually works fine, as follows:


forking the incoming call to two registered sip users, i return:

Code: [Select]
location = fork sip/sip:testuser1@1.2.3.4 sip/sip:testuser2@1.2.3.4
line = <NULL>

Or ...

two or more endpoints on the same line, we return fields as:

Code: [Select]
location = fork sip/01234567890 sip/01234567891
line = my_gateway

Both of the above methods work fine,

but I'm a bit flummoxed how to do the same with a mixture of registered users and lines.

I had hoped something like this would work, but alas it didn't :

Code: [Select]
location = fork sip/sip:test1@1.2.3.4 sip/01234567891;line=my_gateway
line = <NULL>

Is what I'm trying to achieve possible from register.conf ?

If it is, please could you point me in the right direction ?

Thank you!
Regards
Jamie
« Last Edit: July 26, 2017, 09:04:51 PM by jamie »

Monica Tepelus

  • Administrator
  • Full Member
  • *****
  • Posts: 198
    • View Profile
Hi,

Yes, but it's more difficult.
You need to use fork syntax for Yate > 3.3.3. It allows you to set different parameters for each fork leg. You would need to return location=fork and set all the options in different parameters in the message (this is the hard part).

http://docs.yate.ro/wiki/Call_Forker

As far as I remember a stored procedure in plpgsql needs to return a fixed number of parameters. You would need define a maximum number of parameters.

When routing is this complicated we usually prefer an external module or a javascript script that does queries but allows for easier manipulation of message parameters.

jamie

  • Newbie
  • *
  • Posts: 38
    • View Profile
Hi Monica,

Thanks for your reply.

This is actually one of the pages I've been trying to use.

From your notes are you saying we'd need to return 'column' as follows:

( column name = value )

location = fork
param1 = abc
param2  = xyz

If so, I'm unsure how to translate that to the various fork targets. Where would I put the index for example and what format is ?

Just a quick example would be great !

Thank you

Jamie

jamie

  • Newbie
  • *
  • Posts: 38
    • View Profile

I've just been looking at an external script as an alternative option.

I remember now why I went the database route and doing it all in register.conf and the pg function!

Setting up an external script is straightforward.

I can also make it listen for the the call.route message event and point it at something eg tone/busy or moh/default to test.

But my problem has always been authentication.

The auth process it's self is ok,

My problem is when i come to route the call in the .php script, how do I check the user is authenticated before routing ?

There's no username parameter in my call.route, so I've installed user.auth as  well.

But, if i try to listen for the the user.auth event, i can quite often get the call.route event before seeing an auth event, defeating the purpose.

I must be looking at this in the wrong way. I suspect priorities !

Sorry to leave you with two questions, but any pointers would be really helpful !

Thank you!

Jamie

PS I'm still using register.conf for it's other features, eg auth, cdr, line status etc





jamie

  • Newbie
  • *
  • Posts: 38
    • View Profile
Hi Monica,

Forking in the external module is very flexible, here's what I've worked out this evening that solves my original routing requirement. I hope it helps others one day!

I have tested the following, but please let me know if you see any problems ?!


*Simple Example - Fork to 2 Registered SIP users*

Code: [Select]

// Start the fork
$ev->retval = "fork";
// Add the first target
$ev->params["callto.1"] = 'sip/sip:test_user_1@192.168.0.101:5060';
// Add the second target
$ev->params["callto.3"] =  'sip/sip:test_user_2@192.168.0.102:5060';
// Mark handled
$ev->handled = true;





*More Complex Example - Fork to 2 Registered SIP users and then a 3rd Target over a line*

Code: [Select]

// Start the fork
$ev->retval = "fork";

// Add the first target (registered sip user)
$ev->params["callto.1"] = 'sip/sip:test_user_1@192.168.0.101:5060';
// Add a Max Call duration for target 1
$ev->params["callto.1.timeout"]  = "30000";

// To start calling the next target after 3 seconds add a callto param of |next=3000  ( call 1 will not hangup )
$ev->params["callto.2"]  = "|next=3000";

// Add the next Target
$ev->params["callto.3"] =  'sip/sip:test_user_2@192.168.0.102:5060';
// Add it's Max Call duration
$ev->params["callto.3.timeout"]  = "30000";

// To start calling the next target after 3 seconds add a callto param of |drop=3000  ( calls 1 and 2 will both hangup )
$ev->params["callto.4"]  = "|drop=3000";

// Add the final Target
$ev->params["callto.5"] =  'line/sip:449066631234';
// Tell YATE that this is to be routed over line 'test_gateway_1'
$ev->params["callto.5.line"]  = "test_gateway_1";
// Add it's Max Call duration
$ev->params["callto.5.timeout"]  = "60000";

// Mark handled
$ev->handled = true;




For testing purposes, I wrapped the above in the following and listened for the call.route event message.

Code: [Select]

if ( $ev->name==='call.route' && $ev->getValue("called") == "1001") {

     .....

}




Just the authentication mystery to solve now !

Thank you, regards
Jamie


Monica Tepelus

  • Administrator
  • Full Member
  • *****
  • Posts: 198
    • View Profile
Hi,

It's normal to mix routing from external module and the handling of other messages from register.conf.

Regarding your autentication problem, you don't need to do the authentication in the external script, you just need to request it. So you don't need to install user.auth.
To do this you should  set $ev->params["error"] = "noauth" and return false to the call.route message when username param is not set. This will trgger authentication and the next call.route message you receive will have parameter "username" set (in this way you'll know the user was authenticated).

ganapathi

  • Full Member
  • ***
  • Posts: 101
    • View Profile
Hi

As i used pgsql stored function to route a call to user/group. Whereas i am getting result properly but even though calls are not routing to the user .

find the below mentioned configuration for the same.

register.conf

query=SELECT * FROM route_master('${billid}','${called}','${trace}');
result=location

Output of PgSQL:

field   value
trace   4444407
callto.1   sip/sip:4444407@192.168.1.82:5060
dtmfpass   false
location   fork
pbxassist   true
copyparams   pbxassist,dtmfpass
tonedetect_out   true
callto.1.secure   yes

Logs :

<pgsqldb:ALL> Query for 'db.1' returned 8 rows, 8 affected [0xcbd510]
Returned true 'database' delay=0.230988
  thread=0x7f6e54002c10 'Call Router'
  data=0x7f6e4c006200
  retval='(null)'
  param['account'] = 'technobureau_db'
  param['query'] = 'SELECT * FROM route_master('1506767265-8','4444407','');'
  param['results'] = 'true'
  param['handlers'] = 'pgsqldb:100'
  param['columns'] = '2'
  param['rows'] = '8'
  param['affected'] = '8'
  param['dbtype'] = 'pgsqldb'
2017-09-30_17:34:43.806147 <register:WARN> Skipping void route #2
2017-09-30_17:34:43.806158 <register:WARN> Skipping void route #3
2017-09-30_17:34:43.806172 <register:WARN> Skipping void route #4
2017-09-30_17:34:43.806182 <register:WARN> Skipping void route #5
2017-09-30_17:34:43.806192 <register:WARN> Skipping void route #6
2017-09-30_17:34:43.806202 <register:WARN> Skipping void route #7
2017-09-30_17:34:43.806211 <register:WARN> Skipping void route #8

Call.cdr :

Status :hangup
Reason : Offline

But actually user logged-in.

Kindly help me out.

Monica Tepelus

  • Administrator
  • Full Member
  • *****
  • Posts: 198
    • View Profile
The format of what your pgsql procedure is not right for routing.  You return multiple rows with format:
param_name=param_value
This is not correct. You need to have column name = param_name  and value is the one in a row. The correct format would be

param_name1  | param_name2 | param_name3 | ...
row1_value1    | row1_value2    | row1_value3   | ...
row2_value1    | row2_value2 ...

location=name_of_param that holds the actual location (Ex: param_name2)

The other columns will be added as parameters to the call.route message.
By default only the first row of result will matter, unless you activate fallback routing in register.conf