comment
IRC Chat
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

CHAT WebSocket y php, con PHPCLI y mis disculpas jejeje

  • 1 Respuestas
  • 1169 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado alexander1712

  • *
  • Underc0der
  • Mensajes: 850
  • Actividad:
    0%
  • Reputación -2
    • Ver Perfil
    • El blog del programador
    • Email
« en: Octubre 07, 2013, 05:50:40 pm »
Buenas, ayer un amigo me comentó su necesidad de hacer un chat con Websockets (ya había intentado hacer un chat con AJAX y es el desmadre de consumo jajaja, aunque me lo imaginaba tenía que verlo con mis propios hojos), asique busqué un ejemplo y estube varias horas tratando de entender por que no andaba, hasta que me di cuenta que el protocolo había cambiado y ahora se usaba una clave de encriptación basada en XOR con dígitos de control. Me puse a trabajar y mientras buscaba algunas ayudas en internet me encontré con un repositorio y lo que yo llamo "la clase perfecta" si bien le falta pulir mucho para que sea la perfecta clase que mensiono, era la solución para no romperme más la cabeza, y para probar su funcionamiento en unas horas hice un sistema de chat basado en esa clase y ajustando un par de cosas.

Clase Original aquí

ahora mis disculpas ¿por que? por que el código que voy a poner a continuación es un azco, realmente un desorden, por lo que en mi defensa diré simplemente que quería probar la clase, y no reparé en la estructura del código, y en criterio de calidad alguno. De hecho si se fijan no eh tenido tiempo ni de implementar las interfaces, igual primero debería revisar la estructura de la clase.
Probablemente en unos días les presentaré la versión refinada (como hice en el código de bbc)

Ahora que ya saben que se tienen que esperar un azco de código mezclado y sin estructura aparente, les dejo mi desastroso pero funcional código.

