]> git.mxchange.org Git - hub.git/commitdiff
New Exception added, registering of session ids added:
authorRoland Häder <roland@mxchange.org>
Sun, 13 Jun 2010 21:38:38 +0000 (21:38 +0000)
committerRoland Häder <roland@mxchange.org>
Sun, 13 Jun 2010 21:38:38 +0000 (21:38 +0000)
- New PeerAlreadyRegisteredException added which is thrown when the peer is
  already registered with the same session id
- Registering of peers with their session id basicly added, purging unfinished

13 files changed:
.gitattributes
application/hub/config.php
application/hub/exceptions/peer/.htaccess [new file with mode: 0644]
application/hub/exceptions/peer/class_PeerAlreadyRegisteredException.php [new file with mode: 0644]
application/hub/interfaces/lookup/peer_states/class_LookupablePeerState.php
application/hub/main/database/wrapper/class_PeerStateLookupDatabaseWrapper.php
application/hub/main/factories/states/peer/class_PeerStateFactory.php
application/hub/main/handler/network/tcp/class_TcpNetworkPackageHandler.php
application/hub/main/lookup/peer/class_PeerStateLookupTable.php
application/hub/main/nodes/boot/class_HubBootNode.php
application/hub/main/nodes/class_BaseHubNode.php
application/hub/main/resolver/state/network/class_NetworkStateResolver.php
application/hub/main/tools/class_HubTools.php

index ea3e01466a52121c5a370cdce7778b8840ba5703..af852c6f98143379192d4358a1e3853afa635d39 100644 (file)
@@ -16,6 +16,8 @@ application/hub/exceptions/lists/.htaccess -text
 application/hub/exceptions/lists/class_InvalidListHashException.php -text
 application/hub/exceptions/lists/class_ListGroupAlreadyAddedException.php -text
 application/hub/exceptions/lists/class_NoListGroupException.php -text
+application/hub/exceptions/peer/.htaccess -text
+application/hub/exceptions/peer/class_PeerAlreadyRegisteredException.php -text
 application/hub/exceptions/state/.htaccess -text
 application/hub/exceptions/state/class_InvalidStateException.php -text
 application/hub/exceptions/tags/.htaccess -text
index f86fdd3a3c9dd3e36c564030c3d344ae6a7f2431..a96da58c214e5415a59d8d534a90e780cad80e16 100644 (file)
@@ -33,6 +33,12 @@ $cfg->setConfigEntry('node_tcp_listen_port', 9060);
 // CFG: NODE-UDP-LISTEN-PORT
 $cfg->setConfigEntry('node_udp_listen_port', 9060);
 
+// CFG: BOOT-NODE-TCP-LISTEN-PORT
+$cfg->setConfigEntry('boot_node_tcp_listen_port', 9061);
+
+// CFG: BOOT-NODE-UDP-LISTEN-PORT
+$cfg->setConfigEntry('boot_node_udp_listen_port', 9061);
+
 // CFG: NODE-MODE (can be 'regular', 'list', 'master' or 'boot', default is 'regular')
 $cfg->setConfigEntry('node_mode', 'regular');
 
diff --git a/application/hub/exceptions/peer/.htaccess b/application/hub/exceptions/peer/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/application/hub/exceptions/peer/class_PeerAlreadyRegisteredException.php b/application/hub/exceptions/peer/class_PeerAlreadyRegisteredException.php
new file mode 100644 (file)
index 0000000..2cc655c
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * This exception is thrown when a peer is already registered
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            0.0.0
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009, 2010 Hub Developer Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+class PeerAlreadyRegisteredException extends FrameworkException {
+       /**
+        * The super constructor for all exceptions
+        *
+        * @param               $messageArray   Error message array
+        * @param               $code                   Error code
+        * @return      void
+        */
+       public function __construct (array $messageArray, $code) {
+               // Construct the message
+               $message = sprintf("[%s] Sender %s is already registered.",
+                       $messageArray[0]->__toString(),
+                       $messageArray[NetworkPackage::INDEX_PACKAGE_SENDER]
+               );
+
+               // Call parent exception constructor
+               parent::__construct($message, $code);
+       }
+}
+
+// [EOF]
+?>
index 94f7d0970f79449ac55d8481bb072d52a408c104..d315217153059778c9039fd329f018c0a5011af6 100644 (file)
@@ -30,6 +30,15 @@ interface LookupablePeerState extends Lookupable {
         */
        function isSenderNewPeer (array $packageData);
 
+       /**
+        * Registers a peer with given package data. We use the session id from it
+        *
+        * @param       $packageData            Valid raw package data
+        * @param       $socketResource         A valid socket resource
+        * @return<>void
+        */
+       function registerPeerByPackageData (array $packageData, $socketResource);
+
        /**
         * Registers the given peer state and raw package data
         *
@@ -38,6 +47,14 @@ interface LookupablePeerState extends Lookupable {
         * @return      void
         */
        function registerPeerState (PeerStateable $stateInstance, array $packageData);
+
+       /**
+        * Purges old entries of given socket resource. We use the IP address from that resource.
+        *
+        * @param       $socketResource         A valid socket resource
+        * @return      void
+        */
+       function purgeOldEntriesBySocketResource ($socketResource);
 }
 
 // [EOF]
