PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/web/thrift/lib/transport/TSocket.php

https://github.com/lenn0x/Milo-Tracing-Framework
PHP | 313 lines | 145 code | 31 blank | 137 comment | 27 complexity | 0f2ef2e24edd2f89c7d36438eacbb875 MD5 | raw file
  1. <?php
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. * @package thrift.transport
  21. */
  22. /**
  23. * Sockets implementation of the TTransport interface.
  24. *
  25. * @package thrift.transport
  26. */
  27. class TSocket extends TTransport {
  28. /**
  29. * Handle to PHP socket
  30. *
  31. * @var resource
  32. */
  33. private $handle_ = null;
  34. /**
  35. * Remote hostname
  36. *
  37. * @var string
  38. */
  39. protected $host_ = 'localhost';
  40. /**
  41. * Remote port
  42. *
  43. * @var int
  44. */
  45. protected $port_ = '9090';
  46. /**
  47. * Send timeout in milliseconds
  48. *
  49. * @var int
  50. */
  51. private $sendTimeout_ = 100;
  52. /**
  53. * Recv timeout in milliseconds
  54. *
  55. * @var int
  56. */
  57. private $recvTimeout_ = 750;
  58. /**
  59. * Is send timeout set?
  60. *
  61. * @var bool
  62. */
  63. private $sendTimeoutSet_ = FALSE;
  64. /**
  65. * Persistent socket or plain?
  66. *
  67. * @var bool
  68. */
  69. private $persist_ = FALSE;
  70. /**
  71. * Debugging on?
  72. *
  73. * @var bool
  74. */
  75. protected $debug_ = FALSE;
  76. /**
  77. * Debug handler
  78. *
  79. * @var mixed
  80. */
  81. protected $debugHandler_ = null;
  82. /**
  83. * Socket constructor
  84. *
  85. * @param string $host Remote hostname
  86. * @param int $port Remote port
  87. * @param bool $persist Whether to use a persistent socket
  88. * @param string $debugHandler Function to call for error logging
  89. */
  90. public function __construct($host='localhost',
  91. $port=9090,
  92. $persist=FALSE,
  93. $debugHandler=null) {
  94. $this->host_ = $host;
  95. $this->port_ = $port;
  96. $this->persist_ = $persist;
  97. $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
  98. }
  99. /**
  100. * Sets the send timeout.
  101. *
  102. * @param int $timeout Timeout in milliseconds.
  103. */
  104. public function setSendTimeout($timeout) {
  105. $this->sendTimeout_ = $timeout;
  106. }
  107. /**
  108. * Sets the receive timeout.
  109. *
  110. * @param int $timeout Timeout in milliseconds.
  111. */
  112. public function setRecvTimeout($timeout) {
  113. $this->recvTimeout_ = $timeout;
  114. }
  115. /**
  116. * Sets debugging output on or off
  117. *
  118. * @param bool $debug
  119. */
  120. public function setDebug($debug) {
  121. $this->debug_ = $debug;
  122. }
  123. /**
  124. * Get the host that this socket is connected to
  125. *
  126. * @return string host
  127. */
  128. public function getHost() {
  129. return $this->host_;
  130. }
  131. /**
  132. * Get the remote port that this socket is connected to
  133. *
  134. * @return int port
  135. */
  136. public function getPort() {
  137. return $this->port_;
  138. }
  139. /**
  140. * Tests whether this is open
  141. *
  142. * @return bool true if the socket is open
  143. */
  144. public function isOpen() {
  145. return is_resource($this->handle_);
  146. }
  147. /**
  148. * Connects the socket.
  149. */
  150. public function open() {
  151. if ($this->persist_) {
  152. $this->handle_ = @pfsockopen($this->host_,
  153. $this->port_,
  154. $errno,
  155. $errstr,
  156. $this->sendTimeout_/1000.0);
  157. } else {
  158. $this->handle_ = @fsockopen($this->host_,
  159. $this->port_,
  160. $errno,
  161. $errstr,
  162. $this->sendTimeout_/1000.0);
  163. }
  164. // Connect failed?
  165. if ($this->handle_ === FALSE) {
  166. $error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
  167. if ($this->debug_) {
  168. call_user_func($this->debugHandler_, $error);
  169. }
  170. throw new TException($error);
  171. }
  172. stream_set_timeout($this->handle_, 0, $this->sendTimeout_*1000);
  173. $this->sendTimeoutSet_ = TRUE;
  174. }
  175. /**
  176. * Closes the socket.
  177. */
  178. public function close() {
  179. if (!$this->persist_) {
  180. @fclose($this->handle_);
  181. $this->handle_ = null;
  182. }
  183. }
  184. /**
  185. * Uses stream get contents to do the reading
  186. *
  187. * @param int $len How many bytes
  188. * @return string Binary data
  189. */
  190. public function readAll($len) {
  191. // This call does not obey stream_set_timeout values!
  192. // $buf = @stream_get_contents($this->handle_, $len);
  193. $pre = null;
  194. while (TRUE) {
  195. $read = array($this->handle_);
  196. $write = NULL;
  197. $except = NULL;
  198. $nc = @stream_select($read, $write, $except, 0, $this->recvTimeout_*1000);
  199. if ($nc === false || $nc == 0) {
  200. throw new TException('TSocket: timed out reading '.$len.' bytes from '.
  201. $this->host_.':'.$this->port_);
  202. } elseif ($nc > 0) {
  203. $buf = @stream_socket_recvfrom($this->handle_, $len);
  204. if ($buf === FALSE || $buf === '') {
  205. throw new TException('TSocket: Could not read '.$len.' bytes from '.
  206. $this->host_.':'.$this->port_);
  207. }
  208. if (($sz = mb_strlen($buf,'8bit')) < $len) {
  209. $pre .= $buf;
  210. $len -= $sz;
  211. } else {
  212. return $pre.$buf;
  213. }
  214. }
  215. }
  216. }
  217. /**
  218. * Read from the socket
  219. *
  220. * @param int $len How many bytes
  221. * @return string Binary data
  222. */
  223. public function read($len) {
  224. if (!is_resource($this->handle_)) {
  225. throw new TException('Invalid handle, could not read from socket');
  226. }
  227. $read = array($this->handle_);
  228. $write = NULL;
  229. $except = NULL;
  230. $nc = @stream_select($read, $write, $except, 0, $this->recvTimeout_*1000);
  231. if ($nc === false || $nc == 0) {
  232. throw new TException('TSocket: timed out reading '.$len.' bytes from '.
  233. $this->host_.':'.$this->port_);
  234. } elseif ($nc > 0) {
  235. $data = @stream_socket_recvfrom($this->handle_, $len);
  236. if ($data === FALSE || $data === '') {
  237. throw new TException('TSocket: Could not read '.$len.' bytes from '.
  238. $this->host_.':'.$this->port_);
  239. }
  240. }
  241. return $data;
  242. }
  243. /**
  244. * Write to the socket.
  245. *
  246. * @param string $buf The data to write
  247. */
  248. public function write($buf) {
  249. if (!is_resource($this->handle_)) {
  250. throw new TException('Invalid handle, could not write to socket');
  251. }
  252. if (!$this->sendTimeoutSet_) {
  253. stream_set_timeout($this->handle_, 0, $this->sendTimeout_*1000);
  254. $this->sendTimeoutSet_ = TRUE;
  255. }
  256. while (mb_strlen($buf,'8bit') > 0) {
  257. $got = @fwrite($this->handle_, $buf);
  258. if ($got === 0 || $got === FALSE) {
  259. $md = stream_get_meta_data($this->handle_);
  260. if ($md['timed_out']) {
  261. throw new TException('TSocket: timed out writing '.mb_strlen($buf,'8bit').' bytes from '.
  262. $this->host_.':'.$this->port_);
  263. } else {
  264. throw new TException('TSocket: Could not write '.mb_strlen($buf,'8bit').' bytes '.
  265. $this->host_.':'.$this->port_);
  266. }
  267. }
  268. $buf = mb_substr($buf, $got, mb_strlen($buf, '8bit'), '8bit');
  269. }
  270. }
  271. /**
  272. * Flush output to the socket.
  273. */
  274. public function flush() {
  275. $ret = fflush($this->handle_);
  276. if ($ret === FALSE) {
  277. throw new TException('TSocket: Could not flush: '.
  278. $this->host_.':'.$this->port_);
  279. }
  280. }
  281. }
  282. ?>