<?php
//
// +--------------------------------------------------------------------------+
// | |
// | XS PHP Library Generic Classes Library |
// | |
// | Copyright (c) 2001-2002 XSPHPLib Group. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Distributed under the terms of the GNU Lesser General Public License as |
// | published by the Free Software Foundation version 2.1 |
// | See the GNU Lesser General Public License for more details. You should |
// | have received a copy of the GNU Lesser General Public License along with |
// | this package; if not, write to the Free Software Foundation, Inc., |
// | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Authors: Robert Bala <hide@address.com> |
// | |
// +--------------------------------------------------------------------------+
//
// $Id: socket.inc.php,v 1.2 2002/11/28 09:50:30 rbala Exp $
/**
* Generalized Socket class.
*
* Socket class enables comfortable handling Socket connections.
*
* @author Robert Bala <hide@address.com>
* @access public
* @package net
* @version $Id: socket.inc.php,v 1.2 2002/11/28 09:50:30 rbala Exp $
*/
class Socket extends Object {
/**
* IP address or host name.
* @access private
* @var string
*/
var $_host;
/**
* TCP port number.
* @access private
* @var int
*/
var $_port;
/**
* Number of bytes to read and write at IO operations.
* @access private
* @var int
*/
var $_buffer;
/**
* Socket handle.
* @access private
* @var mixed
*/
var $_handle;
/**
* Whether the socket is blocking.
* @access private
* @var boolean
*/
var $_blocked;
/**
* Number of seconds to wait on socket connections.
*
* @access private
* @var int
*/
var $_timeout;
/**
* Socket class constructor.
*
* Creates the new instance of Socket class and sets up basic properties.
*
* @access public
* @param string $host IP address or host name, defaults to "".
* @param int $port TCP port number, defaults to 0.
* @param int $timeout number of seconds to wait on socket connections (optional), defaults to 180.
* @param int $buffer number of bytes to read and write at IO operations (optional), defaults to 1024.
* @return void
*/
function Socket($host='', $port=0, $timeout=180, $buffer=1024) {
Object::Object();
$this->_host = $host;
$this->_port = $port % 65536;
$this->_buffer = $buffer;
$this->_handle = null;
$this->_blocked = true;
$this->_timeout = $timeout;
}
/**
* Gets the socket IP address or host name.
*
* Returns IP address or host name.
*
* @access public
* @return string
*/
function getHost() {
return $this->_host;
}
/**
* Gets the socket TCP port number.
*
* Returns TCP port number.
*
* @access public
* @return int
*/
function getPort() {
return $this->_port;
}
/**
* Gets the socket buffer size.
*
* Returns number of bytes used at socket IO operations.
*
* @access public
* @return int
*/
function getBuffer() {
return $this->_buffer;
}
/**
* Gets the socket handle.
*
* Returns resource handle if the socket connection is opened, null otherwise.
*
* @access public
* @return mixed
*/
function getHandle() {
return $this->_handle;
}
/**
* Gets the socket timed out waiting for data.
*
* Returns number of seconds socket should wait for data.
*
* @access public
* @return int
*/
function getTimeout() {
return $this->_timeout;
}
/**
* Sets the socket IP address or host name.
*
* Returns True on success or a error object if the socket is already
* opened.
*
* @access public
* @return mixed
*/
function setHost($host) {
if (!is_resource($this->_handle)) {
$this->_host = $host;
} else {
return new Error('sethost(): Socket connection already established.');
}
return true;
}
/**
* Sets the socket TCP port number.
*
* Returns True on success or a error object if the socket is already
* opened.
*
* @access public
* @return mixed
*/
function setPort($port) {
if (!is_resource($this->_handle)) {
$this->_port = $port % 65536;
} else {
return new Error('setport(): Socket connection already established.');
}
return true;
}
/**
* Sets the socket buffer size.
*
* Returns True on success or a error object if the buffer size is not a
* valid integer value.
*
* @access public
* @return mixed
*/
function setBuffer($buffer) {
if (is_integer($buffer)) {
$this->_buffer = $buffer;
} else {
return new Error('setbuffer(): Invalid socket buffer size.');
}
return true;
}
/**
* Sets the socket timed out waiting for data.
*
* Returns True on success or a error object if the socket is already
* opened.
*
* @access public
* @return mixed
*/
function setTimeout($timeout) {
if (!is_resource($this->_handle)) {
$this->_timeout = $timeout;
} else {
return new Error('settimeout(): Socket connection already established.');
}
return true;
}
/**
* Opens socket connection.
*
* If called when the socket is already opened, it returns error object
* otherwise it returns true.
*
* @access public
* @return mixed
*/
function open() {
if (!is_resource($this->_handle)) {
$errno = 0;
$errstr = '';
if ($this->_timeout) {
$handle = @fsockopen($this->_host, $this->_port, $errno, $errstr, $this->_timeout);
} else {
$handle = @fsockopen($this->_host, $this->_port, $errno, $errstr);
}
if (!is_resource($handle)) {
return new Error('open(): ' . $errstr, $errno);
}
$this->_handle = $handle;
} else {
return new Error('open(): Socket connection already established');
}
return true;
}
/**
* Disconnects from the peer, closes the socket.
*
* If called when the socket is closed or it couldn't be closed,
* it returns error object, otherwise it returns true.
*
* @access public
* @return mixed
*/
function close() {
if (is_resource($this->_handle)) {
if (@fclose($this->_handle)) {
$this->_handle = null;
} else {
return new Error('close(): Socket could not be disconnected.');
}
} else {
return new Error('close(): Socket connection not established.');
}
return true;
}
/**
* Returns information about an existing socket resource.
*
* If called when the socket is closed, it returns error object,
* otherwise returns information about an existing socket resource.
* Currently returns four entries in the result array: timed_out (bool) -
* The socket timed out waiting for data, blocked (bool) - The socket was
* blocked, eof (bool) - Indicates EOF event unread_bytes (int) - Number
* of bytes left in the socket buffer.
*
* @access public
* @return mixed
*/
function status() {
if (is_resource($this->_handle)) {
return @socket_get_status($this->_handle);
}
return new Error('status(): Socket connection not established.');
}
/**
* Sets blocking socket connection.
*
* A read call to a blocking socket will wait for data to become available
* on the stream. If called when the socket is closed, it returns error
* object, otherwise returns true.
*
* @access public
* @return mixed
*/
function block() {
if (is_resource($this->_handle)) {
if (@socket_set_blocking($this->_handle, TRUE)) {
$this->_blocked = true;
} else {
return new Error('block(): Socket could not be blocked.');
}
} else {
return new Error('block(): Socket connection not established.');
}
return true;
}
/**
* Sets non-blocking socket connection.
*
* A read call to a non-blocking socket will return immediately if there is
* no data available on the stream. If called when the socket is closed, it
* returns error object, otherwise returns true.
*
* @access public
* @return mixed
*/
function unblock() {
if (is_resource($this->_handle)) {
if (@socket_set_blocking($this->_handle, FALSE)) {
$this->_blocked = false;
} else {
return new Error('unblock(): Socket could not be unblocked.');
}
} else {
return new Error('unblock(): Socket connection not established.');
}
return true;
}
/**
* Read data from a socket connection.
*
* Reads up to the socket buffer size from the socket connection. Reading
* stops when the socket buffer size have been read or end-of-stream
* reached, whichever comes first. If called when the socket is closed, it
* returns error object otherwise it returns fread() result.
*
* @access public
* @return mixed
*/
function read() {
if (is_resource($this->_handle)) {
$result = '';
while (!feof($this->_handle)) {
$result .= @fread($this->_handle, $this->_buffer);
}
return $result;
}
return new Error('read(): Socket connection not established.');
}
/**
* Write data to a socket connection.
*
* Write data to a socket connection. Writing will stop after socket buffer
* length bytes have been written or the end of string is reached, whichever
* comes first. If called when the socket is closed, it returns error object
* otherwise it returns fwrite() result.
*
* @access public
* @param string $string the data to write.
* @return mixed
*/
function write($string) {
if (is_resource($this->_handle)) {
return @fwrite($this->_handle, $string, $this->_buffer);
}
return new Error('write(): Socket connection not established.');
}
/**
* Read a line of data from a socket connection.
*
* Read until either the end of the socket or a newline, whichever comes
* first. If called when the socket is closed, it returns error object
* otherwise it returns all available data up to a newline, without
* that newline, or until the end of the socket as string.
*
* @access public
* @return mixed
*/
function readLine() {
if (is_resource($this->_handle)) {
$result = '';
$timeout = time() + $this->_timeout;
while (!feof($this->_handle) && (!$this->_timeout || time() < $timeout)) {
$result .= @fgets($this->_handle, $this->_buffer);
if (ereg("\r\n|\n", $result)) {
return ereg_replace("\r\n|\n", "", $result);
}
}
return $result;
}
return new Error('readline(): Socket connection not established.');
}
/**
* Write a line of data to a socket connection.
*
* Write a line of data to the socket, followed by a trailing "\r\n".
* If called when the socket is closed, it returns error object
* otherwise it returns fputs result.
*
* @access public
* @param string $string the data to write.
* @return mixed
*/
function writeLine($string) {
if (is_resource($this->_handle)) {
return @fputs($this->_handle, $string . "\r\n");
}
return new Error('writeline(): Socket connection not established.');
}
/**
* Read buffer from a socket connection.
*
* Reads up to the specified buffer size from the socket connection. Reading
* stops when the specified buffer size have been read or end-of-stream
* reached, whichever comes first. If called when the socket is closed,
* it returns error object otherwise it returns fread() result.
*
* @access public
* @param string $buffer the data to read.
* @param int $length the buffer length, defaults to 0.
* @return mixed
*/
function readBuffer(&$buffer, $length=0) {
if (is_resource($this->_handle)) {
$buffer = '';
if ($length > 0) {
$buffer = @fread($this->_handle, $length);
} else {
$buffer = @fread($this->_handle, $this->_buffer);
}
return strlen($buffer);
}
return new Error('readbuffer(): Socket connection not established.');
}
/**
* Write buffer to a socket connection.
*
* Write data to a socket connection. Writing will stop after specified
* buffer length bytes have been written or the end of string is reached,
* whichever comes first. If called when the socket is closed, it returns
* error object otherwise it returns fwrite() result.
*
* @access public
* @param string $buffer the data to write.
* @param int $length the buffer length, defaults to 0.
* @return mixed
*/
function writeBuffer(&$buffer, $length=0) {
if (is_resource($this->_handle)) {
if ($length > 0) {
return @fwrite($this->_handle, $buffer, $length);
} else {
return @fwrite($this->_handle, $buffer, $this->_buffer);
}
}
return new Error('writebuffer(): Socket connection not established.');
}
/**
* Finds whether the socket is at end-of-stream or closed.
*
* Returns true if the socket connection is closed or input stream finished,
* false otherwise.
*
* @access public
* @return boolean
*/
function isEof() {
return (is_null($this->_handle) || feof($this->_handle));
}
/**
* Finds whether the socket is opened.
*
* Returns true if the socket connection is opened, false otherwise.
*
* @access public
* @return boolean
*/
function isOpened() {
return is_resource($this->_handle);
}
/**
* Finds whether the socket connection is blocked.
*
* Returns true if the socket connection is blocked, false otherwise.
*
* @access public
* @return boolean
*/
function isBlocked() {
return $this->_blocked;
}
}
?>