diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-04-21 13:00:22 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-04-21 13:00:22 +0000 |
commit | cf3e70cea00a2d6d519fe563370ee9df16fdd913 (patch) | |
tree | b0b46d543dfb40bcd91e4dcfa859768c23dfab59 /src/peerinfo/peerinfo_api.c | |
parent | 66d6dc062c1ab92c4855dc061bf45b3e9531b539 (diff) | |
download | gnunet-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.c | 375 |
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 | */ | ||
42 | typedef void (*TransmissionContinuation)(void *cls, | ||
43 | int success); | ||
44 | |||
45 | |||
46 | /** | ||
47 | * | ||
48 | */ | ||
49 | struct 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 | */ |
38 | struct GNUNET_PEERINFO_Handle | 87 | struct 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 * | |||
52 | GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | 130 | GNUNET_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, | |||
68 | void | 156 | void |
69 | GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) | 157 | GNUNET_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 | */ | ||
178 | static void | ||
179 | trigger_transmit (struct GNUNET_PEERINFO_Handle *h); | ||
180 | |||
181 | |||
182 | /** | ||
183 | * | ||
184 | */ | ||
185 | static void | ||
186 | reconnect (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 | */ | ||
197 | static size_t | ||
198 | do_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 | ||
238 | static void | ||
239 | trigger_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 | */ |
90 | void | 267 | void |
91 | GNUNET_PEERINFO_add_peer_new (struct GNUNET_PEERINFO_Handle *h, | 268 | GNUNET_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 | */ | ||
98 | struct GNUNET_PEERINFO_NewIteratorContext | 299 | struct 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 | */ | ||
331 | static void | ||
332 | peerinfo_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 | */ | ||
405 | static void | ||
406 | iterator_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, | |||
143 | void | 510 | void |
144 | GNUNET_PEERINFO_iterate_cancel_new (struct GNUNET_PEERINFO_NewIteratorContext *ic) | 511 | GNUNET_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 | ||