From 06527ab20861ff28347963d9bd2d8ab062a9edfe Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sat, 5 Oct 2024 10:16:05 +0200 Subject: [PATCH] Add close code and reason to Listener --- src/main/php/websocket/Listener.class.php | 4 +++- src/main/php/websocket/WebSocket.class.php | 14 +++++++------- .../websocket/protocol/Connection.class.php | 9 +++++++-- .../php/websocket/protocol/Messages.class.php | 18 +++++++++--------- .../websocket/unittest/WebSocketTest.class.php | 4 ++-- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/main/php/websocket/Listener.class.php b/src/main/php/websocket/Listener.class.php index b100d90..aaece96 100755 --- a/src/main/php/websocket/Listener.class.php +++ b/src/main/php/websocket/Listener.class.php @@ -23,7 +23,9 @@ public abstract function message($connection, $message); * Closes connection * * @param websocket.protocol.Connection $connection + * @param int $code + * @param string $reason * @return void */ - public function close($connection) { /* NOOP */ } + public function close($connection, $code, $reason) { /* NOOP */ } } \ No newline at end of file diff --git a/src/main/php/websocket/WebSocket.class.php b/src/main/php/websocket/WebSocket.class.php index 3e9cbe8..d6b94fa 100755 --- a/src/main/php/websocket/WebSocket.class.php +++ b/src/main/php/websocket/WebSocket.class.php @@ -186,13 +186,13 @@ public function receive($timeout= null) { break; case Opcodes::CLOSE: - $close= unpack('ncode/a*message', $packet); - $this->conn->close($close['code'], $close['message']); + $close= unpack('ncode/a*reason', $packet); + $this->conn->close($close['code'], $close['reason']); $this->socket->close(); // 1000 is a normal close, all others indicate an error if (1000 === $close['code']) return; - throw new ProtocolException('Connection closed (#'.$close['code'].'): '.$close['message']); + throw new ProtocolException('Connection closed (#'.$close['code'].'): '.$close['reason']); } } } @@ -201,18 +201,18 @@ public function receive($timeout= null) { * Closes connection * * @param int $code - * @param string $message + * @param string $reason * @return void */ - public function close($code= 1000, $message= '') { + public function close($code= 1000, $reason= '') { if (!$this->socket->isConnected()) return; try { - $this->conn->message(Opcodes::CLOSE, pack('n', $code).$message, ($this->random)(4)); + $this->conn->message(Opcodes::CLOSE, pack('na*', $code, $reason), ($this->random)(4)); } catch (Throwable $ignored) { // ... } - $this->conn->close($code, $message); + $this->conn->close($code, $reason); $this->socket->close(); } diff --git a/src/main/php/websocket/protocol/Connection.class.php b/src/main/php/websocket/protocol/Connection.class.php index 31290a8..291ac1e 100755 --- a/src/main/php/websocket/protocol/Connection.class.php +++ b/src/main/php/websocket/protocol/Connection.class.php @@ -65,10 +65,15 @@ public function on($payload) { /** * Closes connection * + * @param int $code + * @param string $reason * @return void */ - public function close() { - $this->listener && $this->listener->close($this); + public function close($code= 1000, $reason= '') { + if ($this->socket->isConnected()) { + $this->listener && $this->listener->close($this, $code, $reason); + $this->socket->close(); + } } /** diff --git a/src/main/php/websocket/protocol/Messages.class.php b/src/main/php/websocket/protocol/Messages.class.php index 821e588..253fb4b 100755 --- a/src/main/php/websocket/protocol/Messages.class.php +++ b/src/main/php/websocket/protocol/Messages.class.php @@ -48,21 +48,21 @@ public function next($socket, $i) { case Opcodes::CLOSE: // Close connection if ('' === $payload) { - $close= ['code' => 1000]; + $close= ['code' => 1000, 'reason' => '']; } else { - $close= unpack('ncode/a*message', $payload); - if (!preg_match('//u', $close['message'])) { - $close= ['code' => 1007]; + $close= unpack('ncode/a*reason', $payload); + if (!preg_match('//u', $close['reason'])) { + $close= ['code' => 1007, 'reason' => '']; } else if ($close['code'] > 2999 || in_array($close['code'], [1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011])) { - // Answer with client code and message + // Answer with client code and reason } else { - $close= ['code' => 1002]; + $close= ['code' => 1002, 'reason' => '']; } } - $conn->answer(Opcodes::CLOSE, pack('na*', $close['code'], $close['message'] ?? '')); - $this->logging->log($i, 'CLOSE', $close); - $socket->close(); + $conn->answer(Opcodes::CLOSE, pack('na*', $close['code'], $close['reason'])); + $this->logging->log($i, 'CLOSE', $close['code'].($close['reason'] ? ': '.$close['reason'] : '')); + $this->listeners->connections[$i]->close($close['code'], $close['reason']); break; } } catch (Throwable $t) { diff --git a/src/test/php/websocket/unittest/WebSocketTest.class.php b/src/test/php/websocket/unittest/WebSocketTest.class.php index 7d4a499..aa52bae 100755 --- a/src/test/php/websocket/unittest/WebSocketTest.class.php +++ b/src/test/php/websocket/unittest/WebSocketTest.class.php @@ -180,7 +180,7 @@ public function listening() { public $events= []; public function open($conn) { $this->events[]= 'open'; } public function message($conn, $message) { $this->events[]= "message<{$message}>"; } - public function close($conn) { $this->events[]= 'close'; } + public function close($conn, $code, $reason) { $this->events[]= "close<{$code}>"; } }; $fixture= $this->fixture("\x81\x04Test")->listening($listener); @@ -188,6 +188,6 @@ public function close($conn) { $this->events[]= 'close'; } iterator_to_array($fixture->receive()); $fixture->close(); - Assert::equals(['open', 'message', 'close'], $listener->events); + Assert::equals(['open', 'message', 'close<1000>'], $listener->events); } } \ No newline at end of file