/*
This file is part of GNUnet.
- (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2009, 2010, 2011 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
*/
#include "platform.h"
#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
-#include "gnunet_service_core.h"
-#include "gnunet_service_core-neighbours.h"
-#include "gnunet_service_core-kx.h"
+#include "gnunet-service-core.h"
+#include "gnunet-service-core_neighbours.h"
+#include "gnunet-service-core_kx.h"
+#include "gnunet-service-core_sessions.h"
+#include "gnunet_constants.h"
/**
* Message ready for transmission via transport service. This struct
* is followed by the actual content of the message.
*/
-struct MessageEntry
+struct NeighbourMessageEntry
{
/**
* We keep messages in a doubly linked list.
*/
- struct MessageEntry *next;
+ struct NeighbourMessageEntry *next;
/**
* We keep messages in a doubly linked list.
*/
- struct MessageEntry *prev;
+ struct NeighbourMessageEntry *prev;
/**
* By when are we supposed to transmit this message?
struct GNUNET_TIME_Absolute deadline;
/**
- * How long is the message? (number of bytes following the "struct
- * MessageEntry", but not including the size of "struct
- * MessageEntry" itself!)
+ * What time did we submit the request?
+ */
+ struct GNUNET_TIME_Absolute submission_time;
+
+ /**
+ * How long is the message? (number of bytes following the `struct
+ * MessageEntry`, but not including the size of `struct
+ * MessageEntry` itself!)
*/
size_t size;
* Head of the batched message queue (already ordered, transmit
* starting with the head).
*/
- struct MessageEntry *message_head;
+ struct NeighbourMessageEntry *message_head;
/**
* Tail of the batched message queue (already ordered, append new
* messages to tail).
*/
- struct MessageEntry *message_tail;
+ struct NeighbourMessageEntry *message_tail;
/**
* Handle for pending requests for transmission to this peer
/**
* ID of task used for re-trying plaintext scheduling.
*/
- GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
+ struct GNUNET_SCHEDULER_Task *retry_plaintext_task;
/**
- * Tracking bandwidth for sending to this peer.
+ * How many messages are in the queue for this neighbour?
*/
- struct GNUNET_BANDWIDTH_Tracker available_send_window;
+ unsigned int queue_size;
/**
- * Tracking bandwidth for sending to this peer.
+ * #GNUNET_YES if this peer currently has excess bandwidth.
*/
- struct GNUNET_BANDWIDTH_Tracker available_recv_window;
-
+ int has_excess_bandwidth;
};
/**
- * Map of peer identities to 'struct Neighbour'.
+ * Map of peer identities to `struct Neighbour`.
*/
-static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
+static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
/**
* Transport service.
static struct GNUNET_TRANSPORT_Handle *transport;
-
/**
* Find the entry for the given neighbour.
*
static struct Neighbour *
find_neighbour (const struct GNUNET_PeerIdentity *peer)
{
- return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
+ if (NULL == neighbours)
+ return NULL;
+ return GNUNET_CONTAINER_multipeermap_get (neighbours,
+ peer);
}
static void
free_neighbour (struct Neighbour *n)
{
- struct MessageEntry *m;
+ struct NeighbourMessageEntry *m;
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Destroying neighbour entry for peer `%4s'\n",
+ "Destroying neighbour entry for peer `%s'\n",
GNUNET_i2s (&n->peer));
-#endif
while (NULL != (m = n->message_head))
{
- GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
+ GNUNET_CONTAINER_DLL_remove (n->message_head,
+ n->message_tail,
+ m);
+ n->queue_size--;
GNUNET_free (m);
}
+ GNUNET_assert (0 == n->queue_size);
if (NULL != n->th)
{
GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
n->th = NULL;
}
- if (NULL != n->kx)
+ GNUNET_STATISTICS_update (GSC_stats,
+ gettext_noop
+ ("# sessions terminated by transport disconnect"),
+ 1, GNUNET_NO);
+ if (NULL != n->kxinfo)
{
- GSC_KX_stop (n->kx);
- n->kx = NULL;
+ GSC_KX_stop (n->kxinfo);
+ n->kxinfo = NULL;
}
- if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
+ if (NULL != n->retry_plaintext_task)
{
GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
- n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
+ n->retry_plaintext_task = NULL;
}
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (neighbours,
- &n->peer.hashPubKey, n));
- GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
- GNUNET_CONTAINER_multihashmap_size (neighbours),
+ GNUNET_CONTAINER_multipeermap_remove (neighbours,
+ &n->peer, n));
+ GNUNET_STATISTICS_set (GSC_stats,
+ gettext_noop ("# neighbour entries allocated"),
+ GNUNET_CONTAINER_multipeermap_size (neighbours),
GNUNET_NO);
GNUNET_free (n);
}
* @return number of bytes transmitted
*/
static size_t
-transmit_ready (void *cls, size_t size, void *buf)
+transmit_ready (void *cls,
+ size_t size,
+ void *buf)
{
struct Neighbour *n = cls;
- struct MessageEntry *m;
+ struct NeighbourMessageEntry *m;
size_t ret;
char *cbuf;
+ struct GNUNET_TIME_Relative delay;
+ struct GNUNET_TIME_Relative overdue;
n->th = NULL;
m = n->message_head;
- if (m == NULL)
+ if (NULL == m)
{
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Encrypted message queue empty, no messages added to buffer for `%4s'\n",
- GNUNET_i2s (&n->peer));
-#endif
+ GNUNET_break (0);
return 0;
}
- GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
- if (buf == NULL)
+ GNUNET_CONTAINER_DLL_remove (n->message_head,
+ n->message_tail,
+ m);
+ n->queue_size--;
+ if (NULL == buf)
{
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Transmission of message of type %u and size %u failed\n",
(unsigned int)
ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
(unsigned int) m->size);
-#endif
GNUNET_free (m);
process_queue (n);
return 0;
}
- ret = 0;
+ delay = GNUNET_TIME_absolute_get_duration (m->submission_time);
+ overdue = GNUNET_TIME_absolute_get_duration (m->deadline);
cbuf = buf;
GNUNET_assert (size >= m->size);
- memcpy (cbuf, &m[1], m->size);
+ memcpy (cbuf,
+ &m[1],
+ m->size);
ret = m->size;
- GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window, m->size);
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Copied message of type %u and size %u into transport buffer for `%4s'\n",
- (unsigned int)
- ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
- (unsigned int) ret, GNUNET_i2s (&n->peer));
-#endif
+ if (overdue.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Copied overdue message of type %u and size %u into transport buffer for `%s' with delay of %s\n",
+ (unsigned int)
+ ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
+ (unsigned int) ret,
+ GNUNET_i2s (&n->peer),
+ GNUNET_STRINGS_relative_time_to_string (delay,
+ GNUNET_YES));
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Copied message of type %u and size %u into transport buffer for `%s' with delay of %s\n",
+ (unsigned int)
+ ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
+ (unsigned int) ret,
+ GNUNET_i2s (&n->peer),
+ GNUNET_STRINGS_relative_time_to_string (delay,
+ GNUNET_YES));
GNUNET_free (m);
+ n->has_excess_bandwidth = GNUNET_NO;
process_queue (n);
GNUNET_STATISTICS_update (GSC_stats,
gettext_noop
static void
process_queue (struct Neighbour *n)
{
- struct MessageEntry *m;
+ struct NeighbourMessageEntry *m;
- if (n->th != NULL)
+ if (NULL != n->th)
return; /* request already pending */
m = n->message_head;
- if (m == NULL)
+ if (NULL == m)
+ {
+ /* notify sessions that the queue is empty and more messages
+ * could thus be queued now */
+ GSC_SESSIONS_solicit (&n->peer);
return;
-#if DEBUG_CORE > 1
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
- (unsigned int) m->size, GNUNET_i2s (&n->peer),
- (unsigned long long)
- GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
-#endif
- n->th =
- GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size,
- m->priority,
- GNUNET_TIME_absolute_get_remaining
- (m->deadline),
- &transmit_ready,
- n);
- if (n->th != NULL)
+ "Asking transport for transmission of %u bytes to `%s' in next %s\n",
+ (unsigned int) m->size,
+ GNUNET_i2s (&n->peer),
+ GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (m->deadline),
+ GNUNET_NO));
+ m->submission_time = GNUNET_TIME_absolute_get ();
+ n->th
+ = GNUNET_TRANSPORT_notify_transmit_ready (transport,
+ &n->peer,
+ m->size,
+ GNUNET_TIME_absolute_get_remaining (m->deadline),
+ &transmit_ready,
+ n);
+ if (NULL != n->th)
return;
/* message request too large or duplicate request */
GNUNET_break (0);
/* discard encrypted message */
- GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
+ GNUNET_CONTAINER_DLL_remove (n->message_head,
+ n->message_tail,
+ m);
+ n->queue_size--;
GNUNET_free (m);
process_queue (n);
}
-
/**
* Function called by transport to notify us that
* a peer connected to us (on the network level).
*
* @param cls closure
* @param peer the peer that connected
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
*/
static void
handle_transport_notify_connect (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_TRANSPORT_ATS_Information
- *ats, uint32_t ats_count)
+ const struct GNUNET_PeerIdentity *peer)
{
struct Neighbour *n;
- if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
+ if (0 == memcmp (peer,
+ &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
{
GNUNET_break (0);
return;
}
n = find_neighbour (peer);
- if (n != NULL)
+ if (NULL != n)
{
/* duplicate connect notification!? */
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s exists already\n",
+ GNUNET_i2s (peer));
return;
}
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received connection from `%4s'.\n",
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received connection from `%s'.\n",
GNUNET_i2s (peer));
-#endif
- n = GNUNET_malloc (sizeof (struct Neighbour));
- n->peer = *pid;
- GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
- GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
- MAX_WINDOW_TIME_S);
- GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
- GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
- MAX_WINDOW_TIME_S);
+ n = GNUNET_new (struct Neighbour);
+ n->peer = *peer;
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (neighbours,
- &n->peer.hashPubKey, n,
+ GNUNET_CONTAINER_multipeermap_put (neighbours,
+ &n->peer,
+ n,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
- GNUNET_CONTAINER_multihashmap_size (neighbours),
+ GNUNET_STATISTICS_set (GSC_stats,
+ gettext_noop ("# neighbour entries allocated"),
+ GNUNET_CONTAINER_multipeermap_size (neighbours),
GNUNET_NO);
- GNUNET_TRANSPORT_set_quota (transport, peer,
- GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
- GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT);
- n->kx = GSC_KX_start (pid);
+ n->kxinfo = GSC_KX_start (peer);
}
{
struct Neighbour *n;
-#if DEBUG_CORE
+ if (0 == memcmp (peer,
+ &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
+ {
+ GNUNET_break (0);
+ return;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peer `%4s' disconnected from us; received notification from transport.\n",
+ "Peer `%s' disconnected from us; received notification from transport.\n",
GNUNET_i2s (peer));
-#endif
n = find_neighbour (peer);
- if (n == NULL)
+ if (NULL == n)
{
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s not found\n",
+ GNUNET_i2s (peer));
return;
}
free_neighbour (n);
* @param cls closure
* @param peer (claimed) identity of the other peer
* @param message the message
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
*/
static void
-handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message,
- const struct GNUNET_TRANSPORT_ATS_Information *ats,
- uint32_t ats_count)
+handle_transport_receive (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_MessageHeader *message)
{
struct Neighbour *n;
- struct GNUNET_TIME_Absolute now;
- int up;
uint16_t type;
- uint16_t size;
- int changed;
-#if DEBUG_CORE > 1
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received message of type %u from `%4s', demultiplexing.\n",
- (unsigned int) ntohs (message->type), GNUNET_i2s (peer));
-#endif
- if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
+ "Received message of type %u from `%s', demultiplexing.\n",
+ (unsigned int) ntohs (message->type),
+ GNUNET_i2s (peer));
+ if (0 == memcmp (peer,
+ &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
{
GNUNET_break (0);
return;
}
n = find_neighbour (peer);
- if (n == NULL)
+ if (NULL == n)
{
/* received message from peer that is not connected!? */
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s not found\n",
+ GNUNET_i2s (peer));
return;
}
-
-
- changed = GNUNET_NO;
- up = (n->status == PEER_STATE_KEY_CONFIRMED);
type = ntohs (message->type);
- size = ntohs (message->size);
switch (type)
{
- case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
- if (size != sizeof (struct SetKeyMessage))
- {
- GNUNET_break_op (0);
- return;
- }
- GNUNET_STATISTICS_update (stats, gettext_noop ("# session keys received"),
- 1, GNUNET_NO);
- handle_set_key (n, (const struct SetKeyMessage *) message, ats, ats_count);
- break;
- case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
- if (size <
- sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return;
- }
- if ((n->status != PEER_STATE_KEY_RECEIVED) &&
- (n->status != PEER_STATE_KEY_CONFIRMED))
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("# failed to decrypt message (no session key)"),
- 1, GNUNET_NO);
- send_key (n);
- return;
- }
- handle_encrypted_message (n, (const struct EncryptedMessage *) message, ats,
- ats_count);
+ case GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY:
+ GSC_KX_handle_ephemeral_key (n->kxinfo, message);
break;
case GNUNET_MESSAGE_TYPE_CORE_PING:
- if (size != sizeof (struct PingMessage))
- {
- GNUNET_break_op (0);
- return;
- }
- GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"),
- 1, GNUNET_NO);
- if ((n->status != PEER_STATE_KEY_RECEIVED) &&
- (n->status != PEER_STATE_KEY_CONFIRMED))
- {
-#if DEBUG_CORE > 1
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
- "PING", GNUNET_i2s (&n->peer));
-#endif
- GNUNET_free_non_null (n->pending_ping);
- n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
- memcpy (n->pending_ping, message, sizeof (struct PingMessage));
- return;
- }
- handle_ping (n, (const struct PingMessage *) message, ats, ats_count);
+ GSC_KX_handle_ping (n->kxinfo, message);
break;
case GNUNET_MESSAGE_TYPE_CORE_PONG:
- if (size != sizeof (struct PongMessage))
- {
- GNUNET_break_op (0);
- return;
- }
- GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"),
- 1, GNUNET_NO);
- if ((n->status != PEER_STATE_KEY_RECEIVED) &&
- (n->status != PEER_STATE_KEY_CONFIRMED))
- {
-#if DEBUG_CORE > 1
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
- "PONG", GNUNET_i2s (&n->peer));
-#endif
- GNUNET_free_non_null (n->pending_pong);
- n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage));
- memcpy (n->pending_pong, message, sizeof (struct PongMessage));
- return;
- }
- handle_pong (n, (const struct PongMessage *) message, ats, ats_count);
+ GSC_KX_handle_pong (n->kxinfo, message);
+ break;
+ case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
+ GSC_KX_handle_encrypted_message (n->kxinfo, message);
+ break;
+ case GNUNET_MESSAGE_TYPE_DUMMY:
+ /* Dummy messages for testing / benchmarking, just discard */
break;
default:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Unsupported message of type %u received.\n"),
- (unsigned int) type);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Unsupported message of type %u (%u bytes) received from peer `%s'\n"),
+ (unsigned int) type,
+ (unsigned int) ntohs (message->size),
+ GNUNET_i2s (peer));
return;
}
- if (n->status == PEER_STATE_KEY_CONFIRMED)
- {
- now = GNUNET_TIME_absolute_get ();
- n->last_activity = now;
- changed = GNUNET_YES;
- if (!up)
- {
- GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"),
- 1, GNUNET_NO);
- n->time_established = now;
- }
- if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->keep_alive_task);
- n->keep_alive_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
- (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- 2), &send_keep_alive, n);
- }
- if (changed)
- handle_peer_status_change (n);
}
/**
* Transmit the given message to the given target.
- *
+ *
* @param target peer that should receive the message (must be connected)
* @param msg message to transmit
* @param timeout by when should the transmission be done?
*/
void
-GDS_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
- const struct GNUNET_MessageHeader *msg,
- struct GNUNET_TIME_Relative timeout)
+GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
+ const struct GNUNET_MessageHeader *msg,
+ struct GNUNET_TIME_Relative timeout)
{
-
+ struct NeighbourMessageEntry *me;
+ struct Neighbour *n;
+ size_t msize;
+
+ n = find_neighbour (target);
+ if (NULL == n)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s not found\n",
+ GNUNET_i2s (target));
+ return;
+ }
+ msize = ntohs (msg->size);
+ me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize);
+ me->deadline = GNUNET_TIME_relative_to_absolute (timeout);
+ me->size = msize;
+ memcpy (&me[1],
+ msg,
+ msize);
+ GNUNET_CONTAINER_DLL_insert_tail (n->message_head,
+ n->message_tail,
+ me);
+ n->queue_size++;
+ process_queue (n);
+}
+
+
+/**
+ * One of our neighbours has excess bandwidth, remember this.
+ *
+ * @param cls NULL
+ * @param pid identity of the peer with excess bandwidth
+ */
+static void
+handle_transport_notify_excess_bw (void *cls,
+ const struct GNUNET_PeerIdentity *pid)
+{
+ struct Neighbour *n;
+
+ n = find_neighbour (pid);
+ if (NULL == n)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s not found\n",
+ GNUNET_i2s (pid));
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Peer %s has excess bandwidth available\n",
+ GNUNET_i2s (pid));
+ n->has_excess_bandwidth = GNUNET_YES;
+ GSC_SESSIONS_solicit (pid);
+}
+
+
+/**
+ * Check how many messages are queued for the given neighbour.
+ *
+ * @param target neighbour to check
+ * @return number of items in the message queue
+ */
+unsigned int
+GSC_NEIGHBOURS_get_queue_size (const struct GNUNET_PeerIdentity *target)
+{
+ struct Neighbour *n;
+
+ n = find_neighbour (target);
+ if (NULL == n)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s not found\n",
+ GNUNET_i2s (target));
+ return UINT_MAX;
+ }
+ return n->queue_size;
+}
+
+
+/**
+ * Check if the given neighbour has excess bandwidth available.
+ *
+ * @param target neighbour to check
+ * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
+ */
+int
+GSC_NEIGHBOURS_check_excess_bandwidth (const struct GNUNET_PeerIdentity *target)
+{
+ struct Neighbour *n;
+
+ n = find_neighbour (target);
+ if (NULL == n)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Peer %s not found\n",
+ GNUNET_i2s (target));
+ return GNUNET_SYSERR;
+ }
+ return n->has_excess_bandwidth;
}
int
GSC_NEIGHBOURS_init ()
{
- neighbours = GNUNET_CONTAINER_multihashmap_create (128);
+ neighbours = GNUNET_CONTAINER_multipeermap_create (128,
+ GNUNET_YES);
transport =
- GNUNET_TRANSPORT_connect (GSC_cfg,
- &GSC_my_identity, NULL,
- &handle_transport_receive,
- &handle_transport_notify_connect,
- &handle_transport_notify_disconnect);
+ GNUNET_TRANSPORT_connect2 (GSC_cfg,
+ &GSC_my_identity,
+ NULL,
+ &handle_transport_receive,
+ &handle_transport_notify_connect,
+ &handle_transport_notify_disconnect,
+ &handle_transport_notify_excess_bw);
if (NULL == transport)
{
- GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ GNUNET_CONTAINER_multipeermap_destroy (neighbours);
neighbours = NULL;
return GNUNET_SYSERR;
}
/**
- * Wrapper around 'free_neighbour'.
+ * Wrapper around #free_neighbour().
*
* @param cls unused
* @param key peer identity
- * @param value the 'struct Neighbour' to free
- * @return GNUNET_OK (continue to iterate)
+ * @param value the `struct Neighbour` to free
+ * @return #GNUNET_OK (continue to iterate)
*/
static int
-free_neighbour_helper (void *cls, const GNUNET_HashCode * key, void *value)
+free_neighbour_helper (void *cls,
+ const struct GNUNET_PeerIdentity * key,
+ void *value)
{
struct Neighbour *n = value;
+ /* transport should have 'disconnected' all neighbours... */
+ GNUNET_break (0);
free_neighbour (n);
return GNUNET_OK;
}
void
GSC_NEIGHBOURS_done ()
{
- if (NULL == transport)
- return;
- GNUNET_CONTAINER_multihashmap_iterate (neighbours, &free_neighbour_helper,
- NULL);
- GNUNET_TRANSPORT_disconnect (transport);
- transport = NULL;
- GNUNET_CONTAINER_multihashmap_destroy (neighbours);
- neighbours = NULL;
+ if (NULL != transport)
+ {
+ GNUNET_TRANSPORT_disconnect (transport);
+ transport = NULL;
+ }
+ if (NULL != neighbours)
+ {
+ GNUNET_CONTAINER_multipeermap_iterate (neighbours,
+ &free_neighbour_helper,
+ NULL);
+ GNUNET_CONTAINER_multipeermap_destroy (neighbours);
+ neighbours = NULL;
+ }
}
/* end of gnunet-service-core_neighbours.c */
-