Tryag File Manager
Home
||
Turbo Force
||
B-F Config_Cpanel
Current Path :
/
home
/
nongapp.eemo.co.kr
/
public_html
/
www
/
Or
Select Your Path :
Upload File :
New :
File
Dir
/home/nongapp.eemo.co.kr/public_html/www/websockets.php
<?php //require_once('./daemonize.php'); $wshome="/home/nongapp.eemo.co.kr/public_html/www"; require_once($wshome.'/users.php'); abstract class WebSocketServer { protected $userClass = 'WebSocketUser'; // redefine this if you want a custom user class. The custom user class should inherit from WebSocketUser. protected $maxBufferSize; protected $master; protected $master2; protected $sockets = array(); protected $sockets2 = array(); protected $users = array(); protected $interactive = true; protected $headerOriginRequired = false; protected $headerSecWebSocketProtocolRequired = false; protected $headerSecWebSocketExtensionsRequired = false; function __construct($addr, $port, $bufferLength = 2048) { $this->maxBufferSize = $bufferLength; $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Failed: socket_create()"); $this->master2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Failed: socket_create()"); socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("Failed: socket_option()"); socket_set_option($this->master2, SOL_SOCKET, SO_REUSEADDR, 1) or die("Failed: socket_option()"); socket_bind($this->master, $addr, $port) or die("Failed: socket_bind()"); socket_bind($this->master2, $addr, 843) or die("Failed: socket_bind()"); socket_listen($this->master,20) or die("Failed: socket_listen()"); socket_listen($this->master2,20) or die("Failed: socket_listen()"); socket_set_nonblock($this->master); socket_set_nonblock($this->master2); $this->sockets[] = $this->master; $this->sockets2[] = $this->master2; $this->stdout("Server started\nListening on: $addr:$port\nMaster socket: ".$this->master); global $WSSERIP; while(true) { //$db=mysql_pconnect($WSSERIP,"root","web!@#") or die(mysql_error()); //mysql_select_db("tophorsev2") or die(mysql_error()); $this->wupdate(); if (empty($this->sockets)) { $this->sockets[] = $master; } if (empty($this->sockets2)) { $this->sockets2[] = $master2; } $read = $this->sockets; $read2 = $this->sockets2; $write = $except = null; $write2 = $except2 = null; socket_select($read2,$write2,$except2,0); foreach ($read2 as $socket2) { if ($socket2 == $this->master2) { $client2 = socket_accept($socket2); if ($client2 < 0) { $this->stderr("Failed: socket_accept()"); continue; } else { $this->connect($client2); $policy='<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>'; socket_write($client2,$policy,strlen($policy)); $this->disconnect($socket2); } } else { } } socket_select($read,$write,$except,1); foreach ($read as $socket) { if ($socket == $this->master) { $client = socket_accept($socket); if ($client < 0) { $this->stderr("Failed: socket_accept()"); continue; } else { $this->connect($client); } } else { $numBytes = @socket_recv($socket,$buffer,$this->maxBufferSize,0); // todo: if($numBytes === false) { error handling } elseif ($numBytes === 0) { remote client disconected } if ($numBytes == 0) { $this->disconnect($socket); } else { $user = $this->getUserBySocket($socket); if (!$user->handshake) { $this->doHandshake($user,$buffer); } else { $bufferC=substr($buffer, 1, strlen($buffer)-2); $tmp_b64buff=base64_decode(trim($bufferC)); $tmp_buff=substr($tmp_b64buff,0,8); if(substr($tmp_buff,0,8)=="[-064**]") { $sn_msg=substr($tmp_b64buff,8); $sn_msg64=base64_encode($sn_msg); //echo "msg: ".$sn_msg64."\n"; $this->process2($user, $sn_msg64); } else { if ($messageC = $this->frame_decode($buffer)) { //echo "소켓메시지 : ".$message."\n"; $this->process($user, $messageC); if($user->hasSentClose) { $this->disconnect($user->socket); } } else { do { $numByte = @socket_recv($socket,$buffer,$this->maxBufferSize,MSG_PEEK); if ($numByte > 0) { $numByte = @socket_recv($socket,$buffer,$this->maxBufferSize,0); if ($messageC = $this->deframe($buffer,$user)) { //echo $message."\n"; $this->process($user,$messageC); if($user->hasSentClose) { $this->disconnect($user->socket); } } } } while($numByte > 0); } } } } } } //-->foreach //mysql_close($db); } //-->while(true) } abstract protected function process($user,$message); // Calked immediately when the data is recieved. abstract protected function process2($user,$message); // Calked immediately when the data is recieved. abstract protected function connected($user); // Called after the handshake response is sent to the client. abstract protected function closed($user); // Called after the connection is closed. abstract protected function wupdate(); // Called after the connection is closed. protected function frame_decode($payload) { if (!isset($payload)) return null; //empty data return nothing $length = ord($payload[1]) & 127; if($length == 126) { $masks = substr($payload, 4, 4); $data = substr($payload, 8); } elseif($length == 127) { $masks = substr($payload, 10, 4); $data = substr($payload, 14); } else { $masks = substr($payload, 2, 4); $data = substr($payload, 6); } for ($i = 0; $i < strlen($masks); ++$i) { $this->say("header[".$i."] =". ord($masks[$i]). " \n"); } //$this->say(" data:$data \n"); //did we just get a PING frame if (strlen($masks)==4 && strlen($data)==0) { return "ping"; } $text = ''; for ($i = 0; $i < strlen($data); ++$i) { $text .= $data[$i] ^ $masks[$i%4]; } return $text; } //end of frame_decode unmask(Received from client) protected function say($msg=""){ //echo $msg."\n"; } //display server console messages protected function send($user,$message) { //$this->stdout("> $message"); $message = $this->frame($message,$user); socket_write($user->socket,$message,strlen($message)); } protected function connect($socket) { @socket_getpeername($socket, $clientIP); $user = new $this->userClass(uniqid(),$socket, $clientIP); array_push($this->users,$user); array_push($this->sockets,$socket); echo $clientIP." : Server Connected\n"; } protected function disconnect($socket,$triggerClosed=true) { $foundUser = null; $foundSocket = null; foreach ($this->users as $key => $user) { if ($user->socket == $socket) { $foundUser = $key; $disconnectedUser = $user; break; } } if ($foundUser !== null) { unset($this->users[$foundUser]); $this->users = array_values($this->users); } foreach ($this->sockets as $key => $sock) { if ($sock == $socket) { $foundSocket = $key; break; } } if ($foundSocket !== null) { unset($this->sockets[$foundSocket]); $this->sockets = array_values($this->sockets); } if ($triggerClosed) { $this->closed($disconnectedUser); } } protected function doHandshake($user, $buffer) { $magicGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; $headers = array(); $lines = explode("\n",$buffer); foreach ($lines as $line) { if (strpos($line,":") !== false) { $header = explode(":",$line,2); $headers[strtolower(trim($header[0]))] = trim($header[1]); } else if (stripos($line,"get ") !== false) { preg_match("/GET (.*) HTTP/i", $buffer, $reqResource); $headers['get'] = trim($reqResource[1]); } } if (isset($headers['sec-websocket-version']) || strtolower($headers['sec-websocket-version']) == 13) { if (isset($headers['get'])) { $user->requestedResource = $headers['get']; } else { // todo: fail the connection $handshakeResponse = "HTTP/1.1 405 Method Not Allowed\r\n\r\n"; } if (!isset($headers['host']) || !$this->checkHost($headers['host'])) { $handshakeResponse = "HTTP/1.1 400 Bad Request"; } if (!isset($headers['upgrade']) || strtolower($headers['upgrade']) != 'websocket') { $handshakeResponse = "HTTP/1.1 400 Bad Request"; } if (!isset($headers['connection']) || strpos(strtolower($headers['connection']), 'upgrade') === FALSE) { $handshakeResponse = "HTTP/1.1 400 Bad Request"; } if (!isset($headers['sec-websocket-key'])) { $handshakeResponse = "HTTP/1.1 400 Bad Request"; } else { } if (!isset($headers['sec-websocket-version']) || strtolower($headers['sec-websocket-version']) != 13) { $handshakeResponse = "HTTP/1.1 426 Upgrade Required\r\nSec-WebSocketVersion: 13"; } if (($this->headerOriginRequired && !isset($headers['origin']) ) || ($this->headerOriginRequired && !$this->checkOrigin($headers['origin']))) { $handshakeResponse = "HTTP/1.1 403 Forbidden"; } if (($this->headerSecWebSocketProtocolRequired && !isset($headers['sec-websocket-protocol'])) || ($this->headerSecWebSocketProtocolRequired && !$this->checkWebsocProtocol($header['sec-websocket-protocol']))) { $handshakeResponse = "HTTP/1.1 400 Bad Request"; } if (($this->headerSecWebSocketExtensionsRequired && !isset($headers['sec-websocket-extensions'])) || ($this->headerSecWebSocketExtensionsRequired && !$this->checkWebsocExtensions($header['sec-websocket-extensions']))) { $handshakeResponse = "HTTP/1.1 400 Bad Request"; } // Done verifying the _required_ headers and optionally required headers. if (isset($handshakeResponse)) { socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse)); $this->disconnect($user->socket); return false; } $user->headers = $headers; $user->handshake = $buffer; $webSocketKeyHash = sha1($headers['sec-websocket-key'] . $magicGUID); $rawToken = ""; for ($i = 0; $i < 20; $i++) { $rawToken .= chr(hexdec(substr($webSocketKeyHash,$i*2, 2))); } $handshakeToken = base64_encode($rawToken) . "\r\n"; $subProtocol = (isset($headers['sec-websocket-protocol'])) ? $this->processProtocol($headers['sec-websocket-protocol']) : ""; $extensions = (isset($headers['sec-websocket-extensions'])) ? $this->processExtensions($headers['sec-websocket-extensions']) : ""; $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $handshakeToken$subProtocol$extensions\r\n"; socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse)); $this->connected($user); } else { $user->headers = $headers; $user->handshake = $buffer; list($resource, $headers, $securityCode) = $this->handleRequestHeader($buffer); $securityResponse = ''; if (isset($headers['Sec-WebSocket-Key1']) && isset($headers['Sec-WebSocket-Key2'])) { $securityResponse = $this->getHandshakeSecurityKey($headers['Sec-WebSocket-Key1'], $headers['Sec-WebSocket-Key2'], $securityCode); } if ($securityResponse) { $handshakeResponse = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: WebSocket\r\n" . "Connection: Upgrade\r\n" . "Sec-WebSocket-Origin: " . $headers['Origin'] . "\r\n" . "Sec-WebSocket-Location: ws://" . $headers['Host'] . $resource . "\r\n" . "\r\n".$securityResponse; } else { $handshakeResponse = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: WebSocket\r\n" . "Connection: Upgrade\r\n" . "WebSocket-Origin: " . $headers['Origin'] . "\r\n" . "WebSocket-Location: ws://" . $headers['Host'] . $resource . "\r\n" . "\r\n"; } socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse)); $this->connected($user); } } protected function checkHost($hostName) { return true; // Override and return false if the host is not one that you would expect. // Ex: You only want to accept hosts from the my-domain.com domain, // but you receive a host from malicious-site.com instead. } protected function checkOrigin($origin) { return true; // Override and return false if the origin is not one that you would expect. } protected function checkWebsocProtocol($protocol) { return true; // Override and return false if a protocol is not found that you would expect. } protected function checkWebsocExtensions($extensions) { return true; // Override and return false if an extension is not found that you would expect. } protected function processProtocol($protocol) { return ""; // return either "Sec-WebSocket-Protocol: SelectedProtocolFromClientList\r\n" or return an empty string. // The carriage return/newline combo must appear at the end of a non-empty string, and must not // appear at the beginning of the string nor in an otherwise empty string, or it will be considered part of // the response body, which will trigger an error in the client as it will not be formatted correctly. } protected function processExtensions($extensions) { return ""; // return either "Sec-WebSocket-Extensions: SelectedExtensions\r\n" or return an empty string. } protected function getUserBySocket($socket) { foreach ($this->users as $user) { if ($user->socket == $socket) { return $user; } } return null; } protected function getUserByIP($ip) { foreach ($this->users as $user) { if ($user->ip == $ip) { return $user; } } return null; } protected function stdout($message) { if ($this->interactive) { echo "$message\n"; } } protected function stderr($message) { if ($this->interactive) { echo "$message\n"; } } protected function frame($message, $user, $messageType='text', $messageContinues=false) { switch ($messageType) { case 'continuous': $b1 = 0; break; case 'text': $b1 = ($user->sendingContinuous) ? 0 : 1; break; case 'binary': $b1 = ($user->sendingContinuous) ? 0 : 2; break; case 'close': $b1 = 8; break; case 'ping': $b1 = 9; break; case 'pong': $b1 = 10; break; } if ($messageContinues) { $user->sendingContinuous = true; } else { $b1 += 128; $user->sendingContinuous = false; } $length = strlen($message); $lengthField = ""; if ($length < 126) { $b2 = $length; } elseif ($length <= 65536) { $b2 = 126; $hexLength = dechex($length); //$this->stdout("Hex Length: $hexLength"); if (strlen($hexLength)%2 == 1) { $hexLength = '0' . $hexLength; } $n = strlen($hexLength) - 2; for ($i = $n; $i >= 0; $i=$i-2) { $lengthField = chr(hexdec(substr($hexLength, $i, 2))) . $lengthField; } while (strlen($lengthField) < 2) { $lengthField = chr(0) . $lengthField; } } else { $b2 = 127; $hexLength = dechex($length); if (strlen($hexLength)%2 == 1) { $hexLength = '0' . $hexLength; } $n = strlen($hexLength) - 2; for ($i = $n; $i >= 0; $i=$i-2) { $lengthField = chr(hexdec(substr($hexLength, $i, 2))) . $lengthField; } while (strlen($lengthField) < 8) { $lengthField = chr(0) . $lengthField; } } return chr($b1) . chr($b2) . $lengthField . $message; } protected function deframe($message, $user) { //echo $this->strtohex($message); $headers = $this->extractHeaders($message); $pongReply = false; $willClose = false; switch($headers['opcode']) { case 0: case 1: case 2: break; case 8: // todo: close the connection $user->hasSentClose = true; return ""; case 9: $pongReply = true; case 10: break; default: //$this->disconnect($user); // todo: fail connection $willClose = true; break; } if ($user->handlingPartialPacket) { $message = $user->partialBuffer . $message; $user->handlingPartialPacket = false; return $this->deframe($message, $user); } if ($this->checkRSVBits($headers,$user)) { return false; } if ($willClose) { // todo: fail the connection return false; } $payload = $user->partialMessage . $this->extractPayload($message,$headers); if ($pongReply) { $reply = $this->frame($payload,$user,'pong'); socket_write($user->socket,$reply,strlen($reply)); return false; } if (extension_loaded('mbstring')) { if ($headers['length'] > mb_strlen($payload)) { $user->handlingPartialPacket = true; $user->partialBuffer = $message; return false; } } else { if ($headers['length'] > strlen($payload)) { $user->handlingPartialPacket = true; $user->partialBuffer = $message; return false; } } $payload = $this->applyMask($headers,$payload); if ($headers['fin']) { $user->partialMessage = ""; return $payload; } $user->partialMessage = $payload; return false; } protected function extractHeaders($message) { $header = array('fin' => $message[0] & chr(128), 'rsv1' => $message[0] & chr(64), 'rsv2' => $message[0] & chr(32), 'rsv3' => $message[0] & chr(16), 'opcode' => ord($message[0]) & 15, 'hasmask' => $message[1] & chr(128), 'length' => 0, 'mask' => ""); $header['length'] = (ord($message[1]) >= 128) ? ord($message[1]) - 128 : ord($message[1]); if ($header['length'] == 126) { if ($header['hasmask']) { $header['mask'] = $message[4] . $message[5] . $message[6] . $message[7]; } $header['length'] = ord($message[2]) * 256 + ord($message[3]); } elseif ($header['length'] == 127) { if ($header['hasmask']) { $header['mask'] = $message[10] . $message[11] . $message[12] . $message[13]; } $header['length'] = ord($message[2]) * 65536 * 65536 * 65536 * 256 + ord($message[3]) * 65536 * 65536 * 65536 + ord($message[4]) * 65536 * 65536 * 256 + ord($message[5]) * 65536 * 65536 + ord($message[6]) * 65536 * 256 + ord($message[7]) * 65536 + ord($message[8]) * 256 + ord($message[9]); } elseif ($header['hasmask']) { $header['mask'] = $message[2] . $message[3] . $message[4] . $message[5]; } //echo $this->strtohex($message); //$this->printHeaders($header); return $header; } protected function extractPayload($message,$headers) { $offset = 2; if ($headers['hasmask']) { $offset += 4; } if ($headers['length'] > 65535) { $offset += 8; } elseif ($headers['length'] > 125) { $offset += 2; } return substr($message,$offset); } protected function applyMask($headers,$payload) { $effectiveMask = ""; if ($headers['hasmask']) { $mask = $headers['mask']; } else { return $payload; } while (strlen($effectiveMask) < strlen($payload)) { $effectiveMask .= $mask; } while (strlen($effectiveMask) > strlen($payload)) { $effectiveMask = substr($effectiveMask,0,-1); } return $effectiveMask ^ $payload; } protected function checkRSVBits($headers,$user) { // override this method if you are using an extension where the RSV bits are used. if (ord($headers['rsv1']) + ord($headers['rsv2']) + ord($headers['rsv3']) > 0) { //$this->disconnect($user); // todo: fail connection return true; } return false; } protected function strtohex($str) { $strout = ""; for ($i = 0; $i < strlen($str); $i++) { $strout .= (ord($str[$i])<16) ? "0" . dechex(ord($str[$i])) : dechex(ord($str[$i])); $strout .= " "; if ($i%32 == 7) { $strout .= ": "; } if ($i%32 == 15) { $strout .= ": "; } if ($i%32 == 23) { $strout .= ": "; } if ($i%32 == 31) { $strout .= "\n"; } } return $strout . "\n"; } protected function printHeaders($headers) { echo "Array\n(\n"; foreach ($headers as $key => $value) { if ($key == 'length' || $key == 'opcode') { echo "\t[$key] => $value\n\n"; } else { echo "\t[$key] => ".$this->strtohex($value)."\n"; } } echo ")\n"; } protected function handleRequestHeader($request) { $resource = $code = null; preg_match('/GET (.*?) HTTP/', $request, $match) && $resource = $match[1]; preg_match("/\r\n(.*?)\$/", $request, $match) && $code = $match[1]; $headers = array(); foreach(explode("\r\n", $request) as $line) { if (strpos($line, ': ') !== false) { list($key, $value) = explode(': ', $line); $headers[trim($key)] = trim($value); } } return array($resource, $headers, $code); } protected function handleSecurityKey($key) { preg_match_all('/[0-9]/', $key, $number); preg_match_all('/ /', $key, $space); if ($number && $space) { return implode('', $number[0]) / count($space[0]); } return ''; } protected function getHandshakeSecurityKey($key1, $key2, $code) { return md5( pack('N', $this->handleSecurityKey($key1)). pack('N', $this->handleSecurityKey($key2)). $code, true ); } }