58 lines
1.9 KiB
PHP
58 lines
1.9 KiB
PHP
<?php
|
|
|
|
function enet_probe(string $host, int $port, float $timeout = 2.0): bool
|
|
{
|
|
$host = trim($host);
|
|
$addr = filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
|
|
? "[{$host}]"
|
|
: $host;
|
|
|
|
$sock = @stream_socket_client(
|
|
"udp://{$addr}:{$port}",
|
|
$errno, $errstr, $timeout, STREAM_CLIENT_CONNECT
|
|
);
|
|
if ($sock === false) return false;
|
|
|
|
stream_set_timeout($sock,
|
|
(int) floor($timeout),
|
|
(int) (fmod($timeout, 1.0) * 1_000_000)
|
|
);
|
|
|
|
$connectID = mt_rand(1, 0x7FFFFFFF);
|
|
|
|
// --- Protocol header (4 bytes, NO CRC32) ---
|
|
// 0x8FFF = SENT_TIME flag (0x8000) | peer 0xFFF (max/unassigned)
|
|
$header = pack('nn', 0x8FFF, 0);
|
|
|
|
// --- Command header (4 bytes) ---
|
|
$cmdHeader = pack('CCn', 0x82, 0xFF, 1);
|
|
|
|
// --- Connect body (44 bytes) ---
|
|
$cmdBody = pack('n', 0); // outgoingPeerID
|
|
$cmdBody .= pack('CC', 0xFF, 0xFF); // incomingSessionID, outgoingSessionID
|
|
$cmdBody .= pack('N', 1400); // mtu
|
|
$cmdBody .= pack('N', 65536); // windowSize
|
|
$cmdBody .= pack('N', 2); // channelCount
|
|
$cmdBody .= pack('N', 0); // incomingBandwidth
|
|
$cmdBody .= pack('N', 0); // outgoingBandwidth
|
|
$cmdBody .= pack('N', 5000); // packetThrottleInterval
|
|
$cmdBody .= pack('N', 2); // packetThrottleAcceleration
|
|
$cmdBody .= pack('N', 2); // packetThrottleDeceleration
|
|
$cmdBody .= pack('N', $connectID); // connectID
|
|
$cmdBody .= pack('N', 0); // data
|
|
|
|
$packet = $header . $cmdHeader . $cmdBody;
|
|
|
|
$written = @fwrite($sock, $packet);
|
|
if ($written !== strlen($packet)) {
|
|
fclose($sock);
|
|
return false;
|
|
}
|
|
|
|
$response = @fread($sock, 512);
|
|
$meta = stream_get_meta_data($sock);
|
|
fclose($sock);
|
|
|
|
return !$meta['timed_out'] && $response !== '' && $response !== false;
|
|
}
|