/** * Constructs a new socket. * * @param string $address Address to make the connection on. * @param string $options Connection options * * @return void */ 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); }
<?php /** * Copyright 2010-12 Nickolas Whiting. All rights reserved. * Use of this source code is governed by the Apache 2 license * that can be found in the LICENSE file. */ require_once dirname(realpath(__FILE__)) . '/../__init__.php'; xp_import('unittest'); unittest\test(function ($test) { $foo = XP_SIG('foo'); xp_signal($foo, function () { }); xp_after($foo, function ($foo) { $foo->foo = 'foo'; }); xp_emit($foo); $test->equal($foo->foo, 'foo'); }, 'API after');
/** * Registers a teardown function. * * @param object $function Closure * * @return void */ public function teardown($function) { xp_after($this->_test, xp_null_exhaust($function)); }
<?php /** * Copyright 2010-12 Nickolas Whiting. All rights reserved. * Use of this source code is governed by the Apache 2 license * that can be found in the LICENSE file. */ require_once '__init__.php'; xp_import('unittest'); unittest\test(function ($test) { $foo = XP_SIG('foo'); xp_before($foo, function ($foo) { $foo->bar = 'HelloWorld'; }); xp_after($foo, function ($foo) { unset($foo->bar); }); xp_signal($foo, function ($foo) use($test) { $test->equal($foo->bar, 'HelloWorld'); }); xp_emit($foo); $test->false(isset($foo->bar)); }, 'Interruptions');
<?php // Handle Foo xp_signal(XP_SIG('foo'), function ($signal) { echo $signal->bar; }); // When foo is emitted insert bar into the event xp_before(XP_SIG('foo'), function ($signal) { echo "I RAN" . PHP_EOL; $signal->bar = 'foo'; }); xp_before(XP_SIG('foo'), xp_high_priority(function ($signal) { echo "I RAN BEFORE" . PHP_EOL; })); // After foo is emitted unset bar in the event xp_after(XP_SIG('foo'), function ($signal) { unset($signal->bar); }); $signal = xp_emit(XP_SIG('foo')); var_dump(isset($signal->bar));