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\Cache\CacheInterface;
6
use React\Dns\Model\Message;
7
use React\Promise\Promise;
8
 
9
final class CachingExecutor implements ExecutorInterface
10
{
11
    /**
12
     * Default TTL for negative responses (NXDOMAIN etc.).
13
     *
14
     * @internal
15
     */
16
    const TTL = 60;
17
 
18
    private $executor;
19
    private $cache;
20
 
21
    public function __construct(ExecutorInterface $executor, CacheInterface $cache)
22
    {
23
        $this->executor = $executor;
24
        $this->cache = $cache;
25
    }
26
 
27
    public function query(Query $query)
28
    {
29
        $id = $query->name . ':' . $query->type . ':' . $query->class;
30
        $cache = $this->cache;
31
        $that = $this;
32
        $executor = $this->executor;
33
 
34
        $pending = $cache->get($id);
35
        return new Promise(function ($resolve, $reject) use ($query, $id, $cache, $executor, &$pending, $that) {
36
            $pending->then(
37
                function ($message) use ($query, $id, $cache, $executor, &$pending, $that) {
38
                    // return cached response message on cache hit
39
                    if ($message !== null) {
40
                        return $message;
41
                    }
42
 
43
                    // perform DNS lookup if not already cached
44
                    return $pending = $executor->query($query)->then(
45
                        function (Message $message) use ($cache, $id, $that) {
46
                            // DNS response message received => store in cache when not truncated and return
47
                            if (!$message->tc) {
48
                                $cache->set($id, $message, $that->ttl($message));
49
                            }
50
 
51
                            return $message;
52
                        }
53
                    );
54
                }
55
            )->then($resolve, function ($e) use ($reject, &$pending) {
56
                $reject($e);
57
                $pending = null;
58
            });
59
        }, function ($_, $reject) use (&$pending, $query) {
60
            $reject(new \RuntimeException('DNS query for ' . $query->name . ' has been cancelled'));
61
            $pending->cancel();
62
            $pending = null;
63
        });
64
    }
65
 
66
    /**
67
     * @param Message $message
68
     * @return int
69
     * @internal
70
     */
71
    public function ttl(Message $message)
72
    {
73
        // select TTL from answers (should all be the same), use smallest value if available
74
        // @link https://tools.ietf.org/html/rfc2181#section-5.2
75
        $ttl = null;
76
        foreach ($message->answers as $answer) {
77
            if ($ttl === null || $answer->ttl < $ttl) {
78
                $ttl = $answer->ttl;
79
            }
80
        }
81
 
82
        if ($ttl === null) {
83
            $ttl = self::TTL;
84
        }
85
 
86
        return $ttl;
87
    }
88
}