aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo/peerinfo_api.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-21 13:00:22 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-21 13:00:22 +0000
commitcf3e70cea00a2d6d519fe563370ee9df16fdd913 (patch)
treeb0b46d543dfb40bcd91e4dcfa859768c23dfab59 /src/peerinfo/peerinfo_api.c
parent66d6dc062c1ab92c4855dc061bf45b3e9531b539 (diff)
downloadgnunet-cf3e70cea00a2d6d519fe563370ee9df16fdd913.tar.gz
gnunet-cf3e70cea00a2d6d519fe563370ee9df16fdd913.zip
towards new peerinfo API
Diffstat (limited to 'src/peerinfo/peerinfo_api.c')
-rw-r--r--src/peerinfo/peerinfo_api.c375
1 files changed, 372 insertions, 3 deletions
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c
index 89422bcb6..aac83f71b 100644
--- a/src/peerinfo/peerinfo_api.c
+++ b/src/peerinfo/peerinfo_api.c
@@ -22,14 +22,63 @@
22 * @file peerinfo/peerinfo_api.c 22 * @file peerinfo/peerinfo_api.c
23 * @brief API to access peerinfo service 23 * @brief API to access peerinfo service
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - document NEW API implementation
28 * - add timeout for iteration
29 * - implement cancellation of iteration
25 */ 30 */
26#include "platform.h" 31#include "platform.h"
27#include "gnunet_client_lib.h" 32#include "gnunet_client_lib.h"
33#include "gnunet_container_lib.h"
28#include "gnunet_peerinfo_service.h" 34#include "gnunet_peerinfo_service.h"
29#include "gnunet_protocols.h" 35#include "gnunet_protocols.h"
30#include "gnunet_time_lib.h" 36#include "gnunet_time_lib.h"
31#include "peerinfo.h" 37#include "peerinfo.h"
32 38
39/**
40 *
41 */
42typedef void (*TransmissionContinuation)(void *cls,
43 int success);
44
45
46/**
47 *
48 */
49struct TransmissionQueueEntry
50{
51 /**
52 *
53 */
54 struct TransmissionQueueEntry *next;
55
56 /**
57 *
58 */
59 struct TransmissionQueueEntry *prev;
60
61 /**
62 *
63 */
64 TransmissionContinuation cont;
65
66 /**
67 *
68 */
69 void *cont_cls;
70
71 /**
72 *
73 */
74 struct GNUNET_TIME_Absolute timeout;
75
76 /**
77 *
78 */
79 size_t size;
80
81};
33 82
34 83
35/** 84/**
@@ -37,6 +86,35 @@
37 */ 86 */
38struct GNUNET_PEERINFO_Handle 87struct GNUNET_PEERINFO_Handle
39{ 88{
89 /**
90 * Our configuration.
91 */
92 const struct GNUNET_CONFIGURATION_Handle *cfg;
93
94 /**
95 * Our scheduler.
96 */
97 struct GNUNET_SCHEDULER_Handle *sched;
98
99 /**
100 * Connection to the service.
101 */
102 struct GNUNET_CLIENT_Connection *client;
103
104 /**
105 *
106 */
107 struct TransmissionQueueEntry *tq_head;
108
109 /**
110 *
111 */
112 struct TransmissionQueueEntry *tq_tail;
113
114 /**
115 *
116 */
117 struct GNUNET_CLIENT_TransmitHandle *th;
40}; 118};
41 119
42 120
@@ -52,7 +130,17 @@ struct GNUNET_PEERINFO_Handle *
52GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 130GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
53 struct GNUNET_SCHEDULER_Handle *sched) 131 struct GNUNET_SCHEDULER_Handle *sched)
54{ 132{
55 return NULL; 133 struct GNUNET_CLIENT_Connection *client;
134 struct GNUNET_PEERINFO_Handle *ret;
135
136 client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg);
137 if (client == NULL)
138 return NULL;
139 ret = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle));
140 ret->client = client;
141 ret->cfg = cfg;
142 ret->sched = sched;
143 return ret;
56} 144}
57 145
58 146
@@ -68,11 +156,100 @@ GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
68void 156void
69GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) 157GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h)
70{ 158{
159 struct TransmissionQueueEntry *tqe;
160
161 while (NULL != (tqe = h->tq_head))
162 {
163 GNUNET_CONTAINER_DLL_remove (h->tq_head,
164 h->tq_tail,
165 tqe);
166 if (tqe->cont != NULL)
167 tqe->cont (tqe->cont_cls, GNUNET_SYSERR);
168 GNUNET_free (tqe);
169 }
170 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
171 GNUNET_free (h);
71} 172}
72 173
73 174
175/**
176 *
177 */
178static void
179trigger_transmit (struct GNUNET_PEERINFO_Handle *h);
180
181
182/**
183 *
184 */
185static void
186reconnect (struct GNUNET_PEERINFO_Handle *h)
187{
188 GNUNET_CLIENT_disconnect (h->client, GNUNET_SYSERR);
189 h->client = GNUNET_CLIENT_connect (h->sched, "client", h->cfg);
190 GNUNET_assert (h->client != NULL);
191}
192
193
194/**
195 *
196 */
197static size_t
198do_transmit (void *cls, size_t size, void *buf)
199{
200 struct GNUNET_PEERINFO_Handle *h = cls;
201 struct TransmissionQueueEntry *tqe = h->tq_head;
202 size_t ret;
203
204 h->th = NULL;
205 if (buf == NULL)
206 {
207#if DEBUG_PEERINFO
208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
209 _
210 ("Failed to transmit message of type %u to `%s' service.\n"),
211 ntohs (msg->type), "peerinfo");
212#endif
213 GNUNET_CONTAINER_DLL_remove (h->tq_head,
214 h->tq_tail,
215 tqe);
216 reconnect (h);
217 trigger_transmit (h);
218 if (tqe->cont != NULL)
219 tqe->cont (tqe->cont_cls, GNUNET_SYSERR);
220 GNUNET_free (tqe);
221 return 0;
222 }
223 ret = tqe->size;
224 GNUNET_assert (size >= ret);
225 memcpy (buf, &tqe[1], ret);
226 GNUNET_CONTAINER_DLL_remove (h->tq_head,
227 h->tq_tail,
228 tqe);
229 if (tqe->cont != NULL)
230 tqe->cont (tqe->cont_cls, GNUNET_OK);
231 else
232 trigger_transmit (h);
233 GNUNET_free (tqe);
234 return ret;
235}
74 236
75 237
238static void
239trigger_transmit (struct GNUNET_PEERINFO_Handle *h)
240{
241 struct TransmissionQueueEntry *tqe;
242
243 if (NULL == (tqe = h->tq_head))
244 return;
245 if (h->th != NULL)
246 return;
247 h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
248 tqe->size,
249 GNUNET_TIME_absolute_get_remaining (tqe->timeout),
250 GNUNET_YES,
251 &do_transmit, h);
252}
76 253
77 254
78/** 255/**
@@ -89,17 +266,163 @@ GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h)
89 */ 266 */
90void 267void
91GNUNET_PEERINFO_add_peer_new (struct GNUNET_PEERINFO_Handle *h, 268GNUNET_PEERINFO_add_peer_new (struct GNUNET_PEERINFO_Handle *h,
92 const struct GNUNET_PeerIdentity *peer,
93 const struct GNUNET_HELLO_Message *hello) 269 const struct GNUNET_HELLO_Message *hello)
94{ 270{
271 uint16_t hs = GNUNET_HELLO_size (hello);
272 struct TransmissionQueueEntry *tqe;
273
274#if DEBUG_PEERINFO
275 struct GNUNET_PeerIdentity peer;
276 GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (hello, &peer));
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
278 "Adding peer `%s' to PEERINFO database (%u bytes of `%s')\n",
279 GNUNET_i2s(&peer),
280 hs,
281 "HELLO");
282#endif
283 tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) + hs);
284 tqe->size = hs;
285 tqe->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
286 memcpy (&tqe[1], hello, hs);
287 GNUNET_CONTAINER_DLL_insert_after (h->tq_head,
288 h->tq_tail,
289 h->tq_tail,
290 tqe);
291 trigger_transmit (h);
95} 292}
96 293
97 294
295
296/**
297 *
298 */
98struct GNUNET_PEERINFO_NewIteratorContext 299struct GNUNET_PEERINFO_NewIteratorContext
99{ 300{
301 /**
302 *
303 */
304 struct GNUNET_PEERINFO_Handle *h;
305
306 /**
307 *
308 */
309 GNUNET_PEERINFO_Processor callback;
310
311 /**
312 *
313 */
314 void *callback_cls;
315
316 /**
317 *
318 */
319 struct GNUNET_TIME_Absolute timeout;
100}; 320};
101 321
102 322
323
324/**
325 * Type of a function to call when we receive a message
326 * from the service.
327 *
328 * @param cls closure
329 * @param msg message received, NULL on timeout or fatal error
330 */
331static void
332peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
333{
334 struct GNUNET_PEERINFO_NewIteratorContext *ic = cls;
335 const struct InfoMessage *im;
336 const struct GNUNET_HELLO_Message *hello;
337 uint16_t ms;
338
339 if (msg == NULL)
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
342 _("Failed to receive response from `%s' service.\n"),
343 "peerinfo");
344 reconnect (ic->h);
345 trigger_transmit (ic->h);
346 ic->callback (ic->callback_cls, NULL, NULL, 1);
347 GNUNET_free (ic);
348 return;
349 }
350 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END)
351 {
352#if DEBUG_PEERINFO
353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
354 "Received end of list of peers from peerinfo database\n");
355#endif
356 trigger_transmit (ic->h);
357 ic->callback (ic->callback_cls, NULL, NULL, 0);
358 GNUNET_free (ic);
359 return;
360 }
361 ms = ntohs (msg->size);
362 if ((ms < sizeof (struct InfoMessage)) ||
363 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO))
364 {
365 GNUNET_break (0);
366 reconnect (ic->h);
367 trigger_transmit (ic->h);
368 ic->callback (ic->callback_cls, NULL, NULL, 2);
369 GNUNET_free (ic);
370 return;
371 }
372 im = (const struct InfoMessage *) msg;
373 hello = NULL;
374 if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader))
375 {
376 hello = (const struct GNUNET_HELLO_Message *) &im[1];
377 if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello))
378 {
379 GNUNET_break (0);
380 reconnect (ic->h);
381 trigger_transmit (ic->h);
382 ic->callback (ic->callback_cls, NULL, NULL, 2);
383 GNUNET_free (ic);
384 return;
385 }
386 }
387#if DEBUG_PEERINFO
388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
389 "Received %u bytes of `%s' information about peer `%s' from PEERINFO database\n",
390 (hello == NULL) ? 0 : (unsigned int) GNUNET_HELLO_size (hello),
391 "HELLO",
392 GNUNET_i2s (&im->peer));
393#endif
394 ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
395 GNUNET_CLIENT_receive (ic->h->client,
396 &peerinfo_handler,
397 ic,
398 GNUNET_TIME_absolute_get_remaining (ic->timeout));
399}
400
401
402/**
403 *
404 */
405static void
406iterator_start_receive (void *cls,
407 int transmit_success)
408{
409 struct GNUNET_PEERINFO_NewIteratorContext *ic = cls;
410
411 if (GNUNET_OK != transmit_success)
412 {
413 ic->callback (ic->callback_cls, NULL, NULL, 2);
414 reconnect (ic->h);
415 trigger_transmit (ic->h);
416 GNUNET_free (ic);
417 return;
418 }
419 GNUNET_CLIENT_receive (ic->h->client,
420 &peerinfo_handler,
421 ic,
422 GNUNET_TIME_absolute_get_remaining (ic->timeout));
423}
424
425
103/** 426/**
104 * Call a method for each known matching host and change its trust 427 * Call a method for each known matching host and change its trust
105 * value. The callback method will be invoked once for each matching 428 * value. The callback method will be invoked once for each matching
@@ -130,7 +453,51 @@ GNUNET_PEERINFO_iterate_new (struct GNUNET_PEERINFO_Handle *h,
130 GNUNET_PEERINFO_Processor callback, 453 GNUNET_PEERINFO_Processor callback,
131 void *callback_cls) 454 void *callback_cls)
132{ 455{
133 return NULL; 456 struct ListAllPeersMessage *lapm;
457 struct ListPeerMessage *lpm;
458 struct GNUNET_PEERINFO_NewIteratorContext *ic;
459 struct TransmissionQueueEntry *tqe;
460
461#if DEBUG_PEERINFO
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
463 "Requesting list of peers from peerinfo database\n");
464#endif
465 if (peer == NULL)
466 {
467 tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
468 sizeof (struct ListAllPeersMessage));
469 tqe->size = sizeof (struct ListAllPeersMessage);
470 lapm = (struct ListAllPeersMessage *) &tqe[1];
471 lapm->header.size = htons (sizeof (struct ListAllPeersMessage));
472 lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
473 lapm->trust_change = htonl (trust_delta);
474 }
475 else
476 {
477 tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
478 sizeof (struct ListPeerMessage));
479 tqe->size = sizeof (struct ListPeerMessage);
480 lpm = (struct ListPeerMessage *) &tqe[1];
481 lpm->header.size = htons (sizeof (struct ListPeerMessage));
482 lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
483 lpm->trust_change = htonl (trust_delta);
484 memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
485 }
486 ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_NewIteratorContext));
487 ic->callback = callback;
488 ic->callback_cls = callback_cls;
489 ic->timeout = GNUNET_TIME_relative_to_absolute (timeout);
490 tqe->timeout = ic->timeout;
491 tqe->cont = &iterator_start_receive;
492 tqe->cont_cls = ic;
493 /* FIXME: sort DLL by timeout? */
494 /* FIXME: add timeout task!? */
495 GNUNET_CONTAINER_DLL_insert_after (h->tq_head,
496 h->tq_tail,
497 h->tq_tail,
498 tqe);
499 trigger_transmit (h);
500 return ic;
134} 501}
135 502
136 503
@@ -143,6 +510,8 @@ GNUNET_PEERINFO_iterate_new (struct GNUNET_PEERINFO_Handle *h,
143void 510void
144GNUNET_PEERINFO_iterate_cancel_new (struct GNUNET_PEERINFO_NewIteratorContext *ic) 511GNUNET_PEERINFO_iterate_cancel_new (struct GNUNET_PEERINFO_NewIteratorContext *ic)
145{ 512{
513 GNUNET_assert (0);
514 // FIXME: not implemented
146} 515}
147 516
148 517