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>
15 * Sockets implementation of the TTransport interface.
17 * @package thrift.transport
18 * @author Mark Slee <mcslee@facebook.com>
20 class TSocket
extends TTransport
{
23 * Handle to PHP socket
27 private $handle_ = null;
34 protected $host_ = 'localhost';
41 protected $port_ = '9090';
44 * Send timeout in milliseconds
48 private $sendTimeout_ = 100;
51 * Recv timeout in milliseconds
55 private $recvTimeout_ = 750;
58 * Is send timeout set?
62 private $sendTimeoutSet_ = FALSE;
65 * Persistent socket or plain?
69 private $persist_ = FALSE;
76 protected $debug_ = FALSE;
83 protected $debugHandler_ = null;
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',
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
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() {
140 * Get the remote port that this socket is connected to
144 public function getPort() {
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_
,
167 $this->sendTimeout_
/1000.0);
169 $this->handle_
= @fsockopen
($this->host_
,
173 $this->sendTimeout_
/1000.0);
177 if ($this->handle_
=== FALSE) {
178 $error = 'TSocket: Could not connect to '.$this->host_
.':'.$this->port_
.' ('.$errstr.' ['.$errno.'])';
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;
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);
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_
);
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_
);
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_
);
258 throw new TException('TSocket: Could not read '.$len.' bytes from '.
259 $this->host_
.':'.$this->port_
);
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_
);
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_
);