blob: 7e736d5f95710cbaddf5e26c631a4b6fa271e2bc [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
2
Mark Sleecfc01932006-09-01 22:18:16 +00003/**
Mark Slee4902c052007-03-01 00:31:30 +00004 * Copyright (c) 2006- Facebook
5 * Distributed under the Thrift Software License
6 *
7 * See accompanying file LICENSE or visit the Thrift site at:
8 * http://developers.facebook.com/thrift/
9 *
10 * @package thrift.protocol
11 * @author Mark Slee <mcslee@facebook.com>
12 */
13
14/**
Mark Slee5f8237d2006-10-26 04:57:03 +000015 * Protocol module. Contains all the types and definitions needed to implement
16 * a protocol encoder/decoder.
Mark Slee6e536442006-06-30 18:28:50 +000017 *
18 * @package thrift.protocol
19 * @author Mark Slee <mcslee@facebook.com>
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000020 * @author Aditya Agarwal <aditya@facebook.com>
Mark Slee6e536442006-06-30 18:28:50 +000021 */
Mark Slee5f8237d2006-10-26 04:57:03 +000022
Mark Slee5f8237d2006-10-26 04:57:03 +000023/**
Mark Sleedac78562007-02-21 07:35:03 +000024 * Protocol exceptions
25 */
26class TProtocolException extends TException {
27 const UNKNOWN = 0;
28 const INVALID_DATA = 1;
29 const NEGATIVE_SIZE = 2;
30 const SIZE_LIMIT = 3;
Mark Slee808454e2007-06-20 21:51:57 +000031 const BAD_VERSION = 4;
Mark Sleedac78562007-02-21 07:35:03 +000032
33 function __construct($message=null, $code=0) {
34 parent::__construct($message, $code);
35 }
36}
37
38/**
Mark Slee5f8237d2006-10-26 04:57:03 +000039 * Protocol base class module.
40 */
Mark Slee6e536442006-06-30 18:28:50 +000041abstract class TProtocol {
Mark Slee97264862007-12-20 03:23:27 +000042 // The below may seem silly, but it is to get around the problem that the
43 // "instanceof" operator can only take in a T_VARIABLE and not a T_STRING
44 // or T_CONSTANT_ENCAPSED_STRING. Using "is_a()" instead of "instanceof" is
45 // a workaround but is deprecated in PHP5. This is used in the generated
46 // deserialization code.
47 static $TBINARYPROTOCOLACCELERATED = 'TBinaryProtocolAccelerated';
Mark Slee6e536442006-06-30 18:28:50 +000048
Mark Slee5f8237d2006-10-26 04:57:03 +000049 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000050 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000051 *
52 * @var TTransport
53 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000054 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000055
56 /**
57 * Constructor
58 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000059 protected function __construct($trans) {
60 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000061 }
62
63 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000064 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000065 *
66 * @return TTransport
67 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000068 public function getTransport() {
69 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000070 }
71
Mark Slee97264862007-12-20 03:23:27 +000072 /**
Mark Sleecfc01932006-09-01 22:18:16 +000073 * Writes the message header
74 *
Mark Sleecfc01932006-09-01 22:18:16 +000075 * @param string $name Function name
76 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
77 * @param int $seqid The sequence id of this message
78 */
Mark Slee5f8237d2006-10-26 04:57:03 +000079 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000080
Mark Sleecfc01932006-09-01 22:18:16 +000081 /**
82 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000083 */
Mark Slee5f8237d2006-10-26 04:57:03 +000084 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000085
Mark Slee6e536442006-06-30 18:28:50 +000086 /**
87 * Writes a struct header.
88 *
Mark Slee6e536442006-06-30 18:28:50 +000089 * @param string $name Struct name
90 * @throws TException on write error
91 * @return int How many bytes written
92 */
Mark Slee5f8237d2006-10-26 04:57:03 +000093 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +000094
95 /**
96 * Close a struct.
97 *
Mark Slee6e536442006-06-30 18:28:50 +000098 * @throws TException on write error
99 * @return int How many bytes written
100 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000101 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000102
103 /*
104 * Starts a field.
105 *
Mark Slee6e536442006-06-30 18:28:50 +0000106 * @param string $name Field name
107 * @param int $type Field type
108 * @param int $fid Field id
109 * @throws TException on write error
110 * @return int How many bytes written
111 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000112 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000113
Mark Slee5f8237d2006-10-26 04:57:03 +0000114 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000115
Mark Slee5f8237d2006-10-26 04:57:03 +0000116 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000117
Mark Slee5f8237d2006-10-26 04:57:03 +0000118 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000119
Mark Slee5f8237d2006-10-26 04:57:03 +0000120 public abstract function writeMapEnd();
Mark Slee97264862007-12-20 03:23:27 +0000121
Mark Slee5f8237d2006-10-26 04:57:03 +0000122 public abstract function writeListBegin($elemType, $size);
Mark Slee97264862007-12-20 03:23:27 +0000123
Mark Slee5f8237d2006-10-26 04:57:03 +0000124 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000125
Mark Slee5f8237d2006-10-26 04:57:03 +0000126 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000127
Mark Slee5f8237d2006-10-26 04:57:03 +0000128 public abstract function writeSetEnd();
Mark Slee97264862007-12-20 03:23:27 +0000129
Mark Slee5f8237d2006-10-26 04:57:03 +0000130 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000131
Mark Slee5f8237d2006-10-26 04:57:03 +0000132 public abstract function writeByte($byte);
Mark Slee97264862007-12-20 03:23:27 +0000133
Mark Slee5f8237d2006-10-26 04:57:03 +0000134 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000135
Mark Slee5f8237d2006-10-26 04:57:03 +0000136 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000137
Mark Slee5f8237d2006-10-26 04:57:03 +0000138 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000139
Mark Slee5f8237d2006-10-26 04:57:03 +0000140 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000141
Mark Slee5f8237d2006-10-26 04:57:03 +0000142 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000143
Mark Sleecfc01932006-09-01 22:18:16 +0000144 /**
145 * Reads the message header
146 *
Mark Sleecfc01932006-09-01 22:18:16 +0000147 * @param string $name Function name
148 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
149 * @parem int $seqid The sequence id of this message
150 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000151 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000152
Mark Sleecfc01932006-09-01 22:18:16 +0000153 /**
154 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000155 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000156 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000157
Mark Slee5f8237d2006-10-26 04:57:03 +0000158 public abstract function readStructBegin(&$name);
Mark Slee97264862007-12-20 03:23:27 +0000159
Mark Slee5f8237d2006-10-26 04:57:03 +0000160 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000161
Mark Slee5f8237d2006-10-26 04:57:03 +0000162 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000163
Mark Slee5f8237d2006-10-26 04:57:03 +0000164 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000165
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000167
Mark Slee5f8237d2006-10-26 04:57:03 +0000168 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000169
Mark Slee5f8237d2006-10-26 04:57:03 +0000170 public abstract function readListBegin(&$elemType, &$size);
Mark Slee97264862007-12-20 03:23:27 +0000171
Mark Slee5f8237d2006-10-26 04:57:03 +0000172 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000173
Mark Slee5f8237d2006-10-26 04:57:03 +0000174 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee97264862007-12-20 03:23:27 +0000175
Mark Slee5f8237d2006-10-26 04:57:03 +0000176 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000177
Mark Slee5f8237d2006-10-26 04:57:03 +0000178 public abstract function readBool(&$bool);
Mark Slee97264862007-12-20 03:23:27 +0000179
Mark Slee5f8237d2006-10-26 04:57:03 +0000180 public abstract function readByte(&$byte);
Mark Slee97264862007-12-20 03:23:27 +0000181
Mark Slee5f8237d2006-10-26 04:57:03 +0000182 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000183
Mark Slee5f8237d2006-10-26 04:57:03 +0000184 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000185
Mark Slee5f8237d2006-10-26 04:57:03 +0000186 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000187
Mark Slee5f8237d2006-10-26 04:57:03 +0000188 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000189
Mark Slee5f8237d2006-10-26 04:57:03 +0000190 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000191
Mark Sleecfc01932006-09-01 22:18:16 +0000192 /**
193 * The skip function is a utility to parse over unrecognized date without
194 * causing corruption.
195 *
Mark Sleecfc01932006-09-01 22:18:16 +0000196 * @param TType $type What type is it
197 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000198 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000199 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000200 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000201 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000202 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000203 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000204 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000205 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000206 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000207 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000208 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000209 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000210 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000211 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000212 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000213 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000214 case TType::STRUCT:
215 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000216 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000217 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000218 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000219 if ($ftype == TType::STOP) {
220 break;
221 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000222 $result += $this->skip($ftype);
223 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000224 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000225 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000226 return $result;
227 }
228 case TType::MAP:
229 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000230 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000231 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000232 $result += $this->skip($keyType);
233 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000234 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000235 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000236 return $result;
237 }
238 case TType::SET:
239 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000240 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000241 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000242 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000243 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000244 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000245 return $result;
246 }
247 case TType::LST:
248 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000249 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000250 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000251 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000252 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000253 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000254 return $result;
255 }
256 default:
257 return 0;
258 }
259 }
Mark Slee99e2b262006-10-10 01:42:29 +0000260
261 /**
262 * Utility for skipping binary data
263 *
264 * @param TTransport $itrans TTransport object
265 * @param int $type Field type
266 */
267 public static function skipBinary($itrans, $type) {
268 switch ($type) {
269 case TType::BOOL:
270 return $itrans->readAll(1);
271 case TType::BYTE:
272 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000273 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000274 return $itrans->readAll(2);
275 case TType::I32:
276 return $itrans->readAll(4);
277 case TType::I64:
278 return $itrans->readAll(8);
279 case TType::DOUBLE:
280 return $itrans->readAll(8);
281 case TType::STRING:
282 $len = unpack('N', $itrans->readAll(4));
283 $len = $len[1];
284 if ($len > 0x7fffffff) {
285 $len = 0 - (($len - 1) ^ 0xffffffff);
286 }
287 return 4 + $itrans->readAll($len);
288 case TType::STRUCT:
289 {
290 $result = 0;
291 while (true) {
292 $ftype = 0;
293 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000294 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000295 $arr = unpack('c', $data);
296 $ftype = $arr[1];
297 if ($ftype == TType::STOP) {
298 break;
299 }
300 // I16 field id
301 $result += $itrans->readAll(2);
302 $result += self::skipBinary($itrans, $ftype);
303 }
304 return $result;
305 }
306 case TType::MAP:
307 {
308 // Ktype
309 $data = $itrans->readAll(1);
310 $arr = unpack('c', $data);
311 $ktype = $arr[1];
312 // Vtype
313 $data = $itrans->readAll(1);
314 $arr = unpack('c', $data);
315 $vtype = $arr[1];
316 // Size
317 $data = $itrans->readAll(4);
318 $arr = unpack('N', $data);
319 $size = $arr[1];
320 if ($size > 0x7fffffff) {
321 $size = 0 - (($size - 1) ^ 0xffffffff);
322 }
323 $result = 6;
324 for ($i = 0; $i < $size; $i++) {
325 $result += self::skipBinary($itrans, $ktype);
326 $result += self::skipBinary($itrans, $vtype);
327 }
328 return $result;
329 }
330 case TType::SET:
331 case TType::LST:
332 {
333 // Vtype
334 $data = $itrans->readAll(1);
335 $arr = unpack('c', $data);
336 $vtype = $arr[1];
337 // Size
338 $data = $itrans->readAll(4);
339 $arr = unpack('N', $data);
340 $size = $arr[1];
341 if ($size > 0x7fffffff) {
342 $size = 0 - (($size - 1) ^ 0xffffffff);
343 }
344 $result = 5;
345 for ($i = 0; $i < $size; $i++) {
346 $result += self::skipBinary($itrans, $vtype);
347 }
348 return $result;
349 }
350 default:
351 return 0;
Mark Slee97264862007-12-20 03:23:27 +0000352 }
Mark Slee99e2b262006-10-10 01:42:29 +0000353 }
Mark Slee6e536442006-06-30 18:28:50 +0000354}
355
Mark Slee5f8237d2006-10-26 04:57:03 +0000356/**
357 * Protocol factory creates protocol objects from transports
358 */
359interface TProtocolFactory {
360 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000361 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000362 *
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000363 * @return TProtcol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000364 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000365 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000366}
Mark Slee97264862007-12-20 03:23:27 +0000367
Mark Slee5f8237d2006-10-26 04:57:03 +0000368
Mark Slee6e536442006-06-30 18:28:50 +0000369?>