index 10c2813b5dc0a829d49e80be64ae6f3cfe47bae0..d1f44cea0b5c0948109f3f78e3a8a00be1127a03 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 class PeerStateLookupDatabaseWrapper extends BaseDatabaseWrapper {
+       // Exception constants
+       const EXCEPTION_PEER_ALREADY_REGISTERED = 0x300;
+
        // Constants for database table names
        const DB_TABLE_PEER_LOOKUP = 'peer_states';
 
        // Constants for database column names
        const DB_COLUMN_PEER_IP         = 'peer_ip';
+       const DB_COLUMN_PEER_PORT       = 'peer_port';
+       const DB_COLUMN_PEER_SESSION_ID = 'peer_session_id';
 
        /**
         * Protected constructor
@@ -95,6 +100,66 @@ class PeerStateLookupDatabaseWrapper extends BaseDatabaseWrapper {
                // Return the result
                return $isNewPeer;
        }
+
+       /**
+        * Registers a new peer with given package data. We use the session id from it.
+        *
+        * @param       $packageData            Raw package data
+        * @param       $socketResource         A valid socket resource
+        * @return      void
+        * @throws      PeerAlreadyRegisteredException  If a peer is already registered
+        * @throws      InvalidSocketException  If the socket resource was invalid
+        */
+       public function registerPeerByPackageData (array $packageData, $socketResource) {
+               // Make sure only new peers can be registered with package data
+               if (!$this->isSenderNewPeer($packageData)) {
+                       // Throw an exception because this should normally not happen
+                       throw new PeerAlreadyRegisteredException(array($this, $packageData), self::EXCEPTION_PEER_ALREADY_REGISTERED);
+               } // END - if
+
+               // Generate a dataset instance
+               $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_PEER_LOOKUP));
+
+               // Session ids must be unique
+               $dataSetInstance->setUniqueKey(self::DB_COLUMN_PEER_SESSION_ID);
+
+               // Add session id
+               $dataSetInstance->addCriteria(self::DB_COLUMN_PEER_SESSION_ID, $packageData[NetworkPackage::INDEX_PACKAGE_SENDER]);
+
+               // Get peer name
+               if (!socket_getpeername($socketResource, $peerName, $peerPort)) {
+                       // Get last error
+                       $lastError = socket_last_error($socketResource);
+
+                       // Doesn't work!
+                       throw new InvalidSocketException(array($this, gettype($socketResource), $lastError, socket_strerror($lastError)), BaseListener::EXCEPTION_INVALID_SOCKET);
+               } // END - if
+
+               // Add ip address and port
+               $dataSetInstance->addCriteria(self::DB_COLUMN_PEER_IP  , $peerName);
+               $dataSetInstance->addCriteria(self::DB_COLUMN_PEER_PORT, $peerPort);
+
+               // "Insert" the data set
+               $this->getDatabaseInstance()->queryInsertDataSet($dataSetInstance);
+       }
+
+       /**
+        * Purges old entries of given socket resource. We use the IP address from that resource.
+        *
+        * @param       $socketResource         A valid socket resource
+        * @return      void
+        * @throws      InvalidSocketException  If the socket resource was invalid
+        */
+       public function purgeOldEntriesBySocketResource ($socketResource) {
+               // Get peer name
+               if (!socket_getpeername($socketResource, $peerName, $peerPort)) {
+                       // Get last error
+                       $lastError = socket_last_error($socketResource);
+
+                       // Doesn't work!
+                       throw new InvalidSocketException(array($this, gettype($socketResource), $lastError, socket_strerror($lastError)), BaseListener::EXCEPTION_INVALID_SOCKET);
+               } // END - if
+       }
 }
 
 // [EOF]
