PageRenderTime 21ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/horde/framework/Horde/Socket/Client.php

https://gitlab.com/JrLucena/moodle
PHP | 212 lines | 97 code | 26 blank | 89 comment | 11 complexity | d3db0686f7dff176a1255ca43ad8b0e6 MD5 | raw file
  1. <?php
  2. namespace Horde\Socket;
  3. /**
  4. * Copyright 2013-2014 Horde LLC (http://www.horde.org/)
  5. *
  6. * See the enclosed file COPYING for license information (LGPL). If you
  7. * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  8. *
  9. * @category Horde
  10. * @copyright 2013-2014 Horde LLC
  11. * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
  12. * @package Socket_Client
  13. */
  14. /**
  15. * Utility interface for establishing a stream socket client.
  16. *
  17. * @author Michael Slusarz <slusarz@horde.org>
  18. * @category Horde
  19. * @copyright 2013-2014 Horde LLC
  20. * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
  21. * @package Socket_Client
  22. *
  23. * @property-read boolean $connected Is there an active connection?
  24. * @property-read boolean $secure Is the active connection secure?
  25. */
  26. class Client
  27. {
  28. /**
  29. * Is there an active connection?
  30. *
  31. * @var boolean
  32. */
  33. protected $_connected = false;
  34. /**
  35. * Configuration parameters.
  36. *
  37. * @var array
  38. */
  39. protected $_params;
  40. /**
  41. * Is the connection secure?
  42. *
  43. * @var boolean
  44. */
  45. protected $_secure = false;
  46. /**
  47. * Constructor.
  48. *
  49. * @param string $host Hostname of remote server.
  50. * @param integer $port Port number of remote server.
  51. * @param integer $timeout Connection timeout (in seconds).
  52. * @param mixed $secure Security layer requested. One of:
  53. * <pre>
  54. * - false (No encryption) [DEFAULT]
  55. * - 'ssl' (Auto-detect SSL version)
  56. * - 'sslv2' (Force SSL version 3)
  57. * - 'sslv3' (Force SSL version 2)
  58. * - 'tls' (TLS; started via protocol-level negotation over unencrypted
  59. * channel)
  60. * - 'tlsv1' (TLS version 1.x connection) (@since 1.1.0)
  61. * - true (TLS if available/necessary)
  62. * </pre>
  63. * @param array $params Additional options.
  64. *
  65. * @throws Horde\Socket\Client\Exception
  66. */
  67. public function __construct(
  68. $host, $port, $timeout = 30, $secure = false, array $params = array()
  69. )
  70. {
  71. if ($secure && !extension_loaded('openssl')) {
  72. if ($secure !== true) {
  73. throw new \InvalidArgumentException('Secure connections require the PHP openssl extension.');
  74. }
  75. $secure = false;
  76. }
  77. $this->_params = $params;
  78. $this->_connect($host, $port, $timeout, $secure);
  79. }
  80. /**
  81. */
  82. public function __get($name)
  83. {
  84. switch ($name) {
  85. case 'connected':
  86. return $this->_connected;
  87. case 'secure':
  88. return $this->_secure;
  89. }
  90. }
  91. /**
  92. * This object can not be cloned.
  93. */
  94. public function __clone()
  95. {
  96. throw new \LogicException('Object cannot be cloned.');
  97. }
  98. /**
  99. * This object can not be serialized.
  100. */
  101. public function __sleep()
  102. {
  103. throw new \LogicException('Object can not be serialized.');
  104. }
  105. /**
  106. * Start a TLS connection.
  107. *
  108. * @return boolean Whether TLS was successfully started.
  109. */
  110. public function startTls()
  111. {
  112. if ($this->connected &&
  113. !$this->secure &&
  114. (@stream_socket_enable_crypto($this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT) === true)) {
  115. $this->_secure = true;
  116. return true;
  117. }
  118. return false;
  119. }
  120. /**
  121. * Close the connection.
  122. */
  123. public function close()
  124. {
  125. if ($this->connected) {
  126. @fclose($this->_stream);
  127. $this->_connected = $this->_secure = false;
  128. $this->_stream = null;
  129. }
  130. }
  131. /* Internal methods. */
  132. /**
  133. * Connect to the remote server.
  134. *
  135. * @see __construct()
  136. *
  137. * @throws Horde\Socket\Client\Exception
  138. */
  139. protected function _connect($host, $port, $timeout, $secure, $retries = 0)
  140. {
  141. switch (strval($secure)) {
  142. case 'ssl':
  143. case 'sslv2':
  144. case 'sslv3':
  145. $conn = $secure . '://';
  146. $this->_secure = true;
  147. break;
  148. case 'tlsv1':
  149. $conn = 'tls://';
  150. $this->_secure = true;
  151. break;
  152. case 'tls':
  153. default:
  154. $conn = 'tcp://';
  155. break;
  156. }
  157. $this->_stream = @stream_socket_client(
  158. $conn . $host . ':' . $port,
  159. $error_number,
  160. $error_string,
  161. $timeout
  162. );
  163. if ($this->_stream === false) {
  164. /* From stream_socket_client() page: a function return of false,
  165. * with an error code of 0, indicates a "problem initializing the
  166. * socket". These kind of issues are seen on the same server
  167. * (and even the same user account) as sucessful connections, so
  168. * these are likely transient issues. Retry up to 3 times in these
  169. * instances. */
  170. if (!$error_number && ($retries < 3)) {
  171. return $this->_connect($host, $port, $timeout, $secure, ++$retries);
  172. }
  173. $e = new Client\Exception(
  174. 'Error connecting to server.'
  175. );
  176. $e->details = sprintf("[%u] %s", $error_number, $error_string);
  177. throw $e;
  178. }
  179. stream_set_timeout($this->_stream, $timeout);
  180. if (function_exists('stream_set_read_buffer')) {
  181. stream_set_read_buffer($this->_stream, 0);
  182. }
  183. stream_set_write_buffer($this->_stream, 0);
  184. $this->_connected = true;
  185. }
  186. }