# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 5.6.0; use strict; use warnings; use Thrift; # # Protocol exceptions # package TProtocolException; use base('Thrift::TException'); use constant UNKNOWN => 0; use constant INVALID_DATA => 1; use constant NEGATIVE_SIZE => 2; use constant SIZE_LIMIT => 3; use constant BAD_VERSION => 4; sub new { my $classname = shift; my $self = $classname->SUPER::new(); return bless($self,$classname); } # # Protocol base class module. # package Thrift::Protocol; sub new { my $classname = shift; my $self = {}; my $trans = shift; $self->{trans}= $trans; return bless($self,$classname); } sub getTransport { my $self = shift; return $self->{trans}; } # # Writes the message header # # @param string $name Function name # @param int $type message type TMessageType::CALL or TMessageType::REPLY # @param int $seqid The sequence id of this message # sub writeMessageBegin { my ($name, $type, $seqid); die "abstract"; } # # Close the message # sub writeMessageEnd { die "abstract"; } # # Writes a struct header. # # @param string $name Struct name # @throws TException on write error # @return int How many bytes written # sub writeStructBegin { my ($name); die "abstract"; } # # Close a struct. # # @throws TException on write error # @return int How many bytes written # sub writeStructEnd { die "abstract"; } # # Starts a field. # # @param string $name Field name # @param int $type Field type # @param int $fid Field id # @throws TException on write error # @return int How many bytes written # sub writeFieldBegin { my ($fieldName, $fieldType, $fieldId); die "abstract"; } sub writeFieldEnd { die "abstract"; } sub writeFieldStop { die "abstract"; } sub writeMapBegin { my ($keyType, $valType, $size); die "abstract"; } sub writeMapEnd { die "abstract"; } sub writeListBegin { my ($elemType, $size); die "abstract"; } sub writeListEnd { die "abstract"; } sub writeSetBegin { my ($elemType, $size); die "abstract"; } sub writeSetEnd { die "abstract"; } sub writeBool { my ($bool); die "abstract"; } sub writeByte { my ($byte); die "abstract"; } sub writeI16 { my ($i16); die "abstract"; } sub writeI32 { my ($i32); die "abstract"; } sub writeI64 { my ($i64); die "abstract"; } sub writeDouble { my ($dub); die "abstract"; } sub writeString { my ($str); die "abstract"; } # # Reads the message header # # @param string $name Function name # @param int $type message type TMessageType::CALL or TMessageType::REPLY # @parem int $seqid The sequence id of this message # sub readMessageBegin { my ($name, $type, $seqid); die "abstract"; } # # Read the close of message # sub readMessageEnd { die "abstract"; } sub readStructBegin { my($name); die "abstract"; } sub readStructEnd { die "abstract"; } sub readFieldBegin { my ($name, $fieldType, $fieldId); die "abstract"; } sub readFieldEnd { die "abstract"; } sub readMapBegin { my ($keyType, $valType, $size); die "abstract"; } sub readMapEnd { die "abstract"; } sub readListBegin { my ($elemType, $size); die "abstract"; } sub readListEnd { die "abstract"; } sub readSetBegin { my ($elemType, $size); die "abstract"; } sub readSetEnd { die "abstract"; } sub readBool { my ($bool); die "abstract"; } sub readByte { my ($byte); die "abstract"; } sub readI16 { my ($i16); die "abstract"; } sub readI32 { my ($i32); die "abstract"; } sub readI64 { my ($i64); die "abstract"; } sub readDouble { my ($dub); die "abstract"; } sub readString { my ($str); die "abstract"; } # # The skip function is a utility to parse over unrecognized data without # causing corruption. # # @param TType $type What type is it # sub skip { my $self = shift; my $type = shift; my $ref; my $result; my $i; if($type == TType::BOOL) { return $self->readBool(\$ref); } elsif($type == TType::BYTE){ return $self->readByte(\$ref); } elsif($type == TType::I16){ return $self->readI16(\$ref); } elsif($type == TType::I32){ return $self->readI32(\$ref); } elsif($type == TType::I64){ return $self->readI64(\$ref); } elsif($type == TType::DOUBLE){ return $self->readDouble(\$ref); } elsif($type == TType::STRING) { return $self->readString(\$ref); } elsif($type == TType::STRUCT) { $result = $self->readStructBegin(\$ref); while (1) { my ($ftype,$fid); $result += $self->readFieldBegin(\$ref, \$ftype, \$fid); if ($ftype == TType::STOP) { last; } $result += $self->skip($ftype); $result += $self->readFieldEnd(); } $result += $self->readStructEnd(); return $result; } elsif($type == TType::MAP) { my($keyType,$valType,$size); $result = $self->readMapBegin(\$keyType, \$valType, \$size); for ($i = 0; $i < $size; $i++) { $result += $self->skip($keyType); $result += $self->skip($valType); } $result += $self->readMapEnd(); return $result; } elsif($type == TType::SET) { my ($elemType,$size); $result = $self->readSetBegin(\$elemType, \$size); for ($i = 0; $i < $size; $i++) { $result += $self->skip($elemType); } $result += $self->readSetEnd(); return $result; } elsif($type == TType::LIST) { my ($elemType,$size); $result = $self->readListBegin(\$elemType, \$size); for ($i = 0; $i < $size; $i++) { $result += $self->skip($elemType); } $result += $self->readListEnd(); return $result; } return 0; } # # Utility for skipping binary data # # @param TTransport $itrans TTransport object # @param int $type Field type # sub skipBinary { my $self = shift; my $itrans = shift; my $type = shift; if($type == TType::BOOL) { return $itrans->readAll(1); } elsif($type == TType::BYTE) { return $itrans->readAll(1); } elsif($type == TType::I16) { return $itrans->readAll(2); } elsif($type == TType::I32) { return $itrans->readAll(4); } elsif($type == TType::I64) { return $itrans->readAll(8); } elsif($type == TType::DOUBLE) { return $itrans->readAll(8); } elsif( $type == TType::STRING ) { my @len = unpack('N', $itrans->readAll(4)); my $len = $len[0]; if ($len > 0x7fffffff) { $len = 0 - (($len - 1) ^ 0xffffffff); } return 4 + $itrans->readAll($len); } elsif( $type == TType::STRUCT ) { my $result = 0; while (1) { my $ftype = 0; my $fid = 0; my $data = $itrans->readAll(1); my @arr = unpack('c', $data); $ftype = $arr[0]; if ($ftype == TType::STOP) { last; } # I16 field id $result += $itrans->readAll(2); $result += $self->skipBinary($itrans, $ftype); } return $result; } elsif($type == TType::MAP) { # Ktype my $data = $itrans->readAll(1); my @arr = unpack('c', $data); my $ktype = $arr[0]; # Vtype $data = $itrans->readAll(1); @arr = unpack('c', $data); my $vtype = $arr[0]; # Size $data = $itrans->readAll(4); @arr = unpack('N', $data); my $size = $arr[0]; if ($size > 0x7fffffff) { $size = 0 - (($size - 1) ^ 0xffffffff); } my $result = 6; for (my $i = 0; $i < $size; $i++) { $result += $self->skipBinary($itrans, $ktype); $result += $self->skipBinary($itrans, $vtype); } return $result; } elsif($type == TType::SET || $type == TType::LIST) { # Vtype my $data = $itrans->readAll(1); my @arr = unpack('c', $data); my $vtype = $arr[0]; # Size $data = $itrans->readAll(4); @arr = unpack('N', $data); my $size = $arr[0]; if ($size > 0x7fffffff) { $size = 0 - (($size - 1) ^ 0xffffffff); } my $result = 5; for (my $i = 0; $i < $size; $i++) { $result += $self->skipBinary($itrans, $vtype); } return $result; } return 0; } # # Protocol factory creates protocol objects from transports # package TProtocolFactory; sub new { my $classname = shift; my $self = {}; return bless($self,$classname); } # # Build a protocol from the base transport # # @return TProtcol protocol # sub getProtocol { my ($trans); die "interface"; } 1;