1
0
mirror of https://github.com/danog/tonProxy.git synced 2024-11-26 12:04:49 +01:00

First commit

This commit is contained in:
Daniil Gentili 2019-12-17 17:35:15 +01:00
commit 5f5ced71ff
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
3 changed files with 218 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
vendor
composer.lock

18
composer.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "danog/ton-proxy",
"description": "Websocket proxy for the TON blockchain ADNL protocol",
"minimum-stability": "dev",
"type": "project",
"require": {
"amphp/websocket-server": "dev-master as v2.0.0-rc1",
"amphp/http-server-static-content": "dev-master",
"amphp/http-server-router": "dev-master",
"amphp/log": "dev-master"
},
"authors": [
{
"name": "Daniil Gentili",
"email": "daniil@daniil.it"
}
]
}

197
main.php Normal file
View File

@ -0,0 +1,197 @@
<?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();
}
);