This repository has been archived on 2024-07-18. You can view files and clone it, but cannot push or open issues or pull requests.
lwb5/ircbot/connection.php

432 lines
10 KiB
PHP

<?php
/*
+---------------------------------------------------------------------------
| PHP-IRC v2.1.1 Service Release
| ========================================================
| by Manick
| (c) 2001-2004 by http://www.phpbots.org/
| Contact: manick@manekian.com
| irc: #manekian@irc.rizon.net
| ========================================
+---------------------------------------------------------------------------
| > connection class module
| > Module written by Manick
| > Module Version Number: 2.1.2
+---------------------------------------------------------------------------
| > This program is free software; you can redistribute it and/or
| > modify it under the terms of the GNU General Public License
| > as published by the Free Software Foundation; either version 2
| > of the License, or (at your option) any later version.
| >
| > This program is distributed in the hope that it will be useful,
| > but WITHOUT ANY WARRANTY; without even the implied warranty of
| > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| > GNU General Public License for more details.
| >
| > You should have received a copy of the GNU General Public License
| > along with this program; if not, write to the Free Software
| > Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+---------------------------------------------------------------------------
| Changes
| =======-------
| > If you wish to suggest or submit an update/change to the source
| > code, email me at manick@manekian.com with the change, and I
| > will look to adding it in as soon as I can.
+---------------------------------------------------------------------------
*/
/* Connection class. A Layer between dcc/irc class and socket class. */
/* To use, simply create an object, call the calls listed under the constructor in order. */
/* Damn I'm hungry... */
class connection {
//External Classes
private $socketClass;
private $ircClass;
private $timerClass;
//Internal variables
private $callbackClass;
private $host;
private $port;
private $connTimeout;
private $transTimeout;
private $sockInt;
//Function specific
private $connected;
private $connStartTime;
private $lastTransTime;
//If this is set to true, this connection class will no longer function.
private $error;
private $errorMsg;
//Called first
function __construct($host, $port, $connTimeout)
{
$this->error = true;
$this->errorMsg = "Connection not initialized";
$this->host = $host;
$this->port = $port;
$this->connTimeout = $connTimeout;
$this->transTimeout = 0;
$this->connected = false;
$this->sockInt = false;
}
//Called second
public function setSocketClass($class)
{
$this->socketClass = $class;
}
//Called third
public function setIrcClass($class)
{
$this->ircClass = $class;
}
//Called fourth
public function setCallbackClass($class)
{
$this->callbackClass = $class;
}
//Called fifth
public function setTimerClass($class)
{
$this->timerClass = $class;
}
//Called sixth
public function init()
{
$this->error = false;
if ($this->host != null)
{
if ($this->connTimeout <= 0)
{
$this->setError("Must set connection timeout > 0 for non-listening sockets");
return;
}
}
else
{
if ($this->connTimeout < 0)
{
$this->setError("Must set connection timeout >= 0 for listening sockets");
return;
}
}
if (!is_object($this->callbackClass))
{
$this->setError("Specified callback class is not an object");
return;
}
if (!is_object($this->socketClass))
{
$this->setError("Specified socket class is not an object");
return;
}
if (!is_object($this->ircClass))
{
$this->setError("Specified irc class is not an object");
return;
}
$sockInt = $this->socketClass->addSocket($this->host, $this->port); // add socket
if ($sockInt == false)
{
$this->setError("Could not create socket");
return;
}
$sockData = $this->socketClass->getSockData($sockInt);
$this->socketClass->setHandler($sockInt, $this->ircClass, $this, "handle");
//Set internal variables
if ($this->port == NULL)
{
$this->port = $sockData->port;
}
$this->sockInt = $sockInt;
return $this->port;
}
public function bind($ip)
{
if ($this->error != false || $this->sockInt == false)
{
return;
}
if ($this->connected == true)
{
return;
}
$this->socketClass->bindIP($this->sockInt, $ip);
}
//Called to listen, only called by onAccept() function in this class
public function listen()
{
$this->error = false;
$this->connected = true;
}
//Called last, and only to start connection to another server
public function connect()
{
if ($this->error == true)
{
return false;
}
if ($this->connTimeout > 0)
{
$this->timerClass->addTimer(irc::randomHash(), $this, "connTimeout", "", $this->connTimeout);
}
$this->timerClass->addTimer(irc::randomHash(), $this->socketClass, "connectSocketTimer", $this->sockInt, 1);
/* $this->socketClass->beginConnect($this->sockInt); */
$this->connStartTime = time();
}
public function disconnect()
{
unset($this->callbackClass);
$this->socketClass->killSocket($this->sockInt);
$this->socketClass->removeSocket($this->sockInt);
$this->setError("Disconnected from server");
}
public function getSockInt()
{
return $this->sockInt;
}
public function setSockInt($sockInt)
{
$this->sockInt = $sockInt;
}
public function setTransTimeout($time)
{
$this->transTimeout = ($time < 0 ? 0 : $time);
}
/* Timers */
public function connTimeout()
{
if ($this->connected == false)
{
$this->handle(CONN_CONNECT_TIMEOUT);
}
}
public function transTimeout()
{
if ($this->error == true)
{
return false;
}
if ($this->connected == false)
{
return true;
}
if ($this->transTimeout > 0)
{
if (time() > $this->transTimeout + $this->lastTransTime)
{
$this->handle(CONN_TRANSFER_TIMEOUT);
}
}
return true;
}
//handle function, handles all calls from socket class, and calls appropriate
//functions in the callback class
public function handle($msg)
{
if ($this->socketClass->getSockStatus($this->sockInt) === false)
{
return false;
}
$stat = false;
if ($this->error == true)
{
return false;
}
switch ($msg)
{
case CONN_CONNECT:
$stat = $this->onConnect();
break;
case CONN_READ:
$stat = $this->onRead();
break;
case CONN_WRITE:
$stat = $this->onWrite();
break;
case CONN_ACCEPT:
$stat = $this->onAccept();
break;
case CONN_DEAD:
$stat = $this->onDead();
break;
case CONN_TRANSFER_TIMEOUT:
$stat = $this->onTransferTimeout();
break;
case CONN_CONNECT_TIMEOUT:
$stat = $this->onConnectTimeout();
break;
default:
return false;
break;
}
return $stat;
}
/* Specific handling functions */
private function onTransferTimeout()
{
$this->callbackClass->onTransferTimeout($this);
}
private function onConnectTimeout()
{
$this->callbackClass->onConnectTimeout($this);
}
private function onConnect()
{
$this->connected = true;
if ($this->transTimeout > 0)
{
$this->timerClass->addTimer(irc::randomHash(), $this, "transTimeout", "", $this->transTimeout);
}
$this->callbackClass->onConnect($this);
return false;
}
//For this function, true can be returned from onRead() to input more data.
private function onRead()
{
$this->lastTransTime = time();
$stat = $this->callbackClass->onRead($this);
if ($stat !== true)
{
$this->socketClass->clearReadSchedule($this->sockInt);
}
return $stat;
}
private function onWrite()
{
$this->socketClass->clearWriteSchedule($this->sockInt);
$this->lastTransTime = time();
$this->callbackClass->onWrite($this);
return false;
}
private function onAccept()
{
//Get the sockInt from the socketClass
$newSockInt = $this->socketClass->hasAccepted($this->sockInt);
if ($newSockInt === false)
{
//False alarm.. just ignore it.
return false;
}
//Create a new connection object for the new socket connection, then return it to onAccept
//We must assume that onAccept will handle the connection object. Otherwise it'll die, and the
//connection will be orphaned.
$newConn = new connection(null, null, 0);
$newConn->setSocketClass($this->socketClass);
$newConn->setIrcClass($this->ircClass);
$newConn->setCallbackClass($this->callbackClass); //Can be overwritten in the onAccept function
$newConn->setTimerClass($this->timerClass);
$newConn->listen();
//We don't need to call init(), we're already setup.
//Setup our connection transmission timeout thing.
if ($this->transTimeout > 0)
{
$this->timerClass->addTimer(irc::randomHash(), $newConn, "transTimeout", "", $this->transTimeout);
}
$newConn->setTransTimeout($this->transTimeout);
//Set handler for our new sockInt to new connection class
$this->socketClass->setHandler($newSockInt, $this->ircClass, $newConn, "handle");
//Set our new sockInt
$newConn->setSockInt($newSockInt);
//Call our callback function for accepting with old object, and new object.
$this->callbackClass->onAccept($this, $newConn);
return false;
}
private function onDead()
{
if ($this->connected == true)
{
$this->setError("Connection is dead");
}
else
{
$this->setError("Could not connect: " . $this->socketClass->getSockStringError($this->sockInt));
}
$this->callbackClass->onDead($this);
return false;
}
/* Error handling routines */
private function setError($msg)
{
$this->error = true;
$this->errorMsg = $msg;
}
public function getError()
{
return $this->error;
}
public function getErrorMsg()
{
return $this->errorMsg;
}
}
?>