aboutsummaryrefslogtreecommitdiff
path: root/src/dv
diff options
context:
space:
mode:
Diffstat (limited to 'src/dv')
-rw-r--r--src/dv/dv.h8
-rw-r--r--src/dv/dv_api.c19
-rw-r--r--src/dv/gnunet-service-dv.c262
3 files changed, 263 insertions, 26 deletions
diff --git a/src/dv/dv.h b/src/dv/dv.h
index 10120a4b0..d43befd70 100644
--- a/src/dv/dv.h
+++ b/src/dv/dv.h
@@ -33,7 +33,8 @@
33 33
34typedef void (*GNUNET_DV_MessageReceivedHandler) (void *cls, 34typedef void (*GNUNET_DV_MessageReceivedHandler) (void *cls,
35 struct GNUNET_PeerIdentity *sender, 35 struct GNUNET_PeerIdentity *sender,
36 struct GNUNET_MessageHeader *msg, 36 char *msg,
37 size_t msg_len,
37 unsigned int distance, 38 unsigned int distance,
38 char *sender_address, 39 char *sender_address,
39 size_t sender_address_len); 40 size_t sender_address_len);
@@ -42,7 +43,8 @@ typedef void (*GNUNET_DV_MessageReceivedHandler) (void *cls,
42 * DV Message, contains a message that was received 43 * DV Message, contains a message that was received
43 * via DV for this peer! 44 * via DV for this peer!
44 * 45 *
45 * Sender address is copied to the end of this struct. 46 * Sender address is copied to the end of this struct,
47 * followed by the actual message received.
46 */ 48 */
47struct GNUNET_DV_MessageReceived 49struct GNUNET_DV_MessageReceived
48{ 50{
@@ -59,7 +61,7 @@ struct GNUNET_DV_MessageReceived
59 /** 61 /**
60 * The message that was sent 62 * The message that was sent
61 */ 63 */
62 struct GNUNET_MessageHeader *msg; 64 size_t msg_len;
63 65
64 /** 66 /**
65 * The distance to the peer that we received the message from 67 * The distance to the peer that we received the message from
diff --git a/src/dv/dv_api.c b/src/dv/dv_api.c
index 15ef822d6..9e99790fb 100644
--- a/src/dv/dv_api.c
+++ b/src/dv/dv_api.c
@@ -250,7 +250,10 @@ void handle_message_receipt (void *cls,
250{ 250{
251 struct GNUNET_DV_Handle *handle = cls; 251 struct GNUNET_DV_Handle *handle = cls;
252 struct GNUNET_DV_MessageReceived *received_msg; 252 struct GNUNET_DV_MessageReceived *received_msg;
253 size_t packed_msg_len;
254 size_t sender_address_len;
253 char *sender_address; 255 char *sender_address;
256 char *packed_msg;
254 257
255 GNUNET_assert(ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE); 258 GNUNET_assert(ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
256 259
@@ -258,17 +261,22 @@ void handle_message_receipt (void *cls,
258 return; 261 return;
259 262
260 received_msg = (struct GNUNET_DV_MessageReceived *)msg; 263 received_msg = (struct GNUNET_DV_MessageReceived *)msg;
261 GNUNET_assert(ntohs(msg->size) == (sizeof(struct GNUNET_DV_MessageReceived) + ntohs(received_msg->msg->size) + ntohs(received_msg->sender_address_len))); 264 packed_msg_len = ntohs(received_msg->msg_len);
265 sender_address_len = ntohs(received_msg->sender_address_len);
266 GNUNET_assert(ntohs(msg->size) == (sizeof(struct GNUNET_DV_MessageReceived) + packed_msg_len + sender_address_len));
262 267
263 sender_address = GNUNET_malloc(ntohs(received_msg->sender_address_len)); 268 sender_address = GNUNET_malloc(sender_address_len);
264 sender_address = memcpy(sender_address, &received_msg[1], ntohs(received_msg->sender_address_len)); 269 memcpy(sender_address, &received_msg[1], sender_address_len);
270 packed_msg = GNUNET_malloc(packed_msg_len);
271 memcpy(packed_msg, &received_msg[1 + sender_address_len], packed_msg_len);
265 272
266 handle->receive_handler(handle->receive_cls, 273 handle->receive_handler(handle->receive_cls,
267 &received_msg->sender, 274 &received_msg->sender,
268 received_msg->msg, 275 packed_msg,
276 packed_msg_len,
269 ntohl(received_msg->distance), 277 ntohl(received_msg->distance),
270 sender_address, 278 sender_address,
271 ntohs(received_msg->sender_address_len)); 279 sender_address_len);
272 280
273 GNUNET_free(sender_address); 281 GNUNET_free(sender_address);
274 282
@@ -281,6 +289,7 @@ void handle_message_receipt (void *cls,
281 * Send a message from the plugin to the DV service indicating that 289 * Send a message from the plugin to the DV service indicating that
282 * a message should be sent via DV to some peer. 290 * a message should be sent via DV to some peer.
283 * 291 *
292 * @param dv_handle the handle to the DV api
284 * @param target the final target of the message 293 * @param target the final target of the message
285 * @param msgbuf the msg(s) to send 294 * @param msgbuf the msg(s) to send
286 * @param msgbuf_size the size of msgbuf 295 * @param msgbuf_size the size of msgbuf
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c
index bb5e03193..0e182fca8 100644
--- a/src/dv/gnunet-service-dv.c
+++ b/src/dv/gnunet-service-dv.c
@@ -67,18 +67,18 @@ static struct GNUNET_SCHEDULER_Handle *sched;
67 * How often do we check about sending out more peer information (if 67 * How often do we check about sending out more peer information (if
68 * we are connected to no peers previously). 68 * we are connected to no peers previously).
69 */ 69 */
70#define GNUNET_DV_DEFAULT_SEND_INTERVAL (500 * GNUNET_CRON_MILLISECONDS) 70#define GNUNET_DV_DEFAULT_SEND_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500))
71 71
72/** 72/**
73 * How long do we wait at most between sending out information? 73 * How long do we wait at most between sending out information?
74 */ 74 */
75#define GNUNET_DV_MAX_SEND_INTERVAL (5000 * GNUNET_CRON_MILLISECONDS) 75#define GNUNET_DV_MAX_SEND_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
76 76
77/** 77/**
78 * How long can we have not heard from a peer and 78 * How long can we have not heard from a peer and
79 * still have it in our tables? 79 * still have it in our tables?
80 */ 80 */
81#define GNUNET_DV_PEER_EXPIRATION_TIME (3000 * GNUNET_CRON_SECONDS) 81#define GNUNET_DV_PEER_EXPIRATION_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1000))
82 82
83/** 83/**
84 * Priority for gossip. 84 * Priority for gossip.
@@ -89,12 +89,12 @@ static struct GNUNET_SCHEDULER_Handle *sched;
89 * How often should we check if expiration time has elapsed for 89 * How often should we check if expiration time has elapsed for
90 * some peer? 90 * some peer?
91 */ 91 */
92#define GNUNET_DV_MAINTAIN_FREQUENCY (5 * GNUNET_CRON_SECONDS) 92#define GNUNET_DV_MAINTAIN_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
93 93
94/** 94/**
95 * How long to allow a message to be delayed? 95 * How long to allow a message to be delayed?
96 */ 96 */
97#define DV_DELAY (5000 * GNUNET_CRON_MILLISECONDS) 97#define DV_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
98 98
99/** 99/**
100 * Priority to use for DV data messages. 100 * Priority to use for DV data messages.
@@ -108,13 +108,52 @@ static struct GNUNET_SCHEDULER_Handle *sched;
108 */ 108 */
109static struct GNUNET_SERVER_Client * client_handle; 109static struct GNUNET_SERVER_Client * client_handle;
110 110
111/**
112 * Task to run when we shut down, cleaning up all our trash
113 */
111GNUNET_SCHEDULER_TaskIdentifier cleanup_task; 114GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
112 115
113/** 116/**
117 * Task to run to gossip about peers. Will reschedule itself forever until shutdown!
118 */
119GNUNET_SCHEDULER_TaskIdentifier gossip_task;
120
121/**
114 * Struct where neighbor information is stored. 122 * Struct where neighbor information is stored.
115 */ 123 */
116struct DistantNeighbor *referees; 124struct DistantNeighbor *referees;
117 125
126static struct GNUNET_TIME_Relative client_transmit_timeout;
127
128static struct GNUNET_TIME_Relative default_dv_delay;
129
130static size_t default_dv_priority = 0;
131
132
133/**
134 * Pending message struct, also a test to see if these can
135 * safely ONLY be freed by callback.
136 */
137struct PendingMessage
138{
139 /**
140 * Copy of message to be sent
141 */
142 struct GNUNET_MessageHeader *msg;
143
144 /**
145 * Size of message to be sent
146 */
147 size_t msg_size;
148
149 /**
150 * Transmit handle, for cancellation if necessary.
151 */
152 struct GNUNET_CORE_TransmitHandle *transmit_handle;
153
154};
155
156
118/** 157/**
119 * Struct to hold information for updating existing neighbors 158 * Struct to hold information for updating existing neighbors
120 */ 159 */
@@ -273,14 +312,13 @@ struct GNUNET_DV_Context
273 312
274 unsigned long long max_table_size; 313 unsigned long long max_table_size;
275 314
276 unsigned int send_interval; 315 struct GNUNET_TIME_Relative send_interval;
277 316
278 unsigned int neighbor_id_loc; 317 unsigned int neighbor_id_loc;
279 318
280 int closing; 319 int closing;
281};
282 320
283static char shortID[5]; 321};
284 322
285static struct GNUNET_DV_Context ctx; 323static struct GNUNET_DV_Context ctx;
286 324
@@ -342,27 +380,136 @@ void send_to_plugin(const struct GNUNET_PeerIdentity * sender, const struct GNUN
342 struct GNUNET_DV_MessageReceived *received_msg; 380 struct GNUNET_DV_MessageReceived *received_msg;
343 int size; 381 int size;
344 382
345 if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) 383 size = sizeof(struct GNUNET_DV_MessageReceived) + sizeof(struct GNUNET_PeerIdentity) + message_size;
346 return;
347
348 size = sizeof(struct GNUNET_DV_MessageReceived) + message_size + sizeof(struct GNUNET_PeerIdentity);
349 received_msg = GNUNET_malloc(size); 384 received_msg = GNUNET_malloc(size);
350 received_msg->header.size = htons(size); 385 received_msg->header.size = htons(size);
351 received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE); 386 received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
352 received_msg->sender_address_len = sizeof(struct GNUNET_PeerIdentity); 387 received_msg->sender_address_len = sizeof(struct GNUNET_PeerIdentity);
353 received_msg->distance = htonl(distant_neighbor->cost); 388 received_msg->distance = htonl(distant_neighbor->cost);
389 received_msg->msg_len = htons(message_size);
354 /* Set the sender in this message to be the original sender! */ 390 /* Set the sender in this message to be the original sender! */
355 memcpy(&received_msg->sender, &distant_neighbor->identity, sizeof(struct GNUNET_PeerIdentity)); 391 memcpy(&received_msg->sender, &distant_neighbor->identity, sizeof(struct GNUNET_PeerIdentity));
356 /* Copy the intermediate sender to the end of the message, this is how the transport identifies this peer */ 392 /* Copy the intermediate sender to the end of the message, this is how the transport identifies this peer */
357 memcpy(&received_msg[1], sender, sizeof(struct GNUNET_PeerIdentity)); 393 memcpy(&received_msg[1], sender, sizeof(struct GNUNET_PeerIdentity));
394 /* Copy the actual message after the sender */
395 memcpy(&received_msg[1 + sizeof(struct GNUNET_PeerIdentity)], message, message_size);
358 396
359 /* FIXME: Send to the client please */ 397 /* FIXME: Send to the client please */
360 GNUNET_SERVER_notify_transmit_ready (client_handle, 398 GNUNET_SERVER_notify_transmit_ready (client_handle,
361 size, CLIENT_TRANSMIT_TIMEOUT, 399 size, client_transmit_timeout,
362 &transmit_to_plugin, &received_msg); 400 &transmit_to_plugin, &received_msg);
363 401
364} 402}
365 403
404
405/**
406 * Function called to notify a client about the socket
407 * begin ready to queue more data. "buf" will be
408 * NULL and "size" zero if the socket was closed for
409 * writing in the meantime.
410 *
411 * @param cls closure
412 * @param size number of bytes available in buf
413 * @param buf where the callee should write the message
414 * @return number of bytes written to buf
415 */
416size_t core_transmit_notify (void *cls,
417 size_t size, void *buf)
418{
419 struct PendingMessage *pending_message = cls;
420 char *send_buf = buf;
421 if ((buf == NULL) || (size < pending_message->msg_size))
422 {
423 return 0;
424 }
425
426 memcpy(send_buf, pending_message->msg, pending_message->msg_size);
427
428 GNUNET_free(pending_message->msg);
429 GNUNET_free(pending_message);
430
431 return size;
432}
433
434/**
435 * Send a DV data message via DV.
436 *
437 * @param recipient the ultimate recipient of this message
438 * @param the original sender of the message
439 * @param message the packed message
440 * @param importance what priority to send this message with
441 * @param timeout how long to possibly delay sending this message
442 */
443static int
444send_message (const struct GNUNET_PeerIdentity * recipient,
445 const struct GNUNET_PeerIdentity * sender,
446 const struct GNUNET_MessageHeader * message,
447 unsigned int importance, struct GNUNET_TIME_Relative timeout)
448{
449 p2p_dv_MESSAGE_Data *toSend;
450 unsigned int msg_size;
451 unsigned int cost;
452 unsigned int recipient_id;
453 unsigned int sender_id;
454 struct DistantNeighbor *target;
455 struct DistantNeighbor *source;
456 struct PendingMessage *pending_message;
457
458 msg_size = ntohs (message->size) + sizeof (p2p_dv_MESSAGE_Data);
459
460 target = GNUNET_CONTAINER_multihashmap_get (ctx.extended_neighbors,
461 &recipient->hashPubKey);
462 if (target == NULL)
463 {
464 /* target unknown to us, drop! */
465 return GNUNET_SYSERR;
466 }
467 recipient_id = target->referrer_id;
468
469 source = GNUNET_CONTAINER_multihashmap_get (ctx.extended_neighbors,
470 &sender->hashPubKey);
471 if (source == NULL)
472 {
473 if (0 != (memcmp (my_identity,
474 sender, sizeof (struct GNUNET_PeerIdentity))))
475 {
476 /* sender unknown to us, drop! */
477 return GNUNET_SYSERR;
478 }
479 sender_id = 0; /* 0 == us */
480 }
481 else
482 {
483 /* find out the number that we use when we gossip about
484 the sender */
485 sender_id = source->our_id;
486 }
487
488 cost = target->cost;
489 pending_message = GNUNET_malloc(sizeof(struct PendingMessage));
490 pending_message->msg = GNUNET_malloc (msg_size);
491 toSend = (p2p_dv_MESSAGE_Data *)pending_message->msg;
492 toSend->header.size = htons (msg_size);
493 toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
494 toSend->sender = htonl (sender_id);
495 toSend->recipient = htonl (recipient_id);
496 memcpy (&toSend[1], message, ntohs (message->size));
497 pending_message->msg_size = msg_size;
498
499 pending_message->transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, importance, timeout, &target->referrer->identity, msg_size, &core_transmit_notify, pending_message);
500 if (NULL == pending_message->transmit_handle)
501 {
502 GNUNET_free (pending_message->msg);
503 GNUNET_free (pending_message);
504 return GNUNET_SYSERR;
505 }
506
507 /*coreAPI->ciphertext_send (&target->referrer->identity,
508 &toSend->header, importance, maxdelay);*/
509 return (int) cost;
510}
511
512
366/** 513/**
367 * Core handler for dv data messages. Whatever this message 514 * Core handler for dv data messages. Whatever this message
368 * contains all we really have to do is rip it out of its 515 * contains all we really have to do is rip it out of its
@@ -434,9 +581,6 @@ static int handle_dv_data_message (void *cls,
434 if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) && 581 if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
435 (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) ) 582 (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
436 { 583 {
437 /* FIXME: send the message, wrap it up and return it to the DV plugin */
438 /*coreAPI->loopback_send (&original_sender, (const char *) packed_message,
439 ntohs (packed_message->size), GNUNET_YES, NULL);*/
440 send_to_plugin(peer, packed_message, ntohs(packed_message->size), pos); 584 send_to_plugin(peer, packed_message, ntohs(packed_message->size), pos);
441 } 585 }
442 586
@@ -463,15 +607,93 @@ static int handle_dv_data_message (void *cls,
463 return GNUNET_OK; 607 return GNUNET_OK;
464 } 608 }
465 609
610 /* At this point we have a message, and we need to forward it on to the
611 * next DV hop.
612 */
466 /* FIXME: Can't send message on, we have to behave. 613 /* FIXME: Can't send message on, we have to behave.
467 * We have to tell core we have a message for the next peer, and let 614 * We have to tell core we have a message for the next peer, and let
468 * transport do transport selection on how to get this message to 'em */ 615 * transport do transport selection on how to get this message to 'em */
469 /*ret = send_message (&destination, 616 /*ret = send_message (&destination,
470 &original_sender, 617 &original_sender,
471 packed_message, DV_PRIORITY, DV_DELAY);*/ 618 packed_message, DV_PRIORITY, DV_DELAY);*/
472 send_to_core(&destination, &original_sender, packed_message, DV_PRIORITY, DV_DELAY); 619 ret = send_message(&destination, &original_sender, packed_message, default_dv_priority, default_dv_delay);
473 620
474 return GNUNET_OK; 621 if (ret != GNUNET_SYSERR)
622 return GNUNET_OK;
623 else
624 return GNUNET_SYSERR;
625}
626
627
628/**
629 * Thread which chooses a peer to gossip about and a peer to gossip
630 * to, then constructs the message and sends it out. Will run until
631 * done_module_dv is called.
632 */
633static void
634neighbor_send_task (void *cls,
635 const struct GNUNET_SCHEDULER_TaskContext *tc)
636{
637#if DEBUG_DV
638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
639 "%s: Entering neighbor_send_thread...\n",
640 GNUNET_i2s(my_identity));
641 char * encPeerAbout;
642 char * encPeerTo;
643#endif
644 struct DistantNeighbor *about;
645 struct DirectNeighbor *to;
646
647 p2p_dv_MESSAGE_NeighborInfo *message;
648 struct PendingMessage *pending_message;
649
650 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
651 return;
652
653 about = GNUNET_CONTAINER_heap_walk_get_next (ctx.neighbor_min_heap);
654 to = GNUNET_CONTAINER_heap_get_random (ctx.neighbor_min_heap, GNUNET_CONTAINER_multihashmap_size(ctx.direct_neighbors));
655
656 if ((about != NULL) && (to != about->referrer /* split horizon */ ) &&
657#if SUPPORT_HIDING
658 (about->hidden == GNUNET_NO) &&
659#endif
660 (to != NULL) &&
661 (0 != memcmp (&about->identity,
662 &to->identity, sizeof (struct GNUNET_PeerIdentity))))
663 {
664#if DEBUG_DV
665 encPeerAbout = GNUNET_strdup(GNUNET_i2s(&about->identity));
666 encPeerTo = GNUNET_strdup(GNUNET_i2s(&to->identity));
667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
668 "%s: Sending info about peer %s to directly connected peer %s\n",
669 GNUNET_i2s(my_identity),
670 encPeerAbout, encPeerTo);
671#endif
672 pending_message = GNUNET_malloc(sizeof(struct PendingMessage));
673 pending_message->msg = GNUNET_malloc(sizeof(p2p_dv_MESSAGE_NeighborInfo));
674 message = (p2p_dv_MESSAGE_NeighborInfo *)pending_message->msg;
675 message->header.size = htons (sizeof (p2p_dv_MESSAGE_NeighborInfo));
676 message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_GOSSIP);
677 message->cost = htonl (about->cost);
678 message->neighbor_id = htonl (about->our_id);
679 memcpy (&message->neighbor,
680 &about->identity, sizeof (struct GNUNET_PeerIdentity));
681
682 pending_message->transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, default_dv_delay, &to->identity, sizeof(p2p_dv_MESSAGE_NeighborInfo), &core_transmit_notify, pending_message);
683
684 if (NULL == pending_message->transmit_handle)
685 {
686 GNUNET_free (pending_message->msg);
687 GNUNET_free (pending_message);
688 return;
689 }
690 /*coreAPI->ciphertext_send (&to->identity, &message.header,
691 GNUNET_DV_DHT_GOSSIP_PRIORITY,
692 ctx.send_interval);*/
693 }
694
695 gossip_task = GNUNET_SCHEDULER_add_delayed(sched, ctx.send_interval, &neighbor_send_task, NULL);
696 return;
475} 697}
476 698
477/** 699/**
@@ -840,6 +1062,9 @@ run (void *cls,
840 timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5); 1062 timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5);
841 sched = scheduler; 1063 sched = scheduler;
842 cfg = c; 1064 cfg = c;
1065
1066 client_transmit_timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5);
1067 default_dv_delay = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5);
843 GNUNET_SERVER_add_handlers (server, plugin_handlers); 1068 GNUNET_SERVER_add_handlers (server, plugin_handlers);
844 coreAPI = 1069 coreAPI =
845 GNUNET_CORE_connect (sched, 1070 GNUNET_CORE_connect (sched,
@@ -862,6 +1087,7 @@ run (void *cls,
862 1087
863 /* Scheduled the task to clean up when shutdown is called */ 1088 /* Scheduled the task to clean up when shutdown is called */
864 1089
1090 gossip_task = GNUNET_SCHEDULER_add_delayed(sched, ctx.send_interval, &neighbor_send_task, NULL);
865 cleanup_task = GNUNET_SCHEDULER_add_delayed (sched, 1091 cleanup_task = GNUNET_SCHEDULER_add_delayed (sched,
866 GNUNET_TIME_UNIT_FOREVER_REL, 1092 GNUNET_TIME_UNIT_FOREVER_REL,
867 &shutdown_task, 1093 &shutdown_task,