diff --git a/ProxyServer.php b/ProxyServer.php index 4a65dc7..d56450d 100644 --- a/ProxyServer.php +++ b/ProxyServer.php @@ -4,133 +4,182 @@ namespace libproxy; -use ErrorException; use libproxy\protocol\DisconnectPacket; use libproxy\protocol\ForwardPacket; use libproxy\protocol\LoginPacket; use libproxy\protocol\ProxyPacket; use libproxy\protocol\ProxyPacketPool; use libproxy\protocol\ProxyPacketSerializer; +use NetherGames\Quiche\io\QueueWriter; +use NetherGames\Quiche\QuicheConnection; +use NetherGames\Quiche\socket\QuicheServerSocket; +use NetherGames\Quiche\SocketAddress; +use NetherGames\Quiche\stream\BiDirectionalQuicheStream; +use NetherGames\Quiche\stream\QuicheStream; use pmmp\thread\ThreadSafeArray; use pocketmine\network\mcpe\raklib\PthreadsChannelReader; use pocketmine\network\mcpe\raklib\SnoozeAwarePthreadsChannelWriter; use pocketmine\network\PacketHandlingException; +use pocketmine\snooze\SleeperHandler; use pocketmine\snooze\SleeperHandlerEntry; -use pocketmine\snooze\SleeperNotifier; use pocketmine\thread\log\AttachableThreadSafeLogger; use pocketmine\utils\Binary; use pocketmine\utils\BinaryDataException; -use pocketmine\utils\Utils; -use raklib\generic\SocketException; use Socket; -use function count; -use function min; -use function socket_accept; -use function socket_close; -use function socket_getpeername; -use function socket_last_error; -use function socket_read; -use function socket_recv; -use function socket_select; -use function socket_set_option; -use function socket_shutdown; -use function socket_strerror; -use function socket_write; +use function array_keys; +use function spl_object_id; use function strlen; -use function trim; -use const MSG_DONTWAIT; -use const MSG_WAITALL; -use const SO_LINGER; -use const SO_RCVTIMEO; -use const SO_SNDTIMEO; -use const SOCKET_EWOULDBLOCK; -use const SOL_SOCKET; +use function substr; class ProxyServer { - private const SERVER_SOCKET = -1; - private const NOTIFY_SOCKET = -2; + public const PING_SYNC_INTERVAL = 2; - private const MAX_FRAME_LENGTH = 65535; - - private const LENGTH_NEEDED = 0; - private const BUFFER = 1; - - /** @var AttachableThreadSafeLogger */ - private AttachableThreadSafeLogger $logger; /** @var PthreadsChannelReader */ private PthreadsChannelReader $mainToThreadReader; /** @var SnoozeAwarePthreadsChannelWriter */ private SnoozeAwarePthreadsChannelWriter $threadToMainWriter; + private QuicheServerSocket $serverSocket; - /** @var Socket */ - private Socket $serverSocket; - /** @var Socket */ - private Socket $notifySocket; + /** @var SleeperHandler */ + private SleeperHandler $sleeperHandler; - /** @var Socket[] */ - private array $sockets = []; - /** @phpstan-var array> */ - private array $socketBuffer = []; + /** @var array */ + private array $streamWriters = []; + /** @var array */ + private array $connectionIdByStreamId = []; + /** @var array */ + private array $connections = []; + /** @var array */ + private array $streams = []; - /** @var int */ - private int $socketId = 0; - - public function __construct(AttachableThreadSafeLogger $logger, Socket $serverSocket, ThreadSafeArray $mainToThreadBuffer, ThreadSafeArray $threadToMainBuffer, SleeperHandlerEntry $sleeperEntry, Socket $notifySocket) + /** @phpstan-var array */ + private array $socketBuffer = []; + /** @phpstan-var array */ + private array $socketBufferLengthNeeded = []; + + private int $streamIdentifier = 0; + private int $lastPingSync = 0; + + public function __construct( + private readonly AttachableThreadSafeLogger $logger, + SocketAddress $serverAddress, + ThreadSafeArray $mainToThreadBuffer, + ThreadSafeArray $threadToMainBuffer, + SleeperHandlerEntry $sleeperEntry, + Socket $notifySocket + ) { - $this->logger = $logger; - $this->serverSocket = $serverSocket; - $this->notifySocket = $notifySocket; + $this->sleeperHandler = new SleeperHandler(); + $this->serverSocket = $this->createServerSocket($serverAddress, $notifySocket); $this->mainToThreadReader = new PthreadsChannelReader($mainToThreadBuffer); $this->threadToMainWriter = new SnoozeAwarePthreadsChannelWriter($threadToMainBuffer, $sleeperEntry->createNotifier()); } + private function createServerSocket(SocketAddress $socketAddress, Socket $notifySocket): QuicheServerSocket + { + $serverSocket = new QuicheServerSocket([$socketAddress], function (QuicheConnection $connection, ?QuicheStream $stream): void { + if ($stream instanceof BiDirectionalQuicheStream) { + $streamIdentifier = $this->streamIdentifier++; + $peerAddress = $connection->getPeerAddress(); + + $this->streamWriters[$streamIdentifier] = $stream->setupWriter(); + $this->connectionIdByStreamId[$streamIdentifier] = spl_object_id($connection); + $this->streams[$streamIdentifier] = $stream; + + $pk = new LoginPacket(); + $pk->ip = $peerAddress->getAddress(); + $pk->port = $peerAddress->getPort(); + $this->sendToMainBuffer($streamIdentifier, $pk); + + $stream->setShutdownReadingCallback(function (bool $peerClosed) use ($streamIdentifier): void { + if ($peerClosed) { + if (isset($this->streamWriters[$streamIdentifier])) { // check if the stream is still open + $this->shutdownStream($streamIdentifier, 'client disconnect', false); + } + } else { + $this->onStreamShutdown($streamIdentifier); + } + }); + + $stream->setOnDataArrival(function (string $data) use ($streamIdentifier): void { + $this->onDataReceive($streamIdentifier, $data); + }); + } else if ($stream === null) { + $this->connections[$connectionId = spl_object_id($connection)] = $connection; + + $connection->setPeerCloseCallback(function () use ($connectionId): void { + unset($this->connections[$connectionId]); + }); + } else { + throw new \RuntimeException('Invalid stream type'); + } + }); + + $serverConfig = $serverSocket->getConfig(); + $serverConfig->loadPrivKeyFromFile(__DIR__ . "/certificates/key.pem"); + $serverConfig->loadCertChainFromFile(__DIR__ . "/certificates/cert.pem"); + $serverConfig->setApplicationProtos(['ng']); + $serverConfig->setVerifyPeer(false); + $serverConfig->enableBidirectionalStreams(); + $serverConfig->setInitialMaxData(10000000); + $serverConfig->setMaxIdleTimeout(2000); + + $serverSocket->registerSocket($notifySocket, fn() => $this->pushSockets()); + + return $serverSocket; + } + public function waitShutdown(): void { - foreach ($this->sockets as $socketId => $socket) { - $this->closeSocket($socketId, "server shutdown", true); + foreach (array_keys($this->streamWriters) as $streamIdentifier) { + $this->shutdownStream($streamIdentifier, 'server shutdown', true); } - while (count($this->sockets) > 0) { - $this->tickProcessor(); - } + $this->serverSocket->close(false, 0, 'server shutdown'); + } - @socket_close($this->serverSocket); - @socket_close($this->notifySocket); + private function onStreamShutdown(int $streamIdentifier): void + { + unset($this->streamWriters[$streamIdentifier], $this->connectionIdByStreamId[$streamIdentifier], $this->streams[$streamIdentifier]); } - private function closeSocket(int $socketId, string $reason, bool $fromMain = false): void + public function getTickSleeper(): SleeperHandler { - if (($socket = $this->getSocket($socketId)) !== null) { - try { - socket_shutdown($socket); - } catch (ErrorException $exception) { - $this->logger->debug('Socket is not connected anymore.'); - } - socket_close($socket); - unset($this->sockets[$socketId], $this->socketBuffer[$socketId]); - } + return $this->sleeperHandler; + } - $this->logger->debug("Disconnected socket with id " . $socketId); + private function getStreamWriter(int $streamIdentifier): ?QueueWriter + { + return $this->streamWriters[$streamIdentifier] ?? null; + } + private function shutdownStream(int $streamIdentifier, string $reason, bool $fromMain): void + { if (!$fromMain) { $pk = new DisconnectPacket(); $pk->reason = $reason; - $this->putPacket($socketId, $pk); + $this->sendToMainBuffer($streamIdentifier, $pk); } - } - public function getSocket(int $socketId): ?Socket - { - return $this->sockets[$socketId] ?? null; + if (($stream = $this->streams[$streamIdentifier] ?? null) !== null) { + if ($stream->isReadable()) { + $stream->shutdownReading(); + } + if ($stream->isWritable()) { + $stream->gracefulShutdownWriting(); + } + + $this->onStreamShutdown($streamIdentifier); + } } - private function putPacket(int $socketId, ProxyPacket $pk): void + private function sendToMainBuffer(int $streamIdentifier, ProxyPacket $pk): void { $serializer = new ProxyPacketSerializer(); - $serializer->putLInt($socketId); + $serializer->putLInt($streamIdentifier); $pk->encode($serializer); @@ -139,26 +188,16 @@ private function putPacket(int $socketId, ProxyPacket $pk): void public function tickProcessor(): void { - $read = $this->sockets; - $read[self::SERVER_SOCKET] = $this->serverSocket; - $read[self::NOTIFY_SOCKET] = $this->notifySocket; - - $write = null; - $except = null; - - $select = socket_select($read, $write, $except, 5); - if ($select !== false && $select > 0) { - foreach ($read as $socketId => $socket) { - /** @var int $socketId */ - if ($socketId === self::NOTIFY_SOCKET) { - socket_read($socket, self::MAX_FRAME_LENGTH); //clean socket - $this->pushSockets(); - } elseif ($socketId === self::SERVER_SOCKET) { - $this->onServerSocketReceive(); - } else { - $this->onSocketReceive($socketId); - } - } + $this->serverSocket->selectSockets(50); + $this->checkPing(); + } + + public function checkPing(): void + { + if (time() - $this->lastPingSync > self::PING_SYNC_INTERVAL) { + $this->lastPingSync = time(); + + } } @@ -166,7 +205,7 @@ private function pushSockets(): void { while (($payload = $this->mainToThreadReader->read()) !== null) { $stream = new ProxyPacketSerializer($payload); - $socketId = $stream->getLInt(); + $streamIdentifier = $stream->getLInt(); if (($pk = ProxyPacketPool::getInstance()->getPacket($payload, $stream->getOffset())) === null) { throw new PacketHandlingException('Packet does not exist'); @@ -175,149 +214,69 @@ private function pushSockets(): void try { $pk->decode($stream); } catch (BinaryDataException $e) { - $this->logger->debug('Closed socket with id(' . $socketId . ') because packet was invalid.'); - $this->closeSocket($socketId, 'Invalid Packet'); + $this->logger->debug('Closed stream with id(' . $streamIdentifier . ') because server sent invalid packet'); + $this->shutdownStream($streamIdentifier, 'invalid packet', false); return; } - try { - switch ($pk->pid()) { - case DisconnectPacket::NETWORK_ID: - /** @var DisconnectPacket $pk */ - if ($this->getSocket($socketId) !== null) { - $this->closeSocket($socketId, $pk->reason, true); - } - break; - case ForwardPacket::NETWORK_ID: - /** @var ForwardPacket $pk */ - if (($socket = $this->getSocket($socketId)) === null) { - throw new PacketHandlingException('Socket with id (' . $socketId . ") doesn't exist."); - } - - try { - if (socket_write($socket, Binary::writeInt(strlen($pk->payload)) . $pk->payload) === false) { - throw new PacketHandlingException('client disconnect'); - } - } catch (ErrorException $exception) { - throw PacketHandlingException::wrap($exception, 'client disconnect'); - } - break; - } - } catch (PacketHandlingException $exception) { - $this->closeSocket($socketId, $exception->getMessage()); + switch ($pk->pid()) { + case DisconnectPacket::NETWORK_ID: + /** @var DisconnectPacket $pk */ + if ($this->getStreamWriter($streamIdentifier) !== null) { + $this->shutdownStream($streamIdentifier, $pk->reason, true); + } + break; + case ForwardPacket::NETWORK_ID: + /** @var ForwardPacket $pk */ + if (($writer = $this->getStreamWriter($streamIdentifier)) === null) { + $this->shutdownStream($streamIdentifier, 'stream not found', false); + return; + } + + $writer->write(Binary::writeInt(strlen($pk->payload)) . $pk->payload); + break; } } } - private function onServerSocketReceive(): void + private function onDataReceive(int $socketIdentifier, string $data): void { - $socket = socket_accept($this->serverSocket); - if ($socket === false) { - $this->logger->debug("Couldn't accept new socket request: " . socket_strerror(socket_last_error($this->serverSocket))); + if (isset($this->socketBuffer[$socketIdentifier])) { //todo: allow reading from a continues stream + $this->socketBuffer[$socketIdentifier] .= $data; } else { - try { - if (socket_getpeername($socket, $ip, $port)) { - $this->sockets[$socketId = $this->socketId++] = $socket; - - $this->logger->debug('Socket(' . $socketId . ') created a session from ' . $ip . ':' . $port); - - socket_set_option($socket, SOL_SOCKET, SO_LINGER, ["l_onoff" => 1, "l_linger" => 0]); - socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, ["sec" => 4, "usec" => 0]); - socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ["sec" => 4, "usec" => 0]); + $this->socketBuffer[$socketIdentifier] = $data; + } - $pk = new LoginPacket(); - $pk->ip = $ip; - $pk->port = $port; + while (true) { + $buffer = $this->socketBuffer[$socketIdentifier]; + $length = strlen($buffer); + $lengthNeeded = $this->socketBufferLengthNeeded[$socketIdentifier] ?? null; - $this->putPacket($socketId, $pk); + if ($lengthNeeded === null) { + if ($length < 4) { // first 4 bytes are the length of the packet + return; // wait for more data } else { - $this->logger->debug('New socket request already disconnected: ' . socket_strerror(socket_last_error($this->serverSocket))); + try { + $packetLength = Binary::readInt(substr($buffer, 0, 4)); + } catch (BinaryDataException $exception) { + $this->shutdownStream($socketIdentifier, 'invalid packet', false); + return; + } + + $this->socketBufferLengthNeeded[$socketIdentifier] = $packetLength; + $this->socketBuffer[$socketIdentifier] = substr($buffer, 4); } - } catch (ErrorException $exception) { - $this->logger->debug('New socket request already disconnected: ' . socket_strerror(socket_last_error($this->serverSocket))); - } - } - } + } else if ($length >= $lengthNeeded) { + $pk = new ForwardPacket(); + $pk->payload = substr($buffer, 0, $lengthNeeded); - private function onSocketReceive(int $socketId): void - { - $rawFrameData = null; - - try { - if (isset($this->socketBuffer[$socketId])) { - /** @var int $length */ - /** @var string $buffer */ - [$length, $buffer] = $this->socketBuffer[$socketId]; - - $rawFrameData = $this->readBytes($socketId, $length, $buffer); - } elseif (($rawFrameLength = $this->readBytes($socketId, 4)) !== null) { - try { - $packetLength = Binary::readInt($rawFrameLength); - } catch (BinaryDataException $exception) { - throw new SocketException('Not enough bytes to read', 0, $exception); - } + $this->sendToMainBuffer($socketIdentifier, $pk); - $this->socketBuffer[$socketId] = [ - self::LENGTH_NEEDED => $packetLength, - self::BUFFER => '', - ]; - - $rawFrameData = $this->readBytes($socketId, $packetLength); + $this->socketBuffer[$socketIdentifier] = substr($buffer, $lengthNeeded); + unset($this->socketBufferLengthNeeded[$socketIdentifier]); + } else { + return; // wait for more data } - } catch (SocketException $exception) { - $this->closeSocket($socketId, $exception->getMessage()); - $this->logger->debug('Socket(' . $socketId . ') returned ' . $exception->getMessage()); - return; } - - // A null frame data indicates that there is not enough bytes to read. - if ($rawFrameData !== null) { - unset($this->socketBuffer[$socketId]); - - $pk = new ForwardPacket(); - $pk->payload = $rawFrameData; - - $this->putPacket($socketId, $pk); - } - } - - private function readBytes(int $socketId, int $remainingLength, string $previousBuffer = ''): ?string - { - /** @var Socket $socket */ - $socket = $this->getSocket($socketId); - - $length = min(self::MAX_FRAME_LENGTH, $remainingLength); - if (Utils::getOS() === Utils::OS_WINDOWS) { - // Honestly I do not think this is a problem since we are not going to deploy - // windows as our "production" nodes. - $receivedLength = @socket_recv($socket, $buffer, $length, MSG_WAITALL); - } else { - $receivedLength = @socket_recv($socket, $buffer, $length, MSG_DONTWAIT); - } - - if (!$receivedLength) { - $errno = socket_last_error($socket); - if ($errno === SOCKET_EWOULDBLOCK) { - return null; - } - // Indicates that the socket was closed. - if ($errno === 0) { - throw new SocketException("client disconnect"); - } - - // Otherwise throw an exception as normal. - throw new SocketException(strtolower(trim(socket_strerror($errno))) . " (errno $errno)", $errno); - } - - if ($remainingLength === $receivedLength) { - return $previousBuffer . $buffer; - } - - $this->socketBuffer[$socketId] = [ - self::LENGTH_NEEDED => $remainingLength - $receivedLength, - self::BUFFER => $previousBuffer . $buffer, - ]; - - return null; } } \ No newline at end of file diff --git a/ProxyThread.php b/ProxyThread.php index ab024f9..f7d7b34 100644 --- a/ProxyThread.php +++ b/ProxyThread.php @@ -6,68 +6,29 @@ namespace libproxy; +use NetherGames\Quiche\SocketAddress; use pmmp\thread\ThreadSafeArray; use pocketmine\Server; use pocketmine\snooze\SleeperHandlerEntry; use pocketmine\thread\log\AttachableThreadSafeLogger; use pocketmine\thread\Thread; -use pocketmine\utils\Utils; -use RuntimeException; use Socket; -use function gc_enable; -use function ini_set; -use function socket_bind; -use function socket_create; -use function socket_last_error; -use function socket_listen; -use function socket_set_option; -use function socket_strerror; -use const AF_INET; -use const SO_RCVBUF; -use const SO_REUSEADDR; -use const SO_SNDBUF; -use const SOCK_STREAM; -use const SOL_SOCKET; -use const SOL_TCP; -use const TCP_NODELAY; class ProxyThread extends Thread { - public ?string $autoloaderPath = null; - /** @var AttachableThreadSafeLogger */ - private AttachableThreadSafeLogger $logger; - /** @var bool */ private bool $ready = false; - /** @var ThreadSafeArray */ - private ThreadSafeArray $mainToThreadBuffer; - /** @var ThreadSafeArray */ - private ThreadSafeArray $threadToMainBuffer; - - /** @var SleeperHandlerEntry */ - private SleeperHandlerEntry $sleeperEntry; - /** @var Socket */ - private Socket $notifySocket; - - /** @var string */ - private string $serverIp; - /** @var int */ - private int $serverPort; - - public function __construct(?string $autoloaderPath, string $serverIp, int $serverPort, AttachableThreadSafeLogger $logger, ThreadSafeArray $mainToThreadBuffer, ThreadSafeArray $threadToMainBuffer, SleeperHandlerEntry $sleeperEntry, Socket $notifySocket) + public function __construct( + private ?string $autoloaderPath, + private string $serverIp, + private int $serverPort, + private AttachableThreadSafeLogger $logger, + private ThreadSafeArray $mainToThreadBuffer, + private ThreadSafeArray $threadToMainBuffer, + private SleeperHandlerEntry $sleeperEntry, + private Socket $notifySocket + ) { - $this->autoloaderPath = $autoloaderPath; - - $this->serverIp = $serverIp; - $this->serverPort = $serverPort; - $this->logger = $logger; - $this->notifySocket = $notifySocket; - - $this->mainToThreadBuffer = $mainToThreadBuffer; - $this->threadToMainBuffer = $threadToMainBuffer; - - $this->sleeperEntry = $sleeperEntry; - $this->setClassLoaders([Server::getInstance()->getLoader()]); } @@ -99,11 +60,11 @@ protected function onRun(): void $proxy = new ProxyServer( $this->logger, - $this->createServerSocket(), + new SocketAddress($this->serverIp, $this->serverPort), $this->mainToThreadBuffer, $this->threadToMainBuffer, $this->sleeperEntry, - $this->notifySocket, + $this->notifySocket ); $this->synchronized(function (): void { @@ -117,33 +78,4 @@ protected function onRun(): void $proxy->waitShutdown(); } - - private function createServerSocket(): Socket - { - $serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - - if ($serverSocket === false) { - throw new RuntimeException("Failed to create socket: " . socket_strerror(socket_last_error())); - } - if (!socket_set_option($serverSocket, SOL_SOCKET, SO_REUSEADDR, 1)) { - throw new RuntimeException("Failed to set option on socket: " . socket_strerror(socket_last_error($serverSocket))); - } - if (!socket_bind($serverSocket, $this->serverIp, $this->serverPort)) { - throw new RuntimeException("Failed to bind to socket: " . socket_strerror(socket_last_error($serverSocket))); - } - if (!socket_listen($serverSocket, 10)) { - throw new RuntimeException("Failed to listen to socket: " . socket_strerror(socket_last_error($serverSocket))); - } - if (!socket_set_option($serverSocket, SOL_TCP, TCP_NODELAY, 1)) { - throw new RuntimeException("Failed to set option on socket: " . socket_strerror(socket_last_error($serverSocket))); - } - - if (Utils::getOS() !== Utils::OS_MACOS) { - if (!socket_set_option($serverSocket, SOL_SOCKET, SO_SNDBUF, 8 * 1024 * 1024) || !socket_set_option($serverSocket, SOL_SOCKET, SO_RCVBUF, 8 * 1024 * 1024)) { - throw new RuntimeException("Failed to set option on socket: " . socket_strerror(socket_last_error($serverSocket))); - } - } - - return $serverSocket; - } } diff --git a/certificates/ca.crt b/certificates/ca.crt new file mode 100644 index 0000000..5a633c4 --- /dev/null +++ b/certificates/ca.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIUZnNKXcvNEELAYaBDlAsTkc+HW60wDQYJKoZIhvcNAQEL +BQAwVDEOMAwGA1UEAwwFTkcgQ0ExCzAJBgNVBAYTAkxVMRMwEQYDVQQIDApMdXhl +bWJvdXJnMRMwEQYDVQQHDApMdXhlbWJvdXJnMQswCQYDVQQKDAJORzAeFw0yNDAx +MjcwOTM4MzFaFw0zNDAxMjQwOTM4MzFaMFQxDjAMBgNVBAMMBU5HIENBMQswCQYD +VQQGEwJMVTETMBEGA1UECAwKTHV4ZW1ib3VyZzETMBEGA1UEBwwKTHV4ZW1ib3Vy +ZzELMAkGA1UECgwCTkcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC5 +aXuHjOeoLaD20CnwB3ACCrFn6bbcvzmjnzrY6nIYDo7BSVXFiW45oL+kl6sf/FOg +fb9LZ9fGWb9luoRIDgyucHWkJ3TSL+AzDqS3bxzwcexj41fOEyVgJu+lqw4iX7qH +jNRI2HXqN6QZPpEdKoMdSBogkuJRYgA70O5mfhRCyPzLDmCen7QCIO/WjtGwfkk1 +i3HllB6KPrcDsl3wG7HzfhmXbC0dsOnK9A5IuwTays+zoKkJJamDXFlrNiC2WccD +6JOLGoutXqP41lLf5y8NZ7nUXRld08+AqTonmRNw6ELMTAS8aw9l84BY78wDvAOd +tailAdEx2Af0Jx7Rf4KkyYoaqGZEVJQY3cIlSA+iZ3jlhjrobZS2UnQT2LtUuD18 +O0+NuRdm6+1mhwQWoAKnrJuRwASrVN1WzrkREuJ0VV0r0uaT/xcxZgcYLAvUOuW7 +TxMBJ7wLjvYJIucQX2YM3YjaDniQmhD2vtv3xStxptrkcNUAHk1BGwCUtbi+/Ubm +dlSmrIe0KiI6MO0NQsVaapc8DuyVIsEk5aKFUhX27hTSyVjqh+uGKF81VAapQOR1 +Ok5mzXHjL8gfvWiJr3dslTMoJRGSEN+PXkpdjXM1hnHJ9PR1irSQLladBSVO3160 +FQz0tqSDpWKFQPSuQKfF+K42oEyesZPZNHAqQjaHiQIDAQABo1MwUTAdBgNVHQ4E +FgQUx2SA73BmHtc5nvr2HrJRv4s6nnAwHwYDVR0jBBgwFoAUx2SA73BmHtc5nvr2 +HrJRv4s6nnAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAqoPG +rfg9ywZx8On5Wdd6VvGjmBG2icJuhid6+8mFG91LPiPWhrbLbE4qg6AAH0/jJLFA +TauQcR27jl0Cedw7sDs+565j6wr1hIzEIUHxrsPcztV35sX46hQW8wAZ2FP1b15Z +ajcjubMqIKkhjnxDdcoK6VHDfPWfe2lGHm1hyhAPu5iU1G1uoJclNzeAv8vJhCbO +JRYk8PBazsRL8cP0dqAeJOWwB7vptIenIooiDfts4MdBKRZ+imYrY0rehXV0qOXy +YNzuR2TvYwc1K8k5yR7loK+6+KGZSEe7y9ZiQ/EHtkRkmKVLvwiWLv3jPohIq2/f +ZnDj+Rq+aeTB3xywNDAVt5AGu76d6S5mnvckh+nGYgVDUc7Z9l6avptNPSRpKzcO +0riINrGuvwHUztbqKpsCQEUfnbuIeALpvTNd0MJrrIHmsrUvY4efzt/kL2vNeh6z +tOb7LOmaNXkMAmYyTBxAgnZkCEoX7Mlyx50wn5ZDZg9KtgetKKTayHj6Rm3cbE+O +NBJbKLD5Cd9G6CsERVA+8340vxi2iY8b9I9b3wRwb/PiUztrMXPNO5Bm+Kik2DyA +HyOTqJVih2OpL3TQj/TpzG0cls/ojgM/Mi8z3t51Q0f4NDkh4sy/9y7FTwhH0nUM +tGb6A7z/+trtsJZZWvtrVV/ltajfD5o4lPnI9Bg= +-----END CERTIFICATE----- diff --git a/certificates/ca.pem b/certificates/ca.pem new file mode 100644 index 0000000..bdf45cb --- /dev/null +++ b/certificates/ca.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +NFt57JmhEwYL9sgoy4sKuHPW2d3KSw== +-----END PRIVATE KEY----- diff --git a/certificates/ca.srl b/certificates/ca.srl new file mode 100644 index 0000000..a1e0936 --- /dev/null +++ b/certificates/ca.srl @@ -0,0 +1 @@ +09057958B65753B134D2510780AEB136F526780B diff --git a/certificates/cert.csr b/certificates/cert.csr new file mode 100644 index 0000000..d79d146 --- /dev/null +++ b/certificates/cert.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEnTCCAoUCAQAwWDESMBAGA1UEAwwJbG9jYWxob3N0MQswCQYDVQQGEwJMVTET +MBEGA1UECAwKTHV4ZW1ib3VyZzETMBEGA1UEBwwKTHV4ZW1ib3VyZzELMAkGA1UE +CgwCTkcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC3Fp/nNUvcLwns +KDcH5ZiVjGRReUkQ71ZaX8mRi2wFxejGxCXfKg2lMjVPZRDcZVrlZJm3G90q6TiW +EeWis5Z7XHezGKH6PNDeW1/sYSAUDZi866T97W4UH9/ZDm889gyrmcNZ6RS3WDjZ +Jta7VVs4CIRrfL6FVJg31/42eXpnyuoVV/Sj7npYwx3pk8VM7b/74AvIxfMeBC2Z +37IeDQJc9G7rw+Pda/Zu8DWNkMk7EDfF2x5eADbLQdn/qdEvo6cjc4+O6gMqjanB +5wSUMudWBFLDQ14i3SG015vvRsN+NL788mujcbHANVTWiGD40DZmkv+PuPq5lE6V +dWir2u6JlOfy6poC/LEZrFZQc1ce/RZzC5vWNOJJGo1dVTgmPVxjWuLcVwljby7h +RWPrc+zTtQB3cy1y1gO5/UVO4IOxpKrIxZHNMz1LyT6okylEvSxw0KT9G/Hzczay +IaXz4EuCkeA5a48Qnn6C3eD6F3lETDv2ihQG4JPjvUJRCQH+G+h5r8KWfQqSXzJg +yEhhTny5sq6tzCrVZXJGzoNTZSnH4VHp6zQAfj5BI6g/dlv7M1U+iX8z68kLYkUQ +8PGGq5ch+vKhoJ6IGJiEvjDoHZYs7Zhbc882qKALttdIzh7vRpjYyPct5VsJAybH +oXhodoxXD45Ovidsgh9MjdbhpNm9swIDAQABoAAwDQYJKoZIhvcNAQELBQADggIB +AHcwZtVp5oAuv7u3dtO3EV9+an+GQlX4pAXSJRXs6BdW8Ns6YegnslEgmy1MLr69 +qMjPtCxsuf7eWJ4EH+e8jHUk38pFLUl1yvwNvArSIULxYmhhPWTaaqG3VqpPyRVp +ale5Ch7jWWXMkx2iKjeL/JipN14hLEMVHfNikgahVTm0LUahJeCuBx30h1TQu/Wt ++Lh/v/luHT8LruQHMfi5KhueRFENGUuaTx3cEIVIUcf6Leor+/LFUgaOaYHBFmYO +pXXW7VJCn0zj1nmieGafn/zYBfbd0vaq3b8nXJ8RNbt6vFHa6RxBKud/hCo9vYzh +dP+QwRS5hh4q9CO27pMQyGN2uIQLuCojo16PYrlhBqHXURJmXSGd4T1ODsBMTODB +kD8mVtReooDLmBlv5xc3Q4sDO4Gi+Upzpu5/AtjZ241r6MIq1qDptWSAphgZnYem +adxxOZjNFC9URbytiD2LVF34M+oaPwC1lTu1BJaIGose4CyAEcZ9xs/8IOM8WZCF +Rv65Cd6KYWIJNAgvCeWXg8oG8Ftm/6MNXf1g6WhFHgCc6RwrnY9zd09o6bwNBTl+ +A7qCf0f0aXaEkugIFgyBI75lxqQkl1YVh1DC9m9IyjfV1CQ0bdRi+gJj3+B86/KY +0n/Um0SMnWAqwo3wbizmRpqiz+5RrbQoZqBi7ryuBB9m +-----END CERTIFICATE REQUEST----- diff --git a/certificates/cert.pem b/certificates/cert.pem new file mode 100644 index 0000000..f4f1f22 --- /dev/null +++ b/certificates/cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfDCCA2SgAwIBAgIUCQV5WLZXU7E00lEHgK6xNvUmeAswDQYJKoZIhvcNAQEL +BQAwVDEOMAwGA1UEAwwFTkcgQ0ExCzAJBgNVBAYTAkxVMRMwEQYDVQQIDApMdXhl +bWJvdXJnMRMwEQYDVQQHDApMdXhlbWJvdXJnMQswCQYDVQQKDAJORzAeFw0yNDAx +MjcwOTM4MzFaFw0zNDAxMjQwOTM4MzFaMFgxEjAQBgNVBAMMCWxvY2FsaG9zdDEL +MAkGA1UEBhMCTFUxEzARBgNVBAgMCkx1eGVtYm91cmcxEzARBgNVBAcMCkx1eGVt +Ym91cmcxCzAJBgNVBAoMAk5HMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEAtxaf5zVL3C8J7Cg3B+WYlYxkUXlJEO9WWl/JkYtsBcXoxsQl3yoNpTI1T2UQ +3GVa5WSZtxvdKuk4lhHlorOWe1x3sxih+jzQ3ltf7GEgFA2YvOuk/e1uFB/f2Q5v +PPYMq5nDWekUt1g42SbWu1VbOAiEa3y+hVSYN9f+Nnl6Z8rqFVf0o+56WMMd6ZPF +TO2/++ALyMXzHgQtmd+yHg0CXPRu68Pj3Wv2bvA1jZDJOxA3xdseXgA2y0HZ/6nR +L6OnI3OPjuoDKo2pwecElDLnVgRSw0NeIt0htNeb70bDfjS+/PJro3GxwDVU1ohg ++NA2ZpL/j7j6uZROlXVoq9ruiZTn8uqaAvyxGaxWUHNXHv0Wcwub1jTiSRqNXVU4 +Jj1cY1ri3FcJY28u4UVj63Ps07UAd3MtctYDuf1FTuCDsaSqyMWRzTM9S8k+qJMp +RL0scNCk/Rvx83M2siGl8+BLgpHgOWuPEJ5+gt3g+hd5REw79ooUBuCT471CUQkB +/hvoea/Cln0Kkl8yYMhIYU58ubKurcwq1WVyRs6DU2Upx+FR6es0AH4+QSOoP3Zb ++zNVPol/M+vJC2JFEPDxhquXIfryoaCeiBiYhL4w6B2WLO2YW3PPNqigC7bXSM4e +70aY2Mj3LeVbCQMmx6F4aHaMVw+OTr4nbIIfTI3W4aTZvbMCAwEAAaNCMEAwHQYD +VR0OBBYEFJdB7gRAzrhIVciQPTz5u2ixbNthMB8GA1UdIwQYMBaAFMdkgO9wZh7X +OZ769h6yUb+LOp5wMA0GCSqGSIb3DQEBCwUAA4ICAQAgiiS6BOCXaqyMAtSVczp0 +NiU1tQU8R6NLhKl9kgquFyjdzfb0kNniKjLARGlghy2aoFyHMWTaBN3wWQ8HXrj1 +MgY3whllbMEkTN6IplwBf5gQpICs6Ah3POlB/cNxs67rrnsCERGMa7LVXPRNVBqo +pyCpDd/p3WR5hXzXvp9nTiIe71t9BLKIc4hLpKl2OsvVHuFuEv+AM7gVEbrvIUyO +Ww2ur1r9ZmBLCIynJVLzd37YvuyxB5K22Pus8kUzsdCJe/K9SWLmClXJzMilvKJ1 +5co48Af6O63D+CMA2QKcb6rPLC4D/+0wbuW3CUJW4QWFjvX9w6ux/oSIEuiMcprH +Lnt1WIbSu8mKUIaMwwzLpKxmlTaypBBPX1G0LGO1NTvWDOZd1K0lD8kP/AtuOcNv +SWQpUEHlHfsC2aemAQPXNuLpqM59unw34J2k/O0vj/7QtbAV6aSlTo9h02Nk/HG3 +pmgGou3CndTe14754liAvcJvPv1GYXz6bh01Nnl2/Ac1W89Ffj87lzk542Y7zRjl +koUb8jPlMBO9kOcldrlWtNVubarTilq/5+ll+1/r1WQ84pnnZNJwRwTBNQsWsjq8 +G7GSC4HcM1KRhIuBAqGcyaLrZJUWbb8ei7t5650YQr8xAKJH1nbaZ66TLrB2PNHy +VpTzlkUCINNNm1YGYqLH3g== +-----END CERTIFICATE----- diff --git a/certificates/key.pem b/certificates/key.pem new file mode 100644 index 0000000..e9cab87 --- /dev/null +++ b/certificates/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +OEnScIDZFm2AqXrgt5XLk/BLbtXwznY= +-----END PRIVATE KEY----- diff --git a/composer.json b/composer.json index 40e2170..a45b5bf 100644 --- a/composer.json +++ b/composer.json @@ -7,11 +7,15 @@ "require": { "php": "^8.0", "ext-sockets": "*", - "ext-pmmpthread": "^6.0.1" + "ext-pmmpthread": "^6.0.1", + "nethergamesmc/quiche": "dev-master" }, "require-dev": { "phpstan/phpstan": "1.10.21" }, + "repositories": [ + { "type": "vcs", "url": "git@github.com:NetherGamesMC/PHP-Quiche.git" } + ], "autoload": { "psr-4": { "libproxy\\": "/"