]> git.mxchange.org Git - hub.git/commitdiff
'hub' project continued:
authorRoland Häder <roland@mxchange.org>
Fri, 27 Apr 2012 15:42:00 +0000 (15:42 +0000)
committerRoland Häder <roland@mxchange.org>
Fri, 27 Apr 2012 15:42:00 +0000 (15:42 +0000)
- New package "decoder" class added which has also a new interface Decodeable
- Handling of incoming packages almost finished
- Loop fixed the second $this->shutdownSocket() call is required
- Many objects have extended BaseFrameworkSystem but should be BaseHubSystem
- TODOs.txt updated

29 files changed:
.gitattributes
application/hub/config.php
application/hub/exceptions/package/class_UnexpectedPackageStatusException.php
application/hub/interfaces/decoder/.htaccess [new file with mode: 0644]
application/hub/interfaces/decoder/class_Decodeable.php [new file with mode: 0644]
application/hub/interfaces/discovery/class_DiscoverableRecipient.php
application/hub/interfaces/handler/chunks/class_HandleableChunks.php
application/hub/interfaces/package/class_Receivable.php
application/hub/main/class_BaseHubSystem.php
application/hub/main/compressor/decorator/class_NetworkPackageCompressorDecorator.php
application/hub/main/decoder/.htaccess [new file with mode: 0644]
application/hub/main/decoder/class_ [new file with mode: 0644]
application/hub/main/decoder/class_BaseDecoder.php [new file with mode: 0644]
application/hub/main/decoder/package/.htaccess [new file with mode: 0644]
application/hub/main/decoder/package/class_PackageDecoder.php [new file with mode: 0644]
application/hub/main/discovery/package/class_PackageRecipientDiscovery.php
application/hub/main/discovery/socket/class_PackageSocketDiscovery.php
application/hub/main/filter/task/node/class_NodeTaskHandlerInitializerFilter.php
application/hub/main/handler/chunks/class_ChunkHandler.php
application/hub/main/helper/connection/class_BaseConnectionHelper.php
application/hub/main/lists/class_BaseList.php
application/hub/main/package/class_NetworkPackage.php
application/hub/main/package/fragmenter/class_PackageFragmenter.php
application/hub/main/statistics/connection/class_ConnectionStatisticsHelper.php
application/hub/main/tasks/hub/chunks/class_HubChunkAssemblerTask.php
application/hub/main/tasks/hub/decoder/.htaccess [new file with mode: 0644]
application/hub/main/tasks/hub/decoder/class_HubPackageDecoderTask.php [new file with mode: 0644]
application/hub/main/tools/class_HubTools.php
docs/TODOs.txt

index c0c459a699a0f8768ddfe155a740c2da07bf0280..3f6d8cc60576e800e6759be7e07d3134d3baef7d 100644 (file)
@@ -40,6 +40,8 @@ application/hub/interfaces/consumer/.htaccess svneol=native#text/plain
 application/hub/interfaces/consumer/class_Consumer.php svneol=native#text/plain
 application/hub/interfaces/cruncher/.htaccess svneol=native#text/plain
 application/hub/interfaces/cruncher/class_CruncherHelper.php svneol=native#text/plain
+application/hub/interfaces/decoder/.htaccess -text svneol=unset#text/plain
+application/hub/interfaces/decoder/class_Decodeable.php svneol=native#text/plain
 application/hub/interfaces/discovery/.htaccess -text svneol=unset#text/plain
 application/hub/interfaces/discovery/class_DiscoverableRecipient.php svneol=native#text/plain
 application/hub/interfaces/discovery/class_DiscoverableSocket.php svneol=native#text/plain
@@ -182,6 +184,10 @@ application/hub/main/database/wrapper/node/class_NodeInformationDatabaseWrapper.
 application/hub/main/database/wrapper/node/class_NodeListDatabaseWrapper.php svneol=native#text/plain
 application/hub/main/database/wrapper/states/.htaccess svneol=native#text/plain
 application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php svneol=native#text/plain
+application/hub/main/decoder/.htaccess -text svneol=unset#text/plain
+application/hub/main/decoder/class_ svneol=native#text/plain
+application/hub/main/decoder/package/.htaccess -text svneol=unset#text/plain
+application/hub/main/decoder/package/class_PackageDecoder.php svneol=native#text/plain
 application/hub/main/decorators/.htaccess -text svneol=unset#text/plain
 application/hub/main/discovery/.htaccess -text svneol=unset#text/plain
 application/hub/main/discovery/class_BaseHubDiscovery.php svneol=native#text/plain
@@ -497,6 +503,8 @@ application/hub/main/tasks/hub/chunks/.htaccess -text svneol=unset#text/plain
 application/hub/main/tasks/hub/chunks/class_HubChunkAssemblerTask.php svneol=native#text/plain
 application/hub/main/tasks/hub/class_Hub svneol=native#text/plain
 application/hub/main/tasks/hub/class_HubSelfConnectTask.php svneol=native#text/plain
+application/hub/main/tasks/hub/decoder/.htaccess -text svneol=unset#text/plain
+application/hub/main/tasks/hub/decoder/class_HubPackageDecoderTask.php svneol=native#text/plain
 application/hub/main/tasks/hub/ping/.htaccess -text svneol=unset#text/plain
 application/hub/main/tasks/hub/ping/class_HubPingTask.php svneol=native#text/plain
 application/hub/main/tasks/hub/update/.htaccess -text svneol=unset#text/plain
index fc996d7e3bc02b5e1fdd0bc950d6e77022ead901..d1394fb6cdc31bdbd3007f1d2f26bfcf9557c06c 100644 (file)
@@ -303,6 +303,12 @@ $cfg->setConfigEntry('stacker_decoded_data_max_size', 100);
 // CFG: STACKER-FINAL-CHUNKS-MAX-SIZE
 $cfg->setConfigEntry('stacker_final_chunks_max_size', 100);
 
+// CFG: STACKER-CHUNK-RAW-DATA-MAX-SIZE
+$cfg->setConfigEntry('stacker_chunk_raw_data_max_size', 100);
+
+// CFG: STACKER-DECODED-PACKAGE-MAX-SIZE
+$cfg->setConfigEntry('stacker_decoded_package_max_size', 100);
+
 // CFG: NEWS-MAIN-LIMIT
 $cfg->setConfigEntry('news_main_limit', 5);
 
@@ -399,6 +405,9 @@ $cfg->setConfigEntry('hub_socket_listener_task_class', 'HubSocketListenerTask');
 // CFG: HUB-CHUNK-ASSEMBLER-TASK-CLASS
 $cfg->setConfigEntry('hub_chunk_assembler_task_class', 'HubChunkAssemblerTask');
 
+// CFG: HUB-PACKAGE-DECODER-TASK-CLASS
+$cfg->setConfigEntry('hub_package_decoder_task_class', 'HubPackageDecoderTask');
+
 // CFG: TASK-NETWORK-PACKAGE-WRITER-STARTUP-DELAY
 $cfg->setConfigEntry('task_network_package_writer_startup_delay', 2500);
 
@@ -429,12 +438,21 @@ $cfg->setConfigEntry('task_socket_listener_max_runs', 0);
 // CFG: TASK-CHUNK-ASSEMBLER-STATUP-DELAY
 $cfg->setConfigEntry('task_chunk_assembler_startup_delay', 1500);
 
+// CFG: TASK-PACKAGE-DECODER-STATUP-DELAY
+$cfg->setConfigEntry('task_package_decoder_startup_delay', 1300);
+
 // CFG: TASK-CHUNK-ASSEMBLER-INTERVAL-DELAY
 $cfg->setConfigEntry('task_chunk_assembler_interval_delay', 10);
 
+// CFG: TASK-PACKAGE-DECODER-INTERVAL-DELAY
+$cfg->setConfigEntry('task_package_decoder_interval_delay', 10);
+
 // CFG: TASK-CHUNK-ASSEMBLER-MAX-RUNS
 $cfg->setConfigEntry('task_chunk_assembler_max_runs', 0);
 
