private function poll_request($timeout, $external)
{
if ($this->terminate) {
return false;
} elseif ($external && !$this->initialization_complete) {
$this->send(\Erlang\term_to_binary(new \Erlang\OtpErlangAtom('polling')));
$this->initialization_complete = true;
}
$poll_timer = null;
if (is_null($timeout) || $timeout < 0) {
$timeout_value_secs = null;
$timeout_value_usecs = null;
} elseif ($timeout == 0) {
$timeout_value_secs = 0;
$timeout_value_usecs = 0;
} elseif ($timeout > 0) {
$poll_timer = microtime(true);
$timeout_value_secs = intval($timeout / 1000);
$timeout_value_usecs = intval($timeout - $timeout_value_secs * 1000) * 1000;
}
$result_read = array($this->s);
$result_write = null;
$result_except = array($this->s);
$result = stream_select($result_read, $result_write, $result_except, $timeout_value_secs, $timeout_value_usecs);
if ($result === false || count($result_except) > 0) {
return false;
}
if (count($result_read) == 0) {
return true;
}
$data = $this->recv('');
$data_size = strlen($data);
if ($data_size == 0) {
return false;
}
$i = 0;
$j = 4;
while (true) {
list(, $command) = unpack('L', substr($data, $i, $j));
switch ($command) {
case MESSAGE_INIT:
$i += $j;
$j = 4 + 4 + 4 + 4 + 4;
list(, $process_index, $process_count, $process_count_max, $process_count_min, $prefix_size) = unpack('L5', substr($data, $i, $j));
$i += $j;
$j = $prefix_size;
$prefix = substr($data, $i, $j - 1);
$i += $j;
$j = 4 + 4 + 4 + 4 + 1 + 1;
$tmp = unpack('L4a/cb/Cc', substr($data, $i, $j));
$timeout_initialize = $tmp['a1'];
$timeout_async = $tmp['a2'];
$timeout_sync = $tmp['a3'];
$timeout_terminate = $tmp['a4'];
$priority_default = $tmp['b'];
$request_timeout_adjustment = $tmp['c'];
$i += $j;
if ($i != $data_size) {
assert($external == false);
$this->handle_events($external, $data, $data_size, $i);
}
return array($process_index, $process_count, $process_count_max, $process_count_min, $prefix, $timeout_initialize, $timeout_sync, $timeout_async, $timeout_terminate, $priority_default, $request_timeout_adjustment == 1);
case MESSAGE_SEND_ASYNC:
case MESSAGE_SEND_SYNC:
$i += $j;
$j = 4;
list(, $name_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $name_size;
$name = substr($data, $i, $j - 1);
$i += $j;
$j = 4;
list(, $pattern_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $pattern_size;
$pattern = substr($data, $i, $j - 1);
$i += $j;
$j = 4;
list(, $request_info_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $request_info_size;
$request_info = substr($data, $i, $j);
$i += $j;
$j = 4;
$i++;
// skip null byte
list(, $request_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $request_size;
$request = substr($data, $i, $j);
$i += $j;
$j = 4 + 1;
$i++;
// skip null byte
$tmp = unpack('La/cb', substr($data, $i, $j));
$request_timeout = $tmp['a'];
$priority = $tmp['b'];
$i += $j;
$j = 16;
$trans_id = substr($data, $i, $j);
$i += $j;
$j = 4;
list(, $pid_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $pid_size;
$pid = substr($data, $i, $j);
$i += $j;
if ($i != $data_size) {
assert($external == true);
if (!$this->handle_events($external, $data, $data_size, $i)) {
return false;
}
}
$data = '';
$this->callback($command, $name, $pattern, $request_info, $request, $request_timeout, $priority, $trans_id, \Erlang\binary_to_term($pid));
break;
case MESSAGE_RECV_ASYNC:
case MESSAGE_RETURN_SYNC:
$i += $j;
$j = 4;
list(, $response_info_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $response_info_size;
$response_info = substr($data, $i, $j);
$i += $j;
$j = 4;
$i++;
// skip null byte
list(, $response_size) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = $response_size;
$response = substr($data, $i, $j);
$i += $j;
$j = 16;
$i++;
// skip null byte
$trans_id = substr($data, $i, $j);
$i += $j;
if ($i != $data_size) {
assert($external == false);
$this->handle_events($external, $data, $data_size, $i);
}
return array($response_info, $response, $trans_id);
case MESSAGE_RETURN_ASYNC:
$i += $j;
$j = 16;
$trans_id = substr($data, $i, $j);
$i += $j;
if ($i != $data_size) {
assert($external == false);
$this->handle_events($external, $data, $data_size, $i);
}
return $trans_id;
case MESSAGE_RETURNS_ASYNC:
$i += $j;
$j = 4;
list(, $trans_id_count) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = 16;
$trans_ids = array();
for ($k = 0; $k < $trans_id_count; $k++) {
$trans_ids[] = substr($data, $i, $j);
$i += $j;
}
if ($i != $data_size) {
assert($external == false);
$this->handle_events($external, $data, $data_size, $i);
}
return $trans_ids;
case MESSAGE_SUBSCRIBE_COUNT:
$i += $j;
$j = 4;
list(, $count) = unpack('L', substr($data, $i, $j));
$i += $j;
if ($i != $data_size) {
assert($external == false);
$this->handle_events($external, $data, $data_size, $i);
}
return $count;
case MESSAGE_TERM:
if (!$this->handle_events($external, $data, $data_size, $i, $command)) {
return false;
}
assert(false);
case MESSAGE_REINIT:
$i += $j;
$j = 4;
list(, $this->process_count) = unpack('L', substr($data, $i, $j));
$i += $j;
$j = 4;
if ($i == $data_size) {
break;
} elseif ($i < $data_size) {
continue 2;
} else {
throw new MessageDecodingException();
}
case MESSAGE_KEEPALIVE:
$this->send(\Erlang\term_to_binary(new \Erlang\OtpErlangAtom('keepalive')));
$i += $j;
$j = 4;
if ($i == $data_size) {
break;
} elseif ($i < $data_size) {
continue 2;
} else {
throw new MessageDecodingException();
}
default:
throw new MessageDecodingException();
}
if (!is_null($poll_timer)) {
$poll_timer_new = microtime(true);
$elapsed = max(0, (int) floor(($poll_timer_new - $poll_timer) * 1000.0));
$poll_timer = $poll_timer_new;
if ($elapsed >= $timeout) {
$timeout = 0;
} else {
$timeout -= $elapsed;
}
}
if (!is_null($timeout_value_secs)) {
if ($timeout == 0) {
return true;
} elseif ($timeout > 0) {
$timeout_value_secs = intval($timeout / 1000);
$timeout_value_usecs = intval($timeout - $timeout_value_secs * 1000) * 1000;
}
}
$result_read = array($this->s);
$result_write = null;
$result_except = array($this->s);
$result = stream_select($result_read, $result_write, $result_except, $timeout_value_secs, $timeout_value_usecs);
if ($result === false || count($result_except) > 0) {
return false;
}
if (count($result_read) == 0) {
return true;
}
$data = $this->recv($data);
$data_size = strlen($data);
if ($data_size == 0) {
return false;
}
$i = 0;
$j = 4;
}
}