car = pos;
pos = pos->next;
}
- if (car == NULL)
- return; /* no pending requests */
}
else
{
car = n->active_client_request_head;
- if (car == NULL)
- return;
}
+ if (car == NULL)
+ return; /* no pending requests */
#if DEBUG_CORE_CLIENT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Permitting client transmission request to `%s'\n",
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);
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,
{
struct GNUNET_MessageHeader done_msg;
struct GNUNET_SERVER_TransmitContext *tc;
-
+ int msize;
/* notify new client about existing neighbours */
+
+ msize = ntohs(message->size);
tc = GNUNET_SERVER_transmit_context_create (client);
- GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
+ 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_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);
/**
* 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);
* @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 (&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;
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)
#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))
{&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)},
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;