diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-01-11 22:13:37 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-01-11 22:13:37 +0000 |
commit | bb4e48f94a3daba7b0294ce8760a231b0601fa11 (patch) | |
tree | c32408c3060ba0a51bf8ca031d944d478a65f866 /src/peerinfo | |
parent | c85579b554836cd5a67e87abb3e11a2d53d6a3e8 (diff) | |
download | gnunet-bb4e48f94a3daba7b0294ce8760a231b0601fa11.tar.gz gnunet-bb4e48f94a3daba7b0294ce8760a231b0601fa11.zip |
adding notification API to peerinfo
Diffstat (limited to 'src/peerinfo')
-rw-r--r-- | src/peerinfo/gnunet-service-peerinfo.c | 250 | ||||
-rw-r--r-- | src/peerinfo/peerinfo_api.c | 243 |
2 files changed, 493 insertions, 0 deletions
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c index ee1287831..4323be478 100644 --- a/src/peerinfo/gnunet-service-peerinfo.c +++ b/src/peerinfo/gnunet-service-peerinfo.c | |||
@@ -26,6 +26,9 @@ | |||
26 | * structure of data/hosts/ and data/credit/). | 26 | * structure of data/hosts/ and data/credit/). |
27 | * | 27 | * |
28 | * @author Christian Grothoff | 28 | * @author Christian Grothoff |
29 | * | ||
30 | * TODO: | ||
31 | * - HostEntries are never 'free'd (add expiration, upper bound?) | ||
29 | */ | 32 | */ |
30 | 33 | ||
31 | #include "platform.h" | 34 | #include "platform.h" |
@@ -84,12 +87,64 @@ struct HostEntry | |||
84 | 87 | ||
85 | }; | 88 | }; |
86 | 89 | ||
90 | |||
91 | /** | ||
92 | * Entries that we still need to tell the client about. | ||
93 | */ | ||
94 | struct PendingEntry | ||
95 | { | ||
96 | |||
97 | /** | ||
98 | * This is a linked list. | ||
99 | */ | ||
100 | struct PendingEntry *next; | ||
101 | |||
102 | /** | ||
103 | * Entry to tell the client about. | ||
104 | */ | ||
105 | struct HostEntry *he; | ||
106 | }; | ||
107 | |||
108 | |||
109 | /** | ||
110 | * Clients to notify of changes to the peer information. | ||
111 | */ | ||
112 | struct NotifyList | ||
113 | { | ||
114 | |||
115 | /** | ||
116 | * This is a linked list. | ||
117 | */ | ||
118 | struct NotifyList *next; | ||
119 | |||
120 | /** | ||
121 | * Client to notify. | ||
122 | */ | ||
123 | struct GNUNET_SERVER_Client *client; | ||
124 | |||
125 | /** | ||
126 | * Notifications pending for this entry. | ||
127 | */ | ||
128 | struct PendingEntry *pending; | ||
129 | |||
130 | /** | ||
131 | * Handle for a transmit ready request. | ||
132 | */ | ||
133 | struct GNUNET_CONNECTION_TransmitHandle *transmit_ctx; | ||
134 | }; | ||
135 | |||
136 | |||
87 | /** | 137 | /** |
88 | * The in-memory list of known hosts. | 138 | * The in-memory list of known hosts. |
89 | */ | 139 | */ |
90 | static struct HostEntry *hosts; | 140 | static struct HostEntry *hosts; |
91 | 141 | ||
92 | /** | 142 | /** |
143 | * Clients to immediately notify about all changes. | ||
144 | */ | ||
145 | static struct NotifyList *notify_list; | ||
146 | |||
147 | /** | ||
93 | * Directory where the hellos are stored in (data/hosts) | 148 | * Directory where the hellos are stored in (data/hosts) |
94 | */ | 149 | */ |
95 | static char *networkIdDirectory; | 150 | static char *networkIdDirectory; |
@@ -101,6 +156,116 @@ static char *trustDirectory; | |||
101 | 156 | ||
102 | 157 | ||
103 | /** | 158 | /** |
159 | * Transmit peer information messages from the pending queue | ||
160 | * to the client. | ||
161 | * | ||
162 | * @param cls the 'struct NotifyList' that we are processing | ||
163 | * @param size number of bytes we can transmit | ||
164 | * @param vbuf where to write the messages | ||
165 | * @return number of bytes written to vbuf | ||
166 | */ | ||
167 | static size_t | ||
168 | transmit_pending_notification (void *cls, | ||
169 | size_t size, | ||
170 | void *vbuf) | ||
171 | { | ||
172 | struct NotifyList *nl = cls; | ||
173 | char *buf = vbuf; | ||
174 | struct PendingEntry *pos; | ||
175 | struct PendingEntry *next; | ||
176 | struct InfoMessage im; | ||
177 | uint16_t hs; | ||
178 | size_t left; | ||
179 | |||
180 | nl->transmit_ctx = NULL; | ||
181 | next = nl->pending; | ||
182 | pos = nl->pending; | ||
183 | left = size; | ||
184 | while ( (pos != NULL) && | ||
185 | (left >= sizeof (struct InfoMessage) + (hs = GNUNET_HELLO_size (pos->he->hello))) ) | ||
186 | { | ||
187 | next = pos->next; | ||
188 | im.header.size = htons (hs + sizeof (struct InfoMessage)); | ||
189 | im.header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO); | ||
190 | im.trust = htonl (pos->he->trust); | ||
191 | im.peer = pos->he->identity; | ||
192 | memcpy (&buf[size - left], &im, sizeof (struct InfoMessage)); | ||
193 | memcpy (&buf[size - left + sizeof (struct InfoMessage)], pos->he->hello, hs); | ||
194 | left -= hs + sizeof (struct InfoMessage); | ||
195 | GNUNET_free (pos); | ||
196 | pos = next; | ||
197 | } | ||
198 | nl->pending = next; | ||
199 | if (nl->pending != NULL) | ||
200 | { | ||
201 | nl->transmit_ctx | ||
202 | = GNUNET_SERVER_notify_transmit_ready (nl->client, | ||
203 | sizeof (struct InfoMessage) + hs, | ||
204 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
205 | &transmit_pending_notification, | ||
206 | nl); | ||
207 | } | ||
208 | return size - left; | ||
209 | } | ||
210 | |||
211 | |||
212 | |||
213 | /** | ||
214 | * Notify client about host change. Checks if the | ||
215 | * respective host entry is already in the list of things | ||
216 | * to send to the client, and if not, adds it. Also | ||
217 | * triggers a new request for transmission if the pending | ||
218 | * list was previously empty. | ||
219 | * | ||
220 | * @param nl client to notify | ||
221 | * @param hc entry to notify about | ||
222 | */ | ||
223 | static void | ||
224 | do_notify (struct NotifyList *nl, | ||
225 | struct HostEntry *he) | ||
226 | { | ||
227 | struct PendingEntry *pe; | ||
228 | |||
229 | pe = nl->pending; | ||
230 | while (NULL != pe) | ||
231 | { | ||
232 | if (pe->he == he) | ||
233 | return; /* already in list */ | ||
234 | pe = pe->next; | ||
235 | } | ||
236 | pe = GNUNET_malloc (sizeof (struct PendingEntry)); | ||
237 | pe->next = nl->pending; | ||
238 | pe->he = he; | ||
239 | nl->pending = pe; | ||
240 | if (nl->transmit_ctx != NULL) | ||
241 | return; /* already trying to transmit */ | ||
242 | nl->transmit_ctx = GNUNET_SERVER_notify_transmit_ready (nl->client, | ||
243 | sizeof (struct InfoMessage) + GNUNET_HELLO_size (he->hello), | ||
244 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
245 | &transmit_pending_notification, | ||
246 | nl); | ||
247 | } | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Notify all clients in the notify list about the | ||
252 | * given host entry changing. | ||
253 | */ | ||
254 | static void | ||
255 | notify_all (struct HostEntry *he) | ||
256 | { | ||
257 | struct NotifyList *nl; | ||
258 | |||
259 | nl = notify_list; | ||
260 | while (NULL != nl) | ||
261 | { | ||
262 | do_notify (nl, he); | ||
263 | nl = nl->next; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | |||
268 | /** | ||
104 | * Address iterator that causes expired entries to be discarded. | 269 | * Address iterator that causes expired entries to be discarded. |
105 | * | 270 | * |
106 | * @param cls pointer to the current time | 271 | * @param cls pointer to the current time |
@@ -231,6 +396,7 @@ add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity) | |||
231 | GNUNET_free (fn); | 396 | GNUNET_free (fn); |
232 | entry->next = hosts; | 397 | entry->next = hosts; |
233 | hosts = entry; | 398 | hosts = entry; |
399 | notify_all (entry); | ||
234 | } | 400 | } |
235 | 401 | ||
236 | 402 | ||
@@ -246,6 +412,7 @@ static int | |||
246 | change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value) | 412 | change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value) |
247 | { | 413 | { |
248 | struct HostEntry *host; | 414 | struct HostEntry *host; |
415 | unsigned int old_trust; | ||
249 | 416 | ||
250 | if (value == 0) | 417 | if (value == 0) |
251 | return 0; | 418 | return 0; |
@@ -256,6 +423,7 @@ change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value) | |||
256 | host = lookup_host_entry (hostId); | 423 | host = lookup_host_entry (hostId); |
257 | } | 424 | } |
258 | GNUNET_assert (host != NULL); | 425 | GNUNET_assert (host != NULL); |
426 | old_trust = host->trust; | ||
259 | if (value > 0) | 427 | if (value > 0) |
260 | { | 428 | { |
261 | if (host->trust + value < host->trust) | 429 | if (host->trust + value < host->trust) |
@@ -276,6 +444,8 @@ change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value) | |||
276 | else | 444 | else |
277 | host->trust += value; | 445 | host->trust += value; |
278 | } | 446 | } |
447 | if (host->trust != old_trust) | ||
448 | notify_all (host); | ||
279 | return value; | 449 | return value; |
280 | } | 450 | } |
281 | 451 | ||
@@ -383,6 +553,8 @@ bind_address (const struct GNUNET_PeerIdentity *peer, | |||
383 | else | 553 | else |
384 | { | 554 | { |
385 | mrg = GNUNET_HELLO_merge (host->hello, hello); | 555 | mrg = GNUNET_HELLO_merge (host->hello, hello); |
556 | /* FIXME: check if old and merged hello are equal, | ||
557 | and if so, bail out early... */ | ||
386 | GNUNET_free (host->hello); | 558 | GNUNET_free (host->hello); |
387 | host->hello = mrg; | 559 | host->hello = mrg; |
388 | } | 560 | } |
@@ -393,6 +565,7 @@ bind_address (const struct GNUNET_PeerIdentity *peer, | |||
393 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | 565 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE |
394 | | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); | 566 | | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); |
395 | GNUNET_free (fn); | 567 | GNUNET_free (fn); |
568 | notify_all (host); | ||
396 | } | 569 | } |
397 | 570 | ||
398 | 571 | ||
@@ -643,6 +816,35 @@ handle_get_all (void *cls, | |||
643 | 816 | ||
644 | 817 | ||
645 | /** | 818 | /** |
819 | * Handle NOTIFY-message. | ||
820 | * | ||
821 | * @param cls closure | ||
822 | * @param client identification of the client | ||
823 | * @param message the actual message | ||
824 | */ | ||
825 | static void | ||
826 | handle_notify (void *cls, | ||
827 | struct GNUNET_SERVER_Client *client, | ||
828 | const struct GNUNET_MessageHeader *message) | ||
829 | { | ||
830 | struct NotifyList *nl; | ||
831 | struct HostEntry *pos; | ||
832 | |||
833 | nl = GNUNET_malloc (sizeof (struct NotifyList)); | ||
834 | nl->next = notify_list; | ||
835 | nl->client = client; | ||
836 | GNUNET_SERVER_client_keep (client); | ||
837 | notify_list = nl; | ||
838 | pos = hosts; | ||
839 | while (NULL != pos) | ||
840 | { | ||
841 | do_notify (nl, pos); | ||
842 | pos = pos->next; | ||
843 | } | ||
844 | } | ||
845 | |||
846 | |||
847 | /** | ||
646 | * List of handlers for the messages understood by this | 848 | * List of handlers for the messages understood by this |
647 | * service. | 849 | * service. |
648 | */ | 850 | */ |
@@ -652,10 +854,57 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = { | |||
652 | sizeof (struct ListPeerMessage)}, | 854 | sizeof (struct ListPeerMessage)}, |
653 | {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, | 855 | {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, |
654 | sizeof (struct ListAllPeersMessage)}, | 856 | sizeof (struct ListAllPeersMessage)}, |
857 | {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY, | ||
858 | sizeof (struct GNUNET_MessageHeader)}, | ||
655 | {NULL, NULL, 0, 0} | 859 | {NULL, NULL, 0, 0} |
656 | }; | 860 | }; |
657 | 861 | ||
658 | 862 | ||
863 | /** | ||
864 | * Function that is called when a client disconnects. | ||
865 | */ | ||
866 | static void | ||
867 | notify_disconnect (void *cls, | ||
868 | struct GNUNET_SERVER_Client *client) | ||
869 | { | ||
870 | struct NotifyList *pos; | ||
871 | struct NotifyList *prev; | ||
872 | struct NotifyList *next; | ||
873 | struct PendingEntry *p; | ||
874 | |||
875 | pos = notify_list; | ||
876 | prev = NULL; | ||
877 | while (pos != NULL) | ||
878 | { | ||
879 | next = pos->next; | ||
880 | if (pos->client == client) | ||
881 | { | ||
882 | while (NULL != (p = pos->pending)) | ||
883 | { | ||
884 | pos->pending = p->next; | ||
885 | GNUNET_free (p); | ||
886 | } | ||
887 | if (pos->transmit_ctx != NULL) | ||
888 | { | ||
889 | GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->transmit_ctx); | ||
890 | pos->transmit_ctx = NULL; | ||
891 | } | ||
892 | if (prev == NULL) | ||
893 | notify_list = next; | ||
894 | else | ||
895 | prev->next = next; | ||
896 | GNUNET_SERVER_client_drop (client); | ||
897 | GNUNET_free (pos); | ||
898 | } | ||
899 | else | ||
900 | { | ||
901 | prev = pos; | ||
902 | } | ||
903 | pos = next; | ||
904 | } | ||
905 | |||
906 | } | ||
907 | |||
659 | 908 | ||
660 | /** | 909 | /** |
661 | * Process statistics requests. | 910 | * Process statistics requests. |
@@ -692,6 +941,7 @@ run (void *cls, | |||
692 | GNUNET_SCHEDULER_add_with_priority (sched, | 941 | GNUNET_SCHEDULER_add_with_priority (sched, |
693 | GNUNET_SCHEDULER_PRIORITY_IDLE, | 942 | GNUNET_SCHEDULER_PRIORITY_IDLE, |
694 | &cron_clean_data_hosts, NULL); | 943 | &cron_clean_data_hosts, NULL); |
944 | GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, NULL); | ||
695 | GNUNET_SERVER_add_handlers (server, handlers); | 945 | GNUNET_SERVER_add_handlers (server, handlers); |
696 | } | 946 | } |
697 | 947 | ||
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c index b5c6c99d7..906c01d77 100644 --- a/src/peerinfo/peerinfo_api.c +++ b/src/peerinfo/peerinfo_api.c | |||
@@ -298,4 +298,247 @@ GNUNET_PEERINFO_for_all (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Context for the info handler. | ||
305 | */ | ||
306 | struct GNUNET_PEERINFO_NotifyContext | ||
307 | { | ||
308 | |||
309 | /** | ||
310 | * Our connection to the PEERINFO service. | ||
311 | */ | ||
312 | struct GNUNET_CLIENT_Connection *client; | ||
313 | |||
314 | /** | ||
315 | * Function to call with information. | ||
316 | */ | ||
317 | GNUNET_PEERINFO_Processor callback; | ||
318 | |||
319 | /** | ||
320 | * Closure for callback. | ||
321 | */ | ||
322 | void *callback_cls; | ||
323 | |||
324 | /** | ||
325 | * Handle to our initial request for message transmission to | ||
326 | * the peerinfo service. | ||
327 | */ | ||
328 | struct GNUNET_CLIENT_TransmitHandle *init; | ||
329 | |||
330 | /** | ||
331 | * Configuration. | ||
332 | */ | ||
333 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
334 | |||
335 | /** | ||
336 | * Scheduler. | ||
337 | */ | ||
338 | struct GNUNET_SCHEDULER_Handle *sched; | ||
339 | }; | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Send a request to the peerinfo service to start being | ||
344 | * notified about all changes to peer information. | ||
345 | * | ||
346 | * @param nc our context | ||
347 | */ | ||
348 | static void | ||
349 | request_notifications (struct GNUNET_PEERINFO_NotifyContext *nc); | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Read notifications from the client handle and pass them | ||
354 | * to the callback. | ||
355 | * | ||
356 | * @param nc our context | ||
357 | */ | ||
358 | static void | ||
359 | receive_notifications (struct GNUNET_PEERINFO_NotifyContext *nc); | ||
360 | |||
361 | |||
362 | /** | ||
363 | * Receive a peerinfo information message, process it and | ||
364 | * go for more. | ||
365 | * | ||
366 | * @param cls closure | ||
367 | * @param msg message received, NULL on timeout or fatal error | ||
368 | */ | ||
369 | static void | ||
370 | process_notification (void *cls, | ||
371 | const struct | ||
372 | GNUNET_MessageHeader * msg) | ||
373 | { | ||
374 | struct GNUNET_PEERINFO_NotifyContext *nc = cls; | ||
375 | const struct InfoMessage *im; | ||
376 | const struct GNUNET_HELLO_Message *hello; | ||
377 | uint16_t ms; | ||
378 | |||
379 | if (msg == NULL) | ||
380 | { | ||
381 | GNUNET_CLIENT_disconnect (nc->client); | ||
382 | nc->client = GNUNET_CLIENT_connect (nc->sched, "peerinfo", nc->cfg); | ||
383 | request_notifications (nc); | ||
384 | return; | ||
385 | } | ||
386 | ms = ntohs (msg->size); | ||
387 | if ((ms < sizeof (struct InfoMessage)) || | ||
388 | (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO)) | ||
389 | { | ||
390 | GNUNET_break (0); | ||
391 | GNUNET_CLIENT_disconnect (nc->client); | ||
392 | nc->client = GNUNET_CLIENT_connect (nc->sched, "peerinfo", nc->cfg); | ||
393 | request_notifications (nc); | ||
394 | return; | ||
395 | } | ||
396 | im = (const struct InfoMessage *) msg; | ||
397 | hello = NULL; | ||
398 | if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader)) | ||
399 | { | ||
400 | hello = (const struct GNUNET_HELLO_Message *) &im[1]; | ||
401 | if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) | ||
402 | { | ||
403 | GNUNET_break (0); | ||
404 | GNUNET_CLIENT_disconnect (nc->client); | ||
405 | nc->client = GNUNET_CLIENT_connect (nc->sched, "peerinfo", nc->cfg); | ||
406 | request_notifications (nc); | ||
407 | return; | ||
408 | } | ||
409 | } | ||
410 | #if DEBUG_PEERINFO | ||
411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
412 | "Received information about peer `%s' from peerinfo database\n", | ||
413 | GNUNET_i2s (&im->peer)); | ||
414 | #endif | ||
415 | nc->callback (nc->callback_cls, &im->peer, hello, ntohl (im->trust)); | ||
416 | receive_notifications (nc); | ||
417 | } | ||
418 | |||
419 | |||
420 | /** | ||
421 | * Read notifications from the client handle and pass them | ||
422 | * to the callback. | ||
423 | * | ||
424 | * @param nc our context | ||
425 | */ | ||
426 | static void | ||
427 | receive_notifications (struct GNUNET_PEERINFO_NotifyContext *nc) | ||
428 | { | ||
429 | GNUNET_CLIENT_receive (nc->client, | ||
430 | &process_notification, | ||
431 | nc, | ||
432 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Transmit our init-notify request, start receiving. | ||
438 | * | ||
439 | * @param cls closure (our 'struct GNUNET_PEERINFO_NotifyContext') | ||
440 | * @param size number of bytes available in buf | ||
441 | * @param buf where the callee should write the message | ||
442 | * @return number of bytes written to buf | ||
443 | */ | ||
444 | static size_t | ||
445 | transmit_notify_request (void *cls, | ||
446 | size_t size, | ||
447 | void *buf) | ||
448 | { | ||
449 | struct GNUNET_PEERINFO_NotifyContext *nc = cls; | ||
450 | struct GNUNET_MessageHeader hdr; | ||
451 | |||
452 | nc->init = NULL; | ||
453 | if (buf == NULL) | ||
454 | { | ||
455 | GNUNET_CLIENT_disconnect (nc->client); | ||
456 | nc->client = GNUNET_CLIENT_connect (nc->sched, "peerinfo", nc->cfg); | ||
457 | request_notifications (nc); | ||
458 | return 0; | ||
459 | } | ||
460 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | ||
461 | hdr.size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
462 | hdr.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY); | ||
463 | memcpy (buf, &hdr, sizeof (struct GNUNET_MessageHeader)); | ||
464 | receive_notifications (nc); | ||
465 | return sizeof (struct GNUNET_MessageHeader); | ||
466 | } | ||
467 | |||
468 | |||
469 | /** | ||
470 | * Send a request to the peerinfo service to start being | ||
471 | * notified about all changes to peer information. | ||
472 | * | ||
473 | * @param nc our context | ||
474 | */ | ||
475 | static void | ||
476 | request_notifications (struct GNUNET_PEERINFO_NotifyContext *nc) | ||
477 | { | ||
478 | GNUNET_assert (NULL == nc->init); | ||
479 | nc->init =GNUNET_CLIENT_notify_transmit_ready (nc->client, | ||
480 | sizeof (struct GNUNET_MessageHeader), | ||
481 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
482 | GNUNET_YES, | ||
483 | &transmit_notify_request, | ||
484 | nc); | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Call a method whenever our known information about peers | ||
490 | * changes. Initially calls the given function for all known | ||
491 | * peers and then only signals changes. | ||
492 | * | ||
493 | * @param cfg configuration to use | ||
494 | * @param sched scheduler to use | ||
495 | * @param callback the method to call for each peer | ||
496 | * @param callback_cls closure for callback | ||
497 | * @return NULL on error | ||
498 | */ | ||
499 | struct GNUNET_PEERINFO_NotifyContext * | ||
500 | GNUNET_PEERINFO_notify (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
501 | struct GNUNET_SCHEDULER_Handle *sched, | ||
502 | GNUNET_PEERINFO_Processor callback, | ||
503 | void *callback_cls) | ||
504 | { | ||
505 | struct GNUNET_PEERINFO_NotifyContext *nc; | ||
506 | struct GNUNET_CLIENT_Connection *client; | ||
507 | |||
508 | client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg); | ||
509 | if (client == NULL) | ||
510 | { | ||
511 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
512 | _("Could not connect to `%s' service.\n"), "peerinfo"); | ||
513 | return NULL; | ||
514 | } | ||
515 | nc = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_NotifyContext)); | ||
516 | nc->sched = sched; | ||
517 | nc->cfg = cfg; | ||
518 | nc->client = client; | ||
519 | nc->callback = callback; | ||
520 | nc->callback_cls = callback_cls; | ||
521 | request_notifications (nc); | ||
522 | return nc; | ||
523 | } | ||
524 | |||
525 | |||
526 | /** | ||
527 | * Stop notifying about changes. | ||
528 | * | ||
529 | * @param nc context to stop notifying | ||
530 | */ | ||
531 | void | ||
532 | GNUNET_PEERINFO_notify_cancel (struct GNUNET_PEERINFO_NotifyContext *nc) | ||
533 | { | ||
534 | if (NULL != nc->init) | ||
535 | { | ||
536 | GNUNET_CLIENT_notify_transmit_ready_cancel (nc->init); | ||
537 | nc->init = NULL; | ||
538 | } | ||
539 | GNUNET_CLIENT_disconnect (nc->client); | ||
540 | GNUNET_free (nc); | ||
541 | } | ||
542 | |||
543 | |||
301 | /* end of peerinfo_api.c */ | 544 | /* end of peerinfo_api.c */ |