+// CFG: TASK-PACKAGE-DECODER-MAX-RUNS
+$cfg->setConfigEntry('task_package_decoder_max_runs', 0);
+
 // CFG: TASK-LIST-CLASS
 $cfg->setConfigEntry('task_list_class', 'TaskList');
 
@@ -555,6 +573,9 @@ $cfg->setConfigEntry('socket_timeout_microseconds', 0);
 // CFG: CHUNK-HANDLER-CLASS
 $cfg->setConfigEntry('chunk_handler_class', 'ChunkHandler');
 
+// CFG: PACKAGE-DECODER-CLASS
+$cfg->setConfigEntry('package_decoder_class', 'PackageDecoder');
+
 ///////////////////////////////////////////////////////////////////////////////
 //                              Peer states
 ///////////////////////////////////////////////////////////////////////////////
index a2bd25b081eda3b140a19920c3c69a9b083a5708..3b63833778bddc02493144fe1416baad3efee469 100644 (file)
@@ -31,13 +31,14 @@ class UnexpectedPackageStatusException extends FrameworkException {
         */
        public function __construct (array $messageArray, $code) {
                // Construct the message
-               $message = sprintf("[%s:%d] Unexpected package status %s!=%s detected, recipient=%s, sender=%s.",
+               $message = sprintf("[%s:%d] Unexpected package status %s!=%s detected, recipient=%s, sender=%s, signature=%s.",
                        $messageArray[0]->__toString(),
                        $this->getLine(),
                        $messageArray[1][NetworkPackage::PACKAGE_DATA_STATUS],
                        $messageArray[2],
                        $messageArray[1][NetworkPackage::PACKAGE_DATA_RECIPIENT],
-                       $messageArray[1][NetworkPackage::PACKAGE_DATA_SENDER]
+                       $messageArray[1][NetworkPackage::PACKAGE_DATA_SENDER],
+                       $messageArray[1][NetworkPackage::PACKAGE_DATA_SIGNATURE]
                );
 
                // Call parent exception constructor
diff --git a/application/hub/interfaces/decoder/.htaccess b/application/hub/interfaces/decoder/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/application/hub/interfaces/decoder/class_Decodeable.php b/application/hub/interfaces/decoder/class_Decodeable.php
new file mode 100644 (file)
index 0000000..72bce82
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * An interface for decoders
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            0.0.0
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 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/>.
+ */
+interface Decodeable extends FrameworkInterface {
+       /**
+        * Checks whether the assoziated stacker for raw package data has some entries left
+        *
+        * @return      $unhandledDataLeft      Whether some unhandled raw package data is left
+        */
+       function ifUnhandledRawPackageDataLeft ();
+
+       /**
+        * Handles raw package data by decoding it
+        *
+        * @return      void
+        */
+       function handleRawPackageData ();
+
+       /**
+        * Checks whether decoded packages have arrived (for this peer)
+        *
+        * @return      $ifDecodedPackagesLeft  Whether decoded packages have arrived
+        */
+       function ifDeocedPackagesLeft ();
+
+       /**
+        * Handles received decoded packages internally (recipient is this node)
+        *
+        * @return      void
+        */
+       function handleDecodedPackage ();
+}
+
+// [EOF]
+?>
index 20189ad6fdd9170086427c53f3532bb8f46407f4..2730741d08000a7c0d7df8a0e660e26ec0677422 100644 (file)
@@ -30,6 +30,14 @@ interface DiscoverableRecipient extends FrameworkInterface {
         */
        function discoverRecipients (array $packageData);
 
+       /**
+        * Tries to discover all recipients by given decoded package data.
+        *
+        * @param       $decodedData    Decoded raw package data array
+        * @return      void
+        */
+       function discoverDecodedRecipients (array $decodedData);
+
        /**
         * "Getter" for recipient iterator
         *
index 2fcc8c53ae1b4bac56932f03e79967f8c47fe012..4c3d66ee8977875572866d336c4abd3b64a066b4 100644 (file)
@@ -70,6 +70,23 @@ interface HandleableChunks extends Handleable {
         * @return      void
         */
        function assembleChunksFromFinalArray ();
+
+       /**
+        * Checks whether the raw package data has been assembled back together.
+        * This can be safely assumed when rawPackageData is not empty and the
+        * collection of all chunks is false (because initHandler() will reset it).
+        *
+        * @return      $isRawPackageDataAvailable      Whether raw package data is available
+        */
+       function ifRawPackageDataIsAvailable ();
+
+       /**
+        * Handles the finally assembled raw package data by feeding it into another
+        * stacker for further decoding/processing.
+        *
+        * @return      void
+        */
+       function handledAssembledRawPackageData ();
 }
 
 // [EOF]
index b6034b048690c812a0427c19b2e02c7204810a8d..869a710bfd2640231e06e400bdc2668c40235dc2 100644 (file)
@@ -68,6 +68,15 @@ interface Receivable extends FrameworkInterface {
         * @return      void
         */
        function addDecodedDataToIncomingStack (Networkable $handlerInstance);
+
+       /**
+        * "Decode" the package content. This method does also verify the attached hash
+        * against the real raw package data (that what the sender has sent).
+        *
+        * @param       $rawPackageContent      The raw package content to be "decoded"
+        * @return      $decodedData            The real package data that the sender has sent
+        */
+       function decodeRawContent ($rawPackageContent);
 }
 
 // [EOF]
index 62c578028bb04f1efa92cbdc0ecf35bb4c821f6b..18a448d7aebfcd33a6c1c0f1fee221566e021af2 100644 (file)
@@ -66,6 +66,16 @@ class BaseHubSystem extends BaseFrameworkSystem {
         */
        private $listenerPoolInstance = NULL;
 
+       /**
+        * Fragmenter instance
+        */
+       private $fragmenterInstance = NULL;
+
+       /**
+        * Decoder instance
+        */
+       private $decoderInstance = NULL;
+
        /**
         * Protected constructor
         *
@@ -210,6 +220,44 @@ class BaseHubSystem extends BaseFrameworkSystem {
                return $this->listenerPoolInstance;
        }
 
+       /**
+        * Setter for fragmenter instance
+        *
+        * @param       $fragmenterInstance             A Fragmentable instance
+        * @return      void
+        */
+       protected final function setFragmenterInstance (Fragmentable $fragmenterInstance) {
+               $this->fragmenterInstance = $fragmenterInstance;
+       }
+
+       /**
+        * Getter for fragmenter instance
+        *
+        * @return      $fragmenterInstance             A Fragmentable instance
+        */
+       protected final function getFragmenterInstance () {
+               return $this->fragmenterInstance;
+       }
+
+       /**
+        * Setter for decoder instance
+        *
+        * @param       $decoderInstance        A Decodeable instance
+        * @return      void
+        */
+       protected final function setDecoderInstance (Decodeable $decoderInstance) {
+               $this->decoderInstance = $decoderInstance;
+       }
+
+       /**
+        * Getter for decoder instance
+        *
+        * @return      $decoderInstance        A Decodeable instance
+        */
+       protected final function getDecoderInstance () {
+               return $this->decoderInstance;
+       }
+
        /**
         * Constructs a callable method name from given socket error code. If the
         * method is not found, a generic one is used.
@@ -219,10 +267,7 @@ class BaseHubSystem extends BaseFrameworkSystem {
         * @throws      UnsupportedSocketErrorHandlerException If the error handler is not implemented
         */
        protected function getSocketErrorHandlerFromCode ($errorCode) {
-               // Set NULL, so everyone is forced to implement socket error handlers
-               $handlerName = NULL;
-
-               // Temporary create a possible name from translated error code
+               // Create a name from translated error code
                $handlerName = 'socketError' . $this->convertToClassName($this->translateSocketErrorCodeToName($errorCode)) . 'Handler';
 
                // Is the call-back method there?
@@ -382,6 +427,9 @@ class BaseHubSystem extends BaseFrameworkSystem {
                // Get a visitor instance
                $visitorInstance = ObjectFactory::createObjectByConfiguredName('shutdown_socket_visitor_class');
 
+               // Debug output
+               $this->debugOutput('HUB-SYSTEM:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString());
+
                // Call the visitor
                $this->accept($visitorInstance);
        }
@@ -403,6 +451,9 @@ class BaseHubSystem extends BaseFrameworkSystem {
                // Get a visitor instance
                $visitorInstance = ObjectFactory::createObjectByConfiguredName('half_shutdown_socket_visitor_class');
 
+               // Debug output
+               $this->debugOutput('HUB-SYSTEM:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString());
+
                // Call the visitor
                $this->accept($visitorInstance);
        }
index 04c2a8ab43fc7968bef2c0ca99a3109ada4cd793..60e96ed74b91b2a47c48071602aa0278a7ceeafd 100644 (file)
@@ -22,7 +22,7 @@
  * 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 NetworkPackageCompressorDecorator extends BaseFrameworkSystem implements Compressor {
+class NetworkPackageCompressorDecorator extends BaseHubSystem implements Compressor {
        /**
         * Protected constructor
         *
diff --git a/application/hub/main/decoder/.htaccess b/application/hub/main/decoder/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/application/hub/main/decoder/class_ b/application/hub/main/decoder/class_
new file mode 100644 (file)
index 0000000..a597db9
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * A ??? decoder class
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            0.0.0
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 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 ???Decoder extends BaseDecoder implements Decodeable {
+       /**
+        * Protected constructor
+        *
+        * @return      void
+        */
+       protected function __construct () {
+               // Call parent constructor
+               parent::__construct(__CLASS__);
+       }
+
+       /**
+        * Creates an instance of this class
+        *
+        * @return      $decoderInstance        An instance of a Decodeable class
+        */
+       public final static function create???Decoder () {
+               // Get new instance
+               $decoderInstance = new ???Decoder();
+
+               // Return the prepared instance
+               return $decoderInstance;
+       }
+}
+
+// [EOF]
+?>
diff --git a/application/hub/main/decoder/class_BaseDecoder.php b/application/hub/main/decoder/class_BaseDecoder.php
new file mode 100644 (file)
index 0000000..35fd129
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * A general Decoder class
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            0.0.0
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 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 BaseDecoder extends BaseHubSystem {
+       /**
+        * Protected constructor
+        *
+        * @param       $className      Name of the class
+        * @return      void
+        */
+       protected function __construct ($className) {
+               // Call parent constructor
+               parent::__construct($className);
+       }
+}
+
+// [EOF]
+?>
diff --git a/application/hub/main/decoder/package/.htaccess b/application/hub/main/decoder/package/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/application/hub/main/decoder/package/class_PackageDecoder.php b/application/hub/main/decoder/package/class_PackageDecoder.php
new file mode 100644 (file)
index 0000000..4d66345
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/**
+ * A Package decoder class
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            0.0.0
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 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 PackageDecoder extends BaseDecoder implements Decodeable {
+       /**
+        * Name for stacker for received packages
+        */
+       const STACKER_NAME_DECODED_PACKAGE = 'decoded_package';
+
+       /**
+        * Protected constructor
+        *
+        * @return      void
+        */
+       protected function __construct () {
+               // Call parent constructor
+               parent::__construct(__CLASS__);
+       }
+
+       /**
+        * Creates an instance of this class
+        *
+        * @param       $stackerInstance        An instance of a Stackable class
+        * @return      $decoderInstance        An instance of a Decodeable class
+        */
+       public final static function createPackageDecoder (Stackable $stackerInstance) {
+               // Get new instance
+               $decoderInstance = new PackageDecoder();
+
+               // Init stacker for received packages
+               $stackerInstance->initStacker(self::STACKER_NAME_DECODED_PACKAGE);
+
+               // Set the stacker instance here
+               $decoderInstance->setStackerInstance($stackerInstance);
+
+               // Get a singleton network package instance
+               $packageInstance = NetworkPackageFactory::createNetworkPackageInstance();
+
+               // And set it in this decoder
+               $decoderInstance->setPackageInstance($packageInstance);
+
+               // Return the prepared instance
+               return $decoderInstance;
+       }
+
+       /**
+        * Checks whether the assoziated stacker for raw package data has some entries left
+        *
+        * @return      $unhandledDataLeft      Whether some unhandled raw package data is left
+        */
+       public function ifUnhandledRawPackageDataLeft () {
+               // Check it
+               $unhandledDataLeft = (!$this->getStackerInstance()->isStackEmpty(ChunkHandler::STACKER_NAME_ASSEMBLED_RAW_DATA));
+
+               // Return it
+               return $unhandledDataLeft;
+       }
+
+       /**
+        * Handles raw package data by decoding it
+        *
+        * @return      void
+        */
+       public function handleRawPackageData () {
+               // Assert on it to make sure the next popNamed() call won't throw an exception
+               assert($this->ifUnhandledRawPackageDataLeft());
+
+               // "Pop" the next raw package content
+               $rawPackageContent = $this->getStackerInstance()->popNamed(ChunkHandler::STACKER_NAME_ASSEMBLED_RAW_DATA);
+
+               // "Decode" the raw package content by using the NetworkPackage instance
+               $decodedData = $this->getPackageInstance()->decodeRawContent($rawPackageContent);
+
+               // Next get a recipient-discovery instance
+               $discoveryInstance = PackageDiscoveryFactory::createPackageDiscoveryInstance();
+
+               // ... then disover all recipient (might be only one), this package may shall be forwarded
+               $discoveryInstance->discoverDecodedRecipients($decodedData);
+
+               // Check for 'recipient' field (the 'sender' field and others are ignored here)
+               if ($discoveryInstance->isRecipientListEmpty()) {
+                       // The recipient is this node so next stack it on 'decoded_package'
+                       $this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECODED_PACKAGE, $decodedData);
+               } else {
+                       // Forward the package to the next node
+                       $this->getPackageInstance()->forwardDecodedPackage($decodedData);
+               }
+       }
+
+       /**
+        * Checks whether decoded packages have arrived (for this peer)
+        *
+        * @return      $ifDecodedPackagesLeft  Whether decoded packages have arrived
+        */
+       public function ifDeocedPackagesLeft () {
+               // Check it ...
+               $ifDecodedPackagesLeft = (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_DECODED_PACKAGE));
+
+               // ... return it
+               return $ifDecodedPackagesLeft;
+       }
+
+       /**
+        * Handles received decoded packages internally (recipient is this node)
+        *
+        * @return      void
+        */
+       public function handleDecodedPackage () {
+               // Get the next entry (assoziative array)
+               $decodedData = $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECODED_PACKAGE);
+
+               // Handle it
+               die('decodedData='.print_r($decodedData,true));
+       }
+}
+
+// [EOF]
+?>
index d1de1423206502e795ab3adc259f13e5fc989384..6c70284b6c340dac4ab968a18db251e136f7cad6 100644 (file)
@@ -41,13 +41,13 @@ class PackageRecipientDiscovery extends BaseHubDiscovery implements Discoverable
                // Get an instance of this class
                $discoveryInstance = new PackageRecipientDiscovery();
 
-               // Output debug message
-               $discoveryInstance->debugOutput('RECIPIENT-DISCOVERY: Initialized.');
-
                // Get recipients list instance and set it
                $listInstance = RecipientListFactory::createRecipientListInstance();
                $discoveryInstance->setListInstance($listInstance);
 
+               // Output debug message
+               $discoveryInstance->debugOutput('RECIPIENT-DISCOVERY: Initialized.');
+
                // Return the prepared instance
                return $discoveryInstance;
        }
@@ -92,6 +92,39 @@ class PackageRecipientDiscovery extends BaseHubDiscovery implements Discoverable
                } // END - switch
        }
 
+       /**
+        * Tries to discover all recipients by given decoded package data.
+        *
+        * @param       $decodedData    Decoded raw package data array
+        * @return      void
+        * @todo        Add some validation of recipient field, e.g. ip:port is found
+        */
+       public function discoverDecodedRecipients (array $decodedData) {
+               // First clear all recipients
+               $this->clearRecipients();
+
+               // Explode 'recipient', first element is the IP/hostname
+               $recipient = explode(':', $decodedData[NetworkPackage::PACKAGE_DATA_RECIPIENT]);
+
+               // Is the 'recipient' field same as this peer's IP?
+               if ($recipient[0] == HubTools::determineOwnExternalIp()) {
+                       /*
+                        * Is same as own external IP, don't do anything here so other
+                        * classes found an empty recipient list for internal (own) handling
+                        * of the original content.
+                        */
+
+                       // Debug output (may flood)
+                       /* NOISY-DEBUG: */ $this->debugOutput('RECIPIENT-DISCOVERY: Recipient ' . $recipient[0] . ' matches own ip (' .  HubTools::determineOwnExternalIp() . ')');
+               } else {
+                       // Debug output (may flood)
+                       /* NOISY-DEBUG: */ $this->debugOutput('RECIPIENT-DISCOVERY: Recipient ' . $recipient[0] . ' is different than own ip (' .  HubTools::determineOwnExternalIp() . '), need to forward (not yet implemented)!');
+
+                       // This package is to be delivered to someone else, so add it
+                       $this->getListInstance()->addEntry('ip_port', $decodedData[NetworkPackage::PACKAGE_DATA_RECIPIENT]);
+               }
+       }
+
        /**
         * "Getter" for recipient iterator
         *
@@ -105,6 +138,19 @@ class PackageRecipientDiscovery extends BaseHubDiscovery implements Discoverable
                return $iteratorInstance;
        }
 
+       /**
+        * Checks whether the recipient list is empty
+        *
+        * @return      $isEmpty        Whether the recipient list is empty
+        */
+       public function isRecipientListEmpty () {
+               // Check it ...
+               $isEmpty = ($this->getListInstance()->count() == 0);
+
+               // Return it
+               return $isEmpty;
+       }
+
        /**
         * Clears all recipients for e.g. another package to deliver. This method
         * simply clears the inner list instance.
index d48b5a5e96de156677e33f02574fd9c020e4b7e8..1816b51c8b1007f4e3a69c1c627067b09d00ac05 100644 (file)
@@ -121,11 +121,9 @@ class PackageSocketDiscovery extends BaseHubDiscovery implements DiscoverableSoc
 
                                // Get a socket resource from our factory (if succeeded)
                                $socketResource = SocketFactory::createSocketFromPackageData($packageData, $protocolName);
-
-                               // This succeeded, so change the state to 'CONNECTED'
                        } catch (SocketConnectionException $e) {
                                // The connection fails of being established, so log it away
-                               $this->debugOutput('SOCKET-DISCOVERY: ' . $e->__toString() . ',message=' . $e->getMessage());
+                               $this->debugOutput('SOCKET-DISCOVERY: Caught ' . $e->__toString() . ',message=' . $e->getMessage());
                        }
                } // END - if
 
index a64280ca4425376ef42fd922e4e323138176f2c2..47c09263166785dda97f61217c3b074c5bed3a1d 100644 (file)
@@ -85,6 +85,12 @@ class NodeTaskHandlerInitializerFilter extends BaseFilter implements Filterable
                // Register it as well
                $handlerInstance->registerTask('chunk_assembler', $taskInstance);
 
+               // Generate package decoder task
+               $taskInstance = ObjectFactory::createObjectByConfiguredName('hub_package_decoder_task_class');
+
+               // Register it as well
+               $handlerInstance->registerTask('package_decoder', $taskInstance);
+
                // Query handler instance
                $handlerInstance->registerTask('query_handler', $nodeInstance->getQueryConnectorInstance());
 
index 5de34ac11f5f1607f04f6993b08dd00c1c469e3a..04db917df4c647706fa1d977836999473c77e00e 100644 (file)
@@ -26,6 +26,7 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
         * Stacker for chunks with final EOP
         */
        const STACKER_NAME_CHUNKS_WITH_FINAL_EOP = 'final_chunks';
+       const STACKER_NAME_ASSEMBLED_RAW_DATA    = 'chunk_raw_data';
 
        /**
         * Chunk splits:
@@ -40,14 +41,25 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
        /**
         * The final array for assembling the original package back together
         */
-       private $finalPackageChunks = array(
-               // Array for package content
-               'content'     => array(),
-               // ... and for the hashes
-               'hashes'      => array(),
-               // ... marker for that the final array is complete for assembling all chunks
-               'is_complete' => false
-       );
+       private $finalPackageChunks = array();
+
+       /**
+        * Array of chunk hashes
+        */
+       private $chunkHashes = array();
+
+       /**
+        * Raw EOP chunk data in an array:
+        *
+        * 0 = Final hash,
+        * 1 = Hash of last chunk
+        */
+       private $eopChunk = array();
+
+       /**
+        * Raw package data
+        */
+       private $rawPackageData = '';
 
        /**
         * Protected constructor
@@ -60,6 +72,9 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
 
                // Set handler name
                $this->setHandlerName('chunk');
+
+               // Initialize handler
+               $this->initHandler();
        }
 
        /**
@@ -76,6 +91,7 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
 
                // Init all stacker
                $stackerInstance->initStacker(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP);
+               $stackerInstance->initStacker(self::STACKER_NAME_ASSEMBLED_RAW_DATA);
 
                // Set the stacker in this handler
                $handlerInstance->setStackerInstance($stackerInstance);
@@ -86,10 +102,44 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
                // ... and set it in this handler
                $handlerInstance->setCryptoInstance($cryptoInstance);
 
+               // Get a fragmenter instance for later verification of serial numbers (e.g. if all are received)
+               $fragmenterInstance = FragmenterFactory::createFragmenterInstance('package');
+
+               // Set it in this handler
+               $handlerInstance->setFragmenterInstance($fragmenterInstance);
+
                // Return the prepared instance
                return $handlerInstance;
        }
 
+       /**
+        * Initializes the handler
+        *
+        * @return      void
+        */
+       private function initHandler () {
+               // Init finalPackageChunks
+               $this->finalPackageChunks = array(
+                       // Array for package content
+                       'content'        => array(),
+                       // ... and for the hashes
+                       'hashes'         => array(),
+                       // ... marker for that the final array is complete for assembling all chunks
+                       'is_complete'    => false,
+                       // ... steps done to assemble all chunks
+                       'assemble_steps' => 0,
+               );
+
+               // ... chunkHashes:
+               $this->chunkHashes = array();
+
+               // ... eopChunk:
+               $this->eopChunk = array(
+                       0 => 'INVALID',
+                       1 => 'INVALID',
+               );
+       }
+
        /**
         * Checks whether the hash generated from package content is the same ("valid") as given
         *
@@ -163,6 +213,133 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
                $this->finalPackageChunks['is_complete'] = true;
        }
 
+       /**
+        * Sorts the chunks array by using the serial number as a sorting key. In
+        * most situations a call of ksort() is enough to accomblish this. So this
+        * method may only call ksort() on the chunks array.
+        *
+        * This method sorts 'content' and 'hashes' so both must have used the
+        * serial numbers as array indexes.
+        *
+        * @return      void
+        */
+       private function sortChunksArray () {
+               // Sort 'content' first
+               ksort($this->finalPackageChunks['content']);
+
+               // ... then 'hashes'
+               ksort($this->finalPackageChunks['hashes']);
+       }
+
+       /**
+        * Prepares the package assemble by removing last chunks (last shall be
+        * hash chunk, pre-last shall be EOP chunk) and verify that all serial
+        * numbers are valid (same as PackageFragmenter class would generate).
+        *
+        * @return      void
+        */
+       private function preparePackageAssmble () {
+               // Make sure both arrays have same count (this however should always be true)
+               assert(count($this->finalPackageChunks['hashes']) == count($this->finalPackageChunks['content']));
+
+               /*
+                * Remove last element (hash chunk) from 'hashes'. This hash will never
+                * be needed, so ignore it.
+                */
+               array_pop($this->finalPackageChunks['hashes']);
+
+               // ... and from 'content' as well but save it for later use
+               $this->chunkHashes = explode(PackageFragmenter::CHUNK_HASH_SEPARATOR, substr(array_pop($this->finalPackageChunks['content']), strlen(PackageFragmenter::HASH_CHUNK_IDENTIFIER)));
+
+               // Remove EOP chunk and keep a copy of it
+               array_pop($this->finalPackageChunks['hashes']);
+               $this->eopChunk = explode(PackageFragmenter::CHUNK_HASH_SEPARATOR, substr(array_pop($this->finalPackageChunks['content']), strlen(PackageFragmenter::END_OF_PACKAGE_IDENTIFIER)));
+
+               // Verify all serial numbers
+               $this->verifyChunkSerialNumbers();
+       }
+
+       /**
+        * Verifies all chunk serial numbers by using a freshly initialized
+        * fragmenter instance. Do ALWAYS sort the array and array_pop() the hash
+        * chunk before calling this method to avoid re-requests of many chunks.
+        *
+        * @return      void
+        */
+       private function verifyChunkSerialNumbers () {
+               // Reset the serial number generator
+               $this->getFragmenterInstance()->resetSerialNumber();
+
+               // "Walk" through all (content) chunks
+               foreach ($this->finalPackageChunks['content'] as $serialNumber=>$content) {
+                       // Get next serial number
+                       $nextSerial = $this->getFragmenterInstance()->getNextHexSerialNumber();
+
+                       // Debug output
+                       //* NOISY-DEBUG */ $this->debugOutput('CHUNK-HANDLER: serialNumber=' . $serialNumber . ',nextSerial=' . $nextSerial);
+
+                       // Is it not the same? Then re-request it
+                       if ($serialNumber != $nextSerial) {
+                               // This is invalid, so remove it
+                               unset($this->finalPackageChunks['content'][$serialNumber]);
+                               unset($this->finalPackageChunks['hashes'][$serialNumber]);
+
+                               // And re-request it with valid serial number (and hash chunk)
+                               $this->rerequestChunkBySerialNumber($nextSerial);
+                       } // END - if
+               } // END - foreach
+       }
+
+       /**
+        * Assembles and verifies ("final check") chunks back together to the
+        * original package (raw data for the start). This method should only be
+        * called AFTER the EOP and final-chunk chunk have been removed.
+        *
+        * @return      void
+        */
+       private function assembleAllChunksToPackage () {
+               // If chunkHashes is not filled, don't continue
+               assert(count($this->chunkHashes) > 0);
+
+               // Init raw package data string
+               $this->rawPackageData = '';
+
+               // That went well, so start assembling all chunks
+               foreach ($this->finalPackageChunks['content'] as $serialNumber=>$content) {
+                       // Is this chunk valid? This should be the case
+                       assert($this->isChunkHashValid(array(
+                               self::CHUNK_SPLITS_INDEX_HASH     => $this->finalPackageChunks['hashes'][$serialNumber],
+                               self::CHUNK_SPLITS_INDEX_RAW_DATA => $content
+                       )));
+
+                       // ... and is also in the hash chunk?
+                       assert(in_array($this->finalPackageChunks['hashes'][$serialNumber], $this->chunkHashes));
+
+                       // Verification okay, add it to the raw data
+                       $this->rawPackageData .= $content;
+               } // END - foreach
+
+               // Debug output
+               //* NOISY-DEBUG: */ $this->debugOutput('CHUNK-HANDLER: eopChunk[1]=' . $this->eopChunk[1] . ',' . chr(10) . 'index=' . (count($this->chunkHashes) - 2) . ',' . chr(10) . 'chunkHashes='.print_r($this->chunkHashes,true));
+
+               // The last chunk hash must match with the one from eopChunk[1]
+               assert($this->eopChunk[1] == $this->chunkHashes[count($this->chunkHashes) - 2]);
+       }
+
+       /**
+        * Verifies the finally assembled raw package data by comparing it against
+        * the final hash.
+        *
+        * @return      void
+        */
+       private function verifyRawPackageData () {
+               // Hash the raw package data for final verification
+               $finalHash = $this->getCryptoInstance()->hashString($this->rawPackageData, $this->eopChunk[0], false);
+
+               // Is it the same?
+               assert($finalHash == $this->eopChunk[0]);
+       }
+
        /**
         * Adds all chunks if the last one verifies as a 'final chunk'.
         *
@@ -295,7 +472,67 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable
                // Make sure the final array is really completed
                assert($this->ifUnassembledChunksAvailable());
 
-               $this->partialStub('Please implement this method.');
+               // Count up stepping
+               $this->finalPackageChunks['assemble_steps']++;
+
+               // Do the next step
+               switch ($this->finalPackageChunks['assemble_steps']) {
+                       case 1: // Sort the chunks array (the serial number shall act as a sorting key)
+                               $this->sortChunksArray();
+                               break;
+
+                       case 2: // Prepare the assemble by removing last two indexes
+                               $this->preparePackageAssmble();
+                               break;
+
+                       case 3: // Assemble all chunks back together to the original package
+                               $this->assembleAllChunksToPackage();
+                               break;
+
+                       case 4: // Verify the raw data by hashing it again
+                               $this->verifyRawPackageData();
+                               break;
+
+                       case 5: // Re-initialize handler to reset it to the old state
+                               $this->initHandler();
+                               break;
+
+                       default: // Invalid step found
+                               $this->debugOutput('CHUNK-HANDLER: Invalid step ' . $this->finalPackageChunks['assemble_steps'] . ' detected.');
+                               break;
+               } // END - switch
+       }
+
+       /**
+        * Checks whether the raw package data has been assembled back together.
+        * This can be safely assumed when rawPackageData is not empty and the
+        * collection of all chunks is false (because initHandler() will reset it).
+        *
+        * @return      $isRawPackageDataAvailable      Whether raw package data is available
+        */
+       public function ifRawPackageDataIsAvailable () {
+               // Check it
+               $isRawPackageDataAvailable = ((!empty($this->rawPackageData)) && (!$this->ifUnassembledChunksAvailable()));
+
+               // Return it
+               return $isRawPackageDataAvailable;
+       }
+
+       /**
+        * Handles the finally assembled raw package data by feeding it into another
+        * stacker for further decoding/processing.
+        *
+        * @return      void
+        */
+       public function handledAssembledRawPackageData () {
+               // Assert to make sure that there is raw package data available
+               assert($this->ifRawPackageDataIsAvailable());
+
+               // Then feed it into the next stacker
+               $this->getStackerInstance()->pushNamed(self::STACKER_NAME_ASSEMBLED_RAW_DATA, $this->rawPackageData);
+
+               // ... and reset it
+               $this->rawPackageData = '';
        }
 }
 
