2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file peerinfo/peerinfo_api_notify.c
23 * @brief notify API to access peerinfo service
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_peerinfo_service.h"
29 #include "gnunet_protocols.h"
32 #define LOG(kind, ...) GNUNET_log_from(kind, "peerinfo-api", __VA_ARGS__)
35 * Context for the info handler.
37 struct GNUNET_PEERINFO_NotifyContext {
39 * Our connection to the PEERINFO service.
41 struct GNUNET_MQ_Handle *mq;
44 * Function to call with information.
46 GNUNET_PEERINFO_Processor callback;
49 * Closure for @e callback.
56 const struct GNUNET_CONFIGURATION_Handle *cfg;
59 * Tasked used for delayed re-connection attempt.
61 struct GNUNET_SCHEDULER_Task *task;
64 * Include friend only HELLOs in callbacks
66 int include_friend_only;
71 * Task to re-try connecting to peerinfo.
73 * @param cls the `struct GNUNET_PEERINFO_NotifyContext *`
80 * We encountered an error, reconnect to the service.
82 * @param nc context to reconnect
85 do_reconnect(struct GNUNET_PEERINFO_NotifyContext *nc)
87 GNUNET_MQ_destroy(nc->mq);
89 nc->task = GNUNET_SCHEDULER_add_now(&reconnect,
95 * We got a disconnect after asking regex to do the announcement.
98 * @param cls the `struct GNUNET_PEERINFO_NotifyContext` to retry
99 * @param error error code
102 mq_error_handler(void *cls,
103 enum GNUNET_MQ_Error error)
105 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
112 * Check that a peerinfo information message is well-formed.
115 * @param im message received
116 * @return #GNUNET_OK if the message is well-formed
119 check_notification(void *cls,
120 const struct InfoMessage *im)
122 uint16_t ms = ntohs(im->header.size) - sizeof(*im);
124 if (ms >= sizeof(struct GNUNET_MessageHeader))
126 const struct GNUNET_HELLO_Message *hello;
128 hello = (const struct GNUNET_HELLO_Message *)&im[1];
129 if (ms != GNUNET_HELLO_size(hello))
132 return GNUNET_SYSERR;
139 return GNUNET_SYSERR;
141 return GNUNET_OK; /* odd... */
146 * Receive a peerinfo information message, process it.
149 * @param im message received
152 handle_notification(void *cls,
153 const struct InfoMessage *im)
155 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
156 const struct GNUNET_HELLO_Message *hello;
157 uint16_t ms = ntohs(im->header.size) - sizeof(struct InfoMessage);
161 hello = (const struct GNUNET_HELLO_Message *)&im[1];
162 LOG(GNUNET_ERROR_TYPE_DEBUG,
163 "Received information about peer `%s' from peerinfo database\n",
164 GNUNET_i2s(&im->peer));
165 nc->callback(nc->callback_cls,
173 * Type of a function to call when we receive a message from the
174 * service. Call the iterator with the result and (if applicable)
175 * continue to receive more messages or trigger processing the next
176 * event (if applicable).
179 * @param msg message received, NULL on timeout or fatal error
182 handle_end_iteration(void *cls,
183 const struct GNUNET_MessageHeader *msg)
185 /* these are ignored by the notify API */
190 * Task to re-try connecting to peerinfo.
192 * @param cls the `struct GNUNET_PEERINFO_NotifyContext *`
197 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
198 struct GNUNET_MQ_MessageHandler handlers[] = {
199 GNUNET_MQ_hd_var_size(notification,
200 GNUNET_MESSAGE_TYPE_PEERINFO_INFO,
203 GNUNET_MQ_hd_fixed_size(end_iteration,
204 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END,
205 struct GNUNET_MessageHeader,
207 GNUNET_MQ_handler_end()
209 struct GNUNET_MQ_Envelope *env;
210 struct NotifyMessage *nm;
213 nc->mq = GNUNET_CLIENT_connect(nc->cfg,
220 env = GNUNET_MQ_msg(nm,
221 GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY);
222 nm->include_friend_only = htonl(nc->include_friend_only);
223 GNUNET_MQ_send(nc->mq,
229 * Call a method whenever our known information about peers
230 * changes. Initially calls the given function for all known
231 * peers and then only signals changes.
233 * If @a include_friend_only is set to #GNUNET_YES peerinfo will include HELLO
234 * messages which are intended for friend to friend mode and which do not
235 * have to be gossiped. Otherwise these messages are skipped.
237 * @param cfg configuration to use
238 * @param include_friend_only include HELLO messages for friends only
239 * @param callback the method to call for each peer
240 * @param callback_cls closure for @a callback
241 * @return NULL on error
243 struct GNUNET_PEERINFO_NotifyContext *
244 GNUNET_PEERINFO_notify(const struct GNUNET_CONFIGURATION_Handle *cfg,
245 int include_friend_only,
246 GNUNET_PEERINFO_Processor callback,
249 struct GNUNET_PEERINFO_NotifyContext *nc;
251 nc = GNUNET_new(struct GNUNET_PEERINFO_NotifyContext);
253 nc->callback = callback;
254 nc->callback_cls = callback_cls;
255 nc->include_friend_only = include_friend_only;
259 LOG(GNUNET_ERROR_TYPE_WARNING,
260 "Could not connect to PEERINFO service.\n");
269 * Stop notifying about changes.
271 * @param nc context to stop notifying
274 GNUNET_PEERINFO_notify_cancel(struct GNUNET_PEERINFO_NotifyContext *nc)
278 GNUNET_MQ_destroy(nc->mq);
281 if (NULL != nc->task)
283 GNUNET_SCHEDULER_cancel(nc->task);
289 /* end of peerinfo_api_notify.c */