From af174b47bc58e51c3d5616776e3a540462ccec11 Mon Sep 17 00:00:00 2001 From: "Nathan S. Evans" Date: Fri, 29 Jan 2010 15:36:37 +0000 Subject: [PATCH] hopefully partially fixing non worky problems on various machines. but since I haven't tested it on any other machines, we shall see if this is the case. Previous issues likely related to the ack_received stuff which was still present which caused tcp connections to have undesirable behavior --- src/transport/gnunet-service-transport.c | 112 +++++++++++++---------- src/transport/test_transport_api.c | 20 ++-- src/transport/transport.h | 2 +- src/transport/transport_api.c | 107 ++++++++++++++++++++-- 4 files changed, 177 insertions(+), 64 deletions(-) diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index fde9d8128..ff2dc2630 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -1122,62 +1122,57 @@ find_ready_address(struct NeighborList *neighbor) { struct ReadyList *head = neighbor->plugins; struct PeerAddressList *addresses; + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_TIME_Relative min_latency = GNUNET_TIME_relative_get_forever(); + struct PeerAddressList *best_address; + + best_address = NULL; while (head != NULL) { addresses = head->addresses; - while ((addresses != NULL) && - ((addresses->connected != GNUNET_YES) || - (addresses->transmit_ready != GNUNET_YES))) - { - addresses = addresses->next; - } - if (addresses != NULL) + while (addresses != NULL) { + if ((addresses->timeout.value < now.value) && (addresses->connected == GNUNET_YES)) + { #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Found ready address, connected is %d\n", - addresses->connected); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Marking long-time inactive connection to `%4s' as down.\n", + GNUNET_i2s (&addresses->ready_list->neighbor->id)); #endif - return addresses; + addresses->connected = GNUNET_NO; + } + addresses = addresses->next; } - - head = head->next; - } - return NULL; - -#if 0 /* Do some checks to keep everything sane, return lowest latency connection */ - while (pos != NULL) - { - /* set plugins that are inactive for a long time back to disconnected */ - if ((pos->timeout.value < now.value) && (pos->connected == GNUNET_YES)) + addresses = head->addresses; + while (addresses != NULL) { + if ((addresses->connected == GNUNET_YES) && + (addresses->transmit_ready == GNUNET_YES) && + ((addresses->latency.value < min_latency.value) || (best_address == NULL))) + { #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Marking long-time inactive connection to `%4s' as down.\n", - GNUNET_i2s (&neighbor->id)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found address with latency %llu, setting as best found yet!\n", + addresses->latency.value); #endif - pos->connected = GNUNET_NO; + best_address = addresses; + } + addresses = addresses->next; } - if (GNUNET_YES == pos->transmit_ready) - { + head = head->next; + } #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Found transmit_ready flag...\n"); -#endif - } - if (((GNUNET_YES == pos->transmit_ready) || - (mq->internal_msg)) && - (pos->connect_attempts < MAX_CONNECT_RETRY) && - ((rl == NULL) || (min_latency.value > pos->latency.value))) - { - rl = pos; - min_latency = pos->latency; - } - pos = pos->next; + if (best_address != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Best address found has latency of %llu!\n", + best_address->latency.value); } #endif + return best_address; + } /** @@ -2223,7 +2218,7 @@ process_hello (struct TransportPlugin *plugin, * The peer specified by the given neighbor has timed-out or a plugin * has disconnected. We may either need to do nothing (other plugins * still up), or trigger a full disconnect and clean up. This - * function updates our state and do the necessary notifications. + * function updates our state and does the necessary notifications. * Also notifies our clients that the neighbor is now officially * gone. * @@ -2233,14 +2228,27 @@ process_hello (struct TransportPlugin *plugin, * disconnect? */ static void -disconnect_neighbor (struct NeighborList *n, int check) +disconnect_neighbor (struct NeighborList *current_handle, int check) { struct ReadyList *rpos; struct NeighborList *npos; struct NeighborList *nprev; + struct NeighborList *n; struct MessageQueue *mq; struct PeerAddressList *peer_addresses; + if (neighbors == NULL) + return; /* We don't have any neighbors, so client has an already removed handle! */ + + npos = neighbors; + while ((npos != NULL) && (current_handle != npos)) + npos = npos->next; + + if (npos == NULL) + return; /* Couldn't find neighbor in existing list, must have been already removed! */ + else + n = npos; + if (GNUNET_YES == check) { rpos = n->plugins; @@ -2749,21 +2757,29 @@ handle_try_connect (void *cls, const struct GNUNET_MessageHeader *message) { const struct TryConnectMessage *tcm; - + struct NeighborList *neighbor; tcm = (const struct TryConnectMessage *) message; #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' request from client %p asking to connect to `%4s'\n", "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer)); #endif - if (NULL == find_neighbor (&tcm->peer)) + neighbor = find_neighbor(&tcm->peer); + + if (neighbor == NULL) setup_new_neighbor (&tcm->peer); -#if DEBUG_TRANSPORT else - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Client asked to connect to `%4s', but connection already exists\n", - "TRY_CONNECT", GNUNET_i2s (&tcm->peer)); + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Client asked to connect to `%4s', but connection already exists\n", + "TRY_CONNECT", GNUNET_i2s (&tcm->peer)); #endif + transmit_to_peer (NULL, NULL, 0, + (const char *) our_hello, GNUNET_HELLO_size(our_hello), + GNUNET_YES, neighbor); + notify_clients_connect (&tcm->peer, GNUNET_TIME_UNIT_FOREVER_REL); + } GNUNET_SERVER_receive_done (client, GNUNET_OK); } diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c index 5fd7124d7..c03f9dec7 100644 --- a/src/transport/test_transport_api.c +++ b/src/transport/test_transport_api.c @@ -31,7 +31,7 @@ #include "gnunet_transport_service.h" #include "transport.h" -#define VERBOSE GNUNET_YES +#define VERBOSE GNUNET_NO #define VERBOSE_ARM GNUNET_NO @@ -125,11 +125,13 @@ notify_receive (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok is (%d)!\n", ok); - GNUNET_assert (ok == 7); - OKPP; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %d from peer (%p)!\n", ntohs(message->type), cls); + GNUNET_assert (ok == 7); + OKPP; + GNUNET_assert (MTYPE == ntohs (message->type)); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)); @@ -220,17 +222,19 @@ exchange_hello_last (void *cls, message, &me->id)); GNUNET_TRANSPORT_offer_hello (p1.th, message); + + /*sleep(10);*/ /* Make sure we are not falling prey to the "favorable timing" bug... + + /* both HELLOs exchanged, get ready to test transmission! */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished exchanging HELLOs, now waiting for transmission!\n"); - /* both HELLOs exchanged, get ready to test transmission! */ GNUNET_TRANSPORT_notify_transmit_ready (p1.th, - &p2.id, - 256, 0, TIMEOUT, ¬ify_ready, - &p1); + &p2.id, + 256, 0, TIMEOUT, ¬ify_ready, + &p1); } - static void exchange_hello (void *cls, const struct GNUNET_MessageHeader *message) diff --git a/src/transport/transport.h b/src/transport/transport.h index 603f1bbc1..89f004ab8 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -30,7 +30,7 @@ #include "gnunet_time_lib.h" #include "gnunet_transport_service.h" -#define DEBUG_TRANSPORT GNUNET_YES +#define DEBUG_TRANSPORT GNUNET_NO /** * For how long do we allow unused bandwidth diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index c6269e562..cbcabfb3b 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c @@ -946,9 +946,23 @@ request_connect (void *cls, size_t size, void *buf) struct GNUNET_TRANSPORT_TransmitHandle *th = cls; struct TryConnectMessage *tcm; struct GNUNET_TRANSPORT_Handle *h; + struct NeighbourList *n; GNUNET_assert (th->notify_delay_task == GNUNET_SCHEDULER_NO_TASK); h = th->handle; + + n = find_neighbour(h, &tcm->peer); + + if (n != NULL) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Asked to TRY_CONNECT to already connected peer!\n"); +#endif + return GNUNET_YES; + } + + if (buf == NULL) { #if DEBUG_TRANSPORT @@ -1356,8 +1370,10 @@ add_neighbour (struct GNUNET_TRANSPORT_Handle *h, h->connect_wait_head = next; else prev->next = next; -// if (GNUNET_YES == n->received_ack) -// { +#if ACK + if (GNUNET_YES == n->received_ack) + { +#endif #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found pending request for `%4s' will trigger it now.\n", @@ -1369,7 +1385,9 @@ add_neighbour (struct GNUNET_TRANSPORT_Handle *h, pos->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; } schedule_request (pos); -// } +#if ACK + } +#endif break; } @@ -1529,6 +1547,10 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) struct NeighbourList *n; struct GNUNET_PeerIdentity me; struct GNUNET_TRANSPORT_TransmitHandle *th; + + struct GNUNET_TRANSPORT_TransmitHandle *prev; + struct GNUNET_TRANSPORT_TransmitHandle *pos; + struct GNUNET_TRANSPORT_TransmitHandle *next; uint16_t size; if ((msg == NULL) || (h->client == NULL)) @@ -1614,9 +1636,80 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) "Receiving `%s' message for `%4s'.\n", "CONNECT", GNUNET_i2s (&cim->id)); #endif - add_neighbour (h, - ntohl (cim->quota_out), - GNUNET_TIME_relative_ntoh (cim->latency), ntohs(cim->distance), &cim->id); + if (find_neighbour(h, &cim->id) == NULL) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Don't know neighbor, adding!\n"); +#endif + add_neighbour (h, + ntohl (cim->quota_out), + GNUNET_TIME_relative_ntoh (cim->latency), ntohs(cim->distance), &cim->id); + } + else + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Do know neighbor, scheduling transmission!\n"); +#endif + n = find_neighbour(h, &cim->id); + n->received_ack = GNUNET_YES; + if (NULL != n->transmit_handle) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Peer connected, scheduling delayed message for delivery now.\n"); +#endif + schedule_request (n->transmit_handle); + } + else + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmit handle is null... Checking for pending stuff(?)\n"); +#endif + prev = NULL; + pos = h->connect_wait_head; + while (pos != NULL) + { + next = pos->next; + if (0 == memcmp (&cim->id, + &pos->target, sizeof (struct GNUNET_PeerIdentity))) + { + pos->neighbour = n; + GNUNET_assert (NULL == n->transmit_handle); + n->transmit_handle = pos; + if (prev == NULL) + h->connect_wait_head = next; + else + prev->next = next; +#if ACK + if (GNUNET_YES == n->received_ack) + { +#endif + #if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found pending request for `%4s' will trigger it now.\n", + GNUNET_i2s (&pos->target)); + #endif + if (pos->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (h->sched, pos->notify_delay_task); + pos->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; + } + schedule_request (pos); +#if ACK + } +#endif + + break; + } + prev = pos; + pos = next; + } + } + } + break; case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: if (size != sizeof (struct DisconnectInfoMessage)) @@ -1882,7 +1975,7 @@ GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle #endif GNUNET_assert (NULL == n->transmit_handle); n->transmit_handle = th; - if (GNUNET_YES != n->received_ack) + if (GNUNET_YES != n->transmit_ok) { #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, -- 2.25.1