aboutsummaryrefslogtreecommitdiff
path: root/src/dv/dv_api.c
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-04-30 14:50:06 +0000
committerNathan S. Evans <evans@in.tum.de>2010-04-30 14:50:06 +0000
commit5f9efe3ff20656b7900fc0b503f3e0cbe75eb20a (patch)
treea6f379dfd9dafc1db1fa95260ab7029f15a9b283 /src/dv/dv_api.c
parente6b08db0728b172da76392967661c09e7bfdbb55 (diff)
downloadgnunet-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.c157
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
41struct PendingMessages 42struct 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
115struct StartContext 126struct 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
139struct 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 */
163static void
164hash_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 */
287void handle_message_receipt (void *cls, 334void 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);