blob: 63e93081ffb6accb87735ea4f1b8b6791977a9eb [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
2
Mark Sleecfc01932006-09-01 22:18:16 +00003/**
Mark Slee5f8237d2006-10-26 04:57:03 +00004 * Protocol module. Contains all the types and definitions needed to implement
5 * a protocol encoder/decoder.
Mark Slee6e536442006-06-30 18:28:50 +00006 *
7 * @package thrift.protocol
8 * @author Mark Slee <mcslee@facebook.com>
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +00009 * @author Aditya Agarwal <aditya@facebook.com>
Mark Slee6e536442006-06-30 18:28:50 +000010 */
Mark Slee5f8237d2006-10-26 04:57:03 +000011
Mark Slee5f8237d2006-10-26 04:57:03 +000012/**
Mark Sleedac78562007-02-21 07:35:03 +000013 * Protocol exceptions
14 */
15class TProtocolException extends TException {
16 const UNKNOWN = 0;
17 const INVALID_DATA = 1;
18 const NEGATIVE_SIZE = 2;
19 const SIZE_LIMIT = 3;
20
21 function __construct($message=null, $code=0) {
22 parent::__construct($message, $code);
23 }
24}
25
26/**
Mark Slee5f8237d2006-10-26 04:57:03 +000027 * Protocol base class module.
28 */
Mark Slee6e536442006-06-30 18:28:50 +000029abstract class TProtocol {
30
Mark Slee5f8237d2006-10-26 04:57:03 +000031 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000032 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000033 *
34 * @var TTransport
35 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000036 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000037
38 /**
39 * Constructor
40 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000041 protected function __construct($trans) {
42 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000043 }
44
45 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000046 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000047 *
48 * @return TTransport
49 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000050 public function getTransport() {
51 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000052 }
53
Mark Sleecfc01932006-09-01 22:18:16 +000054 /**
55 * Writes the message header
56 *
Mark Sleecfc01932006-09-01 22:18:16 +000057 * @param string $name Function name
58 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
59 * @param int $seqid The sequence id of this message
60 */
Mark Slee5f8237d2006-10-26 04:57:03 +000061 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000062
Mark Sleecfc01932006-09-01 22:18:16 +000063 /**
64 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000065 */
Mark Slee5f8237d2006-10-26 04:57:03 +000066 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000067
Mark Slee6e536442006-06-30 18:28:50 +000068 /**
69 * Writes a struct header.
70 *
Mark Slee6e536442006-06-30 18:28:50 +000071 * @param string $name Struct name
72 * @throws TException on write error
73 * @return int How many bytes written
74 */
Mark Slee5f8237d2006-10-26 04:57:03 +000075 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +000076
77 /**
78 * Close a struct.
79 *
Mark Slee6e536442006-06-30 18:28:50 +000080 * @throws TException on write error
81 * @return int How many bytes written
82 */
Mark Slee5f8237d2006-10-26 04:57:03 +000083 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +000084
85 /*
86 * Starts a field.
87 *
Mark Slee6e536442006-06-30 18:28:50 +000088 * @param string $name Field name
89 * @param int $type Field type
90 * @param int $fid Field id
91 * @throws TException on write error
92 * @return int How many bytes written
93 */
Mark Slee5f8237d2006-10-26 04:57:03 +000094 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +000095
Mark Slee5f8237d2006-10-26 04:57:03 +000096 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +000097
Mark Slee5f8237d2006-10-26 04:57:03 +000098 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +000099
Mark Slee5f8237d2006-10-26 04:57:03 +0000100 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000101
Mark Slee5f8237d2006-10-26 04:57:03 +0000102 public abstract function writeMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000103
Mark Slee5f8237d2006-10-26 04:57:03 +0000104 public abstract function writeListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000105
Mark Slee5f8237d2006-10-26 04:57:03 +0000106 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000107
Mark Slee5f8237d2006-10-26 04:57:03 +0000108 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000109
Mark Slee5f8237d2006-10-26 04:57:03 +0000110 public abstract function writeSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000111
Mark Slee5f8237d2006-10-26 04:57:03 +0000112 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000113
Mark Slee5f8237d2006-10-26 04:57:03 +0000114 public abstract function writeByte($byte);
Mark Slee6e536442006-06-30 18:28:50 +0000115
Mark Slee5f8237d2006-10-26 04:57:03 +0000116 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000117
Mark Slee5f8237d2006-10-26 04:57:03 +0000118 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000119
Mark Slee5f8237d2006-10-26 04:57:03 +0000120 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000121
Mark Slee5f8237d2006-10-26 04:57:03 +0000122 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000123
Mark Slee5f8237d2006-10-26 04:57:03 +0000124 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000125
Mark Sleecfc01932006-09-01 22:18:16 +0000126 /**
127 * Reads the message header
128 *
Mark Sleecfc01932006-09-01 22:18:16 +0000129 * @param string $name Function name
130 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
131 * @parem int $seqid The sequence id of this message
132 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000133 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000134
Mark Sleecfc01932006-09-01 22:18:16 +0000135 /**
136 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000137 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000138 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000139
Mark Slee5f8237d2006-10-26 04:57:03 +0000140 public abstract function readStructBegin(&$name);
Mark Slee6e536442006-06-30 18:28:50 +0000141
Mark Slee5f8237d2006-10-26 04:57:03 +0000142 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000143
Mark Slee5f8237d2006-10-26 04:57:03 +0000144 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000145
Mark Slee5f8237d2006-10-26 04:57:03 +0000146 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000147
Mark Slee5f8237d2006-10-26 04:57:03 +0000148 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000149
Mark Slee5f8237d2006-10-26 04:57:03 +0000150 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000151
Mark Slee5f8237d2006-10-26 04:57:03 +0000152 public abstract function readListBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000153
Mark Slee5f8237d2006-10-26 04:57:03 +0000154 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000155
Mark Slee5f8237d2006-10-26 04:57:03 +0000156 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000157
Mark Slee5f8237d2006-10-26 04:57:03 +0000158 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000159
Mark Slee5f8237d2006-10-26 04:57:03 +0000160 public abstract function readBool(&$bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000161
Mark Slee5f8237d2006-10-26 04:57:03 +0000162 public abstract function readByte(&$byte);
Mark Slee6e536442006-06-30 18:28:50 +0000163
Mark Slee5f8237d2006-10-26 04:57:03 +0000164 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000165
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000167
Mark Slee5f8237d2006-10-26 04:57:03 +0000168 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000169
Mark Slee5f8237d2006-10-26 04:57:03 +0000170 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000171
Mark Slee5f8237d2006-10-26 04:57:03 +0000172 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000173
Mark Sleecfc01932006-09-01 22:18:16 +0000174 /**
175 * The skip function is a utility to parse over unrecognized date without
176 * causing corruption.
177 *
Mark Sleecfc01932006-09-01 22:18:16 +0000178 * @param TType $type What type is it
179 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000180 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000181 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000182 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000183 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000184 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000185 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000186 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000187 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000188 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000189 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000190 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000191 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000192 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000193 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000194 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000195 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000196 case TType::STRUCT:
197 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000198 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000199 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000200 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000201 if ($ftype == TType::STOP) {
202 break;
203 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000204 $result += $this->skip($ftype);
205 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000206 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000207 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000208 return $result;
209 }
210 case TType::MAP:
211 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000212 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000213 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000214 $result += $this->skip($keyType);
215 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000216 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000217 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000218 return $result;
219 }
220 case TType::SET:
221 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000222 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000223 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000224 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000225 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000226 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000227 return $result;
228 }
229 case TType::LST:
230 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000231 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000232 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000233 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000234 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000235 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000236 return $result;
237 }
238 default:
239 return 0;
240 }
241 }
Mark Slee99e2b262006-10-10 01:42:29 +0000242
243 /**
244 * Utility for skipping binary data
245 *
246 * @param TTransport $itrans TTransport object
247 * @param int $type Field type
248 */
249 public static function skipBinary($itrans, $type) {
250 switch ($type) {
251 case TType::BOOL:
252 return $itrans->readAll(1);
253 case TType::BYTE:
254 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000255 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000256 return $itrans->readAll(2);
257 case TType::I32:
258 return $itrans->readAll(4);
259 case TType::I64:
260 return $itrans->readAll(8);
261 case TType::DOUBLE:
262 return $itrans->readAll(8);
263 case TType::STRING:
264 $len = unpack('N', $itrans->readAll(4));
265 $len = $len[1];
266 if ($len > 0x7fffffff) {
267 $len = 0 - (($len - 1) ^ 0xffffffff);
268 }
269 return 4 + $itrans->readAll($len);
270 case TType::STRUCT:
271 {
272 $result = 0;
273 while (true) {
274 $ftype = 0;
275 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000276 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000277 $arr = unpack('c', $data);
278 $ftype = $arr[1];
279 if ($ftype == TType::STOP) {
280 break;
281 }
282 // I16 field id
283 $result += $itrans->readAll(2);
284 $result += self::skipBinary($itrans, $ftype);
285 }
286 return $result;
287 }
288 case TType::MAP:
289 {
290 // Ktype
291 $data = $itrans->readAll(1);
292 $arr = unpack('c', $data);
293 $ktype = $arr[1];
294 // Vtype
295 $data = $itrans->readAll(1);
296 $arr = unpack('c', $data);
297 $vtype = $arr[1];
298 // Size
299 $data = $itrans->readAll(4);
300 $arr = unpack('N', $data);
301 $size = $arr[1];
302 if ($size > 0x7fffffff) {
303 $size = 0 - (($size - 1) ^ 0xffffffff);
304 }
305 $result = 6;
306 for ($i = 0; $i < $size; $i++) {
307 $result += self::skipBinary($itrans, $ktype);
308 $result += self::skipBinary($itrans, $vtype);
309 }
310 return $result;
311 }
312 case TType::SET:
313 case TType::LST:
314 {
315 // Vtype
316 $data = $itrans->readAll(1);
317 $arr = unpack('c', $data);
318 $vtype = $arr[1];
319 // Size
320 $data = $itrans->readAll(4);
321 $arr = unpack('N', $data);
322 $size = $arr[1];
323 if ($size > 0x7fffffff) {
324 $size = 0 - (($size - 1) ^ 0xffffffff);
325 }
326 $result = 5;
327 for ($i = 0; $i < $size; $i++) {
328 $result += self::skipBinary($itrans, $vtype);
329 }
330 return $result;
331 }
332 default:
333 return 0;
334 }
335 }
Mark Slee6e536442006-06-30 18:28:50 +0000336}
337
Mark Slee5f8237d2006-10-26 04:57:03 +0000338/**
339 * Protocol factory creates protocol objects from transports
340 */
341interface TProtocolFactory {
342 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000343 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000344 *
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000345 * @return TProtcol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000346 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000347 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000348}
349
350
Mark Slee6e536442006-06-30 18:28:50 +0000351?>