blob: 83daf4be941c1cc84f8d2cc278949b96047d050c [file] [log] [blame]
Mark Slee254ce202007-05-16 02:21:06 +00001#
2# Copyright (c) 2006- Facebook
3# Distributed under the Thrift Software License
4#
5# See accompanying file LICENSE or visit the Thrift site at:
6# http://developers.facebook.com/thrift/
7#
8# package - thrift.socket
9# author - T Jake Luciani <jakers@gmail.com>
10# author - Mark Slee <mcslee@facebook.com>
11#
12
13require 5.6.0;
14use strict;
15use warnings;
16
17use Thrift;
18use Thrift::Transport;
19
20use IO::Socket::INET;
21use IO::Select;
22
23package Thrift::Socket;
24
25use base('Thrift::Transport');
26
27sub new
28{
29 my $classname = shift;
30 my $host = shift || "localhost";
31 my $port = shift || 9090;
32 my $debugHandler = shift;
33
34 my $self = {
35 host => $host,
36 port => $port,
37 debugHandler => $debugHandler,
38 debug => 0,
39 sendTimeout => 100,
40 recvTimeout => 750,
41 handle => undef,
42 };
43
44 return bless($self,$classname);
45}
46
47
48sub setSendTimeout
49{
50 my $self = shift;
51 my $timeout = shift;
52
53 $self->{sendTimeout} = $timeout;
54}
55
56sub setRecvTimeout
57{
58 my $self = shift;
59 my $timeout = shift;
60
61 $self->{recvTimeout} = $timeout;
62}
63
64
65#
66#Sets debugging output on or off
67#
68# @param bool $debug
69#
70sub setDebug
71{
72 my $self = shift;
73 my $debug = shift;
74
75 $self->{debug} = $debug;
76}
77
78#
79# Tests whether this is open
80#
81# @return bool true if the socket is open
82#
83sub isOpen
84{
85 my $self = shift;
86
87 return $self->{handle}->handles->[0]->connected;
88}
89
90#
91# Connects the socket.
92#
93sub open
94{
95 my $self = shift;
96
97 my $sock = IO::Socket::INET->new(PeerAddr => $self->{host},
98 PeerPort => $self->{port},
99 Proto => 'tcp',
100 Timeout => $self->{sendTimeout}/1000)
101 || do {
102 my $error = 'TSocket: Could not connect to '.$self->{host}.':'.$self->{port}.' ('.$!.')';
103
104 if ($self->{debug}) {
105 $self->{debugHandler}->($error);
106 }
107
108 die new Thrift::TException($error);
109
110 };
111
112
113 $self->{handle} = new IO::Select( $sock );
114}
115
116#
117# Closes the socket.
118#
119sub close
120{
121 my $self = shift;
122
123 close( ($self->{handle}->handles())[0] );
124}
125
126#
127# Uses stream get contents to do the reading
128#
129# @param int $len How many bytes
130# @return string Binary data
131#
132sub readAll
133{
134 my $self = shift;
135 my $len = shift;
136
137
138 my $pre = "";
139 while (1) {
140
141 #check for timeout
142 my @sockets = $self->{handle}->can_read( $self->{recvTimeout} );
143
144 if(@sockets == 0){
145 die new Thrift::TException('TSocket: timed out reading '.$len.' bytes from '.
146 $self->{host}.':'.$self->{port});
147 }
148
149 my $sock = $sockets[0];
150
151 my ($buf,$sz);
152 $sock->recv($buf, $len);
153
154 if (!defined $buf || $buf eq '') {
155
156 die new Thrift::TException('TSocket: Could not read '.$len.' bytes from '.
157 $self->{host}.':'.$self->{port});
158
159 } elsif (($sz = length($buf)) < $len) {
160
161 $pre .= $buf;
162 $len -= $sz;
163
164 } else {
165 return $pre.$buf;
166 }
167 }
168}
169
170#
171# Read from the socket
172#
173# @param int $len How many bytes
174# @return string Binary data
175#
176sub read
177{
178 my $self = shift;
179 my $len = shift;
180
181 #check for timeout
182 my @sockets = $self->{handle}->can_read( $self->{sendTimeout} );
183
184 if(@sockets == 0){
185 die new Thrift::TException('TSocket: timed out reading '.$len.' bytes from '.
186 $self->{host}.':'.$self->{port});
187 }
188
189 my $sock = $sockets[0];
190
191 my ($buf,$sz);
192 $sock->recv($buf, $len);
193
194 if (!defined $buf || $buf eq '') {
195
196 die new TException('TSocket: Could not read '.$len.' bytes from '.
197 $self->{host}.':'.$self->{port});
198
199 }
200
201 return $buf;
202}
203
204
205#
206# Write to the socket.
207#
208# @param string $buf The data to write
209#
210sub write
211{
212 my $self = shift;
213 my $buf = shift;
214
215
216 while (length($buf) > 0) {
217
218
219 #check for timeout
220 my @sockets = $self->{handle}->can_write( $self->{recvTimeout} );
221
222 if(@sockets == 0){
223 die new Thrift::TException('TSocket: timed out writing to bytes from '.
224 $self->{host}.':'.$self->{port});
225 }
226
227 my $sock = $sockets[0];
228
229 my $got = $sock->send($buf);
230
231 if (!defined $got || $got == 0 ) {
232 die new Thrift::TException('TSocket: Could not write '.strlen($buf).' bytes '.
233 $self->{host}.':'.$self->{host});
234 }
235
236 $buf = substr($buf, $got);
237 }
238}
239
240#
241# Flush output to the socket.
242#
243sub flush
244{
245 my $self = shift;
246 my $ret = ($self->{handle}->handles())[0]->flush;
247}
248
2491;