]> git.mxchange.org Git - hub.git/blobdiff - application/hub/main/package/class_NetworkPackage.php
Some comments improved
[hub.git] / application / hub / main / package / class_NetworkPackage.php
index e099f688c1ee781451f510fa61d94a727a0729c5..5ca1f31a81c23a14c0f35395f8eff5043b780638 100644 (file)
@@ -52,7 +52,13 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
        const PACKAGE_MASK_SEPARATOR = '^';
 
        /**
-        * SEPARATOR for checksum
+        * Size of an array created by invoking
+        * explode(NetworkPackage::PACKAGE_MASK_SEPARATOR, $content).
+        */
+       const PACKAGE_CONTENT_ARRAY_SIZE = 4;
+
+       /**
+        * Separator for checksum
         */
        const PACKAGE_CHECKSUM_SEPARATOR = '_';
 
@@ -73,6 +79,19 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
        const INDEX_PACKAGE_STATUS    = 3;
        const INDEX_PACKAGE_SIGNATURE = 4;
 
+       /**
+        * Size of the decoded data array ('status' is not included)
+        */
+       const DECODED_DATA_ARRAY_SIZE = 4;
+
+       /**
+        * Named array elements for decoded package content
+        */
+       const PACKAGE_CONTENT_EXTENSION = 'compressor';
+       const PACKAGE_CONTENT_MESSAGE   = 'message';
+       const PACKAGE_CONTENT_TAGS      = 'tags';
+       const PACKAGE_CONTENT_CHECKSUM  = 'checksum';
+
        /**
         * Named array elements for package data
         */
@@ -114,11 +133,6 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
         */
        const TCP_PACKAGE_SIZE = 512;
 
-       /**
-        * Size of the decoded data array
-        */
-       const DECODED_DATA_ARRAY_SIZE = 4;
-
        /**************************************************************************
         *                    Stacker for out-going packages                      *
         **************************************************************************/
@@ -157,6 +171,11 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
         */
        const STACKER_NAME_DECODED_CHUNKED = 'package_chunked_decoded';
 
+       /**
+        * Stacker name for new messages
+        */
+       const STACKER_NAME_NEW_MESSAGE = 'package_new_message';
+
        /**************************************************************************
         *                   Stacker for other/internal purposes                  *
         **************************************************************************/
@@ -236,6 +255,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                                self::STACKER_NAME_DECODED_INCOMING,
                                self::STACKER_NAME_DECODED_HANDLED,
                                self::STACKER_NAME_DECODED_CHUNKED,
