3 * Cake Socket connection class.
7 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8 * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
10 * Licensed under The MIT License
11 * Redistributions of files must retain the above copyright notice.
13 * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
14 * @link http://cakephp.org CakePHP(tm) Project
16 * @subpackage cake.cake.libs
17 * @since CakePHP(tm) v 1.2.0
18 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
20 App
::import('Core', 'Validation');
23 * Cake network socket connection class.
25 * Core base class for network communication.
28 * @subpackage cake.cake.libs
30 class CakeSocket
extends Object {
38 var $description = 'Remote DataSource Network Socket Interface';
41 * Base configuration settings for the socket connection
46 var $_baseConfig = array(
47 'persistent' => false,
48 'host' => 'localhost',
55 * Configuration settings for the socket connection
60 var $config = array();
63 * Reference to socket connection resource
68 var $connection = null;
71 * This boolean contains the current state of the CakeSocket class
76 var $connected = false;
79 * This variable contains an array with the last error number (num) and string (str)
84 var $lastError = array();
89 * @param array $config Socket configuration, which will be merged with the base configuration
90 * @see CakeSocket::$_baseConfig
92 function __construct($config = array()) {
93 parent
::__construct();
95 $this->config
= array_merge($this->_baseConfig
, $config);
96 if (!is_numeric($this->config
['protocol'])) {
97 $this->config
['protocol'] = getprotobyname($this->config
['protocol']);
102 * Connect the socket to the given host and port.
104 * @return boolean Success
108 if ($this->connection
!= null) {
113 if (isset($this->config
['request']) && $this->config
['request']['uri']['scheme'] == 'https') {
117 if ($this->config
['persistent'] == true) {
119 $this->connection
= @pfsockopen
($scheme.$this->config
['host'], $this->config
['port'], $errNum, $errStr, $this->config
['timeout']);
121 $this->connection
= @fsockopen
($scheme.$this->config
['host'], $this->config
['port'], $errNum, $errStr, $this->config
['timeout']);
124 if (!empty($errNum) ||
!empty($errStr)) {
125 $this->setLastError($errNum, $errStr);
128 $this->connected
= is_resource($this->connection
);
129 if ($this->connected
) {
130 stream_set_timeout($this->connection
, $this->config
['timeout']);
132 return $this->connected
;
136 * Get the host name of the current connection.
138 * @return string Host name
142 if (Validation
::ip($this->config
['host'])) {
143 return gethostbyaddr($this->config
['host']);
145 return gethostbyaddr($this->address());
150 * Get the IP address of the current connection.
152 * @return string IP address
156 if (Validation
::ip($this->config
['host'])) {
157 return $this->config
['host'];
159 return gethostbyname($this->config
['host']);
164 * Get all IP addresses associated with the current connection.
166 * @return array IP addresses
169 function addresses() {
170 if (Validation
::ip($this->config
['host'])) {
171 return array($this->config
['host']);
173 return gethostbynamel($this->config
['host']);
178 * Get the last error as a string.
180 * @return string Last error
183 function lastError() {
184 if (!empty($this->lastError
)) {
185 return $this->lastError
['num'] . ': ' . $this->lastError
['str'];
192 * Set the last error.
194 * @param integer $errNum Error code
195 * @param string $errStr Error string
198 function setLastError($errNum, $errStr) {
199 $this->lastError
= array('num' => $errNum, 'str' => $errStr);
203 * Write data to the socket.
205 * @param string $data The data to write to the socket
206 * @return boolean Success
209 function write($data) {
210 if (!$this->connected
) {
211 if (!$this->connect()) {
215 $totalBytes = strlen($data);
216 for ($written = 0, $rv = 0; $written < $totalBytes; $written +
= $rv) {
217 $rv = fwrite($this->connection
, substr($data, $written));
218 if ($rv === false ||
$rv === 0) {
226 * Read data from the socket. Returns false if no data is available or no connection could be
229 * @param integer $length Optional buffer length to read; defaults to 1024
230 * @return mixed Socket data
233 function read($length = 1024) {
234 if (!$this->connected
) {
235 if (!$this->connect()) {
240 if (!feof($this->connection
)) {
241 $buffer = fread($this->connection
, $length);
242 $info = stream_get_meta_data($this->connection
);
243 if ($info['timed_out']) {
244 $this->setLastError(E_WARNING
, __('Connection timed out', true));
254 * Abort socket operation.
256 * @return boolean Success
263 * Disconnect the socket from the current connection.
265 * @return boolean Success
268 function disconnect() {
269 if (!is_resource($this->connection
)) {
270 $this->connected
= false;
273 $this->connected
= !fclose($this->connection
);
275 if (!$this->connected
) {
276 $this->connection
= null;
278 return !$this->connected
;
282 * Destructor, used to disconnect from current connection.
286 function __destruct() {
291 * Resets the state of this Socket instance to it's initial state (before Object::__construct got executed)
293 * @return boolean True on success
296 function reset($state = null) {
298 static $initalState = array();
299 if (empty($initalState)) {
300 $initalState = get_class_vars(__CLASS__
);
302 $state = $initalState;
305 foreach ($state as $property => $value) {
306 $this->{$property} = $value;