index f66bc15c65691c5209ad971a5ead6d53fc3ac844..685d079e31ff7fd774788dcbbe9de3a006cc66dd 100644 (file)
@@ -220,6 +220,9 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc
                $socketResource = $this->getSocketResource();
                $timeout = $this->getConfigInstance()->getConfigEntry('socket_timeout_seconds');
 
+               // Debug output
+               $this->debugOutput('CONNECTION-HELPER: Trying to connect to ' . $recipientData[0] . ':' . $recipientData[1] . ' with socketResource[' . gettype($socketResource) . ']=' . $socketResource . ' ...');
+
                // Try to connect until it is connected
                while ($isConnected = !@socket_connect($socketResource, $recipientData[0], $recipientData[1])) {
                        // Get last socket error
index a484879959ee3e4153d7d3eac3e0f87bca92086f..0fd7a8a8079d613843ba78e4bcfc97da47e92af4 100644 (file)
@@ -203,7 +203,7 @@ class BaseList extends BaseHubSystem implements IteratorAggregate, Countable {
 
                // Add the hash to the index
                $this->listIndex[] = $hash;
-               //* DEBUG: */ print $groupName.'/'.count($this->listIndex).chr(10);
+               //* DEBUG: */ print $groupName.'/'.$this->count().chr(10);
 
                // Now add the entry to the list
                $this->listEntries[$hash] = $entry;
index bd094561cb783993cbe75523b799ec212d436b5c..4e480d3e492ef000243ac74914ad4dcb12c7269e 100644 (file)
@@ -35,7 +35,7 @@
  * 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 NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receivable, Registerable, Visitable {
+class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, Registerable, Visitable {
        /**
         * Package mask for compressing package data:
         * 0: Compressor extension
@@ -71,6 +71,7 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
        const INDEX_PACKAGE_RECIPIENT = 1;
        const INDEX_PACKAGE_CONTENT   = 2;
        const INDEX_PACKAGE_STATUS    = 3;
+       const INDEX_PACKAGE_SIGNATURE = 4;
 
        /**
         * Named array elements for package data
@@ -79,20 +80,22 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
        const PACKAGE_DATA_RECIPIENT = 'recipient';
        const PACKAGE_DATA_CONTENT   = 'content';
        const PACKAGE_DATA_STATUS    = 'status';
+       const PACKAGE_DATA_SIGNATURE = 'signature';
 
        /**
         * All package status
         */
        const PACKAGE_STATUS_NEW     = 'new';
        const PACKAGE_STATUS_FAILED  = 'failed';
+       const PACKAGE_STATUS_DECODED = 'decoded';
 
        /**
-        * Tags SEPARATOR
+        * Tags separator
         */
        const PACKAGE_TAGS_SEPARATOR = ';';
 
        /**
-        * Raw package data SEPARATOR
+        * Raw package data separator
         */
        const PACKAGE_DATA_SEPARATOR = '#';
 
@@ -200,6 +203,10 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
                // Set it in this package
                $packageInstance->setVisitorInstance($visitorInstance);
 
+               // Get crypto instance and set it in this package
+               $cryptoInstance = ObjectFactory::createObjectByConfiguredName('crypto_class');
+               $packageInstance->setCryptoInstance($cryptoInstance);
+
                // Return the prepared instance
                return $packageInstance;
        }
@@ -267,7 +274,10 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
                } // END - if
 
                // Pop the entry (it should be it)
-               $this->getStackerInstance()->popNamed($stackerName);
+               $nextData = $this->getStackerInstance()->popNamed($stackerName);
+
+               // Compare both arrays
+               assert($nextData[self::PACKAGE_DATA_SIGNATURE] == $packageData[self::PACKAGE_DATA_SIGNATURE]);
 
                // Temporary set the new status
                $packageData[self::PACKAGE_DATA_STATUS] = $newStatus;
@@ -368,9 +378,18 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
 
                // Is it not there?
                if ((is_resource($socketResource)) && (!$registryInstance->isSocketRegistered($helperInstance, $socketResource))) {
+                       // Debug message
+                       $this->debugOutput('PACKAGE: Registering socket ' . $socketResource . ' ...');
+
                        // Then register it
                        $registryInstance->registerSocket($helperInstance, $socketResource, $packageData);
-               } // END - if
+               } elseif (!$helperInstance->getStateInstance()->isPeerStateConnected()) {
+                       // Is not connected, then we cannot send
+                       $this->debugOutput('PACKAGE: Unexpected peer state ' . $helperInstance->getStateInstance()->__toString() . ' detected.');
+
+                       // Shutdown the socket
+                       $this->shutdownSocket($socketResource);
+               }
 
                // Debug message
                //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: Reached line ' . __LINE__ . ' after isSocketRegistered() has been called.');
@@ -383,6 +402,9 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
 
                // Enqueue it again on the out-going queue, the connection is up and working at this point
                $this->getStackerInstance()->pushNamed(self::STACKER_NAME_OUTGOING, $packageData);
+
+               // Debug message
+               //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: Reached line ' . __LINE__ . ' after pushNamed() has been called.');
        }
 
        /**
@@ -412,6 +434,27 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
                $this->storeUnsentBytesInBackBuffer($packageData, $sentBytes);
        }
 
+       /**
+        * Generates a signature for given raw package content and sender id
+        *
+        * @param       $content        Raw package data
+        * @param       $senderId       Sender id to generate a signature for
+        * @return      $signature      Signature as BASE64-encoded string
+        */
+       private function generatePackageSignature ($content, $senderId) {
+               // ash content and sender id together, use md5() as last algo
+               $hash = md5($this->getCryptoInstance()->hashString($senderId . $content));
+
+               // Encrypt the content again with the hash as a key
+               $encryptedContent = $this->getCryptoInstance()->encryptString($content, $hash);
+
+               // Encode it with BASE64
+               $signature = base64_encode($encryptedContent);
+
+               // Return it
+               return $signature;
+       }
+
        /**
         * "Enqueues" raw content into this delivery class by reading the raw content
         * from given template instance and pushing it on the 'undeclared' stack.
@@ -450,7 +493,8 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
                        self::PACKAGE_DATA_SENDER    => $nodeInstance->getSessionId(),
                        self::PACKAGE_DATA_RECIPIENT => $helperInstance->getRecipientType(),
                        self::PACKAGE_DATA_CONTENT   => $content,
-                       self::PACKAGE_DATA_STATUS    => self::PACKAGE_STATUS_NEW
+                       self::PACKAGE_DATA_STATUS    => self::PACKAGE_STATUS_NEW,
+                       self::PACKAGE_DATA_SIGNATURE => $this->generatePackageSignature($content, $nodeInstance->getSessionId())
                ));
        }
 
@@ -548,7 +592,7 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
                        $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECLARED);
                } catch (InvalidStateException $e) {
                        // The state is not excepected (shall be 'connected')
-                       $this->debugOutput('PACKAGE: Caught exception ' . $e->__toString() . ' with message=' . $e->getMessage());
+                       $this->debugOutput('PACKAGE: Caught ' . $e->__toString() . ',message=' . $e->getMessage());
 
                        // Mark the package with status failed
                        $this->changePackageStatus($packageData, self::STACKER_NAME_DECLARED, self::PACKAGE_STATUS_FAILED);
@@ -790,6 +834,32 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva
                // Remove this entry
                $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECLARED);
        }
+
+       /**
+        * "Decode" the package content into the same array when it was sent.
+        *
+        * @param       $rawPackageContent      The raw package content to be "decoded"
+        * @return      $decodedData            An array with 'sender', 'recipient', 'content' and 'status' elements
+        */
+       public function decodeRawContent ($rawPackageContent) {
+               // Use the separator '#' to "decode" it
+               $decodedArray = explode(self::PACKAGE_DATA_SEPARATOR, $rawPackageContent);
+
+               // Assert on count (should be always 3)
+               assert(count($decodedArray) == 3);
+
+               // Create 'decodedData' array with all assoziative array elements
+               $decodedData = array(
+                       self::PACKAGE_DATA_SENDER    => $decodedArray[self::INDEX_PACKAGE_SENDER],
+                       self::PACKAGE_DATA_RECIPIENT => $decodedArray[self::INDEX_PACKAGE_RECIPIENT],
+                       self::PACKAGE_DATA_CONTENT   => $decodedArray[self::INDEX_PACKAGE_CONTENT],
+                       self::PACKAGE_DATA_STATUS    => self::PACKAGE_STATUS_DECODED,
+                       self::PACKAGE_DATA_SIGNATURE => $this->generatePackageSignature($decodedArray[self::INDEX_PACKAGE_CONTENT], $decodedArray[self::INDEX_PACKAGE_SENDER])
+               );
+
+               // And return it
+               return $decodedData;
+       }
 }
 
 // [EOF]
