#!/usr/bin/env perl # # 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. # use 5.10.0; use strict; use warnings; use Data::Dumper; use Getopt::Long qw(GetOptions); use Time::HiRes qw(gettimeofday); $SIG{INT} = \&sigint_handler; use lib '../../lib/perl/lib'; use lib 'gen-perl'; use Thrift; use Thrift::BinaryProtocol; use Thrift::BufferedTransport; use Thrift::FramedTransport; use Thrift::MultiplexedProcessor; use Thrift::SSLServerSocket; use Thrift::ServerSocket; use Thrift::Server; use Thrift::UnixServerSocket; use ThriftTest::SecondService; use ThriftTest::ThriftTest; use ThriftTest::Types; $|++; sub usage { print <<"EOF"; Usage: $0 [OPTIONS] Options: (default) --ca Certificate authority file (optional). --cert Certificate file. Required if using --ssl. --ciphers Acceptable cipher list. --domain-socket Use a unix domain socket. --help Show usage. --key Private key file for certificate. Required if using --ssl and private key is not in the certificate file. --port 9090 Port to use. --protocol {binary} binary Protocol to use. --ssl If present, use SSL/TLS. --transport {buffered|framed} buffered Transport to use. EOF } my %opts = ( 'port' => 9090, 'protocol' => 'binary', 'transport' => 'buffered' ); GetOptions(\%opts, qw ( ca=s cert=s ciphers=s domain-socket=s help host=s key=s port=i protocol=s ssl transport=s )) || exit 1; if ($opts{help}) { usage(); exit 0; } if ($opts{ssl} and not defined $opts{cert}) { usage(); exit 1; } my $handler = ThriftTestHandler->new(); my $handler2 = SecondServiceHandler->new(); my $processor = ThriftTest::ThriftTestProcessor->new($handler); my $processor2 = ThriftTest::SecondServiceProcessor->new($handler2); my $serversocket; if ($opts{'domain-socket'}) { unlink($opts{'domain-socket'}); $serversocket = Thrift::UnixServerSocket->new($opts{'domain-socket'}); } elsif ($opts{ssl}) { $serversocket = Thrift::SSLServerSocket->new(\%opts); } else { $serversocket = Thrift::ServerSocket->new(\%opts); } my $transport; if ($opts{transport} eq 'buffered') { $transport = Thrift::BufferedTransportFactory->new(); } elsif ($opts{transport} eq 'framed') { $transport = Thrift::FramedTransportFactory->new(); } else { usage(); exit 1; } my $protocol; if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') { $protocol = Thrift::BinaryProtocolFactory->new(); } else { usage(); exit 1; } if (index($opts{protocol}, 'multi') == 0) { my $newProcessor = Thrift::MultiplexedProcessor->new($protocol); $newProcessor->defaultProcessor($processor); $newProcessor->registerProcessor('ThriftTest', $processor); $newProcessor->registerProcessor('SecondService', $processor2); $processor = $newProcessor; } my $ssltag = ''; if ($opts{ssl}) { $ssltag = '(SSL)'; } my $listening_on = "$opts{port} $ssltag"; if ($opts{'domain-socket'}) { $listening_on = $opts{'domain-socket'}; } my $server = Thrift::SimpleServer->new($processor, $serversocket, $transport, $protocol); print qq|Starting "simple" server ($opts{transport}/$opts{protocol}) listen on: $listening_on\n|; $server->serve(); print "done.\n"; sub sigint_handler { print "received SIGINT, stopping...\n"; $server->stop(); } ### ### Test server implementation ### package ThriftTestHandler; use base qw( ThriftTest::ThriftTestIf ); sub new { my $classname = shift; my $self = {}; return bless($self, $classname); } sub testVoid { print("testVoid()\n"); } sub testString { my $self = shift; my $thing = shift; print("testString($thing)\n"); return $thing; } sub testBool { my $self = shift; my $thing = shift; my $str = $thing ? 'true' : 'false'; print("testBool($str)\n"); return $thing; } sub testByte { my $self = shift; my $thing = shift; print("testByte($thing)\n"); return $thing; } sub testI32 { my $self = shift; my $thing = shift; print("testI32($thing)\n"); return $thing; } sub testI64 { my $self = shift; my $thing = shift; print("testI64($thing)\n"); return $thing; } sub testDouble { my $self = shift; my $thing = shift; print("testDouble($thing)\n"); return $thing; } sub testBinary { my $self = shift; my $thing = shift; my @bytes = split //, $thing; print 'testBinary('; printf( '%02lx', ord $_ ) foreach (@bytes); print ")\n"; return $thing; } sub testStruct { my $self = shift; my $thing = shift; printf(qq|testStruct({"%s", %d, %d, %lld})\n|, $thing->{string_thing}, $thing->{byte_thing}, $thing->{i32_thing}, $thing->{i64_thing}); return $thing; } sub testNest { my $self = shift; my $nest = shift; my $thing = $nest->{struct_thing}; printf(qq|testNest({%d, {"%s", %d, %d, %lld}, %d})\n|, $nest->{byte_thing}, $thing->{string_thing}, $thing->{byte_thing}, $thing->{i32_thing}, $thing->{i64_thing}, $nest->{i32_thing}); return $nest; } sub testMap { my $self = shift; my $thing = shift; printf "testMap({%s})\n", join( ', ', map { $_ . ' => ' . $thing->{$_} } sort keys %$thing ); return $thing; } sub testStringMap { my $self = shift; my $thing = shift; printf "testStringMap({%s})\n", join( ', ', map { $_ . ' => ' . $thing->{$_} } sort keys %$thing ); return $thing; } sub testSet { my $self = shift; my $thing = shift; my @result = sort keys %$thing; printf "testSet({%s})\n", join(', ', @result ); return \@result; } sub testList { my $self = shift; my $thing = shift; print "testList({%s})\n", join(', ', @$thing); return $thing; } sub testEnum { my $self = shift; my $thing = shift; print "testEnum($thing)\n"; return $thing; } sub testTypedef { my $self = shift; my $thing = shift; print("testTypedef($thing)\n"); return $thing; } sub testMapMap { my $self = shift; my $hello = shift; printf("testMapMap(%d)\n", $hello); my $result = { 4 => { 1 => 1, 2 => 2, 3 => 3, 4 => 4 }, -4 => { -1 => -1, -2 => -2, -3 => -3, -4 => -4 } }; return $result; } sub testInsanity { my $self = shift; my $argument = shift; print("testInsanity()\n"); my $hello = ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => 2, i32_thing => 2, i64_thing => 2}); my @hellos; push(@hellos, $hello); my $goodbye = ThriftTest::Xtruct->new({string_thing => 'Goodbye4', byte_thing => 4, i32_thing => 4, i64_thing => 4}); my @goodbyes; push(@goodbyes, $goodbye); my $crazy = ThriftTest::Insanity->new({userMap => { ThriftTest::Numberz::EIGHT => 8 }, xtructs => \@goodbyes}); my $loony = ThriftTest::Insanity->new(); my $result = { 1 => { ThriftTest::Numberz::TWO => $argument, ThriftTest::Numberz::THREE => $argument }, 2 => { ThriftTest::Numberz::SIX => $loony } }; return $result; } sub testMulti { my $self = shift; my $arg0 = shift; my $arg1 = shift; my $arg2 = shift; my $arg3 = shift; my $arg4 = shift; my $arg5 = shift; print("testMulti()\n"); return ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => $arg0, i32_thing => $arg1, i64_thing => $arg2}); } sub testException { my $self = shift; my $arg = shift; print("testException($arg)\n"); if ($arg eq 'Xception') { die ThriftTest::Xception->new({errorCode => 1001, message => $arg}); } elsif ($arg eq 'TException') { die 'astring'; # all unhandled exceptions become TExceptions } else { return ThriftTest::Xtruct->new({string_thing => $arg}); } } sub testMultiException { my $self = shift; my $arg0 = shift; my $arg1 = shift; printf("testMultiException(%s, %s)\n", $arg0, $arg1); if ($arg0 eq 'Xception') { die ThriftTest::Xception->new({errorCode => 1001, message => 'This is an Xception'}); } elsif ($arg0 eq 'Xception2') { my $struct_thing = ThriftTest::Xtruct->new({string_thing => 'This is an Xception2'}); die ThriftTest::Xception2->new({errorCode => 2002, struct_thing => $struct_thing}); } else { return ThriftTest::Xtruct->new({string_thing => $arg1}); } } sub testOneway { my $self = shift; my $num = shift; print("testOneway($num): received\n"); } ### ### Test server implementation ### package SecondServiceHandler; use base qw( ThriftTest::SecondServiceIf ); sub new { my $classname = shift; my $self = {}; return bless($self, $classname); } sub secondtestString { my $self = shift; my $thing = shift; print("testString($thing)\n"); return qq|testString("$thing")|; } 1;