*/
enum PeerStateMachine
{
+ /**
+ * No handshake yet.
+ */
PEER_STATE_DOWN,
+
+ /**
+ * We've sent our session key.
+ */
PEER_STATE_KEY_SENT,
+
+ /**
+ * We've received the other peers session key.
+ */
PEER_STATE_KEY_RECEIVED,
+
+ /**
+ * The other peer has confirmed our session key with a message
+ * encrypted with his session key (which we got). Session is now fully up.
+ */
PEER_STATE_KEY_CONFIRMED
};
*/
struct Neighbour
{
- /**
- * We keep neighbours in a linked list (for now).
- */
- struct Neighbour *next;
/**
* Unencrypted messages destined for this peer.
static struct GNUNET_SERVER_NotificationContext *notifier;
/**
- * We keep neighbours in a linked list (for now).
+ * Map of peer identities to 'struct Neighbour'.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
+
+/**
+ * Neighbour entry for "this" peer.
*/
-static struct Neighbour *neighbours;
+static struct Neighbour self;
/**
* For creating statistics.
*/
static unsigned long long preference_sum;
-/**
- * Total number of neighbours we have.
- */
-static unsigned int neighbour_count;
-
/**
* How much inbound bandwidth are we supposed to be using per second?
- * FIXME: this value is not used!
*/
static unsigned long long bandwidth_target_in_bps;
}
+/**
+ * Helper function for update_preference_sum.
+ */
+static int
+update_preference (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ unsigned long long *ps = cls;
+ struct Neighbour *n = value;
+
+ n->current_preference /= 2;
+ *ps += n->current_preference;
+ return GNUNET_OK;
+}
+
+
/**
* A preference value for a neighbour was update. Update
* the preference sum accordingly.
static void
update_preference_sum (unsigned long long inc)
{
- struct Neighbour *n;
unsigned long long os;
os = preference_sum;
return; /* done! */
/* overflow! compensate by cutting all values in half! */
preference_sum = 0;
- n = neighbours;
- while (n != NULL)
- {
- n->current_preference /= 2;
- preference_sum += n->current_preference;
- n = n->next;
- }
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &update_preference,
+ &preference_sum);
GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO);
}
static struct Neighbour *
find_neighbour (const struct GNUNET_PeerIdentity *peer)
{
- struct Neighbour *ret;
-
- ret = neighbours;
- while ((ret != NULL) &&
- (0 != memcmp (&ret->peer,
- peer, sizeof (struct GNUNET_PeerIdentity))))
- ret = ret->next;
- return ret;
+ return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
}
GNUNET_i2s (&n->peer));
#endif
size = sizeof (struct PeerStatusNotifyMessage) +
- (n->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
n->ats_count,
0);
size = sizeof (struct PeerStatusNotifyMessage) +
- (n->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
}
psnm = (struct PeerStatusNotifyMessage*) buf;
psnm->header.size = htons (size);
unsigned int queue_size;
/* check if neighbour queue is empty enough! */
- queue_size = 0;
- mqe = n->messages;
- while (mqe != NULL)
- {
- queue_size++;
- mqe = mqe->next;
- }
- if (queue_size >= MAX_PEER_QUEUE_SIZE)
+ if (n != &self)
{
+ queue_size = 0;
+ mqe = n->messages;
+ while (mqe != NULL)
+ {
+ queue_size++;
+ mqe = mqe->next;
+ }
+ if (queue_size >= MAX_PEER_QUEUE_SIZE)
+ {
#if DEBUG_CORE_CLIENT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Not considering client transmission requests: queue full\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not considering client transmission requests: queue full\n");
#endif
- return; /* queue still full */
+ return; /* queue still full */
+ }
+ /* find highest priority request */
+ pos = n->active_client_request_head;
+ car = NULL;
+ while (pos != NULL)
+ {
+ if ( (car == NULL) ||
+ (pos->priority > car->priority) )
+ car = pos;
+ pos = pos->next;
+ }
}
- /* find highest priority request */
- pos = n->active_client_request_head;
- car = NULL;
- while (pos != NULL)
+ else
{
- if ( (car == NULL) ||
- (pos->priority > car->priority) )
- car = pos;
- pos = pos->next;
+ car = n->active_client_request_head;
}
if (car == NULL)
return; /* no pending requests */
GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
n->active_client_request_tail,
car);
- GNUNET_CONTAINER_multihashmap_remove (c->requests,
- &n->peer.hashPubKey,
- car);
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (c->requests,
+ &n->peer.hashPubKey,
+ car));
smr.header.size = htons (sizeof (struct SendMessageReady));
smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
smr.size = htons (car->msize);
struct ClientActiveRequest *car;
req = (const struct SendMessageRequest*) message;
- n = find_neighbour (&req->peer);
+ if (0 == memcmp (&req->peer,
+ &my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
+ n = &self;
+ else
+ n = find_neighbour (&req->peer);
if ( (n == NULL) ||
(GNUNET_YES != n->is_connected) ||
(n->status != PEER_STATE_KEY_CONFIRMED) )
}
+/**
+ * Notify client about an existing connection to one of our neighbours.
+ */
+static int
+notify_client_about_neighbour (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct Client *c = cls;
+ struct Neighbour *n = value;
+ size_t size;
+ char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+ struct GNUNET_TRANSPORT_ATS_Information *ats;
+ struct ConnectNotifyMessage *cnm;
+
+ size = sizeof (struct ConnectNotifyMessage) +
+ (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break (0);
+ /* recovery strategy: throw away performance data */
+ GNUNET_array_grow (n->ats,
+ n->ats_count,
+ 0);
+ size = sizeof (struct ConnectNotifyMessage) +
+ (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ }
+ cnm = (struct ConnectNotifyMessage*) buf;
+ cnm->header.size = htons (size);
+ cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+ cnm->ats_count = htonl (n->ats_count);
+ ats = &cnm->ats;
+ memcpy (ats,
+ n->ats,
+ sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
+ ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+ ats[n->ats_count].value = htonl (0);
+ 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");
+#endif
+ cnm->peer = n->peer;
+ send_to_client (c, &cnm->header, GNUNET_NO);
+ }
+ return GNUNET_OK;
+}
+
+
+
/**
* Handle CORE_INIT request.
*/
uint16_t msize;
const uint16_t *types;
uint16_t *wtypes;
- struct Neighbour *n;
- struct ConnectNotifyMessage *cnm;
- char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
- struct GNUNET_TRANSPORT_ATS_Information *ats;
- size_t size;
unsigned int i;
#if DEBUG_CORE_CLIENT
if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
{
/* notify new client about existing neighbours */
- n = neighbours;
- while (n != NULL)
- {
- size = sizeof (struct ConnectNotifyMessage) +
- (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- /* recovery strategy: throw away performance data */
- GNUNET_array_grow (n->ats,
- n->ats_count,
- 0);
- size = sizeof (struct ConnectNotifyMessage) +
- (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- }
- cnm = (struct ConnectNotifyMessage*) buf;
- cnm->header.size = htons (size);
- cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
- cnm->ats_count = htonl (n->ats_count);
- ats = &cnm->ats;
- memcpy (ats,
- n->ats,
- sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
- ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- ats[n->ats_count].value = htonl (0);
- 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");
-#endif
- cnm->peer = n->peer;
- send_to_client (c, &cnm->header, GNUNET_NO);
- }
- n = n->next;
- }
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ ¬ify_client_about_neighbour,
+ c);
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
peer.hashPubKey = *key;
n = find_neighbour (&peer);
+ GNUNET_assert (NULL != n);
GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
n->active_client_request_tail,
car);
}
+/**
+ * Helper function for handle_client_iterate_peers.
+ *
+ * @param cls the 'struct GNUNET_SERVER_TransmitContext' to queue replies
+ * @param key identity of the connected peer
+ * @param value the 'struct Neighbour' for the peer
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+queue_connect_message (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_SERVER_TransmitContext *tc = cls;
+ struct Neighbour *n = value;
+ char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+ struct GNUNET_TRANSPORT_ATS_Information *ats;
+ size_t size;
+ struct ConnectNotifyMessage *cnm;
+
+ cnm = (struct ConnectNotifyMessage*) buf;
+ if (n->status != PEER_STATE_KEY_CONFIRMED)
+ return GNUNET_OK;
+ size = sizeof (struct ConnectNotifyMessage) +
+ (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break (0);
+ /* recovery strategy: throw away performance data */
+ GNUNET_array_grow (n->ats,
+ n->ats_count,
+ 0);
+ size = sizeof (struct PeerStatusNotifyMessage) +
+ n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ }
+ cnm = (struct ConnectNotifyMessage*) buf;
+ cnm->header.size = htons (size);
+ cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+ cnm->ats_count = htonl (n->ats_count);
+ ats = &cnm->ats;
+ memcpy (ats,
+ n->ats,
+ n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
+ ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+ ats[n->ats_count].value = htonl (0);
+#if DEBUG_CORE_CLIENT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending `%s' message to client.\n",
+ "NOTIFY_CONNECT");
+#endif
+ cnm->peer = n->peer;
+ GNUNET_SERVER_transmit_context_append_message (tc,
+ &cnm->header);
+ return GNUNET_OK;
+}
+
+
/**
* Handle CORE_ITERATE_PEERS request.
*
const struct GNUNET_MessageHeader *message)
{
- struct Neighbour *n;
- struct ConnectNotifyMessage *cnm;
struct GNUNET_MessageHeader done_msg;
struct GNUNET_SERVER_TransmitContext *tc;
- char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
- struct GNUNET_TRANSPORT_ATS_Information *ats;
- size_t size;
-
+ int msize;
/* notify new client about existing neighbours */
+
+ msize = ntohs(message->size);
tc = GNUNET_SERVER_transmit_context_create (client);
- cnm = (struct ConnectNotifyMessage*) buf;
- n = neighbours;
- while (n != NULL)
- {
- if (n->status == PEER_STATE_KEY_CONFIRMED)
- {
- size = sizeof (struct ConnectNotifyMessage) +
- (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- /* recovery strategy: throw away performance data */
- GNUNET_array_grow (n->ats,
- n->ats_count,
- 0);
- size = sizeof (struct PeerStatusNotifyMessage) +
- (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- }
- cnm = (struct ConnectNotifyMessage*) buf;
- cnm->header.size = htons (size);
- cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
- cnm->ats_count = htonl (n->ats_count);
- ats = &cnm->ats;
- memcpy (ats,
- n->ats,
- n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
- ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- ats[n->ats_count].value = htonl (0);
-#if DEBUG_CORE_CLIENT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending `%s' message to client.\n",
- "NOTIFY_CONNECT");
-#endif
- cnm->peer = n->peer;
- GNUNET_SERVER_transmit_context_append_message (tc,
- &cnm->header);
- }
- n = n->next;
- }
+ if (msize == sizeof(struct GNUNET_MessageHeader))
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
+ else
+ GNUNET_break(0);
+
done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
- done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+ done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
+ GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
+ GNUNET_SERVER_transmit_context_run (tc,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
+/**
+ * Handle CORE_ITERATE_PEERS request. Notify client about existing neighbours.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
+ */
+static void
+handle_client_have_peer (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+
+{
+ struct GNUNET_MessageHeader done_msg;
+ struct GNUNET_SERVER_TransmitContext *tc;
+ struct GNUNET_PeerIdentity *peer;
+
+ tc = GNUNET_SERVER_transmit_context_create (client);
+ peer = (struct GNUNET_PeerIdentity *) &message[1];
+ GNUNET_CONTAINER_multihashmap_get_multiple(neighbours,
+ &peer->hashPubKey,
+ &queue_connect_message,
+ tc);
+ done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+ done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
GNUNET_SERVER_transmit_context_run (tc,
GNUNET_TIME_UNIT_FOREVER_REL);
/**
* Handle REQUEST_INFO request.
+ *
+ * @param cls unused
+ * @param client client sending the request
+ * @param message iteration request message
*/
static void
handle_client_request_info (void *cls,
int32_t want_reserv;
int32_t got_reserv;
unsigned long long old_preference;
+ struct GNUNET_TIME_Relative rdelay;
+ rdelay = GNUNET_TIME_relative_get_zero();
#if DEBUG_CORE_CLIENT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Core service receives `%s' request.\n", "REQUEST_INFO");
}
else if (want_reserv > 0)
{
- if (GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
- want_reserv).rel_value == 0)
+ rdelay = GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
+ want_reserv);
+ if (rdelay.rel_value == 0)
got_reserv = want_reserv;
else
got_reserv = 0; /* all or nothing */
(int) got_reserv);
#endif
cim.reserved_amount = htonl (got_reserv);
+ cim.reserve_delay = GNUNET_TIME_relative_hton (rdelay);
cim.rim_id = rcm->rim_id;
cim.bw_out = n->bw_out;
cim.preference = n->current_preference;
if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (n->keep_alive_task);
if (n->status == PEER_STATE_KEY_CONFIRMED)
- GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), -1, GNUNET_NO);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# established sessions"),
+ -1,
+ GNUNET_NO);
GNUNET_array_grow (n->ats, n->ats_count, 0);
GNUNET_free_non_null (n->public_key);
GNUNET_free_non_null (n->pending_ping);
static void
consider_free_neighbour (struct Neighbour *n)
{
- struct Neighbour *pos;
- struct Neighbour *prev;
struct GNUNET_TIME_Relative left;
if ( (n->th != NULL) ||
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--;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (neighbours,
+ &n->peer.hashPubKey,
+ n));
GNUNET_STATISTICS_set (stats,
gettext_noop ("# neighbour entries allocated"),
- neighbour_count,
+ GNUNET_CONTAINER_multihashmap_size (neighbours),
GNUNET_NO);
free_neighbour (n);
}
* @return number of bytes transmitted
*/
static size_t
-notify_encrypted_transmit_ready (void *cls, size_t size, void *buf)
+notify_encrypted_transmit_ready (void *cls,
+ size_t size,
+ void *buf)
{
struct Neighbour *n = cls;
struct MessageEntry *m;
}
GNUNET_free (m);
consider_free_neighbour (n);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# encrypted bytes given to transport"),
+ ret,
+ GNUNET_NO);
return ret;
}
GNUNET_break (0);
return GNUNET_SYSERR;
}
- GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes decrypted"), size, GNUNET_NO);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# bytes decrypted"),
+ size,
+ GNUNET_NO);
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Decrypted %u bytes from `%4s' using key %u, IV %u\n",
GNUNET_i2s (pid));
#endif
n = GNUNET_malloc (sizeof (struct Neighbour));
- n->next = neighbours;
- neighbours = n;
- neighbour_count++;
- GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
n->peer = *pid;
GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
now = GNUNET_TIME_absolute_get ();
n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
UINT32_MAX);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (neighbours,
+ &n->peer.hashPubKey,
+ n,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
+ GNUNET_CONTAINER_multihashmap_size (neighbours), GNUNET_NO);
neighbour_quota_update (n, NULL);
consider_free_neighbour (n);
return n;
msize -= sizeof (struct SendMessage);
if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
{
- /* FIXME: should we not allow loopback-injection here? */
- GNUNET_break (0);
+ /* loopback */
+ GNUNET_SERVER_mst_receive (mst,
+ &self,
+ (const char*) &sm[1],
+ msize,
+ GNUNET_YES,
+ GNUNET_NO);
if (client != NULL)
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
n = find_neighbour (&sm->peer);
GNUNET_i2s (&sm->peer),
(unsigned int) msize);
#endif
+ GNUNET_break (0 == ntohl (sm->reserved));
e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
e->priority = ntohl (sm->priority);
e->size = msize;
+ if (GNUNET_YES != (int) ntohl (sm->cork))
+ e->got_slack = GNUNET_YES;
memcpy (&e[1], &sm[1], msize);
/* insert, keep list sorted by deadline */
* @return number of bytes transmitted
*/
static size_t
-notify_transport_connect_done (void *cls, size_t size, void *buf)
+notify_transport_connect_done (void *cls,
+ size_t size,
+ void *buf)
{
struct Neighbour *n = cls;
/* transport should only call us to transmit a message after
* telling us about a successful connection to the respective peer */
#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout on notify connect!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Timeout on notify connect!\n");
#endif
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connection requests timed out in transport"),
+ 1,
+ GNUNET_NO);
return 0;
}
if (buf == NULL)
{
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connection requests timed out in transport"),
+ 1,
+ GNUNET_NO);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
_("Failed to connect to `%4s': transport failed to connect\n"),
GNUNET_i2s (&n->peer));
struct Neighbour *n;
struct GNUNET_TIME_Relative timeout;
- if (0 == memcmp (&cm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
+ if (0 == memcmp (&cm->peer,
+ &my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
{
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ /* In this case a client has asked us to connect to ourselves, not really an error! */
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
+ timeout = GNUNET_TIME_relative_ntoh (cm->timeout);
+ GNUNET_break (ntohl (cm->reserved) == 0);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
n = find_neighbour (&cm->peer);
if (n == NULL)
if ( (GNUNET_YES == n->is_connected) ||
(n->th != NULL) )
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Core received `%s' request for `%4s', already connected!\n",
- "REQUEST_CONNECT",
- GNUNET_i2s (&cm->peer));
+ if (GNUNET_YES == n->is_connected)
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connection requests ignored (already connected)"),
+ 1,
+ GNUNET_NO);
+ else
+ {
+ GNUNET_TRANSPORT_notify_transmit_ready_cancel(n->th);
+ n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
+ &cm->peer,
+ sizeof (struct GNUNET_MessageHeader), 0,
+ timeout,
+ ¬ify_transport_connect_done,
+ n);
+ GNUNET_break (NULL != n->th);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connection requests retried (due to repeat request connect)"),
+ 1,
+ GNUNET_NO);
+ }
return; /* already connected, or at least trying */
}
- GNUNET_STATISTICS_update (stats, gettext_noop ("# connection requests received"), 1, GNUNET_NO);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connection requests received"),
+ 1,
+ GNUNET_NO);
+#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Core received `%s' request for `%4s', will try to establish connection\n",
"REQUEST_CONNECT",
GNUNET_i2s (&cm->peer));
+#endif
- timeout = GNUNET_TIME_relative_ntoh (cm->timeout);
/* ask transport to connect to the peer */
n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
&cm->peer,
* @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 err_msg NULL if successful, otherwise contains error message
*/
static void
process_hello_retry_send_key (void *cls,
const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Message *hello)
+ const struct GNUNET_HELLO_Message *hello,
+ const char *err_msg)
{
struct Neighbour *n = cls;
+ if (err_msg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Error in communication with PEERINFO service\n"));
+ /* return; */
+ }
+
if (peer == NULL)
{
#if DEBUG_CORE
* @param cls pointer to the set key message
* @param peer the peer for which this is the HELLO
* @param hello HELLO message of that peer
+ * @param err_msg NULL if successful, otherwise contains error message
*/
static void
process_hello_retry_handle_set_key (void *cls,
const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Message *hello)
+ const struct GNUNET_HELLO_Message *hello,
+ const char *err_msg)
{
struct Neighbour *n = cls;
struct SetKeyMessage *sm = n->skm;
+ if (err_msg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Error in communication with PEERINFO service\n"));
+ /* return; */
+ }
+
if (peer == NULL)
{
n->skm = NULL;
if (ats_count == 0)
return;
- for (i=0;i<ats_count;i++)
+ for (i = 0; i < ats_count; i++)
{
- for (j=0;j<n->ats_count;j++)
+ for (j=0;j < n->ats_count; j++)
{
if (n->ats[j].type == ats[i].type)
{
break;
}
}
- if (j == n->ats_count)
- GNUNET_array_append (n->ats,
- n->ats_count,
- *ats);
+ if (j == n->ats_count)
+ {
+ GNUNET_array_append (n->ats,
+ n->ats_count,
+ ats[i]);
+ }
}
}
n->ats_count,
0);
size = sizeof (struct PeerStatusNotifyMessage) +
- (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
}
cnm = (struct ConnectNotifyMessage*) buf;
cnm->header.size = htons (size);
cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
cnm->ats_count = htonl (n->ats_count);
+ cnm->peer = n->peer;
mats = &cnm->ats;
memcpy (mats,
n->ats,
const void *m, size_t msize)
{
size_t size = msize + sizeof (struct NotifyTrafficMessage) +
- (sender->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
char buf[size];
struct NotifyTrafficMessage *ntm;
struct GNUNET_TRANSPORT_ATS_Information *ats;
sender->ats_count,
0);
size = msize + sizeof (struct NotifyTrafficMessage) +
- (sender->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
}
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
n = find_neighbour (peer);
if (n == NULL)
n = create_neighbour (peer);
- changed = GNUNET_YES; /* FIXME... */
+ changed = GNUNET_NO;
up = (n->status == PEER_STATE_KEY_CONFIRMED);
type = ntohs (message->type);
size = ntohs (message->size);
GNUNET_break_op (0);
return;
}
- GNUNET_STATISTICS_update (stats, gettext_noop ("# session keys received"), 1, GNUNET_NO);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# session keys received"),
+ 1,
+ GNUNET_NO);
handle_set_key (n,
(const struct SetKeyMessage *) message,
ats, ats_count);
if ((n->status != PEER_STATE_KEY_RECEIVED) &&
(n->status != PEER_STATE_KEY_CONFIRMED))
{
- GNUNET_break_op (0);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# failed to decrypt message (no session key)"),
+ 1,
+ GNUNET_NO);
+ send_key (n);
return;
}
handle_encrypted_message (n,
changed = GNUNET_YES;
if (!up)
{
- GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), 1, GNUNET_NO);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# established sessions"),
+ 1,
+ GNUNET_NO);
n->time_established = now;
}
if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
unsigned long long distributable;
uint64_t need_per_peer;
uint64_t need_per_second;
+ unsigned int neighbour_count;
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
divides by a bit more to avoid division by zero AND to
account for possibility of new neighbours joining any time
AND to convert to double... */
+ neighbour_count = GNUNET_CONTAINER_multihashmap_size (neighbours);
+ if (neighbour_count == 0)
+ return;
if (preference_sum == 0)
{
pref_rel = 1.0 / (double) neighbour_count;
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peer `%4s' disconnected from us; received notification from transport.\n", GNUNET_i2s (peer));
+ "Peer `%4s' disconnected from us; received notification from transport.\n",
+ GNUNET_i2s (peer));
#endif
-
n = find_neighbour (peer);
if (n == NULL)
{
GNUNET_break (0);
return;
}
- GNUNET_break (n->is_connected);
+ GNUNET_break (n->is_connected == GNUNET_YES);
if (n->status == PEER_STATE_KEY_CONFIRMED)
{
cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
+ cnm.reserved = htonl (0);
cnm.peer = *peer;
send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# established sessions"),
+ -1,
+ GNUNET_NO);
}
/* On transport disconnect transport doesn't cancel requests, so must do so here. */
if (n->th != NULL)
{
- GNUNET_TRANSPORT_notify_transmit_ready_cancel(n->th);
+ GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
+ n->th = NULL;
}
- n->th = NULL;
-
n->is_connected = GNUNET_NO;
n->status = PEER_STATE_DOWN;
while (NULL != (car = n->active_client_request_head))
}
+/**
+ * Wrapper around 'free_neighbour'; helper for 'cleaning_task'.
+ */
+static int
+free_neighbour_helper (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct Neighbour *n = value;
+
+ free_neighbour (n);
+ return GNUNET_OK;
+}
+
+
/**
* Last task run during shutdown. Disconnects us from
* the transport.
static void
cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct Neighbour *n;
struct Client *c;
#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Core service shutting down.\n");
#endif
- while (NULL != (n = neighbours))
- {
- neighbours = n->next;
- GNUNET_assert (neighbour_count > 0);
- neighbour_count--;
- free_neighbour (n);
- }
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &free_neighbour_helper,
+ NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ neighbours = NULL;
+ GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), 0, GNUNET_NO);
GNUNET_assert (transport != NULL);
GNUNET_TRANSPORT_disconnect (transport);
transport = NULL;
- GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
GNUNET_SERVER_notification_context_destroy (notifier);
notifier = NULL;
while (NULL != (c = clients))
{&handle_client_iterate_peers, NULL,
GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
sizeof (struct GNUNET_MessageHeader)},
+ {&handle_client_have_peer, NULL,
+ GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
+ sizeof (struct GNUNET_MessageHeader) + sizeof(struct GNUNET_PeerIdentity)},
{&handle_client_request_info, NULL,
GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
sizeof (struct RequestInfoMessage)},
};
char *keyfile;
- cfg = c;
+ cfg = c;
/* parse configuration */
if (
(GNUNET_OK !=
GNUNET_SCHEDULER_shutdown ();
return;
}
+ neighbours = GNUNET_CONTAINER_multihashmap_create (128);
GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
GNUNET_CRYPTO_hash (&my_public_key,
sizeof (my_public_key), &my_identity.hashPubKey);
+ self.public_key = &my_public_key;
+ self.peer = my_identity;
+ self.last_activity = GNUNET_TIME_UNIT_FOREVER_ABS;
+ self.status = PEER_STATE_KEY_CONFIRMED;
+ self.is_connected = GNUNET_YES;
/* setup notification */
notifier = GNUNET_SERVER_notification_context_create (server,
MAX_NOTIFY_QUEUE);