aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo/peerinfo_api.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-01-11 22:13:37 +0000
committerChristian Grothoff <christian@grothoff.org>2010-01-11 22:13:37 +0000
commitbb4e48f94a3daba7b0294ce8760a231b0601fa11 (patch)
treec32408c3060ba0a51bf8ca031d944d478a65f866 /src/peerinfo/peerinfo_api.c
parentc85579b554836cd5a67e87abb3e11a2d53d6a3e8 (diff)
downloadgnunet-bb4e48f94a3daba7b0294ce8760a231b0601fa11.tar.gz
gnunet-bb4e48f94a3daba7b0294ce8760a231b0601fa11.zip
adding notification API to peerinfo
Diffstat (limited to 'src/peerinfo/peerinfo_api.c')
-rw-r--r--src/peerinfo/peerinfo_api.c243
1 files changed, 243 insertions, 0 deletions
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 */
306struct 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 */
348static void
349request_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 */
358static void
359receive_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 */
369static void
370process_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 */
426static void
427receive_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 */
444static size_t
445transmit_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 */
475static void
476request_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 */
499struct GNUNET_PEERINFO_NotifyContext *
500GNUNET_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 */
531void
532GNUNET_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 */