X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=application%2Fhub%2Fmain%2Fpackage%2Fclass_NetworkPackage.php;h=4561e08e22fa0708690fb77922f3e5e22c94388a;hb=f440f321cebdbaae3ffd88a47e4a70f13dae22b8;hp=fad98f9d25609197c68ebb9c2d13df69ce8aac01;hpb=e42e5cccbe065c9f54478350c9b96f408c648a9e;p=hub.git diff --git a/application/hub/main/package/class_NetworkPackage.php b/application/hub/main/package/class_NetworkPackage.php index fad98f9d2..4561e08e2 100644 --- a/application/hub/main/package/class_NetworkPackage.php +++ b/application/hub/main/package/class_NetworkPackage.php @@ -15,11 +15,11 @@ * For performance reasons, this class should only be instanciated once and then * used as a "pipe-through" class. * - * @author Roland Haeder + * @author Roland Haeder * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2012 Hub Developer Team + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2014 Hub Developer Team * @license GNU GPL 3.0 or any newer version - * @link http://www.ship-simu.org + * @link http://www.shipsimu.org * @todo Needs to add functionality for handling the object's type * * This program is free software: you can redistribute it and/or modify @@ -107,6 +107,17 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R const PACKAGE_STATUS_NEW = 'new'; const PACKAGE_STATUS_FAILED = 'failed'; const PACKAGE_STATUS_DECODED = 'decoded'; + const PACKAGE_STATUS_FAKED = 'faked'; + + /** + * Constants for message data array + */ + const MESSAGE_ARRAY_DATA = 'message_data'; + const MESSAGE_ARRAY_TYPE = 'message_type'; + + /** + * Generic answer status field + */ /** * Tags separator @@ -119,15 +130,25 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R const PACKAGE_DATA_SEPARATOR = '#'; /** - * Network target (alias): 'upper hubs' + * Separator for more than one recipient + */ + const PACKAGE_RECIPIENT_SEPARATOR = ':'; + + /** + * Network target (alias): 'upper nodes' */ - const NETWORK_TARGET_UPPER_HUBS = 'upper'; + const NETWORK_TARGET_UPPER = 'upper'; /** * Network target (alias): 'self' */ const NETWORK_TARGET_SELF = 'self'; + /** + * Network target (alias): 'dht' + */ + const NETWORK_TARGET_DHT = 'dht'; + /** * TCP package size in bytes */ @@ -186,13 +207,49 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R const STACKER_NAME_PROCESSED_MESSAGE = 'package_processed_message'; /************************************************************************** - * Stacker for other/internal purposes * + * Stacker for raw data handling * **************************************************************************/ /** - * Stacker name for "back-buffered" packages + * Stacker for outgoing data stream + */ + const STACKER_NAME_OUTGOING_STREAM = 'outgoing_stream'; + + /** + * Array index for final hash */ - const STACKER_NAME_BACK_BUFFER = 'package_backbuffer'; + const RAW_FINAL_HASH_INDEX = 'hash'; + + /** + * Array index for encoded data + */ + const RAW_ENCODED_DATA_INDEX = 'data'; + + /** + * Array index for sent bytes + */ + const RAW_SENT_BYTES_INDEX = 'sent'; + + /** + * Array index for socket resource + */ + const RAW_SOCKET_INDEX = 'socket'; + + /** + * Array index for buffer size + */ + const RAW_BUFFER_SIZE_INDEX = 'buffer'; + + /** + * Array index for diff between buffer and sent bytes + */ + const RAW_DIFF_INDEX = 'diff'; + + /************************************************************************** + * Protocol names * + **************************************************************************/ + const PROTOCOL_TCP = 'TCP'; + const PROTOCOL_UDP = 'UDP'; /** * Protected constructor @@ -222,25 +279,23 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * which have no recipient address and stamp... ;-) This stacker will * also be used for incoming raw data to handle it. */ - $stackerInstance = ObjectFactory::createObjectByConfiguredName('network_package_stacker_class'); + $stackInstance = ObjectFactory::createObjectByConfiguredName('network_package_stacker_class'); // At last, set it in this class - $packageInstance->setStackerInstance($stackerInstance); + $packageInstance->setStackInstance($stackInstance); // Init all stacker - $packageInstance->initStackers(); + $packageInstance->initStacks(); - // Get a visitor instance for speeding up things + // Get a visitor instance for speeding up things and set it $visitorInstance = ObjectFactory::createObjectByConfiguredName('node_raw_data_monitor_visitor_class', array($packageInstance)); - - // Set it in this package $packageInstance->setVisitorInstance($visitorInstance); - // Get crypto instance and set it in this package + // Get crypto instance and set it, too $cryptoInstance = ObjectFactory::createObjectByConfiguredName('crypto_class'); $packageInstance->setCryptoInstance($cryptoInstance); - // Get a singleton package assembler instance from factory and set it here + // Get a singleton package assembler instance from factory and set it here, too $assemblerInstance = PackageAssemblerFactory::createAssemblerInstance($packageInstance); $packageInstance->setAssemblerInstance($assemblerInstance); @@ -254,23 +309,19 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @param $forceReInit Whether to force reinitialization of all stacks * @return void */ - protected function initStackers ($forceReInit = false) { + protected function initStacks ($forceReInit = FALSE) { // Initialize all - foreach ( - array( - self::STACKER_NAME_UNDECLARED, - self::STACKER_NAME_DECLARED, - self::STACKER_NAME_OUTGOING, - self::STACKER_NAME_DECODED_INCOMING, - self::STACKER_NAME_DECODED_HANDLED, - self::STACKER_NAME_DECODED_CHUNKED, - self::STACKER_NAME_NEW_MESSAGE, - self::STACKER_NAME_PROCESSED_MESSAGE, - self::STACKER_NAME_BACK_BUFFER - ) as $stackerName) { - // Init this stacker - $this->getStackerInstance()->initStacker($stackerName, $forceReInit); - } // END - foreach + $this->getStackInstance()->initStacks(array( + self::STACKER_NAME_UNDECLARED, + self::STACKER_NAME_DECLARED, + self::STACKER_NAME_OUTGOING, + self::STACKER_NAME_DECODED_INCOMING, + self::STACKER_NAME_DECODED_HANDLED, + self::STACKER_NAME_DECODED_CHUNKED, + self::STACKER_NAME_NEW_MESSAGE, + self::STACKER_NAME_PROCESSED_MESSAGE, + self::STACKER_NAME_OUTGOING_STREAM + ), $forceReInit); } /** @@ -281,11 +332,11 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ private function getHashFromContent ($content) { // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: content[md5]=' . md5($content) . ',sender=' . $this->getSessionId() . ',compressor=' . $this->getCompressorInstance()->getCompressorExtension()); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: 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( + // @TODO md5() is very weak, but it needs to be fast + $hash = md5( $content . self::PACKAGE_CHECKSUM_SEPARATOR . $this->getSessionId() . @@ -293,6 +344,9 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $this->getCompressorInstance()->getCompressorExtension() ); + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: content[md5]=' . md5($content) . ',sender=' . $this->getSessionId() . ',hash=' . $hash . ',compressor=' . $this->getCompressorInstance()->getCompressorExtension()); + // And return it return $hash; } @@ -325,13 +379,13 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ private function changePackageStatus (array $packageData, $stackerName, $newStatus) { // Skip this for empty stacks - if ($this->getStackerInstance()->isStackEmpty($stackerName)) { + if ($this->getStackInstance()->isStackEmpty($stackerName)) { // This avoids an exception after all packages has failed return; } // END - if // Pop the entry (it should be it) - $nextData = $this->getStackerInstance()->popNamed($stackerName); + $nextData = $this->getStackInstance()->popNamed($stackerName); // Compare both signatures assert($nextData[self::PACKAGE_DATA_SIGNATURE] == $packageData[self::PACKAGE_DATA_SIGNATURE]); @@ -340,23 +394,23 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $packageData[self::PACKAGE_DATA_STATUS] = $newStatus; // And push it again - $this->getStackerInstance()->pushNamed($stackerName, $packageData); + $this->getStackInstance()->pushNamed($stackerName, $packageData); } /** * "Getter" for hash from given content and sender's session id * - * @param $decodedContent Decoded package content + * @param $decodedContent Raw 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]); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: 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( + // @TODO md5() is very weak, but it needs to be fast + $hash = md5( $decodedContent[self::PACKAGE_CONTENT_MESSAGE] . self::PACKAGE_CHECKSUM_SEPARATOR . $sessionId . @@ -373,12 +427,15 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R /////////////////////////////////////////////////////////////////////////// /** - * Delivers the given raw package data. + * Declares the given raw package data by discovering recipients * * @param $packageData Raw package data in an array * @return void */ private function declareRawPackageData (array $packageData) { + // Make sure the required field is there + assert(isset($packageData[self::PACKAGE_DATA_RECIPIENT])); + /* * We need to disover every recipient, just in case we have a * multi-recipient entry like 'upper' is. 'all' may be a not so good @@ -393,6 +450,9 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R // Now get an iterator $iteratorInstance = $discoveryInstance->getIterator(); + // Make sure the iterator instance is valid + assert($iteratorInstance instanceof Iterator); + // Rewind back to the beginning $iteratorInstance->rewind(); @@ -401,14 +461,17 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R // Get current entry $currentRecipient = $iteratorInstance->current(); + // Debug message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Setting recipient to ' . $currentRecipient . ',previous=' . $packageData[self::PACKAGE_DATA_RECIPIENT]); + // Set the recipient $packageData[self::PACKAGE_DATA_RECIPIENT] = $currentRecipient; - // And enqueue it to the writer class - $this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECLARED, $packageData); + // Push the declared package to the next stack. + $this->getStackInstance()->pushNamed(self::STACKER_NAME_DECLARED, $packageData); // Debug message - $this->debugOutput('PACKAGE: Package declared for recipient ' . $currentRecipient); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Package declared for recipient ' . $currentRecipient); // Skip to next entry $iteratorInstance->next(); @@ -447,50 +510,59 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $discoveryInstance = SocketDiscoveryFactory::createSocketDiscoveryInstance(); // Now discover the right protocol - $socketResource = $discoveryInstance->discoverSocket($packageData); + $socketResource = $discoveryInstance->discoverSocket($packageData, BaseConnectionHelper::CONNECTION_TYPE_OUTGOING); + + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Reached line ' . __LINE__ . ' after discoverSocket() has been called.'); // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' after discoverSocket() has been called.'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: stateInstance=' . $helperInstance->getStateInstance()); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Reached line ' . __LINE__ . ' before isSocketRegistered() has been called.'); - // We have to put this socket in our registry, so get an instance - $registryInstance = SocketRegistry::createSocketRegistry(); + // The socket needs to be put in a special registry that can handle such data + $registryInstance = SocketRegistryFactory::createSocketRegistryInstance(); - // Get the listener from registry + // Get the connection helper from registry $helperInstance = Registry::getRegistry()->getInstance('connection'); - // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: stateInstance=' . $helperInstance->getStateInstance()); - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' before isSocketRegistered() has been called.'); + // And make sure it is valid + assert($helperInstance instanceof ConnectionHelper); + + // Get connection info class + $infoInstance = ConnectionInfoFactory::createConnectionInfoInstance(); + + // Will the info instance with connection helper data + $infoInstance->fillWithConnectionHelperInformation($helperInstance); // Is it not there? - if ((is_resource($socketResource)) && (!$registryInstance->isSocketRegistered($helperInstance, $socketResource))) { + if ((is_resource($socketResource)) && (!$registryInstance->isSocketRegistered($infoInstance, $socketResource))) { // Debug message - $this->debugOutput('PACKAGE: Registering socket ' . $socketResource . ' ...'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Registering socket ' . $socketResource . ' ...'); // Then register it - $registryInstance->registerSocket($helperInstance, $socketResource, $packageData); + $registryInstance->registerSocket($infoInstance, $socketResource, $packageData); } elseif (!$helperInstance->getStateInstance()->isPeerStateConnected()) { // Is not connected, then we cannot send - $this->debugOutput('PACKAGE: Unexpected peer state ' . $helperInstance->getStateInstance()->__toString() . ' detected.'); + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Unexpected peer state ' . $helperInstance->getStateInstance()->__toString() . ' detected.'); // Shutdown the socket $this->shutdownSocket($socketResource); } // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' after isSocketRegistered() has been called.'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Reached line ' . __LINE__ . ' after isSocketRegistered() has been called.'); // Make sure the connection is up $helperInstance->getStateInstance()->validatePeerStateConnected(); // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' after validatePeerStateConnected() has been called.'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Reached line ' . __LINE__ . ' after validatePeerStateConnected() has been called.'); // 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); + $this->getStackInstance()->pushNamed(self::STACKER_NAME_OUTGOING, $packageData); // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' after pushNamed() has been called.'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Reached line ' . __LINE__ . ' after pushNamed() has been called.'); } /** @@ -504,7 +576,10 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $sentBytes = 0; // Get the right connection instance - $helperInstance = SocketRegistry::createSocketRegistry()->getHandlerInstanceFromPackageData($packageData); + $helperInstance = SocketRegistryFactory::createSocketRegistryInstance()->getHandlerInstanceFromPackageData($packageData); + + // Test helper instance + assert($helperInstance instanceof ConnectionHelper); // Is this connection still alive? if ($helperInstance->isShuttedDown()) { @@ -514,10 +589,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R } // END - if // Sent out package data - $sentBytes = $helperInstance->sendRawPackageData($packageData); - - // Remember unsent raw bytes in back-buffer, if any - $this->storeUnsentBytesInBackBuffer($packageData, $sentBytes); + $helperInstance->sendRawPackageData($packageData); } /** @@ -528,8 +600,8 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @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, $this->getNodeId(), false)); + // Hash content and sender id together, use md5() as last algo + $hash = md5($this->getCryptoInstance()->hashString($senderId . $content, $this->getPrivateKey(), FALSE)); // Encrypt the content again with the hash as a key $encryptedContent = $this->getCryptoInstance()->encryptString($content, $hash); @@ -555,7 +627,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R // Is it the same? //$isSignatureValid = - die(__METHOD__.': signature='.$signature.chr(10).',decodedArray='.print_r($decodedArray,true)); + exit(__METHOD__ . ': signature=' . $signature . chr(10) . ',decodedArray=' . print_r($decodedArray, TRUE)); } /** @@ -563,18 +635,22 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * from given helper's template instance and pushing it on the 'undeclared' * stack. * - * @param $helperInstance An instance of a HelpableHub class + * @param $helperInstance An instance of a HubHelper class * @return void */ - public function enqueueRawDataFromTemplate (HelpableHub $helperInstance) { + public function enqueueRawDataFromTemplate (HubHelper $helperInstance) { + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': CALLED!'); + // Get the raw content ... $content = $helperInstance->getTemplateInstance()->getRawTemplateData(); + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('content(' . strlen($content) . ')=' . $content); // ... and compress it $content = $this->getCompressorInstance()->compressStream($content); // Add magic in front of it and hash behind it, including BASE64 encoding - $content = sprintf(self::PACKAGE_MASK, + $packageContent = sprintf(self::PACKAGE_MASK, // 1.) Compressor's extension $this->getCompressorInstance()->getCompressorExtension(), // - separator @@ -591,14 +667,20 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $this->getHashFromContent($content) ); + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': Enqueueing package for recipientType=' . $helperInstance->getRecipientType() . ' ...'); + // Now prepare the temporary array and push it on the 'undeclared' stack - $this->getStackerInstance()->pushNamed(self::STACKER_NAME_UNDECLARED, array( + $this->getStackInstance()->pushNamed(self::STACKER_NAME_UNDECLARED, array( self::PACKAGE_DATA_SENDER => $this->getSessionId(), self::PACKAGE_DATA_RECIPIENT => $helperInstance->getRecipientType(), - self::PACKAGE_DATA_CONTENT => $content, + self::PACKAGE_DATA_CONTENT => $packageContent, self::PACKAGE_DATA_STATUS => self::PACKAGE_STATUS_NEW, - self::PACKAGE_DATA_SIGNATURE => $this->generatePackageSignature($content, $this->getSessionId()) + self::PACKAGE_DATA_SIGNATURE => $this->generatePackageSignature($packageContent, $this->getSessionId()) )); + + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': EXIT!'); } /** @@ -608,7 +690,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function isPackageEnqueued () { // Check whether the stacker is not empty - $isEnqueued = (($this->getStackerInstance()->isStackInitialized(self::STACKER_NAME_UNDECLARED)) && (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_UNDECLARED))); + $isEnqueued = (($this->getStackInstance()->isStackInitialized(self::STACKER_NAME_UNDECLARED)) && (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_UNDECLARED))); // Return the result return $isEnqueued; @@ -621,7 +703,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function isPackageDeclared () { // Check whether the stacker is not empty - $isDeclared = (($this->getStackerInstance()->isStackInitialized(self::STACKER_NAME_DECLARED)) && (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_DECLARED))); + $isDeclared = (($this->getStackInstance()->isStackInitialized(self::STACKER_NAME_DECLARED)) && (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_DECLARED))); // Return the result return $isDeclared; @@ -634,12 +716,25 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function isPackageWaitingForDelivery () { // Check whether the stacker is not empty - $isWaitingDelivery = (($this->getStackerInstance()->isStackInitialized(self::STACKER_NAME_OUTGOING)) && (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_OUTGOING))); + $isWaitingDelivery = (($this->getStackInstance()->isStackInitialized(self::STACKER_NAME_OUTGOING)) && (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_OUTGOING))); // Return the result return $isWaitingDelivery; } + /** + * Checks whether encoded (raw) data is pending + * + * @return $isPending Whether encoded data is pending + */ + public function isEncodedDataPending () { + // Check whether the stacker is not empty + $isPending = (($this->getStackInstance()->isStackInitialized(self::STACKER_NAME_OUTGOING_STREAM)) && (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_OUTGOING_STREAM))); + + // Return the result + return $isPending; + } + /** * Delivers an enqueued package to the stated destination. If a non-session * id is provided, recipient resolver is being asked (and instanced once). @@ -651,10 +746,13 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @throws NoTargetException If no target can't be determined */ public function declareEnqueuedPackage () { + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': CALLED!'); + // Make sure this method isn't working if there is no package enqueued if (!$this->isPackageEnqueued()) { // This is not fatal but should be avoided - // @TODO Add some logging here + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: No raw package data waiting declaration, but ' . __METHOD__ . ' has been called!'); return; } // END - if @@ -662,13 +760,13 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * Now there are for sure packages to deliver, so start with the first * one. */ - $packageData = $this->getStackerInstance()->getNamed(self::STACKER_NAME_UNDECLARED); + $packageData = $this->getStackInstance()->popNamed(self::STACKER_NAME_UNDECLARED); // Declare the raw package data for delivery $this->declareRawPackageData($packageData); - // And remove it finally - $this->getStackerInstance()->popNamed(self::STACKER_NAME_UNDECLARED); + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': EXIT!'); } /** @@ -678,30 +776,40 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * * @return void */ - public function deliverDeclaredPackage () { + public function processDeclaredPackage () { + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': CALLED!'); + // Sanity check if we have packages declared if (!$this->isPackageDeclared()) { // This is not fatal but should be avoided - $this->debugOutput('PACKAGE: No package has been declared, but ' . __METHOD__ . ' has been called!'); + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: No package has been declared, but ' . __METHOD__ . ' has been called!'); return; } // END - if // Get the package - $packageData = $this->getStackerInstance()->getNamed(self::STACKER_NAME_DECLARED); + $packageData = $this->getStackInstance()->getNamed(self::STACKER_NAME_DECLARED); + + // Assert on it + assert(isset($packageData[self::PACKAGE_DATA_RECIPIENT])); + // Try to deliver the package try { // And try to send it $this->deliverRawPackageData($packageData); // And remove it finally - $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECLARED); + $this->getStackInstance()->popNamed(self::STACKER_NAME_DECLARED); } catch (InvalidStateException $e) { // The state is not excepected (shall be 'connected') - $this->debugOutput('PACKAGE: Caught ' . $e->__toString() . ',message=' . $e->getMessage()); + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Caught ' . $e->__toString() . ',message=' . $e->getMessage()); // Mark the package with status failed $this->changePackageStatus($packageData, self::STACKER_NAME_DECLARED, self::PACKAGE_STATUS_FAILED); } + + // Debug message + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': EXIT!'); } /** @@ -710,32 +818,108 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @return void */ public function sendWaitingPackage () { - // Send any waiting bytes in the back-buffer before sending a new package - $this->sendBackBufferBytes(); + // Debug message + /* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': CALLED!'); // Sanity check if we have packages waiting for delivery if (!$this->isPackageWaitingForDelivery()) { // This is not fatal but should be avoided - $this->debugOutput('PACKAGE: No package is waiting for delivery, but ' . __METHOD__ . ' was called.'); + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: No package is waiting for delivery, but ' . __METHOD__ . ' was called.'); return; } // END - if // Get the package - $packageData = $this->getStackerInstance()->getNamed(self::STACKER_NAME_OUTGOING); + $packageData = $this->getStackInstance()->getNamed(self::STACKER_NAME_OUTGOING); try { // Now try to send it $this->sendOutgoingRawPackageData($packageData); // And remove it finally - $this->getStackerInstance()->popNamed(self::STACKER_NAME_OUTGOING); + $this->getStackInstance()->popNamed(self::STACKER_NAME_OUTGOING); } catch (InvalidSocketException $e) { // Output exception message - $this->debugOutput('PACKAGE: Package was not delivered: ' . $e->getMessage()); + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Package was not delivered: ' . $e->getMessage()); // Mark package as failed $this->changePackageStatus($packageData, self::STACKER_NAME_OUTGOING, self::PACKAGE_STATUS_FAILED); } + + // Debug message + /* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': EXIT!'); + } + + /** + * Sends out encoded data to a socket + * + * @return void + */ + public function sendEncodedData () { + // Debug message + /* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': CALLED!'); + + // Make sure there is pending encoded data + assert($this->isEncodedDataPending()); + + // Pop current data from stack + $encodedDataArray = $this->getStackInstance()->popNamed(self::STACKER_NAME_OUTGOING_STREAM); + + // Init in this round sent bytes + $sentBytes = 0; + + // Assert on socket + assert(is_resource($encodedDataArray[self::RAW_SOCKET_INDEX])); + + // And deliver it + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: Sending out ' . strlen($encodedDataArray[self::RAW_ENCODED_DATA_INDEX]) . ' bytes,rawBufferSize=' . $encodedDataArray[self::RAW_BUFFER_SIZE_INDEX] . ',diff=' . $encodedDataArray[self::RAW_DIFF_INDEX]); + if ($encodedDataArray[self::RAW_DIFF_INDEX] >= 0) { + // Send all out (encodedData is smaller than or equal buffer size) + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: MD5=' . md5(substr($encodedDataArray[self::RAW_ENCODED_DATA_INDEX], 0, ($encodedDataArray[self::RAW_BUFFER_SIZE_INDEX] - $encodedDataArray[self::RAW_DIFF_INDEX])))); + $sentBytes = @socket_write($encodedDataArray[self::RAW_SOCKET_INDEX], $encodedDataArray[self::RAW_ENCODED_DATA_INDEX], ($encodedDataArray[self::RAW_BUFFER_SIZE_INDEX] - $encodedDataArray[self::RAW_DIFF_INDEX])); + } else { + // Send buffer size out + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: MD5=' . md5(substr($encodedDataArray[self::RAW_ENCODED_DATA_INDEX], 0, $encodedDataArray[self::RAW_BUFFER_SIZE_INDEX]))); + $sentBytes = @socket_write($encodedDataArray[self::RAW_SOCKET_INDEX], $encodedDataArray[self::RAW_ENCODED_DATA_INDEX], $encodedDataArray[self::RAW_BUFFER_SIZE_INDEX]); + } + + // If there was an error, we don't continue here + if ($sentBytes === FALSE) { + // Handle the error with a faked recipientData array + $this->handleSocketError(__METHOD__, __LINE__, $encodedDataArray[self::RAW_SOCKET_INDEX], array('0.0.0.0', '0')); + + // And throw it + throw new InvalidSocketException(array($this, $encodedDataArray[self::RAW_SOCKET_INDEX], $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + } elseif (($sentBytes === 0) && (strlen($encodedDataArray[self::RAW_ENCODED_DATA_INDEX]) > 0)) { + // Nothing sent means we are done + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: All sent! (LINE=' . __LINE__ . ')'); + return; + } else { + // The difference between sent bytes and length of raw data should not go below zero + assert((strlen($encodedDataArray[self::RAW_ENCODED_DATA_INDEX]) - $sentBytes) >= 0); + + // Add total sent bytes + $encodedDataArray[self::RAW_SENT_BYTES_INDEX] += $sentBytes; + + // Cut out the last unsent bytes + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: Sent out ' . $sentBytes . ' of ' . strlen($encodedDataArray[self::RAW_ENCODED_DATA_INDEX]) . ' bytes ...'); + $encodedDataArray[self::RAW_ENCODED_DATA_INDEX] = substr($encodedDataArray[self::RAW_ENCODED_DATA_INDEX], $sentBytes); + + // Calculate difference again + $encodedDataArray[self::RAW_DIFF_INDEX] = $encodedDataArray[self::RAW_BUFFER_SIZE_INDEX] - strlen($encodedDataArray[self::RAW_ENCODED_DATA_INDEX]); + + // Can we abort? + if (strlen($encodedDataArray[self::RAW_ENCODED_DATA_INDEX]) <= 0) { + // Abort here, all sent! + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: All sent! (LINE=' . __LINE__ . ')'); + return; + } // END - if + } + + // Push array back in stack + $this->getStackInstance()->pushNamed(self::STACKER_NAME_OUTGOING_STREAM, $encodedDataArray); + + // Debug message + /* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ': EXIT!'); } /////////////////////////////////////////////////////////////////////////// @@ -747,9 +931,9 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * * @return $isPending Whether decoded raw data is pending */ - private function isDecodedDataPending () { + private function isRawDataPending () { // Just return whether the stack is not empty - $isPending = (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_DECODED_INCOMING)); + $isPending = (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_DECODED_INCOMING)); // Return the status return $isPending; @@ -766,7 +950,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $poolInstance->accept($this->getVisitorInstance()); // Check for new data arrival - $hasArrived = $this->isDecodedDataPending(); + $hasArrived = $this->isRawDataPending(); // Return the status return $hasArrived; @@ -784,22 +968,22 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * This method should only be called if decoded raw data is pending, * so check it again. */ - if (!$this->isDecodedDataPending()) { + if (!$this->isRawDataPending()) { // This is not fatal but should be avoided - // @TODO Add some logging here + self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: No raw (decoded?) data is pending, but ' . __METHOD__ . ' has been called!'); return; } // END - if // Very noisy debug message: - /* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Stacker size is ' . $this->getStackerInstance()->getStackCount(self::STACKER_NAME_DECODED_INCOMING) . ' entries.'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Stacker size is ' . $this->getStackInstance()->getStackCount(self::STACKER_NAME_DECODED_INCOMING) . ' entries.'); // "Pop" the next entry (the same array again) from the stack - $decodedData = $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECODED_INCOMING); + $decodedData = $this->getStackInstance()->popNamed(self::STACKER_NAME_DECODED_INCOMING); // Make sure both array elements are there assert( (is_array($decodedData)) && - (isset($decodedData[BaseRawDataHandler::PACKAGE_DECODED_DATA])) && + (isset($decodedData[BaseRawDataHandler::PACKAGE_RAW_DATA])) && (isset($decodedData[BaseRawDataHandler::PACKAGE_ERROR_CODE])) ); @@ -807,17 +991,18 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * Also make sure the error code is SOCKET_ERROR_UNHANDLED because we * only want to handle unhandled packages here. */ - /* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: errorCode=' . $decodedData[BaseRawDataHandler::PACKAGE_ERROR_CODE]); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: errorCode=' . $decodedData[BaseRawDataHandler::PACKAGE_ERROR_CODE] . '(' . BaseRawDataHandler::SOCKET_ERROR_UNHANDLED . ')'); assert($decodedData[BaseRawDataHandler::PACKAGE_ERROR_CODE] == BaseRawDataHandler::SOCKET_ERROR_UNHANDLED); - // Remove the last chunk SEPARATOR (because it is being added and we don't need it) - if (substr($decodedData[BaseRawDataHandler::PACKAGE_DECODED_DATA], -1, 1) == PackageFragmenter::CHUNK_SEPARATOR) { + // Remove the last chunk SEPARATOR (because there is no need for it) + if (substr($decodedData[BaseRawDataHandler::PACKAGE_RAW_DATA], -1, 1) == PackageFragmenter::CHUNK_SEPARATOR) { // It is there and should be removed - $decodedData[BaseRawDataHandler::PACKAGE_DECODED_DATA] = substr($decodedData[BaseRawDataHandler::PACKAGE_DECODED_DATA], 0, -1); + $decodedData[BaseRawDataHandler::PACKAGE_RAW_DATA] = substr($decodedData[BaseRawDataHandler::PACKAGE_RAW_DATA], 0, -1); } // END - if // This package is "handled" and can be pushed on the next stack - $this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECODED_HANDLED, $decodedData); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Pushing ' . strlen($decodedData[BaseRawDataHandler::PACKAGE_RAW_DATA]) . ' bytes to stack ' . self::STACKER_NAME_DECODED_HANDLED . ' ...'); + $this->getStackInstance()->pushNamed(self::STACKER_NAME_DECODED_HANDLED, $decodedData); } /** @@ -826,18 +1011,18 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @param $handlerInstance An instance of a Networkable class * @return void */ - public function addDecodedDataToIncomingStack (Networkable $handlerInstance) { + public function addRawDataToIncomingStack (Networkable $handlerInstance) { /* * Get the decoded data from the handler, this is an array with - * 'decoded_data' and 'error_code' as elements. + * 'raw_data' and 'error_code' as elements. */ - $decodedData = $handlerInstance->getNextDecodedData(); + $decodedData = $handlerInstance->getNextRawData(); // Very noisy debug message: - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: decodedData[' . gettype($decodedData) . ']=' . print_r($decodedData, true)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: decodedData[' . gettype($decodedData) . ']=' . print_r($decodedData, TRUE)); // And push it on our stack - $this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECODED_INCOMING, $decodedData); + $this->getStackInstance()->pushNamed(self::STACKER_NAME_DECODED_INCOMING, $decodedData); } /** @@ -845,9 +1030,9 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * * @return $isHandled Whether incoming decoded data is handled */ - public function isIncomingDecodedDataHandled () { + public function isIncomingRawDataHandled () { // Determine if the stack is not empty - $isHandled = (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_DECODED_HANDLED)); + $isHandled = (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_DECODED_HANDLED)); // Return it return $isHandled; @@ -866,6 +1051,19 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R return $isHandled; } + /** + * Checks whether the assembler has multiple packages pending + * + * @return $isPending Whether the assembler has multiple packages pending + */ + public function ifMultipleMessagesPending () { + // Determine if the stack is not empty + $isPending = ($this->getAssemblerInstance()->ifMultipleMessagesPending()); + + // Return it + return $isPending; + } + /** * Handles the attached assemler's pending data queue to be finally * assembled to the raw package data back. @@ -877,6 +1075,16 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $this->getAssemblerInstance()->handlePendingData(); } + /** + * Handles multiple messages. + * + * @return void + */ + public function handleMultipleMessages () { + // Handle it + $this->getAssemblerInstance()->handleMultipleMessages(); + } + /** * Assembles incoming decoded data so it will become an abstract network * package again. The assembler does later do it's job by an other task, @@ -886,19 +1094,27 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function assembleDecodedDataToPackage () { // Make sure the raw decoded package data is handled - assert($this->isIncomingDecodedDataHandled()); + assert($this->isIncomingRawDataHandled()); // Get current package content (an array with two elements; see handleIncomingDecodedData() for details) - $packageContent = $this->getStackerInstance()->getNamed(self::STACKER_NAME_DECODED_HANDLED); + $packageContent = $this->getStackInstance()->getNamed(self::STACKER_NAME_DECODED_HANDLED); + + // Assert on some elements + assert( + (is_array($packageContent)) && + (isset($packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA])) && + (isset($packageContent[BaseRawDataHandler::PACKAGE_ERROR_CODE])) + ); // Start assembling the raw package data array by chunking it $this->getAssemblerInstance()->chunkPackageContent($packageContent); // Remove the package from 'handled_decoded' stack ... - $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECODED_HANDLED); + $this->getStackInstance()->popNamed(self::STACKER_NAME_DECODED_HANDLED); // ... and push it on the 'chunked' stacker - $this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECODED_CHUNKED, $packageContent); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: Pushing ' . strlen($packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA]) . ' bytes on stack ' . self::STACKER_NAME_DECODED_CHUNKED . ',packageContent=' . print_r($packageContent, TRUE)); + $this->getStackInstance()->pushNamed(self::STACKER_NAME_DECODED_CHUNKED, $packageContent); } /** @@ -909,26 +1125,29 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function accept (Visitor $visitorInstance) { // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: ' . $visitorInstance->__toString() . ' has visited - START'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: ' . $visitorInstance->__toString() . ' has visited - CALLED!'); // Visit the package $visitorInstance->visitNetworkPackage($this); + // Then visit the assembler to handle multiple packages + $this->getAssemblerInstance()->accept($visitorInstance); + // Debug message - //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: ' . $visitorInstance->__toString() . ' has visited - FINISHED'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: ' . $visitorInstance->__toString() . ' has visited - EXIT!'); } /** - * Clears all stacker + * Clears all stacks * * @return void */ - public function clearAllStacker () { + public function clearAllStacks () { // Call the init method to force re-initialization - $this->initStackers(true); + $this->initStacks(TRUE); // Debug message - /* DEBUG: */ $this->debugOutput('PACKAGE: All stacker have been re-initialized.'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: All stacker have been re-initialized.'); } /** @@ -941,7 +1160,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function removeFirstFailedPackage () { // Get the package again - $packageData = $this->getStackerInstance()->getNamed(self::STACKER_NAME_DECLARED); + $packageData = $this->getStackInstance()->getNamed(self::STACKER_NAME_DECLARED); // Is the package status 'failed'? if ($packageData[self::PACKAGE_DATA_STATUS] != self::PACKAGE_STATUS_FAILED) { @@ -950,7 +1169,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R } // END - if // Remove this entry - $this->getStackerInstance()->popNamed(self::STACKER_NAME_DECLARED); + $this->getStackInstance()->popNamed(self::STACKER_NAME_DECLARED); } /** @@ -971,7 +1190,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @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)); + exit(__METHOD__ . ':INVALID SIG! UNDER CONSTRUCTION!' . chr(10)); } // END - if */ @@ -998,7 +1217,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R * @return void * @throws InvalidDataChecksumException If the checksum doesn't match */ - public function handleDecodedData (array $decodedData) { + public function handleRawData (array $decodedData) { /* * "Decode" the package's content by a simple explode() call, for * details of the array elements, see comments for constant @@ -1037,7 +1256,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R $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); + $this->getStackInstance()->pushNamed(self::STACKER_NAME_NEW_MESSAGE, $decodedContent); } /** @@ -1047,7 +1266,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ public function isNewMessageArrived () { // Determine if the stack is not empty - $hasArrived = (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_NEW_MESSAGE)); + $hasArrived = (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_NEW_MESSAGE)); // Return it return $hasArrived; @@ -1061,7 +1280,7 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ 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); + $decodedContent = $this->getStackInstance()->popNamed(self::STACKER_NAME_NEW_MESSAGE); // Now get a filter chain back from factory with given tags array $chainInstance = PackageFilterChainFactory::createChainByTagsArray($decodedContent[self::PACKAGE_CONTENT_TAGS]); @@ -1072,6 +1291,41 @@ class NetworkPackage extends BaseHubSystem implements Deliverable, Receivable, R */ $chainInstance->processMessage($decodedContent[self::PACKAGE_CONTENT_MESSAGE], $this); } + + /** + * Checks whether a processed message is pending for "interpretation" + * + * @return $isPending Whether a processed message is pending + */ + public function isProcessedMessagePending () { + // Check it + $isPending = (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_PROCESSED_MESSAGE)); + + // Return it + return $isPending; + } + + /** + * Handle processed messages by "interpreting" the 'message_type' element + * + * @return void + */ + public function handleProcessedMessage () { + // Get it from the stacker, it is the full array with the processed message + $messageArray = $this->getStackInstance()->popNamed(self::STACKER_NAME_PROCESSED_MESSAGE); + + // Add type for later easier handling + $messageArray[self::MESSAGE_ARRAY_DATA][self::MESSAGE_ARRAY_TYPE] = $messageArray[self::MESSAGE_ARRAY_TYPE]; + + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('NETWORK-PACKAGE[' . __METHOD__ . ':' . __LINE__ . ']: messageArray=' . print_r($messageArray, TRUE)); + + // Create a handler instance from given message type + $handlerInstance = MessageTypeHandlerFactory::createMessageTypeHandlerInstance($messageArray[self::MESSAGE_ARRAY_TYPE]); + + // Handle message data + $handlerInstance->handleMessageData($messageArray[self::MESSAGE_ARRAY_DATA], $this); + } } // [EOF]