Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace React\Dns\Query;
4
 
5
use React\Promise\Promise;
6
 
7
/**
8
 * Send DNS queries over a UDP or TCP/IP stream transport.
9
 *
10
 * This class will automatically choose the correct transport protocol to send
11
 * a DNS query to your DNS server. It will always try to send it over the more
12
 * efficient UDP transport first. If this query yields a size related issue
13
 * (truncated messages), it will retry over a streaming TCP/IP transport.
14
 *
15
 * For more advanced usages one can utilize this class directly.
16
 * The following example looks up the `IPv6` address for `reactphp.org`.
17
 *
18
 * ```php
19
 * $executor = new SelectiveTransportExecutor($udpExecutor, $tcpExecutor);
20
 *
21
 * $executor->query(
22
 *     new Query($name, Message::TYPE_AAAA, Message::CLASS_IN)
23
 * )->then(function (Message $message) {
24
 *     foreach ($message->answers as $answer) {
25
 *         echo 'IPv6: ' . $answer->data . PHP_EOL;
26
 *     }
27
 * }, 'printf');
28
 * ```
29
 *
30
 * Note that this executor only implements the logic to select the correct
31
 * transport for the given DNS query. Implementing the correct transport logic,
32
 * implementing timeouts and any retry logic is left up to the given executors,
33
 * see also [`UdpTransportExecutor`](#udptransportexecutor) and
34
 * [`TcpTransportExecutor`](#tcptransportexecutor) for more details.
35
 *
36
 * Note that this executor is entirely async and as such allows you to execute
37
 * any number of queries concurrently. You should probably limit the number of
38
 * concurrent queries in your application or you're very likely going to face
39
 * rate limitations and bans on the resolver end. For many common applications,
40
 * you may want to avoid sending the same query multiple times when the first
41
 * one is still pending, so you will likely want to use this in combination with
42
 * a `CoopExecutor` like this:
43
 *
44
 * ```php
45
 * $executor = new CoopExecutor(
46
 *     new SelectiveTransportExecutor(
47
 *         $datagramExecutor,
48
 *         $streamExecutor
49
 *     )
50
 * );
51
 * ```
52
 */
53
class SelectiveTransportExecutor implements ExecutorInterface
54
{
55
    private $datagramExecutor;
56
    private $streamExecutor;
57
 
58
    public function __construct(ExecutorInterface $datagramExecutor, ExecutorInterface $streamExecutor)
59
    {
60
        $this->datagramExecutor = $datagramExecutor;
61
        $this->streamExecutor = $streamExecutor;
62
    }
63
 
64
    public function query(Query $query)
65
    {
66
        $stream = $this->streamExecutor;
67
        $pending = $this->datagramExecutor->query($query);
68
 
69
        return new Promise(function ($resolve, $reject) use (&$pending, $stream, $query) {
70
            $pending->then(
71
                $resolve,
72
                function ($e) use (&$pending, $stream, $query, $resolve, $reject) {
73
                    if ($e->getCode() === (\defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90)) {
74
                        $pending = $stream->query($query)->then($resolve, $reject);
75
                    } else {
76
                        $reject($e);
77
                    }
78
                }
79
            );
80
        }, function () use (&$pending) {
81
            $pending->cancel();
82
            $pending = null;
83
        });
84
    }
85
}