blob: 658e54cca6ba795b9e69d4f4374c7fc2b60d5343 [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 {
42
Mark Slee5f8237d2006-10-26 04:57:03 +000043 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000044 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000045 *
46 * @var TTransport
47 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000048 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000049
50 /**
51 * Constructor
52 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000053 protected function __construct($trans) {
54 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000055 }
56
57 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000058 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000059 *
60 * @return TTransport
61 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000062 public function getTransport() {
63 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000064 }
65
Mark Sleecfc01932006-09-01 22:18:16 +000066 /**
67 * Writes the message header
68 *
Mark Sleecfc01932006-09-01 22:18:16 +000069 * @param string $name Function name
70 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
71 * @param int $seqid The sequence id of this message
72 */
Mark Slee5f8237d2006-10-26 04:57:03 +000073 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000074
Mark Sleecfc01932006-09-01 22:18:16 +000075 /**
76 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000077 */
Mark Slee5f8237d2006-10-26 04:57:03 +000078 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000079
Mark Slee6e536442006-06-30 18:28:50 +000080 /**
81 * Writes a struct header.
82 *
Mark Slee6e536442006-06-30 18:28:50 +000083 * @param string $name Struct name
84 * @throws TException on write error
85 * @return int How many bytes written
86 */
Mark Slee5f8237d2006-10-26 04:57:03 +000087 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +000088
89 /**
90 * Close a struct.
91 *
Mark Slee6e536442006-06-30 18:28:50 +000092 * @throws TException on write error
93 * @return int How many bytes written
94 */
Mark Slee5f8237d2006-10-26 04:57:03 +000095 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +000096
97 /*
98 * Starts a field.
99 *
Mark Slee6e536442006-06-30 18:28:50 +0000100 * @param string $name Field name
101 * @param int $type Field type
102 * @param int $fid Field id
103 * @throws TException on write error
104 * @return int How many bytes written
105 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000106 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000107
Mark Slee5f8237d2006-10-26 04:57:03 +0000108 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000109
Mark Slee5f8237d2006-10-26 04:57:03 +0000110 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000111
Mark Slee5f8237d2006-10-26 04:57:03 +0000112 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000113
Mark Slee5f8237d2006-10-26 04:57:03 +0000114 public abstract function writeMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000115
Mark Slee5f8237d2006-10-26 04:57:03 +0000116 public abstract function writeListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000117
Mark Slee5f8237d2006-10-26 04:57:03 +0000118 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000119
Mark Slee5f8237d2006-10-26 04:57:03 +0000120 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000121
Mark Slee5f8237d2006-10-26 04:57:03 +0000122 public abstract function writeSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000123
Mark Slee5f8237d2006-10-26 04:57:03 +0000124 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000125
Mark Slee5f8237d2006-10-26 04:57:03 +0000126 public abstract function writeByte($byte);
Mark Slee6e536442006-06-30 18:28:50 +0000127
Mark Slee5f8237d2006-10-26 04:57:03 +0000128 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000129
Mark Slee5f8237d2006-10-26 04:57:03 +0000130 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000131
Mark Slee5f8237d2006-10-26 04:57:03 +0000132 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000133
Mark Slee5f8237d2006-10-26 04:57:03 +0000134 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000135
Mark Slee5f8237d2006-10-26 04:57:03 +0000136 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000137
Mark Sleecfc01932006-09-01 22:18:16 +0000138 /**
139 * Reads the message header
140 *
Mark Sleecfc01932006-09-01 22:18:16 +0000141 * @param string $name Function name
142 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
143 * @parem int $seqid The sequence id of this message
144 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000145 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000146
Mark Sleecfc01932006-09-01 22:18:16 +0000147 /**
148 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000149 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000150 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000151
Mark Slee5f8237d2006-10-26 04:57:03 +0000152 public abstract function readStructBegin(&$name);
Mark Slee6e536442006-06-30 18:28:50 +0000153
Mark Slee5f8237d2006-10-26 04:57:03 +0000154 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000155
Mark Slee5f8237d2006-10-26 04:57:03 +0000156 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000157
Mark Slee5f8237d2006-10-26 04:57:03 +0000158 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000159
Mark Slee5f8237d2006-10-26 04:57:03 +0000160 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000161
Mark Slee5f8237d2006-10-26 04:57:03 +0000162 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000163
Mark Slee5f8237d2006-10-26 04:57:03 +0000164 public abstract function readListBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000165
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000167
Mark Slee5f8237d2006-10-26 04:57:03 +0000168 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000169
Mark Slee5f8237d2006-10-26 04:57:03 +0000170 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000171
Mark Slee5f8237d2006-10-26 04:57:03 +0000172 public abstract function readBool(&$bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000173
Mark Slee5f8237d2006-10-26 04:57:03 +0000174 public abstract function readByte(&$byte);
Mark Slee6e536442006-06-30 18:28:50 +0000175
Mark Slee5f8237d2006-10-26 04:57:03 +0000176 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000177
Mark Slee5f8237d2006-10-26 04:57:03 +0000178 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000179
Mark Slee5f8237d2006-10-26 04:57:03 +0000180 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000181
Mark Slee5f8237d2006-10-26 04:57:03 +0000182 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000183
Mark Slee5f8237d2006-10-26 04:57:03 +0000184 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000185
Mark Sleecfc01932006-09-01 22:18:16 +0000186 /**
187 * The skip function is a utility to parse over unrecognized date without
188 * causing corruption.
189 *
Mark Sleecfc01932006-09-01 22:18:16 +0000190 * @param TType $type What type is it
191 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000192 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000193 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000194 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000195 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000196 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000197 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000198 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000199 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000200 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000201 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000202 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000203 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000204 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000205 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000206 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000207 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000208 case TType::STRUCT:
209 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000210 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000211 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000212 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000213 if ($ftype == TType::STOP) {
214 break;
215 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000216 $result += $this->skip($ftype);
217 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000218 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000219 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000220 return $result;
221 }
222 case TType::MAP:
223 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000224 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000225 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000226 $result += $this->skip($keyType);
227 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000228 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000229 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000230 return $result;
231 }
232 case TType::SET:
233 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000234 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000235 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000236 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000237 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000238 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000239 return $result;
240 }
241 case TType::LST:
242 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000243 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000244 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000245 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000246 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000247 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000248 return $result;
249 }
250 default:
251 return 0;
252 }
253 }
Mark Slee99e2b262006-10-10 01:42:29 +0000254
255 /**
256 * Utility for skipping binary data
257 *
258 * @param TTransport $itrans TTransport object
259 * @param int $type Field type
260 */
261 public static function skipBinary($itrans, $type) {
262 switch ($type) {
263 case TType::BOOL:
264 return $itrans->readAll(1);
265 case TType::BYTE:
266 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000267 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000268 return $itrans->readAll(2);
269 case TType::I32:
270 return $itrans->readAll(4);
271 case TType::I64:
272 return $itrans->readAll(8);
273 case TType::DOUBLE:
274 return $itrans->readAll(8);
275 case TType::STRING:
276 $len = unpack('N', $itrans->readAll(4));
277 $len = $len[1];
278 if ($len > 0x7fffffff) {
279 $len = 0 - (($len - 1) ^ 0xffffffff);
280 }
281 return 4 + $itrans->readAll($len);
282 case TType::STRUCT:
283 {
284 $result = 0;
285 while (true) {
286 $ftype = 0;
287 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000288 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000289 $arr = unpack('c', $data);
290 $ftype = $arr[1];
291 if ($ftype == TType::STOP) {
292 break;
293 }
294 // I16 field id
295 $result += $itrans->readAll(2);
296 $result += self::skipBinary($itrans, $ftype);
297 }
298 return $result;
299 }
300 case TType::MAP:
301 {
302 // Ktype
303 $data = $itrans->readAll(1);
304 $arr = unpack('c', $data);
305 $ktype = $arr[1];
306 // Vtype
307 $data = $itrans->readAll(1);
308 $arr = unpack('c', $data);
309 $vtype = $arr[1];
310 // Size
311 $data = $itrans->readAll(4);
312 $arr = unpack('N', $data);
313 $size = $arr[1];
314 if ($size > 0x7fffffff) {
315 $size = 0 - (($size - 1) ^ 0xffffffff);
316 }
317 $result = 6;
318 for ($i = 0; $i < $size; $i++) {
319 $result += self::skipBinary($itrans, $ktype);
320 $result += self::skipBinary($itrans, $vtype);
321 }
322 return $result;
323 }
324 case TType::SET:
325 case TType::LST:
326 {
327 // Vtype
328 $data = $itrans->readAll(1);
329 $arr = unpack('c', $data);
330 $vtype = $arr[1];
331 // Size
332 $data = $itrans->readAll(4);
333 $arr = unpack('N', $data);
334 $size = $arr[1];
335 if ($size > 0x7fffffff) {
336 $size = 0 - (($size - 1) ^ 0xffffffff);
337 }
338 $result = 5;
339 for ($i = 0; $i < $size; $i++) {
340 $result += self::skipBinary($itrans, $vtype);
341 }
342 return $result;
343 }
344 default:
345 return 0;
346 }
347 }
Mark Slee6e536442006-06-30 18:28:50 +0000348}
349
Mark Slee5f8237d2006-10-26 04:57:03 +0000350/**
351 * Protocol factory creates protocol objects from transports
352 */
353interface TProtocolFactory {
354 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000355 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000356 *
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000357 * @return TProtcol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000358 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000359 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000360}
361
362
Mark Slee6e536442006-06-30 18:28:50 +0000363?>