r1281@opsdev009 (orig r69409): mcslee | 2007-11-13 02:19:08 -0800
[amiethrift.git] / lib / php / src / transport / TSocket.php
blobe1bd3bd68159fba48f58e69ad515747a3a362658
1 <?php
3 /**
4 * Copyright (c) 2006- Facebook
5 * Distributed under the Thrift Software License
7 * See accompanying file LICENSE or visit the Thrift site at:
8 * http://developers.facebook.com/thrift/
10 * @package thrift.transport
11 * @author Mark Slee <mcslee@facebook.com>
14 /**
15 * Sockets implementation of the TTransport interface.
17 * @package thrift.transport
18 * @author Mark Slee <mcslee@facebook.com>
20 class TSocket extends TTransport {
22 /**
23 * Handle to PHP socket
25 * @var resource
27 private $handle_ = null;
29 /**
30 * Remote hostname
32 * @var string
34 protected $host_ = 'localhost';
36 /**
37 * Remote port
39 * @var int
41 protected $port_ = '9090';
43 /**
44 * Send timeout in milliseconds
46 * @var int
48 private $sendTimeout_ = 100;
50 /**
51 * Recv timeout in milliseconds
53 * @var int
55 private $recvTimeout_ = 750;
57 /**
58 * Is send timeout set?
60 * @var bool
62 private $sendTimeoutSet_ = FALSE;
64 /**
65 * Persistent socket or plain?
67 * @var bool
69 private $persist_ = FALSE;
71 /**
72 * Debugging on?
74 * @var bool
76 protected $debug_ = FALSE;
78 /**
79 * Debug handler
81 * @var mixed
83 protected $debugHandler_ = null;
85 /**
86 * Socket constructor
88 * @param string $host Remote hostname
89 * @param int $port Remote port
90 * @param bool $persist Whether to use a persistent socket
91 * @param string $debugHandler Function to call for error logging
93 public function __construct($host='localhost',
94 $port=9090,
95 $persist=FALSE,
96 $debugHandler=null) {
97 $this->host_ = $host;
98 $this->port_ = $port;
99 $this->persist_ = $persist;
100 $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
104 * Sets the send timeout.
106 * @param int $timeout
108 public function setSendTimeout($timeout) {
109 $this->sendTimeout_ = $timeout;
113 * Sets the receive timeout.
115 * @param int $timeout
117 public function setRecvTimeout($timeout) {
118 $this->recvTimeout_ = $timeout;
122 * Sets debugging output on or off
124 * @param bool $debug
126 public function setDebug($debug) {
127 $this->debug_ = $debug;
131 * Get the host that this socket is connected to
133 * @return string host
135 public function getHost() {
136 return $this->host_;
140 * Get the remote port that this socket is connected to
142 * @return int port
144 public function getPort() {
145 return $this->port_;
149 * Tests whether this is open
151 * @return bool true if the socket is open
153 public function isOpen() {
154 return is_resource($this->handle_);
158 * Connects the socket.
160 public function open() {
162 if ($this->persist_) {
163 $this->handle_ = @pfsockopen($this->host_,
164 $this->port_,
165 $errno,
166 $errstr,
167 $this->sendTimeout_/1000.0);
168 } else {
169 $this->handle_ = @fsockopen($this->host_,
170 $this->port_,
171 $errno,
172 $errstr,
173 $this->sendTimeout_/1000.0);
176 // Connect failed?
177 if ($this->handle_ === FALSE) {
178 $error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
179 if ($this->debug_) {
180 call_user_func($this->debugHandler_, $error);
182 throw new TException($error);
185 stream_set_timeout($this->handle_, 0, $this->sendTimeout_*1000);
186 $this->sendTimeoutSet_ = TRUE;
190 * Closes the socket.
192 public function close() {
193 if (!$this->persist_) {
194 @fclose($this->handle_);
195 $this->handle_ = null;
200 * Uses stream get contents to do the reading
202 * @param int $len How many bytes
203 * @return string Binary data
205 public function readAll($len) {
206 if ($this->sendTimeoutSet_) {
207 stream_set_timeout($this->handle_, 0, $this->recvTimeout_*1000);
208 $this->sendTimeoutSet_ = FALSE;
210 // This call does not obey stream_set_timeout values!
211 // $buf = @stream_get_contents($this->handle_, $len);
213 $pre = null;
214 while (TRUE) {
215 $buf = @fread($this->handle_, $len);
216 if ($buf === FALSE || $buf === '') {
217 $md = stream_get_meta_data($this->handle_);
218 if ($md['timed_out']) {
219 throw new TException('TSocket: timed out reading '.$len.' bytes from '.
220 $this->host_.':'.$this->port_);
221 } else {
222 throw new TException('TSocket: Could not read '.$len.' bytes from '.
223 $this->host_.':'.$this->port_);
225 } else if (($sz = strlen($buf)) < $len) {
226 $md = stream_get_meta_data($this->handle_);
227 if ($md['timed_out']) {
228 throw new TException('TSocket: timed out reading '.$len.' bytes from '.
229 $this->host_.':'.$this->port_);
230 } else {
231 $pre .= $buf;
232 $len -= $sz;
234 } else {
235 return $pre.$buf;
241 * Read from the socket
243 * @param int $len How many bytes
244 * @return string Binary data
246 public function read($len) {
247 if ($this->sendTimeoutSet_) {
248 stream_set_timeout($this->handle_, 0, $this->recvTimeout_*1000);
249 $this->sendTimeoutSet_ = FALSE;
251 $data = @fread($this->handle_, $len);
252 if ($data === FALSE || $data === '') {
253 $md = stream_get_meta_data($this->handle_);
254 if ($md['timed_out']) {
255 throw new TException('TSocket: timed out reading '.$len.' bytes from '.
256 $this->host_.':'.$this->port_);
257 } else {
258 throw new TException('TSocket: Could not read '.$len.' bytes from '.
259 $this->host_.':'.$this->port_);
262 return $data;
266 * Write to the socket.
268 * @param string $buf The data to write
270 public function write($buf) {
271 if (!$this->sendTimeoutSet_) {
272 stream_set_timeout($this->handle_, 0, $this->sendTimeout_*1000);
273 $this->sendTimeoutSet_ = TRUE;
275 while (strlen($buf) > 0) {
276 $got = @fwrite($this->handle_, $buf);
277 if ($got === 0 || $got === FALSE) {
278 $md = stream_get_meta_data($this->handle_);
279 if ($md['timed_out']) {
280 throw new TException('TSocket: timed out writing '.$len.' bytes from '.
281 $this->host_.':'.$this->port_);
282 } else {
283 throw new TException('TSocket: Could not write '.strlen($buf).' bytes '.
284 $this->host_.':'.$this->port_);
287 $buf = substr($buf, $got);
292 * Flush output to the socket.
294 public function flush() {
295 $ret = fflush($this->handle_);
296 if ($ret === FALSE) {
297 throw new TException('TSocket: Could not flush: '.
298 $this->host_.':'.$this->port_);