index 22e340239ef4bb8813cde995f05bde166fba2588..1256fa6e632862cbddb398927fa3515f7075c23d 100644 (file)
@@ -42,19 +42,26 @@ class PeerStateFactory extends ObjectFactory {
         * for the peer given in $packageData 'sender' element or it changes the state if it differs
         * from current state.
         *
-        * @param       $errorCode              The last error code
-        * @param       $packageData    Raw package data
-        * @return      $stateInstance  A Stateable class instance
+        * @param       $errorCode                      The last error code
+        * @param       $packageData            Raw package data
+        * @param       $socketResource         A valid socket resource
+        * @return      $stateInstance          A Stateable class instance
         */
-       public static final function createPeerStateInstanceByErrorCode ($errorCode, array $packageData) {
+       public static final function createPeerStateInstanceByErrorCode ($errorCode, array $packageData, $socketResource) {
                // So first we need our lookup table
                $tableInstance = self::getTableInstance();
 
+               // Purge old entries
+               $tableInstance->purgeOldEntriesBySocketResource($socketResource);
+
                // Do we have an entry?
                if ($tableInstance->isSenderNewPeer($packageData)) {
                        // Is a new peer so create the state instance based on error code, first we need a config entry
                        $configEntry = 'peer_state_' . $errorCode . '_class';
 
+                       // Register the new peer with its session id
+                       $tableInstance->registerPeerByPackageData($packageData, $socketResource);
+
                        // Then get it
                        $stateInstance = ObjectFactory::createObjectByConfiguredName($configEntry);
 
index a5d09ed7da944c7fa629d4369087b61611861a40..1bc4100647ecf105775dba7174a037cccfc0c570 100644 (file)
@@ -136,7 +136,7 @@ class TcpNetworkPackageHandler extends BaseNetworkPackageHandler implements Netw
                }
 
                // Get a state from the resolver for this package
-               $stateInstance = $this->getResolverInstance()->resolveStateByPackage($this, $packageData);
+               $stateInstance = $this->getResolverInstance()->resolveStateByPackage($this, $packageData, $resource);
                die('UNFINISHED:'.$stateInstance->__toString()."\n");
        }
 }
index 60b452196eee61659a1a187cd286338586647f61..2447a1d9f249e7c46f5aef56e1eb1b958016ba54 100644 (file)
@@ -65,6 +65,18 @@ class PeerStateLookupTable extends BaseLookupTable implements LookupablePeerStat
                return $isNewPeer;
        }
 
+       /**
+        * Registers a peer with given package data. We use the session id from it
+        *
+        * @param       $packageData            Valid raw package data
+        * @param       $socketResource         A valid socket resource
+        * @return      void
+        */
+       public function registerPeerByPackageData (array $packageData, $socketResource) {
+               // Just handle it over
+               $this->getWrapperInstance()->registerPeerByPackageData($packageData, $socketResource);
+       }
+
        /**
         * Registers the given peer state and raw package data
         *
@@ -75,7 +87,17 @@ class PeerStateLookupTable extends BaseLookupTable implements LookupablePeerStat
        public function registerPeerState (PeerStateable $stateInstance, array $packageData) {
                die(__METHOD__."\n");
        }
-}
+
+       /**
+        * Purges old entries of given socket resource. We use the IP address from that resource.
+        *
+        * @param       $socketResource         A valid socket resource
+        * @return      void
+        */
+       public function purgeOldEntriesBySocketResource ($socketResource) {
+               // Just handle it over
+               $this->getWrapperInstance()->purgeOldEntriesBySocketResource($socketResource);
+       }
 
 // [EOF]
 ?>
