125 lines
4.1 KiB
PHP
125 lines
4.1 KiB
PHP
<?php
|
|
|
|
require __DIR__ . "/../vendor/autoload.php";
|
|
|
|
use Ratchet\MessageComponentInterface;
|
|
use Ratchet\ConnectionInterface;
|
|
use Ratchet\Server\IoServer;
|
|
use Ratchet\Http\HttpServer;
|
|
use Ratchet\Http\Router;
|
|
use Ratchet\WebSocket\WsServer;
|
|
use Symfony\Component\Routing\RouteCollection;
|
|
use Symfony\Component\Routing\Route;
|
|
use Symfony\Component\Routing\RequestContext;
|
|
use Symfony\Component\Routing\Matcher\UrlMatcher;
|
|
use ComCen\Http\LoginController;
|
|
use ComCen\Http\RegisterController;
|
|
use ComCen\Database\Handler;
|
|
use \ComCen\Security\TokenHandler;
|
|
|
|
class WebSocketServer implements MessageComponentInterface
|
|
{
|
|
private $connectionsData = [];
|
|
|
|
private function isSameConnection(ConnectionInterface $connection1, ConnectionInterface $connection2): bool
|
|
{
|
|
return $connection1->resourceId === $connection2->resourceId;
|
|
}
|
|
private function getConnectionIndex(ConnectionInterface $connection): int | null
|
|
{
|
|
foreach ($this->connectionsData as $i => $connectionData) {
|
|
if ($this->isSameConnection($connection, $connectionData["connection"])) {
|
|
return $i;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
private function sendToAllAuthenticated(string $username, string $msg): void
|
|
{
|
|
foreach ($this->connectionsData as $connectionData) {
|
|
if ($connectionData["username"] !== $username) {
|
|
$connectionData["connection"]->send("{\"sender\": \"{$username}\",\"msg\": \"{$msg}\"");
|
|
}
|
|
}
|
|
}
|
|
private function deleteGivenId(int $id): void
|
|
{
|
|
foreach ($this->connectionsData as $i => $connectionData) {
|
|
if ($connectionData["connection"]->resourceId === $id) {
|
|
array_splice($this->connectionsData, $i, 1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function onOpen(ConnectionInterface $conn): void
|
|
{
|
|
$this->connectionsData[] = [
|
|
"connection" => $conn,
|
|
"username" => null
|
|
];
|
|
echo "New connection: {$conn->resourceId}\n";
|
|
}
|
|
|
|
public function onMessage(ConnectionInterface $from, $msg): void
|
|
{
|
|
$decodedMsg = json_decode($msg, true);
|
|
if (!$decodedMsg) {
|
|
$from->send("{\"error\"}: \"not or empty json\"");
|
|
return;
|
|
}
|
|
$index = $this->getConnectionIndex($from);
|
|
if ($index === null) return;
|
|
|
|
if ($this->connectionsData[$index]["username"]) {
|
|
$msgContent = $decodedMsg["msg"] ?? null;
|
|
if ($msgContent) {
|
|
$this->sendToAllAuthenticated($this->connectionsData[$index]["username"], $msgContent);
|
|
$from->send("{\"success\"}: \"message send\"");
|
|
return;
|
|
}
|
|
$from->send("{\"error\"}: \"no message\"");
|
|
return;
|
|
}
|
|
|
|
$token = $decodedMsg["token"] ?? null;
|
|
if ($token) {
|
|
$tokenUser = TokenHandler::getTokenOwnership($token);
|
|
if ($tokenUser) {
|
|
$this->connectionsData[$index]["username"] = $tokenUser;
|
|
$from->send("{\"success\"}: \"authenticated\"");
|
|
return;
|
|
}
|
|
$from->send("{\"error\"}: \"invalid token\"");
|
|
return;
|
|
}
|
|
$from->send("{\"error\"}: \"you are not authenticated\"");
|
|
}
|
|
|
|
public function onClose(ConnectionInterface $conn): void
|
|
{
|
|
$this->deleteGivenId($conn->resourceId);
|
|
echo "Connection {$conn->resourceId} closed\n";
|
|
}
|
|
|
|
public function onError(ConnectionInterface $conn, \Exception $e): void
|
|
{
|
|
echo "Error: {$e->getMessage()}\n";
|
|
$this->deleteGivenId($conn->resourceId);
|
|
$this->onClose($conn);
|
|
}
|
|
}
|
|
|
|
$routes = new RouteCollection();
|
|
$routes->add("login", new Route("/login", ["_controller" => new LoginController()]));
|
|
$routes->add("register", new Route("/register", ["_controller" => new RegisterController()]));
|
|
$routes->add("ws", new Route("/ws", ["_controller" => new WsServer(new WebSocketServer())]));
|
|
|
|
$server = IoServer::factory(
|
|
new HttpServer(new Router(new UrlMatcher($routes, new RequestContext()))),
|
|
8080
|
|
);
|
|
|
|
echo "Server running on http://localhost:8080\n";
|
|
|
|
$server->run(); |