Changeset 1818
- Timestamp:
- 09/02/08 04:02:28 (4 months ago)
- Files:
-
- labs/incubator/src/main/php/net/stubbles/remote/protocol/easc/stubEASCHeader.php (modified) (6 diffs)
- labs/incubator/src/main/php/net/stubbles/remote/protocol/easc/stubEASCMessageType.php (added)
- labs/incubator/src/main/php/net/stubbles/remote/protocol/easc/stubEASCProtocolHandler.php (modified) (12 diffs)
- labs/incubator/src/test/php/net/stubbles/remote/protocol/easc/stubEASCHeaderTestCase.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
labs/incubator/src/main/php/net/stubbles/remote/protocol/easc/stubEASCHeader.php
r1817 r1818 9 9 * @version $Id$ 10 10 */ 11 stubClassLoader::load('net::stubbles::peer::stubSocket'); 11 stubClassLoader::load('net::stubbles::lang::exceptions::stubIllegalArgumentException', 12 'net::stubbles::peer::stubSocket', 13 'net::stubbles::remote::protocol::easc::stubEASCMessageType' 14 ); 12 15 /** 13 16 * Class for handling easc message headers. … … 71 74 * type of message 72 75 * 73 * @var int76 * @var stubEASCMessageType 74 77 */ 75 78 protected $messageType; … … 90 93 * constructor 91 94 * 92 * @param int $magicNumber magic easc protocol number93 * @param int $versionMajor major part of protocol version94 * @param int $versionMinor minor part of protocol version95 * @param int$messageType type of message that follows after header96 * @param bool $transactionActive whether a transaction is active or not97 * @param int $dataLength length of data after header98 */ 99 public function __construct($magicNumber, $versionMajor, $versionMinor, $messageType, $transactionActive, $dataLength)95 * @param int $magicNumber magic easc protocol number 96 * @param int $versionMajor major part of protocol version 97 * @param int $versionMinor minor part of protocol version 98 * @param stubEASCMessageType $messageType type of message that follows after header 99 * @param bool ÂŽ $transactionActive whether a transaction is active or not 100 * @param int $dataLength length of data after header 101 */ 102 public function __construct($magicNumber, $versionMajor, $versionMinor, stubEASCMessageType $messageType, $transactionActive, $dataLength) 100 103 { 101 104 $this->magicNumber = $magicNumber; … … 128 131 129 132 $header = unpack('Nmagic/cvmajor/cvminor/ctype/ctran/Nlength', $headerString); 130 return new self($header['magic'], $header['vmajor'], $header['vminor'], $header['type'], $header['tran'], $header['length']); 133 try { 134 $messageType = stubEASCMessageType::forValue(new ReflectionClass('stubEASCMessageType'), $header['type']); 135 } catch (stubIllegalArgumentException $iae) { 136 $messageType = stubEASCMessageType::$UNKNOWN; 137 } 138 139 return new self($header['magic'], 140 $header['vmajor'], 141 $header['vminor'], 142 $messageType, 143 (bool) $header['tran'], 144 $header['length'] 145 ); 131 146 } 132 147 … … 143 158 { 144 159 return $socket->write(pack('Nc4N', 145 self::DEFAULT_MAGIC_NUMBER, // magic number to ensure correctness of message146 $this->versionMajor, // version: major147 $this->versionMinor, // version: minor148 $this->messageType ,// message type149 $this->transactionActive, // compression150 $this->dataLength // length of data to follow160 self::DEFAULT_MAGIC_NUMBER, // magic number to ensure correctness of message 161 $this->versionMajor, // version: major 162 $this->versionMinor, // version: minor 163 $this->messageType->value(), // message type 164 $this->transactionActive, // compression 165 $this->dataLength // length of data to follow 151 166 ) 152 167 ); … … 186 201 * returns type of message that follows after header 187 202 * 188 * @return int203 * @return stubEASCMessageType 189 204 */ 190 205 public function getMessageType() labs/incubator/src/main/php/net/stubbles/remote/protocol/easc/stubEASCProtocolHandler.php
r1817 r1818 8 8 * @version $Id$ 9 9 */ 10 stubClassLoader::load('net::stubbles::remote::protocol::stubByteCountedString', 10 stubClassLoader::load('net::stubbles::peer::stubBSDSocket', 11 'net::stubbles::remote::stubRemoteException', 12 'net::stubbles::remote::protocol::stubByteCountedString', 11 13 'net::stubbles::remote::protocol::stubProtocolHandler', 12 14 'net::stubbles::remote::protocol::easc::stubEASCException', 13 15 'net::stubbles::remote::protocol::easc::stubEASCHeader', 14 'net::stubbles:: peer::stubBSDSocket'16 'net::stubbles::remote::protocol::easc::stubEASCMessageType' 15 17 ); 16 18 /** … … 41 43 protected $socket; 42 44 /** 43 * request message type: init44 */45 const MSG_INIT = 0x0000;46 /**47 * request message type: lookup48 */49 const MSG_LOOKUP = 0x0001;50 /**51 * request message type: call52 */53 const MSG_CALL = 0x0002;54 /**55 * request message type: finalize56 */57 const MSG_FINALIZE = 0x0003;58 /**59 * request message type: transaction operation60 */61 const MSG_TRAN_OP = 0x0004;62 /**63 * response message type: value64 */65 const MSG_VALUE = 0x0005;66 /**67 * response message type: exception68 */69 const MSG_EXCEPTION = 0x0006;70 /**71 * response message type: error72 */73 const MSG_ERROR = 0x0007;74 /**75 45 * transaction message type: begin of transaction 76 46 */ … … 118 88 $this->socket->connect(); 119 89 if ($url->getUser() !== null) { 120 $this->sendPacket(s elf::MSG_INIT, "\1", array(new stubByteCountedString($url->getUser()),90 $this->sendPacket(stubEASCMessageType::$INITIALIZE, "\1", array(new stubByteCountedString($url->getUser()), 121 91 new stubByteCountedString($url->getPassword()) 122 92 ) 123 93 ); 124 94 } else { 125 $this->sendPacket(s elf::MSG_INIT, "\0");95 $this->sendPacket(stubEASCMessageType::$INITIALIZE, "\0"); 126 96 } 127 97 } … … 135 105 public function lookup($name) 136 106 { 137 return $this->sendPacket(s elf::MSG_LOOKUP, '', array(new stubByteCountedString($name)));107 return $this->sendPacket(stubEASCMessageType::$LOOKUP, '', array(new stubByteCountedString($name))); 138 108 } 139 109 … … 146 116 public function begin($tran) 147 117 { 148 return $this->sendPacket(s elf::MSG_TRAN_OP, pack('N', self::TRAN_BEGIN));118 return $this->sendPacket(stubEASCMessageType::$TRANSACTION, pack('N', self::TRAN_BEGIN)); 149 119 } 150 120 … … 157 127 public function rollback($tran) 158 128 { 159 return $this->sendPacket(s elf::MSG_TRAN_OP, pack('N', self::TRAN_ROLLBACK));129 return $this->sendPacket(stubEASCMessageType::$TRANSACTION, pack('N', self::TRAN_ROLLBACK)); 160 130 } 161 131 … … 168 138 public function commit($tran) 169 139 { 170 return $this->sendPacket(s elf::MSG_TRAN_OP, pack('N', self::TRAN_COMMIT));140 return $this->sendPacket(stubEASCMessageType::$TRANSACTION, pack('N', self::TRAN_COMMIT)); 171 141 } 172 142 … … 182 152 public function invoke($oid, $method, array $args) 183 153 { 184 return $this->sendPacket(s elf::MSG_CALL,154 return $this->sendPacket(stubEASCMessageType::$CALL, 185 155 pack('NN', 0, $oid), 186 156 array(new stubByteCountedString($method), … … 193 163 * sends a packet, reads and evaluates the response 194 164 * 195 * @param int$type165 * @param stubEASCMessageType $type 196 166 * @param string $data optional 197 167 * @param array<stubByteCountedString> $bytes optional … … 200 170 * @throws stubEASCException for unrecoverable errors 201 171 */ 202 protected function sendPacket( $type, $data = '', array $bytes = array())172 protected function sendPacket(stubEASCMessageType $type, $data = '', array $bytes = array()) 203 173 { 204 174 $bsize = sizeof($bytes); … … 208 178 } 209 179 210 $requestHeader = new stubEASCHeader(stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, $type, false, $length); 180 $requestHeader = new stubEASCHeader(stubEASCHeader::DEFAULT_MAGIC_NUMBER, 181 $this->version['major'], 182 $this->version['minor'], 183 $type, 184 false, 185 $length 186 ); 211 187 try { 212 188 $requestHeader->writeToSocket($this->socket, $data); … … 226 202 } elseif (stubEASCHeader::DEFAULT_MAGIC_NUMBER != $responseHeader->getMagicNumber()) { 227 203 $this->socket->close(); 228 throw new stubEASCException('Magic number mismatch, got "' . $responseHeader->getMagicNumber() . '" but expected "' . stubEASCHeader::MAGIC_NUMBER . '".'); 229 } 230 231 // Perform actions based on response type 232 $context = array('handler' => $this); 204 throw new stubEASCException('Magic number mismatch, got "' . $responseHeader->getMagicNumber() . '" but expected "' . stubEASCHeader::DEFAULT_MAGIC_NUMBER . '".'); 205 } 206 233 207 try { 234 switch ($responseHeader->getMessageType()) { 235 case self::MSG_VALUE: 236 $data = stubByteCountedString::readFrom($this->socket); 237 return $this->serializer->unserialize(new stubPHPSerializedData($data), $context); 238 239 case self::MSG_EXCEPTION: 240 $data = stubByteCountedString::readFrom($this->socket); 241 $reference = $this->serializer->unserialize(new stubPHPSerializedData($data), $context); 242 if ($reference instanceof stubRemoteException) { 243 throw $reference; 244 } elseif ($reference instanceof stubExceptionReference) { 245 throw new stubRemoteException($reference->getMessage(), $reference); 246 } 247 248 throw new stubRemoteException('lang.XPException', new XPException($this->stringOf($reference))); 249 250 case self::MSG_ERROR: 251 $message = stubByteCountedString::readFrom($this->socket); // not serialized! 252 $this->socket->close(); 253 throw new stubRemoteException($message, new stubEASCException($message)); 254 255 default: 256 $data = $this->readBytes($responseHeader->getDataLength()); 257 $this->socket->close(); 258 throw new stubEASCException('Unknown message type: ' . $data); 259 } 208 $responseHeader->getMessageType()->process($this->socket, $this->serializer, array('handler' => $this)); 260 209 } catch (stubConnectionException $ce) { 261 210 throw new stubRemoteException($ce->getMessage(), $ce); 262 211 } 263 212 } 264 265 /**266 * reads a specified number of bytes267 *268 * @param int $num269 * @return string270 */271 protected function readBytes($amount)272 {273 $return = '';274 while (strlen($return) < $amount) {275 $buffer = $this->socket->readBinary($amount - strlen($return));276 if (0 === strlen($buffer)) {277 return null;278 }279 280 $return .= $buffer;281 }282 283 return $return;284 }285 286 /**287 * creates a string representation of a given value288 *289 * @param mixed $value290 * @return string291 */292 protected function stringOf($value)293 {294 if ($value instanceof Proxy) {295 $s = 'Proxy<';296 foreach ($value->getClass()->getInterfaces() as $iface) {297 $s .= $iface->getName() . ', ';298 }299 300 return substr($s, 0, -2) . '>';301 }302 303 return xp::stringOf($value);304 }305 213 } 306 214 ?> labs/incubator/src/test/php/net/stubbles/remote/protocol/easc/stubEASCHeaderTestCase.php
r1817 r1818 32 32 public function setUp() 33 33 { 34 $this->eascHeader = new stubEASCHeader(stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, 1, false, 4);34 $this->eascHeader = new stubEASCHeader(stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, stubEASCMessageType::$INITIALIZE, false, 4); 35 35 } 36 36 … … 45 45 $this->assertEquals(1, $this->eascHeader->getVersionMajor()); 46 46 $this->assertEquals(0, $this->eascHeader->getVersionMinor()); 47 $this->assert Equals(1, $this->eascHeader->getMessageType());47 $this->assertSame(stubEASCMessageType::$INITIALIZE, $this->eascHeader->getMessageType()); 48 48 $this->assertFalse($this->eascHeader->isTransactionActive()); 49 49 $this->assertEquals(4, $this->eascHeader->getDataLength()); … … 60 60 $mockSocket->expects($this->once()) 61 61 ->method('write') 62 ->with($this->equalTo(pack('Nc4N', stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, 1, false, 4)))62 ->with($this->equalTo(pack('Nc4N', stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, stubEASCMessageType::$INITIALIZE->value(), false, 4))) 63 63 ->will($this->returnValue(stubEASCHeader::SIZE)); 64 64 $this->assertEquals(stubEASCHeader::SIZE, $this->eascHeader->writeToSocket($mockSocket)); … … 76 76 ->method('readBinary') 77 77 ->with($this->equalTo(stubEASCHeader::SIZE)) 78 ->will($this->returnValue(pack('Nc4N', stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, 1, false, 4)));78 ->will($this->returnValue(pack('Nc4N', stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, stubEASCMessageType::$INITIALIZE->value(), false, 4))); 79 79 $eascHeader = stubEASCHeader::readFromSocket($mockSocket); 80 80 $this->assertType('stubEASCHeader', $eascHeader); 81 $this->assertEquals(stubEASCHeader::DEFAULT_MAGIC_NUMBER, $ this->eascHeader->getMagicNumber());82 $this->assertEquals(1, $ this->eascHeader->getVersionMajor());83 $this->assertEquals(0, $ this->eascHeader->getVersionMinor());84 $this->assert Equals(1, $this->eascHeader->getMessageType());85 $this->assertFalse($ this->eascHeader->isTransactionActive());86 $this->assertEquals(4, $ this->eascHeader->getDataLength());81 $this->assertEquals(stubEASCHeader::DEFAULT_MAGIC_NUMBER, $eascHeader->getMagicNumber()); 82 $this->assertEquals(1, $eascHeader->getVersionMajor()); 83 $this->assertEquals(0, $eascHeader->getVersionMinor()); 84 $this->assertSame(stubEASCMessageType::$INITIALIZE, $eascHeader->getMessageType()); 85 $this->assertFalse($eascHeader->isTransactionActive()); 86 $this->assertEquals(4, $eascHeader->getDataLength()); 87 87 } 88 88 … … 101 101 $this->assertNull(stubEASCHeader::readFromSocket($mockSocket)); 102 102 } 103 104 /** 105 * no data on socket does not create an instance 106 * 107 * @test 108 */ 109 public function readFromSocketUnknownMessageType() 110 { 111 $mockSocket = $this->getMock('stubSocket', array(), array('localhost', 313)); 112 $mockSocket->expects($this->once()) 113 ->method('readBinary') 114 ->with($this->equalTo(stubEASCHeader::SIZE)) 115 ->will($this->returnValue(pack('Nc4N', stubEASCHeader::DEFAULT_MAGIC_NUMBER, 1, 0, 0x0020, false, 4))); 116 $eascHeader = stubEASCHeader::readFromSocket($mockSocket); 117 $this->assertType('stubEASCHeader', $eascHeader); 118 $this->assertEquals(stubEASCHeader::DEFAULT_MAGIC_NUMBER, $eascHeader->getMagicNumber()); 119 $this->assertEquals(1, $eascHeader->getVersionMajor()); 120 $this->assertEquals(0, $eascHeader->getVersionMinor()); 121 $this->assertSame(stubEASCMessageType::$UNKNOWN, $eascHeader->getMessageType()); 122 $this->assertFalse($eascHeader->isTransactionActive()); 123 $this->assertEquals(4, $eascHeader->getDataLength()); 124 } 103 125 } 104 126 ?>
