<?php
class Timer{
function Timer(){
$this->start = explode(" ",microtime());
}
function current_time(){
$curr = explode(" ",microtime());
return $curr[1] - $this->start[0] - $this->start[1] + $curr[0];
}
}
ignore_user_abort(1);
set_time_limit(0);
//Configurations
$iPort_number = 6666;
$sAddress = 'localhost';
$sManagement_pass = 'hhbgzpqmhgyt67hjnyhapm8cb4sl75';
function error($mess){
$error_string = gmdate("[H:i:s] ").$mess;
if($fd = fopen(gmdate("d_m_y")."errors.txt","a+")){
$string = $error_string."\r\n";
fputs($fd,$string);
fclose($fd);
}
}
class Http_request{
function Http_request(){
$this->P_TYPE = 'GET';
$this->BUF = '';
$this->TIME = time();
$this->NEED = NULL;
$this->DATA = '';
$this->GET = array();
$this->POST = array();
$this->HEADERS = array();
$this->PSEGMENT = '';
$this->STATE = 0;
$this->KEY = '';
}
function add2buffer($sSring){
switch($this->P_TYPE){
case 'GET':
$this->BUF .= $sSring;
break;
case 'CCSIS':
$this->DATA .= $sSring;
$this->NEED -= strlen($sSring);
break;
case 'POST':
$this->PSEGMENT .= $sSring;
$this->NEED -= strlen($sSring);
break;
}
}
function parse_headers(){
if(substr($this->BUF,0,5) == 'CCSIS'){
/* skipped */
return 1;
}
return 0;
}
}
class CCSIS_client{
function CCSIS_client($rSock,$sKey){
$this->socket = $rSock;
/* skipped */
}
}
class Transfer_server{
function Transfer_server(){
global $sAddress,$sManagement_pass;
$this->RUN = 1;
$this->poll = array();
$this->server_ip = gethostbyname($sAddress);
$this->pasword = $sManagement_pass;
$this->write_stack = array(array(),array());
$this->my_mark = new Timer();
$this->read_stack = array(array(),array());
$this->pid_path = 'server.pid';
}
/* skipped */
function start(){
global $iPort_number,$sAddress;
if(file_exists($this->pid_path) && function_exists("posix_kill")){
$fp = fopen($this->pid_path,"r");
$pid = fgets($fp,64);
fclose($fp);
if(posix_kill($pid,0)) {
$this->error('Сервер уже запущен.');
exit;
}
unlink($this->pid_path);
}
if (!$this->client_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)){
$this->error("socket_create() failed: " . socket_strerror(socket_last_error($this->client_sock)));
}else if(!$ret = socket_bind($this->client_sock, $sAddress, $iPort_number)){
$this->error("socket_bind() failed: " . socket_strerror($ret));
socket_close($this->client_sock);
if(file_exists($this->pid_path)) {
$this->error("Server already running...");
exit;
}
}else if(!socket_listen($this->client_sock,50)){
$this->error("socket_listen() failed: " . socket_strerror(socket_last_error($this->client_sock)));
socket_shutdown($this->client_sock);
socket_close($this->client_sock);
}else if(!socket_set_option($this->client_sock,SOL_SOCKET,SO_REUSEADDR,1)){
$this->error(socket_strerror(socket_last_error($this->client_sock)));
}else{
$this->write_pid();
$iWait_s = null;
for($set = array($this->client_sock),$set_w = array();$this->RUN;$set_w = array_values($this->write_stack[0]),$set = array_values($this->read_stack[0]), $set[] = $this->client_sock){
if(socket_select($set,$set_w, $set_e = NULL,$iWait_s)){
if(in_array($this->client_sock, $set)){
if(!($client_s = socket_accept($this->client_sock))){
$this->error(socket_strerror(socket_last_error($this->client_sock)));
}else{
$this->add2read_stack($client_s);
}
unset($set[array_search($this->client_sock,$set)]);
}
$this->prepare_read_stack($set);
$this->send_write_stack($set_w);
}
}
socket_close($this->client_sock);
unlink($this->pid_path);
}
}
function add2write_stack($rSock,$sData,$client_id = 0){
if($client_id && isset($this->write_stack[1][$rSock])){
$this->write_stack[1][$rSock][0] .= $sData;
}else{
$this->write_stack[0][$rSock] = $rSock;
$this->write_stack[1][$rSock] = array($sData,$client_id);
}
}
function send_write_stack($send){
if(!empty($send)){
$err_mess = array();
foreach($send AS $rSock){
$iC_id = $this->write_stack[1][$rSock][1];
if(($iWritten = @socket_write($rSock,$this->write_stack[1][$rSock][0])) !== false && $iWritten < strlen($this->write_stack[1][$rSock][0])){
$this->write_stack[1][$rSock][0] = substr($this->write_stack[1][$rSock][0],$iWritten);
}else{
$this->unset_write_stack_item($rSock);
if($iWritten !== false){
if($iC_id == 0){
socket_shutdown($rSock);
socket_close($rSock);
}
}else{
if($iC_id){
$this->client_unset($iC_id);
}
}
}
$this->out_traffic += $iWritten;
}
foreach($err_mess AS $mess){
$this->server_mess($mess);
}
}
}
function add2read_stack($rSock){
$this->read_stack[0][$rSock] = $rSock;
$this->read_stack[1][$rSock] = new Http_request();
}
function prepare_read_stack($read){
if(!empty($read)){
foreach($read AS $rSock){
switch($this->read_stack[1][$rSock]->STATE){
case 0:
if($tmp = socket_read($rSock,35,PHP_BINARY_READ)){
$this->in_traffic += strlen($tmp);
if(strlen($tmp) + strlen($this->read_stack[1][$rSock]->BUF) >= 35){
/* skipped */
// start ab compatible hack.
$this->unset_read_stack_item($rSock);
$tmp = socket_read($rSock,3500,PHP_BINARY_READ);
$this->add2write_stack($rSock,"HTTP/1.0 200 OK\r\nServer: CCSIS update server/1.0a\r\nContent-Type: text/html; charset=windows-1251\r\n\r\nAccess denied.");
// end ab compatible hack.
/* skipped */
}else{
$this->read_stack[1][$rSock]->add2buffer($tmp);
}
}else{
$this->log("Соединение утеряно.");
$this->unset_read_stack_item($rSock);
socket_shutdown($rSock);
socket_close($rSock);
}
break;
case 1:
/* skipped */
break;
}
}
}
$this->clean_read_stack();
}
function unset_read_stack_item($rSock){
unset($this->read_stack[0][$rSock],$this->read_stack[1][$rSock]);
}
function unset_write_stack_item($rSock){
unset($this->write_stack[0][$rSock],$this->write_stack[1][$rSock]);
}
function clean_read_stack(){
foreach($this->read_stack[1] AS $rSock => $oValue){
if(time() - $oValue->TIME > 70){
socket_shutdown($this->read_stack[0][$rSock]);
socket_close($this->read_stack[0][$rSock]);
$this->unset_read_stack_item($rSock);
}
}
}
function prepare_http_request($rSock,$oHttp_request){
global $CCSIS_NS;
//fprint_r($oHttp_request,'prepare_http_request(');
if($struct = unserialize(my_decrypt($oHttp_request->DATA,$oHttp_request->KEY))){
foreach($struct AS $arr){
if(isset($arr['cmd'])){
if($arr['password'] == $this->pasword){
switch($arr['cmd']){
case "shutdown":
$this->RUN = 0;
$this->log('Server has been stopped');
break;
/* skipped */
case "srv_info":
$this->add2write_stack($rSock,serialize(array('memory'=>(function_exists('memory_get_usage')?memory_get_usage():'--'),'uptime' => $this->my_mark->current_time())));
break;
case "get_debug_info":
ob_start();
print_r($this);
$sData = ob_get_clean();
$this->add2write_stack($rSock,$sData);
break;
default:
$this->add2write_stack($rSock,sprintf('Unknown command "%s"',$arr['cmd'])."\r\n");
}
}
}else if(isset($arr['request'])){
switch($arr['request']){
case "status":
$this->add2write_stack($rSock,'Standby');
break;
/* skipped */
default:
$this->add2write_stack($rSock,sprintf('Unknown request "%s"',$arr['request'])."\r\n");
}
}
}
}else{
$this->add2write_stack($rSock,"HTTP/1.0 200 OK\r\nServer: CCSIS update server/1.0a\r\nContent-Type: text/html; charset=windows-1251\r\n\r\nAccess denied.");
$this->log("Broken data.");
}
}
function error($mess){
$error_string = gmdate("[H:i:s] ").$mess;
if($fd = fopen(gmdate("d_m_y")."errors.txt","a+")){
$string = $error_string."\r\n";
fputs($fd,$string);
fclose($fd);
}
}
function log($mess){
$this->error(sprintf('Server message: %s',$mess),0);
}
function write_pid(){
if($fp = fopen($this->pid_path,"w")) {
if(function_exists("posix_getpid")){
fputs($fp,posix_getpid());
}
fclose($fp);
}
}
}
$oServer = new Transfer_server;
$oServer->start();
?>