38443-vm/ws/server.php
Flatlogic Bot 4883125cda v2
2026-02-15 10:30:17 +00:00

101 lines
3.0 KiB
PHP

<?php
// Very basic WebSocket server in pure PHP
$host = '0.0.0.0';
$port = 8080;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, $host, $port);
socket_listen($socket);
$clients = [$socket];
echo "Server started on $host:$port\n";
while (true) {
$read = $clients;
$write = $except = null;
socket_select($read, $write, $except, null);
if (in_array($socket, $read)) {
$new_socket = socket_accept($socket);
$clients[] = $new_socket;
$header = socket_read($new_socket, 1024);
perform_handshake($header, $new_socket, $host, $port);
echo "New client connected\n";
$key = array_search($socket, $read);
unset($read[$key]);
}
foreach ($read as $client_socket) {
$data = socket_read($client_socket, 1024);
if ($data === false || strlen($data) === 0) {
$key = array_search($client_socket, $clients);
unset($clients[$key]);
socket_close($client_socket);
echo "Client disconnected\n";
continue;
}
$decoded_data = unmask($data);
if ($decoded_data) {
$response = mask(json_encode(['type' => 'message', 'data' => $decoded_data]));
foreach ($clients as $client) {
if ($client != $socket) {
@socket_write($client, $response, strlen($response));
}
}
}
}
}
function perform_handshake($receved_header, $client_conn, $host, $port) {
$headers = array();
$lines = preg_split("/\r\n/", $receved_header);
foreach ($lines as $line) {
$line = chop($line);
if (preg_match('/\A(\S+): (.*)\z/', $line, $matches)) {
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$upgrade = "HTTP/1.1 101 Switching Protocols\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept: $secAccept\r\n\r\n";
socket_write($client_conn, $upgrade, strlen($upgrade));
}
function unmask($text) {
$length = ord($text[1]) & 127;
if ($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
} elseif ($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
} else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i % 4];
}
return $text;
}
function mask($text) {
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125)
$header = pack('CC', $b1, $length);
elseif ($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif ($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header . $text;
}