dns-over-https/lib/Internal/HttpsSocket.php

101 lines
3.6 KiB
PHP
Raw Normal View History

2019-06-10 19:32:28 +02:00
<?php
namespace Amp\DoH\Internal;
2019-06-12 13:48:57 +02:00
use Amp\DoH\DoHException;
2019-06-10 19:32:28 +02:00
use Amp\DoH\Nameserver;
2019-12-12 22:27:22 +01:00
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Request;
2019-06-10 19:32:28 +02:00
use Amp\Promise;
2019-06-18 12:54:24 +02:00
use danog\LibDNSJson\JsonDecoderFactory;
use danog\LibDNSJson\QueryEncoderFactory;
2019-06-10 19:32:28 +02:00
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
2019-06-11 20:07:46 +02:00
use function Amp\call;
2019-06-10 19:32:28 +02:00
/** @internal */
final class HttpsSocket extends Socket
{
2019-12-12 22:27:22 +01:00
/** @var \Amp\Http\HttpClient */
2019-06-10 19:32:28 +02:00
private $httpClient;
/** @var \Amp\DoH\Nameserver */
private $nameserver;
/** @var \LibDNS\Encoder\Encoder */
private $encoder;
/** @var \LibDNS\Decoder\Decoder */
private $decoder;
/** @var \Amp\Deferred */
private $responseDeferred;
2019-12-12 22:27:22 +01:00
public static function connect(DelegateHttpClient $httpClient, Nameserver $nameserver): Socket
2019-06-10 19:32:28 +02:00
{
2019-12-12 22:27:22 +01:00
return new self($httpClient, $nameserver);
2019-06-10 19:32:28 +02:00
}
2019-12-12 22:27:22 +01:00
protected function __construct(DelegateHttpClient $httpClient, Nameserver $nameserver)
2019-06-10 19:32:28 +02:00
{
2019-12-12 22:27:22 +01:00
$this->httpClient = $httpClient;
2019-06-10 19:32:28 +02:00
$this->nameserver = $nameserver;
if ($nameserver->getType() !== Nameserver::GOOGLE_JSON) {
$this->encoder = (new EncoderFactory)->create();
$this->decoder = (new DecoderFactory)->create();
} else {
2019-06-10 21:04:10 +02:00
$this->encoder = (new QueryEncoderFactory)->create();
$this->decoder = (new JsonDecoderFactory)->create();
2019-06-10 19:32:28 +02:00
}
parent::__construct();
}
2019-06-11 20:07:46 +02:00
2019-06-11 15:22:50 +02:00
protected function resolve(Message $message): Promise
2019-06-10 19:32:28 +02:00
{
$id = $message->getID();
switch ($this->nameserver->getType()) {
case Nameserver::RFC8484_GET:
2019-06-10 21:04:10 +02:00
$data = $this->encoder->encode($message);
2019-12-12 22:27:22 +01:00
$request = new Request($this->nameserver->getUri().'?'.\http_build_query(['dns' => \base64_encode($data), 'ct' => 'application/dns-message']), "GET");
$request->setHeader('accept', 'application/dns-message');
$request->setHeaders($this->nameserver->getHeaders());
2019-06-10 19:32:28 +02:00
break;
case Nameserver::RFC8484_POST:
2019-06-10 21:04:10 +02:00
$data = $this->encoder->encode($message);
2019-12-12 22:27:22 +01:00
$request = new Request($this->nameserver->getUri(), "POST");
$request->setBody($data);
$request->setHeader('content-type', 'application/dns-message');
$request->setHeader('accept', 'application/dns-message');
2019-12-13 00:18:38 +01:00
$request->setHeader('content-length', \strlen($data));
2019-12-12 22:27:22 +01:00
$request->setHeaders($this->nameserver->getHeaders());
2019-06-10 19:32:28 +02:00
break;
case Nameserver::GOOGLE_JSON:
2019-06-10 21:04:10 +02:00
$data = $this->encoder->encode($message);
2019-12-12 22:27:22 +01:00
$request = new Request($this->nameserver->getUri().'?'.$data, "GET");
$request->setHeader('accept', 'application/dns-json');
$request->setHeaders($this->nameserver->getHeaders());
2019-06-10 19:32:28 +02:00
break;
}
2019-06-11 15:22:50 +02:00
$response = $this->httpClient->request($request);
return call(function () use ($response, $id) {
$response = yield $response;
if ($response->getStatus() !== 200) {
2019-06-12 13:48:57 +02:00
throw new DoHException("HTTP result !== 200: ".$response->getStatus()." ".$response->getReason(), $response->getStatus());
}
2019-12-12 22:27:22 +01:00
$response = yield $response->getBody()->buffer();
2019-06-10 21:04:10 +02:00
2019-06-10 19:32:28 +02:00
switch ($this->nameserver->getType()) {
case Nameserver::RFC8484_GET:
case Nameserver::RFC8484_POST:
2019-06-11 15:22:50 +02:00
return $this->decoder->decode($response);
2019-06-10 19:32:28 +02:00
case Nameserver::GOOGLE_JSON:
2019-06-11 15:22:50 +02:00
return $this->decoder->decode($response, $id);
2019-06-10 19:32:28 +02:00
}
});
}
}