]> git.mxchange.org Git - hub.git/blobdiff - application/hub/main/package/fragmenter/class_PackageFragmenter.php
New singleton-factories introduced:
[hub.git] / application / hub / main / package / fragmenter / class_PackageFragmenter.php
index 1cf6db7ea45fbfe2e0fe52638c5eab910119d5dd..ca073ae07e356c9d5265cd16cb2c160182ba580c 100644 (file)
@@ -1,9 +1,15 @@
 <?php
 /**
  * A PackageFragmenter class to fragment package data into smaller chunks for
- * delivery. This class does add a serial number to it and in the first data
- * submission chunk it will add a sumerization of all fragements and their
- * serial numbers.
+ * delivery. This class calculates a final hash on the raw input data and
+ * fragments the data into smaller chunks after it has been encoded by a
+ * "outgoing encoding stream".
+ *
+ * All chunks are extended with a hash and a serial number to make it later
+ * easier to verify them and put them back in the right order and to, if
+ * required, request a re-delivery of an invalid chunk (e.g. hash didn't match).
+ * Also an "end-of-package" marker is being added as the last chunk to mark the
+ * end of of the whole package submission.
  *
  * @author             Roland Haeder <webmaster@ship-simu.org>
  * @version            0.0.0
@@ -64,6 +70,7 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
         * Maximum possible serial number
         */
        private $maxSerialNumber  = 0;
+
        /**
         * Seperator between chunk data, serial number and chunk hash
         */
@@ -74,11 +81,21 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
         */
        const CHUNK_HASH_SEPERATOR = ';';
 
+       /**
+        * Seperator between two chunks
+        */
+       const CHUNK_SEPERATOR = '|';
+
        /**
         * Identifier for hash chunk
         */
        const HASH_CHUNK_IDENTIFIER = 'HASH-CHUNK:';
 
+       /**
+        * Identifier for end-of-package marker
+        */
+       const END_OF_PACKAGE_IDENTIFIER = 'EOP:';
+
        /**
         * Protected constructor
         *
@@ -101,12 +118,6 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                // Get new instance
                $fragmenterInstance = new PackageFragmenter();
 
-               // Get an output stream for all out-going packages
-               $streamInstance = ObjectFactory::createObjectByConfiguredName('node_raw_package_output_stream');
-
-               // And set it in this fragmenter
-               $fragmenterInstance->setOutputStreamInstance($streamInstance);
-
                // And also a crypto instance (for our encrypted messages)
                $cryptoInstance = ObjectFactory::createObjectByConfiguredName('crypto_class');
                $fragmenterInstance->setCryptoInstance($cryptoInstance);
@@ -287,16 +298,39 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                return $encodedSerialNumber;
        }
 
+       /**
+        * Appends an end-of-package chunk to the chunk list for given chunk and
+        * final hash.
+        *
+        * @param       $chunkHash      Last chunk's hash
+        * @param       $finalHash      Final hash for raw (unencoded) data
+        * @return      void
+        */
+       private function appendEndOfPackageChunk ($chunkHash, $finalHash) {
+               // Generate end-of-package marker
+               $rawData =
+                       self::END_OF_PACKAGE_IDENTIFIER .
+                       $finalHash . self::CHUNK_HASH_SEPERATOR .
+                       $chunkHash . self::CHUNK_SEPERATOR;
+
+               // Also get a hash from it
+               $chunkHash = $this->generateHashFromRawData($rawData);
+
+               // Append it to the chunk's data and hash array
+               $this->chunkHashes[$finalHash][] = $chunkHash;
+               $this->chunks[$finalHash][]      = $rawData;
+       }
+
        /**
         * Splits the given encoded data into smaller chunks, the size of the final
         * and the seperator is being subtracted from chunk size to fit it into a
         * TCP package (512 bytes).
         *
-        * @param       $encodedData    Encoded data string
-        * @param       $finalHash              Final hash from the raw data
+        * @param       $rawData        Raw data string
+        * @param       $finalHash      Final hash from the raw data
         * @return      void
         */
