blob: 239648e7afa9b37a0cc5846926c96674b5d84e9e [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
David Reissea2cba82009-03-30 21:35:00 +00002/*
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
Mark Slee4902c052007-03-01 00:31:30 +000010 *
David Reissea2cba82009-03-30 21:35:00 +000011 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
Mark Slee4902c052007-03-01 00:31:30 +000019 *
20 * @package thrift.protocol
Mark Slee4902c052007-03-01 00:31:30 +000021 */
22
David Reissea2cba82009-03-30 21:35:00 +000023
Mark Slee4902c052007-03-01 00:31:30 +000024/**
Mark Slee5f8237d2006-10-26 04:57:03 +000025 * Protocol module. Contains all the types and definitions needed to implement
26 * a protocol encoder/decoder.
Mark Slee6e536442006-06-30 18:28:50 +000027 *
28 * @package thrift.protocol
Mark Slee6e536442006-06-30 18:28:50 +000029 */
Mark Slee5f8237d2006-10-26 04:57:03 +000030
Mark Slee5f8237d2006-10-26 04:57:03 +000031/**
Mark Sleedac78562007-02-21 07:35:03 +000032 * Protocol exceptions
33 */
34class TProtocolException extends TException {
35 const UNKNOWN = 0;
36 const INVALID_DATA = 1;
37 const NEGATIVE_SIZE = 2;
38 const SIZE_LIMIT = 3;
Mark Slee808454e2007-06-20 21:51:57 +000039 const BAD_VERSION = 4;
Mark Sleedac78562007-02-21 07:35:03 +000040
41 function __construct($message=null, $code=0) {
42 parent::__construct($message, $code);
43 }
44}
45
46/**
Mark Slee5f8237d2006-10-26 04:57:03 +000047 * Protocol base class module.
48 */
Mark Slee6e536442006-06-30 18:28:50 +000049abstract class TProtocol {
Mark Slee97264862007-12-20 03:23:27 +000050 // The below may seem silly, but it is to get around the problem that the
51 // "instanceof" operator can only take in a T_VARIABLE and not a T_STRING
52 // or T_CONSTANT_ENCAPSED_STRING. Using "is_a()" instead of "instanceof" is
53 // a workaround but is deprecated in PHP5. This is used in the generated
54 // deserialization code.
55 static $TBINARYPROTOCOLACCELERATED = 'TBinaryProtocolAccelerated';
Mark Slee6e536442006-06-30 18:28:50 +000056
Mark Slee5f8237d2006-10-26 04:57:03 +000057 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000058 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000059 *
60 * @var TTransport
61 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000062 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000063
64 /**
65 * Constructor
66 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000067 protected function __construct($trans) {
68 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000069 }
70
71 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000072 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000073 *
74 * @return TTransport
75 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000076 public function getTransport() {
77 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000078 }
79
Mark Slee97264862007-12-20 03:23:27 +000080 /**
Mark Sleecfc01932006-09-01 22:18:16 +000081 * Writes the message header
82 *
Mark Sleecfc01932006-09-01 22:18:16 +000083 * @param string $name Function name
84 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
85 * @param int $seqid The sequence id of this message
86 */
Mark Slee5f8237d2006-10-26 04:57:03 +000087 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000088
Mark Sleecfc01932006-09-01 22:18:16 +000089 /**
90 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000091 */
Mark Slee5f8237d2006-10-26 04:57:03 +000092 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000093
Mark Slee6e536442006-06-30 18:28:50 +000094 /**
95 * Writes a struct header.
96 *
Mark Slee6e536442006-06-30 18:28:50 +000097 * @param string $name Struct name
98 * @throws TException on write error
99 * @return int How many bytes written
100 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000101 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000102
103 /**
104 * Close a struct.
105 *
Mark Slee6e536442006-06-30 18:28:50 +0000106 * @throws TException on write error
107 * @return int How many bytes written
108 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000109 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000110
111 /*
112 * Starts a field.
113 *
Mark Slee6e536442006-06-30 18:28:50 +0000114 * @param string $name Field name
115 * @param int $type Field type
116 * @param int $fid Field id
117 * @throws TException on write error
118 * @return int How many bytes written
119 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000120 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000121
Mark Slee5f8237d2006-10-26 04:57:03 +0000122 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000123
Mark Slee5f8237d2006-10-26 04:57:03 +0000124 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000125
Mark Slee5f8237d2006-10-26 04:57:03 +0000126 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000127
Mark Slee5f8237d2006-10-26 04:57:03 +0000128 public abstract function writeMapEnd();
Mark Slee97264862007-12-20 03:23:27 +0000129
Mark Slee5f8237d2006-10-26 04:57:03 +0000130 public abstract function writeListBegin($elemType, $size);
Mark Slee97264862007-12-20 03:23:27 +0000131
Mark Slee5f8237d2006-10-26 04:57:03 +0000132 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000133
Mark Slee5f8237d2006-10-26 04:57:03 +0000134 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000135
Mark Slee5f8237d2006-10-26 04:57:03 +0000136 public abstract function writeSetEnd();
Mark Slee97264862007-12-20 03:23:27 +0000137
Mark Slee5f8237d2006-10-26 04:57:03 +0000138 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000139
Mark Slee5f8237d2006-10-26 04:57:03 +0000140 public abstract function writeByte($byte);
Mark Slee97264862007-12-20 03:23:27 +0000141
Mark Slee5f8237d2006-10-26 04:57:03 +0000142 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000143
Mark Slee5f8237d2006-10-26 04:57:03 +0000144 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000145
Mark Slee5f8237d2006-10-26 04:57:03 +0000146 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000147
Mark Slee5f8237d2006-10-26 04:57:03 +0000148 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000149
Mark Slee5f8237d2006-10-26 04:57:03 +0000150 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000151
Mark Sleecfc01932006-09-01 22:18:16 +0000152 /**
153 * Reads the message header
154 *
Mark Sleecfc01932006-09-01 22:18:16 +0000155 * @param string $name Function name
156 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
157 * @parem int $seqid The sequence id of this message
158 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000159 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000160
Mark Sleecfc01932006-09-01 22:18:16 +0000161 /**
162 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000163 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000164 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000165
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public abstract function readStructBegin(&$name);
Mark Slee97264862007-12-20 03:23:27 +0000167
Mark Slee5f8237d2006-10-26 04:57:03 +0000168 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000169
Mark Slee5f8237d2006-10-26 04:57:03 +0000170 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000171
Mark Slee5f8237d2006-10-26 04:57:03 +0000172 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000173
Mark Slee5f8237d2006-10-26 04:57:03 +0000174 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000175
Mark Slee5f8237d2006-10-26 04:57:03 +0000176 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000177
Mark Slee5f8237d2006-10-26 04:57:03 +0000178 public abstract function readListBegin(&$elemType, &$size);
Mark Slee97264862007-12-20 03:23:27 +0000179
Mark Slee5f8237d2006-10-26 04:57:03 +0000180 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000181
Mark Slee5f8237d2006-10-26 04:57:03 +0000182 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee97264862007-12-20 03:23:27 +0000183
Mark Slee5f8237d2006-10-26 04:57:03 +0000184 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000185
Mark Slee5f8237d2006-10-26 04:57:03 +0000186 public abstract function readBool(&$bool);
Mark Slee97264862007-12-20 03:23:27 +0000187
Mark Slee5f8237d2006-10-26 04:57:03 +0000188 public abstract function readByte(&$byte);
Mark Slee97264862007-12-20 03:23:27 +0000189
Mark Slee5f8237d2006-10-26 04:57:03 +0000190 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000191
Mark Slee5f8237d2006-10-26 04:57:03 +0000192 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000193
Mark Slee5f8237d2006-10-26 04:57:03 +0000194 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000195
Mark Slee5f8237d2006-10-26 04:57:03 +0000196 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000197
Mark Slee5f8237d2006-10-26 04:57:03 +0000198 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000199
Mark Sleecfc01932006-09-01 22:18:16 +0000200 /**
201 * The skip function is a utility to parse over unrecognized date without
202 * causing corruption.
203 *
Mark Sleecfc01932006-09-01 22:18:16 +0000204 * @param TType $type What type is it
205 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000206 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000207 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000208 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000209 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000210 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000211 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000212 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000213 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000214 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000215 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000216 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000217 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000218 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000219 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000220 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000221 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000222 case TType::STRUCT:
223 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000224 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000225 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000226 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000227 if ($ftype == TType::STOP) {
228 break;
229 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000230 $result += $this->skip($ftype);
231 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000232 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000233 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000234 return $result;
235 }
236 case TType::MAP:
237 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000238 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000239 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000240 $result += $this->skip($keyType);
241 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000242 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000243 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000244 return $result;
245 }
246 case TType::SET:
247 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000248 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000249 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000250 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000251 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000252 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000253 return $result;
254 }
255 case TType::LST:
256 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000257 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000258 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000259 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000260 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000261 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000262 return $result;
263 }
264 default:
Jake Farrell51700642011-10-07 00:17:25 +0000265 throw new TProtocolException('Unknown field type: '.$type,
266 TProtocolException::INVALID_DATA);
Mark Slee6e536442006-06-30 18:28:50 +0000267 }
268 }
Mark Slee99e2b262006-10-10 01:42:29 +0000269
270 /**
271 * Utility for skipping binary data
272 *
273 * @param TTransport $itrans TTransport object
274 * @param int $type Field type
275 */
276 public static function skipBinary($itrans, $type) {
277 switch ($type) {
278 case TType::BOOL:
279 return $itrans->readAll(1);
280 case TType::BYTE:
281 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000282 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000283 return $itrans->readAll(2);
284 case TType::I32:
285 return $itrans->readAll(4);
286 case TType::I64:
287 return $itrans->readAll(8);
288 case TType::DOUBLE:
289 return $itrans->readAll(8);
290 case TType::STRING:
291 $len = unpack('N', $itrans->readAll(4));
292 $len = $len[1];
293 if ($len > 0x7fffffff) {
294 $len = 0 - (($len - 1) ^ 0xffffffff);
295 }
296 return 4 + $itrans->readAll($len);
297 case TType::STRUCT:
298 {
299 $result = 0;
300 while (true) {
301 $ftype = 0;
302 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000303 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000304 $arr = unpack('c', $data);
305 $ftype = $arr[1];
306 if ($ftype == TType::STOP) {
307 break;
308 }
309 // I16 field id
310 $result += $itrans->readAll(2);
311 $result += self::skipBinary($itrans, $ftype);
312 }
313 return $result;
314 }
315 case TType::MAP:
316 {
317 // Ktype
318 $data = $itrans->readAll(1);
319 $arr = unpack('c', $data);
320 $ktype = $arr[1];
321 // Vtype
322 $data = $itrans->readAll(1);
323 $arr = unpack('c', $data);
324 $vtype = $arr[1];
325 // Size
326 $data = $itrans->readAll(4);
327 $arr = unpack('N', $data);
328 $size = $arr[1];
329 if ($size > 0x7fffffff) {
330 $size = 0 - (($size - 1) ^ 0xffffffff);
331 }
332 $result = 6;
333 for ($i = 0; $i < $size; $i++) {
334 $result += self::skipBinary($itrans, $ktype);
335 $result += self::skipBinary($itrans, $vtype);
336 }
337 return $result;
338 }
339 case TType::SET:
340 case TType::LST:
341 {
342 // Vtype
343 $data = $itrans->readAll(1);
344 $arr = unpack('c', $data);
345 $vtype = $arr[1];
346 // Size
347 $data = $itrans->readAll(4);
348 $arr = unpack('N', $data);
349 $size = $arr[1];
350 if ($size > 0x7fffffff) {
351 $size = 0 - (($size - 1) ^ 0xffffffff);
352 }
353 $result = 5;
354 for ($i = 0; $i < $size; $i++) {
355 $result += self::skipBinary($itrans, $vtype);
356 }
357 return $result;
358 }
359 default:
Jake Farrell51700642011-10-07 00:17:25 +0000360 throw new TProtocolException('Unknown field type: '.$type,
361 TProtocolException::INVALID_DATA);
Mark Slee97264862007-12-20 03:23:27 +0000362 }
Mark Slee99e2b262006-10-10 01:42:29 +0000363 }
Mark Slee6e536442006-06-30 18:28:50 +0000364}
365
Mark Slee5f8237d2006-10-26 04:57:03 +0000366/**
367 * Protocol factory creates protocol objects from transports
368 */
369interface TProtocolFactory {
370 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000371 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000372 *
Bryan Duxbury17115d72010-08-12 16:59:19 +0000373 * @return TProtocol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000374 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000375 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000376}