89 lines
2.7 KiB
PHP
89 lines
2.7 KiB
PHP
<?php
|
|
|
|
require __DIR__ . '/../app/Core/Database.php';
|
|
|
|
use App\Core\Database;
|
|
|
|
$server = stream_socket_server('tcp://0.0.0.0:8081', $errno, $errstr);
|
|
if (!$server) {
|
|
fwrite(STDERR, "WebSocket error: $errstr\n");
|
|
exit(1);
|
|
}
|
|
|
|
stream_set_blocking($server, false);
|
|
$clients = [];
|
|
$lastEventId = 0;
|
|
echo "WebSocket listening on 0.0.0.0:8081\n";
|
|
|
|
while (true) {
|
|
$read = array_merge([$server], array_column($clients, 'socket'));
|
|
$write = $except = [];
|
|
@stream_select($read, $write, $except, 1);
|
|
|
|
foreach ($read as $socket) {
|
|
if ($socket === $server) {
|
|
$client = stream_socket_accept($server, 0);
|
|
if ($client) {
|
|
stream_set_blocking($client, false);
|
|
$clients[(int) $client] = ['socket' => $client, 'handshake' => false];
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$id = (int) $socket;
|
|
$buffer = fread($socket, 2048);
|
|
if ($buffer === '' || $buffer === false) {
|
|
fclose($socket);
|
|
unset($clients[$id]);
|
|
continue;
|
|
}
|
|
|
|
if (!$clients[$id]['handshake']) {
|
|
if (preg_match('/Sec-WebSocket-Key: (.*)\r\n/i', $buffer, $matches)) {
|
|
$key = trim($matches[1]);
|
|
$accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
|
|
fwrite($socket, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $accept\r\n\r\n");
|
|
$clients[$id]['handshake'] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
$db = Database::connection();
|
|
$stmt = $db->prepare('SELECT id, match_id, event_type, points_home, points_away FROM match_events WHERE id > :id ORDER BY id ASC LIMIT 50');
|
|
$stmt->execute(['id' => $lastEventId]);
|
|
foreach ($stmt->fetchAll() as $event) {
|
|
$lastEventId = (int) $event['id'];
|
|
broadcast($clients, json_encode(['type' => 'match_event', 'data' => $event]));
|
|
}
|
|
} catch (Throwable $e) {
|
|
usleep(300000);
|
|
}
|
|
}
|
|
|
|
function broadcast(array &$clients, string $payload): void
|
|
{
|
|
$frame = frame($payload);
|
|
foreach ($clients as $id => $client) {
|
|
if (!$client['handshake']) {
|
|
continue;
|
|
}
|
|
if (@fwrite($client['socket'], $frame) === false) {
|
|
fclose($client['socket']);
|
|
unset($clients[$id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function frame(string $payload): string
|
|
{
|
|
$length = strlen($payload);
|
|
if ($length <= 125) {
|
|
return chr(129) . chr($length) . $payload;
|
|
}
|
|
if ($length <= 65535) {
|
|
return chr(129) . chr(126) . pack('n', $length) . $payload;
|
|
}
|
|
return chr(129) . chr(127) . pack('J', $length) . $payload;
|
|
}
|