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 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.
17 * @file peerinfo/peerinfo_api_notify.c
18 * @brief notify API to access peerinfo service
19 * @author Christian Grothoff
22 #include "gnunet_util_lib.h"
23 #include "gnunet_peerinfo_service.h"
24 #include "gnunet_protocols.h"
27 #define LOG(kind,...) GNUNET_log_from (kind, "peerinfo-api",__VA_ARGS__)
30 * Context for the info handler.
32 struct GNUNET_PEERINFO_NotifyContext
36 * Our connection to the PEERINFO service.
38 struct GNUNET_MQ_Handle *mq;
41 * Function to call with information.
43 GNUNET_PEERINFO_Processor callback;
46 * Closure for @e callback.
53 const struct GNUNET_CONFIGURATION_Handle *cfg;
56 * Tasked used for delayed re-connection attempt.
58 struct GNUNET_SCHEDULER_Task *task;
61 * Include friend only HELLOs in callbacks
63 int include_friend_only;
68 * Task to re-try connecting to peerinfo.
70 * @param cls the `struct GNUNET_PEERINFO_NotifyContext *`
73 reconnect (void *cls);
77 * We encountered an error, reconnect to the service.
79 * @param nc context to reconnect
82 do_reconnect (struct GNUNET_PEERINFO_NotifyContext *nc)
84 GNUNET_MQ_destroy (nc->mq);
86 nc->task = GNUNET_SCHEDULER_add_now (&reconnect,
92 * We got a disconnect after asking regex to do the announcement.
95 * @param cls the `struct GNUNET_PEERINFO_NotifyContext` to retry
96 * @param error error code
99 mq_error_handler (void *cls,
100 enum GNUNET_MQ_Error error)
102 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
109 * Check that a peerinfo information message is well-formed.
112 * @param im message received
113 * @return #GNUNET_OK if the message is well-formed
116 check_notification (void *cls,
117 const struct InfoMessage *im)
119 uint16_t ms = ntohs (im->header.size) - sizeof (*im);
121 if (ms >= sizeof (struct GNUNET_MessageHeader))
123 const struct GNUNET_HELLO_Message *hello;
125 hello = (const struct GNUNET_HELLO_Message *) &im[1];
126 if (ms != GNUNET_HELLO_size (hello))
129 return GNUNET_SYSERR;
136 return GNUNET_SYSERR;
138 return GNUNET_OK; /* odd... */
143 * Receive a peerinfo information message, process it.
146 * @param im message received
149 handle_notification (void *cls,
150 const struct InfoMessage *im)
152 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
153 const struct GNUNET_HELLO_Message *hello;
154 uint16_t ms = ntohs (im->header.size) - sizeof (struct InfoMessage);
158 hello = (const struct GNUNET_HELLO_Message *) &im[1];
159 LOG (GNUNET_ERROR_TYPE_DEBUG,
160 "Received information about peer `%s' from peerinfo database\n",
161 GNUNET_i2s (&im->peer));
162 nc->callback (nc->callback_cls,
170 * Type of a function to call when we receive a message from the
171 * service. Call the iterator with the result and (if applicable)
172 * continue to receive more messages or trigger processing the next
173 * event (if applicable).
176 * @param msg message received, NULL on timeout or fatal error
179 handle_end_iteration (void *cls,
180 const struct GNUNET_MessageHeader *msg)
182 /* these are ignored by the notify API */
187 * Task to re-try connecting to peerinfo.
189 * @param cls the `struct GNUNET_PEERINFO_NotifyContext *`
192 reconnect (void *cls)
194 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
195 struct GNUNET_MQ_MessageHandler handlers[] = {
196 GNUNET_MQ_hd_var_size (notification,
197 GNUNET_MESSAGE_TYPE_PEERINFO_INFO,
200 GNUNET_MQ_hd_fixed_size (end_iteration,
201 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END,
202 struct GNUNET_MessageHeader,
204 GNUNET_MQ_handler_end ()
206 struct GNUNET_MQ_Envelope *env;
207 struct NotifyMessage *nm;
210 nc->mq = GNUNET_CLIENT_connect (nc->cfg,
217 env = GNUNET_MQ_msg (nm,
218 GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY);
219 nm->include_friend_only = htonl (nc->include_friend_only);
220 GNUNET_MQ_send (nc->mq,
226 * Call a method whenever our known information about peers
227 * changes. Initially calls the given function for all known
228 * peers and then only signals changes.
230 * If @a include_friend_only is set to #GNUNET_YES peerinfo will include HELLO
231 * messages which are intended for friend to friend mode and which do not
232 * have to be gossiped. Otherwise these messages are skipped.
234 * @param cfg configuration to use
235 * @param include_friend_only include HELLO messages for friends only
236 * @param callback the method to call for each peer
237 * @param callback_cls closure for @a callback
238 * @return NULL on error
240 struct GNUNET_PEERINFO_NotifyContext *
241 GNUNET_PEERINFO_notify (const struct GNUNET_CONFIGURATION_Handle *cfg,
242 int include_friend_only,
243 GNUNET_PEERINFO_Processor callback,
246 struct GNUNET_PEERINFO_NotifyContext *nc;
248 nc = GNUNET_new (struct GNUNET_PEERINFO_NotifyContext);
250 nc->callback = callback;
251 nc->callback_cls = callback_cls;
252 nc->include_friend_only = include_friend_only;
256 LOG (GNUNET_ERROR_TYPE_WARNING,
257 "Could not connect to PEERINFO service.\n");
266 * Stop notifying about changes.
268 * @param nc context to stop notifying
271 GNUNET_PEERINFO_notify_cancel (struct GNUNET_PEERINFO_NotifyContext *nc)
275 GNUNET_MQ_destroy (nc->mq);
278 if (NULL != nc->task)
280 GNUNET_SCHEDULER_cancel (nc->task);
286 /* end of peerinfo_api_notify.c */