+                               self::STACKER_NAME_NEW_MESSAGE,
                                self::STACKER_NAME_BACK_BUFFER
                        ) as $stackerName) {
                                // Init this stacker
@@ -244,14 +264,15 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
        }
 
        /**
-        * "Getter" for hash from given content and helper instance
+        * "Getter" for hash from given content
         *
-        * @param       $content                        Raw package content
-        * @param       $helperInstance         An instance of a HelpableHub class
-        * @param       $nodeInstance           An instance of a NodeHelper class
-        * @return      $hash                           Hash for given package content
+        * @param       $content        Raw package content
+        * @return      $hash           Hash for given package content
         */
        private function getHashFromContent ($content) {
+               // Debug message
+               //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: content[md5]=' . md5($content) . ',sender=' . $this->getSessionId() . ',compressor=' . $this->getCompressorInstance()->getCompressorExtension());
+
                // Create the hash
                // @TODO crc32() is very weak, but it needs to be fast
                $hash = crc32(
@@ -266,6 +287,24 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                return $hash;
        }
 
+       /**
+        * Checks whether the checksum (sometimes called "hash") is the same
+        *
+        * @param       $decodedContent         Package raw content
+        * @param       $decodedData            Whole raw package data array
+        * @return      $isChecksumValid        Whether the checksum is the same
+        */
+       private function isChecksumValid (array $decodedContent, array $decodedData) {
+               // Get checksum
+               $checksum = $this->getHashFromContentSessionId($decodedContent, $decodedData[self::PACKAGE_DATA_SENDER]);
+
+               // Is it the same?
+               $isChecksumValid = ($checksum == $decodedContent[self::PACKAGE_CONTENT_CHECKSUM]);
+
+               // Return it
+               return $isChecksumValid;
+       }
+
        /**
         * Change the package with given status in given stack
         *
@@ -284,7 +323,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                // Pop the entry (it should be it)
                $nextData = $this->getStackerInstance()->popNamed($stackerName);
 
-               // Compare both arrays
+               // Compare both signatures
                assert($nextData[self::PACKAGE_DATA_SIGNATURE] == $packageData[self::PACKAGE_DATA_SIGNATURE]);
 
                // Temporary set the new status
@@ -294,6 +333,31 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                $this->getStackerInstance()->pushNamed($stackerName, $packageData);
        }
 
+       /**
+        * "Getter" for hash from given content and sender's session id
+        *
+        * @param       $decodedContent         Decoded package content
+        * @param       $sessionId                      Session id of the sender
+        * @return      $hash                           Hash for given package content
+        */
+       public function getHashFromContentSessionId (array $decodedContent, $sessionId) {
+               // Debug message
+               //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: content[md5]=' . md5($decodedContent[self::PACKAGE_CONTENT_MESSAGE]) . ',sender=' . $sessionId . ',compressor=' . $decodedContent[self::PACKAGE_CONTENT_EXTENSION]);
+
+               // Create the hash
+               // @TODO crc32() is very weak, but it needs to be fast
+               $hash = crc32(
+                       $decodedContent[self::PACKAGE_CONTENT_MESSAGE] .
+                       self::PACKAGE_CHECKSUM_SEPARATOR .
+                       $sessionId .
+                       self::PACKAGE_CHECKSUM_SEPARATOR .
+                       $decodedContent[self::PACKAGE_CONTENT_EXTENSION]
+               );
+
+               // And return it
+               return $hash;
+       }
+
        ///////////////////////////////////////////////////////////////////////////
        //                   Delivering packages / raw data
        ///////////////////////////////////////////////////////////////////////////
@@ -467,9 +531,27 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                return $signature;
        }
 
+       /**
+        * Checks whether the signature of given package data is 'valid', here that
+        * means it is the same or not.
+        *
+        * @param       $decodedArray           An array with 'decoded' (explode() was mostly called) data
+        * @return      $isSignatureValid       Whether the signature is valid
+        * @todo        Unfinished area, signatures are currently NOT fully supported
+        */
+       private function isPackageSignatureValid (array $decodedArray) {
+               // Generate the signature of comparing it
+               $signature = $this->generatePackageSignature($decodedArray[self::INDEX_PACKAGE_CONTENT], $decodedArray[self::INDEX_PACKAGE_SENDER]);
+
+               // Is it the same?
+               //$isSignatureValid = 
+               die(__METHOD__.': signature='.$signature.chr(10).',decodedArray='.print_r($decodedArray,true));
+       }
+
        /**
         * "Enqueues" raw content into this delivery class by reading the raw content
-        * from given template instance and pushing it on the 'undeclared' stack.
+        * from given helper's template instance and pushing it on the 'undeclared'
+        * stack.
         *
         * @param       $helperInstance         An instance of a HelpableHub class
         * @return      void
@@ -566,8 +648,10 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                        return;
                } // END - if
 
-               // Now we know for sure there are packages to deliver, we can start
-               // with the first one.
+               /*
+                * Now there are for sure packages to deliver, so start with the first
+                * one.
+                */
                $packageData = $this->getStackerInstance()->getNamed(self::STACKER_NAME_UNDECLARED);
 
                // Declare the raw package data for delivery
@@ -807,15 +891,6 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                $this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECODED_CHUNKED, $packageContent);
        }
 
