Project

General

Profile

1 12773 antonis.le
<?php
2
/*
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
10
 *
11
 *   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.
19
 *
20
 * @package thrift.protocol
21
 */
22
23
24
/**
25
 * Protocol module. Contains all the types and definitions needed to implement
26
 * a protocol encoder/decoder.
27
 *
28
 * @package thrift.protocol
29
 */
30
31
/**
32
 * Protocol exceptions
33
 */
34
class TProtocolException extends TException {
35
  const UNKNOWN = 0;
36
  const INVALID_DATA = 1;
37
  const NEGATIVE_SIZE = 2;
38
  const SIZE_LIMIT = 3;
39
  const BAD_VERSION = 4;
40
41
  function __construct($message=null, $code=0) {
42
    parent::__construct($message, $code);
43
  }
44
}
45
46
/**
47
 * Protocol base class module.
48
 */
49
abstract class TProtocol {
50
  // 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';
56
57
  /**
58
   * Underlying transport
59
   *
60
   * @var TTransport
61
   */
62
  protected $trans_;
63
64
  /**
65
   * Constructor
66
   */
67
  protected function __construct($trans) {
68
    $this->trans_ = $trans;
69
  }
70
71
  /**
72
   * Accessor for transport
73
   *
74
   * @return TTransport
75
   */
76
  public function getTransport() {
77
    return $this->trans_;
78
  }
79
80
  /**
81
   * Writes the message header
82
   *
83
   * @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
   */
87
  public abstract function writeMessageBegin($name, $type, $seqid);
88
89
  /**
90
   * Close the message
91
   */
92
  public abstract function writeMessageEnd();
93
94
  /**
95
   * Writes a struct header.
96
   *
97
   * @param string     $name Struct name
98
   * @throws TException on write error
99
   * @return int How many bytes written
100
   */
101
  public abstract function writeStructBegin($name);
102
103
  /**
104
   * Close a struct.
105
   *
106
   * @throws TException on write error
107
   * @return int How many bytes written
108
   */
109
  public abstract function writeStructEnd();
110
111
  /*
112
   * Starts a field.
113
   *
114
   * @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
   */
120
  public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
121
122
  public abstract function writeFieldEnd();
123
124
  public abstract function writeFieldStop();
125
126
  public abstract function writeMapBegin($keyType, $valType, $size);
127
128
  public abstract function writeMapEnd();
129
130
  public abstract function writeListBegin($elemType, $size);
131
132
  public abstract function writeListEnd();
133
134
  public abstract function writeSetBegin($elemType, $size);
135
136
  public abstract function writeSetEnd();
137
138
  public abstract function writeBool($bool);
139
140
  public abstract function writeByte($byte);
141
142
  public abstract function writeI16($i16);
143
144
  public abstract function writeI32($i32);
145
146
  public abstract function writeI64($i64);
147
148
  public abstract function writeDouble($dub);
149
150
  public abstract function writeString($str);
151
152
  /**
153
   * Reads the message header
154
   *
155
   * @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
   */
159
  public abstract function readMessageBegin(&$name, &$type, &$seqid);
160
161
  /**
162
   * Read the close of message
163
   */
164
  public abstract function readMessageEnd();
165
166
  public abstract function readStructBegin(&$name);
167
168
  public abstract function readStructEnd();
169
170
  public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
171
172
  public abstract function readFieldEnd();
173
174
  public abstract function readMapBegin(&$keyType, &$valType, &$size);
175
176
  public abstract function readMapEnd();
177
178
  public abstract function readListBegin(&$elemType, &$size);
179
180
  public abstract function readListEnd();
181
182
  public abstract function readSetBegin(&$elemType, &$size);
183
184
  public abstract function readSetEnd();
185
186
  public abstract function readBool(&$bool);
187
188
  public abstract function readByte(&$byte);
189
190
  public abstract function readI16(&$i16);
191
192
  public abstract function readI32(&$i32);
193
194
  public abstract function readI64(&$i64);
195
196
  public abstract function readDouble(&$dub);
197
198
  public abstract function readString(&$str);
199
200
  /**
201
   * The skip function is a utility to parse over unrecognized date without
202
   * causing corruption.
203
   *
204
   * @param TType $type What type is it
205
   */
206
  public function skip($type) {
207
    switch ($type) {
208
    case TType::BOOL:
209
      return $this->readBool($bool);
210
    case TType::BYTE:
211
      return $this->readByte($byte);
212
    case TType::I16:
213
      return $this->readI16($i16);
214
    case TType::I32:
215
      return $this->readI32($i32);
216
    case TType::I64:
217
      return $this->readI64($i64);
218
    case TType::DOUBLE:
219
      return $this->readDouble($dub);
220
    case TType::STRING:
221
      return $this->readString($str);
222
    case TType::STRUCT:
223
      {
224
        $result = $this->readStructBegin($name);
225
        while (true) {
226
          $result += $this->readFieldBegin($name, $ftype, $fid);
227
          if ($ftype == TType::STOP) {
228
            break;
229
          }
230
          $result += $this->skip($ftype);
231
          $result += $this->readFieldEnd();
232
        }
233
        $result += $this->readStructEnd();
234
        return $result;
235
      }
236
    case TType::MAP:
237
      {
238
        $result = $this->readMapBegin($keyType, $valType, $size);
239
        for ($i = 0; $i < $size; $i++) {
240
          $result += $this->skip($keyType);
241
          $result += $this->skip($valType);
242
        }
243
        $result += $this->readMapEnd();
244
        return $result;
245
      }
246
    case TType::SET:
247
      {
248
        $result = $this->readSetBegin($elemType, $size);
249
        for ($i = 0; $i < $size; $i++) {
250
          $result += $this->skip($elemType);
251
        }
252
        $result += $this->readSetEnd();
253
        return $result;
254
      }
255
    case TType::LST:
256
      {
257
        $result = $this->readListBegin($elemType, $size);
258
        for ($i = 0; $i < $size; $i++) {
259
          $result += $this->skip($elemType);
260
        }
261
        $result += $this->readListEnd();
262
        return $result;
263
      }
264
    default:
265
      return 0;
266
    }
267
  }
268
269
  /**
270
   * Utility for skipping binary data
271
   *
272
   * @param TTransport $itrans TTransport object
273
   * @param int        $type   Field type
274
   */
275
  public static function skipBinary($itrans, $type) {
276
    switch ($type) {
277
    case TType::BOOL:
278
      return $itrans->readAll(1);
279
    case TType::BYTE:
280
      return $itrans->readAll(1);
281
    case TType::I16:
282
      return $itrans->readAll(2);
283
    case TType::I32:
284
      return $itrans->readAll(4);
285
    case TType::I64:
286
      return $itrans->readAll(8);
287
    case TType::DOUBLE:
288
      return $itrans->readAll(8);
289
    case TType::STRING:
290
      $len = unpack('N', $itrans->readAll(4));
291
      $len = $len[1];
292
      if ($len > 0x7fffffff) {
293
        $len = 0 - (($len - 1) ^ 0xffffffff);
294
      }
295
      return 4 + $itrans->readAll($len);
296
    case TType::STRUCT:
297
      {
298
        $result = 0;
299
        while (true) {
300
          $ftype = 0;
301
          $fid = 0;
302
          $data = $itrans->readAll(1);
303
          $arr = unpack('c', $data);
304
          $ftype = $arr[1];
305
          if ($ftype == TType::STOP) {
306
            break;
307
          }
308
          // I16 field id
309
          $result += $itrans->readAll(2);
310
          $result += self::skipBinary($itrans, $ftype);
311
        }
312
        return $result;
313
      }
314
    case TType::MAP:
315
      {
316
        // Ktype
317
        $data = $itrans->readAll(1);
318
        $arr = unpack('c', $data);
319
        $ktype = $arr[1];
320
        // Vtype
321
        $data = $itrans->readAll(1);
322
        $arr = unpack('c', $data);
323
        $vtype = $arr[1];
324
        // Size
325
        $data = $itrans->readAll(4);
326
        $arr = unpack('N', $data);
327
        $size = $arr[1];
328
        if ($size > 0x7fffffff) {
329
          $size = 0 - (($size - 1) ^ 0xffffffff);
330
        }
331
        $result = 6;
332
        for ($i = 0; $i < $size; $i++) {
333
          $result += self::skipBinary($itrans, $ktype);
334
          $result += self::skipBinary($itrans, $vtype);
335
        }
336
        return $result;
337
      }
338
    case TType::SET:
339
    case TType::LST:
340
      {
341
        // Vtype
342
        $data = $itrans->readAll(1);
343
        $arr = unpack('c', $data);
344
        $vtype = $arr[1];
345
        // Size
346
        $data = $itrans->readAll(4);
347
        $arr = unpack('N', $data);
348
        $size = $arr[1];
349
        if ($size > 0x7fffffff) {
350
          $size = 0 - (($size - 1) ^ 0xffffffff);
351
        }
352
        $result = 5;
353
        for ($i = 0; $i < $size; $i++) {
354
          $result += self::skipBinary($itrans, $vtype);
355
        }
356
        return $result;
357
      }
358
    default:
359
      return 0;
360
    }
361
  }
362
}
363
364
/**
365
 * Protocol factory creates protocol objects from transports
366
 */
367
interface TProtocolFactory {
368
  /**
369
   * Build a protocol from the base transport
370
   *
371
   * @return TProtocol protocol
372
   */
373
  public function getProtocol($trans);
374
}