// CFG: STACKER-ANNOUNCEMENT-MAX-SIZE
$cfg->setConfigEntry('stacker_announcement_max_size', 20);
+// CFG: STACKER-ANNOUNCEMENT-ANSWER-MAX-SIZE
+$cfg->setConfigEntry('stacker_announcement_answer_max_size', 20);
+
// CFG: STACKER-SELF-CONNECT-MAX-SIZE
$cfg->setConfigEntry('stacker_self_connect_max_size', 10);
// CFG: EXTERNAL-IP
$cfg->setConfigEntry('external_ip', '');
+// CFG: INTERNAL-IP
+$cfg->setConfigEntry('internal_ip', ConsoleTools::acquireSelfIPAddress());
+
// CFG: NODE-STATUS
$cfg->setConfigEntry('node_status', 'invalid');
// CFG: PACKAGE-DECODER-CLASS
$cfg->setConfigEntry('package_decoder_class', 'PackageDecoder');
+// CFG: PACKAGE-RECIPIENT-MAX-COUNT
+// @TODO This is very static, rewrite it to more flexible
+$cfg->setConfigEntry('package_recipient_max_count', 3);
+
///////////////////////////////////////////////////////////////////////////////
// Peer states
///////////////////////////////////////////////////////////////////////////////
*/
public function __construct (array $messageArray, $code) {
// Construct the message
- $message = sprintf("[%s:%d] This node (%s) is not accepting announcements, but got one from session-id=%s,ip=%s,tcp.port=%s,udp.port=%s,status=%s.",
+ $message = sprintf("[%s:%d] This node (%s) is not accepting announcements, but got one from session-id=%s,ip=%s/%s,tcp.port=%s,udp.port=%s,status=%s.",
$messageArray[0]->__toString(),
$this->getLine(),
$messageArray[1]->__toString(),
$messageArray[2][XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_SESSION_ID],
$messageArray[2][XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_EXTERNAL_IP],
+ $messageArray[2][XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_INTERNAL_IP],
$messageArray[2][XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_TCP_PORT],
$messageArray[2][XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_UDP_PORT],
$messageArray[2][XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_NODE_STATUS]
const EXCEPTION_CHUNK_ALREADY_ASSEMBLED = 0x901;
const EXCEPTION_ANNOUNCEMENT_NOT_ACCEPTED = 0x902;
+ // Message status codes
+ const MESSAGE_STATUS_CODE_OKAY = 'OKAY';
+
/**
* Separator for all bootstrap node entries
*/
$this->debugBackTrace('Unsupported protocol ' . $protocol . ' specified!');
break;
} // END - switch
+
+ // Now put both together
+ $recipient = $recipientIp . ':' . $recipientPort;
+
+ // Debug message
+ $this->debugOutput('DATABASE-WRAPPER: sessionId[' . $protocol . ']=' . $sessionId . ' resolved as recipient=' . $recipient);
} // END - if
// Return result
// This may be a direct recipient (node's session id)
default:
- $this->partialStub('Please add code handling recipients ' . $packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]);
+ /*
+ * Try to solve it, if an exception comes back, it is not a
+ * session-id, nor IP:port and not a hostname:port combination.
+ */
+ try {
+ // "Explode" all recipients
+ $recipients = explode(NetworkPackage::PACKAGE_RECIPIENT_SEPARATOR, $packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]);
+
+ // Is maximum reached?
+ assert(count($recipients) <= $this->getConfigInstance()->getConfigEntry('package_recipient_max_count'));
+
+ // Try it on all
+ foreach ($recipients as $recipient) {
+ // Try to sole a single recipient
+ $ipPort = HubTools::resolveSessionId($recipient, $packageData[NetworkPackage::PACKAGE_DATA_PROTOCOL]);
+
+ // Add it as recipient
+ $this->getListInstance()->addEntry('ip_port', $ipPort);
+ } // END - foreach
+ } catch (FrameworkException $e) {
+ // Didn't work, pleace add more code
+ $this->partialStub('Please add code handling recipients ' . $packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT] . ',packageData=' . print_r($packageData, true) . ',exception=' . $e->__toString() . ',message=' . $e->getMessage());
+ }
break;
} // END - switch
}
throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
} // END - if
+ // Debug message
+ /* NOISY-DEBUG: */ $this->debugOutput('protocolName=' . $protocolName . ',packageData=' . print_r($packageData, true));
+
/*
* Now we have the listener instance, we can determine the right
* resource to continue. The first step is to get the attached pool
// Init array
$this->dataXmlNodes = array(
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_EXTERNAL_IP => '',
+ XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_INTERNAL_IP => '',
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_NODE_STATUS => '',
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_SESSION_ID => '',
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_TCP_PORT => 9060,
// Init message data array
$this->messageDataElements = array(
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_EXTERNAL_IP,
+ XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_INTERNAL_IP,
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_NODE_STATUS,
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_SESSION_ID,
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_TCP_PORT,
XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_UDP_PORT
);
+
+ // Init message-data->configuration translation array
+ $this->messageToConfig = array(
+ XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_EXTERNAL_IP => 'other_external_ip',
+ XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_INTERNAL_IP => 'other_internal_ip',
+ XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_SESSION_ID => 'other_session_id'
+ );
}
/**
$dataSetInstance->addCriteria('node_' . $key, $messageData[$key]);
} // END - foreach
}
+
+ /**
+ * Initializes configuration data from given message data array
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ */
+ protected function initMessageConfigurationData (array $messageData) {
+ // "Walk" throught the translation array
+ foreach ($this->messageToConfig as $messageKey => $configKey) {
+ // Set the element in configuration
+ $this->getConfigInstance()->setConfigEntry($configKey, $messageData[$messageKey]);
+ } // END - foreach
+
+ // Translate last exception into a status code
+ $statusCode = $this->getTranslatedStatusFromLastException();
+
+ // Set it in configuration (temporarily)
+ $this->getConfigInstance()->setConfigEntry('answer_status', $statusCode);
+ }
+
+ /**
+ * Removes configuration data with given message data array from global
+ * configuration
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ */
+ protected function removeMessageConfigurationData (array $messageData) {
+ // "Walk" throught the translation array again
+ foreach ($this->messageToConfig as $dummy => $configKey) {
+ // Now unset this configuration entry (to save some memory)
+ $this->getConfigInstance()->unsetConfigEntry($configKey);
+ } // END - foreach
+
+ // Remove 'answer_status' as well
+ $this->getConfigInstance()->unsetConfigEntry('answer_status');
+ }
}
// [EOF]
<?php
/**
- * A general message handler
+ * A general message handler, this class must be abstract to make the template
+ * method pattern working.
*
* @author Roland Haeder <webmaster@ship-simu.org>
* @version 0.0.0
* 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 BaseMessageHandler extends BaseHandler {
+abstract class BaseMessageHandler extends BaseHandler {
/**
* Array with search criteria elements
*/
*/
protected $messageDataElements = array();
+ /**
+ * Array for translating message data elements (other node's data mostly)
+ * into configuration elements.
+ */
+ protected $messageToConfig = array();
+
+ /**
+ * Last exception instance from database layer or NULL (default)
+ */
+ private $lastException = NULL;
+
/**
* Protected constructor
*
);
}
+ /**
+ * Getter for last exception
+ *
+ * @return $lastException Last thrown exception
+ */
+ protected final function getLastException () {
+ return $this->lastException;
+ }
+
+ /**
+ * "Getter" for a translated last exception as a status code
+ *
+ * @return $statusCode Translated status code from last exception
+ */
+ protected function getTranslatedStatusFromLastException () {
+ // Default is all fine
+ $statusCode = self::MESSAGE_STATUS_CODE_OKAY;
+
+ // Is the last exception not NULL?
+ if ($this->lastException instanceof FrameworkException) {
+ // "Determine" the right status code (may differ from exception to exception)
+ $this->debugInstance('lastException=' . $this->lastException->__toString() . ',message=' . $this->lastException->getMessage() . ' is not finished!');
+ } // END - if
+
+ // Return the status code
+ return $statusCode;
+ }
+
/**
* Registers an other node with this node by given message data. The
* following data must always be present:
// Nothing found, so register it
$wrapperInstance->registerNodeByMessageData($messageData, $this);
}
+
+ // Save last exception
+ $this->lastException = $wrapperInstance->getLastException();
}
/**
// Load descriptor XML
$helperInstance->loadDescriptorXml();
+ /*
+ * Set missing (temporary) configuration data, mostly it needs to be
+ * copied from message data array.
+ */
+ $this->initMessageConfigurationData($messageData);
+
// Compile any configuration variables
$helperInstance->getTemplateInstance()->compileConfigInVariables();
// Deliver the package
$helperInstance->sendPackage($nodeInstance);
+
+ /*
+ * Remove temporary configuration
+ */
+ $this->removeMessageConfigurationData($messageData);
}
+
+ /**
+ * Initializes configuration data from given message data array
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ */
+ abstract protected function initMessageConfigurationData (array $messageData);
+
+ /**
+ * Removes configuration data with given message data array from global
+ * configuration
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ */
+ abstract protected function removeMessageConfigurationData (array $messageData);
}
// [EOF]
// Please don't call this method!
throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
}
+
+ /**
+ * Initializes configuration data from given message data array
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ * @throws UnsupportedOperationException If this method is called
+ */
+ protected function initMessageConfigurationData (array $messageData) {
+ // Please don't call this method!
+ throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
+ }
+
+ /**
+ * Removes configuration data with given message data array from global configuration
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ * @throws UnsupportedOperationException If this method is called
+ */
+ protected function removeMessageConfigurationData (array $messageData) {
+ // Please don't call this method!
+ throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
+ }
}
// [EOF]
// Call parent constructor
parent::__construct(__CLASS__);
- // Set recipient type to 'other'
- $this->setRecipientType(NetworkPackage::NETWORK_TARGET_OTHER);
+ // Init package tags
+ $this->setPackageTags(array('announcement_answer'));
}
/**
// Get new instance
$helperInstance = new NodeAnnouncementMessageAnswerHelper();
+ // Set session id of other peer as recipient
+ $helperInstance->setRecipientType($messageData[XmlAnnouncementTemplateEngine::ANNOUNCEMENT_DATA_SESSION_ID]);
+
// Set message data
$helperInstance->setMessageData($messageData);
$packageInstance = NetworkPackageFactory::createNetworkPackageInstance();
// Next, feed the content in. The network package class is a pipe-through class.
- $packageInstance->enqueueRawDataFromTemplate($this);
+ $packageInstance->enqueueRawDataFromTemplate($this, 'TCP');
}
}
*/
private $messageData = array();
+ /**
+ * Package tags
+ */
+ private $packageTags = array();
+
+
/**
* Protected constructor
*
public final function getMessageData () {
return $this->messageData;
}
+
+ /**
+ * Getter for package tags in a simple array
+ *
+ * @return $packageTags An array with all tags for the currently handled package
+ */
+ public final function getPackageTags () {
+ return $this->packageTags;
+ }
+
+ /**
+ * Setter for package tags in a simple array
+ *
+ * @param $packageTags An array with all tags for the currently handled package
+ * @return void
+ */
+ public final function setPackageTags (array $packageTags) {
+ $this->packageTags = $packageTags;
+ }
}
// [EOF]
*/
const PACKAGE_DATA_SEPARATOR = '#';
+ /**
+ * Separator for more than one recipient
+ */
+ const PACKAGE_RECIPIENT_SEPARATOR = ':';
+
/**
* Network target (alias): 'upper hubs'
*/
*/
const NETWORK_TARGET_SELF = 'self';
- /**
- * Network target (alias): 'other'
- */
- const NETWORK_TARGET_OTHER = 'other';
-
/**
* TCP package size in bytes
*/
// Get current entry
$currentRecipient = $iteratorInstance->current();
+ // Debug message
+ $this->debugOutput('NETWORK-PACKAGE: Setting recipient to ' . $currentRecipient . ',previous=' . $packageData[self::PACKAGE_DATA_RECIPIENT]);
+
// Set the recipient
$packageData[self::PACKAGE_DATA_RECIPIENT] = $currentRecipient;
$this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECLARED, $packageData);
// Debug message
- $this->debugOutput('PACKAGE: Package declared for recipient ' . $currentRecipient);
+ $this->debugOutput('NETWORK-PACKAGE: Package declared for recipient ' . $currentRecipient);
// Skip to next entry
$iteratorInstance->next();
$socketResource = $discoveryInstance->discoverSocket($packageData);
// Debug message
- //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' after discoverSocket() has been called.');
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: Reached line ' . __LINE__ . ' after discoverSocket() has been called.');
// We have to put this socket in our registry, so get an instance
$registryInstance = SocketRegistry::createSocketRegistry();
$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.');
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: stateInstance=' . $helperInstance->getStateInstance());
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: Reached line ' . __LINE__ . ' before isSocketRegistered() has been called.');
// Is it not there?
if ((is_resource($socketResource)) && (!$registryInstance->isSocketRegistered($helperInstance, $socketResource))) {
// Debug message
- $this->debugOutput('PACKAGE: Registering socket ' . $socketResource . ' ...');
+ $this->debugOutput('NETWORK-PACKAGE: Registering socket ' . $socketResource . ' ...');
// Then register it
$registryInstance->registerSocket($helperInstance, $socketResource, $packageData);
} elseif (!$helperInstance->getStateInstance()->isPeerStateConnected()) {
// Is not connected, then we cannot send
- $this->debugOutput('PACKAGE: Unexpected peer state ' . $helperInstance->getStateInstance()->__toString() . ' detected.');
+ $this->debugOutput('NETWORK-PACKAGE: 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: */ $this->debugOutput('NETWORK-PACKAGE: 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: */ $this->debugOutput('NETWORK-PACKAGE: 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);
// Debug message
- //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: Reached line ' . __LINE__ . ' after pushNamed() has been called.');
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: Reached line ' . __LINE__ . ' after pushNamed() has been 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!');
+ $this->debugOutput('NETWORK-PACKAGE: No package has been declared, but ' . __METHOD__ . ' has been called!');
return;
} // END - if
$this->getStackerInstance()->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());
+ $this->debugOutput('NETWORK-PACKAGE: Caught ' . $e->__toString() . ',message=' . $e->getMessage());
// Mark the package with status failed
$this->changePackageStatus($packageData, self::STACKER_NAME_DECLARED, self::PACKAGE_STATUS_FAILED);
// 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.');
+ $this->debugOutput('NETWORK-PACKAGE: No package is waiting for delivery, but ' . __METHOD__ . ' was called.');
return;
} // END - if
$this->getStackerInstance()->popNamed(self::STACKER_NAME_OUTGOING);
} catch (InvalidSocketException $e) {
// Output exception message
- $this->debugOutput('PACKAGE: Package was not delivered: ' . $e->getMessage());
+ $this->debugOutput('NETWORK-PACKAGE: Package was not delivered: ' . $e->getMessage());
// Mark package as failed
$this->changePackageStatus($packageData, self::STACKER_NAME_OUTGOING, self::PACKAGE_STATUS_FAILED);
} // 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: */ $this->debugOutput('NETWORK-PACKAGE: Stacker size is ' . $this->getStackerInstance()->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 = $handlerInstance->getNextDecodedData();
// Very noisy debug message:
- //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: decodedData[' . gettype($decodedData) . ']=' . print_r($decodedData, true));
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: decodedData[' . gettype($decodedData) . ']=' . print_r($decodedData, true));
// And push it on our stack
$this->getStackerInstance()->pushNamed(self::STACKER_NAME_DECODED_INCOMING, $decodedData);
*/
public function accept (Visitor $visitorInstance) {
// Debug message
- //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: ' . $visitorInstance->__toString() . ' has visited - START');
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: ' . $visitorInstance->__toString() . ' has visited - START');
// Visit the package
$visitorInstance->visitNetworkPackage($this);
// Debug message
- //* NOISY-DEBUG: */ $this->debugOutput('PACKAGE: ' . $visitorInstance->__toString() . ' has visited - FINISHED');
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: ' . $visitorInstance->__toString() . ' has visited - FINISHED');
}
/**
$this->initStackers(true);
// Debug message
- /* DEBUG: */ $this->debugOutput('PACKAGE: All stacker have been re-initialized.');
+ /* DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: All stacker have been re-initialized.');
}
/**
// Handle message data
$handlerInstance->handleMessageData($messageArray[self::MESSAGE_ARRAY_DATA], $this);
-
- die(__METHOD__ . ':messageArray='.print_r($messageArray,true));
}
}
const ANNOUNCEMENT_DATA_SESSION_ID = 'session-id';
const ANNOUNCEMENT_DATA_NODE_STATUS = 'node-status';
const ANNOUNCEMENT_DATA_EXTERNAL_IP = 'external-ip';
+ const ANNOUNCEMENT_DATA_INTERNAL_IP = 'internal-ip';
const ANNOUNCEMENT_DATA_TCP_PORT = 'tcp-port';
const ANNOUNCEMENT_DATA_UDP_PORT = 'udp-port';
self::ANNOUNCEMENT_DATA_UDP_PORT,
self::ANNOUNCEMENT_DATA_SESSION_ID,
self::ANNOUNCEMENT_DATA_EXTERNAL_IP,
+ self::ANNOUNCEMENT_DATA_INTERNAL_IP,
'object-type-list',
);
}
return false;
} // END - if
- // Assign the found characters to variable and use the last entry from
- // stack as the name
+ /*
+ * Assign the found characters to variable and use the last entry from
+ * stack as the name.
+ */
parent::assignVariable($this->getStackerInstance()->getNamed('announcement'), $characters);
}
$this->getStackerInstance()->pushNamed('announcement', self::ANNOUNCEMENT_DATA_EXTERNAL_IP);
}
+ /**
+ * Starts the private ip
+ *
+ * @return void
+ */
+ private function startInternalIp () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement', self::ANNOUNCEMENT_DATA_INTERNAL_IP);
+ }
+
/**
* Starts the object type list
*
$this->getStackerInstance()->popNamed('announcement');
}
+ /**
+ * Finishes the private ip
+ *
+ * @return void
+ */
+ private function finishInternalIp () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement');
+ }
+
/**
* Finishes the public ip
*
* Main nodes in the XML tree
*/
private $mainNodes = array(
- '|||'
+ 'announcement-answer'
);
/**
* Sub nodes in the XML tree
*/
private $subNodes = array(
+ // These nodes don't contain any data
+ 'node-data',
+ 'other-data',
+ // Data from *this* node
+ 'node-external-ip',
+ 'node-tcp-port',
+ 'node-udp-port',
+ 'node-session-id',
+ 'node-status',
+ // Data from other node
+ 'other-external-ip',
+ 'other-session-id',
+ // Answer status (code)
+ 'answer-status'
);
/**
* Load a specified announcement-answer template into the engine
*
* @param $template The announcement-answer template we shall load which is
- * located in 'announcement-answer' by default
+ * located in 'announcement_answer' by default
* @return void
*/
public function loadAnnouncementAnswerTemplate ($template = 'announcement_answer') {
return false;
} // END - if
- // Get current XML node name as an array index
- $nodeName = $this->getStackerInstance()->getNamed('announcement-answer');
-
- $this->partialStub('TODO: Do something with the gathered data.');
+ /*
+ * Assign the found characters to variable and use the last entry from
+ * stack as the name.
+ */
+ parent::assignVariable($this->getStackerInstance()->getNamed('announcement_answer'), $characters);
}
/**
}
/**
- * Starts the |||
+ * Starts the announcement-answer
*
* @return void
*/
private function startAnnouncementAnswer () {
// Push the node name on the stacker
- $this->getStackerInstance()->pushNamed('announcement-answer', '|||');
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'announcement-answer');
+ }
+
+ /**
+ * Starts the node-data
+ *
+ * @return void
+ */
+ private function startNodeData () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-data');
+ }
+
+ /**
+ * Starts the node-external-ip
+ *
+ * @return void
+ */
+ private function startNodeExternalIp () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-external-ip');
+ }
+
+ /**
+ * Starts the node-internal-ip
+ *
+ * @return void
+ */
+ private function startNodeInternalIp () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-internal-ip');
+ }
+
+ /**
+ * Starts the node-tcp-port
+ *
+ * @return void
+ */
+ private function startNodeTcpPort () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-tcp-port');
+ }
+
+ /**
+ * Starts the node-udp-port
+ *
+ * @return void
+ */
+ private function startNodeUdpPort () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-udp-port');
+ }
+
+ /**
+ * Starts the node-session-id
+ *
+ * @return void
+ */
+ private function startNodeSessionId () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-session-id');
+ }
+
+ /**
+ * Starts the node-status
+ *
+ * @return void
+ */
+ private function startNodeStatus () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'node-status');
+ }
+
+ /**
+ * Finishes the node-status
+ *
+ * @return void
+ */
+ private function finishNodeStatus () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the node-session-id
+ *
+ * @return void
+ */
+ private function finishNodeSessionId () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the node-udp-port
+ *
+ * @return void
+ */
+ private function finishNodeUdpPort () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the node-tcp-port
+ *
+ * @return void
+ */
+ private function finishNodeTcpPort () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the node-internal-ip
+ *
+ * @return void
+ */
+ private function finishNodeInternalIp () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the node-external-ip
+ *
+ * @return void
+ */
+ private function finishNodeExternalIp () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the node-data
+ *
+ * @return void
+ */
+ private function finishNodeData () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Starts the other-data
+ *
+ * @return void
+ */
+ private function startOtherData () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'other-data');
+ }
+
+ /**
+ * Starts the other-external-ip
+ *
+ * @return void
+ */
+ private function startOtherExternalIp () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'other-external-ip');
+ }
+
+ /**
+ * Starts the other-internal-ip
+ *
+ * @return void
+ */
+ private function startOtherInternalIp () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'other-internal-ip');
+ }
+
+ /**
+ * Starts the other-session-id
+ *
+ * @return void
+ */
+ private function startOtherSessionId () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'other-session-id');
+ }
+
+ /**
+ * Finishes the other-session-id
+ *
+ * @return void
+ */
+ private function finishOtherSessionId () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the other-internal-ip
+ *
+ * @return void
+ */
+ private function finishOtherInternalIp () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the other-external-ip
+ *
+ * @return void
+ */
+ private function finishOtherExternalIp () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Finishes the other-data
+ *
+ * @return void
+ */
+ private function finishOtherData () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
+ }
+
+ /**
+ * Starts the answer-status
+ *
+ * @return void
+ */
+ private function startAnswerStatus () {
+ // Push the node name on the stacker
+ $this->getStackerInstance()->pushNamed('announcement_answer', 'answer-status');
+ }
+
+ /**
+ * Finishes the answer-status
+ *
+ * @return void
+ */
+ private function finishAnswerStatus () {
+ // Pop the last entry
+ $this->getStackerInstance()->popNamed('announcement_answer');
}
/**
- * Finishes the |||
+ * Finishes the announcement-answer
*
* @return void
*/
private function finishAnnouncementAnswer () {
// Pop the last entry
- $this->getStackerInstance()->popNamed('announcement-answer');
+ $this->getStackerInstance()->popNamed('announcement_answer');
}
}
// Return it
return $ip;
}
+
+ /**
+ * Determine IP or 'internal_ip' if set
+ *
+ * @return $ip The determined external ip of this node
+ */
+ public static function determineOwnInternalIp () {
+ // Is the external_ip config entry set?
+ if (FrameworkConfiguration::getSelfInstance()->getConfigEntry('internal_ip') != '') {
+ // Use it as internal ip
+ $ip = FrameworkConfiguration::getSelfInstance()->getConfigEntry('internal_ip');
+ } else {
+ // Determine own internal ip by connecting to my (coder) server at 188.138.90.169
+ $ip = ConsoleTools::acquireSelfIPAddress();
+ }
+
+ // Return it
+ return $ip;
+ }
}
// [EOF]
<listener>
<!-- Public external IP address //-->
<external-ip>{?external_ip?}</external-ip>
+ <!-- Private internal IP address //-->
+ <internal-ip>{?internal_ip?}</internal-ip>
<!-- Listener ports for both connections //-->
<tcp-port>{?node_tcp_listen_port?}</tcp-port>
<udp-port>{?node_udp_listen_port?}</udp-port>
along with this program. If not, see <http://www.gnu.org/licenses/>
//-->
<announcement-answer>
+ <!--
+ The following data is from this node.
+ //-->
+ <node-data>
+ <!--
+ This node's external IP/hostname
+ //-->
+ <node-external-ip>{?external_ip?}</node-external-ip>
+ <!--
+ This node's internal IP/hostname
+ //-->
+ <node-internal-ip>{?internal_ip?}</node-internal-ip>
+ <!--
+ This node's TCP port
+ //-->
+ <node-tcp-port>{?node_tcp_listen_port?}</node-tcp-port>
+ <!--
+ This node's UDP port
+ //-->
+ <node-udp-port>{?node_udp_listen_port?}</node-udp-port>
+ <!--
+ This node's session id
+ //-->
+ <node-session-id>{?session_id?}</node-session-id>
+ <!--
+ This node's status
+ //-->
+ <node-status>{?node_status?}</node-status>
+ </node-data>
+ <!--
+ The following data is the other node's data. This data is being sent to
+ confirm that it has been received correctly.
+ //-->
+ <other-data>
+ <!--
+ Other node's external IP/hostname
+ //-->
+ <other-external-ip>{?other_external_ip?}</other-external-ip>
+ <!--
+ Other node's internal IP/hostname
+ //-->
+ <other-internal-ip>{?other_internal_ip?}</other-internal-ip>
+ <!--
+ Other node's session id
+ //-->
+ <other-session-id>{?other_session_id?}</other-session-id>
+ </other-data>
+ <!--
+ Status of this answer. This can be something like OKAY if all went fine or
+ any other error code.
+ //-->
+ <answer-status>{?answer_status?}</answer-status>
</announcement-answer>
<!--
Recipient limitation:
---------------------
- upper - Only uploaded to "upper" hubs, these are bootstrap and
- list-nodes
- self - Only upload to itself
- ??? - More to follow ...
+ upper - Only uploaded to "upper" hubs, these are bootstrap and
+ list-nodes
+ self - Only upload to itself
+ direct - Only direct recipient(s)
+ ??? - More to follow ...
//-->
<object-recipient-limitation>upper</object-recipient-limitation>
<!--
<!-- The recipient type for this type of object //-->
<object-recipient-type>hub</object-recipient-type>
</object-list-entry>
+ <!-- A single object type we want to share. //-->
+ <object-list-entry>
+ <!-- The actual name, this must be the same as tag names are. //-->
+ <object-name>announcement_answer</object-name>
+ <!-- Recipient limitation //-->
+ <object-recipient-limitation>direct</object-recipient-limitation>
+ <!-- Maximum spread of the object //-->
+ <object-max-spread>1</object-max-spread>
+ <!-- The protocol we should use for transmission //-->
+ <object-protocol>tcp</object-protocol>
+ <!-- The recipient type for this type of object //-->
+ <object-recipient-type>hub</object-recipient-type>
+ </object-list-entry>
</object-list>
</object-registry>