-       /**
-        * Checks whether a new package has arrived
-        *
-        * @return      $hasArrived             Whether a new package has arrived for processing
-        */
-       public function isNewPackageArrived () {
-               // @TODO Add some content here
-       }
-
        /**
         * Accepts the visitor to process the visit "request"
         *
@@ -881,18 +956,101 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R
                // Assert on count (should be always 3)
                assert(count($decodedArray) == self::DECODED_DATA_ARRAY_SIZE);
 
-               // Create 'decodedData' array with all assoziative array elements
+               // Generate the signature of comparing it
+               /*
+                * @todo Unsupported feature of "signed" messages commented out
+               if (!$this->isPackageSignatureValid($decodedArray)) {
+                       // Is not valid, so throw an exception here
+                       die('INVALID SIG! UNDER CONSTRUCTION!' . chr(10));
+               } // END - if
+               */
+
+               /*
+                * Create 'decodedData' array with all assoziative array elements,
+                * except signature.
+                */
                $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])
+                       self::PACKAGE_DATA_STATUS    => self::PACKAGE_STATUS_DECODED
                );
 
                // And return it
                return $decodedData;
        }
+
+       /**
+        * Handles decoded data for this node by "decoding" the 'content' part of
+        * it. Again this method uses explode() for the "decoding" process.
+        *
+        * @param       $decodedData    An array with decoded raw package data
+        * @return      void
+        * @throws      InvalidDataChecksumException    If the checksum doesn't match
+        */
+       public function handleDecodedData (array $decodedData) {
+               /*
+                * "Decode" the package's content by a simple explode() call, for
+                * details of the array elements, see comments for constant
+                * PACKAGE_MASK.
+                */
+               $decodedContent = explode(self::PACKAGE_MASK_SEPARATOR, $decodedData[self::PACKAGE_DATA_CONTENT]);
+
+               // Assert on array count for a very basic validation
+               assert(count($decodedContent) == self::PACKAGE_CONTENT_ARRAY_SIZE);
+
+               // Convert the indexed array into an associative array
+               $decodedContent = array(
+                       // Compressor's extension used to compress the data
+                       self::PACKAGE_CONTENT_EXTENSION => $decodedContent[self::INDEX_COMPRESSOR_EXTENSION],
+                       // Package data (aka "message") in BASE64-decoded form
+                       self::PACKAGE_CONTENT_MESSAGE   => base64_decode($decodedContent[self::INDEX_PACKAGE_DATA]),
+                       // Tags as an indexed array for "tagging" the message
+                       self::PACKAGE_CONTENT_TAGS      => explode(self::PACKAGE_TAGS_SEPARATOR, $decodedContent[self::INDEX_TAGS]),
+                       // Checksum of the _decoded_ data
+                       self::PACKAGE_CONTENT_CHECKSUM  => $decodedContent[self::INDEX_CHECKSUM]
+               );
+
+               // Is the checksum valid?
+               if (!$this->isChecksumValid($decodedContent, $decodedData)) {
+                       // Is not the same, so throw an exception here
+                       throw new InvalidDataChecksumException(array($this, $decodedContent, $decodedData), BaseListener::EXCEPTION_INVALID_DATA_CHECKSUM);
+               } // END - if
+
+               /*
+                * It is the same, then decompress it, the original message is than
+                * fully decoded.
+                */
+               $decodedContent[self::PACKAGE_CONTENT_MESSAGE] = $this->getCompressorInstance()->decompressStream($decodedContent[self::PACKAGE_CONTENT_MESSAGE]);
+
+               // And push it on the next stack
+               $this->getStackerInstance()->pushNamed(self::STACKER_NAME_NEW_MESSAGE, $decodedContent);
+       }
+
+       /**
+        * Checks whether a new message has arrived
+        *
+        * @return      $hasArrived             Whether a new message has arrived for processing
+        */
+       public function isNewMessageArrived () {
+               // Determine if the stack is not empty
+               $hasArrived = (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_NEW_MESSAGE));
+
+               // Return it
+               return $hasArrived;
+       }
+
+       /**
+        * Handles newly arrived messages
+        *
+        * @return      void
+        */
+       public function handleNewlyArrivedMessage () {
+               // Get it from the stacker, it is the full array with the decoded message
+               $decodedContent = $this->getStackerInstance()->popNamed(self::STACKER_NAME_NEW_MESSAGE);
+
+               die('decodedContent='.print_r($decodedContent,true));
+       }
 }
 
 // [EOF]