Yate Community Forum
General Category => Yate users hangout place => Topic started by: jamie on July 25, 2017, 08:09:44 PM
-
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:
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:
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 :
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
-
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.
-
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
-
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
-
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*
// 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*
// 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.
if ( $ev->name==='call.route' && $ev->getValue("called") == "1001") {
.....
}
Just the authentication mystery to solve now !
Thank you, regards
Jamie
-
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).
-
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.
-
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