1 /*
2  *  Copyright (C) 2014-2019 Savoir-faire Linux Inc.
3  *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "infohash.h"
22 #include "log_enable.h"
23 
24 namespace dht {
25 
26 namespace net {
27     class DatagramSocket;
28 }
29 
30 class OPENDHT_PUBLIC DhtInterface {
31 public:
32     DhtInterface() = default;
DhtInterface(const Logger & l)33     DhtInterface(const Logger& l) : DHT_LOG(l) {};
34     virtual ~DhtInterface() = default;
35 
36     // [[deprecated]]
37     using Status = NodeStatus;
38     // [[deprecated]]
39     using NodeExport = dht::NodeExport;
40 
41     /**
42      * Get the current status of the node for the given family.
43      */
44     virtual NodeStatus getStatus(sa_family_t af) const = 0;
45     virtual NodeStatus getStatus() const = 0;
46 
getSocket()47     virtual net::DatagramSocket* getSocket() const { return {}; };
48 
49     /**
50      * Get the ID of the DHT node.
51      */
52     virtual const InfoHash& getNodeId() const = 0;
53 
54     /**
55      * Performs final operations before quitting.
56      */
57     virtual void shutdown(ShutdownCallback cb) = 0;
58 
59     /**
60      * Returns true if the node is running (have access to an open socket).
61      *
62      *  af: address family. If non-zero, will return true if the node
63      *     is running for the provided family.
64      */
65     virtual bool isRunning(sa_family_t af = 0) const = 0;
66 
67     virtual void registerType(const ValueType& type) = 0;
68 
69     virtual const ValueType& getType(ValueType::Id type_id) const = 0;
70 
71     /**
72      * Insert a node in the main routing table.
73      * The node is not pinged, so this should be
74      * used to bootstrap efficiently from previously known nodes.
75      */
76     virtual void insertNode(const InfoHash& id, const SockAddr&) = 0;
77     virtual void insertNode(const NodeExport& n) = 0;
78 
79     virtual void pingNode(SockAddr, DoneCallbackSimple&& cb={}) = 0;
80 
81     virtual time_point periodic(const uint8_t *buf, size_t buflen, SockAddr) = 0;
82     virtual time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) = 0;
83 
84     /**
85      * Get a value by searching on all available protocols (IPv4, IPv6),
86      * and call the provided get callback when values are found at key.
87      * The operation will start as soon as the node is connected to the network.
88      * @param cb a function called when new values are found on the network.
89      *         It should return false to stop the operation.
90      * @param donecb a function called when the operation is complete.
91                   cb and donecb won't be called again afterward.
92      * @param f a filter function used to prefilter values.
93      */
94     virtual void get(const InfoHash& key, GetCallback cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) = 0;
95     virtual void get(const InfoHash& key, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f={}, Where&& w = {}) = 0;
96     virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) = 0;
97     virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) = 0;
98 
99     /**
100       * Similar to Dht::get, but sends a Query to filter data remotely.
101       * @param key the key for which to query data for.
102       * @param cb a function called when new values are found on the network.
103       *         It should return false to stop the operation.
104       * @param done_cb a function called when the operation is complete.
105                       cb and done_cb won't be called again afterward.
106       * @param q a query used to filter values on the remotes before they send a
107       *        response.
108       */
109     virtual void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) = 0;
110     virtual void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) = 0;
111 
112     /**
113      * Get locally stored data for the given hash.
114      */
115     virtual std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const = 0;
116 
117     /**
118      * Get locally stored data for the given key and value id.
119      */
120     virtual Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const = 0;
121 
122     /**
123      * Announce a value on all available protocols (IPv4, IPv6).
124      *
125      * The operation will start as soon as the node is connected to the network.
126      * The done callback will be called once, when the first announce succeeds, or fails.
127      */
128     virtual void put(const InfoHash& key,
129            Sp<Value>,
130            DoneCallback cb=nullptr,
131            time_point created=time_point::max(),
132            bool permanent = false) = 0;
133     virtual void put(const InfoHash& key,
134            const Sp<Value>& v,
135            DoneCallbackSimple cb,
136            time_point created=time_point::max(),
137            bool permanent = false) = 0;
138     virtual void put(const InfoHash& key,
139            Value&& v,
140            DoneCallback cb=nullptr,
141            time_point created=time_point::max(),
142            bool permanent = false) = 0;
143     virtual void put(const InfoHash& key,
144            Value&& v,
145            DoneCallbackSimple cb,
146            time_point created=time_point::max(),
147            bool permanent = false) = 0;
148 
149     /**
150      * Get data currently being put at the given hash.
151      */
152     virtual std::vector<Sp<Value>> getPut(const InfoHash&) const = 0;
153 
154     /**
155      * Get data currently being put at the given hash with the given id.
156      */
157     virtual Sp<Value> getPut(const InfoHash&, const Value::Id&) const = 0;
158 
159     /**
160      * Stop any put/announce operation at the given location,
161      * for the value with the given id.
162      */
163     virtual bool cancelPut(const InfoHash&, const Value::Id&) = 0;
164 
165     /**
166      * Listen on the network for any changes involving a specified hash.
167      * The node will register to receive updates from relevent nodes when
168      * new values are added or removed.
169      *
170      * @return a token to cancel the listener later.
171      */
172     virtual size_t listen(const InfoHash&, GetCallback, Value::Filter={}, Where w = {}) = 0;
173     virtual size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) = 0;
174     virtual size_t listen(const InfoHash&, ValueCallback, Value::Filter={}, Where w = {}) = 0;
175 
176     virtual bool cancelListen(const InfoHash&, size_t token) = 0;
177 
178     /**
179      * Inform the DHT of lower-layer connectivity changes.
180      * This will cause the DHT to assume a public IP address change.
181      * The DHT will recontact neighbor nodes, re-register for listen ops etc.
182      */
183     virtual void connectivityChanged(sa_family_t) = 0;
184     virtual void connectivityChanged() = 0;
185 
186     /**
187      * Get the list of good nodes for local storage saving purposes
188      * The list is ordered to minimize the back-to-work delay.
189      */
190     virtual std::vector<NodeExport> exportNodes() const = 0;
191 
192     virtual std::vector<ValuesExport> exportValues() const = 0;
193     virtual void importValues(const std::vector<ValuesExport>&) = 0;
194 
195     virtual NodeStats getNodesStats(sa_family_t af) const = 0;
196 
197     virtual std::string getStorageLog() const = 0;
198     virtual std::string getStorageLog(const InfoHash&) const = 0;
199 
200     virtual std::string getRoutingTablesLog(sa_family_t) const = 0;
201     virtual std::string getSearchesLog(sa_family_t) const = 0;
202     virtual std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const = 0;
203 
204     virtual void dumpTables() const = 0;
205     virtual std::vector<unsigned> getNodeMessageStats(bool in = false) = 0;
206 
207     /**
208      * Set the in-memory storage limit in bytes
209      */
210     virtual void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) = 0;
211 
212     /**
213      * Returns the total memory usage of stored values and the number
214      * of stored values.
215      */
216     virtual std::pair<size_t, size_t> getStoreSize() const = 0;
217 
218     virtual std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) = 0;
219 
220     /**
221      * Enable or disable logging of DHT internal messages
222      */
223     virtual void setLoggers(LogMethod error = {}, LogMethod warn = {}, LogMethod debug = {}) {
224         DHT_LOG.DBG = debug;
225         DHT_LOG.WARN = warn;
226         DHT_LOG.ERR = error;
227     }
228 
setLogger(const Logger & l)229     virtual void setLogger(const Logger& l) {
230         DHT_LOG.DBG = l.DBG;
231         DHT_LOG.WARN = l.WARN;
232         DHT_LOG.ERR = l.ERR;
233     }
234 
235     /**
236      * Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
237      */
setLogFilter(const InfoHash & f)238     virtual void setLogFilter(const InfoHash& f)
239     {
240         DHT_LOG.setFilter(f);
241     }
242 
setPushNotificationToken(const std::string &)243     virtual void setPushNotificationToken(const std::string&) {};
244 
245     /**
246      * Call linked callback with a push notification
247      * @param notification to process
248      */
249     virtual void pushNotificationReceived(const std::map<std::string, std::string>& data) = 0;
250 
251 protected:
252     Logger DHT_LOG;
253 };
254 
255 } // namespace dht
256