Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit 4c08a31

Browse files
author
Ivan Poddubny
committed
Totally rewritten wait_responce in asmanager
* much cleaner code * sends every AMI request with an ActionID * added support for eventlists
1 parent fa5af89 commit 4c08a31

File tree

1 file changed

+100
-58
lines changed

1 file changed

+100
-58
lines changed

phpagi-asmanager.php

Lines changed: 100 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class AGI_AsteriskManager
8888
*/
8989
private $event_handlers;
9090

91+
private $_buffer = NULL;
92+
9193
/**
9294
* Whether we're successfully logged in
9395
*
@@ -132,19 +134,79 @@ function AGI_AsteriskManager($config=NULL, $optconfig=array())
132134
function send_request($action, $parameters=array())
133135
{
134136
$req = "Action: $action\r\n";
135-
foreach($parameters as $var=>$val)
136-
{
137-
// Модификация. Передача нескольких параметров
138-
if (is_array($val))
139-
foreach ($val as $l){
140-
$req .= "$var: $l\r\n";
137+
$actionid = null;
138+
foreach ($parameters as $var=>$val) {
139+
if (is_array($val)) {
140+
foreach ($val as $line) {
141+
$req .= "$var: $line\r\n";
141142
}
142-
else
143+
} else {
143144
$req .= "$var: $val\r\n";
145+
if (strtolower($var) == "actionid") {
146+
$actionid = $val;
147+
}
148+
}
149+
}
150+
if (!$actionid) {
151+
$actionid = $this->ActionID();
152+
$req .= "ActionID: $actionid\r\n";
144153
}
145154
$req .= "\r\n";
155+
146156
fwrite($this->socket, $req);
147-
return $this->wait_response();
157+
158+
return $this->wait_response(false, $actionid);
159+
}
160+
161+
function read_one_msg($allow_timeout = false)
162+
{
163+
$type = null;
164+
165+
while(false === ($pos = strpos($this->_buffer, "\r\n\r\n"))) {
166+
$this->_buffer .= @fgets($this->socket, 4096);
167+
}
168+
$msg = substr($this->_buffer, 0, $pos);
169+
$this->_buffer = substr($this->_buffer, $pos+4);
170+
171+
$msgarr = explode("\r\n", $msg);
172+
173+
$parameters = array();
174+
175+
$r = explode(': ', $msgarr[0]);
176+
$type = strtolower($r[0]);
177+
178+
if ($r[1] == 'Follows') {
179+
$str = array_pop($msgarr);
180+
$lastline = strpos($str, '--END COMMAND--');
181+
if (false !== $lastline) {
182+
$parameters['data'] = substr($str, 0, $lastline-1); // cut '\n' too
183+
}
184+
}
185+
186+
foreach ($msgarr as $num=>$str) {
187+
$kv = explode(': ', $str);
188+
$key = $kv[0];
189+
$val = $kv[1];
190+
$parameters[$key] = $val;
191+
}
192+
193+
// process response
194+
switch($type)
195+
{
196+
case '': // timeout occured
197+
$timeout = $allow_timeout;
198+
break;
199+
case 'event':
200+
$this->process_event($parameters);
201+
break;
202+
case 'response':
203+
break;
204+
default:
205+
$this->log('Unhandled response packet from Manager: ' . print_r($parameters, true));
206+
break;
207+
}
208+
209+
return $parameters;
148210
}
149211

150212
/**
@@ -153,64 +215,44 @@ function send_request($action, $parameters=array())
153215
* If a request was just sent, this will return the response.
154216
* Otherwise, it will loop forever, handling events.
155217
*
218+
* XXX this code is slightly better then the original one
219+
* however it's still totally screwed up and needs to be rewritten,
220+
* for two reasons at least:
221+
* 1. it does not handle socket errors in any way
222+
* 2. it is terribly synchronous, esp. with eventlists,
223+
* i.e. your code is blocked on waiting until full responce is received
224+
*
156225
* @param boolean $allow_timeout if the socket times out, return an empty array
157226
* @return array of parameters, empty on timeout
158227
*/
159-
function wait_response($allow_timeout=false)
228+
function wait_response($allow_timeout = false, $actionid = null)
160229
{
161-
$timeout = false;
162-
do
163-
{
164-
$type = NULL;
165-
$parameters = array();
166-
167-
$buffer = trim(fgets($this->socket, 4096));
168-
while($buffer != '')
169-
{
170-
$a = strpos($buffer, ':');
171-
if($a)
172-
{
173-
if(!count($parameters)) // first line in a response?
174-
{
175-
$type = strtolower(substr($buffer, 0, $a));
176-
if(substr($buffer, $a + 2) == 'Follows')
177-
{
178-
// A follows response means there is a miltiline field that follows.
179-
$parameters['data'] = '';
180-
$buff = fgets($this->socket, 4096);
181-
while(substr($buff, 0, 6) != '--END ')
182-
{
183-
$parameters['data'] .= $buff;
184-
$buff = fgets($this->socket, 4096);
185-
}
186-
}
187-
}
188-
189-
// store parameter in $parameters
190-
$parameters[substr($buffer, 0, $a)] = substr($buffer, $a + 2);
191-
}
192-
$buffer = trim(fgets($this->socket, 4096));
193-
}
230+
$res = array();
231+
if ($actionid) {
232+
do {
233+
$res = $this->read_one_msg($allow_timeout);
234+
} while (!( isset($res['ActionID']) && $res['ActionID']==$actionid ));
235+
} else {
236+
$res = $this->read_one_msg($allow_timeout);
237+
return $res;
238+
}
194239

195-
// process response
196-
switch($type)
197-
{
198-
case '': // timeout occured
199-
$timeout = $allow_timeout;
200-
break;
201-
case 'event':
202-
$this->process_event($parameters);
203-
break;
204-
case 'response':
240+
if (isset($res['EventList']) && $res['EventList']=='start') {
241+
$evlist = array();
242+
do {
243+
$res = $this->wait_response(false, $actionid);
244+
if (isset($res['EventList']) && $res['EventList']=='Complete')
205245
break;
206-
default:
207-
$this->log('Unhandled response packet from Manager: ' . print_r($parameters, true));
208-
break;
209-
}
210-
} while($type != 'response' && !$timeout);
211-
return $parameters;
246+
else
247+
$evlist[] = $res;
248+
} while(true);
249+
$res['events'] = $evlist;
250+
}
251+
252+
return $res;
212253
}
213254

255+
214256
/**
215257
* Connect to Asterisk
216258
*

0 commit comments

Comments
 (0)