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
// 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');
--- /dev/null
+Deny from all
--- /dev/null
+<?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]
+?>
*/
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
*
* @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]
* 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
// 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]
* 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);
}
// 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");
}
}
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
*
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]
?>
// 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));
// 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();
// 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();
*
* @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;
} // 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;
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);
}