public function __construct($address, $options = [])
{
parent::__construct();
$defaults = ['port' => null, 'domain' => AF_INET, 'type' => SOCK_STREAM, 'protocol' => SOL_TCP];
$options += $defaults;
$this->_address = $address;
$this->_options = $options;
/**
* TODO
*
* Shorten this entire loop.
*/
$this->_idle = new Process(function ($processor) {
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug('Entering socket wait loop');
}
$idle = $processor->get_routine()->get_idles_available();
// 30 second default wait
$time = 30;
$utime = 0;
// Determine if another function has requested to execute in x
// amount of time
if (count($processor->get_routine()->get_signals()) !== 0) {
// If we have signals to process only poll and continue
$time = 0;
} elseif (count($idle) >= 2) {
$default_wait_time = time() + $this->default_wait_time;
foreach ($idle as $_idle) {
// if ($_idle->get_idle() instanceof Time) {
// // echo $default_wait_time.PHP_EOL;
// // echo $_idle->get_idle()->get_time_until().PHP_EOL;
// // echo $_idle->get_idle()->get_time_until() < $default_wait_time.PHP_EOL;
// // echo $_idle->get_idle()->get_time_until() > $default_wait_time.PHP_EOL;
// // echo $_idle.PHP_EOL;
// }
// if ($_idle->get_idle() instanceof Time && (
// // $default_wait_time > $_idle->get_idle()->get_time_until())) {
// // $time = round($_idle->get_idle()->convert_length(
// // $_idle->get_idle()->get_time_left(),
// // TIME_SECONDS
// // ), 3);
// // if ($time > 0 && $time < 1) {
// // $utime = $time * 1000;
// // $time = 0;
// // }
// // echo $time.PHP_EOL;
// // break;
// }
}
}
// establish sockets
$re = [$this->_connection->get_resource()];
$wr = $ex = [];
foreach ($this->_clients as $_k => $_c) {
$_resource = $_c->get_resource();
// test if socket is still connected
// send disconnect if disconnect detected
if ($_c->is_connected() === false) {
xp_emit(new SIG_Disconnect($_c));
unset($this->_clients[$_k]);
continue;
} else {
$re[] = $_resource;
$ex[] = $_resource;
}
}
$count = socket_select($re, $wr, $ex, $time, $utime);
if ($count === false) {
logger(XPSPL_LOG)->debug('Socket wait loop ended PROBLEM');
return false;
} elseif ($count == 0) {
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug('Socket wait loop ended no connection changes');
}
return true;
}
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug('Socket wait loop ended connection changes detected');
}
// Check Read
if (count($re) !== 0) {
foreach ($re as $_r) {
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug(sprintf('Connection Read %s', strval(intval($_r))));
}
$id = intval($_r);
if (!isset($this->_clients[$id])) {
$client = new Client($_r);
$id = intval($client->get_resource());
xp_emit(new SIG_Connect($this, $client));
$this->_clients[$id] = $client;
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug(sprintf('Added Connection %s', strval(intval($id))));
}
} else {
$this->_clients[$id]->_read_buffer();
xp_emit(new SIG_Read($this, $this->_clients[$id]));
}
}
}
// Check Write
if (count($wr) !== 0) {
foreach ($wr as $_write) {
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug(sprintf('Connection Write %s', strval($_write)));
}
$processor->get_routine()->add_signal(new SIG_Write($this, $this->_clients[intval($_write)]));
}
}
// Errors
if (count($ex) !== 0) {
foreach ($ex as $_excep) {
if (XPSPL_DEBUG) {
logger(XPSPL_LOG)->debug(sprintf('Connection Exception %s', strval($_excep)));
}
$this->_clients[intval($_excep)]->error = socket_last_error($_excep);
$this->_clients[intval($_excep)]->error_str = socket_strerror($_excep);
$processor->get_routine()->add_signal(new SIG_Error($this, $this->_clients[intval($_excep)]));
}
}
});
$this->on_disconnect(xp_priority(PHP_INT_MAX, '\\network\\system_disconnect'));
// After processing read clean the buffer
xp_after(new SIG_Read($this), xp_low_priority('\\network\\clean_buffer'));
// Emit this has started
xp_emit($this);
}