diff options
Diffstat (limited to 'src/namestore/namestore_api_monitor.c')
-rw-r--r-- | src/namestore/namestore_api_monitor.c | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c deleted file mode 100644 index 6670e54ce..000000000 --- a/src/namestore/namestore_api_monitor.c +++ /dev/null | |||
@@ -1,388 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2016, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/namestore_api_monitor.c | ||
22 | * @brief API to monitor changes in the NAMESTORE | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_crypto_lib.h" | ||
29 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_dnsparser_lib.h" | ||
31 | #include "gnunet_arm_service.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | #include "gnunet_namestore_service.h" | ||
34 | #include "namestore.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Handle for a monitoring activity. | ||
39 | */ | ||
40 | struct GNUNET_NAMESTORE_ZoneMonitor | ||
41 | { | ||
42 | /** | ||
43 | * Configuration (to reconnect). | ||
44 | */ | ||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
46 | |||
47 | /** | ||
48 | * Handle to namestore service. | ||
49 | */ | ||
50 | struct GNUNET_MQ_Handle *mq; | ||
51 | |||
52 | /** | ||
53 | * Function to call on errors. | ||
54 | */ | ||
55 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
56 | |||
57 | /** | ||
58 | * Closure for @e error_cb. | ||
59 | */ | ||
60 | void *error_cb_cls; | ||
61 | |||
62 | /** | ||
63 | * Function to call on events. | ||
64 | */ | ||
65 | GNUNET_NAMESTORE_RecordMonitor monitor; | ||
66 | |||
67 | /** | ||
68 | * Closure for @e monitor. | ||
69 | */ | ||
70 | void *monitor_cls; | ||
71 | |||
72 | /** | ||
73 | * Function called when we've synchronized. | ||
74 | */ | ||
75 | GNUNET_SCHEDULER_TaskCallback sync_cb; | ||
76 | |||
77 | /** | ||
78 | * Closure for @e sync_cb. | ||
79 | */ | ||
80 | void *sync_cb_cls; | ||
81 | |||
82 | /** | ||
83 | * Monitored zone. | ||
84 | */ | ||
85 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
86 | |||
87 | /** | ||
88 | * Do we first iterate over all existing records? | ||
89 | */ | ||
90 | int iterate_first; | ||
91 | }; | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Reconnect to the namestore service. | ||
96 | * | ||
97 | * @param zm monitor to reconnect | ||
98 | */ | ||
99 | static void | ||
100 | reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Handle SYNC message from the namestore service. | ||
105 | * | ||
106 | * @param cls the monitor | ||
107 | * @param msg the sync message | ||
108 | */ | ||
109 | static void | ||
110 | handle_sync (void *cls, const struct GNUNET_MessageHeader *msg) | ||
111 | { | ||
112 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
113 | |||
114 | (void) cls; | ||
115 | (void) msg; | ||
116 | if (NULL != zm->sync_cb) | ||
117 | zm->sync_cb (zm->sync_cb_cls); | ||
118 | } | ||
119 | |||
120 | |||
121 | /** | ||
122 | * We've received a notification about a change to our zone. | ||
123 | * Check that it is well-formed. | ||
124 | * | ||
125 | * @param cls the zone monitor handle | ||
126 | * @param lrm the message from the service. | ||
127 | */ | ||
128 | static int | ||
129 | check_result (void *cls, const struct RecordResultMessage *lrm) | ||
130 | { | ||
131 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
132 | size_t lrm_len; | ||
133 | size_t exp_lrm_len; | ||
134 | size_t name_len; | ||
135 | size_t rd_len; | ||
136 | unsigned rd_count; | ||
137 | const char *name_tmp; | ||
138 | const char *rd_ser_tmp; | ||
139 | |||
140 | (void) cls; | ||
141 | if ((0 != GNUNET_memcmp (&lrm->private_key, &zm->zone)) && | ||
142 | (GNUNET_NO == GNUNET_is_zero (&zm->zone))) | ||
143 | { | ||
144 | GNUNET_break (0); | ||
145 | return GNUNET_SYSERR; | ||
146 | } | ||
147 | lrm_len = ntohs (lrm->gns_header.header.size); | ||
148 | rd_len = ntohs (lrm->rd_len); | ||
149 | rd_count = ntohs (lrm->rd_count); | ||
150 | name_len = ntohs (lrm->name_len); | ||
151 | if (name_len > MAX_NAME_LEN) | ||
152 | { | ||
153 | GNUNET_break (0); | ||
154 | return GNUNET_SYSERR; | ||
155 | } | ||
156 | exp_lrm_len = sizeof(struct RecordResultMessage) + name_len + rd_len; | ||
157 | if (lrm_len != exp_lrm_len) | ||
158 | { | ||
159 | GNUNET_break (0); | ||
160 | return GNUNET_SYSERR; | ||
161 | } | ||
162 | if (0 == name_len) | ||
163 | { | ||
164 | GNUNET_break (0); | ||
165 | return GNUNET_SYSERR; | ||
166 | } | ||
167 | name_tmp = (const char *) &lrm[1]; | ||
168 | if (name_tmp[name_len - 1] != '\0') | ||
169 | { | ||
170 | GNUNET_break (0); | ||
171 | return GNUNET_SYSERR; | ||
172 | } | ||
173 | rd_ser_tmp = (const char *) &name_tmp[name_len]; | ||
174 | { | ||
175 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
176 | |||
177 | if (GNUNET_OK != | ||
178 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)) | ||
179 | { | ||
180 | GNUNET_break (0); | ||
181 | return GNUNET_SYSERR; | ||
182 | } | ||
183 | } | ||
184 | return GNUNET_OK; | ||
185 | } | ||
186 | |||
187 | |||
188 | /** | ||
189 | * We've received a notification about a change to our zone. | ||
190 | * Forward to monitor callback. | ||
191 | * | ||
192 | * @param cls the zone monitor handle | ||
193 | * @param lrm the message from the service. | ||
194 | */ | ||
195 | static void | ||
196 | handle_result (void *cls, const struct RecordResultMessage *lrm) | ||
197 | { | ||
198 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
199 | size_t name_len; | ||
200 | size_t rd_len; | ||
201 | unsigned rd_count; | ||
202 | const char *name_tmp; | ||
203 | const char *rd_ser_tmp; | ||
204 | |||
205 | rd_len = ntohs (lrm->rd_len); | ||
206 | rd_count = ntohs (lrm->rd_count); | ||
207 | name_len = ntohs (lrm->name_len); | ||
208 | name_tmp = (const char *) &lrm[1]; | ||
209 | rd_ser_tmp = (const char *) &name_tmp[name_len]; | ||
210 | { | ||
211 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
212 | |||
213 | GNUNET_assert ( | ||
214 | GNUNET_OK == | ||
215 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)); | ||
216 | zm->monitor (zm->monitor_cls, &lrm->private_key, name_tmp, rd_count, rd); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Generic error handler, called with the appropriate error code and | ||
223 | * the same closure specified at the creation of the message queue. | ||
224 | * Not every message queue implementation supports an error handler. | ||
225 | * | ||
226 | * @param cls closure with the `struct GNUNET_NAMESTORE_ZoneMonitor *` | ||
227 | * @param error error code | ||
228 | */ | ||
229 | static void | ||
230 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
231 | { | ||
232 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
233 | |||
234 | (void) error; | ||
235 | reconnect (zm); | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Reconnect to the namestore service. | ||
241 | * | ||
242 | * @param zm monitor to reconnect | ||
243 | */ | ||
244 | static void | ||
245 | reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | ||
246 | { | ||
247 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
248 | { GNUNET_MQ_hd_fixed_size (sync, | ||
249 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC, | ||
250 | struct GNUNET_MessageHeader, | ||
251 | zm), | ||
252 | GNUNET_MQ_hd_var_size (result, | ||
253 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, | ||
254 | struct RecordResultMessage, | ||
255 | zm), | ||
256 | GNUNET_MQ_handler_end () }; | ||
257 | struct GNUNET_MQ_Envelope *env; | ||
258 | struct ZoneMonitorStartMessage *sm; | ||
259 | |||
260 | if (NULL != zm->mq) | ||
261 | { | ||
262 | GNUNET_MQ_destroy (zm->mq); | ||
263 | zm->error_cb (zm->error_cb_cls); | ||
264 | } | ||
265 | zm->mq = GNUNET_CLIENT_connect (zm->cfg, | ||
266 | "namestore", | ||
267 | handlers, | ||
268 | &mq_error_handler, | ||
269 | zm); | ||
270 | if (NULL == zm->mq) | ||
271 | return; | ||
272 | env = GNUNET_MQ_msg (sm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START); | ||
273 | sm->iterate_first = htonl (zm->iterate_first); | ||
274 | sm->zone = zm->zone; | ||
275 | GNUNET_MQ_send (zm->mq, env); | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Begin monitoring a zone for changes. If @a iterate_first is set, | ||
281 | * we Will first call the @a monitor function on all existing records | ||
282 | * in the selected zone(s). In any case, we will call @a sync and | ||
283 | * afterwards call @a monitor whenever a record changes. | ||
284 | * | ||
285 | * @param cfg configuration to use to connect to namestore | ||
286 | * @param zone zone to monitor | ||
287 | * @param iterate_first #GNUNET_YES to first iterate over all existing records, | ||
288 | * #GNUNET_NO to only return changes that happen from now | ||
289 | * on | ||
290 | * @param error_cb function to call on error (i.e. disconnect); note that | ||
291 | * unlike the other error callbacks in this API, a call to this | ||
292 | * function does NOT destroy the monitor handle, it merely signals | ||
293 | * that monitoring is down. You need to still explicitly call | ||
294 | * #GNUNET_NAMESTORE_zone_monitor_stop(). | ||
295 | * @param error_cb_cls closure for @a error_cb | ||
296 | * @param monitor function to call on zone changes | ||
297 | * @param monitor_cls closure for @a monitor | ||
298 | * @param sync_cb function called when we're in sync with the namestore | ||
299 | * @param cls closure for @a sync_cb | ||
300 | * @return handle to stop monitoring | ||
301 | */ | ||
302 | struct GNUNET_NAMESTORE_ZoneMonitor * | ||
303 | GNUNET_NAMESTORE_zone_monitor_start ( | ||
304 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
305 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
306 | int iterate_first, | ||
307 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
308 | void *error_cb_cls, | ||
309 | GNUNET_NAMESTORE_RecordMonitor monitor, | ||
310 | void *monitor_cls, | ||
311 | GNUNET_SCHEDULER_TaskCallback sync_cb, | ||
312 | void *sync_cb_cls) | ||
313 | { | ||
314 | struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
315 | |||
316 | zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor); | ||
317 | if (NULL != zone) | ||
318 | zm->zone = *zone; | ||
319 | zm->iterate_first = iterate_first; | ||
320 | zm->error_cb = error_cb; | ||
321 | zm->error_cb_cls = error_cb_cls; | ||
322 | zm->monitor = monitor; | ||
323 | zm->monitor_cls = monitor_cls; | ||
324 | zm->sync_cb = sync_cb; | ||
325 | zm->sync_cb_cls = sync_cb_cls; | ||
326 | zm->cfg = cfg; | ||
327 | reconnect (zm); | ||
328 | if (NULL == zm->mq) | ||
329 | { | ||
330 | GNUNET_free (zm); | ||
331 | return NULL; | ||
332 | } | ||
333 | return zm; | ||
334 | } | ||
335 | |||
336 | |||
337 | /** | ||
338 | * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start | ||
339 | * for the next record(s). This function is used to allow clients that merely | ||
340 | * monitor the NAMESTORE to still throttle namestore operations, so we can be | ||
341 | * sure that the monitors can keep up. | ||
342 | * | ||
343 | * Note that #GNUNET_NAMESTORE_records_store() only waits for this | ||
344 | * call if the previous limit set by the client was already reached. | ||
345 | * Thus, by using a @a limit greater than 1, monitors basically enable | ||
346 | * a queue of notifications to be processed asynchronously with some | ||
347 | * delay. Note that even with a limit of 1 the | ||
348 | * #GNUNET_NAMESTORE_records_store() function will run asynchronously | ||
349 | * and the continuation may be invoked before the monitors completed | ||
350 | * (or even started) processing the notification. Thus, monitors will | ||
351 | * only closely track the current state of the namestore, but not | ||
352 | * be involved in the transactions. | ||
353 | * | ||
354 | * @param zm the monitor | ||
355 | * @param limit number of records to return to the iterator in one shot | ||
356 | * (before #GNUNET_NAMESTORE_zone_monitor_next is to be called again) | ||
357 | */ | ||
358 | void | ||
359 | GNUNET_NAMESTORE_zone_monitor_next (struct GNUNET_NAMESTORE_ZoneMonitor *zm, | ||
360 | uint64_t limit) | ||
361 | { | ||
362 | struct GNUNET_MQ_Envelope *env; | ||
363 | struct ZoneMonitorNextMessage *nm; | ||
364 | |||
365 | env = GNUNET_MQ_msg (nm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT); | ||
366 | nm->limit = GNUNET_htonll (limit); | ||
367 | GNUNET_MQ_send (zm->mq, env); | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Stop monitoring a zone for changes. | ||
373 | * | ||
374 | * @param zm handle to the monitor activity to stop | ||
375 | */ | ||
376 | void | ||
377 | GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | ||
378 | { | ||
379 | if (NULL != zm->mq) | ||
380 | { | ||
381 | GNUNET_MQ_destroy (zm->mq); | ||
382 | zm->mq = NULL; | ||
383 | } | ||
384 | GNUNET_free (zm); | ||
385 | } | ||
386 | |||
387 | |||
388 | /* end of namestore_api_monitor.c */ | ||