diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-04-30 14:50:06 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-04-30 14:50:06 +0000 |
commit | 5f9efe3ff20656b7900fc0b503f3e0cbe75eb20a (patch) | |
tree | a6f379dfd9dafc1db1fa95260ab7029f15a9b283 /src/dv/dv_api.c | |
parent | e6b08db0728b172da76392967661c09e7bfdbb55 (diff) | |
download | gnunet-5f9efe3ff20656b7900fc0b503f3e0cbe75eb20a.tar.gz gnunet-5f9efe3ff20656b7900fc0b503f3e0cbe75eb20a.zip |
dv changes. add propagation of disconnect messages, dv updates on peer direct connections. Result of those two changes should be a much better learned topology for all peers. This was periodic gossip is really only to stop timeouts from removing peers. Also changed dv_api to wait for message queuing by dv service before calling transport transmit continuation, so that addresses that are no longer available can be caught by transport service. Perhaps some other stuff I have forgotten about. Should be kinda sorta working, need to make better testcases and do more debugging as errors inevitably pop up
Diffstat (limited to 'src/dv/dv_api.c')
-rw-r--r-- | src/dv/dv_api.c | 157 |
1 files changed, 129 insertions, 28 deletions
diff --git a/src/dv/dv_api.c b/src/dv/dv_api.c index a2d9f1762..29b6dcca3 100644 --- a/src/dv/dv_api.c +++ b/src/dv/dv_api.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "gnunet_time_lib.h" | 36 | #include "gnunet_time_lib.h" |
37 | #include "gnunet_dv_service.h" | 37 | #include "gnunet_dv_service.h" |
38 | #include "dv.h" | 38 | #include "dv.h" |
39 | #include "../transport/plugin_transport.h" | ||
39 | 40 | ||
40 | 41 | ||
41 | struct PendingMessages | 42 | struct PendingMessages |
@@ -109,12 +110,21 @@ struct GNUNET_DV_Handle | |||
109 | */ | 110 | */ |
110 | void *receive_cls; | 111 | void *receive_cls; |
111 | 112 | ||
113 | /** | ||
114 | * Current unique ID | ||
115 | */ | ||
116 | uint32_t uid_gen; | ||
117 | |||
118 | /** | ||
119 | * Hashmap containing outstanding send requests awaiting confirmation. | ||
120 | */ | ||
121 | struct GNUNET_CONTAINER_MultiHashMap *send_callbacks; | ||
122 | |||
112 | }; | 123 | }; |
113 | 124 | ||
114 | 125 | ||
115 | struct StartContext | 126 | struct StartContext |
116 | { | 127 | { |
117 | |||
118 | /** | 128 | /** |
119 | * Start message | 129 | * Start message |
120 | */ | 130 | */ |
@@ -126,6 +136,37 @@ struct StartContext | |||
126 | struct GNUNET_DV_Handle *handle; | 136 | struct GNUNET_DV_Handle *handle; |
127 | }; | 137 | }; |
128 | 138 | ||
139 | struct SendCallbackContext | ||
140 | { | ||
141 | /** | ||
142 | * The continuation to call once a message is confirmed sent (or failed) | ||
143 | */ | ||
144 | GNUNET_TRANSPORT_TransmitContinuation cont; | ||
145 | |||
146 | /** | ||
147 | * Closure to call with send continuation. | ||
148 | */ | ||
149 | void *cont_cls; | ||
150 | |||
151 | /** | ||
152 | * Target of the message. | ||
153 | */ | ||
154 | struct GNUNET_PeerIdentity target; | ||
155 | }; | ||
156 | |||
157 | /** | ||
158 | * Convert unique ID to hash code. | ||
159 | * | ||
160 | * @param uid unique ID to convert | ||
161 | * @param hash set to uid (extended with zeros) | ||
162 | */ | ||
163 | static void | ||
164 | hash_from_uid (uint32_t uid, | ||
165 | GNUNET_HashCode *hash) | ||
166 | { | ||
167 | memset (hash, 0, sizeof(GNUNET_HashCode)); | ||
168 | *((uint32_t*)hash) = uid; | ||
169 | } | ||
129 | 170 | ||
130 | /** | 171 | /** |
131 | * Try to (re)connect to the dv service. | 172 | * Try to (re)connect to the dv service. |
@@ -283,58 +324,98 @@ static void add_pending(struct GNUNET_DV_Handle *handle, struct GNUNET_DV_SendMe | |||
283 | process_pending_message(handle); | 324 | process_pending_message(handle); |
284 | } | 325 | } |
285 | 326 | ||
286 | 327 | /** | |
328 | * Handles a message sent from the DV service to us. | ||
329 | * Parse it out and give it to the plugin. | ||
330 | * | ||
331 | * @param cls the handle to the DV API | ||
332 | * @param msg the message that was received | ||
333 | */ | ||
287 | void handle_message_receipt (void *cls, | 334 | void handle_message_receipt (void *cls, |
288 | const struct GNUNET_MessageHeader * msg) | 335 | const struct GNUNET_MessageHeader * msg) |
289 | { | 336 | { |
290 | struct GNUNET_DV_Handle *handle = cls; | 337 | struct GNUNET_DV_Handle *handle = cls; |
291 | struct GNUNET_DV_MessageReceived *received_msg; | 338 | struct GNUNET_DV_MessageReceived *received_msg; |
339 | struct GNUNET_DV_SendResultMessage *send_result_msg; | ||
292 | size_t packed_msg_len; | 340 | size_t packed_msg_len; |
293 | size_t sender_address_len; | 341 | size_t sender_address_len; |
294 | char *sender_address; | 342 | char *sender_address; |
295 | char *packed_msg; | 343 | char *packed_msg; |
296 | char *packed_msg_start; | 344 | char *packed_msg_start; |
345 | GNUNET_HashCode uidhash; | ||
346 | struct SendCallbackContext *send_ctx; | ||
297 | 347 | ||
298 | if (msg == NULL) | 348 | if (msg == NULL) |
299 | { | 349 | { |
300 | return; /* Connection closed? */ | 350 | return; /* Connection closed? */ |
301 | } | 351 | } |
302 | 352 | ||
303 | GNUNET_assert(ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE); | 353 | GNUNET_assert((ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE) || (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT)); |
304 | 354 | ||
305 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) | 355 | switch (ntohs(msg->type)) |
306 | return; | 356 | { |
357 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE: | ||
358 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) | ||
359 | return; | ||
307 | 360 | ||
308 | received_msg = (struct GNUNET_DV_MessageReceived *)msg; | 361 | received_msg = (struct GNUNET_DV_MessageReceived *)msg; |
309 | packed_msg_len = ntohl(received_msg->msg_len); | 362 | packed_msg_len = ntohl(received_msg->msg_len); |
310 | sender_address_len = ntohl(received_msg->sender_address_len); | 363 | sender_address_len = ntohl(received_msg->sender_address_len); |
311 | 364 | ||
312 | GNUNET_assert(ntohs(msg->size) == (sizeof(struct GNUNET_DV_MessageReceived) + packed_msg_len + sender_address_len)); | 365 | GNUNET_assert(ntohs(msg->size) == (sizeof(struct GNUNET_DV_MessageReceived) + packed_msg_len + sender_address_len)); |
313 | #if DEBUG_DV | 366 | #if DEBUG_DV |
314 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "dv api receives message, size checks out!\n"); | 367 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "dv api receives message, size checks out!\n"); |
315 | #endif | 368 | #endif |
316 | sender_address = GNUNET_malloc(sender_address_len); | 369 | sender_address = GNUNET_malloc(sender_address_len); |
317 | memcpy(sender_address, &received_msg[1], sender_address_len); | 370 | memcpy(sender_address, &received_msg[1], sender_address_len); |
318 | packed_msg_start = (char *)&received_msg[1]; | 371 | packed_msg_start = (char *)&received_msg[1]; |
319 | packed_msg = GNUNET_malloc(packed_msg_len); | 372 | packed_msg = GNUNET_malloc(packed_msg_len); |
320 | memcpy(packed_msg, &packed_msg_start[sender_address_len], packed_msg_len); | 373 | memcpy(packed_msg, &packed_msg_start[sender_address_len], packed_msg_len); |
321 | 374 | ||
322 | #if DEBUG_DV | 375 | #if DEBUG_DV |
323 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: packed message type: %d or %d\n", ntohs(((struct GNUNET_MessageHeader *)packed_msg)->type), ((struct GNUNET_MessageHeader *)packed_msg)->type); | 376 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: packed message type: %d or %d\n", ntohs(((struct GNUNET_MessageHeader *)packed_msg)->type), ((struct GNUNET_MessageHeader *)packed_msg)->type); |
324 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: message sender reported as %s\n", GNUNET_i2s(&received_msg->sender)); | 377 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: message sender reported as %s\n", GNUNET_i2s(&received_msg->sender)); |
325 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: distance is %u\n", ntohl(received_msg->distance)); | 378 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: distance is %u\n", ntohl(received_msg->distance)); |
326 | #endif | 379 | #endif |
327 | 380 | ||
328 | handle->receive_handler(handle->receive_cls, | 381 | handle->receive_handler(handle->receive_cls, |
329 | &received_msg->sender, | 382 | &received_msg->sender, |
330 | packed_msg, | 383 | packed_msg, |
331 | packed_msg_len, | 384 | packed_msg_len, |
332 | ntohl(received_msg->distance), | 385 | ntohl(received_msg->distance), |
333 | sender_address, | 386 | sender_address, |
334 | sender_address_len); | 387 | sender_address_len); |
388 | |||
389 | GNUNET_free(sender_address); | ||
390 | break; | ||
391 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT: | ||
392 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_SendResultMessage)) | ||
393 | return; | ||
335 | 394 | ||
336 | GNUNET_free(sender_address); | 395 | send_result_msg = (struct GNUNET_DV_SendResultMessage *)msg; |
396 | hash_from_uid(ntohl(send_result_msg->uid), &uidhash); | ||
397 | send_ctx = GNUNET_CONTAINER_multihashmap_get(handle->send_callbacks, &uidhash); | ||
398 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got uid of %u or %u, hash of %s !!!!\n", ntohl(send_result_msg->uid), send_result_msg->uid, GNUNET_h2s(&uidhash)); | ||
337 | 399 | ||
400 | if ((send_ctx != NULL) && (send_ctx->cont != NULL)) | ||
401 | { | ||
402 | #if DEBUG_DV | ||
403 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "dv api notifies transport of send result (%u)!\n", ntohl(send_result_msg->result)); | ||
404 | #endif | ||
405 | if (ntohl(send_result_msg->result) == 0) | ||
406 | { | ||
407 | send_ctx->cont(send_ctx->cont_cls, &send_ctx->target, GNUNET_OK); | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | send_ctx->cont(send_ctx->cont_cls, &send_ctx->target, GNUNET_SYSERR); | ||
412 | } | ||
413 | } | ||
414 | GNUNET_free_non_null(send_ctx); | ||
415 | break; | ||
416 | default: | ||
417 | break; | ||
418 | } | ||
338 | GNUNET_CLIENT_receive (handle->client, | 419 | GNUNET_CLIENT_receive (handle->client, |
339 | &handle_message_receipt, | 420 | &handle_message_receipt, |
340 | handle, GNUNET_TIME_UNIT_FOREVER_REL); | 421 | handle, GNUNET_TIME_UNIT_FOREVER_REL); |
@@ -361,14 +442,18 @@ int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle, | |||
361 | unsigned int priority, | 442 | unsigned int priority, |
362 | struct GNUNET_TIME_Relative timeout, | 443 | struct GNUNET_TIME_Relative timeout, |
363 | const void *addr, | 444 | const void *addr, |
364 | size_t addrlen) | 445 | size_t addrlen, |
446 | GNUNET_TRANSPORT_TransmitContinuation | ||
447 | cont, void *cont_cls) | ||
365 | { | 448 | { |
366 | struct GNUNET_DV_SendMessage *msg; | 449 | struct GNUNET_DV_SendMessage *msg; |
450 | struct SendCallbackContext *send_ctx; | ||
367 | char *end_of_message; | 451 | char *end_of_message; |
368 | /* FIXME: Copy message to end of thingy, can't just allocate dummy! */ | 452 | GNUNET_HashCode uidhash; |
369 | #if DEBUG_DV | 453 | #if DEBUG_DV |
370 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV SEND called with message of size %d, address size %d, total size to send is %d\n", msgbuf_size, addrlen, sizeof(struct GNUNET_DV_SendMessage) + msgbuf_size + addrlen); | 454 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV SEND called with message of size %d, address size %d, total size to send is %d\n", msgbuf_size, addrlen, sizeof(struct GNUNET_DV_SendMessage) + msgbuf_size + addrlen); |
371 | #endif | 455 | #endif |
456 | dv_handle->uid_gen++; | ||
372 | msg = GNUNET_malloc(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); | 457 | msg = GNUNET_malloc(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); |
373 | msg->header.size = htons(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); | 458 | msg->header.size = htons(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); |
374 | msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND); | 459 | msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND); |
@@ -377,12 +462,26 @@ int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle, | |||
377 | msg->priority = htonl(priority); | 462 | msg->priority = htonl(priority); |
378 | msg->timeout = timeout; | 463 | msg->timeout = timeout; |
379 | msg->addrlen = htonl(addrlen); | 464 | msg->addrlen = htonl(addrlen); |
465 | msg->uid = htonl(dv_handle->uid_gen); | ||
380 | memcpy(&msg[1], addr, addrlen); | 466 | memcpy(&msg[1], addr, addrlen); |
381 | end_of_message = (char *)&msg[1]; | 467 | end_of_message = (char *)&msg[1]; |
382 | end_of_message = &end_of_message[addrlen]; | 468 | end_of_message = &end_of_message[addrlen]; |
383 | memcpy(end_of_message, msgbuf, msgbuf_size); | 469 | memcpy(end_of_message, msgbuf, msgbuf_size); |
384 | add_pending(dv_handle, msg); | 470 | add_pending(dv_handle, msg); |
385 | 471 | ||
472 | send_ctx = GNUNET_malloc(sizeof(struct SendCallbackContext)); | ||
473 | |||
474 | send_ctx->cont = cont; | ||
475 | if (cont == NULL) | ||
476 | fprintf(stderr, "DV_SEND called with null continuation!\n"); | ||
477 | send_ctx->cont_cls = cont_cls; | ||
478 | memcpy(&send_ctx->target, target, sizeof(struct GNUNET_PeerIdentity)); | ||
479 | |||
480 | hash_from_uid(dv_handle->uid_gen, &uidhash); | ||
481 | |||
482 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "set uid of %u or %u, hash of %s !!!!\n", dv_handle->uid_gen, htonl(dv_handle->uid_gen), GNUNET_h2s(&uidhash)); | ||
483 | GNUNET_CONTAINER_multihashmap_put(dv_handle->send_callbacks, &uidhash, send_ctx, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
484 | |||
386 | return GNUNET_OK; | 485 | return GNUNET_OK; |
387 | } | 486 | } |
388 | 487 | ||
@@ -464,6 +563,8 @@ GNUNET_DV_connect (struct GNUNET_SCHEDULER_Handle *sched, | |||
464 | GNUNET_YES, | 563 | GNUNET_YES, |
465 | &transmit_start, start_context); | 564 | &transmit_start, start_context); |
466 | 565 | ||
566 | handle->send_callbacks = GNUNET_CONTAINER_multihashmap_create(100); | ||
567 | |||
467 | GNUNET_CLIENT_receive (handle->client, | 568 | GNUNET_CLIENT_receive (handle->client, |
468 | &handle_message_receipt, | 569 | &handle_message_receipt, |
469 | handle, GNUNET_TIME_UNIT_FOREVER_REL); | 570 | handle, GNUNET_TIME_UNIT_FOREVER_REL); |