Bill, When I connect and do a DTMF digit when events all is on: event "events DTMF" gets these: Content-Length: 3690 Content-Type: text/event-plain Channel-State: CS_EXECUTE Channel-State-Number: 4 Channel-Name: sofia/default/1008%4010.0.1.250%3A5060 Unique-ID: f3b34b4b-a1bb-4caf-b49d-cd7f277a9ae7Call-Direction: inboundAnswer-State: answeredChannel-Read-Codec-Name: PCMU Channel-Read-Codec-Rate: 8000 Channel-Write-Codec-Name: PCMU Channel-Write-Codec-Rate: 8000 Caller-Username: 1008 Caller-Dialplan: XML Caller-Caller-ID-Name: Brian%20West Caller-Caller-ID-Number: 1008 Caller-Network-Addr: 10.0.1.10 Caller-Destination-Number: 9999 Caller-Unique-ID: f3b34b4b-a1bb-4caf-b49d-cd7f277a9ae7 Caller-Source: mod_sofia Caller-Context: default Caller-Channel-Name: sofia/default/1008%4010.0.1.250%3A5060 Caller-Channel-Created-Time: 1199497969261353 Caller-Channel-Answered-Time: 1199497969345822 Caller-Channel-Hangup-Time: 0 Caller-Channel-Transfer-Time: 0 Caller-Screen-Bit: yes Caller-Privacy-Hide-Name: no Caller-Privacy-Hide-Number: no variable_sip_authorized: true variable_sip_mailbox: 1008 variable_sip_auth_username: 1008 variable_sip_auth_realm: 10.0.1.250 variable_mailbox: 1008 variable_record_stereo: true variable_accountcode: 1008 variable_user_context: default variable_effective_caller_id_name: Extension%201008 variable_effective_caller_id_number: 1008 variable_sip_from_user: 1008 variable_sip_from_port: 5060 variable_sip_from_uri: 1008%4010.0.1.250%3A5060 variable_sip_from_uri: 1008%4010.0.1.250%3A5060 variable_sip_from_host: 10.0.1.250 variable_sip_from_user_stripped: 1008 variable_sofia_profile_name: default variable_sip_req_user: 9999 variable_sip_req_port: 5060 variable_sip_req_uri: 9999%4010.0.1.250%3A5060 variable_sip_req_host: 10.0.1.250 variable_sip_to_user: 9999 variable_sip_to_port: 5060 variable_sip_to_uri: 9999%4010.0.1.250%3A5060 variable_sip_to_host: 10.0.1.250 variable_sip_contact_user: 1008 variable_sip_contact_port: 5060 variable_sip_contact_uri: 1008%4010.0.1.10%3A5060 variable_sip_contact_host: 10.0.1.10 variable_channel_name: sofia/default/1008%4010.0.1.250%3A5060 variable_sip_call_id: 5898854f-9bcbf32d%4010.0.1.10 variable_sip_user_agent: Linksys/SPA962-5.1.7 variable_sip_via_host: 10.0.1.10 variable_sip_via_port: 5060 variable_sip_via_rport: 5060 variable_max_forwards: 70 variable_presence_id: 1008%4010.0.1.250 variable_switch_r_sdp: v%3D0%0D%0Ao%3D-%201678769%201678769%20IN %20IP4%2010.0.1.10%0D%0As%3D-%0D%0Ac%3DIN%20IP4%2010.0.1.10%0D%0At %3D0%200%0D%0Am%3Daudio%2016414%20RTP/AVP %200%202%204%208%2018%2096%2097%2098%20101%0D%0Aa%3Drtpmap%3A0%20PCMU/ 8000%0D%0Aa%3Drtpmap%3A2%20G726-32/8000%0D%0Aa%3Drtpmap %3A4%20G723/8000%0D%0Aa%3Drtpmap%3A8%20PCMA/8000%0D%0Aa%3Drtpmap %3A18%20G729a/8000%0D%0Aa%3Drtpmap%3A96%20G726-40/8000%0D%0Aa%3Drtpmap %3A97%20G726-24/8000%0D%0Aa%3Drtpmap%3A98%20G726-16/8000%0D%0Aa %3Drtpmap%3A101%20telephone-event/8000%0D%0Aa%3Dfmtp%3A101%200-15%0D %0Aa%3Dptime%3A30%0D%0A variable_remote_media_ip: 10.0.1.10 variable_remote_media_port: 16414 variable_read_codec: PCMU variable_read_rate: 8000 variable_write_codec: PCMU variable_write_rate: 8000 variable_use_profile: nat variable_numbering_plan: US variable_default_gateway: asterlink.com variable_default_area_code: 918 variable_user_name: default variable_domain_name: 10.0.1.250 variable_local_media_ip: 10.0.1.250 variable_local_media_port: 16414 variable_endpoint_disposition: ANSWER DTMF-Digit: 5 DTMF-Duration: 720 Event-Name: DTMF Core-UUID: 0b75d60f-25cb-4be0-9f3c-e70bf91eaaa9 FreeSWITCH-Hostname: localhost.localdomain FreeSWITCH-IPv4: 10.0.1.250 FreeSWITCH-IPv6: 127.0.0.1 Event-Date-Local: 2008-01-04%2019%3A52%3A54 Event-Date-GMT: Sat,%2005%20Jan%202008%2001%3A52%3A54%20GMT Event-Date-timestamp: 1199497974959896 Event-Calling-File: switch_channel.c Event-Calling-Function: switch_channel_dequeue_dtmf Event-Calling-Line-Number: 275 Thats the DTMF event :) /b On Jan 4, 2008, at 7:04 PM, Bill Binko wrote:
I've been trying to implement a basic IVR that interacts with our database using PHP. With some help on IRC, I've created an Event Socket interface for PHP. It is rudimentary at this point, and not ready for prime-time, but it is working -- FreeSwitch connects to my process when a call comes in, sends the basic context info, and I can issue calls.
After a call to "event plain ALL", I start receiving events. Mainly HEARTBEAT events, with a few others thrown in.
What I'm NOT seeing is any DTMF events. Now, I know that the DTMF codes are recognized by other parts of FreeSwitch, such as the IVR, and I've ensure that my SIP client is sending them in-audio, SIP INFO and RFC2833. However, I'm not getting anything when I connect and press buttons.
I have some other issues with the Event Socket, that I'd love to get through, but without the DTMF, most of the applications we're working on won't go very far.
Is there anything I have to do to be able to get these Events to show up?
Thanks Bill
PS: I've attached the EventSocketListener PHP class. You can run it from the command line and it will listen on port 9090 -- obviously, it's not clean nor done, but it is working
#!/usr/local/bin/php <?php
/** * Based loosely on the NET_Server code in PEAR. * This is only an example - considerable additional work is needed * Specifically, the code in the handleConnection method should be * handled in a subclass * * */
class Message { var $properties = array(); var $content = null; }
class EventSocketListener {
var $host; var $port; var $sock; var $is_parent = true; var $clientInfo; var $clientFD;
var $connectionContext = array();
function &create($port, $host = "localhost") { $esl = new EventSocketListener; $esl->port = $port; $esl->host = $host; if (!function_exists('socket_create')) { return PEAR::raiseError('Sockets extension not available.'); } return $esl; }
function start() { if (($this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; }
if (!socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 1)) { echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL; }
if (socket_bind($this->sock, $this->host, $this->port) === false) { echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($this->sock)) . "\n"; }
if (socket_listen($this->sock, 5) === false) { echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($this->sock)) . "\n"; }
// Dear children, please do not become zombies pcntl_signal(SIGCHLD, SIG_IGN);
// wait for incmoning connections while (true) { // new connection if(($fd = socket_accept($this->sock))) { $pid = pcntl_fork(); if($pid == -1) { return PEAR::raiseError('Could not fork child process.'); } // This is the child => handle the request elseif($pid == 0) { // this is not the parent $this->_isParent = false; // store the new file descriptor $this->clientFD = $fd;
$peer_host = ""; $peer_port = ""; socket_getpeername($this->clientFD, $peer_host, $peer_port); $this->clientInfo = array( "host" => $peer_host, "port" => $peer_port, "connectOn" => time() ); $this->handleConnection(); socket_shutdown($this->clientFD, 2); socket_close($this->clientFD); } else /* Parent does nothing */ { } } } }
function handleConnection() { $fd = $this->clientFD; //first, read headers & setup a state for this connection $line = ""; socket_write($fd, "CONNECT\n\n"); do { $line = socket_read($fd, 2048, PHP_NORMAL_READ); if (trim($line) == "") break; //we got a header, we need to add it to the list($key, $value) = explode(":", $line); $key = trim($key); $value = trim(urldecode($value)); $this->connectionContext[$key] = $value; } while ($line != "");
// print_r($this->connectionContext); $this->callConnected();
exit();
}
function processMessages($returnOnReply = false) { $fd = $this->clientFD; $result = new Message(); $props = array(); while (true) { do { $line = @socket_read($fd, 2048, PHP_NORMAL_READ); if (socket_last_error($fd) == 104) return null; if ($line == null || $line == FALSE || trim($line) == "") break; //we got a header, we need to add it to the message list($key, $value) = explode(":", $line); $key = trim($key); $value = trim(urldecode($value)); $props[$key] = $value; } while ($line != ""); $result->properties = $props;
if (isset($props['Content-Length'])) { $length = $props['Content-Length']; print("Reading content - $length\n"); $data = socket_read($fd, $length); $result->content = $data; } if (isset($props['Content-Type'])) { $type = $props['Content-Type']; if ($returnOnReply && ($type == "command/reply" || $type == "api/response")) { return $result; } else if ($type == "text/event-plain") //only plain events for now { $this->handleEvent($result); } } else { print("UNKNOWN MESSAGE: \n"); print_r($result); } } }
function invokeCommand($command) { //Send the command print("Invoking: $command\n"); $this->sendCommand($command); // Wait for the response $result = $this->processMessages(true); return $result; }
function sendCommand($command) { $fd = $this->clientFD; socket_write($fd, trim($command) . "\n\n"); }
/*-----------------------------------------------------*/ /* Abstract Methods - should move to subclass*/
function callConnected() { print_r($this->connectionContext); print("----------------\n"); $result = $this->invokeCommand("log DEBUG"); print_r($result); $result = $this->invokeCommand("event plain ALL"); print_r($result);
$this->processMessages(false); print("DONE PROCESSING MESSAGES"); print_r($this->connectionContext); }
function handleCommandResponse($response) { print("Recieved Unhandled Response:\n"); print_r($response); }
function handleEvent($event) { print("Recieved Unhandled Event:\n"); print_r($event); } }
// create a server that forks new processes $server = &EventSocketListener::create(9090);
// start the server $server->start(); ?>
_______________________________________________ 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