2 This file is part of GNUnet.
3 (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file peerinfo/peerinfo_api_notify.c
23 * @brief notify API to access peerinfo service
24 * @author Christian Grothoff
27 #include "gnunet_client_lib.h"
28 #include "gnunet_peerinfo_service.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_time_lib.h"
33 #define LOG(kind,...) GNUNET_log_from (kind, "nse-api",__VA_ARGS__)
36 * Context for the info handler.
38 struct GNUNET_PEERINFO_NotifyContext
42 * Our connection to the PEERINFO service.
44 struct GNUNET_CLIENT_Connection *client;
47 * Function to call with information.
49 GNUNET_PEERINFO_Processor callback;
52 * Closure for callback.
57 * Handle to our initial request for message transmission to
58 * the peerinfo service.
60 struct GNUNET_CLIENT_TransmitHandle *init;
65 const struct GNUNET_CONFIGURATION_Handle *cfg;
68 * Tasked used for delayed re-connection attempt.
70 GNUNET_SCHEDULER_TaskIdentifier task;
73 * Include friend only HELLOs in callbacks
76 int include_friend_only;
81 * Send a request to the peerinfo service to start being
82 * notified about all changes to peer information.
84 * @param nc our context
87 request_notifications (struct GNUNET_PEERINFO_NotifyContext *nc);
91 * Read notifications from the client handle and pass them
94 * @param nc our context
97 receive_notifications (struct GNUNET_PEERINFO_NotifyContext *nc);
101 * Task to re-try connecting to peerinfo.
103 * @param cls the 'struct GNUNET_PEERINFO_NotifyContext'
104 * @param tc scheduler context
107 reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
109 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
111 nc->task = GNUNET_SCHEDULER_NO_TASK;
112 nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg);
113 if (NULL == nc->client)
117 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, nc);
120 request_notifications (nc);
125 * Receive a peerinfo information message, process it and
129 * @param msg message received, NULL on timeout or fatal error
132 process_notification (void *cls, const struct GNUNET_MessageHeader *msg)
134 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
135 const struct InfoMessage *im;
136 const struct GNUNET_HELLO_Message *hello;
141 GNUNET_CLIENT_disconnect (nc->client);
142 reconnect (nc, NULL);
145 ms = ntohs (msg->size);
146 if ((ms < sizeof (struct InfoMessage)) ||
147 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO))
150 GNUNET_CLIENT_disconnect (nc->client);
151 nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg);
152 request_notifications (nc);
155 im = (const struct InfoMessage *) msg;
157 if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader))
159 hello = (const struct GNUNET_HELLO_Message *) &im[1];
160 if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello))
163 GNUNET_CLIENT_disconnect (nc->client);
164 nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg);
165 request_notifications (nc);
170 LOG (GNUNET_ERROR_TYPE_DEBUG,
171 "Received information about peer `%s' from peerinfo database\n",
172 GNUNET_i2s (&im->peer));
173 nc->callback (nc->callback_cls, &im->peer, hello, NULL);
174 receive_notifications (nc);
179 * Read notifications from the client handle and pass them
182 * @param nc our context
185 receive_notifications (struct GNUNET_PEERINFO_NotifyContext *nc)
187 GNUNET_CLIENT_receive (nc->client, &process_notification, nc,
188 GNUNET_TIME_UNIT_FOREVER_REL);
193 * Transmit our init-notify request, start receiving.
195 * @param cls closure (our 'struct GNUNET_PEERINFO_NotifyContext')
196 * @param size number of bytes available in buf
197 * @param buf where the callee should write the message
198 * @return number of bytes written to buf
201 transmit_notify_request (void *cls, size_t size, void *buf)
203 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
204 struct NotifyMessage nm;
209 GNUNET_CLIENT_disconnect (nc->client);
210 nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg);
211 request_notifications (nc);
214 GNUNET_assert (size >= sizeof (struct NotifyMessage));
215 nm.header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY);
216 nm.header.size = htons (sizeof (struct NotifyMessage));
217 nm.include_friend_only = htonl (nc->include_friend_only);
218 memcpy (buf, &nm, sizeof (struct NotifyMessage));
219 receive_notifications (nc);
220 return sizeof (struct NotifyMessage);
225 * Send a request to the peerinfo service to start being
226 * notified about all changes to peer information.
228 * @param nc our context
231 request_notifications (struct GNUNET_PEERINFO_NotifyContext *nc)
233 GNUNET_assert (NULL == nc->init);
235 GNUNET_CLIENT_notify_transmit_ready (nc->client,
236 sizeof (struct NotifyMessage),
237 GNUNET_TIME_UNIT_FOREVER_REL,
238 GNUNET_YES, &transmit_notify_request,
244 * Call a method whenever our known information about peers
245 * changes. Initially calls the given function for all known
246 * peers and then only signals changes.
248 * If include_friend_only is set to GNUNET_YES peerinfo will include HELLO
249 * messages which are intended for friend to friend mode and which do not
250 * have to be gossiped. Otherwise these messages are skipped.
252 * @param cfg configuration to use
253 * @param include_friend_only include HELLO messages for friends only
254 * @param callback the method to call for each peer
255 * @param callback_cls closure for callback
256 * @return NULL on error
258 struct GNUNET_PEERINFO_NotifyContext *
259 GNUNET_PEERINFO_notify (const struct GNUNET_CONFIGURATION_Handle *cfg,
260 int include_friend_only,
261 GNUNET_PEERINFO_Processor callback, void *callback_cls)
263 struct GNUNET_PEERINFO_NotifyContext *nc;
264 struct GNUNET_CLIENT_Connection *client;
266 client = GNUNET_CLIENT_connect ("peerinfo", cfg);
269 LOG (GNUNET_ERROR_TYPE_WARNING, _("Could not connect to `%s' service.\n"),
273 nc = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_NotifyContext));
276 nc->callback = callback;
277 nc->callback_cls = callback_cls;
278 nc->include_friend_only = include_friend_only;
279 request_notifications (nc);
285 * Stop notifying about changes.
287 * @param nc context to stop notifying
290 GNUNET_PEERINFO_notify_cancel (struct GNUNET_PEERINFO_NotifyContext *nc)
292 if (NULL != nc->init)
294 GNUNET_CLIENT_notify_transmit_ready_cancel (nc->init);
297 if (NULL != nc->client)
298 GNUNET_CLIENT_disconnect (nc->client);
299 if (GNUNET_SCHEDULER_NO_TASK != nc->task)
300 GNUNET_SCHEDULER_cancel (nc->task);
304 /* end of peerinfo_api_notify.c */