1
0
mirror of https://github.com/danog/tonProxy.git synced 2024-11-30 04:29:11 +01:00
tonProxy/main.php

198 lines
5.2 KiB
PHP
Raw Normal View History

2019-12-17 17:35:15 +01:00
<?php
use Amp\Http\Server\HttpServer;
use Amp\Http\Server\Request;
use Amp\Http\Server\RequestHandler\CallableRequestHandler;
use Amp\Http\Server\Response;
use Amp\Http\Server\Router;
use Amp\Http\Status;
use Amp\Log\ConsoleFormatter;
use Amp\Log\StreamHandler;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket;
use Amp\Socket\Socket as SocketSocket;
use Amp\Success;
use Amp\Websocket\Client;
use Amp\Websocket\Message;
use Amp\Websocket\Server\ClientHandler;
use Amp\Websocket\Server\Websocket;
use Monolog\Logger;
use function Amp\ByteStream\getStdout;
use function Amp\call;
use function Amp\Socket\connect;
require __DIR__.'/vendor/autoload.php';
$ip = '127.0.0.1'; // Connect to local TON validator
$ip = 'ton.daniil.it';
$port = 9999;
$logHandler = new StreamHandler(getStdout());
$logHandler->setFormatter(new ConsoleFormatter);
$logger = new Logger('server');
$logger->pushHandler($logHandler);
$websocket = new Websocket(new class($ip, $port, $logger) implements ClientHandler {
/**
* TON validator URI.
*
* @var string
*/
private $validatorUri;
/**
* Logger.
*
* @var Logger
*/
private $logger;
/**
* Constructor.
*
* @param string $ip Validator IP
* @param integer $port Validator port
* @param Logger $logger Logger
*/
public function __construct(string $ip, int $port, Logger $logger)
{
$this->validatorUri = "tcp://$ip:$port";
$this->logger = $logger;
}
/**
* Called when the HTTP server is started.
*
* @param Websocket $endpoint
*
* @return Promise
*/
public function onStart(Websocket $endpoint): Promise
{
$this->logger->notice("Started WS server!");
return new Success();
}
/**
* Called when the HTTP server is stopped.
*
* @param Websocket $endpoint
*
* @return Promise
*/
public function onStop(Websocket $endpoint): Promise
{
$this->logger->notice("Stopped WS server!");
return new Success();
}
/**
* Accept all incoming connections.
*
* @param \Amp\Http\Server\Request $request
* @param \Amp\Http\Server\Response $response
*
* @return \Amp\Promise
*/
public function handleHandshake(\Amp\Http\Server\Request $request, \Amp\Http\Server\Response $response): \Amp\Promise
{
return new Success($response);
}
/**
* Handle client.
*
* @param Client $client Websocket client
* @param Request $request HTTP request
* @param Response $response HTTP response
*
* @return Promise
*/
public function handleClient(Client $client, Request $request, Response $response): Promise
{
return call([$this, 'handleClientGenerator'], $client);
}
/**
* Handle client.
*
* @param Client $client Websocket client
* @param Request $request HTTP request
* @param Response $response HTTP response
*
* @return Promise
*/
public function handleClientGenerator(Client $client): \Generator
{
$socket = yield connect($this->validatorUri);
try {
yield [
call([$this, 'readLoop'], $client, $socket),
call([$this, 'writeLoop'], $client, $socket),
];
} catch (\Throwable $e) {
$this->logger->alert("Got exception in loops: $e");
} finally {
try {
$socket->close();
} catch (\Throwable $e) {
}
try {
$client->close();
} catch (\Throwable $e) {
}
}
}
public function readLoop(Client $client, SocketSocket $socket): \Generator
{
try {
$this->logger->warning("Entered read loop");
while ($message = yield $client->receive()) {
if (!$message instanceof Message) {
throw new \Exception('Connection closed!');
}
yield $socket->write(yield $message->buffer());
}
} finally {
$this->logger->warning("Exited read loop");
$client->close();
$socket->close();
}
}
public function writeLoop(Client $client, SocketSocket $socket): \Generator
{
try {
$this->logger->warning("Entered write loop");
while (($message = yield $socket->read()) !== null) {
yield $client->sendBinary($message);
}
} finally {
$this->logger->warning("Exited write loop");
$client->close();
$socket->close();
}
}
});
$sockets = [
Socket\listen('127.0.0.1:80'),
Socket\listen('[::1]:80'),
];
$router = new Router;
$router->addRoute('GET', '/ton', $websocket);
$router->setFallback(
new CallableRequestHandler(
function () {
return new Response(Status::FOUND, ['location' => 'https://ton.madelineproto.xyz'], 'Redirecting you to <a href="https://ton.madelineproto.xyz">https://ton.madelineproto.xyz</a>...');
}
)
);
$server = new HttpServer($sockets, $router, $logger);
Loop::run(
function () use ($server) {
yield $server->start();
}
);