From 614afe91d2c80b6fec4e6a090319c1a585944d75 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Thu, 2 Dec 2010 11:59:56 +0000 Subject: [PATCH] Working version of transport service with ATS integration all tests passing on my machine --- src/transport/gnunet-service-transport.c | 66 +-- src/transport/test_plugin_transport_http.c | 8 +- src/transport/test_transport_api.c | 30 +- .../test_transport_api_reliability.c | 6 +- src/transport/transport.h | 22 +- src/transport/transport_api.c | 488 +++++++----------- 6 files changed, 210 insertions(+), 410 deletions(-) diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 04c198676..3b645bb30 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -2222,11 +2222,9 @@ notify_clients_connect (const struct GNUNET_PeerIdentity *peer, GNUNET_NO); cim.header.size = htons (sizeof (struct ConnectInfoMessage)); cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); - cim.distance = htonl (distance); - cim.latency = GNUNET_TIME_relative_hton (latency); cim.ats_count = htonl(0); - cim.ats.type = htonl(0); - cim.ats.value = htonl(0); + cim.ats.type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); + cim.ats.value = htonl (0); memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity)); cpos = clients; while (cpos != NULL) @@ -3386,12 +3384,10 @@ schedule_next_ping (struct ForeignAddressList *fal) * * @param message the payload * @param n peer who claimed to be the sender - * @param ats ATS information - * @param ats_count numbers of elements following the ats struct (excluding the 0-terminator) */ static void handle_payload_message (const struct GNUNET_MessageHeader *message, - struct NeighbourList *n, struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) + struct NeighbourList *n) { struct InboundMessage *im; struct TransportClient *cpos; @@ -3446,21 +3442,24 @@ handle_payload_message (const struct GNUNET_MessageHeader *message, gettext_noop ("# payload received from other peers"), msize, GNUNET_NO); - /* transmit message to all clients */ - im = GNUNET_malloc (sizeof (struct InboundMessage) + ats_count * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + msize); - im->header.size = htons (sizeof (struct InboundMessage) + ats_count * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + msize); + uint32_t ats_count = 2; + uint16_t size = sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + msize; + + im = GNUNET_malloc (size); + im->header.size = htons (size); im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); im->peer = n->id; im->ats_count = htonl(ats_count); - /* insert ATS elements */ - memcpy (&(im->ats), ats, ats_count * sizeof(struct GNUNET_TRANSPORT_ATS_Information)); - /* insert ATS terminator */ - (&im->ats)[ats_count].type = htonl(0); - (&im->ats)[ats_count].value = htonl(0); - /* insert msg after terminator */ - memcpy (&(&im->ats)[ats_count+1], message, msize); - + /* Setting ATS data */ + (&(im->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE); + (&(im->ats))[0].value = htonl (n->distance); + (&(im->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY); + (&(im->ats))[1].value = htonl ((uint32_t) n->latency.rel_value); + (&(im->ats))[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); + (&(im->ats))[ats_count].value = htonl (0); + + memcpy (&((&(im->ats))[ats_count+1]), message, msize); cpos = clients; while (cpos != NULL) { @@ -3681,17 +3680,7 @@ check_pending_validation (void *cls, if (NULL != (prem = n->pre_connect_message_buffer)) { n->pre_connect_message_buffer = NULL; - struct GNUNET_TRANSPORT_ATS_Information * ats = GNUNET_malloc(2 * sizeof(struct GNUNET_TRANSPORT_ATS_Information)); - ats[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY); - if (n->latency.rel_value <= UINT32_MAX) - ats[0].value = htonl((uint32_t) n->latency.rel_value); - else - ats[0].value = htonl(UINT32_MAX); - ats[1].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE); - ats[1].value = htonl(n->distance); - //handle_payload_message (prem, n, NULL, 0); - handle_payload_message (prem, n, ats, 2); - GNUNET_free (ats); + handle_payload_message (prem, n); GNUNET_free (prem); } } @@ -4696,7 +4685,6 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer, struct ForeignAddressList *peer_address; uint16_t msize; struct NeighbourList *n; - struct GNUNET_TRANSPORT_ATS_Information * ats; struct GNUNET_TIME_Relative ret; if (is_blacklisted (peer, plugin)) return GNUNET_TIME_UNIT_FOREVER_REL; @@ -4782,17 +4770,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer, handle_pong (plugin, message, peer, sender_address, sender_address_len); break; default: - ats = GNUNET_malloc(2 * sizeof(struct GNUNET_TRANSPORT_ATS_Information)); - ats[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY); - if (n->latency.rel_value <= UINT32_MAX) - ats[0].value = htonl((uint32_t) n->latency.rel_value); - else - ats[0].value = htonl(UINT32_MAX); - ats[1].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE); - ats[1].value = htonl(n->distance); - //handle_payload_message (message, n, NULL, 0); - handle_payload_message (message, n, ats, 2); - GNUNET_free(ats); + handle_payload_message (message, n); break; } } @@ -4875,16 +4853,14 @@ handle_start (void *cls, cim.header.size = htons (sizeof (struct ConnectInfoMessage)); cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); cim.ats_count = htonl(0); - cim.ats.type = htonl(0); - cim.ats.value = htonl(0); + cim.ats.type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); + cim.ats.value = htonl (0); n = neighbours; while (n != NULL) { if (GNUNET_YES == n->received_pong) { cim.id = n->id; - cim.latency = GNUNET_TIME_relative_hton (n->latency); - cim.distance = htonl (n->distance); transmit_to_client (c, &cim.header, GNUNET_NO); } n = n->next; diff --git a/src/transport/test_plugin_transport_http.c b/src/transport/test_plugin_transport_http.c index a711f6772..6b6463f1a 100644 --- a/src/transport/test_plugin_transport_http.c +++ b/src/transport/test_plugin_transport_http.c @@ -1311,7 +1311,7 @@ main (int argc, char *const *argv) }; int ret; char *const argv_prog[] = { - "test_plugin_transport_http", + "test_gnunet_transport_plugin_http", "-c", "test_plugin_transport_data_http.conf", "-L", @@ -1322,7 +1322,7 @@ main (int argc, char *const *argv) #endif NULL }; - GNUNET_log_setup ("test_plugin_transport_http", + GNUNET_log_setup ("test_gnunet_transport_plugin_http", #if VERBOSE "DEBUG", #else @@ -1336,9 +1336,9 @@ main (int argc, char *const *argv) "test_gnunet_transport_plugin_http", "testcase", options, &run, NULL)) ? GNUNET_NO : GNUNET_YES; - GNUNET_DISK_directory_remove ("/tmp/test_plugin_transport_http"); + GNUNET_DISK_directory_remove ("/tmp/test_gnunet_transport_plugin_http"); return fail; } -/* end of test_plugin_transport_http.c */ +/* end of test_gnunet_transport_plugin_http.c */ diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c index 1f9c56974..f05b3cb5d 100644 --- a/src/transport/test_transport_api.c +++ b/src/transport/test_transport_api.c @@ -82,8 +82,6 @@ static int is_http; static int is_https; -static int is_multi_protocol; - static GNUNET_SCHEDULER_TaskIdentifier die_task; static char * key_file_p1; @@ -142,7 +140,8 @@ static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) + const struct GNUNET_TRANSPORT_ATS_Information *ats, + uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok is (%d)!\n", ok); @@ -187,7 +186,8 @@ notify_ready (void *cls, size_t size, void *buf) static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) + const struct GNUNET_TRANSPORT_ATS_Information *ats, + uint32_t ats_count) { if (cls == &p1) { @@ -346,12 +346,6 @@ run (void *cls, die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); - if (is_multi_protocol) - { - setup_peer (&p1, "test_transport_api_multi_peer1.conf"); - setup_peer (&p2, "test_transport_api_multi_peer2.conf"); - } - if (is_udp) { setup_peer (&p1, "test_transport_api_udp_peer1.conf"); @@ -567,22 +561,10 @@ main (int argc, char *argv[]) { is_http = GNUNET_YES; } - else if (strstr(argv[0], "multi") != NULL) - { - is_multi_protocol = GNUNET_YES; - } ret = check (); - if (is_multi_protocol) - { - GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-multi-peer-1/"); - GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-multi-peer-2/"); - } - else - { - GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-1"); - GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-2"); - } + GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-1"); + GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-2"); return ret; } diff --git a/src/transport/test_transport_api_reliability.c b/src/transport/test_transport_api_reliability.c index e67399f71..31c597008 100644 --- a/src/transport/test_transport_api_reliability.c +++ b/src/transport/test_transport_api_reliability.c @@ -185,7 +185,8 @@ static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) + const struct GNUNET_TRANSPORT_ATS_Information *ats, + uint32_t ats_count) { static int n; unsigned int s; @@ -323,7 +324,8 @@ notify_ready (void *cls, size_t size, void *buf) static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) + const struct GNUNET_TRANSPORT_ATS_Information *ats, + uint32_t ats_count) { if (cls == &p1) { diff --git a/src/transport/transport.h b/src/transport/transport.h index 8f22abd18..595fcf51b 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -89,17 +89,7 @@ struct ConnectInfoMessage * Number of ATS key-value pairs that follow this struct * (excluding the 0-terminator). */ - uint32_t ats_count GNUNET_PACKED; - - /** - * Transport distance metric (i.e. hops for DV) - */ - uint32_t distance; - - /** - * Latency estimate. - */ - struct GNUNET_TIME_RelativeNBO latency; + uint32_t ats_count; /** * Identity of the new neighbour. @@ -206,21 +196,11 @@ struct InboundMessage */ uint32_t ats_count GNUNET_PACKED; - /** - * Latency estimate. - */ - //struct GNUNET_TIME_RelativeNBO latency; - /** * Which peer sent the message? */ struct GNUNET_PeerIdentity peer; - /** - * Distance metric. - */ - //uint32_t distance; - /** * First of the ATS information blocks (we must have at least * one due to the 0-termination requirement). 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 @@ */ #define STOP_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) -/** - * How large to start with for the hashmap of neighbours. - */ -#define STARTING_NEIGHBOURS_SIZE 10 - /** * What stage are we in for transmission processing? @@ -192,33 +187,18 @@ struct ControlMessage }; + /** - * Context for storing information about attempted next transmission. + * Entry in linked list of all of our current neighbours. */ -struct TryTransmitContext +struct NeighbourList { /** - * Main transport handle. - */ - struct GNUNET_TRANSPORT_Handle *h; - - /** - * Returned transmission handle. - */ - struct GNUNET_TRANSPORT_TransmitHandle *ret; - - /** - * Time to retry the send task. + * This is a linked list. */ - struct GNUNET_TIME_Relative retry_time; -}; + struct NeighbourList *next; -/** - * Entry in hash table of all of our current neighbours. - */ -struct NeighbourList -{ /** * Overall transport handle. */ @@ -255,11 +235,6 @@ struct NeighbourList */ int is_connected; - /** - * Are we in the middle of disconnecting the peer already? - */ - unsigned int in_disconnect; - }; @@ -359,7 +334,7 @@ struct GNUNET_TRANSPORT_Handle /** * Linked list of the current neighbours of this peer. */ - struct GNUNET_CONTAINER_MultiHashMap *neighbours; + struct NeighbourList *neighbours; /** * Peer identity as assumed by this process, or all zeros. @@ -396,6 +371,7 @@ struct GNUNET_TRANSPORT_Handle }; +// FIXME: replace with hash map! /** * Get the neighbour list entry for the given peer * @@ -407,7 +383,13 @@ static struct NeighbourList * neighbour_find (struct GNUNET_TRANSPORT_Handle *h, const struct GNUNET_PeerIdentity *peer) { - return GNUNET_CONTAINER_multihashmap_get(h->neighbours, &peer->hashPubKey); + struct NeighbourList *pos; + + pos = h->neighbours; + while ((pos != NULL) && + (0 != memcmp (peer, &pos->id, sizeof (struct GNUNET_PeerIdentity)))) + pos = pos->next; + return pos; } @@ -435,90 +417,6 @@ quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -/** - * Iterator over hash map entries, attempt to schedule - * a transmission to entries in the neighbour hashmap. - * - * @param cls closure a TryTransmitContext - * @param key current key code - * @param value value in the hash map, the neighbour entry to consider - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -try_schedule_transmission (void *cls, - const GNUNET_HashCode * key, - void *value) -{ - struct NeighbourList *n = value; - struct TryTransmitContext *try_transmit_ctx = cls; - struct GNUNET_TIME_Relative duration; - GNUNET_CONNECTION_TransmitReadyNotify notify; - struct GNUNET_TRANSPORT_TransmitHandle *th; - struct GNUNET_TIME_Absolute duration_abs; - - if (n->transmit_stage != TS_QUEUED) - return GNUNET_YES; /* not eligible, keep iterating */ - if (n->is_connected != GNUNET_YES) - return GNUNET_YES; /* keep iterating */ - - th = &n->transmit_handle; - GNUNET_break (n == th->neighbour); - /* check outgoing quota */ - duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, - th->notify_size - sizeof (struct OutboundMessage)); - duration_abs = GNUNET_TIME_relative_to_absolute (duration); - if (th->timeout.abs_value < duration_abs.abs_value) - { - /* signal timeout! */ -#if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n", - duration.rel_value, - GNUNET_i2s (&n->id)); -#endif - if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (th->notify_delay_task); - th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; - } - n->transmit_stage = TS_NEW; - if (NULL != (notify = th->notify)) - { - th->notify = NULL; - GNUNET_assert (0 == notify (th->notify_cls, 0, NULL)); - } - return GNUNET_YES; /* keep iterating */ - } - if (duration.rel_value > 0) - { -#if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n", - (unsigned int) n->out_tracker.available_bytes_per_s__, - (unsigned int) th->notify_size - sizeof (struct OutboundMessage), - GNUNET_i2s (&n->id), - (unsigned long long) duration.rel_value); -#endif - try_transmit_ctx->retry_time = GNUNET_TIME_relative_min (try_transmit_ctx->retry_time, - duration); - return GNUNET_YES; /* keep iterating */ - } -#if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Have %u bytes of bandwidth available for transmission to `%4s' right now\n", - th->notify_size - sizeof (struct OutboundMessage), - GNUNET_i2s (&n->id)); -#endif - - if ( (try_transmit_ctx->ret == NULL) || - (try_transmit_ctx->ret->priority < th->priority) ) - try_transmit_ctx->ret = th; - return GNUNET_YES; -} - - /** * Figure out which transmission to a peer can be done right now. * If none can, schedule a task to call 'schedule_transmission' @@ -532,24 +430,88 @@ try_schedule_transmission (void *cls, static struct GNUNET_TRANSPORT_TransmitHandle * schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h) { - struct TryTransmitContext try_transmit_ctx; + struct GNUNET_TRANSPORT_TransmitHandle *ret; + struct GNUNET_TRANSPORT_TransmitHandle *th; + struct NeighbourList *n; + struct NeighbourList *next; + struct GNUNET_TIME_Relative retry_time; + struct GNUNET_TIME_Relative duration; + GNUNET_CONNECTION_TransmitReadyNotify notify; if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->quota_task); h->quota_task = GNUNET_SCHEDULER_NO_TASK; } - try_transmit_ctx.h = h; - try_transmit_ctx.ret = NULL; - try_transmit_ctx.retry_time = GNUNET_TIME_UNIT_FOREVER_REL; - GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, - &try_schedule_transmission, - &try_transmit_ctx); - if (try_transmit_ctx.ret == NULL) - h->quota_task = GNUNET_SCHEDULER_add_delayed (try_transmit_ctx.retry_time, + retry_time = GNUNET_TIME_UNIT_FOREVER_REL; + ret = NULL; + next = h->neighbours; + while (NULL != (n = next)) + { + next = n->next; + if (n->transmit_stage != TS_QUEUED) + continue; /* not eligible */ + if (n->is_connected != GNUNET_YES) + continue; + + th = &n->transmit_handle; + GNUNET_break (n == th->neighbour); + /* check outgoing quota */ + duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, + th->notify_size - sizeof (struct OutboundMessage)); + struct GNUNET_TIME_Absolute duration_abs = GNUNET_TIME_relative_to_absolute (duration); + if (th->timeout.abs_value < duration_abs.abs_value) + { + /* signal timeout! */ +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n", + duration.rel_value, + GNUNET_i2s (&n->id)); +#endif + if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (th->notify_delay_task); + th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; + } + n->transmit_stage = TS_NEW; + if (NULL != (notify = th->notify)) + { + th->notify = NULL; + GNUNET_assert (0 == notify (th->notify_cls, 0, NULL)); + } + continue; + } + if (duration.rel_value > 0) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n", + (unsigned int) n->out_tracker.available_bytes_per_s__, + (unsigned int) th->notify_size - sizeof (struct OutboundMessage), + GNUNET_i2s (&n->id), + duration.rel_value); +#endif + retry_time = GNUNET_TIME_relative_min (retry_time, + duration); + continue; + } +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Have %u bytes of bandwidth available for transmission to `%4s' right now\n", + th->notify_size - sizeof (struct OutboundMessage), + GNUNET_i2s (&n->id)); +#endif + + if ( (ret == NULL) || + (ret->priority < th->priority) ) + ret = th; + } + if (ret == NULL) + h->quota_task = GNUNET_SCHEDULER_add_delayed (retry_time, "a_transmit_ready, h); - return try_transmit_ctx.ret; + return ret; } @@ -815,39 +777,18 @@ schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, } -/** - * FIXME: document - */ struct SetQuotaContext { - /** - * FIXME: document - */ struct GNUNET_TRANSPORT_Handle *handle; - /** - * FIXME: document - */ struct GNUNET_PeerIdentity target; - /** - * FIXME: document - */ GNUNET_SCHEDULER_Task cont; - /** - * Closure for 'cont'. - */ void *cont_cls; - /** - * FIXME: document - */ struct GNUNET_TIME_Absolute timeout; - /** - * FIXME: document - */ struct GNUNET_BANDWIDTH_Value32NBO quota_in; }; @@ -868,10 +809,9 @@ send_set_quota (void *cls, size_t size, void *buf) if (buf == NULL) { - if (sqc->cont != NULL) - GNUNET_SCHEDULER_add_continuation (sqc->cont, - sqc->cont_cls, - GNUNET_SCHEDULER_REASON_TIMEOUT); + GNUNET_SCHEDULER_add_continuation (sqc->cont, + sqc->cont_cls, + GNUNET_SCHEDULER_REASON_TIMEOUT); GNUNET_free (sqc); return 0; } @@ -1150,21 +1090,9 @@ static void neighbour_free (struct NeighbourList *n) { struct GNUNET_TRANSPORT_Handle *h; + struct NeighbourList *prev; + struct NeighbourList *pos; - /* Added so task gets canceled when a disconnect is received! */ - /* Method 1 - if (n->transmit_handle.notify_delay_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel(n->transmit_handle.notify_delay_task); - n->transmit_handle.notify_delay_task = GNUNET_SCHEDULER_NO_TASK; - n->transmit_handle.notify = NULL; - } - */ - /* NATE: if the above is not needed, then clearly this assertion - should hold (I've checked the code and I'm pretty sure this is - true. -CG - FIXME: remove above comments once we've seen tests pass with the assert... */ - GNUNET_assert (n->transmit_handle.notify_delay_task == GNUNET_SCHEDULER_NO_TASK); GNUNET_assert (n->transmit_handle.notify == NULL); h = n->h; #if DEBUG_TRANSPORT @@ -1175,10 +1103,17 @@ neighbour_free (struct NeighbourList *n) GNUNET_break (n->is_connected == GNUNET_NO); GNUNET_break (n->transmit_stage == TS_NEW); - GNUNET_assert(GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove(h->neighbours, - &n->id.hashPubKey, - n)); + prev = NULL; + pos = h->neighbours; + while (pos != n) + { + prev = pos; + pos = pos->next; + } + if (prev == NULL) + h->neighbours = n->next; + else + prev->next = n->next; GNUNET_free (n); } @@ -1199,14 +1134,6 @@ neighbour_disconnect (struct NeighbourList *n) #endif GNUNET_break (n->is_connected == GNUNET_YES); n->is_connected = GNUNET_NO; - /* FIXME: this 'in_disconnect' flag is dubious; we should define - clearly what disconnect means for pending 'notify_transmit_ready' - requests; maybe a good approach is to REQUIRE clients to - call 'notify_transmit_ready_cancel' on pending requests on disconnect - and otherwise FAIL HARD with an assertion failure before - 'neighbour_free' right here (transmit_stage would be forced - to 'TS_NEW') */ - n->in_disconnect = GNUNET_YES; if (h->nd_cb != NULL) h->nd_cb (h->cls, &n->id); if (n->transmit_stage == TS_NEW) @@ -1225,35 +1152,6 @@ static void demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg); -/** - * Iterator over hash map entries, for getting rid of a neighbor - * upon a reconnect call. - * - * @param cls closure (NULL) - * @param key current key code - * @param value value in the hash map, the neighbour entry to forget - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -forget_neighbours (void *cls, - const GNUNET_HashCode * key, - void *value) -{ - struct NeighbourList *n = value; - -#if DEBUG_TRANSPORT_DISCONNECT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Disconnecting due to reconnect being called\n"); -#endif - if (n->is_connected) - neighbour_disconnect (n); - - return GNUNET_YES; -} - - /** * Try again to connect to transport service. * @@ -1266,6 +1164,8 @@ reconnect (void *cls, { struct GNUNET_TRANSPORT_Handle *h = cls; struct ControlMessage *pos; + struct NeighbourList *n; + struct NeighbourList *next; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) @@ -1274,10 +1174,18 @@ reconnect (void *cls, return; } /* Forget about all neighbours that we used to be connected to */ - GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, - &forget_neighbours, - NULL); - + n = h->neighbours; + while (NULL != n) + { +#if DEBUG_TRANSPORT_DISCONNECT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting due to reconnect being called\n"); +#endif + next = n->next; + if (n->is_connected) + neighbour_disconnect (n); + n = next; + } #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service.\n"); @@ -1402,7 +1310,6 @@ send_request_connect_message(struct GNUNET_TRANSPORT_Handle *h, struct Neighbour GNUNET_TIME_UNIT_FOREVER_REL, &send_transport_request_connect, trcm); } - /** * Add neighbour to our list * @@ -1429,58 +1336,15 @@ neighbour_add (struct GNUNET_TRANSPORT_Handle *h, #endif n = GNUNET_malloc (sizeof (struct NeighbourList)); n->id = *pid; - n->h = h; GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, MAX_BANDWIDTH_CARRY_S); - GNUNET_CONTAINER_multihashmap_put (h->neighbours, - &pid->hashPubKey, - n, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); - - return n; -} - + n->next = h->neighbours; + n->h = h; + h->neighbours = n; -/** - * Iterator over hash map entries, for deleting state of a neighbor. - * - * @param cls closure (NULL) - * @param key current key code - * @param value value in the hash map, the neighbour entry to delete - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -delete_neighbours (void *cls, - const GNUNET_HashCode * key, - void *value) -{ - struct NeighbourList *n = value; - struct GNUNET_TRANSPORT_TransmitHandle *th; - switch (n->transmit_stage) - { - case TS_NEW: - case TS_TRANSMITTED: - /* nothing to do */ - break; - case TS_QUEUED: - case TS_TRANSMITTED_QUEUED: - th = &n->transmit_handle; - if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (th->notify_delay_task); - th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); - break; - default: - GNUNET_break (0); - } - GNUNET_free (n); - return GNUNET_YES; + return n; } @@ -1518,7 +1382,6 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, ret->nc_cb = nc; ret->nd_cb = nd; ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; - ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE); schedule_reconnect (ret); return ret; } @@ -1530,6 +1393,8 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) { + struct GNUNET_TRANSPORT_TransmitHandle *th; + struct NeighbourList *n; struct HelloWaitList *hwl; struct GNUNET_CLIENT_Connection *client; struct ControlMessage *cm; @@ -1537,20 +1402,31 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); #endif - /* FIXME: this flag is dubious, we should be able to do this - more cleanly; also, we should probably do 'disconnect' - callbacks for every connected peer here, i.e. by calling - the iterator with 'forget_neighbours' instead of 'delete_neighbours'. - */ - handle->in_disconnect = GNUNET_YES; - - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap_iterate(handle->neighbours, - &delete_neighbours, - handle)); - GNUNET_CONTAINER_multihashmap_destroy (handle->neighbours); - + while (NULL != (n = handle->neighbours)) + { + handle->neighbours = n->next; + switch (n->transmit_stage) + { + case TS_NEW: + case TS_TRANSMITTED: + /* nothing to do */ + break; + case TS_QUEUED: + case TS_TRANSMITTED_QUEUED: + th = &n->transmit_handle; + if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (th->notify_delay_task); + th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); + break; + default: + GNUNET_break (0); + } + GNUNET_free (n); + } while (NULL != (hwl = handle->hwl_head)) { handle->hwl_head = hwl->next; @@ -1634,6 +1510,7 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) struct NeighbourList *n; struct GNUNET_PeerIdentity me; uint16_t size; + uint32_t ats_count; if (h->client == NULL) { @@ -1695,12 +1572,19 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: - if (size != sizeof (struct ConnectInfoMessage)) + + if (size < sizeof (struct ConnectInfoMessage)) { GNUNET_break (0); break; } cim = (const struct ConnectInfoMessage *) msg; + ats_count = ntohl (cim->ats_count); + if (size != sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) + { + GNUNET_break (0); + break; + } #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s'.\n", @@ -1708,29 +1592,16 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) #endif n = neighbour_find (h, &cim->id); if (n == NULL) - n = neighbour_add (h, - &cim->id); + n = neighbour_add (h, &cim->id); if (n == NULL) - { - GNUNET_break (0); - return; - } + return; GNUNET_break (n->is_connected == GNUNET_NO); - if (ntohl ((&cim->ats)[ntohl (cim->ats_count)].type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) - { - GNUNET_break (0); - return; - } - fprintf(stderr,"transport_api GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT ats_count %u\n",ntohl (cim->ats_count)); - n->is_connected = GNUNET_YES; + n->is_connected = GNUNET_YES; + /* FIXME */ if (h->nc_cb != NULL) - h->nc_cb (h->cls, &n->id, - NULL, - 0); - /* if (h->nc_cb != NULL) h->nc_cb (h->cls, &n->id, - &(cim->ats), - ntohl (cim->ats_count));*/ + NULL,0); + /* FIXEND */ break; case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: if (size != sizeof (struct DisconnectInfoMessage)) @@ -1798,9 +1669,10 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) } im = (const struct InboundMessage *) msg; GNUNET_break (0 == ntohl (im->reserved)); - GNUNET_assert(sizeof (struct InboundMessage) + ntohl(im->ats_count) * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + sizeof (struct GNUNET_MessageHeader) <= size); - imm = (const struct GNUNET_MessageHeader *) &((&im->ats)[ntohl(im->ats_count)+1]); - if (ntohs (imm->size) + sizeof (struct InboundMessage) + ntohl(im->ats_count) * sizeof(struct GNUNET_TRANSPORT_ATS_Information) != size) + ats_count = ntohl(im->ats_count); + //imm = (const struct GNUNET_MessageHeader *) &im[1]; + imm = (const struct GNUNET_MessageHeader *) &((&(im->ats))[ats_count+1]); + if (ntohs (imm->size) + sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) != size) { GNUNET_break (0); break; @@ -1821,22 +1693,11 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) GNUNET_break (0); break; } - if (ntohl ((&im->ats)[ntohl(im->ats_count)].type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) - { - GNUNET_break (0); - return; - } - fprintf(stderr,"transport_api GNUNET_MESSAGE_TYPE_TRANSPORT_RECV ats_count %u\n",ntohl (im->ats_count)); - if (h->rec != NULL) - h->rec (h->cls, &im->peer, - imm, - NULL, - 0); - - /*h->rec (h->cls, &im->peer, - imm, - &im->ats, - ntohl (im->ats_count));*/ + /* FIXME: */ + if (h->rec != NULL) + h->rec (h->cls, &im->peer, imm, + NULL, 0); + /* ENDFIX */ break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -2025,7 +1886,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct n = th->neighbour; #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmission request of %u bytes to `%4s' was canceled.\n", + "Transmission request of %u bytes to `%4s' was cancelled.\n", th->notify_size - sizeof (struct OutboundMessage), GNUNET_i2s (&n->id)); #endif @@ -2041,8 +1902,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct break; case TS_QUEUED: n->transmit_stage = TS_NEW; - if ( (n->in_disconnect == GNUNET_NO) && - (n->is_connected == GNUNET_NO) ) + if (n->is_connected == GNUNET_NO) neighbour_free (n); break; case TS_TRANSMITTED: -- 2.25.1