From 4dfbbe06642a017594f132bd2bdea5fcf9c21c74 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Sat, 8 Aug 2009 19:16:32 +0000 Subject: [PATCH] New iterator introduced, low-level TCP connections supported (unfinished): - New iterator NetworkListenIterator added which should be used for listening to network packages through multiple listeners. - Several getter added to get a list of all listeners --- .gitattributes | 2 + application/hub/config.php | 3 + .../hub/main/iterator/network/.htaccess | 1 + .../network/class_NetworkListenIterator.php | 124 ++++++++++++++++++ .../hub/main/listener/class_BaseListener.php | 4 +- .../main/listener/tcp/class_TcpListener.php | 46 ++++++- application/hub/main/lists/class_BaseList.php | 45 ++++++- .../main/lists/groups/class_ListGroupList.php | 9 ++ application/hub/main/pools/class_BasePool.php | 31 ++++- .../pools/client/class_DefaultClientPool.php | 34 ++++- 10 files changed, 284 insertions(+), 15 deletions(-) create mode 100644 application/hub/main/iterator/network/.htaccess create mode 100644 application/hub/main/iterator/network/class_NetworkListenIterator.php diff --git a/.gitattributes b/.gitattributes index 46eae1536..eda6bd360 100644 --- a/.gitattributes +++ b/.gitattributes @@ -100,6 +100,8 @@ application/hub/main/filter/shutdown/class_HubShutdownNodeFilter.php -text application/hub/main/iterator/.htaccess -text application/hub/main/iterator/class_ -text application/hub/main/iterator/class_BaseIterator.php -text +application/hub/main/iterator/network/.htaccess -text +application/hub/main/iterator/network/class_NetworkListenIterator.php -text application/hub/main/iterator/pool/.htaccess -text application/hub/main/iterator/pool/handler/.htaccess -text application/hub/main/iterator/pool/handler/class_Handler -text diff --git a/application/hub/config.php b/application/hub/config.php index 51b113b95..2f9a39e84 100644 --- a/application/hub/config.php +++ b/application/hub/config.php @@ -99,6 +99,9 @@ $cfg->setConfigEntry('handler_listener_pool_visitor_class', 'HandlerListenerPool // CFG: HANDLER-POOL-ITERATOR-CLASS $cfg->setConfigEntry('handler_pool_iterator_class', 'HandlerPoolIterator'); +// CFG: NETWORK-LISTEN-ITERATOR-CLASS +$cfg->setConfigEntry('network_listen_iterator_class', 'NetworkListenIterator'); + // CFG: LIST-GROUP-CLASS $cfg->setConfigEntry('list_group_class', 'ListGroupList'); diff --git a/application/hub/main/iterator/network/.htaccess b/application/hub/main/iterator/network/.htaccess new file mode 100644 index 000000000..3a4288278 --- /dev/null +++ b/application/hub/main/iterator/network/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/application/hub/main/iterator/network/class_NetworkListenIterator.php b/application/hub/main/iterator/network/class_NetworkListenIterator.php new file mode 100644 index 000000000..62640bd01 --- /dev/null +++ b/application/hub/main/iterator/network/class_NetworkListenIterator.php @@ -0,0 +1,124 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 Hub Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.ship-simu.org + * @todo This current implementation is not recommended, use a + * @todo latency-based iteration or similar approaches + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +class NetworkListenIterator extends BaseIterator implements Iterator { + /** + * Key for the global list index + */ + private $indexKey = 0; + + /** + * Protected constructor + * + * @return void + */ + protected function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + } + + /** + * Creates an instance of this class + * + * @param $listInstance A list of a IteratorAggregate + * @return $iteratorInstance An instance a Iterator class + */ + public final static function createNetworkListenIterator (IteratorAggregate $listInstance) { + // Get new instance + $iteratorInstance = new NetworkListenIterator(); + + // Set the list + $iteratorInstance->setListInstance($listInstance); + + // Return the prepared instance + return $iteratorInstance; + } + + /** + * Getter for current value from group or generic + * + * @return $current Current value in iteration + * @throws IndexOutOfBoundsException If $indexKey is out of bounds + */ + public function current () { + // Default is null + $current = null; + + // Is the entry valid? + if (!$this->valid()) { + // Throw an exception here + throw new IndexOutOfBoundsException($this->key(), self::EXCEPTION_INDEX_OUT_OF_BOUNDS); + } // END - if + + // Now get the entry + $current = $this->getListInstance()->getEntry($this->key()); + + // Return it + return $current; + } + + /** + * Getter for key from group or generic + * + * @return $indexKey Current key in iteration + */ + public function key () { + return $this->indexKey; + } + + /** + * Advances to the next entry + * + * @return void + */ + public function next () { + $this->indexKey++; + } + + /** + * Rewinds to the beginning of the iteration + * + * @return void + */ + public function rewind () { + $this->indexKey = 0; + } + + /** + * Checks wether the current entry is valid (not at the end of the list) + * + * @return $isValid Wether the current entry is there + */ + public function valid () { + // Check for total active clients and if we are not at the end + $isValid = ($this->key() < $this->getListInstance()->count()); + + // Return result + return $isValid; + } +} + +// [EOF] +?> diff --git a/application/hub/main/listener/class_BaseListener.php b/application/hub/main/listener/class_BaseListener.php index b4213785c..c53d81e91 100644 --- a/application/hub/main/listener/class_BaseListener.php +++ b/application/hub/main/listener/class_BaseListener.php @@ -169,7 +169,7 @@ class BaseListener extends BaseHubSystem implements Visitable { * @return void */ protected final function setSocketResource ($socketResource) { - $this->socketResource = $setSocketResource; + $this->socketResource = $socketResource; } /** @@ -188,7 +188,7 @@ class BaseListener extends BaseHubSystem implements Visitable { * @return void */ protected final function setPoolInstance (PoolableClient $poolInstance) { - $this->poolInstance = $setPoolInstance; + $this->poolInstance = $poolInstance; } /** diff --git a/application/hub/main/listener/tcp/class_TcpListener.php b/application/hub/main/listener/tcp/class_TcpListener.php index b5f3bc179..d7d3de766 100644 --- a/application/hub/main/listener/tcp/class_TcpListener.php +++ b/application/hub/main/listener/tcp/class_TcpListener.php @@ -136,6 +136,13 @@ class TcpListener extends BaseListener implements Listenable { // And add it to this listener $this->setPoolInstance($poolInstance); + // Initialize iterator for listening on packages + $iteratorInstance = ObjectFactory::createObjectByConfiguredName('network_listen_iterator_class', array($poolInstance->getPoolEntriesInstance())); + + // Rewind it and remember it in this class + $iteratorInstance->rewind(); + $this->setIteratorInstance($iteratorInstance); + // Output message $this->debugOutput('LISTENER: TCP listener now ready on IP ' . $this->getListenAddress() . ', port ' . $this->getListenPort() . ' for service.'); } @@ -146,8 +153,43 @@ class TcpListener extends BaseListener implements Listenable { * @return void * @todo 0% done */ - public function doListen() { - $this->partialStub('Need to implement this method.'); + public function doListen () { + // Get all readers + $readers = $this->getPoolInstance()->getAllSockets(); + + // Check if we have some clients left + $left = socket_select($readers, $writers = null, $excepts = null, 0, 150); + + // Some new clients found? + if ($left < 1) { + // Nothing new found + return; + } // END - if + + // Do we have changed clients? + if (in_array($this->getSocketResource(), $readers)) { + // Then accept it + $newSocket = socket_accept($this->getSocketResource()); + + // Add it to the clients + $this->getPoolInstance()->addClient($newSocket); + } // END - if + + // Do we have to rewind? + if (!$this->getIteratorInstance()->valid()) { + // Rewind the list + $this->getIteratorInstance()->rewind(); + } // END - if + + // Get the current value + $current = $this->getIteratorInstance()->current(); + + // Handle it here + $this->partialStub('current['.gettype($current).']='.$current); + + // Advance to next entry. This should be the last line + $this->getIteratorInstance()->next(); + die("OK!\n"); } } diff --git a/application/hub/main/lists/class_BaseList.php b/application/hub/main/lists/class_BaseList.php index fc6969ae6..3403a63a1 100644 --- a/application/hub/main/lists/class_BaseList.php +++ b/application/hub/main/lists/class_BaseList.php @@ -138,6 +138,44 @@ class BaseList extends BaseHubSystem implements IteratorAggregate, Countable { //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . '/' . $subGroup . ' - START'); } + /** + * Gets an array from given list + * + * @param $list The requested list + * @return $array The requested array + * @throws NoListGroupException If the given group is not found + */ + public final function getArrayFromList ($list) { + // Is the group there? + if ((!is_null($list)) && (!$this->isGroupSet($list))) { + // Throw the exception here + throw new NoListGroupException(array($this, $list), self::EXCEPTION_GROUP_NOT_FOUND); + } // END - if + + // Init array + $array = array(); + + // Is there another list? + if (!is_null($list)) { + // Then get it as well + $array = $this->listGroups[$list]->getArrayFromList(null); + } // END - if + + // Walk through all entries + foreach ($this->listIndex as $hash) { + //* DEBUG: */ print __METHOD__.':hash='.$hash."\n"; + // Is the list entry set? + if ($this->isHashValid($hash)) { + // Add it + $array[] = $this->listEntries[$hash]; + //* DEBUG: */ print __METHOD__.": ADDED!\n"; + } // END - if + } // END - foreach + + // Return it + return $array; + } + /** * Adds the given entry to list group * @@ -147,7 +185,7 @@ class BaseList extends BaseHubSystem implements IteratorAggregate, Countable { * @throws NoListGroupException If the given group is not found */ public function addEntry ($groupName, $entry) { - //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - START'); + //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): '.$groupName . ' - START'); // Is the group already added? if (!$this->isGroupSet($groupName)) { // Throw the exception here @@ -156,13 +194,16 @@ class BaseList extends BaseHubSystem implements IteratorAggregate, Countable { // Generate hash $hash = $this->generateHash($groupName, $groupName, $entry); + //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): hash='.$hash.''); // Add the hash to the index $this->listIndex[] = $hash; + //* DEBUG: */ print $groupName.'/'.count($this->listIndex)."\n"; // Now add the entry to the list $this->listEntries[$hash] = $entry; - //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - FINISHED'); + //* DEBUG: */ print $groupName.'/'.count($this->listEntries)."\n"; + //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): '.$groupName . ' - FINISHED'); } /** diff --git a/application/hub/main/lists/groups/class_ListGroupList.php b/application/hub/main/lists/groups/class_ListGroupList.php index 1cf106252..19bae2743 100644 --- a/application/hub/main/lists/groups/class_ListGroupList.php +++ b/application/hub/main/lists/groups/class_ListGroupList.php @@ -44,6 +44,15 @@ class ListGroupList extends BaseList implements Listable { // Return the prepared instance return $listInstance; } + + /** + * Gets an array from this group + * + * @return $array The array from this group + */ + public final function getArrayFromGroup () { + $this->debugInstance(); + } } // [EOF] diff --git a/application/hub/main/pools/class_BasePool.php b/application/hub/main/pools/class_BasePool.php index 3eafd2d9a..5908ad52d 100644 --- a/application/hub/main/pools/class_BasePool.php +++ b/application/hub/main/pools/class_BasePool.php @@ -41,6 +41,15 @@ class BasePool extends BaseHubSystem implements Visitable { $this->poolEntriesInstance = ObjectFactory::createObjectByConfiguredName('pool_entries_list_class'); } + /** + * Getter for pool entries instance + * + * @return $poolEntriesInstance An instance for pool entries (list) + */ + public final function getPoolEntriesInstance () { + return $this->poolEntriesInstance; + } + /** * Adds an instance to a pool segment * @@ -51,13 +60,13 @@ class BasePool extends BaseHubSystem implements Visitable { */ protected final function addInstance ($group, $poolName, Visitable $instance) { // Is the pool group there? - if (!$this->poolEntriesInstance->isGroupSet($group)) { + if (!$this->getPoolEntriesInstance()->isGroupSet($group)) { // Create the missing pool group - $this->poolEntriesInstance->addGroup($group); + $this->getPoolEntriesInstance()->addGroup($group); } // END - if // Add it to given pool group - $this->poolEntriesInstance->addInstance($group, $poolName, $instance); + $this->getPoolEntriesInstance()->addInstance($group, $poolName, $instance); } /** @@ -67,7 +76,7 @@ class BasePool extends BaseHubSystem implements Visitable { * @return void */ protected final function addPoolEntry ($poolEntry) { - $this->poolEntriesInstance->addEntry('generic', $poolEntry); + $this->getPoolEntriesInstance()->addEntry('generic', $poolEntry); } /** @@ -110,6 +119,20 @@ class BasePool extends BaseHubSystem implements Visitable { // Debug message //* DEBUG: */ $this->debugOutput('POOL: ' . $visitorInstance->__toString() . ' has visited - FINISHED'); } + + /** + * Gets the arra from specified list + * + * @param $list The list identifier we should return + * @return $array The requested array + */ + protected final function getArrayFromList ($list) { + // Get the array + $array = $this->getPoolEntriesInstance()->getArrayFromList($list); + + // Return it + return $array; + } } // [EOF] diff --git a/application/hub/main/pools/client/class_DefaultClientPool.php b/application/hub/main/pools/client/class_DefaultClientPool.php index 7f83a288c..08fb52154 100644 --- a/application/hub/main/pools/client/class_DefaultClientPool.php +++ b/application/hub/main/pools/client/class_DefaultClientPool.php @@ -50,13 +50,12 @@ class DefaultClientPool extends BasePool implements PoolableClient { } /** - * Adds a socket resource to the client pool + * Validates given socket * - * @param $socketResource A valid (must be!) socket resource + * @param $socketResource A valid socket resource * @return void - * @throws InvalidSocketException If the given resource is invalid or errorous */ - public function addClient ($socketResource) { + private function validateSocket ($socketResource) { // Is it a valid resource? if (!is_resource($socketResource)) { // Throw an exception @@ -72,15 +71,40 @@ class DefaultClientPool extends BasePool implements PoolableClient { $errorMessage = socket_strerror($errorCode); // Shutdown this socket - $this->getListenerInstance()->shutdownSocket($mainSocket); + $this->getListenerInstance()->shutdownSocket($socketResource); // And throw again throw new InvalidSocketException(array($this, gettype($socketResource), $errorCode, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); } // END - if + } + + /** + * Adds a socket resource to the client pool + * + * @param $socketResource A valid (must be!) socket resource + * @return void + * @throws InvalidSocketException If the given resource is invalid or errorous + */ + public function addClient ($socketResource) { + // Validate the socket + $this->validateSocket($socketResource); // Add it finally to the pool $this->addPoolEntry($socketResource); } + + /** + * Getter for array of all socket resources + * + * @return $sockets An array with all sockets + */ + public final function getAllSockets () { + // Get the list + $sockets = $this->getArrayFromList('generic'); + + // Return it + return $sockets; + } } // -- 2.39.5