-       private function splitEncodedDataIntoChunks ($encodedData, $finalHash) {
+       private function splitEncodedDataIntoChunks ($rawData, $finalHash) {
                // Make sure final hashes with at least 32 bytes can pass
                assert(strlen($finalHash) >= 32);
 
@@ -304,17 +338,24 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                $dataChunkSize = $this->getDataChunkSizeFromHash($finalHash);
                //* NOISY-DEBUG: */ $this->debugOutput('FRAGMENTER: dataChunkSize=' . $dataChunkSize);
 
+               // Init variables
+               $chunkHash = '';
+
                // Now split it up
-               for ($idx = 0; $idx < strlen($encodedData); $idx += $dataChunkSize) {
+               for ($idx = 0; $idx < strlen($rawData); $idx += $dataChunkSize) {
                        // Get the next chunk
-                       $chunk = substr($encodedData, $idx, $dataChunkSize);
+                       $chunk = substr($rawData, $idx, $dataChunkSize);
 
                        // Hash it and remember it in seperate array
                        $chunkHash = $this->getCryptoInstance()->hashString($chunk);
                        $this->chunkHashes[$finalHash][] = $chunkHash;
 
                        // Prepend the hash to the chunk
-                       $chunk = $chunkHash . self::CHUNK_DATA_HASH_SEPERATOR . $this->getNextHexSerialNumber() . self::CHUNK_DATA_HASH_SEPERATOR . $chunk;
+                       $chunk =
+                               $chunkHash . self::CHUNK_DATA_HASH_SEPERATOR .
+                               $this->getNextHexSerialNumber() . self::CHUNK_DATA_HASH_SEPERATOR .
+                               $chunk . self::CHUNK_SEPERATOR
+                       ;
 
                        // Make sure the chunk is not larger than a TCP package can hold
                        assert(strlen($chunk) <= NetworkPackage::TCP_PACKAGE_SIZE);
@@ -325,40 +366,44 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                } // END - for
 
                // Debug output
-               $this->debugOutput('FRAGMENTER: Encoded data of ' . strlen($encodedData) . ' bytes has been fragmented into ' . count($this->chunks[$finalHash]) . ' chunk(s).');
+               //* 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);
        }
 
        /**
         * Prepends a chunk (or more) with all hashes from all chunks + final chunk.
         *
-        * @param       $encodedData    Encoded data string
-        * @param       $finalHash              Final hash from the raw data
+        * @param       $rawData        Raw data string
+        * @param       $finalHash      Final hash from the raw data
         * @return      void
         */
-       private function prependHashChunk ($encodedData, $finalHash) {
+       private function prependHashChunk ($rawData, $finalHash) {
                // "Implode" the whole array of hashes into one string
                $rawData = self::HASH_CHUNK_IDENTIFIER . implode(self::CHUNK_HASH_SEPERATOR, $this->chunkHashes[$finalHash]);
 
                // Also get a hash from it
                $chunkHash = $this->generateHashFromRawData($rawData);
 
-               // Also encode this one
-               $encodedData = $this->getOutputStreamInstance()->streamData($rawData);
-
                // Calulcate chunk size
                $dataChunkSize = $this->getDataChunkSizeFromHash($chunkHash);
 
                // Now array_unshift() it to the two chunk arrays
-               for ($idx = 0; $idx < strlen($encodedData); $idx += $dataChunkSize) {
+               for ($idx = 0; $idx < strlen($rawData); $idx += $dataChunkSize) {
                        // Get the next chunk
-                       $chunk = substr($encodedData, $idx, $dataChunkSize);
+                       $chunk = substr($rawData, $idx, $dataChunkSize);
 
                        // Hash it and remember it in seperate array
                        $chunkHash = $this->getCryptoInstance()->hashString($chunk);
                        array_unshift($this->chunkHashes[$finalHash], $chunkHash);
 
                        // Prepend the hash to the chunk
-                       $chunk = $chunkHash . self::CHUNK_DATA_HASH_SEPERATOR . $this->getNextHexSerialNumber() . self::CHUNK_DATA_HASH_SEPERATOR . $chunk;
+                       $chunk =
+                               $chunkHash . self::CHUNK_DATA_HASH_SEPERATOR .
+                               $this->getNextHexSerialNumber() . self::CHUNK_DATA_HASH_SEPERATOR .
+                               $chunk . self::CHUNK_SEPERATOR
+                       ;
 
                        // Make sure the chunk is not larger than a TCP package can hold
                        assert(strlen($chunk) <= NetworkPackage::TCP_PACKAGE_SIZE);
@@ -395,14 +440,11 @@ class PackageFragmenter extends BaseFrameworkSystem implements Fragmentable, Reg
                        // Init pointer
                        $this->initPointer($finalHash);
 
-                       // Encode the package for delivery
-                       $encodedData = $this->getOutputStreamInstance()->streamData($rawData);
-
                        // Split the encoded data into smaller chunks
-                       $this->splitEncodedDataIntoChunks($encodedData, $finalHash);
+                       $this->splitEncodedDataIntoChunks($rawData, $finalHash);
 
                        // Prepend a chunk with all hashes together
-                       $this->prependHashChunk($encodedData, $finalHash);
+                       $this->prependHashChunk($rawData, $finalHash);
 
                        // Mark the package as fragmented
                        $this->markPackageDataProcessed($packageData);