message recv bugfix
This commit is contained in:
parent
8809203953
commit
bc4663e3a7
|
@ -36,9 +36,10 @@ class fuckwebsockets{
|
|||
"max_tcp_sndtime" => 30, // in seconds
|
||||
"tcp_write_size" => 4096, // in bytes
|
||||
"tcp_keepalive" => true,
|
||||
"ws_ping_interval" => 0, // 0 for disabled, int for ping interval
|
||||
"ws_ping_interval" => 0, // int for ping interval, 0 for disabled, in seconds
|
||||
"max_ws_rcv_size" => 4096, // in bytes
|
||||
"http_headers" => [] // Eg ["Host" => "localhost"]
|
||||
"http_headers" => [], // Eg ["Host" => "localhost"]
|
||||
"debug_log" => true
|
||||
],
|
||||
$options
|
||||
);
|
||||
|
@ -348,6 +349,7 @@ class fuckwebsockets{
|
|||
|
||||
// handle incoming messages
|
||||
$buffer = null;
|
||||
$bufferlength = 0;
|
||||
|
||||
// remove socket timeout
|
||||
socket_set_option(
|
||||
|
@ -365,57 +367,47 @@ class fuckwebsockets{
|
|||
// decode message
|
||||
$this->socket_recv($this->client, $header, 2, MSG_WAITALL);
|
||||
|
||||
$finalmessage = (ord($header[0]) & 0x80) === 128;
|
||||
$opcode = ord($header[0]) & 0x0F;
|
||||
$finalmessage = ord($header[0]) & 0x80;
|
||||
$masked = ord($header[1]) & 0x80;
|
||||
$masked = (ord($header[1]) & 0x80) === 128;
|
||||
$messagelength = ord($header[1]) & 0x7F;
|
||||
|
||||
// disconnect if frame isn't masked
|
||||
if(!$masked){
|
||||
switch($messagelength){
|
||||
|
||||
$this->ws_disconnect($this->client, self::close_bad_data, "Received unmasked frame");
|
||||
}
|
||||
case 126:
|
||||
$this->socket_recv($this->client, $messagelength, 2, MSG_WAITALL);
|
||||
$messagelength = unpack("n", $messagelength)[1];
|
||||
break;
|
||||
|
||||
// get extension length
|
||||
$extensionlength = 0;
|
||||
|
||||
if($messagelength >= 0x7E){
|
||||
|
||||
$extensionlength = 2;
|
||||
|
||||
if($messagelength == 0x7F){
|
||||
|
||||
$extensionlength = 8;
|
||||
}
|
||||
|
||||
$messagelength = 0;
|
||||
|
||||
$this->socket_recv($this->client, $header, $extensionlength, MSG_WAITALL);
|
||||
|
||||
for($i=0; $i<$extensionlength; $i++){
|
||||
|
||||
$messagelength += ord($header[$i]) << ($extensionlength - $i - 1) * 8;
|
||||
}
|
||||
case 127:
|
||||
$this->socket_recv($this->client, $messagelength, 8, MSG_WAITALL);
|
||||
$messagelength = unpack("J", $messagelength)[1];
|
||||
break;
|
||||
}
|
||||
|
||||
if($messagelength > $this->options["max_ws_rcv_size"]){
|
||||
|
||||
$this->ws_disconnect($this->client, self::close_too_big, "Frame exceeded " . $this->options["max_ws_rcv_size"] . "b limit");
|
||||
$this->ws_disconnect($this->client, self::close_too_big, "Frame exceeds " . $this->options["max_ws_rcv_size"] . "b limit");
|
||||
}
|
||||
|
||||
// get mask
|
||||
$this->socket_recv($this->client, $mask, 4, MSG_WAITALL);
|
||||
if($masked){
|
||||
|
||||
// extract data from frame
|
||||
$this->socket_recv($this->client, $frame_data, $messagelength, MSG_WAITALL);
|
||||
// get mask and message payload
|
||||
$this->socket_recv($this->client, $frame_data, $messagelength + 4, MSG_WAITALL);
|
||||
|
||||
// unmask data
|
||||
for($i=0; $i<strlen($frame_data); $i++){
|
||||
for($i=4; $i<$messagelength; $i++){
|
||||
|
||||
$frame_data[$i] = $frame_data[$i] ^ $mask[$i % 4];
|
||||
$frame_data[$i] = $frame_data[$i] ^ $frame_data[$i % 4];
|
||||
}
|
||||
|
||||
$frame_data = substr($frame_data, 4);
|
||||
}else{
|
||||
|
||||
// get message payload
|
||||
$this->socket_recv($this->client, $frame_data, $messagelength, MSG_WAITALL);
|
||||
}
|
||||
|
||||
// handle data
|
||||
// call user functions
|
||||
switch($opcode){
|
||||
|
||||
case self::op_text:
|
||||
|
@ -423,14 +415,8 @@ class fuckwebsockets{
|
|||
if($finalmessage === false){
|
||||
// partial message, come back later
|
||||
|
||||
if(strlen($buffer) > 0){
|
||||
|
||||
// message is partial but client is
|
||||
// sending more op_text frames? makes no sense!
|
||||
$this->ws_disconnect($this->client, self::close_protocol, "Did not send continue frame for partial message");
|
||||
}
|
||||
|
||||
$buffer = $frame_data;
|
||||
$bufferlength = $messagelength;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -441,27 +427,30 @@ class fuckwebsockets{
|
|||
|
||||
case self::op_continue:
|
||||
$buffer .= $frame_data;
|
||||
$bufferlength += $messagelength;
|
||||
|
||||
if(strlen($buffer) > $this->options["max_ws_rcv_size"]){
|
||||
if($bufferlength > $this->options["max_ws_rcv_size"]){
|
||||
|
||||
$this->ws_disconnect($this->client, self::close_too_big, "Message exceeded " . $this->options["max_ws_rcv_size"] . " bytes limit");
|
||||
$this->ws_disconnect($this->client, self::close_too_big, "Message buffer exceeds " . $this->options["max_ws_rcv_size"] . "b limit");
|
||||
}
|
||||
|
||||
if($finalmessage === true){
|
||||
if($finalmessage){
|
||||
|
||||
// we received the entire thing, trigger event
|
||||
$this->log($this->client, "Text frame (buffered): {$buffer}");
|
||||
$this->log($this->client, "Text frame (buffer): {$buffer}");
|
||||
$buffer = null;
|
||||
$bufferlength = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case self::op_ping:
|
||||
if(strlen($frame_data) > 128){
|
||||
if($messagelength > 126){
|
||||
|
||||
$this->ws_disconnect($this->client, self::close_too_big, "Ping frame exceeded 128 bytes");
|
||||
}
|
||||
|
||||
$this->log($this->client, "Received ping: " . $frame_data);
|
||||
$this->ws_send($this->client, self::op_pong, $frame_data);
|
||||
break;
|
||||
|
||||
|
@ -499,12 +488,18 @@ class fuckwebsockets{
|
|||
exit(0);
|
||||
}elseif($state === false){
|
||||
|
||||
$error = socket_last_error();
|
||||
if($error === 0){
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if($client->request->handshake === false){
|
||||
|
||||
$this->http_disconnect($client, 408, "Read timeout");
|
||||
$this->http_disconnect($client, 408, socket_strerror($error));
|
||||
}else{
|
||||
|
||||
$this->ws_disconnect($client, self::close_no_status, "Read timeout");
|
||||
$this->ws_disconnect($client, self::close_no_status, socket_strerror($error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -590,7 +585,10 @@ class fuckwebsockets{
|
|||
|
||||
public function log(object $client, string $message){
|
||||
|
||||
echo $client->ip . ":" . $client->port . "] " . $message . "\n";
|
||||
if($this->options["debug_log"]){
|
||||
|
||||
echo $client->ip . ":" . $client->port . "] " . $message . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public function http_disconnect(object $client, int $errcode, string $message){
|
||||
|
|
Loading…
Reference in New Issue