blob: deddfa256a347f286de947ecd2282aa4eaebad32 [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;
31
32 function __construct($message=null, $code=0) {
33 parent::__construct($message, $code);
34 }
35}
36
37/**
Mark Slee5f8237d2006-10-26 04:57:03 +000038 * Protocol base class module.
39 */
Mark Slee6e536442006-06-30 18:28:50 +000040abstract class TProtocol {
41
Mark Slee5f8237d2006-10-26 04:57:03 +000042 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000043 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000044 *
45 * @var TTransport
46 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000047 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000048
49 /**
50 * Constructor
51 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000052 protected function __construct($trans) {
53 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000054 }
55
56 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000057 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000058 *
59 * @return TTransport
60 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000061 public function getTransport() {
62 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000063 }
64
Mark Sleecfc01932006-09-01 22:18:16 +000065 /**
66 * Writes the message header
67 *
Mark Sleecfc01932006-09-01 22:18:16 +000068 * @param string $name Function name
69 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
70 * @param int $seqid The sequence id of this message
71 */
Mark Slee5f8237d2006-10-26 04:57:03 +000072 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000073
Mark Sleecfc01932006-09-01 22:18:16 +000074 /**
75 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000076 */
Mark Slee5f8237d2006-10-26 04:57:03 +000077 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000078
Mark Slee6e536442006-06-30 18:28:50 +000079 /**
80 * Writes a struct header.
81 *
Mark Slee6e536442006-06-30 18:28:50 +000082 * @param string $name Struct name
83 * @throws TException on write error
84 * @return int How many bytes written
85 */
Mark Slee5f8237d2006-10-26 04:57:03 +000086 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +000087
88 /**
89 * Close a struct.
90 *
Mark Slee6e536442006-06-30 18:28:50 +000091 * @throws TException on write error
92 * @return int How many bytes written
93 */
Mark Slee5f8237d2006-10-26 04:57:03 +000094 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +000095
96 /*
97 * Starts a field.
98 *
Mark Slee6e536442006-06-30 18:28:50 +000099 * @param string $name Field name
100 * @param int $type Field type
101 * @param int $fid Field id
102 * @throws TException on write error
103 * @return int How many bytes written
104 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000105 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000106
Mark Slee5f8237d2006-10-26 04:57:03 +0000107 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000108
Mark Slee5f8237d2006-10-26 04:57:03 +0000109 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000110
Mark Slee5f8237d2006-10-26 04:57:03 +0000111 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000112
Mark Slee5f8237d2006-10-26 04:57:03 +0000113 public abstract function writeMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000114
Mark Slee5f8237d2006-10-26 04:57:03 +0000115 public abstract function writeListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000116
Mark Slee5f8237d2006-10-26 04:57:03 +0000117 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000118
Mark Slee5f8237d2006-10-26 04:57:03 +0000119 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000120
Mark Slee5f8237d2006-10-26 04:57:03 +0000121 public abstract function writeSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000122
Mark Slee5f8237d2006-10-26 04:57:03 +0000123 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000124
Mark Slee5f8237d2006-10-26 04:57:03 +0000125 public abstract function writeByte($byte);
Mark Slee6e536442006-06-30 18:28:50 +0000126
Mark Slee5f8237d2006-10-26 04:57:03 +0000127 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000128
Mark Slee5f8237d2006-10-26 04:57:03 +0000129 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000130
Mark Slee5f8237d2006-10-26 04:57:03 +0000131 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000132
Mark Slee5f8237d2006-10-26 04:57:03 +0000133 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000134
Mark Slee5f8237d2006-10-26 04:57:03 +0000135 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000136
Mark Sleecfc01932006-09-01 22:18:16 +0000137 /**
138 * Reads the message header
139 *
Mark Sleecfc01932006-09-01 22:18:16 +0000140 * @param string $name Function name
141 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
142 * @parem int $seqid The sequence id of this message
143 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000144 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000145
Mark Sleecfc01932006-09-01 22:18:16 +0000146 /**
147 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000148 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000149 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000150
Mark Slee5f8237d2006-10-26 04:57:03 +0000151 public abstract function readStructBegin(&$name);
Mark Slee6e536442006-06-30 18:28:50 +0000152
Mark Slee5f8237d2006-10-26 04:57:03 +0000153 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000154
Mark Slee5f8237d2006-10-26 04:57:03 +0000155 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000156
Mark Slee5f8237d2006-10-26 04:57:03 +0000157 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000158
Mark Slee5f8237d2006-10-26 04:57:03 +0000159 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000160
Mark Slee5f8237d2006-10-26 04:57:03 +0000161 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000162
Mark Slee5f8237d2006-10-26 04:57:03 +0000163 public abstract function readListBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000164
Mark Slee5f8237d2006-10-26 04:57:03 +0000165 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000166
Mark Slee5f8237d2006-10-26 04:57:03 +0000167 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000168
Mark Slee5f8237d2006-10-26 04:57:03 +0000169 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000170
Mark Slee5f8237d2006-10-26 04:57:03 +0000171 public abstract function readBool(&$bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000172
Mark Slee5f8237d2006-10-26 04:57:03 +0000173 public abstract function readByte(&$byte);
Mark Slee6e536442006-06-30 18:28:50 +0000174
Mark Slee5f8237d2006-10-26 04:57:03 +0000175 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000176
Mark Slee5f8237d2006-10-26 04:57:03 +0000177 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000178
Mark Slee5f8237d2006-10-26 04:57:03 +0000179 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000180
Mark Slee5f8237d2006-10-26 04:57:03 +0000181 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000182
Mark Slee5f8237d2006-10-26 04:57:03 +0000183 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000184
Mark Sleecfc01932006-09-01 22:18:16 +0000185 /**
186 * The skip function is a utility to parse over unrecognized date without
187 * causing corruption.
188 *
Mark Sleecfc01932006-09-01 22:18:16 +0000189 * @param TType $type What type is it
190 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000191 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000192 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000193 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000194 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000195 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000196 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000197 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000198 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000199 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000200 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000201 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000202 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000203 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000204 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000205 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000206 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000207 case TType::STRUCT:
208 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000209 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000210 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000211 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000212 if ($ftype == TType::STOP) {
213 break;
214 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000215 $result += $this->skip($ftype);
216 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000217 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000218 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000219 return $result;
220 }
221 case TType::MAP:
222 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000223 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000224 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000225 $result += $this->skip($keyType);
226 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000227 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000228 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000229 return $result;
230 }
231 case TType::SET:
232 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000233 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000234 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000235 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000236 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000237 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000238 return $result;
239 }
240 case TType::LST:
241 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000242 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000243 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000244 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000245 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000246 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000247 return $result;
248 }
249 default:
250 return 0;
251 }
252 }
Mark Slee99e2b262006-10-10 01:42:29 +0000253
254 /**
255 * Utility for skipping binary data
256 *
257 * @param TTransport $itrans TTransport object
258 * @param int $type Field type
259 */
260 public static function skipBinary($itrans, $type) {
261 switch ($type) {
262 case TType::BOOL:
263 return $itrans->readAll(1);
264 case TType::BYTE:
265 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000266 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000267 return $itrans->readAll(2);
268 case TType::I32:
269 return $itrans->readAll(4);
270 case TType::I64:
271 return $itrans->readAll(8);
272 case TType::DOUBLE:
273 return $itrans->readAll(8);
274 case TType::STRING:
275 $len = unpack('N', $itrans->readAll(4));
276 $len = $len[1];
277 if ($len > 0x7fffffff) {
278 $len = 0 - (($len - 1) ^ 0xffffffff);
279 }
280 return 4 + $itrans->readAll($len);
281 case TType::STRUCT:
282 {
283 $result = 0;
284 while (true) {
285 $ftype = 0;
286 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000287 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000288 $arr = unpack('c', $data);
289 $ftype = $arr[1];
290 if ($ftype == TType::STOP) {
291 break;
292 }
293 // I16 field id
294 $result += $itrans->readAll(2);
295 $result += self::skipBinary($itrans, $ftype);
296 }
297 return $result;
298 }
299 case TType::MAP:
300 {
301 // Ktype
302 $data = $itrans->readAll(1);
303 $arr = unpack('c', $data);
304 $ktype = $arr[1];
305 // Vtype
306 $data = $itrans->readAll(1);
307 $arr = unpack('c', $data);
308 $vtype = $arr[1];
309 // Size
310 $data = $itrans->readAll(4);
311 $arr = unpack('N', $data);
312 $size = $arr[1];
313 if ($size > 0x7fffffff) {
314 $size = 0 - (($size - 1) ^ 0xffffffff);
315 }
316 $result = 6;
317 for ($i = 0; $i < $size; $i++) {
318 $result += self::skipBinary($itrans, $ktype);
319 $result += self::skipBinary($itrans, $vtype);
320 }
321 return $result;
322 }
323 case TType::SET:
324 case TType::LST:
325 {
326 // Vtype
327 $data = $itrans->readAll(1);
328 $arr = unpack('c', $data);
329 $vtype = $arr[1];
330 // Size
331 $data = $itrans->readAll(4);
332 $arr = unpack('N', $data);
333 $size = $arr[1];
334 if ($size > 0x7fffffff) {
335 $size = 0 - (($size - 1) ^ 0xffffffff);
336 }
337 $result = 5;
338 for ($i = 0; $i < $size; $i++) {
339 $result += self::skipBinary($itrans, $vtype);
340 }
341 return $result;
342 }
343 default:
344 return 0;
345 }
346 }
Mark Slee6e536442006-06-30 18:28:50 +0000347}
348
Mark Slee5f8237d2006-10-26 04:57:03 +0000349/**
350 * Protocol factory creates protocol objects from transports
351 */
352interface TProtocolFactory {
353 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000354 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000355 *
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000356 * @return TProtcol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000357 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000358 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000359}
360
361
Mark Slee6e536442006-06-30 18:28:50 +0000362?>