Changeset 1815
- Timestamp:
- 09/02/08 00:30:40 (4 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
labs/incubator/src/main/php/net/stubbles/remote/protocol/easc/stubEASCProtocolHandler.php
r1804 r1815 8 8 * @version $Id$ 9 9 */ 10 stubClassLoader::load('net::stubbles::remote::protocol::stubProtocolHandler', 10 stubClassLoader::load('net::stubbles::remote::protocol::stubByteCountedString', 11 'net::stubbles::remote::protocol::stubProtocolHandler', 12 'net::stubbles::remote::protocol::easc::stubEASCException', 11 13 'net::stubbles::peer::stubBSDSocket' 12 14 ); … … 32 34 protected $version = array('major' => 0, 'minor' => 0); 33 35 /** 36 * socket used to connect to remote server 37 * 38 * @var stubBSDSocket 39 */ 40 protected $socket; 41 /** 34 42 * magic easc protocol number 35 43 */ 36 const MAGIC_NUMBER = 0x3c872747;44 const MAGIC_NUMBER = 0x3c872747; 37 45 /** 38 46 * request message type: init 39 47 */ 40 const MSG_INIT = 0x0000;48 const MSG_INIT = 0x0000; 41 49 /** 42 50 * request message type: lookup 43 51 */ 44 const MSG_LOOKUP = 0x0001;52 const MSG_LOOKUP = 0x0001; 45 53 /** 46 54 * request message type: call 47 55 */ 48 const MSG_CALL = 0x0002;56 const MSG_CALL = 0x0002; 49 57 /** 50 58 * request message type: finalize 51 59 */ 52 const MSG_FINALIZE = 0x0003;60 const MSG_FINALIZE = 0x0003; 53 61 /** 54 62 * request message type: transaction operation 55 63 */ 56 const MSG_TRAN_OP = 0x0004;64 const MSG_TRAN_OP = 0x0004; 57 65 /** 58 66 * response message type: value 59 67 */ 60 const MSG_VALUE = 0x0005;68 const MSG_VALUE = 0x0005; 61 69 /** 62 70 * response message type: exception 63 71 */ 64 const MSG_EXCEPTION = 0x0006;72 const MSG_EXCEPTION = 0x0006; 65 73 /** 66 74 * response message type: error 67 75 */ 68 const MSG_ERROR = 0x0007;76 const MSG_ERROR = 0x0007; 69 77 /** 70 78 * transaction message type: begin of transaction 71 79 */ 72 const TRAN_BEGIN = 0x0001;80 const TRAN_BEGIN = 0x0001; 73 81 /** 74 82 * transaction message type: state of transaction 75 83 */ 76 const TRAN_STATE = 0x0002;84 const TRAN_STATE = 0x0002; 77 85 /** 78 86 * transaction message type: commit transaction 79 87 */ 80 const TRAN_COMMIT = 0x0003;88 const TRAN_COMMIT = 0x0003; 81 89 /** 82 90 * transaction message type: rollback transaction 83 91 */ 84 const TRAN_ROLLBACK = 0x0004;92 const TRAN_ROLLBACK = 0x0004; 85 93 86 94 /** … … 90 98 { 91 99 $this->serializer = new stubEASCSerializer(); 92 $this->serializer-> mapping('I',new stubRemoteInterfaceMapping());93 $this->serializer-> exceptionName('naming/NameNotFound', 'net::stubbles::remote::stubNameNotFoundException');94 $this->serializer-> exceptionName('invoke/Exception', 'net::stubbles::remote::stubInvocationException');95 $this->serializer-> packageMapping('net.xp_framework.easc.reflect', 'net::stubbles::remote::easc::reflect');100 $this->serializer->addMapping(new stubRemoteInterfaceMapping()); 101 $this->serializer->addExceptionMapping('net::stubbles::remote::stubNameNotFoundException', 'naming/NameNotFound'); 102 $this->serializer->addExceptionMapping('net::stubbles::remote::stubInvocationException', 'invoke/Exception'); 103 $this->serializer->addPackageMapping('net::stubbles::remote::easc::reflect', 'net.xp_framework.easc.reflect'); 96 104 } 97 105 … … 109 117 $this->version['minor'] 110 118 ); 111 $this-> _sock= new stubBSDSocket($url->getHost('localhost'), $url->getPort(6448));112 $this-> _sock->setOption(getprotobyname('tcp'), TCP_NODELAY, true);113 $this-> _sock->connect();119 $this->socket = new stubBSDSocket($url->getHost('localhost'), $url->getPort(6448)); 120 $this->socket->setOption(getprotobyname('tcp'), TCP_NODELAY, true); 121 $this->socket->connect(); 114 122 if ($url->getUser() !== null) { 115 $this->sendPacket(self::MSG_INIT, "\1", array(new ByteCountedString($url->getUser()),116 new ByteCountedString($url->getPassword())123 $this->sendPacket(self::MSG_INIT, "\1", array(new stubByteCountedString($url->getUser()), 124 new stubByteCountedString($url->getPassword()) 117 125 ) 118 126 ); … … 130 138 public function lookup($name) 131 139 { 132 return $this->sendPacket(self::MSG_LOOKUP, '', array(new ByteCountedString($name)));140 return $this->sendPacket(self::MSG_LOOKUP, '', array(new stubByteCountedString($name))); 133 141 } 134 142 … … 136 144 * begins a transaction 137 145 * 138 * @param remote.UserTransaction tran146 * @param UserTransaction tran 139 147 * @return bool 140 148 */ 141 149 public function begin($tran) 142 150 { 143 return $this->sendPacket(self::MSG_TRAN_OP, pack('N', self::TRAN_BEGIN));151 return $this->sendPacket(self::MSG_TRAN_OP, pack('N', self::TRAN_BEGIN)); 144 152 } 145 153 … … 147 155 * rolls back a transaction 148 156 * 149 * @param remote.UserTransaction tran157 * @param UserTransaction tran 150 158 * @return bool 151 159 */ 152 160 public function rollback($tran) 153 161 { 154 return $this->sendPacket(self::MSG_TRAN_OP, pack('N', self::TRAN_ROLLBACK));162 return $this->sendPacket(self::MSG_TRAN_OP, pack('N', self::TRAN_ROLLBACK)); 155 163 } 156 164 … … 158 166 * commits a transaction 159 167 * 160 * @param remote.UserTransaction tran168 * @param UserTransaction tran 161 169 * @return bool 162 170 */ 163 171 public function commit($tran) 164 172 { 165 return $this->sendPacket(self::MSG_TRAN_OP, pack('N', self::TRAN_COMMIT));173 return $this->sendPacket(self::MSG_TRAN_OP, pack('N', self::TRAN_COMMIT)); 166 174 } 167 175 … … 170 178 * and given arguments 171 179 * 172 * @param int $oid id of the object to invoke the method on173 * @param string $method the name of the method to invoke174 * @param array<int,mixed>$args arguments for the method to invoke180 * @param int $oid id of the object to invoke the method on 181 * @param string $method the name of the method to invoke 182 * @param mixed $args arguments for the method to invoke 175 183 * @return mixed 176 * @throws stubRemoteException 177 */ 178 public function invoke($oid, $method, array $args) 179 { 180 return $this->sendPacket(self::MSG_CALL, pack('NN', 0, $oid), array(new ByteCountedString($method), 181 new ByteCountedString($this->serializer->representationOf($args)) 182 ) 184 */ 185 public function invoke($oid, $method, $args) 186 { 187 return $this->sendPacket(self::MSG_CALL, 188 pack('NN', 0, $oid), 189 array(new stubByteCountedString($method), 190 new stubByteCountedString($this->serializer->serialize(stubArrayList::with(array($args)))) 191 ) 183 192 ); 184 193 } … … 187 196 * sends a packet, reads and evaluates the response 188 197 * 189 * @param int $type190 * @param string $data optional191 * @param array< ByteCountedString> $bytes optional198 * @param int $type 199 * @param string $data optional 200 * @param array<stubByteCountedString> $bytes optional 192 201 * @return mixed 193 * @throws remote.RemoteExceptionfor server errors194 * @throws lang.Errorfor unrecoverable errors202 * @throws stubRemoteException for server errors 203 * @throws stubEASCException for unrecoverable errors 195 204 */ 196 205 protected function sendPacket($type, $data = '', array $bytes = array()) 197 206 { 198 207 $bsize = sizeof($bytes); 199 // Calculate packet length208 // calculate packet length 200 209 $length = strlen($data); 201 210 for ($i = 0; $i < $bsize; $i++) { … … 205 214 // Write packet 206 215 $packet = pack('Nc4Na*', 207 self::MAGIC_NUMBER, 208 $this->versionMajor, 209 $this->versionMinor, 210 $type, 211 false, 212 $length, 213 $data 216 self::MAGIC_NUMBER, // magic number to ensure correctness of message 217 $this->versionMajor, // version: major 218 $this->versionMinor, // version: minor 219 $type, // message type 220 false, // compression: always false, probably used in later protocol versions 221 $length, // length of data to follow 222 $data // the real data to send 214 223 ); 215 224 216 225 try { 217 $this-> _sock->write($packet);226 $this->socket->write($packet); 218 227 for ($i = 0; $i < $bsize; $i++) { 219 $bytes[$i]->writeTo($this-> _sock);228 $bytes[$i]->writeTo($this->socket); 220 229 } 221 230 222 231 $header = unpack('Nmagic/cvmajor/cvminor/ctype/ctran/Nlength', $this->readBytes(12)); 223 } catch ( IOException $e) {224 throw new RemoteException($e->getMessage(), $e);232 } catch (stubConnectionException $ce) { 233 throw new stubRemoteException($ce->getMessage(), $ce); 225 234 } 226 235 227 236 if (self::MAGIC_NUMBER != $header['magic']) { 228 $this-> _sock->close();229 throw new Error('Magic number mismatch (have: ' . $header['magic'] . ' expect: ' . self::MAGIC_NUMBER);237 $this->socket->close(); 238 throw new stubEASCException('Magic number mismatch (have: ' . $header['magic'] . ' expect: ' . self::MAGIC_NUMBER); 230 239 } 231 240 232 241 // Perform actions based on response type 233 $c tx= array('handler' => $this);242 $context = array('handler' => $this); 234 243 try { 235 244 switch ($header['type']) { 236 245 case self::MSG_VALUE: 237 $data = ByteCountedString::readFrom($this->_sock);238 return $this->serializer->unserialize(new stubPHPSerializedData($data), $c tx);246 $data = stubByteCountedString::readFrom($this->socket); 247 return $this->serializer->unserialize(new stubPHPSerializedData($data), $context); 239 248 240 249 case self::MSG_EXCEPTION: 241 $data = ByteCountedString::readFrom($this->_sock);242 $reference = $this->serializer->unserialize(new stubPHPSerializedData($data), $c tx);243 if ($reference instanceof RemoteException) {250 $data = stubByteCountedString::readFrom($this->socket); 251 $reference = $this->serializer->unserialize(new stubPHPSerializedData($data), $context); 252 if ($reference instanceof stubRemoteException) { 244 253 throw $reference; 245 } elseif ($reference instanceof ExceptionReference) { 246 throw new RemoteException($reference->getMessage(), $reference); 247 } else { 248 throw new RemoteException('lang.XPException', new XPException($this->stringOf($reference))); 254 } elseif ($reference instanceof stubExceptionReference) { 255 throw new stubRemoteException($reference->getMessage(), $reference); 249 256 } 257 258 throw new stubRemoteException('lang.XPException', new XPException($this->stringOf($reference))); 250 259 251 260 case self::MSG_ERROR: 252 $message = ByteCountedString::readFrom($this->_sock); // Not serialized!253 $this-> _sock->close();254 throw new RemoteException($message, new Error($message));261 $message = stubByteCountedString::readFrom($this->socket); // not serialized! 262 $this->socket->close(); 263 throw new stubRemoteException($message, new stubEASCException($message)); 255 264 256 265 default: 257 $data = $this->readBytes($header['length']); // Read all left-over bytes258 $this-> _sock->close();259 throw new Error('Unknown message type');266 $data = $this->readBytes($header['length']); 267 $this->socket->close(); 268 throw new stubEASCException('Unknown message type: ' . $data); 260 269 } 261 } catch ( IOException $e) {262 throw new RemoteException($e->getMessage(), $e);270 } catch (stubConnectionException $ce) { 271 throw new stubRemoteException($ce->getMessage(), $ce); 263 272 } 264 273 } … … 270 279 * @return string 271 280 */ 272 protected function readBytes($ num)281 protected function readBytes($amount) 273 282 { 274 283 $return = ''; 275 while (strlen($return) < $ num) {276 $buf = $this->_sock->readBinary($num- strlen($return));277 if (0 === strlen($buf )) {284 while (strlen($return) < $amount) { 285 $buffer = $this->socket->readBinary($amount - strlen($return)); 286 if (0 === strlen($buffer)) { 278 287 return null; 279 288 } 280 289 281 $return .= $buf ;290 $return .= $buffer; 282 291 } 283 292
