root/archive/2.0/amp_conf/bin/php-asmanager.php

Revision 774, 18.7 kB (checked in by rcourtna, 8 years ago)

database_get is broken with * 1.2. "Value:" no longer occurs at position 0 in the response string from *.

We should probably use the phpagi as packaged on sourceforge, rather than manage our own version. Old Upgrade scripts would need to use the customized version for backwards compat tho .. yuck.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2
3 /**
4 * phpagi-asmanager.php : PHP Asterisk Manager functions
5 * Website: http://phpagi.sourceforge.net
6 *
7 * Copyright (c) 2004 Matthew Asham <matthewa@bcwireless.net>
8 * All Rights Reserved.
9 *
10 * This software is released under the terms of the GNU Public License v2
11 *  A copy of which is available from http://www.fsf.org/licenses/gpl.txt
12 *
13 *
14 *  You are requested to drop me an Email letting me know that you're
15 *  using it.  This is more of a courtesy than anything else, but I am
16 *  interested to know how it is being used.
17 *
18 * @package phpAGI
19 * @version 2.0
20 */
21
22
23 /**
24 * Written for PHP 4.3.4, should work with older PHP 4.x versions. 
25 * Please submit bug reports, patches, etc to http://sourceforge.net/projects/phpagi/
26 * Gracias. :)
27 *
28 */
29   define('AST_CONFIG_DIR', '/etc/asterisk/');
30   define('AST_SPOOL_DIR', '/var/spool/asterisk/');
31   define('AST_TMP_DIR', AST_SPOOL_DIR . '/tmp/');
32   define('DEFAULT_PHPAGI_CONFIG', AST_CONFIG_DIR . '/phpagi.conf');
33
34   define("AMP_CONF", "/etc/amportal.conf");
35
36   define('AST_DIGIT_ANY', '0123456789#*');
37
38   define('AGI_PORT', 4573);
39
40   define('AGIRES_OK', 200);
41
42
43   define('AST_STATE_DOWN', 0);
44   define('AST_STATE_RESERVED', 1);
45   define('AST_STATE_OFFHOOK', 2);
46   define('AST_STATE_DIALING', 3);
47   define('AST_STATE_RING', 4);
48   define('AST_STATE_RINGING', 5);
49   define('AST_STATE_UP', 6);
50   define('AST_STATE_BUSY', 7);
51   define('AST_STATE_DIALING_OFFHOOK', 8);
52   define('AST_STATE_PRERING', 9);
53
54
55 /**
56 * Asterisk Manager class
57 *
58 * @link http://www.voip-info.org/wiki-Asterisk+config+manager.conf
59 * @link http://www.voip-info.org/wiki-Asterisk+manager+API
60 * @example examples/sip_show_peer.php Get information about a sip peer
61 * @package phpAGI
62 */
63 class AGI_AsteriskManager
64 {
65     /**
66     * Config variables
67     *
68     * @var array
69     * @access public
70     */
71     var $config;
72     
73     /**
74     * Socket
75     *
76     * @access public
77     */
78     var $socket = NULL;
79     
80     /**
81     * Server we are connected to
82     *
83     * @access public
84     * @var string
85     */
86     var $server;
87     
88     /**
89     * Port on the server we are connected to
90     *
91     * @access public
92     * @var integer
93     */
94     var $port;
95     
96     /**
97     * Parent AGI
98     *
99     * @access private
100     * @var AGI
101     */
102     var $pagi;
103     
104     /**
105     * Event Handlers
106     *
107     * @access private
108     * @var array
109     */
110     var $event_handlers;
111     
112     /**
113     * Constructor
114     *
115     * @param string $config is the name of the config file to parse or a parent agi from which to read the config
116     * @param array $optconfig is an array of configuration vars and vals, stuffed into $this->config['asmanager']
117     */
118     function AGI_AsteriskManager($config=NULL, $optconfig=array())
119     {
120         // load config
121         if(!is_null($config) && file_exists($config))
122             $this->config = parse_ini_file($config, true);
123         elseif(file_exists(DEFAULT_PHPAGI_CONFIG))
124             $this->config = parse_ini_file(DEFAULT_PHPAGI_CONFIG, true);
125         
126         // If optconfig is specified, stuff vals and vars into 'asmanager' config array.
127         foreach($optconfig as $var=>$val)
128             $this->config['asmanager'][$var] = $val;
129         
130         // add default values to config for uninitialized values
131         if(!isset($this->config['asmanager']['server'])) $this->config['asmanager']['server'] = 'localhost';
132         if(!isset($this->config['asmanager']['port'])) $this->config['asmanager']['port'] = 5038;
133         if(!isset($this->config['asmanager']['username'])) $this->config['asmanager']['username'] = 'phpagi';
134         if(!isset($this->config['asmanager']['secret'])) $this->config['asmanager']['secret'] = 'phpagi';
135     }
136     
137     /**
138     * Send a request
139     *
140     * @param string $action
141     * @param array $parameters
142     * @return array of parameters
143     */
144     function send_request($action, $parameters=array())
145     {
146         $req = "Action: $action\r\n";
147         foreach($parameters as $var=>$val)
148             $req .= "$var: $val\r\n";
149         $req .= "\r\n";
150         fwrite($this->socket, $req);
151         return $this->wait_response();
152     }
153     
154     /**
155     * Wait for a response
156     *
157     * If a request was just sent, this will return the response.
158     * Otherwise, it will loop forever, handling events.
159     *
160     * @param boolean $allow_timeout if the socket times out, return an empty array
161     * @return array of parameters, empty on timeout
162     */
163     function wait_response($allow_timeout=false)
164     {
165         $timeout = false;
166         do
167         {
168             $type = NULL;
169             $parameters = array();
170         
171             $buffer = trim(fgets($this->socket, 4096));
172             while($buffer != '')
173             {
174             $a = strpos($buffer, ':');
175             if($a)
176             {
177             if(!count($parameters)) // first line in a response?
178             {
179             $type = strtolower(substr($buffer, 0, $a));
180             if(substr($buffer, $a + 2) == 'Follows')
181             {
182                 // A follows response means there is a miltiline field that follows.
183                 $parameters['data'] = '';
184                 $buff = fgets($this->socket, 4096);
185                 while(substr($buff, 0, 6) != '--END ')
186                 {
187                 $parameters['data'] .= $buff;
188                 $buff = fgets($this->socket, 4096);
189                 }
190             }
191             }
192         
193             // store parameter in $parameters
194             $parameters[substr($buffer, 0, $a)] = substr($buffer, $a + 2);
195             }
196             $buffer = trim(fgets($this->socket, 4096));
197             }
198         
199             // process response
200             switch($type)
201             {
202             case '': // timeout occured
203             $timeout = $allow_timeout;
204             break;
205             case 'event':
206             $this->process_event($parameters);
207             break;
208             case 'response':
209             break;
210             default:
211             $this->log('Unhandled response packet from Manager: ' . print_r($parameters, true));
212             break;
213             }
214         } while($type != 'response' && !$timeout);
215         return $parameters;
216     }
217     
218     /**
219     * Connect to Asterisk
220     *
221     * @example examples/sip_show_peer.php Get information about a sip peer
222     *
223     * @param string $server
224     * @param string $username
225     * @param string $secret
226     * @return boolean true on success
227     */
228     function connect($server=NULL, $username=NULL, $secret=NULL)
229     {
230         // use config if not specified
231         if(is_null($server)) $server = $this->config['asmanager']['server'];
232         if(is_null($username)) $username = $this->config['asmanager']['username'];
233         if(is_null($secret)) $secret = $this->config['asmanager']['secret'];
234         
235         // get port from server if specified
236         if(strpos($server, ':') !== false)
237         {
238             $c = explode(':', $server);
239             $this->server = $c[0];
240             $this->port = $c[1];
241         }
242         else
243         {
244             $this->server = $server;
245             $this->port = $this->config['asmanager']['port'];
246         }
247         
248         // connect the socket
249         $errno = $errstr = NULL;
250         $this->socket = @fsockopen($this->server, $this->port, $errno, $errstr);
251         if($this->socket == false)
252         {
253             $this->log("Unable to connect to manager {$this->server}:{$this->port} ($errno): $errstr");
254             return false;
255         }
256         
257         // read the header
258         $str = fgets($this->socket);
259         if($str == false)
260         {
261             // a problem.
262             $this->log("Asterisk Manager header not received.");
263             return false;
264         }
265         else
266         {
267             // note: don't $this->log($str) until someone looks to see why it mangles the logging
268         }
269         
270         // login
271         $res = $this->send_request('login', array('Username'=>$username, 'Secret'=>$secret));
272         if($res['Response'] != 'Success')
273         {
274             $this->log("Failed to login.");
275             $this->disconnect();
276             return false;
277         }
278         return true;
279     }
280     
281     /**
282     * Disconnect
283     *
284     * @example examples/sip_show_peer.php Get information about a sip peer
285     */
286     function disconnect()
287     {
288         $this->logoff();
289         fclose($this->socket);
290     }
291     
292     /**
293     * Set Absolute Timeout
294     *
295     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+AbsoluteTimeout
296     * @param string $channel
297     * @param integer $timeout
298     */
299     function AbsoluteTimeout($channel, $timeout)
300     {
301         return $this->send_request('AbsoluteTimeout', array('Channel'=>$channel, 'Timeout'=>$timeout));
302     }
303     
304     /**
305     * Change monitoring filename of a channel
306     *
307     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ChangeMonitor
308     * @param string $channel
309     * @param string $file
310     */
311     function ChangeMonitor($channel, $file)
312     {
313         return $this->send_request('ChangeMontior', array('Channel'=>$channel, 'File'=>$file));
314     }
315     
316     /**
317     * Execute Command
318     *
319     * @example examples/sip_show_peer.php Get information about a sip peer
320     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Command
321     * @link http://www.voip-info.org/wiki-Asterisk+CLI
322     * @param string $commadn
323     */
324     function Command($command)
325     {   
326         return $this->send_request('Command', array('Command'=>$command));
327     }
328     
329     /**
330     * Enable/Disable sending of events to this manager
331     *
332     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Events
333     * @param string $eventmask is either 'on', 'off', or 'system,call,log'
334     */
335     function Events($eventmask)
336     {
337         return $this->send_request('Events', array('EventMask'=>$eventmask));
338     }
339     
340     /**
341     * Check Extension Status
342     *
343     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ExtensionState
344     * @param string $exten
345     * @param string $context
346     * @param string $actionid
347     */
348     function ExtensionState($exten, $context, $actionid)
349     {
350         return $this->send_request('ExtensionState', array('Exten'=>$exten, 'Context'=>$context, 'ActionID'=>$actionid));
351     }
352     
353     /**
354     * Gets a Channel Variable
355     *
356     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+GetVar
357     * @param string $channel
358     * @param string $variable
359     */
360     function GetVar($channel, $variable)
361     {
362         return $this->send_request('GetVar', array('Channel'=>$channel, 'Variable'=>$variable));
363     }
364     
365     /**
366     * Hangup Channel
367     *
368     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Hangup
369     * @param string $channel
370     */
371     function Hangup($channel)
372     {
373         return $this->send_request('Hangup', array('Channel'=>$channel));
374     }
375     
376     /**
377     * List IAX Peers
378     *
379     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+IAXpeers
380     */
381     function IAXPeers()
382     {
383         return $this->send_request('IAXPeers');
384     }
385     
386     /**
387     * List available manager commands
388     *
389     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ListCommands
390     */
391     function ListCommands()
392     {
393         return $this->send_request('ListCommands');
394     }
395     
396     /**
397     * Logoff Manager
398     *
399     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Logoff
400     */
401     function Logoff()
402     {
403         return $this->send_request('Logoff');
404     }
405     
406     /**
407     * Check Mailbox Message Count
408     *
409     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+MailboxCount
410     * @param string $mailbox
411     */
412     function MailboxCount($mailbox)
413     {
414         return $this->send_request('MailboxCount', array('Mailbox'=>$mailbox));
415     }
416     
417     /**
418     * Check Mailbox
419     *
420     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+MailboxStatus
421     * @param string $mailbox
422     */
423     function MailboxStatus($mailbox)
424     {   
425         return $this->send_request('MailboxStatus', array('Mailbox'=>$mailbox));
426     }
427     
428     /**
429     * Monitor a channel
430     *
431     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Monitor
432     * @param string $channel
433     * @param string $file
434     */
435     function Monitor($channel, $file)
436     {
437         return $this->send_request('Monitor', array('Channel'=>$channel, 'File'=>$file));
438     }
439     
440     /**
441     * Originate Call
442     *
443     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Originate
444     * @param string $channel
445     * @param string $exten
446     * @param string $context
447     * @param string $priority
448     * @param integer $timeout
449     * @param string $callerid
450     * @param string $variable
451     * @param string $account
452     * @param string $application
453     * @param string $data
454     */
455     function Originate($channel, $exten, $context, $priority, $timeout, $callerid, $variable, $account, $application, $data)
456     {
457         $parameters = array();
458         if($channel) $parameters['Channel'] = $channel;
459         if($exten) $parameters['Exten'] = $exten;
460         if($context) $parameters['Context'] = $context;
461         if($priority) $parameters['Priority'] = $priority;
462         if($timeout) $parameters['Timeout'] = $timeout;
463         if($callerid) $parameters['CallerID'] = $callerid;
464         if($variable) $parameters['Variable'] = $variable;
465         if($account) $parameters['Account'] = $account;
466         if($application) $parameters['Application'] = $application;
467         if($data) $parameters['Data'] = $data;
468         return $this->send_request('Originate', $parameters);
469     }   
470     
471     /**
472     * List parked calls
473     *
474     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ParkedCalls
475     */
476     function ParkedCalls()
477     {
478         return $this->send_request('ParkedCalls');
479     }
480     
481     /**
482     * Ping
483     *
484     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Ping
485     */
486     function Ping()
487     {
488         return $this->send_request('Ping');
489     }
490     
491     /**
492     * Queues
493     *
494     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Queues
495     */
496     function Queues()
497     {
498         return $this->send_request('Queues');
499     }
500     
501     /**
502     * Queue Status
503     *
504     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+QueueStatus
505     */
506     function QueueStatus()
507     {
508         return $this->send_request('QueueStatus');
509     }
510     
511     /**
512     * Redirect
513     *
514     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Redirect
515     * @param string $channel
516     * @param string $extrachannel
517     * @param string $exten
518     * @param string $context
519     * @param string $priority
520     */
521     function Redirect($channel, $extrachannel, $exten, $context, $priority)
522     {
523         return $this->send_request('Redirect', array('Channel'=>$channel, 'ExtraChannel'=>$extrachannel, 'Exten'=>$exten,
524                                 'Context'=>$context, 'Priority'=>$priority));
525     }
526     
527     /**
528     * Set the CDR UserField
529     */
530     function SetCDRUserField()
531     {
532         // XXX need to look at source to find this function...
533         return $this->send_request('SetCDRUserField');
534     }
535     
536     /**
537     * Set Channel Variable
538     *
539     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+SetVar
540     * @param string $channel
541     * @param string $variable
542     * @param string $value
543     */
544     function SetVar($channel, $variable, $value)
545     {
546         return $this->send_request('SetVar', array('Channel'=>$channel, 'Variable'=>$variable, 'Value'=>$value));
547     }
548     
549     /**
550     * List SIP Peers
551     */
552     function SIPpeers()
553     {
554     // XXX need to look at source to find this function...
555         return $this->send_request('SIPpeers');
556     }
557     
558     /**
559     * Channel Status
560     *
561     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Status
562     * @param string $channel
563     */
564     function Status($channel)
565     {   
566         return $this->send_request('Status', array('Channel'=>$channel));
567     }
568     
569     /**
570     * Stop monitoring a channel
571     *
572     * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+StopMonitor
573     * @param string $channel
574     */
575     function StopMontor($channel)
576     {
577         return $this->send_request('StopMonitor', array('Channel'=>$channel));
578     }
579     
580     /**
581     * Dial over Zap channel while offhook
582     */
583     function ZapDialOffhook()
584     {
585         // XXX need to look at source to find this function...
586         return $this->send_request('ZapDialOffhook');
587     }
588     
589     /**
590     * Toggle Zap channel Do Not Disturb status OFF
591     */
592     function ZapDNDoff()
593     {
594         // XXX need to look at source to find this function...
595         return $this->send_request('ZapDNDoff');
596     }
597     
598     /**
599     * Toggle Zap channel Do Not Disturb status ON
600     */
601     function ZapDNDon()
602     {
603         // XXX need to look at source to find this function...
604         return $this->send_request('ZapDNDon');
605     }
606     
607     /**
608     * Hangup Zap Channel
609     */
610     function ZapHangup()
611     {
612         // XXX need to look at source to find this function...
613         return $this->send_request('ZapHangup');
614     }
615     
616     /**
617     * Transfer Zap Channel
618     */
619     function ZapTransfer()
620     {
621         // XXX need to look at source to find this function...
622         return $this->send_request('ZapTransfer');
623     }
624     
625     /*
626     * Log a message
627     *
628     * @param string $message
629     * @param integer $level from 1 to 4
630     */
631     function log($message, $level=1)
632     {
633         if($this->pagi != false)
634             $this->pagi->conlog($message, $level);
635         else
636             error_log(date('r') . ' - ' . $message);
637     }
638     
639     /**
640     * Add event handler
641     *
642     * Known Events include ( http://www.voip-info.org/wiki-asterisk+manager+events )
643     *   Link - Fired when two voice channels are linked together and voice data exchange commences.
644     *   Unlink - Fired when a link between two voice channels is discontinued, for example, just before call completion.
645     *   Newexten -
646     *   Hangup -
647     *   Newchannel -
648     *   Newstate -
649     *   Reload - Fired when the "RELOAD" console command is executed.
650     *   Shutdown -
651     *   ExtensionStatus -
652     *   Rename -
653     *   Newcallerid -
654     *   Alarm -
655     *   AlarmClear -
656     *   Agentcallbacklogoff -
657     *   Agentcallbacklogin -
658     *   Agentlogoff -
659     *   MeetmeJoin -
660     *   MessageWaiting -
661     *   join -
662     *   leave -
663     *   AgentCalled -
664     *   ParkedCall -
665     *   Cdr -
666     *   ParkedCallsComplete -
667     *   QueueParams -
668     *   QueueMember -
669     *   QueueStatusEnd -
670     *   Status -
671     *   StatusComplete -
672     *   ZapShowChannels -
673     *   ZapShowChannelsComplete -
674     *
675     * @param string $event type or * for default handler
676     * @param string $callback function
677     * @return boolean sucess
678     */
679     function add_event_handler($event, $callback)
680     {
681         $event = strtolower($event);
682         if(isset($this->event_handlers[$event]))
683         {
684             $this->log("$event handler is already defined, not over-writing.");
685             return false;
686         }
687         $this->event_handlers[$event] = $callback;
688         return true;
689     }
690     
691     /**
692     * Process event
693     *
694     * @access private
695     * @param array $parameters
696     * @return mixed result of event handler or false if no handler was found
697     */
698     function process_event($parameters)
699     {
700         $ret = false;
701         $e = strtolower($parameters['Event']);
702         $this->log("Got event.. $e");       
703         
704         $handler = '';
705         if(isset($this->event_handlers[$e])) $handler = $this->event_handlers[$e];
706         elseif(isset($this->event_handlers['*'])) $handler = $this->event_handlers['*'];
707         
708         if(function_exists($handler))
709         {
710             $this->log("Execute handler $handler");
711             $ret = $handler($e, $parameters, $this->server, $this->port);
712         }
713         else
714             $this->log("No event handler for event '$e'");
715         return $ret;
716     }
717     
718     /** Show all entries in the asterisk database
719      * @return Array associative array of key=>value
720      */
721     function database_show() {
722         $r = $this->command("database show");
723         
724         $data = explode("\n",$r["data"]);
725         $db = array();
726         
727         foreach ($data as $line) {
728             $temp = explode(":",$line);
729             $db[ trim($temp[0]) ] = trim($temp[1]);
730         }
731         return $db;
732     }
733     
734     /** Add an entry to the asterisk database
735      * @param string $family    The family name to use
736      * @param string $key        The key name to use
737      * @param mixed $value        The value to add
738      * @return bool True if successful
739      */
740     function database_put($family, $key, $value) {
741         $r = $this->command("database put ".str_replace(" ","/",$family)." ".str_replace(" ","/",$key)." ".$value);
742         return (bool)strstr($r["data"], "success");
743     }
744     
745     /** Get an entry from the asterisk database
746      * @param string $family    The family name to use
747      * @param string $key        The key name to use
748      * @return mixed Value of the key, or false if error
749      */
750     function database_get($family, $key) {
751         $r = $this->command("database get ".str_replace(" ","/",$family)." ".str_replace(" ","/",$key));
752         $data = strpos($r["data"],"Value:");
753         if ($data !== false) {
754             return trim(substr($r["data"],6+$data));
755         } else {
756             return false;
757         }
758     }
759     
760     /** Delete an entry from the asterisk database
761      * @param string $family    The family name to use
762      * @param string $key        The key name to use
763      * @return bool True if successful
764      */
765     function database_del($family, $key) {
766         $r = $this->command("database del ".str_replace(" ","/",$family)." ".str_replace(" ","/",$key));
767         return (bool)strstr($r["data"], "removed");
768     }
769     
770     /** Delete a family from the asterisk database
771      * @param string $family    The family name to use
772      * @return bool True if successful
773      */
774     function database_deltree($family) {
775         $r = $this->command("database deltree ".str_replace(" ","/",$family));
776         return (bool)strstr($r["data"], "removed");
777     }
778 }
779 ?>
Note: See TracBrowser for help on using the browser.