1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2017 Nathan Osman
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #ifndef QMDNSENGINE_CACHE_H
26 #define QMDNSENGINE_CACHE_H
27 
28 #include <QList>
29 #include <QObject>
30 
31 #include "qmdnsengine_export.h"
32 
33 namespace QMdnsEngine
34 {
35 
36 class Record;
37 
38 class QMDNSENGINE_EXPORT CachePrivate;
39 
40 /**
41  * @brief %Cache for DNS records
42  *
43  * Records are added to the cache using the addRecord() method which are then
44  * stored in the cache until they are considered to have expired, at which
45  * point they are purged. The shouldQuery() signal is used to indicate when a
46  * record is approaching expiry and the recordExpired() signal indicates when
47  * a record has expired (at which point it is removed).
48  *
49  * The cache can be queried to retrieve one or more records matching a given
50  * type. For example, to retrieve all TXT records that match a given name:
51  *
52  * @code
53  * Cache cache;
54  *
55  * QList<QMdnsEngine::Record> records;
56  * cache.lookupRecords("My Service._http._tcp.local.", QMdnsEngine::TXT, records);
57  *
58  * foreach (QMdnsEngine::Record record, records) {
59  *     qDebug() << "Record:" << record.name();
60  * }
61  * @endcode
62  *
63  * Alternatively, lookupRecord() can be used to find a single record.
64  */
65 class QMDNSENGINE_EXPORT Cache : public QObject
66 {
67     Q_OBJECT
68 
69 public:
70 
71     /**
72      * @brief Create an empty cache.
73      */
74     explicit Cache(QObject *parent = 0);
75 
76     /**
77      * @brief Add a record to the cache
78      * @param record add this record to the cache
79      *
80      * The TTL for the record will be added to the current time to calculate
81      * when the record expires. Existing records of the same name and type
82      * will be replaced, resetting their expiration.
83      */
84     void addRecord(const Record &record);
85 
86     /**
87      * @brief Retrieve a single record from the cache
88      * @param name name of record to retrieve or null for any
89      * @param type type of record to retrieve or ANY for all types
90      * @param record storage for the record retrieved
91      * @return true if a record was retrieved
92      *
93      * Some record types allow multiple records to be stored with identical
94      * names and types. This method will only retrieve the first matching
95      * record. Use lookupRecords() to obtain all of the records.
96      */
97     bool lookupRecord(const QByteArray &name, quint16 type, Record &record) const;
98 
99     /**
100      * @brief Retrieve multiple records from the cache
101      * @param name name of records to retrieve or null for any
102      * @param type type of records to retrieve or ANY for all types
103      * @param records storage for the records retrieved
104      * @return true if records were retrieved
105      */
106     bool lookupRecords(const QByteArray &name, quint16 type, QList<Record> &records) const;
107 
108 Q_SIGNALS:
109 
110     /**
111      * @brief Indicate that a record will expire soon and a new query should be issued
112      * @param record reference to the record that will soon expire
113      *
114      * This signal is emitted when a record reaches approximately 50%, 85%,
115      * 90%, and 95% of its lifetime.
116      */
117     void shouldQuery(const Record &record);
118 
119     /**
120      * @brief Indicate that the specified record expired
121      * @param record reference to the record that has expired
122      */
123     void recordExpired(const Record &record);
124 
125 private:
126 
127     CachePrivate *const d;
128 };
129 
130 }
131 
132 #endif // QMDNSENGINE_CACHE_H
133