diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2010-12-02 11:59:56 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2010-12-02 11:59:56 +0000 |
commit | 614afe91d2c80b6fec4e6a090319c1a585944d75 (patch) | |
tree | ecd31dde4d596ec9c63fb5efde6243866c24bdc4 /src/transport/transport_api.c | |
parent | 318e4c9274fefbb546363633ea465f9f339cb828 (diff) | |
download | gnunet-614afe91d2c80b6fec4e6a090319c1a585944d75.tar.gz gnunet-614afe91d2c80b6fec4e6a090319c1a585944d75.zip |
Working version of transport service with ATS integration
all tests passing on my machine
Diffstat (limited to 'src/transport/transport_api.c')
-rw-r--r-- | src/transport/transport_api.c | 488 |
1 files changed, 174 insertions, 314 deletions
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index 4d7825701..643f8b0f4 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c | |||
@@ -60,11 +60,6 @@ | |||
60 | */ | 60 | */ |
61 | #define STOP_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | 61 | #define STOP_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) |
62 | 62 | ||
63 | /** | ||
64 | * How large to start with for the hashmap of neighbours. | ||
65 | */ | ||
66 | #define STARTING_NEIGHBOURS_SIZE 10 | ||
67 | |||
68 | 63 | ||
69 | /** | 64 | /** |
70 | * What stage are we in for transmission processing? | 65 | * What stage are we in for transmission processing? |
@@ -192,33 +187,18 @@ struct ControlMessage | |||
192 | 187 | ||
193 | }; | 188 | }; |
194 | 189 | ||
190 | |||
195 | /** | 191 | /** |
196 | * Context for storing information about attempted next transmission. | 192 | * Entry in linked list of all of our current neighbours. |
197 | */ | 193 | */ |
198 | struct TryTransmitContext | 194 | struct NeighbourList |
199 | { | 195 | { |
200 | 196 | ||
201 | /** | 197 | /** |
202 | * Main transport handle. | 198 | * This is a linked list. |
203 | */ | ||
204 | struct GNUNET_TRANSPORT_Handle *h; | ||
205 | |||
206 | /** | ||
207 | * Returned transmission handle. | ||
208 | */ | ||
209 | struct GNUNET_TRANSPORT_TransmitHandle *ret; | ||
210 | |||
211 | /** | ||
212 | * Time to retry the send task. | ||
213 | */ | 199 | */ |
214 | struct GNUNET_TIME_Relative retry_time; | 200 | struct NeighbourList *next; |
215 | }; | ||
216 | 201 | ||
217 | /** | ||
218 | * Entry in hash table of all of our current neighbours. | ||
219 | */ | ||
220 | struct NeighbourList | ||
221 | { | ||
222 | /** | 202 | /** |
223 | * Overall transport handle. | 203 | * Overall transport handle. |
224 | */ | 204 | */ |
@@ -255,11 +235,6 @@ struct NeighbourList | |||
255 | */ | 235 | */ |
256 | int is_connected; | 236 | int is_connected; |
257 | 237 | ||
258 | /** | ||
259 | * Are we in the middle of disconnecting the peer already? | ||
260 | */ | ||
261 | unsigned int in_disconnect; | ||
262 | |||
263 | }; | 238 | }; |
264 | 239 | ||
265 | 240 | ||
@@ -359,7 +334,7 @@ struct GNUNET_TRANSPORT_Handle | |||
359 | /** | 334 | /** |
360 | * Linked list of the current neighbours of this peer. | 335 | * Linked list of the current neighbours of this peer. |
361 | */ | 336 | */ |
362 | struct GNUNET_CONTAINER_MultiHashMap *neighbours; | 337 | struct NeighbourList *neighbours; |
363 | 338 | ||
364 | /** | 339 | /** |
365 | * Peer identity as assumed by this process, or all zeros. | 340 | * Peer identity as assumed by this process, or all zeros. |
@@ -396,6 +371,7 @@ struct GNUNET_TRANSPORT_Handle | |||
396 | }; | 371 | }; |
397 | 372 | ||
398 | 373 | ||
374 | // FIXME: replace with hash map! | ||
399 | /** | 375 | /** |
400 | * Get the neighbour list entry for the given peer | 376 | * Get the neighbour list entry for the given peer |
401 | * | 377 | * |
@@ -407,7 +383,13 @@ static struct NeighbourList * | |||
407 | neighbour_find (struct GNUNET_TRANSPORT_Handle *h, | 383 | neighbour_find (struct GNUNET_TRANSPORT_Handle *h, |
408 | const struct GNUNET_PeerIdentity *peer) | 384 | const struct GNUNET_PeerIdentity *peer) |
409 | { | 385 | { |
410 | return GNUNET_CONTAINER_multihashmap_get(h->neighbours, &peer->hashPubKey); | 386 | struct NeighbourList *pos; |
387 | |||
388 | pos = h->neighbours; | ||
389 | while ((pos != NULL) && | ||
390 | (0 != memcmp (peer, &pos->id, sizeof (struct GNUNET_PeerIdentity)))) | ||
391 | pos = pos->next; | ||
392 | return pos; | ||
411 | } | 393 | } |
412 | 394 | ||
413 | 395 | ||
@@ -436,90 +418,6 @@ quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
436 | 418 | ||
437 | 419 | ||
438 | /** | 420 | /** |
439 | * Iterator over hash map entries, attempt to schedule | ||
440 | * a transmission to entries in the neighbour hashmap. | ||
441 | * | ||
442 | * @param cls closure a TryTransmitContext | ||
443 | * @param key current key code | ||
444 | * @param value value in the hash map, the neighbour entry to consider | ||
445 | * @return GNUNET_YES if we should continue to | ||
446 | * iterate, | ||
447 | * GNUNET_NO if not. | ||
448 | */ | ||
449 | static int | ||
450 | try_schedule_transmission (void *cls, | ||
451 | const GNUNET_HashCode * key, | ||
452 | void *value) | ||
453 | { | ||
454 | struct NeighbourList *n = value; | ||
455 | struct TryTransmitContext *try_transmit_ctx = cls; | ||
456 | struct GNUNET_TIME_Relative duration; | ||
457 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
458 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
459 | struct GNUNET_TIME_Absolute duration_abs; | ||
460 | |||
461 | if (n->transmit_stage != TS_QUEUED) | ||
462 | return GNUNET_YES; /* not eligible, keep iterating */ | ||
463 | if (n->is_connected != GNUNET_YES) | ||
464 | return GNUNET_YES; /* keep iterating */ | ||
465 | |||
466 | th = &n->transmit_handle; | ||
467 | GNUNET_break (n == th->neighbour); | ||
468 | /* check outgoing quota */ | ||
469 | duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, | ||
470 | th->notify_size - sizeof (struct OutboundMessage)); | ||
471 | duration_abs = GNUNET_TIME_relative_to_absolute (duration); | ||
472 | if (th->timeout.abs_value < duration_abs.abs_value) | ||
473 | { | ||
474 | /* signal timeout! */ | ||
475 | #if DEBUG_TRANSPORT | ||
476 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
477 | "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n", | ||
478 | duration.rel_value, | ||
479 | GNUNET_i2s (&n->id)); | ||
480 | #endif | ||
481 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
482 | { | ||
483 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | ||
484 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
485 | } | ||
486 | n->transmit_stage = TS_NEW; | ||
487 | if (NULL != (notify = th->notify)) | ||
488 | { | ||
489 | th->notify = NULL; | ||
490 | GNUNET_assert (0 == notify (th->notify_cls, 0, NULL)); | ||
491 | } | ||
492 | return GNUNET_YES; /* keep iterating */ | ||
493 | } | ||
494 | if (duration.rel_value > 0) | ||
495 | { | ||
496 | #if DEBUG_TRANSPORT | ||
497 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
498 | "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n", | ||
499 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
500 | (unsigned int) th->notify_size - sizeof (struct OutboundMessage), | ||
501 | GNUNET_i2s (&n->id), | ||
502 | (unsigned long long) duration.rel_value); | ||
503 | #endif | ||
504 | try_transmit_ctx->retry_time = GNUNET_TIME_relative_min (try_transmit_ctx->retry_time, | ||
505 | duration); | ||
506 | return GNUNET_YES; /* keep iterating */ | ||
507 | } | ||
508 | #if DEBUG_TRANSPORT | ||
509 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
510 | "Have %u bytes of bandwidth available for transmission to `%4s' right now\n", | ||
511 | th->notify_size - sizeof (struct OutboundMessage), | ||
512 | GNUNET_i2s (&n->id)); | ||
513 | #endif | ||
514 | |||
515 | if ( (try_transmit_ctx->ret == NULL) || | ||
516 | (try_transmit_ctx->ret->priority < th->priority) ) | ||
517 | try_transmit_ctx->ret = th; | ||
518 | return GNUNET_YES; | ||
519 | } | ||
520 | |||
521 | |||
522 | /** | ||
523 | * Figure out which transmission to a peer can be done right now. | 421 | * Figure out which transmission to a peer can be done right now. |
524 | * If none can, schedule a task to call 'schedule_transmission' | 422 | * If none can, schedule a task to call 'schedule_transmission' |
525 | * whenever a peer transmission can be done in the future and | 423 | * whenever a peer transmission can be done in the future and |
@@ -532,24 +430,88 @@ try_schedule_transmission (void *cls, | |||
532 | static struct GNUNET_TRANSPORT_TransmitHandle * | 430 | static struct GNUNET_TRANSPORT_TransmitHandle * |
533 | schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h) | 431 | schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h) |
534 | { | 432 | { |
535 | struct TryTransmitContext try_transmit_ctx; | 433 | struct GNUNET_TRANSPORT_TransmitHandle *ret; |
434 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
435 | struct NeighbourList *n; | ||
436 | struct NeighbourList *next; | ||
437 | struct GNUNET_TIME_Relative retry_time; | ||
438 | struct GNUNET_TIME_Relative duration; | ||
439 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
536 | 440 | ||
537 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) | 441 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) |
538 | { | 442 | { |
539 | GNUNET_SCHEDULER_cancel (h->quota_task); | 443 | GNUNET_SCHEDULER_cancel (h->quota_task); |
540 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | 444 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; |
541 | } | 445 | } |
542 | try_transmit_ctx.h = h; | 446 | retry_time = GNUNET_TIME_UNIT_FOREVER_REL; |
543 | try_transmit_ctx.ret = NULL; | 447 | ret = NULL; |
544 | try_transmit_ctx.retry_time = GNUNET_TIME_UNIT_FOREVER_REL; | 448 | next = h->neighbours; |
545 | GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, | 449 | while (NULL != (n = next)) |
546 | &try_schedule_transmission, | 450 | { |
547 | &try_transmit_ctx); | 451 | next = n->next; |
548 | if (try_transmit_ctx.ret == NULL) | 452 | if (n->transmit_stage != TS_QUEUED) |
549 | h->quota_task = GNUNET_SCHEDULER_add_delayed (try_transmit_ctx.retry_time, | 453 | continue; /* not eligible */ |
454 | if (n->is_connected != GNUNET_YES) | ||
455 | continue; | ||
456 | |||
457 | th = &n->transmit_handle; | ||
458 | GNUNET_break (n == th->neighbour); | ||
459 | /* check outgoing quota */ | ||
460 | duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, | ||
461 | th->notify_size - sizeof (struct OutboundMessage)); | ||
462 | struct GNUNET_TIME_Absolute duration_abs = GNUNET_TIME_relative_to_absolute (duration); | ||
463 | if (th->timeout.abs_value < duration_abs.abs_value) | ||
464 | { | ||
465 | /* signal timeout! */ | ||
466 | #if DEBUG_TRANSPORT | ||
467 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
468 | "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n", | ||
469 | duration.rel_value, | ||
470 | GNUNET_i2s (&n->id)); | ||
471 | #endif | ||
472 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
473 | { | ||
474 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | ||
475 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
476 | } | ||
477 | n->transmit_stage = TS_NEW; | ||
478 | if (NULL != (notify = th->notify)) | ||
479 | { | ||
480 | th->notify = NULL; | ||
481 | GNUNET_assert (0 == notify (th->notify_cls, 0, NULL)); | ||
482 | } | ||
483 | continue; | ||
484 | } | ||
485 | if (duration.rel_value > 0) | ||
486 | { | ||
487 | #if DEBUG_TRANSPORT | ||
488 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
489 | "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n", | ||
490 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
491 | (unsigned int) th->notify_size - sizeof (struct OutboundMessage), | ||
492 | GNUNET_i2s (&n->id), | ||
493 | duration.rel_value); | ||
494 | #endif | ||
495 | retry_time = GNUNET_TIME_relative_min (retry_time, | ||
496 | duration); | ||
497 | continue; | ||
498 | } | ||
499 | #if DEBUG_TRANSPORT | ||
500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
501 | "Have %u bytes of bandwidth available for transmission to `%4s' right now\n", | ||
502 | th->notify_size - sizeof (struct OutboundMessage), | ||
503 | GNUNET_i2s (&n->id)); | ||
504 | #endif | ||
505 | |||
506 | if ( (ret == NULL) || | ||
507 | (ret->priority < th->priority) ) | ||
508 | ret = th; | ||
509 | } | ||
510 | if (ret == NULL) | ||
511 | h->quota_task = GNUNET_SCHEDULER_add_delayed (retry_time, | ||
550 | "a_transmit_ready, | 512 | "a_transmit_ready, |
551 | h); | 513 | h); |
552 | return try_transmit_ctx.ret; | 514 | return ret; |
553 | } | 515 | } |
554 | 516 | ||
555 | 517 | ||
@@ -815,39 +777,18 @@ schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, | |||
815 | } | 777 | } |
816 | 778 | ||
817 | 779 | ||
818 | /** | ||
819 | * FIXME: document | ||
820 | */ | ||
821 | struct SetQuotaContext | 780 | struct SetQuotaContext |
822 | { | 781 | { |
823 | /** | ||
824 | * FIXME: document | ||
825 | */ | ||
826 | struct GNUNET_TRANSPORT_Handle *handle; | 782 | struct GNUNET_TRANSPORT_Handle *handle; |
827 | 783 | ||
828 | /** | ||
829 | * FIXME: document | ||
830 | */ | ||
831 | struct GNUNET_PeerIdentity target; | 784 | struct GNUNET_PeerIdentity target; |
832 | 785 | ||
833 | /** | ||
834 | * FIXME: document | ||
835 | */ | ||
836 | GNUNET_SCHEDULER_Task cont; | 786 | GNUNET_SCHEDULER_Task cont; |
837 | 787 | ||
838 | /** | ||
839 | * Closure for 'cont'. | ||
840 | */ | ||
841 | void *cont_cls; | 788 | void *cont_cls; |
842 | 789 | ||
843 | /** | ||
844 | * FIXME: document | ||
845 | */ | ||
846 | struct GNUNET_TIME_Absolute timeout; | 790 | struct GNUNET_TIME_Absolute timeout; |
847 | 791 | ||
848 | /** | ||
849 | * FIXME: document | ||
850 | */ | ||
851 | struct GNUNET_BANDWIDTH_Value32NBO quota_in; | 792 | struct GNUNET_BANDWIDTH_Value32NBO quota_in; |
852 | }; | 793 | }; |
853 | 794 | ||
@@ -868,10 +809,9 @@ send_set_quota (void *cls, size_t size, void *buf) | |||
868 | 809 | ||
869 | if (buf == NULL) | 810 | if (buf == NULL) |
870 | { | 811 | { |
871 | if (sqc->cont != NULL) | 812 | GNUNET_SCHEDULER_add_continuation (sqc->cont, |
872 | GNUNET_SCHEDULER_add_continuation (sqc->cont, | 813 | sqc->cont_cls, |
873 | sqc->cont_cls, | 814 | GNUNET_SCHEDULER_REASON_TIMEOUT); |
874 | GNUNET_SCHEDULER_REASON_TIMEOUT); | ||
875 | GNUNET_free (sqc); | 815 | GNUNET_free (sqc); |
876 | return 0; | 816 | return 0; |
877 | } | 817 | } |
@@ -1150,21 +1090,9 @@ static void | |||
1150 | neighbour_free (struct NeighbourList *n) | 1090 | neighbour_free (struct NeighbourList *n) |
1151 | { | 1091 | { |
1152 | struct GNUNET_TRANSPORT_Handle *h; | 1092 | struct GNUNET_TRANSPORT_Handle *h; |
1093 | struct NeighbourList *prev; | ||
1094 | struct NeighbourList *pos; | ||
1153 | 1095 | ||
1154 | /* Added so task gets canceled when a disconnect is received! */ | ||
1155 | /* Method 1 | ||
1156 | if (n->transmit_handle.notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
1157 | { | ||
1158 | GNUNET_SCHEDULER_cancel(n->transmit_handle.notify_delay_task); | ||
1159 | n->transmit_handle.notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1160 | n->transmit_handle.notify = NULL; | ||
1161 | } | ||
1162 | */ | ||
1163 | /* NATE: if the above is not needed, then clearly this assertion | ||
1164 | should hold (I've checked the code and I'm pretty sure this is | ||
1165 | true. -CG | ||
1166 | FIXME: remove above comments once we've seen tests pass with the assert... */ | ||
1167 | GNUNET_assert (n->transmit_handle.notify_delay_task == GNUNET_SCHEDULER_NO_TASK); | ||
1168 | GNUNET_assert (n->transmit_handle.notify == NULL); | 1096 | GNUNET_assert (n->transmit_handle.notify == NULL); |
1169 | h = n->h; | 1097 | h = n->h; |
1170 | #if DEBUG_TRANSPORT | 1098 | #if DEBUG_TRANSPORT |
@@ -1175,10 +1103,17 @@ neighbour_free (struct NeighbourList *n) | |||
1175 | GNUNET_break (n->is_connected == GNUNET_NO); | 1103 | GNUNET_break (n->is_connected == GNUNET_NO); |
1176 | GNUNET_break (n->transmit_stage == TS_NEW); | 1104 | GNUNET_break (n->transmit_stage == TS_NEW); |
1177 | 1105 | ||
1178 | GNUNET_assert(GNUNET_YES == | 1106 | prev = NULL; |
1179 | GNUNET_CONTAINER_multihashmap_remove(h->neighbours, | 1107 | pos = h->neighbours; |
1180 | &n->id.hashPubKey, | 1108 | while (pos != n) |
1181 | n)); | 1109 | { |
1110 | prev = pos; | ||
1111 | pos = pos->next; | ||
1112 | } | ||
1113 | if (prev == NULL) | ||
1114 | h->neighbours = n->next; | ||
1115 | else | ||
1116 | prev->next = n->next; | ||
1182 | GNUNET_free (n); | 1117 | GNUNET_free (n); |
1183 | } | 1118 | } |
1184 | 1119 | ||
@@ -1199,14 +1134,6 @@ neighbour_disconnect (struct NeighbourList *n) | |||
1199 | #endif | 1134 | #endif |
1200 | GNUNET_break (n->is_connected == GNUNET_YES); | 1135 | GNUNET_break (n->is_connected == GNUNET_YES); |
1201 | n->is_connected = GNUNET_NO; | 1136 | n->is_connected = GNUNET_NO; |
1202 | /* FIXME: this 'in_disconnect' flag is dubious; we should define | ||
1203 | clearly what disconnect means for pending 'notify_transmit_ready' | ||
1204 | requests; maybe a good approach is to REQUIRE clients to | ||
1205 | call 'notify_transmit_ready_cancel' on pending requests on disconnect | ||
1206 | and otherwise FAIL HARD with an assertion failure before | ||
1207 | 'neighbour_free' right here (transmit_stage would be forced | ||
1208 | to 'TS_NEW') */ | ||
1209 | n->in_disconnect = GNUNET_YES; | ||
1210 | if (h->nd_cb != NULL) | 1137 | if (h->nd_cb != NULL) |
1211 | h->nd_cb (h->cls, &n->id); | 1138 | h->nd_cb (h->cls, &n->id); |
1212 | if (n->transmit_stage == TS_NEW) | 1139 | if (n->transmit_stage == TS_NEW) |
@@ -1226,35 +1153,6 @@ static void demultiplexer (void *cls, | |||
1226 | 1153 | ||
1227 | 1154 | ||
1228 | /** | 1155 | /** |
1229 | * Iterator over hash map entries, for getting rid of a neighbor | ||
1230 | * upon a reconnect call. | ||
1231 | * | ||
1232 | * @param cls closure (NULL) | ||
1233 | * @param key current key code | ||
1234 | * @param value value in the hash map, the neighbour entry to forget | ||
1235 | * @return GNUNET_YES if we should continue to | ||
1236 | * iterate, | ||
1237 | * GNUNET_NO if not. | ||
1238 | */ | ||
1239 | static int | ||
1240 | forget_neighbours (void *cls, | ||
1241 | const GNUNET_HashCode * key, | ||
1242 | void *value) | ||
1243 | { | ||
1244 | struct NeighbourList *n = value; | ||
1245 | |||
1246 | #if DEBUG_TRANSPORT_DISCONNECT | ||
1247 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1248 | "Disconnecting due to reconnect being called\n"); | ||
1249 | #endif | ||
1250 | if (n->is_connected) | ||
1251 | neighbour_disconnect (n); | ||
1252 | |||
1253 | return GNUNET_YES; | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | /** | ||
1258 | * Try again to connect to transport service. | 1156 | * Try again to connect to transport service. |
1259 | * | 1157 | * |
1260 | * @param cls the handle to the transport service | 1158 | * @param cls the handle to the transport service |
@@ -1266,6 +1164,8 @@ reconnect (void *cls, | |||
1266 | { | 1164 | { |
1267 | struct GNUNET_TRANSPORT_Handle *h = cls; | 1165 | struct GNUNET_TRANSPORT_Handle *h = cls; |
1268 | struct ControlMessage *pos; | 1166 | struct ControlMessage *pos; |
1167 | struct NeighbourList *n; | ||
1168 | struct NeighbourList *next; | ||
1269 | 1169 | ||
1270 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | 1170 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; |
1271 | if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | 1171 | if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) |
@@ -1274,10 +1174,18 @@ reconnect (void *cls, | |||
1274 | return; | 1174 | return; |
1275 | } | 1175 | } |
1276 | /* Forget about all neighbours that we used to be connected to */ | 1176 | /* Forget about all neighbours that we used to be connected to */ |
1277 | GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, | 1177 | n = h->neighbours; |
1278 | &forget_neighbours, | 1178 | while (NULL != n) |
1279 | NULL); | 1179 | { |
1280 | 1180 | #if DEBUG_TRANSPORT_DISCONNECT | |
1181 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1182 | "Disconnecting due to reconnect being called\n"); | ||
1183 | #endif | ||
1184 | next = n->next; | ||
1185 | if (n->is_connected) | ||
1186 | neighbour_disconnect (n); | ||
1187 | n = next; | ||
1188 | } | ||
1281 | #if DEBUG_TRANSPORT | 1189 | #if DEBUG_TRANSPORT |
1282 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1283 | "Connecting to transport service.\n"); | 1191 | "Connecting to transport service.\n"); |
@@ -1402,7 +1310,6 @@ send_request_connect_message(struct GNUNET_TRANSPORT_Handle *h, struct Neighbour | |||
1402 | GNUNET_TIME_UNIT_FOREVER_REL, &send_transport_request_connect, trcm); | 1310 | GNUNET_TIME_UNIT_FOREVER_REL, &send_transport_request_connect, trcm); |
1403 | } | 1311 | } |
1404 | 1312 | ||
1405 | |||
1406 | /** | 1313 | /** |
1407 | * Add neighbour to our list | 1314 | * Add neighbour to our list |
1408 | * | 1315 | * |
@@ -1429,58 +1336,15 @@ neighbour_add (struct GNUNET_TRANSPORT_Handle *h, | |||
1429 | #endif | 1336 | #endif |
1430 | n = GNUNET_malloc (sizeof (struct NeighbourList)); | 1337 | n = GNUNET_malloc (sizeof (struct NeighbourList)); |
1431 | n->id = *pid; | 1338 | n->id = *pid; |
1432 | n->h = h; | ||
1433 | GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, | 1339 | GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, |
1434 | GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, | 1340 | GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, |
1435 | MAX_BANDWIDTH_CARRY_S); | 1341 | MAX_BANDWIDTH_CARRY_S); |
1436 | GNUNET_CONTAINER_multihashmap_put (h->neighbours, | 1342 | n->next = h->neighbours; |
1437 | &pid->hashPubKey, | 1343 | n->h = h; |
1438 | n, | 1344 | h->neighbours = n; |
1439 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1440 | |||
1441 | return n; | ||
1442 | } | ||
1443 | |||
1444 | 1345 | ||
1445 | /** | ||
1446 | * Iterator over hash map entries, for deleting state of a neighbor. | ||
1447 | * | ||
1448 | * @param cls closure (NULL) | ||
1449 | * @param key current key code | ||
1450 | * @param value value in the hash map, the neighbour entry to delete | ||
1451 | * @return GNUNET_YES if we should continue to | ||
1452 | * iterate, | ||
1453 | * GNUNET_NO if not. | ||
1454 | */ | ||
1455 | static int | ||
1456 | delete_neighbours (void *cls, | ||
1457 | const GNUNET_HashCode * key, | ||
1458 | void *value) | ||
1459 | { | ||
1460 | struct NeighbourList *n = value; | ||
1461 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
1462 | 1346 | ||
1463 | switch (n->transmit_stage) | 1347 | return n; |
1464 | { | ||
1465 | case TS_NEW: | ||
1466 | case TS_TRANSMITTED: | ||
1467 | /* nothing to do */ | ||
1468 | break; | ||
1469 | case TS_QUEUED: | ||
1470 | case TS_TRANSMITTED_QUEUED: | ||
1471 | th = &n->transmit_handle; | ||
1472 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
1473 | { | ||
1474 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | ||
1475 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1476 | } | ||
1477 | GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); | ||
1478 | break; | ||
1479 | default: | ||
1480 | GNUNET_break (0); | ||
1481 | } | ||
1482 | GNUNET_free (n); | ||
1483 | return GNUNET_YES; | ||
1484 | } | 1348 | } |
1485 | 1349 | ||
1486 | 1350 | ||
@@ -1518,7 +1382,6 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
1518 | ret->nc_cb = nc; | 1382 | ret->nc_cb = nc; |
1519 | ret->nd_cb = nd; | 1383 | ret->nd_cb = nd; |
1520 | ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; | 1384 | ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; |
1521 | ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE); | ||
1522 | schedule_reconnect (ret); | 1385 | schedule_reconnect (ret); |
1523 | return ret; | 1386 | return ret; |
1524 | } | 1387 | } |
@@ -1530,6 +1393,8 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
1530 | void | 1393 | void |
1531 | GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) | 1394 | GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) |
1532 | { | 1395 | { |
1396 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
1397 | struct NeighbourList *n; | ||
1533 | struct HelloWaitList *hwl; | 1398 | struct HelloWaitList *hwl; |
1534 | struct GNUNET_CLIENT_Connection *client; | 1399 | struct GNUNET_CLIENT_Connection *client; |
1535 | struct ControlMessage *cm; | 1400 | struct ControlMessage *cm; |
@@ -1537,20 +1402,31 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) | |||
1537 | #if DEBUG_TRANSPORT | 1402 | #if DEBUG_TRANSPORT |
1538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); | 1403 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); |
1539 | #endif | 1404 | #endif |
1540 | /* FIXME: this flag is dubious, we should be able to do this | ||
1541 | more cleanly; also, we should probably do 'disconnect' | ||
1542 | callbacks for every connected peer here, i.e. by calling | ||
1543 | the iterator with 'forget_neighbours' instead of 'delete_neighbours'. | ||
1544 | */ | ||
1545 | |||
1546 | handle->in_disconnect = GNUNET_YES; | 1405 | handle->in_disconnect = GNUNET_YES; |
1547 | 1406 | while (NULL != (n = handle->neighbours)) | |
1548 | GNUNET_assert (GNUNET_SYSERR != | 1407 | { |
1549 | GNUNET_CONTAINER_multihashmap_iterate(handle->neighbours, | 1408 | handle->neighbours = n->next; |
1550 | &delete_neighbours, | 1409 | switch (n->transmit_stage) |
1551 | handle)); | 1410 | { |
1552 | GNUNET_CONTAINER_multihashmap_destroy (handle->neighbours); | 1411 | case TS_NEW: |
1553 | 1412 | case TS_TRANSMITTED: | |
1413 | /* nothing to do */ | ||
1414 | break; | ||
1415 | case TS_QUEUED: | ||
1416 | case TS_TRANSMITTED_QUEUED: | ||
1417 | th = &n->transmit_handle; | ||
1418 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
1419 | { | ||
1420 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | ||
1421 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1422 | } | ||
1423 | GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); | ||
1424 | break; | ||
1425 | default: | ||
1426 | GNUNET_break (0); | ||
1427 | } | ||
1428 | GNUNET_free (n); | ||
1429 | } | ||
1554 | while (NULL != (hwl = handle->hwl_head)) | 1430 | while (NULL != (hwl = handle->hwl_head)) |
1555 | { | 1431 | { |
1556 | handle->hwl_head = hwl->next; | 1432 | handle->hwl_head = hwl->next; |
@@ -1634,6 +1510,7 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1634 | struct NeighbourList *n; | 1510 | struct NeighbourList *n; |
1635 | struct GNUNET_PeerIdentity me; | 1511 | struct GNUNET_PeerIdentity me; |
1636 | uint16_t size; | 1512 | uint16_t size; |
1513 | uint32_t ats_count; | ||
1637 | 1514 | ||
1638 | if (h->client == NULL) | 1515 | if (h->client == NULL) |
1639 | { | 1516 | { |
@@ -1695,12 +1572,19 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1695 | } | 1572 | } |
1696 | break; | 1573 | break; |
1697 | case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: | 1574 | case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: |
1698 | if (size != sizeof (struct ConnectInfoMessage)) | 1575 | |
1576 | if (size < sizeof (struct ConnectInfoMessage)) | ||
1699 | { | 1577 | { |
1700 | GNUNET_break (0); | 1578 | GNUNET_break (0); |
1701 | break; | 1579 | break; |
1702 | } | 1580 | } |
1703 | cim = (const struct ConnectInfoMessage *) msg; | 1581 | cim = (const struct ConnectInfoMessage *) msg; |
1582 | ats_count = ntohl (cim->ats_count); | ||
1583 | if (size != sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) | ||
1584 | { | ||
1585 | GNUNET_break (0); | ||
1586 | break; | ||
1587 | } | ||
1704 | #if DEBUG_TRANSPORT | 1588 | #if DEBUG_TRANSPORT |
1705 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1589 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1706 | "Receiving `%s' message for `%4s'.\n", | 1590 | "Receiving `%s' message for `%4s'.\n", |
@@ -1708,29 +1592,16 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1708 | #endif | 1592 | #endif |
1709 | n = neighbour_find (h, &cim->id); | 1593 | n = neighbour_find (h, &cim->id); |
1710 | if (n == NULL) | 1594 | if (n == NULL) |
1711 | n = neighbour_add (h, | 1595 | n = neighbour_add (h, &cim->id); |
1712 | &cim->id); | ||
1713 | if (n == NULL) | 1596 | if (n == NULL) |
1714 | { | 1597 | return; |
1715 | GNUNET_break (0); | ||
1716 | return; | ||
1717 | } | ||
1718 | GNUNET_break (n->is_connected == GNUNET_NO); | 1598 | GNUNET_break (n->is_connected == GNUNET_NO); |
1719 | if (ntohl ((&cim->ats)[ntohl (cim->ats_count)].type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) | 1599 | n->is_connected = GNUNET_YES; |
1720 | { | 1600 | /* FIXME */ |
1721 | GNUNET_break (0); | ||
1722 | return; | ||
1723 | } | ||
1724 | fprintf(stderr,"transport_api GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT ats_count %u\n",ntohl (cim->ats_count)); | ||
1725 | n->is_connected = GNUNET_YES; | ||
1726 | if (h->nc_cb != NULL) | 1601 | if (h->nc_cb != NULL) |
1727 | h->nc_cb (h->cls, &n->id, | ||
1728 | NULL, | ||
1729 | 0); | ||
1730 | /* if (h->nc_cb != NULL) | ||
1731 | h->nc_cb (h->cls, &n->id, | 1602 | h->nc_cb (h->cls, &n->id, |
1732 | &(cim->ats), | 1603 | NULL,0); |
1733 | ntohl (cim->ats_count));*/ | 1604 | /* FIXEND */ |
1734 | break; | 1605 | break; |
1735 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: | 1606 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: |
1736 | if (size != sizeof (struct DisconnectInfoMessage)) | 1607 | if (size != sizeof (struct DisconnectInfoMessage)) |
@@ -1798,9 +1669,10 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1798 | } | 1669 | } |
1799 | im = (const struct InboundMessage *) msg; | 1670 | im = (const struct InboundMessage *) msg; |
1800 | GNUNET_break (0 == ntohl (im->reserved)); | 1671 | GNUNET_break (0 == ntohl (im->reserved)); |
1801 | GNUNET_assert(sizeof (struct InboundMessage) + ntohl(im->ats_count) * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + sizeof (struct GNUNET_MessageHeader) <= size); | 1672 | ats_count = ntohl(im->ats_count); |
1802 | imm = (const struct GNUNET_MessageHeader *) &((&im->ats)[ntohl(im->ats_count)+1]); | 1673 | //imm = (const struct GNUNET_MessageHeader *) &im[1]; |
1803 | if (ntohs (imm->size) + sizeof (struct InboundMessage) + ntohl(im->ats_count) * sizeof(struct GNUNET_TRANSPORT_ATS_Information) != size) | 1674 | imm = (const struct GNUNET_MessageHeader *) &((&(im->ats))[ats_count+1]); |
1675 | if (ntohs (imm->size) + sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) != size) | ||
1804 | { | 1676 | { |
1805 | GNUNET_break (0); | 1677 | GNUNET_break (0); |
1806 | break; | 1678 | break; |
@@ -1821,22 +1693,11 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1821 | GNUNET_break (0); | 1693 | GNUNET_break (0); |
1822 | break; | 1694 | break; |
1823 | } | 1695 | } |
1824 | if (ntohl ((&im->ats)[ntohl(im->ats_count)].type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) | 1696 | /* FIXME: */ |
1825 | { | 1697 | if (h->rec != NULL) |
1826 | GNUNET_break (0); | 1698 | h->rec (h->cls, &im->peer, imm, |
1827 | return; | 1699 | NULL, 0); |
1828 | } | 1700 | /* ENDFIX */ |
1829 | fprintf(stderr,"transport_api GNUNET_MESSAGE_TYPE_TRANSPORT_RECV ats_count %u\n",ntohl (im->ats_count)); | ||
1830 | if (h->rec != NULL) | ||
1831 | h->rec (h->cls, &im->peer, | ||
1832 | imm, | ||
1833 | NULL, | ||
1834 | 0); | ||
1835 | |||
1836 | /*h->rec (h->cls, &im->peer, | ||
1837 | imm, | ||
1838 | &im->ats, | ||
1839 | ntohl (im->ats_count));*/ | ||
1840 | break; | 1701 | break; |
1841 | default: | 1702 | default: |
1842 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1703 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
@@ -2025,7 +1886,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct | |||
2025 | n = th->neighbour; | 1886 | n = th->neighbour; |
2026 | #if DEBUG_TRANSPORT | 1887 | #if DEBUG_TRANSPORT |
2027 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1888 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2028 | "Transmission request of %u bytes to `%4s' was canceled.\n", | 1889 | "Transmission request of %u bytes to `%4s' was cancelled.\n", |
2029 | th->notify_size - sizeof (struct OutboundMessage), | 1890 | th->notify_size - sizeof (struct OutboundMessage), |
2030 | GNUNET_i2s (&n->id)); | 1891 | GNUNET_i2s (&n->id)); |
2031 | #endif | 1892 | #endif |
@@ -2041,8 +1902,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct | |||
2041 | break; | 1902 | break; |
2042 | case TS_QUEUED: | 1903 | case TS_QUEUED: |
2043 | n->transmit_stage = TS_NEW; | 1904 | n->transmit_stage = TS_NEW; |
2044 | if ( (n->in_disconnect == GNUNET_NO) && | 1905 | if (n->is_connected == GNUNET_NO) |
2045 | (n->is_connected == GNUNET_NO) ) | ||
2046 | neighbour_free (n); | 1906 | neighbour_free (n); |
2047 | break; | 1907 | break; |
2048 | case TS_TRANSMITTED: | 1908 | case TS_TRANSMITTED: |