* Also an "end-of-package" marker is being added as the last chunk to mark the
* end of of the whole package submission.
*
- * @author Roland Haeder <webmaster@ship-simu.org>
+ * @author Roland Haeder <webmaster@shipsimu.org>
* @version 0.0.0
- * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2012 Hub Developer Team
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2015 Hub Developer Team
* @license GNU GPL 3.0 or any newer version
- * @link http://www.ship-simu.org
+ * @link http://www.shipsimu.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
private $processedPackages = array();
/**
- * Serial number
+ * Serial numbers (array key is final hash)
*/
- private $serialNumber = 0x00000000;
+ private $serialNumber = array();
/**
* Maximum possible serial number, "cache" for speeding up things
$isProcessed = (
(isset($this->processedPackages[$index]))
&&
- ($this->processedPackages[$index] === true)
+ ($this->processedPackages[$index] === TRUE)
);
// Return it
*/
private function markPackageDataProcessed (array $packageData) {
// Remember it (until we may remove it)
- $this->processedPackages[$this->getProcessedPackagesIndex($packageData)] = true;
+ $this->processedPackages[$this->getProcessedPackagesIndex($packageData)] = TRUE;
}
/**
assert(strlen($finalHash) > 0);
// Is the pointer already initialized?
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': finalHash[' . gettype($finalHash) . ']=' . $finalHash);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: finalHash[' . gettype($finalHash) . ']=' . $finalHash);
assert(isset($this->chunkPointers[$finalHash]));
// Return it
assert(isset($this->chunkPointers[$finalHash]));
// Count one up
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': finalHash[' . gettype($finalHash) . ']=' . $finalHash);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: finalHash[' . gettype($finalHash) . ']=' . $finalHash);
$this->chunkPointers[$finalHash]++;
}
* Get the crypto instance and hash the data with no extra salt because
* the other peer doesn't have *this* peer's salt.
*/
- $hash = $this->getCryptoInstance()->hashString($rawData, '', false);
+ $hash = $this->getCryptoInstance()->hashString($rawData, '', FALSE);
// Return it
return $hash;
$this->generateHashFromRawData($lastChunk);
// Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': Adding EOP chunk with size of ' . strlen($chunkData) . ',finalHash=' . $finalHash . ' ...');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: Adding EOP chunk with size of ' . strlen($chunkData) . ',finalHash=' . $finalHash . ' ...');
// Add it as regular chunk
$this->addChunkData($finalHash, $chunkData);
// Calculate real (data) chunk size
$dataChunkSize = $this->getDataChunkSizeFromHash($finalHash);
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': dataChunkSize=' . $dataChunkSize);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: dataChunkSize=' . $dataChunkSize);
// Init variables
$chunkHash = '';
} // END - for
// Debug output
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': Raw data of ' . strlen($rawData) . ' bytes has been fragmented into ' . count($this->chunks[$finalHash]) . ' chunk(s).');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: Raw data of ' . strlen($rawData) . ' bytes has been fragmented into ' . count($this->chunks[$finalHash]) . ' chunk(s).');
// Add end-of-package chunk
$this->appendEndOfPackageChunk($chunkData, $finalHash);
* @param $prepend Whether append (default) or prepend the chunk
* @return void
*/
- private function addChunkData ($finalHash, $chunkData, $prepend = false) {
+ private function addChunkData ($finalHash, $chunkData, $prepend = FALSE) {
// Hash it
- $rawDataHash = $this->getCryptoInstance()->hashString($chunkData, '', false);
+ $rawDataHash = $this->getCryptoInstance()->hashString($chunkData, '', FALSE);
// Prepend the hash to the chunk
$rawData = (
$rawDataHash . self::CHUNK_DATA_HASH_SEPARATOR .
- $this->getNextHexSerialNumber() . self::CHUNK_DATA_HASH_SEPARATOR .
+ $this->getNextHexSerialNumber($finalHash) . self::CHUNK_DATA_HASH_SEPARATOR .
$chunkData . self::CHUNK_SEPARATOR
);
// Make sure the chunk is not larger than a TCP package can hold
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': assert: ' . strlen($rawData) . '/' . NetworkPackage::TCP_PACKAGE_SIZE . ' ...');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: assert: ' . strlen($rawData) . '/' . NetworkPackage::TCP_PACKAGE_SIZE . ' ...');
// @TODO This assert broke packages where the hash chunk was very large: assert(strlen($rawData) <= NetworkPackage::TCP_PACKAGE_SIZE);
// Add it to the array
- if ($prepend === true) {
+ if ($prepend === TRUE) {
// Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': Prepending ' . strlen($rawData) . ' bytes of a chunk, finalHash=' . $finalHash . ' ...');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: Prepending ' . strlen($rawData) . ' bytes of a chunk, finalHash=' . $finalHash . ' ...');
array_unshift($this->chunkHashes[$finalHash], $rawDataHash);
array_unshift($this->chunks[$finalHash] , $rawData);
} else {
// Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': Appending ' . strlen($rawData) . ' bytes of a chunk, finalHash=' . $finalHash . ' ...');
- $this->chunks[$finalHash][] = $rawData;
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: Appending ' . strlen($rawData) . ' bytes of a chunk, finalHash=' . $finalHash . ' ...');
+
+ // Is the array there?
+ if (!isset($this->chunks[$finalHash])) {
+ // Then initialize it
+ $this->chunks[$finalHash] = array();
+ $this->chunkHashes[$finalHash] = array();
+ } // END - if
+
+ // Add both
+ array_push($this->chunks[$finalHash] , $rawData);
array_push($this->chunkHashes[$finalHash], $rawDataHash);
}
}
$rawData = self::HASH_CHUNK_IDENTIFIER . implode(self::CHUNK_HASH_SEPARATOR, $this->chunkHashes[$finalHash]);
// Prepend chunk
- $this->addChunkData($finalHash, $rawData, true);
+ $this->addChunkData($finalHash, $rawData, TRUE);
}
/**
* "Getter" for the next hexadecimal-encoded serial number
*
+ * @param $finalHash Final hash
* @return $encodedSerialNumber The next hexadecimal-encoded serial number
*/
- public function getNextHexSerialNumber () {
+ public function getNextHexSerialNumber ($finalHash) {
// Assert on maximum serial number length
- assert($this->serialNumber <= $this->maxSerialNumber);
+ assert(isset($this->serialNumber[$finalHash]));
+ assert($this->serialNumber[$finalHash] <= $this->maxSerialNumber);
// Encode the current serial number
- $encodedSerialNumber = $this->dec2Hex($this->serialNumber, self::MAX_SERIAL_LENGTH);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber[' . $finalHash . ']=' . $this->serialNumber[$finalHash]);
+ $encodedSerialNumber = $this->dec2Hex($this->serialNumber[$finalHash], self::MAX_SERIAL_LENGTH);
// Count one up
- $this->serialNumber++;
+ $this->serialNumber[$finalHash]++;
// Return the encoded serial number
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: encodedSerialNumber=' . $encodedSerialNumber);
return $encodedSerialNumber;
}
public function fragmentPackageArray (array $packageData, ConnectionHelper $helperInstance) {
// Is this package already fragmented?
if (!$this->isPackageProcessed($packageData)) {
- // Remove package status and protocol, the recipient doesn't need this
- unset($packageData[NetworkPackage::PACKAGE_DATA_STATUS]);
- unset($packageData[NetworkPackage::PACKAGE_DATA_PROTOCOL]);
-
// First we need to "implode" the array
$rawData = implode(NetworkPackage::PACKAGE_DATA_SEPARATOR, $packageData);
// Remember it
$this->processedPackages[$this->getProcessedPackagesIndex($packageData)] = $finalHash;
- // Init pointer
+ // Init pointer and reset serial number
$this->initPointer($finalHash);
+ $this->resetSerialNumber($finalHash);
// Split the encoded data into smaller chunks
$this->splitEncodedDataIntoChunks($rawData, $finalHash);
}
// Return final hash
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': finalHash[' . gettype($finalHash) . ']=' . $finalHash);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: finalHash[' . gettype($finalHash) . ']=' . $finalHash);
return $finalHash;
}
*
* @param $finalHash Final hash for faster lookup
* @return $rawDataChunk Raw package data chunk
- * @throws AssertionException If $finalHash was not 'true'
+ * @throws AssertionException If $finalHash was not 'TRUE'
*/
public function getNextRawDataChunk ($finalHash) {
// Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': finalHash[' . gettype($finalHash) . ']=' . $finalHash);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-FRAGMENTER[' . __METHOD__ . ':' . __LINE__ . ']: finalHash[' . gettype($finalHash) . ']=' . $finalHash);
try {
// Get current chunk index
$current = $this->getCurrentChunkPointer($finalHash);
} catch (AssertionException $e) {
- // This may happen when the final hash is true
- if ($finalHash === true) {
+ // This may happen when the final hash is TRUE
+ if ($finalHash === TRUE) {
// Set current to null
$current = NULL;
} else {
}
/**
- * Resets the serial number to zero
+ * Resets the serial number to zero for given final hash
*
+ * @param $finalHash Final hash to reset counter for
* @return void
*/
- public function resetSerialNumber () {
- // Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('FRAGMENTER: Resetting serial number, previous=' . $this->serialNumber);
+ public function resetSerialNumber ($finalHash) {
+ // Final hash must be set
+ assert((is_string($finalHash)) && (!empty($finalHash)));
- // Reset serial number
- $this->serialNumber = 0;
+ // Reset/set serial number
+ $this->serialNumber[$finalHash] = 0;
}
}