index e4cf363dccc6e43bc9eb6b2773059393bdd2edd0..f884f53bbc58a57dfb96f245c2c1cadf84609d5b 100644 (file)
@@ -61,7 +61,7 @@ class HubBootNode extends BaseHubNode implements NodeHelper, Registerable {
                // Now check if the IP address matches one of the bootstrap nodes
                if ($this->ifAddressMatchesBootstrappingNodes($this->getConfigInstance()->detectServerAddress())) {
                        // Get our port from configuration
-                       $ourPort = $this->getConfigInstance()->getConfigEntry('node_tcp_listen_port');
+                       $ourPort = $this->getConfigInstance()->getConfigEntry('boot_node_tcp_listen_port');
 
                        // Extract port
                        $bootPort = substr($this->getBootIpPort(), -strlen($ourPort), strlen($ourPort));
index e28e339b08ad2c3a302f4663cf597dd3880d7662..e3c1dc3bb56cde252a401973e60d272b40b75970 100644 (file)
@@ -550,7 +550,13 @@ class BaseHubNode extends BaseHubSystem implements Updateable {
 
                // Setup address and port
                $listenerInstance->setListenAddressByConfiguration('node_listen_addr');
-               $listenerInstance->setListenPortByConfiguration('node_tcp_listen_port');
+               if ($this instanceof HubBootNode) {
+                       // Bootstrap have different listening port
+                       $listenerInstance->setListenPortByConfiguration('boot_node_tcp_listen_port');
+               } else {
+                       // All other nodes use the default port
+                       $listenerInstance->setListenPortByConfiguration('node_tcp_listen_port');
+               }
 
                // Initialize the listener
                $listenerInstance->initListener();
@@ -572,7 +578,13 @@ class BaseHubNode extends BaseHubSystem implements Updateable {
 
                // Setup address and port
                $listenerInstance->setListenAddressByConfiguration('node_listen_addr');
-               $listenerInstance->setListenPortByConfiguration('node_udp_listen_port');
+               if ($this instanceof HubBootNode) {
+                       // Bootstrap have different listening port
+                       $listenerInstance->setListenPortByConfiguration('boot_node_udp_listen_port');
+               } else {
+                       // All other nodes use the default port
+                       $listenerInstance->setListenPortByConfiguration('node_udp_listen_port');
+               }
 
                // Initialize the listener
                $listenerInstance->initListener();
index 203a871495723c7041483cfac290977cb519a29a..5b8de96465bd5cfaf751ace50fc145e37eec6bd3 100644 (file)
@@ -63,10 +63,11 @@ class NetworkStateResolver extends BaseStateResolver implements StateResolver {
         *
         * @param       $packageInstance        An instance of a package class
         * @param       $packageData            Raw package data
+        * @param       $socketResource         A valid socket resource
         * @return      $stateInstance          An instance of the resolved state
         * @todo        ~30% done
         */
-       public function resolveStateByPackage (Networkable $packageInstance, array $packageData) {
+       public function resolveStateByPackage (Networkable $packageInstance, array $packageData, $socketResource) {
                // Init state instance
                $stateInstance = null;
 
@@ -87,7 +88,7 @@ class NetworkStateResolver extends BaseStateResolver implements StateResolver {
                } // END - if
 
                // Create a state instance based on $errorCode. This factory does the hard work for us
-               $stateInstance = PeerStateFactory::createPeerStateInstanceByErrorCode($errorCode, $packageData);
+               $stateInstance = PeerStateFactory::createPeerStateInstanceByErrorCode($errorCode, $packageData, $socketResource);
 
                // Return the prepared instance
                return $stateInstance;
index 9f51a99474395d96a234f2ff4b90f21977675c54..4525f503e2ae72707d1c2da747c4f9f28b5a068a 100644 (file)
@@ -113,12 +113,18 @@ class HubTools extends BaseFrameworkSystem {
                if (!preg_match('/((?:2[0-5]{2}|1\d{2}|[1-9]\d|[1-9])\.(?:(?:2[0-5]{2}|1\d{2}|[1-9]\d|\d)\.){2}(?:2[0-5]{2}|1\d{2}|[1-9]\d|\d)):(\d|[1-9]\d|[1-9]\d{2,3}|[1-5]\d{4}|6[0-4]\d{3}|654\d{2}|655[0-2]\d|6553[0-5])/', $sessionId)) {
                        // Is it in cache?
                        if (isset($selfInstance->sessionIdCache[$sessionId])) {
+                               // Debug message
+                               $selfInstance->debugOutput('HUB-TOOLS: Using entry from sessionIdCache[] array.');
+
                                // Then use it
                                $recipient = $selfInstance->sessionIdCache[$sessionId];
                        } elseif (!preg_match('/([a-f0-9]{' . $selfInstance->getSessionIdLength() . '})/', $sessionId)) {
                                // Invalid session id
                                throw new InvalidSessionIdException($sessionId, self::EXCEPTION_SESSION_ID_IS_INVALID);
                        } else {
+                               // Debug message
+                               $selfInstance->debugOutput('HUB-TOOLS: Using internal resolver.');
+
                                // Resolve it here
                                $recipient = $selfInstance->resolveIpPortBySessionId($sessionId);
                        }