index 81f63f242273c2bad97f64db60461f7bfceb55cd..d1c59c7fbcd3f33b0788f44a34bcb7f777f68b40 100644 (file)
@@ -30,7 +30,7 @@
  * 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 PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Registerable {
+class PackageFragmenter extends BaseHubSystem implements Fragmentable, Registerable {
        /**
         * Cached chunk size in bits
         */
@@ -284,40 +284,21 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                return $hash;
        }
 
-       /**
-        * "Getter" for the next hexadecimal-encoded serial number
-        *
-        * @return      $encodedSerialNumber    The next hexadecimal-encoded serial number
-        */
-       private function getNextHexSerialNumber () {
-               // Assert on maximum serial number length
-               assert($this->serialNumber <= $this->maxSerialNumber);
-
-               // Encode the current serial number
-               $encodedSerialNumber = $this->dec2Hex($this->serialNumber, self::MAX_SERIAL_LENGTH);
-
-               // Count one up
-               $this->serialNumber++;
-
-               // Return the encoded serial number
-               return $encodedSerialNumber;
-       }
-
        /**
         * Appends an end-of-package chunk to the chunk list for given chunk and
         * final hash. As of 23-March-2012 the format of this chunk will be as any
         * regular one to keep things easy (KISS) in ChunkHandler class.
         *
-        * @param       $chunkHash      Last chunk's hash
+        * @param       $lastChunk      Last chunk raw data
         * @param       $finalHash      Final hash for raw (unencoded) data
         * @return      void
         */
-       private function appendEndOfPackageChunk ($chunkHash, $finalHash) {
+       private function appendEndOfPackageChunk ($lastChunk, $finalHash) {
                // Generate end-of-package marker
                $chunkData =
                        self::END_OF_PACKAGE_IDENTIFIER .
                        $finalHash . self::CHUNK_HASH_SEPARATOR .
-                       $chunkHash;
+                       $this->generateHashFromRawData($lastChunk);
 
                // Add it as regular chunk
                $this->addChunkData($finalHash, $chunkData);
@@ -342,6 +323,7 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
 
                // Init variables
                $chunkHash = '';
+               $chunkData = '';
 
                // Now split it up
                for ($idx = 0; $idx < strlen($rawData); $idx += $dataChunkSize) {
@@ -356,7 +338,7 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                //* NOISY-DEBUG: */ $this->debugOutput('FRAGMENTER: Raw data of ' . strlen($rawData) . ' bytes has been fragmented into ' . count($this->chunks[$finalHash]) . ' chunk(s).');
 
                // Add end-of-package chunk
-               $this->appendEndOfPackageChunk($chunkHash, $finalHash);
+               $this->appendEndOfPackageChunk($chunkData, $finalHash);
        }
 
        /**
@@ -429,6 +411,25 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                } // END - for
        }
 
+       /**
+        * "Getter" for the next hexadecimal-encoded serial number
+        *
+        * @return      $encodedSerialNumber    The next hexadecimal-encoded serial number
+        */
+       public function getNextHexSerialNumber () {
+               // Assert on maximum serial number length
+               assert($this->serialNumber <= $this->maxSerialNumber);
+
+               // Encode the current serial number
+               $encodedSerialNumber = $this->dec2Hex($this->serialNumber, self::MAX_SERIAL_LENGTH);
+
+               // Count one up
+               $this->serialNumber++;
+
+               // Return the encoded serial number
+               return $encodedSerialNumber;
+       }
+
        /**
         * This method does "implode" the given package data array into one long
         * string, splits it into small chunks, adds a serial number and checksum
@@ -517,6 +518,15 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                // Return the chunk array
                return $rawDataChunk;
        }
+
+       /**
+        * Resets the serial number to zero
+        *
+        * @return      void
+        */
+       public function resetSerialNumber () {
+               $this->serialNumber = 0;
+       }
 }
 
 // [EOF]
index 4e42fe89c94a9a6319b1ab6d8b0398ac7e016ab3..c73be9a6b31fc654381d03b6cf41409189323452 100644 (file)
@@ -94,7 +94,8 @@ class ConnectionStatisticsHelper extends BaseHubSystem {
                        self::$connectionStatistics[$helperInstance->getProtocol()][$helperInstance->__toString()]['retry_count']++;
                }
 
-               // Create/update 'last_update' for later purging
+               // Create/update 'last_update' for purging
+               // @TODO last_update is not being used at the moment
                self::$connectionStatistics[$helperInstance->getProtocol()][$helperInstance->__toString()]['last_update'] = time();
        }
 }