Código: PHP
  1. <?php
  2.  
  3. /** WebSocketServer
  4.  *  @original code: https://github.com/ghedipunk/PHP-Websockets/blob/master/users.php
  5.  *  @redesign: Alexander171294
  6.  *  @Proyect Name: PHSP: phSocketPlus
  7.  *  @contact: Alexander171294@gmail.com
  8.  *  @Status: Prototype
  9.  *  @Date: 07/10/13  
  10.  */          
  11.  
  12. interface iphSocketPlus
  13. {
  14.  
  15. }
  16.  
  17. interface iSocketPlusUser
  18. {
  19.  
  20. }
  21.  
  22. trait Property // mi hermosa clase property
  23. {
  24.     // llamando a funciones setters
  25.     Public function __set($property, $value)
  26.     {
  27.             return call_user_func(array($this, 'set_'.$property), $value);
  28.     }
  29.    
  30.     // llamando a funciones getters
  31.     Public function __get($property)
  32.     {
  33.         if(is_callable(array($this, 'get_'.$property)))
  34.             return call_user_func(array($this, 'get_'.$property));
  35.         elseif(is_callable(array(parent, 'get_'.$property)))
  36.             return call_user_func(array(parent, 'get_'.$property));
  37.         else
  38.         // no hay funcion getter para este atributo (o no existe el atributo)
  39.             throw new exception('The atribute $'.$property.' not exist in get');  
  40.     }
  41. }
  42.  
  43. abstract class AbstractWebSocketUser {
  44.   private $socket;
  45.   private $id;
  46.   private $headers = array();
  47.   private $handshake = false;
  48.  
  49.   private $handlingPartialPacket = false;
  50.   private $partialBuffer = "";
  51.  
  52.   private $sendingContinuous = false;
  53.   private $partialMessage = "";
  54.  
  55.   private $hasSentClose = false;
  56.  
  57.   private $RequestedResource = null;
  58.  
  59.   public function __construct($id,$socket)
  60.   {
  61.     $this->id = $id;
  62.     $this->socket = $socket;
  63.   }
  64.  
  65.   public function get_socket()
  66.   {
  67.     return $this->socket;
  68.   }
  69.  
  70.   public function get_id()
  71.   {
  72.     return $this->id;
  73.   }
  74.  
  75.   public function get_headers()
  76.   {
  77.     return $this->headers;
  78.   }
  79.  
  80.   public function get_handshake()
  81.   {
  82.     return $this->handshake;
  83.   }
  84.  
  85.   public function get_handlingPartialPacket()
  86.   {
  87.     return $this->handlingPartialPacket;
  88.   }
  89.  
  90.   public function get_partialBuffer()
  91.   {
  92.     return $this->partialBuffer;
  93.   }
  94.  
  95.   public function get_sendingContinuous()
  96.   {
  97.     return $this->sendingContinuous;
  98.   }
  99.  
  100.   public function get_partialMessage()
  101.   {
  102.     return $this->partialMessage;
  103.   }
  104.  
  105.   public function get_hasSentClose()
  106.   {
  107.     return $this->hasSentClose;
  108.   }
  109.  
  110.   public function get_RequestedResource()
  111.   {
  112.     return $this->RequestedResource;
  113.   }
  114.  
  115.   public function set_RequestedResource($value)
  116.   {
  117.     $this->RequestedResource = $value;
  118.   }
  119.  
  120.   public function set_socket($value)
  121.   {
  122.     $this->socket = $value;
  123.   }
  124.  
  125.   public function set_id($value)
  126.   {
  127.     $this->id = $value;
  128.   }
  129.  
  130.   public function set_headers($value)
  131.   {
  132.     $this->headers = $value;
  133.   }
  134.  
  135.   public function set_handshake($value)
  136.   {
  137.     $this->handshake = $value;
  138.   }
  139.  
  140.   public function set_handlingPartialPacket($value)
  141.   {
  142.     $this->handlingPartialPacket = $value;
  143.   }
  144.  
  145.   public function set_partialBuffer($value)
  146.   {
  147.     $this->partialBuffer = $value;
  148.   }
  149.  
  150.   public function set_sendingContinuous($value)
  151.   {
  152.     $this->sendingContinuous = $value;
  153.   }
  154.  
  155.   public function set_partialMessage($value)
  156.   {
  157.     $this->partialMessage = $value;
  158.   }
  159.  
  160.   public function set_hasSentClose($value)
  161.   {
  162.     $this->hasSentClose = $value;
  163.   }
  164. }
  165.  
  166. class SocketPlusUser extends AbstractWebSocketUser implements iSocketPlusUser
  167. {
  168. use Property;
  169.  
  170.     private $accedio = false; // si accedió
  171.     private $name = null; // nombre de usuario
  172.     private $channel = null;
  173.     private $founder = false;
  174.     private $moderator = false;
  175.     static $users = array();
  176.     static $channels = array(); // array complejo
  177.     static $uonlines = array();
  178.    
  179.     // acceder
  180.     public function acceder($user, $pass)
  181.     {
  182.         if(isset(self::$users[$user]) && self::$users[$user]==$pass)
  183.         {
  184.             $this->accedio = true;
  185.             $this->name = $user;
  186.             return true;
  187.         } else {return false;}
  188.     }
  189.    
  190.     public function registrarse($user, $pass)
  191.     {
  192.         if(strlen($user)<3 || strlen($pass)<3) return false;
  193.         if(!isset(self::$users[$user]))
  194.         {
  195.             self::$users[$user] = $pass;
  196.             return true;
  197.         } else {return false;}
  198.     }
  199.    
  200.     public function crear_canal($name, $desc)
  201.     {
  202.         if(strlen($name)<3 || strlen($desc)<3) return false;
  203.         if(!isset(self::$channels[$name]))
  204.         {
  205.             self::$channels[$name]['name'] = $desc;
  206.             self::$channels[$name]['userlist'] = array();
  207.             self::$channels[$name]['founder'] = $this->name;
  208.             self::$channels[$name]['specialusers'] = array();
  209.             return true;
  210.         } else {return false;}
  211.     }
  212.    
  213.     public function ir_canal($user, $canal)
  214.     {
  215.         if(isset(self::$channels[$canal]))
  216.         {
  217.             // si estás banneado
  218.             if(isset(self::$channels[$canal]['specialusers'][$this->name]) && self::$channels[$canal]['specialusers'][$this->name] == 'B' && self::$channels[$canal]['founder'] != $this->name)
  219.             { $this->channel = null; return false; }
  220.             $this->channel = $canal;
  221.             self::$channels[$canal]['userlist'][] = $user;
  222.               if(self::$channels[$canal]['founder'] == $this->name)
  223.                   $this->founder=true;
  224.               else
  225.                   $this->founder=false;
  226.               if(isset(self::$channels[$canal]['specialusers'][$this->name]) && self::$channels[$canal]['specialusers'][$this->name] == 'M')  // si somos moderadores
  227.                   $this->moderator=true;
  228.               else
  229.                   $this->moderator=false;
  230.             return true;
  231.         } else { return false; }
  232.     }
  233.    
  234.     public function cambiar_pass($user, $pass, $pass2)
  235.     {
  236.         if(strlen($pass2)<3) return false;
  237.         if(isset(self::$users[$user]) && self::$users[$user]==$pass)
  238.         {
  239.             self::$users[$user]=$pass2;
  240.             return true;
  241.         } else {return false;}
  242.     }
  243.    
  244.     public function get_accedio()
  245.     {
  246.       return $this->accedio;
  247.     }
  248.    
  249.     public function get_name()
  250.     {
  251.       return $this->name;
  252.     }
  253.    
  254.     public function get_channel()
  255.     {
  256.       return $this->channel;
  257.     }
  258.    
  259.     public function set_channel($value)
  260.     {
  261.       $this->channel = $value;
  262.     }
  263.    
  264.     public function get_founder()
  265.     {
  266.       return $this->founder;
  267.     }
  268.    
  269.     public function get_moderator()
  270.     {
  271.       return $this->moderator;
  272.     }
  273.  
  274. }
  275.  
  276. // Original Class
  277. abstract class WebSocketServer {
  278.  
  279.         protected $userClass = 'WebSocketUser'; // redefine this if you want a custom user class.  The custom user class should inherit from WebSocketUser.
  280.         protected $maxBufferSize;        
  281.         protected $master;
  282.         protected $sockets                              = array();
  283.         protected $users                                = array();
  284.         protected $interactive                          = true;
  285.         protected $headerOriginRequired                 = false;
  286.         protected $headerSecWebSocketProtocolRequired   = false;
  287.         protected $headerSecWebSocketExtensionsRequired = false;
  288.  
  289.         function __construct($addr, $port, $userClass=null , $bufferLength = 2048) {
  290.                 $this->maxBufferSize = $bufferLength;
  291.     if(!empty($userClass)) $this->userClass = $userClass;
  292.                 $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)  or die("Failed: socket_create()");
  293.                 socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("Failed: socket_option()");
  294.                 socket_bind($this->master, $addr, $port)                      or die("Failed: socket_bind()");
  295.                 socket_listen($this->master,20)                               or die("Failed: socket_listen()");
  296.                 $this->sockets[] = $this->master;
  297.     $this->stdout('###### WEBCHAT SERVER ###### v1.0');
  298.                 $this->stdout("Server started\nListening on: $addr:$port\nMaster socket: ".$this->master);
  299.  
  300.                 while(true) {
  301.                         if (empty($this->sockets)) {
  302.                                 $this->sockets[] = $master;
  303.                         }
  304.                         $read = $this->sockets;
  305.                         $write = $except = null;
  306.                         @socket_select($read,$write,$except,null);
  307.                         foreach ($read as $socket) {
  308.                                 if ($socket == $this->master) {
  309.                                         $client = socket_accept($socket);
  310.                                         if ($client < 0) {
  311.                                                 $this->stderr("Failed: socket_accept()");
  312.                                                 continue;
  313.                                         } else {
  314.                                                 $this->connect($client);
  315.                                         }
  316.                                 } else {
  317.                                         $numBytes = @socket_recv($socket,$buffer,$this->maxBufferSize,0); // todo: if($numBytes === false) { error handling } elseif ($numBytes === 0) { remote client disconected }
  318.                                         if ($numBytes == 0) {
  319.                                                 $this->disconnect($socket);
  320.                                         } else {
  321.                                                 $user = $this->getUserBySocket($socket);
  322.                                                 if (!$user->handshake) {
  323.                                                         $this->doHandshake($user,$buffer);
  324.                                                 } else {
  325.               if ($message = $this->deframe($buffer, $user)) {
  326.                 $this->process($user, utf8_encode($message));
  327.                 if($user->hasSentClose) {
  328.                   $this->disconnect($user->socket);
  329.                 }
  330.               } else {
  331.                                                                 do {
  332.                                                                         $numByte = @socket_recv($socket,$buffer,$this->maxBufferSize,MSG_PEEK);
  333.                                                                         if ($numByte > 0) {
  334.                                                                                 $numByte = @socket_recv($socket,$buffer,$this->maxBufferSize,0);
  335.                                                                                 if ($message = $this->deframe($buffer,$user)) {
  336.                                                                                         $this->process($user,$message);
  337.                       if($user->hasSentClose) {
  338.                         $this->disconnect($user->socket);
  339.                       }
  340.                                                                                 }
  341.                                                                         }
  342.                                                                 } while($numByte > 0);
  343.                                                         }
  344.                                                 }
  345.                                         }
  346.                                 }
  347.                         }
  348.                 }
  349.         }
  350.  
  351.         abstract protected function process($user,$message); // Calked immediately when the data is recieved.
  352.         abstract protected function connected($user);        // Called after the handshake response is sent to the client.
  353.         abstract protected function closed($user);           // Called after the connection is closed.
  354.  
  355.         protected function connecting($user) {
  356.     // Override to handle a connecting user, after the instance of the User is created, but before
  357.     // the handshake has completed.
  358.   }
  359.  
  360.   protected function send($user,$message) {
  361.                 //$this->stdout("> $message");
  362.                 $message = $this->frame($message,$user);
  363.                 socket_write($user->socket,$message,strlen($message));
  364.         }
  365.  
  366.         protected function connect($socket) {
  367.                 $user = new $this->userClass(uniqid(),$socket);
  368.                 array_push($this->users,$user);
  369.                 array_push($this->sockets,$socket);
  370.                 $this->connecting($user);
  371.         }
  372.  
  373.         protected function disconnect($socket,$triggerClosed=true) {
  374.                 $foundUser = null;
  375.                 $foundSocket = null;
  376.                 foreach ($this->users as $key => $user) {
  377.                         if ($user->socket == $socket) {
  378.                                 $foundUser = $key;
  379.                                 $disconnectedUser = $user;
  380.                                 break;
  381.                         }
  382.                 }
  383.                 if ($foundUser !== null) {
  384.                         unset($this->users[$foundUser]);
  385.                         $this->users = array_values($this->users);
  386.                 }
  387.                 foreach ($this->sockets as $key => $sock) {
  388.                         if ($sock == $socket) {
  389.                                 $foundSocket = $key;
  390.                                 break;
  391.                         }
  392.                 }
  393.                 if ($foundSocket !== null) {
  394.                         unset($this->sockets[$foundSocket]);
  395.                         $this->sockets = array_values($this->sockets);
  396.                 }
  397.                 if ($triggerClosed) {
  398.                         $this->closed($disconnectedUser);
  399.                 }
  400.         }
  401.  
  402.         protected function doHandshake($user, $buffer) {
  403.                 $magicGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
  404.                 $headers = array();
  405.                 $lines = explode("\n",$buffer);
  406.                 foreach ($lines as $line) {
  407.                         if (strpos($line,":") !== false) {
  408.                                 $header = explode(":",$line,2);
  409.                                 $headers[strtolower(trim($header[0]))] = trim($header[1]);
  410.                         } else if (stripos($line,"get ") !== false) {
  411.                                 preg_match("/GET (.*) HTTP/i", $buffer, $reqResource);
  412.                                 $headers['get'] = trim($reqResource[1]);
  413.                         }
  414.                 }
  415.                 if (isset($headers['get'])) {
  416.                         $user->requestedResource = $headers['get'];
  417.                 } else {
  418.                         // todo: fail the connection
  419.                         $handshakeResponse = "HTTP/1.1 405 Method Not Allowed\r\n\r\n";                
  420.                 }
  421.                 if (!isset($headers['host']) || !$this->checkHost($headers['host'])) {
  422.                         $handshakeResponse = "HTTP/1.1 400 Bad Request";
  423.                 }
  424.                 if (!isset($headers['upgrade']) || strtolower($headers['upgrade']) != 'websocket') {
  425.                         $handshakeResponse = "HTTP/1.1 400 Bad Request";
  426.                 }
  427.                 if (!isset($headers['connection']) || strpos(strtolower($headers['connection']), 'upgrade') === FALSE) {
  428.                         $handshakeResponse = "HTTP/1.1 400 Bad Request";
  429.                 }
  430.                 if (!isset($headers['sec-websocket-key'])) {
  431.                         $handshakeResponse = "HTTP/1.1 400 Bad Request";
  432.                 } else {
  433.  
  434.                 }
  435.                 if (!isset($headers['sec-websocket-version']) || strtolower($headers['sec-websocket-version']) != 13) {
  436.                         $handshakeResponse = "HTTP/1.1 426 Upgrade Required\r\nSec-WebSocketVersion: 13";
  437.                 }
  438.                 if (($this->headerOriginRequired && !isset($headers['origin']) ) || ($this->headerOriginRequired && !$this->checkOrigin($headers['origin']))) {
  439.                         $handshakeResponse = "HTTP/1.1 403 Forbidden";
  440.                 }
  441.                 if (($this->headerSecWebSocketProtocolRequired && !isset($headers['sec-websocket-protocol'])) || ($this->headerSecWebSocketProtocolRequired && !$this->checkWebsocProtocol($header['sec-websocket-protocol']))) {
  442.                         $handshakeResponse = "HTTP/1.1 400 Bad Request";
  443.                 }
  444.                 if (($this->headerSecWebSocketExtensionsRequired && !isset($headers['sec-websocket-extensions'])) || ($this->headerSecWebSocketExtensionsRequired && !$this->checkWebsocExtensions($header['sec-websocket-extensions']))) {
  445.                         $handshakeResponse = "HTTP/1.1 400 Bad Request";
  446.                 }
  447.  
  448.                 // Done verifying the _required_ headers and optionally required headers.
  449.  
  450.                 if (isset($handshakeResponse)) {
  451.                         socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse));
  452.                         $this->disconnect($user->socket);
  453.                         return false;
  454.                 }
  455.  
  456.                 $user->headers = $headers;
  457.                 $user->handshake = $buffer;
  458.  
  459.                 $webSocketKeyHash = sha1($headers['sec-websocket-key'] . $magicGUID);
  460.  
  461.                 $rawToken = "";
  462.                 for ($i = 0; $i < 20; $i++) {
  463.                         $rawToken .= chr(hexdec(substr($webSocketKeyHash,$i*2, 2)));
  464.                 }
  465.                 $handshakeToken = base64_encode($rawToken) . "\r\n";
  466.  
  467.                 $subProtocol = (isset($headers['sec-websocket-protocol'])) ? $this->processProtocol($headers['sec-websocket-protocol']) : "";
  468.                 $extensions = (isset($headers['sec-websocket-extensions'])) ? $this->processExtensions($headers['sec-websocket-extensions']) : "";
  469.  
  470.                 $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $handshakeToken$subProtocol$extensions\r\n";
  471.                 socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse));
  472.     $this->connected($user);
  473.         }
  474.  
  475.         protected function checkHost($hostName) {
  476.                 return true; // Override and return false if the host is not one that you would expect.
  477.                                      // Ex: You only want to accept hosts from the my-domain.com domain,
  478.                                          // but you receive a host from malicious-site.com instead.
  479.         }
  480.  
  481.         protected function checkOrigin($origin) {
  482.                 return true; // Override and return false if the origin is not one that you would expect.
  483.         }
  484.  
  485.         protected function checkWebsocProtocol($protocol) {
  486.                 return true; // Override and return false if a protocol is not found that you would expect.
  487.         }
  488.  
  489.         protected function checkWebsocExtensions($extensions) {
  490.                 return true; // Override and return false if an extension is not found that you would expect.
  491.         }
  492.  
  493.         protected function processProtocol($protocol) {
  494.                 return ""; // return either "Sec-WebSocket-Protocol: SelectedProtocolFromClientList\r\n" or return an empty string.  
  495.                                    // The carriage return/newline combo must appear at the end of a non-empty string, and must not
  496.                                    // appear at the beginning of the string nor in an otherwise empty string, or it will be considered part of
  497.                                    // the response body, which will trigger an error in the client as it will not be formatted correctly.
  498.         }
  499.  
  500.         protected function processExtensions($extensions) {
  501.                 return ""; // return either "Sec-WebSocket-Extensions: SelectedExtensions\r\n" or return an empty string.
  502.         }
  503.  
  504.         protected function getUserBySocket($socket) {
  505.                 foreach ($this->users as $user) {
  506.                         if ($user->socket == $socket) {
  507.                                 return $user;
  508.                         }
  509.                 }
  510.                 return null;
  511.         }
  512.  
  513.   // no la protegemos para que pueda ser reescrita si se cambia
  514.   // el método de salida cuando se hereda la clase
  515.         private function stdout($message) {
  516.                 if ($this->interactive) {
  517.                         echo "$message\n";
  518.                 }
  519.         }
  520.  
  521.   // no la protegemos para que pueda ser reescrita si se cambia
  522.   // el método de salida cuando se hereda la clase
  523.         private function stderr($message) {
  524.                 if ($this->interactive) {
  525.                         echo "$message\n";
  526.                 }
  527.         }
  528.  
  529.         protected function frame($message, $user, $messageType='text', $messageContinues=false) {
  530.                 switch ($messageType) {
  531.                         case 'continuous':
  532.                                 $b1 = 0;
  533.                                 break;
  534.                         case 'text':
  535.                                 $b1 = ($user->sendingContinuous) ? 0 : 1;
  536.                                 break;
  537.                         case 'binary':
  538.                                 $b1 = ($user->sendingContinuous) ? 0 : 2;
  539.                                 break;
  540.                         case 'close':
  541.                                 $b1 = 8;
  542.                                 break;
  543.                         case 'ping':
  544.                                 $b1 = 9;
  545.                                 break;
  546.                         case 'pong':
  547.                                 $b1 = 10;
  548.                                 break;
  549.                 }
  550.                 if ($messageContinues) {
  551.                         $user->sendingContinuous = true;
  552.                 } else {
  553.                         $b1 += 128;
  554.                         $user->sendingContinuous = false;
  555.                 }
  556.  
  557.                 $length = strlen($message);
  558.                 $lengthField = "";
  559.                 if ($length < 126) {
  560.                         $b2 = $length;
  561.                 } elseif ($length <= 65536) {
  562.                         $b2 = 126;
  563.                         $hexLength = dechex($length);
  564.                         //$this->stdout("Hex Length: $hexLength");
  565.                         if (strlen($hexLength)%2 == 1) {
  566.                                 $hexLength = '0' . $hexLength;
  567.                         }
  568.                         $n = strlen($hexLength) - 2;
  569.  
  570.                         for ($i = $n; $i >= 0; $i=$i-2) {
  571.                                 $lengthField = chr(hexdec(substr($hexLength, $i, 2))) . $lengthField;
  572.                         }
  573.                         while (strlen($lengthField) < 2) {
  574.                                 $lengthField = chr(0) . $lengthField;
  575.                         }
  576.                 } else {
  577.                         $b2 = 127;
  578.                         $hexLength = dechex($length);
  579.                         if (strlen($hexLength)%2 == 1) {
  580.                                 $hexLength = '0' . $hexLength;
  581.                         }
  582.                         $n = strlen($hexLength) - 2;
  583.  
  584.                         for ($i = $n; $i >= 0; $i=$i-2) {
  585.                                 $lengthField = chr(hexdec(substr($hexLength, $i, 2))) . $lengthField;
  586.                         }
  587.                         while (strlen($lengthField) < 8) {
  588.                                 $lengthField = chr(0) . $lengthField;
  589.                         }
  590.                 }
  591.  
  592.                 return chr($b1) . chr($b2) . $lengthField . $message;
  593.         }
  594.  
  595.         protected function deframe($message, $user) {
  596.                 //echo $this->strtohex($message);
  597.                 $headers = $this->extractHeaders($message);
  598.                 $pongReply = false;
  599.                 $willClose = false;
  600.                 switch($headers['opcode']) {
  601.                         case 0:
  602.                         case 1:
  603.                         case 2:
  604.                                 break;
  605.                         case 8:
  606.                                 // todo: close the connection
  607.                                 $user->hasSentClose = true;
  608.                                 return "";
  609.                         case 9:
  610.                                 $pongReply = true;
  611.                         case 10:
  612.                                 break;
  613.                         default:
  614.                                 //$this->disconnect($user); // todo: fail connection
  615.                                 $willClose = true;
  616.                                 break;
  617.                 }
  618.  
  619.                 if ($user->handlingPartialPacket) {
  620.                         $message = $user->partialBuffer . $message;
  621.                         $user->handlingPartialPacket = false;
  622.                         return $this->deframe($message, $user);
  623.                 }
  624.  
  625.                 if ($this->checkRSVBits($headers,$user)) {
  626.                         return false;
  627.                 }
  628.  
  629.                 if ($willClose) {
  630.                         // todo: fail the connection
  631.                         return false;
  632.                 }
  633.  
  634.                 $payload = $user->partialMessage . $this->extractPayload($message,$headers);
  635.  
  636.                 if ($pongReply) {
  637.                         $reply = $this->frame($payload,$user,'pong');
  638.                         socket_write($user->socket,$reply,strlen($reply));
  639.                         return false;
  640.                 }
  641.                 if (extension_loaded('mbstring')) {
  642.                         if ($headers['length'] > mb_strlen($payload)) {
  643.                                 $user->handlingPartialPacket = true;
  644.                                 $user->partialBuffer = $message;
  645.                                 return false;
  646.                         }
  647.                 } else {
  648.                         if ($headers['length'] > strlen($payload)) {
  649.                                 $user->handlingPartialPacket = true;
  650.                                 $user->partialBuffer = $message;
  651.                                 return false;
  652.                         }
  653.                 }
  654.  
  655.                 $payload = $this->applyMask($headers,$payload);
  656.  
  657.                 if ($headers['fin']) {
  658.                         $user->partialMessage = "";
  659.                         return $payload;
  660.                 }
  661.                 $user->partialMessage = $payload;
  662.                 return false;
  663.         }
  664.  
  665.         protected function extractHeaders($message) {
  666.                 $header = array('fin'     => $message[0] & chr(128),
  667.                                                 'rsv1'    => $message[0] & chr(64),
  668.                                                 'rsv2'    => $message[0] & chr(32),
  669.                                                 'rsv3'    => $message[0] & chr(16),
  670.                                                 'opcode'  => ord($message[0]) & 15,
  671.                                                 'hasmask' => $message[1] & chr(128),
  672.                                                 'length'  => 0,
  673.                                                 'mask'    => "");
  674.                 $header['length'] = (ord($message[1]) >= 128) ? ord($message[1]) - 128 : ord($message[1]);
  675.  
  676.                 if ($header['length'] == 126) {
  677.                         if ($header['hasmask']) {
  678.                                 $header['mask'] = $message[4] . $message[5] . $message[6] . $message[7];
  679.                         }
  680.                         $header['length'] = ord($message[2]) * 256
  681.                                                           + ord($message[3]);
  682.                 } elseif ($header['length'] == 127) {
  683.                         if ($header['hasmask']) {
  684.                                 $header['mask'] = $message[10] . $message[11] . $message[12] . $message[13];
  685.                         }
  686.                         $header['length'] = ord($message[2]) * 65536 * 65536 * 65536 * 256
  687.                                                           + ord($message[3]) * 65536 * 65536 * 65536
  688.                                                           + ord($message[4]) * 65536 * 65536 * 256
  689.                                                           + ord($message[5]) * 65536 * 65536
  690.                                                           + ord($message[6]) * 65536 * 256
  691.                                                           + ord($message[7]) * 65536
  692.                                                           + ord($message[8]) * 256
  693.                                                           + ord($message[9]);
  694.                 } elseif ($header['hasmask']) {
  695.                         $header['mask'] = $message[2] . $message[3] . $message[4] . $message[5];
  696.                 }
  697.                 //echo $this->strtohex($message);
  698.                 //$this->printHeaders($header);
  699.                 return $header;
  700.         }
  701.  
  702.         protected function extractPayload($message,$headers) {
  703.                 $offset = 2;
  704.                 if ($headers['hasmask']) {
  705.                         $offset += 4;
  706.                 }
  707.                 if ($headers['length'] > 65535) {
  708.                         $offset += 8;
  709.                 } elseif ($headers['length'] > 125) {
  710.                         $offset += 2;
  711.                 }
  712.                 return substr($message,$offset);
  713.         }
  714.  
  715.         protected function applyMask($headers,$payload) {
  716.                 $effectiveMask = "";
  717.                 if ($headers['hasmask']) {
  718.                         $mask = $headers['mask'];
  719.                 } else {
  720.                         return $payload;
  721.                 }
  722.  
  723.                 while (strlen($effectiveMask) < strlen($payload)) {
  724.                         $effectiveMask .= $mask;
  725.                 }
  726.                 while (strlen($effectiveMask) > strlen($payload)) {
  727.                         $effectiveMask = substr($effectiveMask,0,-1);
  728.                 }
  729.                 return $effectiveMask ^ $payload;
  730.         }
  731.         protected function checkRSVBits($headers,$user) { // override this method if you are using an extension where the RSV bits are used.
  732.                 if (ord($headers['rsv1']) + ord($headers['rsv2']) + ord($headers['rsv3']) > 0) {
  733.                         //$this->disconnect($user); // todo: fail connection
  734.                         return true;
  735.                 }
  736.                 return false;
  737.         }
  738.  
  739.         protected function strtohex($str) {
  740.                 $strout = "";
  741.                 for ($i = 0; $i < strlen($str); $i++) {
  742.                         $strout .= (ord($str[$i])<16) ? "0" . dechex(ord($str[$i])) : dechex(ord($str[$i]));
  743.                         $strout .= " ";
  744.                         if ($i%32 == 7) {
  745.                                 $strout .= ": ";
  746.                         }
  747.                         if ($i%32 == 15) {
  748.                                 $strout .= ": ";
  749.                         }
  750.                         if ($i%32 == 23) {
  751.                                 $strout .= ": ";
  752.                         }
  753.                         if ($i%32 == 31) {
  754.                                 $strout .= "\n";
  755.                         }
  756.                 }
  757.                 return $strout . "\n";
  758.         }
  759.  
  760.         protected function printHeaders($headers) {
  761.                 echo "Array\n(\n";
  762.                 foreach ($headers as $key => $value) {
  763.                         if ($key == 'length' || $key == 'opcode') {
  764.                                 echo "\t[$key] => $value\n\n";
  765.                         } else {
  766.                                 echo "\t[$key] => ".$this->strtohex($value)."\n";
  767.  
  768.                         }
  769.  
  770.                 }
  771.                 echo ")\n";
  772.         }
  773. }
  774.  
  775. class phSocketPlus extends WebSocketServer implements iphSocketPlus
  776. {
  777.   use Property;
  778.  
  779.     public function __construct($addr, $port=722, $userClass='SocketPlusUser')
  780.     {
  781.       parent::__construct($addr, $port, $userClass);
  782.     }
  783.  
  784.   protected function process($user,$message) // Calked immediately when the data is recieved.
  785.   {
  786.       // procesar
  787.       #parent::send($user,$mensaje);
  788.      // obtenemos el mensaje y vemos que comando es
  789.       $command = null;
  790.       for($i=0; $i<3; $i++)
  791.       {
  792.         $command .= $message[$i];
  793.       }
  794.       $params = null;
  795.       for($i=4; $i<strlen($message); $i++)
  796.       {
  797.         $params .= $message[$i];
  798.       }
  799.       switch($command)
  800.       {
  801.           case 'AUT':
  802.             if(!$user->accedio)
  803.             {
  804.               $this->HEout('AUTentificate command');
  805.               if($this->autenticate($user, $params))
  806.               {
  807.                   $this->MEout('Welcome '.$user->name.'...');
  808.                   parent::send($user,'#SERVER: Welcome '.htmlentities($user->name).'...');
  809.               } else { parent::send($user,'#SERVER: Access Deneid...'); }
  810.             } else { parent::send($user,'#SERVER: @'.$user->name); }
  811.           break;
  812.           case 'NEW':
  813.             if(!$user->accedio)
  814.             {
  815.               $this->HEout('New Account command - '.$params);
  816.               if($this->registrate($user, $params))
  817.               {
  818.                   $this->MEout('New Account '.htmlentities($params).'...');
  819.                   parent::send($user,'#SERVER: new account create success...');
  820.               } else { parent::send($user,'#SERVER: Isn\'t possible register your account...'); }
  821.             } else { parent::send($user,'#SERVER: @'.htmlentities($user->name)); }
  822.           break;
  823.           case 'CHN':
  824.             if($user->accedio)
  825.             {
  826.               $this->HEout('Join Channel command');
  827.               // si ya tenía canal
  828.               if($user->channel!=null) $this->killchannel($user);
  829.               if($this->ir_canal($user, $params))
  830.               {
  831.                   $this->MEout('Join to channel '.$params.'...');
  832.                   $this->meunicanal($user);
  833.                   parent::send($user,'#SERVER: Welcome to channel: '.SocketPlusUser::$channels[$params]['name']);
  834.               } else { parent::send($user,'#SERVER: the channel '.htmlentities($params).' not exist...'); $user->channel = null;}
  835.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  836.           break;
  837.           case 'PWD':
  838.             if($user->accedio)
  839.             {
  840.               $this->HEout('Change password command');
  841.               if($this->cambiar_pass($user, $params))
  842.               {
  843.                   $this->MEout('Change Password '.$params.'...');
  844.                   parent::send($user,'#SERVER: Change Password Success');
  845.               } else { parent::send($user,'#SERVER: isn\'t possible change password...'); }
  846.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  847.           break;
  848.           case 'ULT':
  849.             if($user->accedio)
  850.             {
  851.               $this->HEout('User List command');
  852.               if($user->channel!=null)
  853.               {
  854.                 parent::send($user,'#SERVER: Users in this channel:');
  855.                 $this->obtener_usuarios($user);
  856.                 $this->MEout('User List...');
  857.               }
  858.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  859.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  860.           break;
  861.           case 'NEC':
  862.               if($user->accedio)
  863.               {
  864.                 $this->HEout('New Chanel command');
  865.                 if($this->crear_canal($user, $params))
  866.                 {
  867.                     parent::send($user,'#SERVER: Channel Create Success');
  868.                     $this->MEout('New Channel Create Success...');
  869.                 } else { parent::send($user,'#SERVER: Channel isn\'t create, type HLP for help'); }
  870.                
  871.               }
  872.               else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  873.           break;
  874.           case 'MOD':
  875.             if($user->accedio)
  876.             {
  877.               $this->HEout('Add Moderator command');
  878.               if($user->channel!=null)
  879.               {
  880.                 if($user->founder==true)
  881.                 {
  882.                     $this->addmod($user, $params);
  883.                     parent::send($user,'#SERVER: Add Moderator :)');
  884.                     $this->MEout('Add Moderator To Channel...');
  885.                 } else { parent::send($user,'#SERVER: You aren\'t founder, type HLP for help'); }
  886.               }
  887.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  888.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  889.           break;
  890.           case 'USR':
  891.             if($user->accedio)
  892.             {
  893.               $this->HEout('Delete Moderator command');
  894.               if($user->channel!=null)
  895.               {
  896.                 if($user->founder==true)
  897.                 {
  898.                     $this->quitmod($user, $params);
  899.                     parent::send($user,'#SERVER: Delete Moderator');
  900.                     $this->MEout('Delete Moderator of the Channel...');
  901.                 } else { parent::send($user,'#SERVER: You aren\'t founder, type HLP for help'); }
  902.               }
  903.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  904.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  905.           break;
  906.           case 'BAN':
  907.             if($user->accedio)
  908.             {
  909.               $this->HEout('REQUEST BAN USER command');
  910.               if($user->channel!=null)
  911.               {
  912.                 if($user->founder==true || $user->moderator==true)
  913.                 {
  914.                     $this->ban($user, $params);
  915.                     parent::send($user,'#SERVER: Ban user success');
  916.                     $this->MEout('Ban Aproved...');
  917.                 } else { parent::send($user,'#SERVER: You aren\'t Founder or Moderator, type HLP for help'); }
  918.               }
  919.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  920.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  921.           break;
  922.           case 'KIK':
  923.             if($user->accedio)
  924.             {
  925.               $this->HEout('REQUEST KIK USER command');
  926.               if($user->channel!=null)
  927.               {
  928.                 if($user->founder==true || $user->moderator==true)
  929.                 {
  930.                     $this->kik($user, $params);
  931.                     parent::send($user,'#SERVER: Kik user success');
  932.                     $this->MEout('Kik Aproved...');
  933.                 } else { parent::send($user,'#SERVER: You aren\'t Founder or Moderator, type HLP for help'); }
  934.               }
  935.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  936.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  937.           break;
  938.           case 'DEL':
  939.             if($user->accedio)
  940.             {
  941.               $this->HEout('REQUEST DELETE CHANEL command');
  942.               if($user->channel!=null)
  943.               {
  944.                 if($user->founder==true || $user->moderator==true)
  945.                 {
  946.                     //$this->channeldelete($user, $params);  <---- Falta Hacer
  947.                     parent::send($user,'#SERVER: Delete chanel deneid by SERVER');
  948.                     $this->MEout('Delete channel Deneid...');
  949.                 } else { parent::send($user,'#SERVER: You aren\'t Founder or Moderator, type HLP for help'); }
  950.               }
  951.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  952.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  953.           break;
  954.           case 'GRD':
  955.             if($user->accedio)
  956.             {
  957.               $this->HEout('REQUEST GRADE USER command');
  958.               if($user->channel!=null)
  959.               {
  960.                     parent::send($user,'#SERVER: '.$this->getGrade($user));
  961.                     $this->MEout('Grade sent');
  962.               }
  963.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  964.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  965.           break;
  966.           case 'HLP':
  967.                $this->HEout('help command');
  968.                $this->MEout('Show Help...');
  969.                parent::send($user,'#SERVER: Help Command');
  970.                parent::send($user,'*Acces your account use: AUT user@pass');
  971.                parent::send($user,'*View Help use: HLP');
  972.                parent::send($user,'*Register an account use: NEW user@pass');
  973.                parent::send($user,'*Change your password use: PWD user@oldpass@newpass');
  974.                parent::send($user,'*Access to channel: CHN ChannelName');  
  975.                parent::send($user,'*List of users in channel: ULT');
  976.                parent::send($user,'*New channel: NEC ChannelName@Channel Welcome');
  977.                parent::send($user,'*Kik User: KIK user');
  978.                parent::send($user,'*Ban user: BAN user');
  979.                parent::send($user,'*Moderator Add: MOD user');
  980.                parent::send($user,'*Moderator Delete: USR user');
  981.                parent::send($user,'*Get Grade (is mod, is founder or is user): GRD');
  982.                parent::send($user,'*Destroy Channel: DEL mypassword');            //TODO
  983.                parent::send($user,'*[M]userName: hello <-- is a moderator');
  984.                parent::send($user,'*[F]userName: hello <-- is a founder');
  985.           break;
  986.           default:
  987.             if($user->accedio)
  988.             {
  989.               if($user->channel!=null)
  990.               {
  991.                 $this->HEout('MSG command');
  992.                 $this->resend($user, $message);
  993.                 $this->MEout('New Message... Resending to terminals');
  994.               }
  995.               else { parent::send($user,'#SERVER: Join Channel is required, type HLP for help'); }
  996.             } else { parent::send($user,'#SERVER: Authentication is required, type HLP for help'); }
  997.           break;
  998.       }
  999.   }
  1000.  
  1001.   private function autenticate($user, $params)
  1002.   {
  1003.     $user_init = strpos($params,'@');
  1004.     $usr = null;
  1005.     if($user_init===false) return false;
  1006.     for($i = 0; $i<$user_init; $i++)
  1007.       $usr.=$params[$i];
  1008.     $pss = null;
  1009.     for($i = $user_init+1; $i<strlen($params); $i++)
  1010.       $pss.=$params[$i];
  1011.     return $user->acceder($usr, $pss);
  1012.   }
  1013.  
  1014.   private function crear_canal($user, $params)
  1015.   {
  1016.     $user_init = strpos($params,'@');
  1017.     $name = null;
  1018.     if($user_init===false) return false;
  1019.     for($i = 0; $i<$user_init; $i++)
  1020.       $name.=$params[$i];
  1021.     $name = trim($name);
  1022.     $desc = null;
  1023.     for($i = $user_init+1; $i<strlen($params); $i++)
  1024.       $desc.=$params[$i];
  1025.     return $user->crear_canal($name, $desc);
  1026.   }
  1027.  
  1028.   private function getGrade($user)
  1029.   {
  1030.       if($user->founder)
  1031.           return 'You Are a Founder of the channel';
  1032.       elseif($user->moderator)
  1033.           return 'You Are a Moderator of the channel';
  1034.       else
  1035.           return 'You Are a User in the channel';
  1036.   }
  1037.  
  1038.   private function cambiar_pass($user, $params)
  1039.   {
  1040.     $user_init = strpos($params,'@');
  1041.     $usr = null;
  1042.     if($user_init===false) return false;
  1043.     for($i = 0; $i<$user_init; $i++)
  1044.       $usr.=$params[$i];
  1045.     $passs = null;
  1046.     for($i = $user_init+1; $i<strlen($params); $i++)
  1047.       $passs.=$params[$i];
  1048.     $pass_init = strpos($passs,'@');
  1049.     if($pass_init===false) return false;
  1050.     $pss1 = null;
  1051.     for($i = 0; $i<$pass_init; $i++)
  1052.       $pss1.=$passs[$i];
  1053.     $pss2 = null;
  1054.     for($i = $pass_init+1; $i<strlen($passs); $i++)
  1055.       $pss2.=$passs[$i];
  1056.     return $user->cambiar_pass($usr, $pss1, $pss2);
  1057.   }
  1058.  
  1059.   private function registrate($user, $params)
  1060.   {
  1061.     $user_init = strpos($params,'@');
  1062.     $usr = null;
  1063.     if($user_init===false) return false;
  1064.     for($i = 0; $i<$user_init; $i++)
  1065.       $usr.=$params[$i];
  1066.     $pss = null;
  1067.     for($i = $user_init+1; $i<strlen($params); $i++)
  1068.       $pss.=$params[$i];
  1069.     return $user->registrarse($usr, $pss);
  1070.   }
  1071.  
  1072.   private function obtener_usuarios($user)
  1073.   {
  1074.      
  1075.       $userlist = SocketPlusUser::$channels[$user->channel]['userlist'];
  1076.       for($i=0; $i<count($userlist); $i++)
  1077.       {
  1078.           $rango = '@';
  1079.           if($userlist[$i]->founder == true) $rango = '[F]';
  1080.           if($user->moderator == true) $rango = '[M]';
  1081.           parent::send($user, $rango.$userlist[$i]->name);
  1082.       }
  1083.   }
  1084.  
  1085.   private function resend($user, $message)
  1086.   {
  1087.       $rango = '@';
  1088.       if($user->founder == true) $rango = '[F]';
  1089.       if($user->moderator == true) $rango = '[M]';
  1090.       $userlist = SocketPlusUser::$channels[$user->channel]['userlist'];
  1091.       for($i=0; $i<count($userlist); $i++)
  1092.       {
  1093.           if($userlist[$i]->name != $user->name) // no nos enviamos a nosotros mismos
  1094.               parent::send($userlist[$i], $rango.$user->name.': '.$message);
  1095.       }
  1096.   }
  1097.  
  1098.   private function addmod($me, $user)
  1099.   {
  1100.     SocketPlusUser::$channels[$me->channel]['specialusers'][$user]='M';
  1101.   }
  1102.  
  1103.   private function quitmod($me, $user)
  1104.   {
  1105.     unset(SocketPlusUser::$channels[$me->channel]['specialusers'][$user]);
  1106.   }
  1107.  
  1108.   private function ban($me, $user)
  1109.   {
  1110.     SocketPlusUser::$channels[$me->channel]['specialusers'][$user]='B';
  1111.   }
  1112.  
  1113.   private function kik($user, $objetivo) // el user se fue del canal
  1114.   {
  1115.       $userlist = SocketPlusUser::$channels[$user->channel]['userlist'];
  1116.       for($i=0; $i<count($userlist); $i++)
  1117.       {
  1118.           if($userlist[$i]->founder != true)
  1119.             {
  1120.               $userlist[$i]->channel = null;
  1121.               unset(SocketPlusUser::$channels[$user->channel]['userlist'][$i]);
  1122.               SocketPlusUser::$channels[$user->channel]['userlist'] = array_values(SocketPlusUser::$channels[$user->channel]['userlist']);
  1123.               parent::send($userlist[$i], '#SERVER You Forced Disconnected from the channel');
  1124.             }
  1125.       }
  1126.   }
  1127.  
  1128.   private function killchannel($user) // el user se fue del canal
  1129.   {
  1130.       $rango = '@';
  1131.       if($user->founder == true) $rango = '[F]';
  1132.       if($user->moderator == true) $rango = '[M]';
  1133.       $userlist = SocketPlusUser::$channels[$user->channel]['userlist'];
  1134.       for($i=0; $i<count($userlist); $i++)
  1135.       {
  1136.           if($userlist[$i]->name != $user->name) // no nos enviamos a nosotros mismos
  1137.               parent::send($userlist[$i], '***Lost Connection: '.$rango.$user->name);
  1138.           else
  1139.            {
  1140.                 unset(SocketPlusUser::$channels[$user->channel]['userlist'][$i]); //lo quitamos de la lista de usuarios
  1141.                 SocketPlusUser::$channels[$user->channel]['userlist'] = array_values(SocketPlusUser::$channels[$user->channel]['userlist']);
  1142.            }
  1143.       }
  1144.   }
  1145.  
  1146.   private function meunicanal($user) // el user se fue del canal
  1147.   {
  1148.       $rango = '@';
  1149.       if($user->founder == true) $rango = '[F]';
  1150.       if($user->moderator == true) $rango = '[M]';
  1151.       $userlist = SocketPlusUser::$channels[$user->channel]['userlist'];
  1152.       for($i=0; $i<count($userlist); $i++)
  1153.       {
  1154.           if($userlist[$i]->name != $user->name) // no nos enviamos a nosotros mismos
  1155.               parent::send($userlist[$i], '***JOIN A CHANEL: '.$rango.$user->name);
  1156.       }
  1157.   }
  1158.  
  1159.   private function ir_canal($user, $params)
  1160.   {
  1161.     return $user->ir_canal($user, $params);
  1162.   }
  1163.  
  1164.   private function stdout($message)
  1165.   {
  1166.       echo '-----<>'.$message."\r\n";
  1167.   }
  1168.  
  1169.   private function MEout($message)
  1170.   {
  1171.       echo '<<-----'.$message."\r\n";
  1172.   }
  1173.  
  1174.   private function HEout($message)
  1175.   {
  1176.       echo '----->>'.$message."\r\n";
  1177.   }
  1178.  
  1179.   private function stderr($message)
  1180.   {
  1181.       echo '-----**'.$message."\r\n";
  1182.   }
  1183.  
  1184.         protected function connected($user)        // Called after the handshake response is sent to the client.
  1185.   {
  1186.       echo '-----<> Connected Success #'.$user->id."\r\n";
  1187.   }
  1188.  
  1189.         protected function closed($user)           // Called after the connection is closed.
  1190.   {
  1191.       // borrar de la lista donde estaba dicho user
  1192.       $this->killchannel($user);
  1193.       // nos vimos!
  1194.       echo '-----<> CLOSE: #'.$user->id."\r\n";
  1195.   }
  1196.  
  1197. }
  1198.  
  1199. // definimos los usuarios:
  1200. SocketPlusUser::$users = array('alex' => '1234',
  1201.                                'prueba' => '1234');
  1202.  
  1203. SocketPlusUser::$channels[1]['name'] = 'Canal de ejemplo';
  1204. SocketPlusUser::$channels[1]['userlist'] = null;
  1205.  
  1206. SocketPlusUser::$channels['alex']['name'] = 'El Canal de alex';
  1207. SocketPlusUser::$channels['alex']['userlist'] = null;
  1208.  
  1209. // iniciamos el servidor
  1210. $socket = new phSocketPlus('localhost','778');

estube a punto de implementar hilos (threads) pero, se me acabó el tiempo asique lo publico así.

este código permite crear varias salas, poner moderadores, et
« Última modificación: Octubre 07, 2013, 06:26:15 pm por alexmanycol »

Marcado como mejor respuesta por: en Diciembre 07, 2018, 01:07:05 pm

Desconectado alexander1712

  • *
  • Underc0der
  • Mensajes: 850
  • Actividad:
    0%
  • Reputación -2
    • Ver Perfil
    • El blog del programador
    • Email
« Respuesta #1 en: Octubre 07, 2013, 06:27:51 pm »
sigo acá abajo, porque no me deja poner más nada en el comentario de arriba jajajjaja

Como decía, permite crear salas, poner moderadores, es parecido a un IRC.
Aunque no me baso en ningún protocolo como xmpp o IRC, por lo que no aconcejo el uso de éste código.

es simplemente demostrativo.

dejo el HTML que conecta con el servidor de arriba.

Código: HTML5
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  3. <title>Abrir un WebSocket</title>
  4. </head>
  5.  
  6. <h1>Chat de prueba</h1>
  7.  
  8. <script type="text/javascript">
  9.  
  10.  
  11.         function escribir(texto){
  12.                 valor = document.getElementById("caja").value;
  13.                 document.getElementById("caja").value = texto + "\n" + valor;
  14.         }      
  15.  
  16.         var mysocket = new WebSocket("ws://localhost:778");
  17.  
  18.         mysocket.onopen = function (evt){
  19.                 escribir("Conectado al chat...");
  20.                
  21.         };
  22.  
  23.         mysocket.onmessage = function (evt){
  24.                 escribir(evt.data);
  25.                
  26.         };
  27.  
  28.         mysocket.onclose = function (evt){
  29.                  escribir("Desconectado del chat...");
  30.         };
  31.  
  32.         mysocket.onerror = function (evt) {
  33.                 escribir("ERROR: " + evt.data);
  34.         }
  35.  
  36.         function enviar(texto) {
  37.                 mysocket.send(texto);
  38.                 escribir("Yo: " + texto);
  39.         }
  40.  
  41.         function desconectar(){        
  42.                 mysocket.close();
  43.         }
  44.  
  45.        
  46.  
  47.  
  48. <textarea id="caja" cols="100" rows="20"></textarea><br/>
  49. <input id="mensaje" type="text" size="105"></input>
  50. <button onClick="enviar(document.getElementById('mensaje').value);">Enviar</button>
  51.  
  52.  
  53. <br><br>
  54. <hr>
  55.  
  56.  
  57. </body>
  58. </html>

no es de mi autoría pero lo googlee asique no se de quien es jajajaj, si alguien encuentra fuente por favor la agrega.

saludos!
« Última modificación: Marzo 27, 2014, 05:25:09 pm por Expermicid »

 

¿Te gustó el post? COMPARTILO!



[PHP] Simple Chat By Doddy H

Iniciado por BigBear

Respuestas: 4
Vistas: 1518
Último mensaje Agosto 10, 2011, 05:07:27 pm
por ~ Yoya ~
[PHP] DH Chat 0.5

Iniciado por BigBear

Respuestas: 6
Vistas: 4487
Último mensaje Diciembre 15, 2015, 04:51:45 pm
por EPSILON