Problem accessing channel variables
Hi all, I'm trying to write something to fit into a two factor auth mechanism. I have a CGI script which is called with a phone number and a PIN as parameters. In the script I use the event socket api to place a call. The PHP code I'm using to write to the socket is straight out of the FS docs (can't remember exactly, I think I got it from the wiki). This is my api command: api originate {originate_timeout=30}sofia/external/${dExt}@MGC '&play_and_get_digits(4 4 2 30000 # torvalds-says-linux.wav torvalds-says-linux.wav foo \d+)' This all works fine, up to a point. The call is made, the wav is played. But then PAGD is supposed to put the digits into a channel var, in this case "foo". But I've been having trouble getting the value of this channel var *reliably*. If the # key is used to terminate the input, then I can get the channel var value with api uuid_getvar $uuid foo However, if the input is terminated by PAGD because 4 digits have been entered, then the call is hung up (by FS/PAGD) before I have a chance to get the value of the channel var. Can anyone help here please? I suppose I can work around this by increasing the digits to 5 and telling people to use # to terminate the input, but I'd like to understand the correct way to use PAGD if possible. If you think I'm going about this the wrong way entirely, then please suggest an alternative :-) My code is below. As I say, lines 1-71 are straight out of the docs. 1 <?php 2 3 $password = "xxxxxx"; 4 $port = "xxxx"; 5 $host = "127.0.0.1"; 6 7 function event_socket_create($host, $port, $password) { 8 $fp = fsockopen($host, $port, $errno, $errdesc) 9 or die("Connection to $host failed"); 10 socket_set_blocking($fp,false); 11 12 if ($fp) { 13 while (!feof($fp)) { 14 $buffer = fgets($fp, 1024); 15 usleep(100); //allow time for reponse 16 if (trim($buffer) == "Content-Type: auth/request") { 17 fputs($fp, "auth $password\n\n"); 18 break; 19 } 20 } 21 return $fp; 22 } 23 else { 24 return false; 25 } 26 } 27 28 function event_socket_request($fp, $cmd) { 29 30 if ($fp) { 31 fputs($fp, $cmd."\n\n"); 32 usleep(200); //allow time for reponse 33 34 $response = ""; 35 $i = 0; 36 $contentlength = 0; 37 while (!feof($fp)) { 38 $buffer = fgets($fp, 4096); 39 if ($contentlength > 0) { 40 $response .= $buffer; 41 } 42 43 if ($contentlength == 0) { //if contentlenght is already don't process again 44 if (strlen(trim($buffer)) > 0) { //run only if buffer has content 45 $temparray = split(":", trim($buffer)); 46 if ($temparray[0] == "Content-Length") { 47 $contentlength = trim($temparray[1]); 48 } 49 } 50 } 51 52 usleep(200); //allow time for reponse 53 54 //optional because of script timeout //don't let while loop become endless 55 if ($i > 90000) { break; } 56 57 if ($contentlength > 0) { //is contentlength set 58 //stop reading if all content has been read. 59 if (strlen($response) >= $contentlength) { 60 break; 61 } 62 } 63 $i++; 64 } 65 66 return $response; 67 } 68 else { 69 echo "no handle"; 70 } 71 } 72 73 function strip_cr($str) { 74 return preg_replace("/\n/",'',$str); 75 } 76 77 $dExt = $_GET['dExt']; 78 if ($dExt) { 79 $fp = event_socket_create($host, $port, $password); 80 81 # Place call and find uuid 82 $cmd = "api originate {originate_timeout=30}sofia/external/677${dExt}@194.145.191.131 '&play_and_get_digits(4 4 2 30000 # torvalds-says-linux.wav torvalds-says-linux.wav foo \d+)'"; 83 $response = event_socket_request($fp, $cmd); 84 $response = preg_replace('/</','<',$response); 85 $response = preg_replace('/>/','>',$response); 86 $response = strip_cr($response); 87 $bits = preg_split('/\s+/',$response); 88 $uuid = $bits[1]; 89 90 echo '<pre>'; 91 echo date('H:i:s') . "\n"; 92 echo "call placed: $cmd\n"; 93 echo "response :$response:\n"; 94 echo "uuid $uuid\n"; 95 96 # Retrieve channel variable 97 $cmd = "api uuid_getvar $uuid foo"; 98 $response = ''; 99 while (! $response or $response == '_undef_') { 100 echo "in loop : got _undef_\n"; 101 $response = event_socket_request($fp, $cmd); 102 $response = strip_cr($response); 103 } 104 echo "response :$response:\n"; 105 echo '</pre>'; 106 107 # Close socket 108 fclose($fp); 109 } else { 110 echo 'Request URL in this format: /test.php?dExt=<phone_number>' . "\n"; 111 } 112 113 ?> Cheers, Rich -- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
If you listen to events then you should be able to reliably receive a hangup event containing the variables *if you are still connected at that time*. If you want a 100% reliable method use CDRs. mod_xml_cdr can submit call CDRs to a webserver just after call hangup. The XML is verbose and will contain a full call history and all channel variables. Because it's submitted ASAP you get the results in real time and reliable. If the module can't submit the CDRs it writes them to an error folder on disk where you can resubmit them. Real time seems useful for your use-case, as your script would just need to check your DB whether the CDR had been submitted yet. The channel UUID can either be captured from events or specified in advance in the originate (originate_uuid). There's a uuid api call to generate them for you. I'd suggest looking at this method. On 28 November 2012 10:54, Richard Gration <richgration@gmail.com> wrote:
Hi all,
I'm trying to write something to fit into a two factor auth mechanism. I have a CGI script which is called with a phone number and a PIN as parameters. In the script I use the event socket api to place a call. The PHP code I'm using to write to the socket is straight out of the FS docs (can't remember exactly, I think I got it from the wiki). This is my api command:
api originate {originate_timeout=30}sofia/external/${dExt}@MGC '&play_and_get_digits(4 4 2 30000 # torvalds-says-linux.wav torvalds-says-linux.wav foo \d+)'
This all works fine, up to a point. The call is made, the wav is played. But then PAGD is supposed to put the digits into a channel var, in this case "foo". But I've been having trouble getting the value of this channel var *reliably*. If the # key is used to terminate the input, then I can get the channel var value with
api uuid_getvar $uuid foo
However, if the input is terminated by PAGD because 4 digits have been entered, then the call is hung up (by FS/PAGD) before I have a chance to get the value of the channel var. Can anyone help here please? I suppose I can work around this by increasing the digits to 5 and telling people to use # to terminate the input, but I'd like to understand the correct way to use PAGD if possible.
If you think I'm going about this the wrong way entirely, then please suggest an alternative :-)
My code is below. As I say, lines 1-71 are straight out of the docs.
1 <?php 2 3 $password = "xxxxxx"; 4 $port = "xxxx"; 5 $host = "127.0.0.1"; 6 7 function event_socket_create($host, $port, $password) { 8 $fp = fsockopen($host, $port, $errno, $errdesc) 9 or die("Connection to $host failed"); 10 socket_set_blocking($fp,false); 11 12 if ($fp) { 13 while (!feof($fp)) { 14 $buffer = fgets($fp, 1024); 15 usleep(100); //allow time for reponse 16 if (trim($buffer) == "Content-Type: auth/request") { 17 fputs($fp, "auth $password\n\n"); 18 break; 19 } 20 } 21 return $fp; 22 } 23 else { 24 return false; 25 } 26 } 27 28 function event_socket_request($fp, $cmd) { 29 30 if ($fp) { 31 fputs($fp, $cmd."\n\n"); 32 usleep(200); //allow time for reponse 33 34 $response = ""; 35 $i = 0; 36 $contentlength = 0; 37 while (!feof($fp)) { 38 $buffer = fgets($fp, 4096); 39 if ($contentlength > 0) { 40 $response .= $buffer; 41 } 42 43 if ($contentlength == 0) { //if contentlenght is already don't process again 44 if (strlen(trim($buffer)) > 0) { //run only if buffer has content 45 $temparray = split(":", trim($buffer)); 46 if ($temparray[0] == "Content-Length") { 47 $contentlength = trim($temparray[1]); 48 } 49 } 50 } 51 52 usleep(200); //allow time for reponse 53 54 //optional because of script timeout //don't let while loop become endless 55 if ($i > 90000) { break; } 56 57 if ($contentlength > 0) { //is contentlength set 58 //stop reading if all content has been read. 59 if (strlen($response) >= $contentlength) { 60 break; 61 } 62 } 63 $i++; 64 } 65 66 return $response; 67 } 68 else { 69 echo "no handle"; 70 } 71 } 72 73 function strip_cr($str) { 74 return preg_replace("/\n/",'',$str); 75 } 76 77 $dExt = $_GET['dExt']; 78 if ($dExt) { 79 $fp = event_socket_create($host, $port, $password); 80 81 # Place call and find uuid 82 $cmd = "api originate {originate_timeout=30}sofia/external/677${dExt}@194.145.191.131 '&play_and_get_digits(4 4 2 30000 # torvalds-says-linux.wav torvalds-says-linux.wav foo \d+)'"; 83 $response = event_socket_request($fp, $cmd); 84 $response = preg_replace('/</','<',$response); 85 $response = preg_replace('/>/','>',$response); 86 $response = strip_cr($response); 87 $bits = preg_split('/\s+/',$response); 88 $uuid = $bits[1]; 89 90 echo '<pre>'; 91 echo date('H:i:s') . "\n"; 92 echo "call placed: $cmd\n"; 93 echo "response :$response:\n"; 94 echo "uuid $uuid\n"; 95 96 # Retrieve channel variable 97 $cmd = "api uuid_getvar $uuid foo"; 98 $response = ''; 99 while (! $response or $response == '_undef_') { 100 echo "in loop : got _undef_\n"; 101 $response = event_socket_request($fp, $cmd); 102 $response = strip_cr($response); 103 } 104 echo "response :$response:\n"; 105 echo '</pre>'; 106 107 # Close socket 108 fclose($fp); 109 } else { 110 echo 'Request URL in this format: /test.php?dExt=<phone_number>' . "\n"; 111 } 112 113 ?>
Cheers, Rich
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
Hi, Thanks for your reply. I was wondering ...
If you listen to events then you should be able to reliably receive a hangup event containing the variables if you are still connected at that time.
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
If you want a 100% reliable method use CDRs.
mod_xml_cdr can submit call CDRs to a webserver just after call hangup. The XML is verbose and will contain a full call history and all channel variables. Because it's submitted ASAP you get the results in real time and reliable. If the module can't submit the CDRs it writes them to an error folder on disk where you can resubmit them.
Real time seems useful for your use-case, as your script would just need to check your DB whether the CDR had been submitted yet. The channel UUID can either be captured from events or specified in advance in the originate (originate_uuid). There's a uuid api call to generate them for you. I'd suggest looking at this method.
This is all great info, thanks :-) I'm capturing the uuid from the response from the originate command, that's no problem. The box I'm doing this on is being a B2BUA for us at the moment. The CDRs are already being HTTP POSTed to a URL, I can't change that as our billing depends on it. I can see the channel variable coming though in the POST content, so maybe I can frob the CDR script to give me what I want. Thanks again for the info. Cheers, Rich -- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
You subscribe to the events you're interested in with 'events' http://wiki.freeswitch.org/wiki/Event_socket#event There's no polling involved. FS will send all subscribed events through the socket, you just need to receive them. Use select()/poll()/equivalent to detect when data has arrived. Since you already have xml_cdr working that would be the best place to collect it, if you can add an extra DB insert in the handler. -Steve On 29 November 2012 11:58, Richard Gration <richgration@gmail.com> wrote:
Hi,
Thanks for your reply. I was wondering ...
If you listen to events then you should be able to reliably receive a hangup event containing the variables if you are still connected at that time.
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
If you want a 100% reliable method use CDRs.
mod_xml_cdr can submit call CDRs to a webserver just after call hangup. The XML is verbose and will contain a full call history and all channel variables. Because it's submitted ASAP you get the results in real time and reliable. If the module can't submit the CDRs it writes them to an error folder on disk where you can resubmit them.
Real time seems useful for your use-case, as your script would just need to check your DB whether the CDR had been submitted yet. The channel UUID can either be captured from events or specified in advance in the originate (originate_uuid). There's a uuid api call to generate them for you. I'd suggest looking at this method.
This is all great info, thanks :-) I'm capturing the uuid from the response from the originate command, that's no problem.
The box I'm doing this on is being a B2BUA for us at the moment. The CDRs are already being HTTP POSTed to a URL, I can't change that as our billing depends on it. I can see the channel variable coming though in the POST content, so maybe I can frob the CDR script to give me what I want.
Thanks again for the info.
Cheers, Rich
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
Hi Steve, Thanks for all your help, I have working code now :-) I don't know if this is a local configuration "feature" but the events are returned synchronously from the "event plain CHANNEL_HANGUP" call, so I just loop looking for my uuid. Cheers, Rich PS For anyone interested in some alpha code ... $dExt = $_GET['dExt']; $pin = $_GET['pin']; if ($dExt and $pin) { $fp = event_socket_create($host, $port, $password); # How shall we abuse the callee today? $wav1 = 'ivr/32000/ivr-douche_telecom.wav'; $wav2 = 'ivr/32000/ivr-thank_you_for_calling.wav'; # Place call and find uuid $cmd = "api originate {ignore_early_media=true,originate_timeout=30}sofia/external/677${dExt}@MGC '&play_and_get_digits(4 9 1 10000 # $wav1 $wav2 foo \d+)'"; $response = event_socket_request($fp, $cmd); $response = strip_cr($response); $bits = preg_split('/\s+/',$response); $uuid = $bits[1]; $continue = 1; $cmd = "event plain CHANNEL_HANGUP"; while ($continue) { error_log("running $cmd"); $response = event_socket_request($fp, $cmd); error_log("got $response"); if (preg_match("/$uuid/",$response)) { $continue = 0; } } $dbhRo = DbConnect::GetConnection('db-readonly'); $res_struct = mysql_query("SELECT strSrcMedia FROM cdr WHERE strSipSessionId = '$uuid'",$dbhRo); $res = mysql_fetch_array($res_struct); $pin_from_user = $res[0]; $result = $pin == $pin_from_user ? 1 : 0 ; echo "<pre>"; echo date('H:i:s') . "\n"; echo "uuid = $uuid\n"; echo "$result\n"; echo "</pre>"; # Close socket fclose($fp); } else { echo -1; } On 29 November 2012 13:56, Steven Ayre <steveayre@gmail.com> wrote:
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
You subscribe to the events you're interested in with 'events' http://wiki.freeswitch.org/wiki/Event_socket#event
There's no polling involved. FS will send all subscribed events through the socket, you just need to receive them. Use select()/poll()/equivalent to detect when data has arrived.
Since you already have xml_cdr working that would be the best place to collect it, if you can add an extra DB insert in the handler.
-Steve
On 29 November 2012 11:58, Richard Gration <richgration@gmail.com> wrote:
Hi,
Thanks for your reply. I was wondering ...
If you listen to events then you should be able to reliably receive a hangup event containing the variables if you are still connected at that time.
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
If you want a 100% reliable method use CDRs.
mod_xml_cdr can submit call CDRs to a webserver just after call hangup. The XML is verbose and will contain a full call history and all channel variables. Because it's submitted ASAP you get the results in real time and reliable. If the module can't submit the CDRs it writes them to an error folder on disk where you can resubmit them.
Real time seems useful for your use-case, as your script would just need to check your DB whether the CDR had been submitted yet. The channel UUID can either be captured from events or specified in advance in the originate (originate_uuid). There's a uuid api call to generate them for you. I'd suggest looking at this method.
This is all great info, thanks :-) I'm capturing the uuid from the response from the originate command, that's no problem.
The box I'm doing this on is being a B2BUA for us at the moment. The CDRs are already being HTTP POSTed to a URL, I can't change that as our billing depends on it. I can see the channel variable coming though in the POST content, so maybe I can frob the CDR script to give me what I want.
Thanks again for the info.
Cheers, Rich
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
In this case just receiving events until yours arrives is good enough. A regex for the UUID is My suggestion of select/poll/etc would be for a script using a single connection to start multiple calls, where you'd need to multiplex between detecting start call events (timeout/dbrow/etc) and incoming events. Since you're not sending anything else just receiving events works fine. It's be better to parse events and check the Unique-ID header, but a simple regex would work. It'd fail in cases like where calls are bridged (the uuid will appear in events of both call legs) but in this case there's only one leg so that's probably going to be good enough. As an optimisation, since you already know the UUID and only watch a single one on the connection you can use the 'myevents <uuid>' command - that'll limit it to only events for that channel, so you'll no longer waste processing on events for other channels and no longer need to check the uuid in the event. Since you're still always waiting for CHANNEL_HANGUP and assuming you still have the ESL connection up, does the variable you're looking appear in the hangup event? If so perhaps CDR isn't needed. The wait for the CHANNEL_HANGUP event isn't strictly speaking required, you could also poll the DB. But waiting for CHANNEL_HANGUP will have the advantage of not checking the DB until it expects the CDR to be available. Since On 29 November 2012 19:23, Richard Gration <richgration@gmail.com> wrote:
Hi Steve,
Thanks for all your help, I have working code now :-)
I don't know if this is a local configuration "feature" but the events are returned synchronously from the "event plain CHANNEL_HANGUP" call, so I just loop looking for my uuid.
Cheers, Rich
PS For anyone interested in some alpha code ...
$dExt = $_GET['dExt']; $pin = $_GET['pin'];
if ($dExt and $pin) { $fp = event_socket_create($host, $port, $password);
# How shall we abuse the callee today? $wav1 = 'ivr/32000/ivr-douche_telecom.wav'; $wav2 = 'ivr/32000/ivr-thank_you_for_calling.wav';
# Place call and find uuid $cmd = "api originate {ignore_early_media=true,originate_timeout=30}sofia/external/677${dExt}@MGC '&play_and_get_digits(4 9 1 10000 # $wav1 $wav2 foo \d+)'"; $response = event_socket_request($fp, $cmd); $response = strip_cr($response); $bits = preg_split('/\s+/',$response); $uuid = $bits[1];
$continue = 1; $cmd = "event plain CHANNEL_HANGUP"; while ($continue) { error_log("running $cmd"); $response = event_socket_request($fp, $cmd); error_log("got $response"); if (preg_match("/$uuid/",$response)) { $continue = 0; } }
$dbhRo = DbConnect::GetConnection('db-readonly'); $res_struct = mysql_query("SELECT strSrcMedia FROM cdr WHERE strSipSessionId = '$uuid'",$dbhRo); $res = mysql_fetch_array($res_struct); $pin_from_user = $res[0]; $result = $pin == $pin_from_user ? 1 : 0 ;
echo "<pre>"; echo date('H:i:s') . "\n"; echo "uuid = $uuid\n"; echo "$result\n"; echo "</pre>";
# Close socket fclose($fp); } else { echo -1; }
On 29 November 2012 13:56, Steven Ayre <steveayre@gmail.com> wrote:
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
You subscribe to the events you're interested in with 'events' http://wiki.freeswitch.org/wiki/Event_socket#event
There's no polling involved. FS will send all subscribed events through the socket, you just need to receive them. Use select()/poll()/equivalent to detect when data has arrived.
Since you already have xml_cdr working that would be the best place to collect it, if you can add an extra DB insert in the handler.
-Steve
On 29 November 2012 11:58, Richard Gration <richgration@gmail.com> wrote:
Hi,
Thanks for your reply. I was wondering ...
If you listen to events then you should be able to reliably receive a hangup event containing the variables if you are still connected at that
time.
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
If you want a 100% reliable method use CDRs.
mod_xml_cdr can submit call CDRs to a webserver just after call
hangup.
The XML is verbose and will contain a full call history and all channel variables. Because it's submitted ASAP you get the results in real time and reliable. If the module can't submit the CDRs it writes them to an error folder on disk where you can resubmit them.
Real time seems useful for your use-case, as your script would just need to check your DB whether the CDR had been submitted yet. The channel UUID can either be captured from events or specified in advance in the originate (originate_uuid). There's a uuid api call to generate them for you. I'd suggest looking at this method.
This is all great info, thanks :-) I'm capturing the uuid from the response from the originate command, that's no problem.
The box I'm doing this on is being a B2BUA for us at the moment. The CDRs are already being HTTP POSTed to a URL, I can't change that as our billing depends on it. I can see the channel variable coming though in the POST content, so maybe I can frob the CDR script to give me what I want.
Thanks again for the info.
Cheers, Rich
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE: http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
I would recommend that you adjust your DB check code to run in a loop. CDR submission occurs *after* CHANNEL_HANGUP - so you have a race condition and may check the DB before the CDR has been committed. You'd need to handle a) trying again after a short delay if the CDR isn't there yet and b) a timeout in case xml_cdr fails and the CDR isn't available (or the script'll keep running until it is). On 29 November 2012 19:23, Richard Gration <richgration@gmail.com> wrote:
Hi Steve,
Thanks for all your help, I have working code now :-)
I don't know if this is a local configuration "feature" but the events are returned synchronously from the "event plain CHANNEL_HANGUP" call, so I just loop looking for my uuid.
Cheers, Rich
PS For anyone interested in some alpha code ...
$dExt = $_GET['dExt']; $pin = $_GET['pin'];
if ($dExt and $pin) { $fp = event_socket_create($host, $port, $password);
# How shall we abuse the callee today? $wav1 = 'ivr/32000/ivr-douche_telecom.wav'; $wav2 = 'ivr/32000/ivr-thank_you_for_calling.wav';
# Place call and find uuid $cmd = "api originate {ignore_early_media=true,originate_timeout=30}sofia/external/677${dExt}@MGC '&play_and_get_digits(4 9 1 10000 # $wav1 $wav2 foo \d+)'"; $response = event_socket_request($fp, $cmd); $response = strip_cr($response); $bits = preg_split('/\s+/',$response); $uuid = $bits[1];
$continue = 1; $cmd = "event plain CHANNEL_HANGUP"; while ($continue) { error_log("running $cmd"); $response = event_socket_request($fp, $cmd); error_log("got $response"); if (preg_match("/$uuid/",$response)) { $continue = 0; } }
$dbhRo = DbConnect::GetConnection('db-readonly'); $res_struct = mysql_query("SELECT strSrcMedia FROM cdr WHERE strSipSessionId = '$uuid'",$dbhRo); $res = mysql_fetch_array($res_struct); $pin_from_user = $res[0]; $result = $pin == $pin_from_user ? 1 : 0 ;
echo "<pre>"; echo date('H:i:s') . "\n"; echo "uuid = $uuid\n"; echo "$result\n"; echo "</pre>";
# Close socket fclose($fp); } else { echo -1; }
On 29 November 2012 13:56, Steven Ayre <steveayre@gmail.com> wrote:
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
You subscribe to the events you're interested in with 'events' http://wiki.freeswitch.org/wiki/Event_socket#event
There's no polling involved. FS will send all subscribed events through the socket, you just need to receive them. Use select()/poll()/equivalent to detect when data has arrived.
Since you already have xml_cdr working that would be the best place to collect it, if you can add an extra DB insert in the handler.
-Steve
On 29 November 2012 11:58, Richard Gration <richgration@gmail.com> wrote:
Hi,
Thanks for your reply. I was wondering ...
If you listen to events then you should be able to reliably receive a hangup event containing the variables if you are still connected at that
time.
... how I listen for these events. Is it just a case of polling the socket for them at frequent enough intervals?
If you want a 100% reliable method use CDRs.
mod_xml_cdr can submit call CDRs to a webserver just after call
hangup.
The XML is verbose and will contain a full call history and all channel variables. Because it's submitted ASAP you get the results in real time and reliable. If the module can't submit the CDRs it writes them to an error folder on disk where you can resubmit them.
Real time seems useful for your use-case, as your script would just need to check your DB whether the CDR had been submitted yet. The channel UUID can either be captured from events or specified in advance in the originate (originate_uuid). There's a uuid api call to generate them for you. I'd suggest looking at this method.
This is all great info, thanks :-) I'm capturing the uuid from the response from the originate command, that's no problem.
The box I'm doing this on is being a B2BUA for us at the moment. The CDRs are already being HTTP POSTed to a URL, I can't change that as our billing depends on it. I can see the channel variable coming though in the POST content, so maybe I can frob the CDR script to give me what I want.
Thanks again for the info.
Cheers, Rich
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE: http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
-- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
On 29 November 2012 19:43, Steven Ayre <steveayre@gmail.com> wrote:
I would recommend that you adjust your DB check code to run in a loop. CDR submission occurs after CHANNEL_HANGUP - so you have a race condition and may check the DB before the CDR has been committed. You'd need to handle a) trying again after a short delay if the CDR isn't there yet and b) a timeout in case xml_cdr fails and the CDR isn't available (or the script'll keep running until it is).
I agree the script needs work, particularly in error handling :-) I also need to set an alarm before I go into read event loop I think. I've had a few zombies to deal with so far ... I tried using myevents but I didn't read anything. I might try and suss that out at some point. R -- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
Forgot to say, no I don't get the channel var in the hangup event. I thought I would too. -- Once our basic material needs are met - in my utopia, anyway - life becomes a perpetual celebration in which everyone has a talent to contribute. But we cannot levitate ourselves into that blessed condition by wishing it. We need to brace ourselves for a struggle against terrifying obstacles, both of our own making and imposed by the natural world. And the first step is to recover from the delusion that is positive thinking. -- Barbara Ehrenreich
participants (2)
-
Richard Gration
-
Steven Ayre