index abedc43268b7de4e6c3eab6618075a37e8211a1f..e5aaca9f7269dbd5c5fb87a70b35c2d536762928 100644 (file)
@@ -89,6 +89,12 @@ class HubChunkAssemblerTask extends BaseTask implements Taskable, Visitable {
                         * 'final array' for last verification.
                         */
                        $this->getHandlerInstance()->handleAvailableChunksWithFinal();
+               } elseif ($this->getHandlerInstance()->ifRawPackageDataIsAvailable()) {
+                       /*
+                        * The final raw package data is back together again. So feed it
+                        * into the next stack for further decoding/processing
+                        */
+                       $this->getHandlerInstance()->handledAssembledRawPackageData();
                }
        }
 }
diff --git a/application/hub/main/tasks/hub/decoder/.htaccess b/application/hub/main/tasks/hub/decoder/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/application/hub/main/tasks/hub/decoder/class_HubPackageDecoderTask.php b/application/hub/main/tasks/hub/decoder/class_HubPackageDecoderTask.php
new file mode 100644 (file)
index 0000000..dd9d177
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * A PackageDecoder hub-task
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            0.0.0
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 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 HubPackageDecoderTask extends BaseTask implements Taskable, Visitable {
+       /**
+        * Protected constructor
+        *
+        * @return      void
+        */
+       protected function __construct () {
+               // Call parent constructor
+               parent::__construct(__CLASS__);
+       }
+
+       /**
+        * Creates an instance of this class
+        *
+        * @return      $taskInstance   An instance of a Visitable class
+        */
+       public final static function createHubPackageDecoderTask () {
+               // Get new instance
+               $taskInstance = new HubPackageDecoderTask();
+
+               // Get a chunk handler instance
+               $handlerInstance = ChunkHandlerFactory::createChunkHandlerInstance();
+
+               // Get the stacker from it, we don't need the handler here
+               $stackerInstance = $handlerInstance->getStackerInstance();
+
+               // Get a decoder instance
+               $decoderInstance = ObjectFactory::createObjectByConfiguredName('package_decoder_class', array($stackerInstance));
+
+               // ... and also set the decoder instance here
+               $taskInstance->setDecoderInstance($decoderInstance);
+
+               // Return the prepared instance
+               return $taskInstance;
+       }
+
+       /**
+        * Accepts the visitor to process the visit "request"
+        *
+        * @param       $visitorInstance        An instance of a Visitor class
+        * @return      void
+        * @todo        Maybe visit some sub-objects
+        */
+       public function accept (Visitor $visitorInstance) {
+               // Visit this task
+               $visitorInstance->visitTask($this);
+       }
+
+       /**
+        * Executes the task
+        *
+        * @return      void
+        */
+       public function executeTask () {
+               // Check if the stacker has some entries left
+               if ($this->getDecoderInstance()->ifUnhandledRawPackageDataLeft()) {
+                       // Then handle it
+                       $this->getDecoderInstance()->handleRawPackageData();
+               } elseif ($this->getDecoderInstance()->ifDeocedPackagesLeft()) {
+                       // Some decoded packages have arrived (for this peer)
+                       $this->getDecoderInstance()->handleDecodedPackage();
+               }
+       }
+}
+
+// [EOF]
+?>
index 2313a61623b303899f5f2604673101c7d78c2ba2..c7063ece5f8eab7bef7e2d11c40156276a11d207 100644 (file)
@@ -21,7 +21,7 @@
  * 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 HubTools extends BaseFrameworkSystem {
+class HubTools extends BaseHubSystem {
        // Constants for exceptions
        const EXCEPTION_SESSION_ID_IS_INVALID = 0x200;
        const EXCEPTION_HOSTNAME_NOT_FOUND    = 0x201;
index af92510b7069f30e3d454d8e90f96ad0a05cb391..1613cdbb892f873e5e065f8832ac57b22bd95734 100644 (file)
@@ -6,7 +6,7 @@
 ./application/hub/interfaces/helper/connections/class_ConnectionHelper.php:38:  * @todo        We may want to implement a filter for ease notification of other objects like our pool
 ./application/hub/interfaces/helper/messages/class_MessageHelper.php:10: * @todo               Please find another name for this interface
 ./application/hub/interfaces/nodes/class_NodeHelper.php:10: * @todo            We need to find a better name for this interface
-./application/hub/main/class_BaseHubSystem.php:331:                            // @TODO On some systems it is 134, on some 107?
+./application/hub/main/class_BaseHubSystem.php:376:                            // @TODO On some systems it is 134, on some 107?
 ./application/hub/main/commands/console/class_HubConsoleChatCommand.php:107:    * @todo        Should we add some more filters?
 ./application/hub/main/commands/console/class_HubConsoleChatCommand.php:58:     * @todo        Try to create a ChatActivationTask or so
 ./application/hub/main/commands/console/class_HubConsoleCruncherCommand.php:107:        * @todo        Should we add some more filters?
@@ -22,6 +22,7 @@
 ./application/hub/main/cruncher/mcrypt/class_HubMcryptCruncher.php:98:         // @TODO Implement this method
 ./application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php:177:    * @todo        Unfinished area
 ./application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php:219:    * @todo        Unfinished area
+./application/hub/main/discovery/package/class_PackageRecipientDiscovery.php:100:       * @todo        Add some validation of recipient field, e.g. ip:port is found
 ./application/hub/main/discovery/socket/class_PackageSocketDiscovery.php:102:                  // @TODO We may need some logging here
 ./application/hub/main/factories/socket/class_SocketFactory.php:10: * @todo            Find an interface for hub helper
 ./application/hub/main/filter/bootstrap/chat/class_ChatBootstrapGenericActivationFilter.php:54:         * @todo        Maybe we want to do somthing more here?
 ./application/hub/main/nodes/regular/class_HubRegularNode.php:58:       * @todo        Implement this method
 ./application/hub/main/nodes/regular/class_HubRegularNode.php:68:       * @todo        Unfinished method
 ./application/hub/main/nodes/regular/class_HubRegularNode.php:91:              // @TODO Add some filters here
-./application/hub/main/package/class_NetworkPackage.php:237:    * @todo        $helperInstance is unused
 ./application/hub/main/package/class_NetworkPackage.php:23: * @todo            Needs to add functionality for handling the object's type
-./application/hub/main/package/class_NetworkPackage.php:241:           // @TODO crc32() is very weak, but it needs to be fast
-./application/hub/main/package/class_NetworkPackage.php:404:                   // @TODO We may want to do somthing more here?
-./application/hub/main/package/class_NetworkPackage.php:510:                   // @TODO Add some logging here
-./application/hub/main/package/class_NetworkPackage.php:536:                   // @TODO Add some logging here
-./application/hub/main/package/class_NetworkPackage.php:640:                   // @TODO Add some logging here
-./application/hub/main/package/class_NetworkPackage.php:739:           // @TODO Add some content here
-./application/hub/main/package/class_NetworkPackage.php:778:    * @todo        This may be enchanced for outgoing packages?
+./application/hub/main/package/class_NetworkPackage.php:244:    * @todo        $helperInstance is unused
+./application/hub/main/package/class_NetworkPackage.php:248:           // @TODO crc32() is very weak, but it needs to be fast
+./application/hub/main/package/class_NetworkPackage.php:426:                   // @TODO We may want to do somthing more here?
+./application/hub/main/package/class_NetworkPackage.php:554:                   // @TODO Add some logging here
+./application/hub/main/package/class_NetworkPackage.php:580:                   // @TODO Add some logging here
+./application/hub/main/package/class_NetworkPackage.php:684:                   // @TODO Add some logging here
+./application/hub/main/package/class_NetworkPackage.php:783:           // @TODO Add some content here
+./application/hub/main/package/class_NetworkPackage.php:822:    * @todo        This may be enchanced for outgoing packages?
 ./application/hub/main/package/fragmenter/class_PackageFragmenter.php:274:      * @todo        Implement a way to send non-announcement packages with extra-salt
-./application/hub/main/package/fragmenter/class_PackageFragmenter.php:441:      * @todo        $helperInstance is unused
+./application/hub/main/package/fragmenter/class_PackageFragmenter.php:442:      * @todo        $helperInstance is unused
 ./application/hub/main/producer/cruncher/keys/class_CruncherKeyProducer.php:106:                       // @TODO Do something with it
 ./application/hub/main/producer/cruncher/keys/class_CruncherKeyProducer.php:62:         * @todo        Find something for init phase of this key producer
 ./application/hub/main/producer/cruncher/keys/class_CruncherKeyProducer.php:72:         * @todo        ~30% done
 ./application/hub/main/resolver/state/peer/class_PeerStateResolver.php:59:      * @todo        ~30% done
 ./application/hub/main/states/node/init/class_NodeInitState.php:60:     * @todo        We might want to move some calls to this method to fill it with life
 ./application/hub/main/statistics/connection/class_ConnectionStatisticsHelper.php:11: * @todo          Find an interface for hub helper
+./application/hub/main/statistics/connection/class_ConnectionStatisticsHelper.php:98:          // @TODO last_update is not being used at the moment
 ./application/hub/main/streams/raw_data/input/class_RawDataInputStream.php:57:  * @todo        Do we need to do something more here?
 ./application/hub/main/streams/raw_data/output/class_RawDataOutputStream.php:53:        * @todo        Do we need to do something more here?
 ./application/hub/main/tasks/chat/class_ChatTelnetListenerTask.php:53:  * @todo        Maybe visit some sub-objects
 ./application/hub/main/tasks/hub/class_HubSelfConnectTask.php:53:       * @todo        0%
 ./application/hub/main/tasks/hub/class_HubSocketListenerTask.php:63:           // @TODO Do we need to visit this task? $visitorInstance->visitTask($this);
 ./application/hub/main/tasks/hub/class_HubSocketListenerTask.php:70:    * @todo        0% done
+./application/hub/main/tasks/hub/decoder/class_HubPackageDecoderTask.php:65:    * @todo        Maybe visit some sub-objects
 ./application/hub/main/tasks/hub/ping/class_HubPingTask.php:63:         * @todo        Also visit some sub-objects?
 ./application/hub/main/tasks/hub/ping/class_HubPingTask.php:74:         * @todo        0% done
 ./application/hub/main/tasks/hub/update/class_HubUpdateCheckTask.php:53:        * @todo        0%
 ./inc/classes/exceptions/main/class_MissingMethodException.php:13: * @todo             Try to rewrite user/guest login classes and mark this exception as deprecated
 ./inc/classes/exceptions/main/class_NoConfigEntryException.php:10: * @todo             Rename this class to NoFoundEntryException
 ./inc/classes/interfaces/class_FrameworkInterface.php:11: * @todo              Find a better name for this interface
-./inc/classes/main/class_BaseFrameworkSystem.php:1301:  * @todo        Write a logging mechanism for productive mode
-./inc/classes/main/class_BaseFrameworkSystem.php:1315:                 // @TODO Finish this part!
+./inc/classes/main/class_BaseFrameworkSystem.php:1306:  * @todo        Write a logging mechanism for productive mode
+./inc/classes/main/class_BaseFrameworkSystem.php:1320:                 // @TODO Finish this part!
 ./inc/classes/main/class_BaseFrameworkSystem.php:195:  // @todo Try to clean these constants up
 ./inc/classes/main/class_BaseFrameworkSystem.php:465:   * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
 ./inc/classes/main/commands/web/class_WebLoginAreaCommand.php:64:       * @todo        Add some stuff here: Some personal data, app/game related data