*/
GNUNET_SCHEDULER_TaskIdentifier quota_update_task;
+ /**
+ * ID of task used for cleaning up dead neighbour entries.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier dead_clean_task;
+
/**
* At what time did we generate our encryption key?
*/
*/
enum PeerStateMachine status;
+ /**
+ * Are we currently connected to this neighbour?
+ */
+ int is_connected;
};
n = neighbours;
while (n != NULL)
{
+ if (n->status == PEER_STATE_KEY_CONFIRMED)
+ {
#if DEBUG_CORE_CLIENT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
#endif
- cnm.distance = htonl (n->last_distance);
- cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
- cnm.peer = n->peer;
- send_to_client (c, &cnm.header, GNUNET_NO);
+ cnm.distance = htonl (n->last_distance);
+ cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
+ cnm.peer = n->peer;
+ send_to_client (c, &cnm.header, GNUNET_NO);
+ }
n = n->next;
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
rcm = (const struct RequestInfoMessage *) message;
n = find_neighbour (&rcm->peer);
memset (&cim, 0, sizeof (cim));
- if ((n != NULL) && (n->status == PEER_STATE_KEY_CONFIRMED))
+ if (n != NULL)
{
update_window (GNUNET_YES,
&n->available_send_window,
}
+/**
+ * Free the given entry for the neighbour (it has
+ * already been removed from the list at this point).
+ *
+ * @param n neighbour to free
+ */
+static void
+free_neighbour (struct Neighbour *n)
+{
+ struct MessageEntry *m;
+
+ if (n->pitr != NULL)
+ {
+ GNUNET_PEERINFO_iterate_cancel (n->pitr);
+ n->pitr = NULL;
+ }
+ if (n->skm != NULL)
+ {
+ GNUNET_free (n->skm);
+ n->skm = NULL;
+ }
+ while (NULL != (m = n->messages))
+ {
+ n->messages = m->next;
+ GNUNET_free (m);
+ }
+ while (NULL != (m = n->encrypted_head))
+ {
+ n->encrypted_head = m->next;
+ GNUNET_free (m);
+ }
+ if (NULL != n->th)
+ GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
+ if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (sched, n->retry_plaintext_task);
+ if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (sched, n->retry_set_key_task);
+ if (n->quota_update_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (sched, n->quota_update_task);
+ if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (sched, n->dead_clean_task);
+ GNUNET_free_non_null (n->public_key);
+ GNUNET_free_non_null (n->pending_ping);
+ GNUNET_free_non_null (n->pending_pong);
+ GNUNET_free (n);
+}
+
+
+/**
+ * Consider freeing the given neighbour since we may not need
+ * to keep it around anymore.
+ *
+ * @param n neighbour to consider discarding
+ */
+static void
+consider_free_neighbour (struct Neighbour *n);
+
+
+/**
+ * Task triggered when a neighbour entry might have gotten stale.
+ *
+ * @param cls the 'struct Neighbour'
+ * @param tc scheduler context (not used)
+ */
+static void
+consider_free_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Neighbour *n = cls;
+ n->dead_clean_task = GNUNET_SCHEDULER_NO_TASK;
+ consider_free_neighbour (n);
+}
+
+
+/**
+ * Consider freeing the given neighbour since we may not need
+ * to keep it around anymore.
+ *
+ * @param n neighbour to consider discarding
+ */
+static void
+consider_free_neighbour (struct Neighbour *n)
+{
+ struct Neighbour *pos;
+ struct Neighbour *prev;
+ struct GNUNET_TIME_Relative left;
+
+ if ( (n->th != NULL) ||
+ (n->pitr != NULL) ||
+ (n->status == PEER_STATE_KEY_CONFIRMED) ||
+ (GNUNET_YES == n->is_connected) )
+ return; /* no chance */
+
+ left = GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_add (n->last_activity,
+ MAX_PONG_DELAY));
+ if (left.value > 0)
+ {
+ if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (sched, n->dead_clean_task);
+ n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (sched,
+ left,
+ &consider_free_task,
+ n);
+ return;
+ }
+ /* actually free the neighbour... */
+ prev = NULL;
+ pos = neighbours;
+ while (pos != n)
+ {
+ prev = pos;
+ pos = pos->next;
+ }
+ if (prev == NULL)
+ neighbours = n->next;
+ else
+ prev->next = n->next;
+ GNUNET_assert (neighbour_count > 0);
+ neighbour_count--;
+ free_neighbour (n);
+}
+
+
/**
* Check if we have encrypted messages for the specified neighbour
* pending, and if so, check with the transport about sending them
else
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Transmission for message of type %u and size %u failed\n",
+ "Transmission of message of type %u and size %u failed\n",
ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
m->size);
}
GNUNET_free (m);
+ consider_free_neighbour (n);
return ret;
}
/**
- * Handle CORE_SEND request.
- *
- * @param cls unused
- * @param client the client issuing the request
- * @param message the "struct SendMessage"
+ * Function that recalculates the bandwidth quota for the
+ * given neighbour and transmits it to the transport service.
+ *
+ * @param cls neighbour for the quota update
+ * @param tc context
*/
static void
-handle_client_send (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message);
+neighbour_quota_update (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Schedule the task that will recalculate the bandwidth
+ * quota for this peer (and possibly force a disconnect of
+ * idle peers by calculating a bandwidth of zero).
+ */
+static void
+schedule_quota_update (struct Neighbour *n)
+{
+ GNUNET_assert (n->quota_update_task ==
+ GNUNET_SCHEDULER_NO_TASK);
+ n->quota_update_task
+ = GNUNET_SCHEDULER_add_delayed (sched,
+ QUOTA_UPDATE_FREQUENCY,
+ &neighbour_quota_update,
+ n);
+}
/**
- * Function called to notify us that we either succeeded
- * or failed to connect (at the transport level) to another
- * peer. We should either free the message we were asked
- * to transmit or re-try adding it to the queue.
+ * Initialize a new 'struct Neighbour'.
*
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * @param pid ID of the new neighbour
+ * @return handle for the new neighbour
*/
-static size_t
-send_connect_continuation (void *cls, size_t size, void *buf)
+static struct Neighbour *
+create_neighbour (const struct GNUNET_PeerIdentity *pid)
{
- struct SendMessage *sm = cls;
+ struct Neighbour *n;
+ struct GNUNET_TIME_Absolute now;
- if (buf == NULL)
- {
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Asked to send message to disconnected peer `%4s' and connection failed. Discarding message.\n",
- GNUNET_i2s (&sm->peer));
-#endif
- GNUNET_free (sm);
- return 0;
- }
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connection to peer `%4s' succeeded, retrying original transmission request\n",
- GNUNET_i2s (&sm->peer));
-#endif
- handle_client_send (NULL, NULL, &sm->header);
- GNUNET_free (sm);
- return 0;
+ n = GNUNET_malloc (sizeof (struct Neighbour));
+ n->next = neighbours;
+ neighbours = n;
+ neighbour_count++;
+ n->peer = *pid;
+ GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
+ now = GNUNET_TIME_absolute_get ();
+ n->encrypt_key_created = now;
+ n->last_activity = now;
+ n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
+ n->bpm_in = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
+ n->bpm_out = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
+ n->bpm_out_internal_limit = (uint32_t) - 1;
+ n->bpm_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
+ n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ (uint32_t) - 1);
+ schedule_quota_update (n);
+ return n;
}
+
+
+
/**
* Handle CORE_SEND request.
*
const struct GNUNET_MessageHeader *message)
{
const struct SendMessage *sm;
- struct SendMessage *smc;
const struct GNUNET_MessageHeader *mh;
struct Neighbour *n;
struct MessageEntry *prev;
}
n = find_neighbour (&sm->peer);
if (n == NULL)
- {
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Core received `%s' request for `%4s', will try to establish connection within %llu ms\n",
- "SEND",
- GNUNET_i2s (&sm->peer),
- GNUNET_TIME_absolute_get_remaining
- (GNUNET_TIME_absolute_ntoh(sm->deadline)).value);
-#endif
- msize += sizeof (struct SendMessage);
- /* ask transport to connect to the peer */
- smc = GNUNET_malloc (msize);
- memcpy (smc, sm, msize);
- if (NULL ==
- GNUNET_TRANSPORT_notify_transmit_ready (transport,
- &sm->peer,
- 0, 0,
- GNUNET_TIME_absolute_get_remaining
- (GNUNET_TIME_absolute_ntoh
- (sm->deadline)),
- &send_connect_continuation,
- smc))
- {
- /* transport has already a request pending for this peer! */
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Dropped second message destined for `%4s' since connection is still down.\n",
- GNUNET_i2s(&sm->peer));
-#endif
- GNUNET_free (smc);
- }
- if (client != NULL)
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
- }
+ n = create_neighbour (&sm->peer);
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
GNUNET_SERVER_receive_done (client, GNUNET_OK);
n = find_neighbour (&cm->peer);
- if (n != NULL)
+ if (n == NULL)
+ n = create_neighbour (&cm->peer);
+ if ( (n->is_connected) ||
+ (n->th != NULL) )
return; /* already connected, or at least trying */
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
GNUNET_i2s (&cm->peer));
#endif
/* ask transport to connect to the peer */
- /* FIXME: timeout zero OK? need for cancellation? */
- GNUNET_TRANSPORT_notify_transmit_ready (transport,
- &cm->peer,
- 0, 0,
- GNUNET_TIME_UNIT_ZERO,
- NULL,
- NULL);
+ /* FIXME: timeout zero OK? */
+ n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
+ &cm->peer,
+ 0, 0,
+ GNUNET_TIME_UNIT_ZERO,
+ NULL,
+ NULL);
}
* the neighbour's struct and retry send_key. Or, if we did not get a
* HELLO, just do nothing.
*
- * @param cls NULL
+ * @param cls the 'struct Neighbour' to retry sending the key for
* @param peer the peer for which this is the HELLO
* @param hello HELLO message of that peer
* @param trust amount of trust we currently have in that peer
GNUNET_i2s (&n->peer));
#endif
GNUNET_assert (n->pitr == NULL);
- //sleep(10);
n->pitr = GNUNET_PEERINFO_iterate (cfg,
sched,
&n->peer,
GNUNET_break (0);
return;
}
+ GNUNET_break (n->is_connected);
n->last_latency = latency;
n->last_distance = distance;
up = (n->status == PEER_STATE_KEY_CONFIRMED);
}
-/**
- * Function that recalculates the bandwidth quota for the
- * given neighbour and transmits it to the transport service.
- *
- * @param cls neighbour for the quota update
- * @param tc context
- */
-static void
-neighbour_quota_update (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Schedule the task that will recalculate the bandwidth
- * quota for this peer (and possibly force a disconnect of
- * idle peers by calculating a bandwidth of zero).
- */
-static void
-schedule_quota_update (struct Neighbour *n)
-{
- GNUNET_assert (n->quota_update_task ==
- GNUNET_SCHEDULER_NO_TASK);
- n->quota_update_task
- = GNUNET_SCHEDULER_add_delayed (sched,
- QUOTA_UPDATE_FREQUENCY,
- &neighbour_quota_update,
- n);
-}
-
-
/**
* Function that recalculates the bandwidth quota for the
* given neighbour and transmits it to the transport service.
n = find_neighbour (peer);
if (n != NULL)
{
- /* duplicate connect notification!? */
- GNUNET_break (0);
- return;
+ if (n->is_connected)
+ {
+ /* duplicate connect notification!? */
+ GNUNET_break (0);
+ return;
+ }
+ }
+ else
+ {
+ n = create_neighbour (peer);
}
now = GNUNET_TIME_absolute_get ();
- n = GNUNET_malloc (sizeof (struct Neighbour));
- n->next = neighbours;
- neighbours = n;
- neighbour_count++;
- n->peer = *peer;
+ n->is_connected = GNUNET_YES;
n->last_latency = latency;
n->last_distance = distance;
- GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
- n->encrypt_key_created = now;
- n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
- n->last_activity = now;
n->last_asw_update = now;
n->last_arw_update = now;
- n->bpm_in = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
- n->bpm_out = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
- n->bpm_out_internal_limit = (uint32_t) - 1;
- n->bpm_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
- n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- (uint32_t) - 1);
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received connection from `%4s'.\n",
GNUNET_i2s (&n->peer));
#endif
- schedule_quota_update (n);
cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT);
cnm.distance = htonl (n->last_distance);
}
-/**
- * Free the given entry for the neighbour (it has
- * already been removed from the list at this point).
- *
- * @param n neighbour to free
- */
-static void
-free_neighbour (struct Neighbour *n)
-{
- struct MessageEntry *m;
-
- if (n->pitr != NULL)
- {
- GNUNET_PEERINFO_iterate_cancel (n->pitr);
- n->pitr = NULL;
- }
- if (n->skm != NULL)
- {
- GNUNET_free (n->skm);
- n->skm = NULL;
- }
- while (NULL != (m = n->messages))
- {
- n->messages = m->next;
- GNUNET_free (m);
- }
- while (NULL != (m = n->encrypted_head))
- {
- n->encrypted_head = m->next;
- GNUNET_free (m);
- }
- if (NULL != n->th)
- GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
- if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (sched, n->retry_plaintext_task);
- if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (sched, n->retry_set_key_task);
- if (n->quota_update_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (sched, n->quota_update_task);
- GNUNET_free_non_null (n->public_key);
- GNUNET_free_non_null (n->pending_ping);
- GNUNET_free_non_null (n->pending_pong);
- GNUNET_free (n);
-}
-
-
/**
* Function called by transport telling us that a peer
* disconnected.
{
struct DisconnectNotifyMessage cnm;
struct Neighbour *n;
- struct Neighbour *p;
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Peer `%4s' disconnected from us.\n", GNUNET_i2s (peer));
#endif
- p = NULL;
- n = neighbours;
- while ((n != NULL) &&
- (0 != memcmp (&n->peer, peer, sizeof (struct GNUNET_PeerIdentity))))
- {
- p = n;
- n = n->next;
- }
- if (n == NULL)
- {
- GNUNET_break (0);
- return;
- }
- if (p == NULL)
- neighbours = n->next;
- else
- p->next = n->next;
- GNUNET_assert (neighbour_count > 0);
- neighbour_count--;
+ n = find_neighbour (peer);
+ GNUNET_break (n->is_connected);
cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
cnm.peer = *peer;
send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_DISCONNECT);
- free_neighbour (n);
+ n->is_connected = GNUNET_NO;
}
};
-struct NeighborList;
+struct NeighbourList;
/**
- * For each neighbor we keep a list of messages
- * that we still want to transmit to the neighbor.
+ * For each neighbour we keep a list of messages
+ * that we still want to transmit to the neighbour.
*/
struct MessageQueue
{
struct ForeignAddressList *specific_address;
/**
- * Peer ID of the Neighbor this entry belongs to.
+ * Peer ID of the Neighbour this entry belongs to.
*/
- struct GNUNET_PeerIdentity neighbor_id;
+ struct GNUNET_PeerIdentity neighbour_id;
/**
* Plugin that we used for the transmission.
*/
struct TransportPlugin *plugin;
+ /**
+ * At what time should we fail?
+ */
+ struct GNUNET_TIME_Absolute timeout;
+
/**
* Internal message of the transport system that should not be
* included in the usual SEND-SEND_OK transmission confirmation
/**
- * For a given Neighbor, which plugins are available
+ * For a given Neighbour, which plugins are available
* to talk to this peer and what are their costs?
*/
struct ReadyList
/**
- * Entry in linked list of all of our current neighbors.
+ * Entry in linked list of all of our current neighbours.
*/
-struct NeighborList
+struct NeighbourList
{
/**
* This is a linked list.
*/
- struct NeighborList *next;
+ struct NeighbourList *next;
/**
* Which of our transports is connected to this peer
struct MessageQueue *messages_tail;
/**
- * Identity of this neighbor.
+ * Identity of this neighbour.
*/
struct GNUNET_PeerIdentity id;
*/
GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+ /**
+ * ID of task scheduled to run when we should retry transmitting
+ * the head of the message queue.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier retry_task;
+
/**
* How long until we should consider this peer dead
* (if we don't receive another message in the
* this particular peer. This latency may have been calculated
* over multiple transports. This value reflects how long it took
* us to receive a response when SENDING via this particular
- * transport/neighbor/address combination!
+ * transport/neighbour/address combination!
*
* FIXME: we need to periodically send PINGs to update this
* latency (at least more often than the current "huge" (11h?)
uint64_t last_received;
/**
- * Global quota for inbound traffic for the neighbor in bytes/ms.
+ * Global quota for inbound traffic for the neighbour in bytes/ms.
*/
uint32_t quota_in;
unsigned int quota_violation_count;
/**
- * Have we seen an PONG from this neighbor in the past (and
+ * Have we seen an PONG from this neighbour in the past (and
* not had a disconnect since)?
*/
int received_pong;
static struct GNUNET_HELLO_Message *our_hello;
/**
- * "version" of "our_hello". Used to see if a given neighbor has
+ * "version" of "our_hello". Used to see if a given neighbour has
* already been sent the latest version of our HELLO message.
*/
static unsigned int our_hello_version;
static struct GNUNET_SERVER_Handle *server;
/**
- * All known neighbors and their HELLOs.
+ * All known neighbours and their HELLOs.
*/
-static struct NeighborList *neighbors;
+static struct NeighbourList *neighbours;
/**
- * Number of neighbors we'd like to have.
+ * Number of neighbours we'd like to have.
*/
static uint32_t max_connect_per_transport;
/**
- * The peer specified by the given neighbor has timed-out or a plugin
+ * The peer specified by the given neighbour 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.
- * Also notifies our clients that the neighbor is now officially
+ * Also notifies our clients that the neighbour is now officially
* gone.
*
- * @param n the neighbor list entry for the peer
+ * @param n the neighbour list entry for the peer
* @param check should we just check if all plugins
* disconnected or must we ask all plugins to
* disconnect?
*/
-static void disconnect_neighbor (struct NeighborList *n, int check);
+static void disconnect_neighbour (struct NeighbourList *n, int check);
/**
- * Check the ready list for the given neighbor and if a plugin is
+ * Check the ready list for the given neighbour and if a plugin is
* ready for transmission (and if we have a message), do so!
*
- * @param neighbor target peer for which to transmit
+ * @param neighbour target peer for which to transmit
*/
-static void try_transmission_to_peer (struct NeighborList *neighbor);
+static void try_transmission_to_peer (struct NeighbourList *neighbour);
/**
- * Find an entry in the neighbor list for a particular peer.
+ * Find an entry in the neighbour list for a particular peer.
* if sender_address is not specified (NULL) then return the
* first matching entry. If sender_address is specified, then
* make sure that the address and address_len also matches.
*
* @return NULL if not found.
*/
-static struct NeighborList *
-find_neighbor (const struct GNUNET_PeerIdentity *key)
+static struct NeighbourList *
+find_neighbour (const struct GNUNET_PeerIdentity *key)
{
- struct NeighborList *head = neighbors;
+ struct NeighbourList *head = neighbours;
while ((head != NULL) &&
(0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
/**
- * Update the quota values for the given neighbor now.
+ * Update the quota values for the given neighbour now.
*/
static void
-update_quota (struct NeighborList *n)
+update_quota (struct NeighbourList *n)
{
struct GNUNET_TIME_Relative delta;
uint64_t allowed;
/**
* Transmit a 'SEND_OK' notification to the given client for the
- * given neighbor.
+ * given neighbour.
*
* @param client who to notify
- * @param n neighbor to notify about
+ * @param n neighbour to notify about
* @param result status code for the transmission request
*/
static void
transmit_send_ok (struct TransportClient *client,
- struct NeighborList *n,
+ struct NeighbourList *n,
int result)
{
struct SendOkMessage send_ok_msg;
int result)
{
struct MessageQueue *mq = cls;
- struct NeighborList *n;
+ struct NeighbourList *n;
- n = find_neighbor(&mq->neighbor_id);
+ n = find_neighbour(&mq->neighbour_id);
GNUNET_assert (n != NULL);
if (mq->specific_address != NULL)
{
GNUNET_free (mq);
try_transmission_to_peer (n);
if (result != GNUNET_OK)
- disconnect_neighbor (n, GNUNET_YES);
+ disconnect_neighbour (n, GNUNET_YES);
}
/**
* Find an address in any of the available transports for
- * the given neighbor that would be good for message
+ * the given neighbour that would be good for message
* transmission. This is essentially the transport selection
* routine.
*
- * @param neighbor for whom to select an address
+ * @param neighbour for whom to select an address
* @return selected address, NULL if we have none
*/
struct ForeignAddressList *
-find_ready_address(struct NeighborList *neighbor)
+find_ready_address(struct NeighbourList *neighbour)
{
- struct ReadyList *head = neighbor->plugins;
+ struct ReadyList *head = neighbour->plugins;
struct ForeignAddressList *addresses;
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
struct ForeignAddressList *best_address;
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Marking long-time inactive connection to `%4s' as down.\n",
- GNUNET_i2s (&neighbor->id));
+ GNUNET_i2s (&neighbour->id));
#endif
addresses->connected = GNUNET_NO;
}
/**
- * Check the ready list for the given neighbor and if a plugin is
+ * We should re-try transmitting to the given peer,
+ * hopefully we've learned something in the meantime.
+ */
+static void
+retry_transmission_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct NeighbourList *n = cls;
+
+ n->retry_task = GNUNET_SCHEDULER_NO_TASK;
+ try_transmission_to_peer (n);
+}
+
+
+/**
+ * Check the ready list for the given neighbour and if a plugin is
* ready for transmission (and if we have a message), do so!
*
- * @param neighbor target peer for which to transmit
+ * @param neighbour target peer for which to transmit
*/
static void
-try_transmission_to_peer (struct NeighborList *neighbor)
+try_transmission_to_peer (struct NeighbourList *neighbour)
{
struct GNUNET_TIME_Relative min_latency;
struct ReadyList *rl;
struct MessageQueue *mq;
+ struct GNUNET_TIME_Relative timeout;
- if (neighbor->messages_head == NULL)
+ if (neighbour->messages_head == NULL)
return; /* nothing to do */
min_latency = GNUNET_TIME_UNIT_FOREVER_REL;
rl = NULL;
- mq = neighbor->messages_head;
+ mq = neighbour->messages_head;
/* FIXME: support bi-directional use of TCP */
if (mq->specific_address == NULL)
- mq->specific_address = find_ready_address(neighbor);
- GNUNET_CONTAINER_DLL_remove (neighbor->messages_head,
- neighbor->messages_tail,
+ mq->specific_address = find_ready_address(neighbour);
+ GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
+ neighbour->messages_tail,
mq);
if (mq->specific_address == NULL)
{
+ timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
+ if (timeout.value == 0)
+ {
#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No destination address available to transmit message of size %u to peer `%4s'\n",
- mq->message_buf_size,
- GNUNET_i2s (&mq->neighbor_id));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No destination address available to transmit message of size %u to peer `%4s'\n",
+ mq->message_buf_size,
+ GNUNET_i2s (&mq->neighbour_id));
#endif
- if (mq->client != NULL)
- transmit_send_ok (mq->client, neighbor, GNUNET_NO);
- GNUNET_free (mq);
- return; /* nobody ready */
+ if (mq->client != NULL)
+ transmit_send_ok (mq->client, neighbour, GNUNET_NO);
+ GNUNET_free (mq);
+ return; /* nobody ready */
+ }
+ if (neighbour->retry_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (sched,
+ neighbour->retry_task);
+ neighbour->retry_task = GNUNET_SCHEDULER_add_delayed (sched,
+ timeout,
+ &retry_transmission_task,
+ neighbour);
+ return;
}
if (mq->specific_address->connected == GNUNET_NO)
mq->specific_address->connect_attempts++;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
mq->message_buf_size,
- GNUNET_i2s (&neighbor->id),
+ GNUNET_i2s (&neighbour->id),
GNUNET_a2s (mq->specific_address->addr,
mq->specific_address->addrlen),
rl->plugin->short_name);
#endif
rl->plugin->api->send (rl->plugin->api->cls,
- &mq->neighbor_id,
+ &mq->neighbour_id,
mq->message_buf,
mq->message_buf_size,
mq->priority,
* @param client source of the transmission request (can be NULL)
* @param peer_address ForeignAddressList where we should send this message
* @param priority how important is the message
+ * @param timeout how long do we have to transmit?
* @param message_buf message(s) to send GNUNET_MessageHeader(s)
* @param message_buf_size total size of all messages in message_buf
* @param is_internal is this an internal message; these are pre-pended and
* also do not count for plugins being "ready" to transmit
- * @param neighbor handle to the neighbor for transmission
+ * @param neighbour handle to the neighbour for transmission
*/
static void
transmit_to_peer (struct TransportClient *client,
struct ForeignAddressList *peer_address,
unsigned int priority,
+ struct GNUNET_TIME_Relative timeout,
const char *message_buf,
size_t message_buf_size,
- int is_internal, struct NeighborList *neighbor)
+ int is_internal, struct NeighbourList *neighbour)
{
struct MessageQueue *mq;
if (client != NULL)
{
/* check for duplicate submission */
- mq = neighbor->messages_head;
+ mq = neighbour->messages_head;
while (NULL != mq)
{
if (mq->client == client)
memcpy (&mq[1], message_buf, message_buf_size);
mq->message_buf = (const char*) &mq[1];
mq->message_buf_size = message_buf_size;
- memcpy(&mq->neighbor_id, &neighbor->id, sizeof(struct GNUNET_PeerIdentity));
+ memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
mq->internal_msg = is_internal;
mq->priority = priority;
+ mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
if (is_internal)
- GNUNET_CONTAINER_DLL_insert (neighbor->messages_head,
- neighbor->messages_tail,
+ GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
+ neighbour->messages_tail,
mq);
else
- GNUNET_CONTAINER_DLL_insert_after (neighbor->messages_head,
- neighbor->messages_tail,
- neighbor->messages_tail,
+ GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
+ neighbour->messages_tail,
+ neighbour->messages_tail,
mq);
- try_transmission_to_peer (neighbor);
+ try_transmission_to_peer (neighbour);
}
{
struct GNUNET_HELLO_Message *hello;
struct TransportClient *cpos;
- struct NeighborList *npos;
+ struct NeighbourList *npos;
struct GeneratorContext gc;
gc.plug_pos = plugins;
our_hello = hello;
our_hello_version++;
GNUNET_PEERINFO_add_peer (cfg, sched, &my_identity, our_hello);
- npos = neighbors;
+ npos = neighbours;
while (npos != NULL)
{
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Transmitting updated `%s' to neighbor `%4s'\n",
+ "Transmitting updated `%s' to neighbour `%4s'\n",
"HELLO", GNUNET_i2s (&npos->id));
#endif
transmit_to_peer (NULL, NULL, 0,
+ HELLO_ADDRESS_EXPIRATION,
(const char *) our_hello,
GNUNET_HELLO_size(our_hello),
GNUNET_NO, npos);
* Find a ForeignAddressList entry for the given neighbour
* that matches the given address and transport.
*
- * @param neighbor which peer we care about
+ * @param neighbour which peer we care about
* @param tname name of the transport plugin
* @param addr binary address
* @param addrlen length of addr
* @return NULL if no such entry exists
*/
static struct ForeignAddressList *
-find_peer_address(struct NeighborList *neighbor,
+find_peer_address(struct NeighbourList *neighbour,
const char *tname,
const char *addr,
size_t addrlen)
struct ReadyList *head;
struct ForeignAddressList *address_head;
- head = neighbor->plugins;
+ head = neighbour->plugins;
while (head != NULL)
{
if (0 == strcmp (tname, head->plugin->short_name))
/**
- * Get the peer address struct for the given neighbor and
+ * Get the peer address struct for the given neighbour and
* address. If it doesn't yet exist, create it.
*
- * @param neighbor which peer we care about
+ * @param neighbour which peer we care about
* @param tname name of the transport plugin
* @param addr binary address
* @param addrlen length of addr
* @return NULL if we do not have a transport plugin for 'tname'
*/
static struct ForeignAddressList *
-add_peer_address(struct NeighborList *neighbor,
+add_peer_address(struct NeighbourList *neighbour,
const char *tname,
const char *addr,
size_t addrlen)
struct ReadyList *head;
struct ForeignAddressList *ret;
- ret = find_peer_address (neighbor, tname, addr, addrlen);
+ ret = find_peer_address (neighbour, tname, addr, addrlen);
if (ret != NULL)
return ret;
- head = neighbor->plugins;
+ head = neighbour->plugins;
while (head != NULL)
{
if (0 == strcmp (tname, head->plugin->short_name))
unsigned int challenge = ntohl(pong->challenge);
struct GNUNET_HELLO_Message *hello;
struct GNUNET_PeerIdentity target;
- struct NeighborList *n;
+ struct NeighbourList *n;
struct ForeignAddressList *fal;
if (ve->challenge != challenge)
&target,
hello);
GNUNET_free (hello);
- n = find_neighbor (&target);
+ n = find_neighbour (&target);
if (n != NULL)
{
fal = add_peer_address (n, ve->transport_name,
notify_clients_connect (&target, n->latency, n->distance);
n->received_pong = GNUNET_YES;
}
+ if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (sched,
+ n->retry_task);
+ n->retry_task = GNUNET_SCHEDULER_NO_TASK;
+ try_transmission_to_peer (n);
+ }
}
/* clean up validation entry */
static void
-neighbor_timeout_task (void *cls,
+neighbour_timeout_task (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct NeighborList *n = cls;
+ struct NeighbourList *n = cls;
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Neighbor `%4s' has timed out!\n", GNUNET_i2s (&n->id));
+ "Neighbour `%4s' has timed out!\n", GNUNET_i2s (&n->id));
#endif
n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- disconnect_neighbor (n, GNUNET_NO);
+ disconnect_neighbour (n, GNUNET_NO);
}
/**
- * Create a fresh entry in our neighbor list for the given peer.
- * Will try to transmit our current HELLO to the new neighbor. Also
+ * Create a fresh entry in our neighbour list for the given peer.
+ * Will try to transmit our current HELLO to the new neighbour. Also
* notifies our clients about the new "connection".
*
* @param peer the peer for which we create the entry
- * @return the new neighbor list entry
+ * @return the new neighbour list entry
*/
-static struct NeighborList *
-setup_new_neighbor (const struct GNUNET_PeerIdentity *peer)
+static struct NeighbourList *
+setup_new_neighbour (const struct GNUNET_PeerIdentity *peer)
{
- struct NeighborList *n;
+ struct NeighbourList *n;
struct TransportPlugin *tp;
struct ReadyList *rl;
GNUNET_assert (our_hello != NULL);
- n = GNUNET_malloc (sizeof (struct NeighborList));
- n->next = neighbors;
- neighbors = n;
+ n = GNUNET_malloc (sizeof (struct NeighbourList));
+ n->next = neighbours;
+ neighbours = n;
n->id = *peer;
n->last_quota_update = GNUNET_TIME_absolute_get ();
n->peer_timeout =
n->distance = -1;
n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- &neighbor_timeout_task, n);
+ &neighbour_timeout_task, n);
transmit_to_peer (NULL, NULL, 0,
+ HELLO_ADDRESS_EXPIRATION,
(const char *) our_hello, GNUNET_HELLO_size(our_hello),
GNUNET_NO, n);
return n;
struct GNUNET_PeerIdentity id;
struct TransportPlugin *tp;
struct ValidationEntry *va;
- struct NeighborList *neighbor;
+ struct NeighbourList *neighbour;
struct ForeignAddressList *peer_address;
struct TransportPingMessage ping;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
&id.hashPubKey,
va,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- neighbor = find_neighbor(&id);
- if (neighbor == NULL)
- neighbor = setup_new_neighbor(&id);
- peer_address = add_peer_address(neighbor, tname, addr, addrlen);
+ neighbour = find_neighbour(&id);
+ if (neighbour == NULL)
+ neighbour = setup_new_neighbour(&id);
+ peer_address = add_peer_address(neighbour, tname, addr, addrlen);
GNUNET_assert(peer_address != NULL);
hello_size = GNUNET_HELLO_size(our_hello);
tsize = sizeof(struct TransportPingMessage) + hello_size;
#endif
transmit_to_peer (NULL, peer_address,
GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+ HELLO_VERIFICATION_TIMEOUT,
message_buf, tsize,
- GNUNET_YES, neighbor);
+ GNUNET_YES, neighbour);
GNUNET_free(message_buf);
return GNUNET_OK;
}
* Add the given address to the list of foreign addresses
* available for the given peer (check for duplicates).
*
- * @param cls the respective 'struct NeighborList' to update
+ * @param cls the respective 'struct NeighbourList' to update
* @param tname name of the transport
* @param expiration expiration time
* @param addr the address
struct GNUNET_TIME_Absolute expiration,
const void *addr, size_t addrlen)
{
- struct NeighborList *n = cls;
+ struct NeighbourList *n = cls;
struct ForeignAddressList *fal;
fal = find_peer_address (n, tname, addr, addrlen);
struct GNUNET_HELLO_Message *plain_hello;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
struct GNUNET_PeerIdentity target;
- struct NeighborList *n;
+ struct NeighbourList *n;
if (peer == NULL)
{
if (h == NULL)
return;
chvc->hello_known = GNUNET_YES;
- n = find_neighbor (peer);
+ n = find_neighbour (peer);
if (n != NULL)
GNUNET_HELLO_iterate_addresses (h,
GNUNET_NO,
/**
- * The peer specified by the given neighbor has timed-out or a plugin
+ * The peer specified by the given neighbour 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 does the necessary notifications.
- * Also notifies our clients that the neighbor is now officially
+ * Also notifies our clients that the neighbour is now officially
* gone.
*
- * @param n the neighbor list entry for the peer
+ * @param n the neighbour list entry for the peer
* @param check should we just check if all plugins
* disconnected or must we ask all plugins to
* disconnect?
*/
static void
-disconnect_neighbor (struct NeighborList *n, int check)
+disconnect_neighbour (struct NeighbourList *n, int check)
{
struct ReadyList *rpos;
- struct NeighborList *npos;
- struct NeighborList *nprev;
+ struct NeighbourList *npos;
+ struct NeighbourList *nprev;
struct MessageQueue *mq;
struct ForeignAddressList *peer_addresses;
struct ForeignAddressList *peer_pos;
"Disconnecting from `%4s'\n",
GNUNET_i2s (&n->id));
#endif
- /* remove n from neighbors list */
+ /* remove n from neighbours list */
nprev = NULL;
- npos = neighbors;
+ npos = neighbours;
while ((npos != NULL) && (npos != n))
{
nprev = npos;
}
GNUNET_assert (npos != NULL);
if (nprev == NULL)
- neighbors = n->next;
+ neighbours = n->next;
else
nprev->next = n->next;
GNUNET_CONTAINER_DLL_remove (n->messages_head,
n->messages_tail,
mq);
- GNUNET_assert (0 == memcmp(&mq->neighbor_id,
+ GNUNET_assert (0 == memcmp(&mq->neighbour_id,
&n->id,
sizeof(struct GNUNET_PeerIdentity)));
GNUNET_free (mq);
GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
}
+ if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (sched, n->retry_task);
+ n->retry_task = GNUNET_SCHEDULER_NO_TASK;
+ }
/* finally, free n itself */
GNUNET_free (n);
}
struct TransportPingMessage *ping;
struct TransportPongMessage *pong;
uint16_t msize;
- struct NeighborList *n;
+ struct NeighbourList *n;
struct ReadyList *rl;
struct ForeignAddressList *fal;
GNUNET_CRYPTO_rsa_sign (my_private_key,
&pong->purpose, &pong->signature));
- n = find_neighbor(peer);
+ n = find_neighbour(peer);
if (n == NULL)
- n = setup_new_neighbor(peer);
+ n = setup_new_neighbour(peer);
/* broadcast 'PONG' to all available addresses */
rl = n->plugins;
while (rl != NULL)
{
transmit_to_peer(NULL, fal,
TRANSPORT_PONG_PRIORITY,
+ HELLO_VERIFICATION_TIMEOUT,
(const char *)pong,
ntohs(pong->header.size),
GNUNET_YES,
struct InboundMessage *im;
struct ForeignAddressList *peer_address;
uint16_t msize;
- struct NeighborList *n;
+ struct NeighbourList *n;
- n = find_neighbor (peer);
+ n = find_neighbour (peer);
if (n == NULL)
{
if (message == NULL)
return; /* disconnect of peer already marked down */
- n = setup_new_neighbor (peer);
+ n = setup_new_neighbour (peer);
}
service_context = n->plugins;
while ((service_context != NULL) && (plugin != service_context->plugin))
GNUNET_i2s (&n->id));
#endif
/* TODO: call stats */
- disconnect_neighbor (n, GNUNET_YES);
+ disconnect_neighbour (n, GNUNET_YES);
return;
}
peer_address = add_peer_address(n,
n->timeout_task =
GNUNET_SCHEDULER_add_delayed (sched,
GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- &neighbor_timeout_task, n);
+ &neighbour_timeout_task, n);
update_quota (n);
if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
{
if (! n->received_pong)
{
GNUNET_break_op (0);
+#if DEBUG_TRANSPORT || 1
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Received message of type %u from `%4s', prior to key confirmation (dropped).\n",
+ ntohs (message->type), GNUNET_i2s (peer));
+#endif
break;
}
#if DEBUG_TRANSPORT
{
struct TransportClient *c;
struct ConnectInfoMessage cim;
- struct NeighborList *n;
+ struct NeighbourList *n;
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
/* tell new client about all existing connections */
cim.header.size = htons (sizeof (struct ConnectInfoMessage));
cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
- n = neighbors;
+ n = neighbours;
while (n != NULL)
{
if (GNUNET_YES == n->received_pong)
const struct GNUNET_MessageHeader *message)
{
struct TransportClient *tc;
- struct NeighborList *n;
+ struct NeighbourList *n;
const struct OutboundMessage *obm;
const struct GNUNET_MessageHeader *obmm;
uint16_t size;
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- n = find_neighbor (&obm->peer);
+ n = find_neighbour (&obm->peer);
if (n == NULL)
- n = setup_new_neighbor (&obm->peer);
+ n = setup_new_neighbour (&obm->peer);
tc = clients;
while ((tc != NULL) && (tc->client != client))
tc = tc->next;
ntohs (obmm->size),
ntohs (obmm->type), GNUNET_i2s (&obm->peer));
#endif
- transmit_to_peer (tc, NULL, ntohl (obm->priority), (char *)obmm,
+ transmit_to_peer (tc, NULL, ntohl (obm->priority),
+ GNUNET_TIME_relative_ntoh (obm->timeout),
+ (char *)obmm,
ntohs (obmm->size), GNUNET_NO, n);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
{
const struct QuotaSetMessage *qsm =
(const struct QuotaSetMessage *) message;
- struct NeighborList *n;
+ struct NeighbourList *n;
struct TransportPlugin *p;
struct ReadyList *rl;
- n = find_neighbor (&qsm->peer);
+ n = find_neighbour (&qsm->peer);
if (n == NULL)
{
GNUNET_SERVER_receive_done (client, GNUNET_OK);