[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r33127 - in gnunet/src: core include
From: |
gnunet |
Subject: |
[GNUnet-SVN] r33127 - in gnunet/src: core include |
Date: |
Wed, 23 Apr 2014 13:04:54 +0200 |
Author: grothoff
Date: 2014-04-23 13:04:53 +0200 (Wed, 23 Apr 2014)
New Revision: 33127
Modified:
gnunet/src/core/gnunet-service-core_kx.c
gnunet/src/core/gnunet-service-core_sessions.c
gnunet/src/core/gnunet-service-core_sessions.h
gnunet/src/core/gnunet-service-core_typemap.c
gnunet/src/core/gnunet-service-core_typemap.h
gnunet/src/include/gnunet_protocols.h
Log:
fix #3348: send typemap confirmation messages, perform faster typemap
retransmissions for unconfirmed typemaps, restart retransmissions on reconnect
Modified: gnunet/src/core/gnunet-service-core_kx.c
===================================================================
--- gnunet/src/core/gnunet-service-core_kx.c 2014-04-23 10:47:47 UTC (rev
33126)
+++ gnunet/src/core/gnunet-service-core_kx.c 2014-04-23 11:04:53 UTC (rev
33127)
@@ -821,13 +821,15 @@
(GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
(end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) )
{
- GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys
ignored"),
+ GNUNET_STATISTICS_update (GSC_stats,
+ gettext_noop ("# old ephemeral keys ignored"),
1, GNUNET_NO);
return;
}
start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
- GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# ephemeral keys
received"),
+ GNUNET_STATISTICS_update (GSC_stats,
+ gettext_noop ("# ephemeral keys received"),
1, GNUNET_NO);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -884,11 +886,17 @@
break;
case GNUNET_CORE_KX_STATE_KEY_SENT:
/* fine, need to send our key after updating our status, see below */
+ GSC_SESSIONS_reinit (&kx->peer);
break;
case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
+ /* other peer already got our key, but typemap did go down */
+ GSC_SESSIONS_reinit (&kx->peer);
+ break;
case GNUNET_CORE_KX_STATE_UP:
+ /* other peer already got our key, typemap NOT down */
+ break;
case GNUNET_CORE_KX_STATE_REKEY_SENT:
- /* other peer already got our key */
+ /* other peer already got our key, typemap NOT down */
break;
default:
GNUNET_break (0);
@@ -1509,6 +1517,9 @@
case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
GSC_SESSIONS_set_typemap (dmc->peer, m);
return GNUNET_OK;
+ case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
+ GSC_SESSIONS_confirm_typemap (dmc->peer, m);
+ return GNUNET_OK;
default:
GSC_CLIENTS_deliver_message (dmc->peer, m,
ntohs (m->size),
Modified: gnunet/src/core/gnunet-service-core_sessions.c
===================================================================
--- gnunet/src/core/gnunet-service-core_sessions.c 2014-04-23 10:47:47 UTC
(rev 33126)
+++ gnunet/src/core/gnunet-service-core_sessions.c 2014-04-23 11:04:53 UTC
(rev 33127)
@@ -137,6 +137,12 @@
GNUNET_SCHEDULER_TaskIdentifier typemap_task;
/**
+ * Retransmission delay we currently use for the typemap
+ * transmissions (if not confirmed).
+ */
+ struct GNUNET_TIME_Relative typemap_delay;
+
+ /**
* Is the neighbour queue empty and thus ready for us
* to transmit an encrypted message?
*/
@@ -151,7 +157,35 @@
};
+GNUNET_NETWORK_STRUCT_BEGIN
+
/**
+ * Message sent to confirm that a typemap was received.
+ */
+struct TypeMapConfirmationMessage
+{
+
+ /**
+ * Header with type #GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP.
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Reserved, always zero.
+ */
+ uint32_t reserved GNUNET_PACKED;
+
+ /**
+ * Hash of the (decompressed) type map that was received.
+ */
+ struct GNUNET_HashCode tm_hash;
+
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
+/**
* Map of peer identities to `struct Session`.
*/
static struct GNUNET_CONTAINER_MultiPeerMap *sessions;
@@ -203,10 +237,16 @@
}
while (NULL != (sme = session->sme_head))
{
- GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme);
+ GNUNET_CONTAINER_DLL_remove (session->sme_head,
+ session->sme_tail,
+ sme);
GNUNET_free (sme);
}
- GNUNET_SCHEDULER_cancel (session->typemap_task);
+ if (GNUNET_SCHEDULER_NO_TASK != session->typemap_task)
+ {
+ GNUNET_SCHEDULER_cancel (session->typemap_task);
+ session->typemap_task = GNUNET_SCHEDULER_NO_TASK;
+ }
GSC_CLIENTS_notify_clients_about_neighbour (&session->peer,
session->tmap, NULL);
GNUNET_assert (GNUNET_YES ==
@@ -224,7 +264,7 @@
/**
* Transmit our current typemap message to the other peer.
- * (Done periodically in case an update got lost).
+ * (Done periodically until the typemap is confirmed).
*
* @param cls the `struct Session *`
* @param tc unused
@@ -237,20 +277,14 @@
struct GNUNET_MessageHeader *hdr;
struct GNUNET_TIME_Relative delay;
- if (0 == session->first_typemap)
- {
- delay = TYPEMAP_FREQUENCY_FIRST;
- session->first_typemap = 1;
- }
- else
- {
- delay = TYPEMAP_FREQUENCY;
- }
+ session->typemap_delay = GNUNET_TIME_STD_BACKOFF (session->typemap_delay);
+ delay = session->typemap_delay;
/* randomize a bit to avoid spont. sync */
delay.rel_value_us +=
GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000 * 1000);
session->typemap_task =
- GNUNET_SCHEDULER_add_delayed (delay, &transmit_typemap_task, session);
+ GNUNET_SCHEDULER_add_delayed (delay,
+ &transmit_typemap_task, session);
GNUNET_STATISTICS_update (GSC_stats,
gettext_noop ("# type map refreshes sent"), 1,
GNUNET_NO);
@@ -261,6 +295,24 @@
/**
+ * Restart the typemap task for the given session.
+ *
+ * @param session session to restart typemap transmission for
+ */
+static void
+start_typemap_task (struct Session *session)
+{
+ if (GNUNET_SCHEDULER_NO_TASK != session->typemap_task)
+ GNUNET_SCHEDULER_cancel (session->typemap_task);
+ session->typemap_delay = GNUNET_TIME_UNIT_SECONDS;
+ session->typemap_task =
+ GNUNET_SCHEDULER_add_delayed (session->typemap_delay,
+ &transmit_typemap_task,
+ session);
+}
+
+
+/**
* Create a session, a key exchange was just completed.
*
* @param peer peer that is now connected
@@ -279,10 +331,9 @@
session->tmap = GSC_TYPEMAP_create ();
session->peer = *peer;
session->kxinfo = kx;
- session->typemap_task =
- GNUNET_SCHEDULER_add_now (&transmit_typemap_task, session);
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (sessions, peer,
+ GNUNET_CONTAINER_multipeermap_put (sessions,
+ &session->peer,
session,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"),
@@ -290,10 +341,83 @@
GNUNET_NO);
GSC_CLIENTS_notify_clients_about_neighbour (peer,
NULL, session->tmap);
+ start_typemap_task (session);
}
/**
+ * The other peer has indicated that he 'lost' the session
+ * (KX down), reinitialize the session on our end, in particular
+ * this means to restart the typemap transmission.
+ *
+ * @param peer peer that is now connected
+ */
+void
+GSC_SESSIONS_reinit (const struct GNUNET_PeerIdentity *peer)
+{
+ struct Session *session;
+
+ session = find_session (peer);
+ if (NULL == session)
+ {
+ /* KX/session is new for both sides; thus no need to restart what
+ has not yet begun */
+ return;
+ }
+ start_typemap_task (session);
+}
+
+
+/**
+ * The other peer has confirmed receiving our type map,
+ * check if it is current and if so, stop retransmitting it.
+ *
+ * @param peer peer that confirmed the type map
+ * @param msg confirmation message we received
+ */
+void
+GSC_SESSIONS_confirm_typemap (const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct TypeMapConfirmationMessage *cmsg;
+ struct Session *session;
+
+ session = find_session (peer);
+ if (NULL == session)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (ntohs (msg->size) != sizeof (struct TypeMapConfirmationMessage))
+ {
+ GNUNET_break_op (0);
+ return;
+ }
+ cmsg = (const struct TypeMapConfirmationMessage *) msg;
+ if (GNUNET_YES !=
+ GSC_TYPEMAP_check_hash (&cmsg->tm_hash))
+ {
+ /* our typemap has changed in the meantime, do not
+ accept confirmation */
+ GNUNET_STATISTICS_update (GSC_stats,
+ gettext_noop
+ ("# outdated typemap confirmations received"),
+ 1, GNUNET_NO);
+ return;
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != session->typemap_task)
+ {
+ GNUNET_SCHEDULER_cancel (session->typemap_task);
+ session->typemap_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_STATISTICS_update (GSC_stats,
+ gettext_noop
+ ("# valid typemap confirmations received"),
+ 1, GNUNET_NO);
+}
+
+
+/**
* Notify the given client about the session (client is new).
*
* @param cls the `struct GSC_Client`
@@ -325,7 +449,8 @@
GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client)
{
/* notify new client about existing sessions */
- GNUNET_CONTAINER_multipeermap_iterate (sessions,
¬ify_client_about_session,
+ GNUNET_CONTAINER_multipeermap_iterate (sessions,
+ ¬ify_client_about_session,
client);
}
@@ -592,11 +717,14 @@
size_t used;
used = 0;
- while ((NULL != (pos = session->sme_head)) && (used + pos->size <= msize))
+ while ( (NULL != (pos = session->sme_head)) &&
+ (used + pos->size <= msize) )
{
memcpy (&pbuf[used], &pos[1], pos->size);
used += pos->size;
- GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, pos);
+ GNUNET_CONTAINER_DLL_remove (session->sme_head,
+ session->sme_tail,
+ pos);
GNUNET_free (pos);
}
/* compute average payload size */
@@ -619,7 +747,8 @@
/**
- * Send a message to the neighbour now.
+ * Send an updated typemap message to the neighbour now,
+ * and restart typemap transmissions.
*
* @param cls the message
* @param key neighbour's identity
@@ -627,38 +756,42 @@
* @return always #GNUNET_OK
*/
static int
-do_send_message (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
+do_restart_typemap_message (void *cls,
+ const struct GNUNET_PeerIdentity *key,
+ void *value)
{
const struct GNUNET_MessageHeader *hdr = cls;
struct Session *session = value;
- struct SessionMessageEntry *m;
+ struct SessionMessageEntry *sme;
uint16_t size;
size = ntohs (hdr->size);
- m = GNUNET_malloc (sizeof (struct SessionMessageEntry) + size);
- memcpy (&m[1], hdr, size);
- m->size = size;
- m->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
- GNUNET_CONTAINER_DLL_insert_tail (session->sme_head, session->sme_tail, m);
+ sme = GNUNET_malloc (sizeof (struct SessionMessageEntry) + size);
+ memcpy (&sme[1], hdr, size);
+ sme->size = size;
+ sme->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
+ GNUNET_CONTAINER_DLL_insert (session->sme_head,
+ session->sme_tail,
+ sme);
try_transmission (session);
+ start_typemap_task (session);
return GNUNET_OK;
}
/**
- * Broadcast a message to all neighbours.
+ * Broadcast an updated typemap message to all neighbours.
+ * Restarts the retransmissions until the typemaps are confirmed.
*
* @param msg message to transmit
*/
void
-GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg)
+GSC_SESSIONS_broadcast_typemap (const struct GNUNET_MessageHeader *msg)
{
if (NULL == sessions)
return;
GNUNET_CONTAINER_multipeermap_iterate (sessions,
- &do_send_message,
+ &do_restart_typemap_message,
(void *) msg);
}
@@ -732,7 +865,7 @@
/**
- * We've received a typemap message from a peer, update ours.
+ * We have received a typemap message from a peer, update ours.
* Notifies clients about the session.
*
* @param peer peer this is about
@@ -744,6 +877,8 @@
{
struct Session *session;
struct GSC_TypeMap *nmap;
+ struct SessionMessageEntry *sme;
+ struct TypeMapConfirmationMessage *tmc;
nmap = GSC_TYPEMAP_get_from_message (msg);
if (NULL == nmap)
@@ -754,8 +889,24 @@
GNUNET_break (0);
return;
}
+ sme = GNUNET_malloc (sizeof (struct SessionMessageEntry) +
+ sizeof (struct TypeMapConfirmationMessage));
+ sme->deadline = GNUNET_TIME_absolute_get ();
+ sme->size = sizeof (struct TypeMapConfirmationMessage);
+ sme->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
+ tmc = (struct TypeMapConfirmationMessage *) &sme[1];
+ tmc->header.size = htons (sizeof (struct TypeMapConfirmationMessage));
+ tmc->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP);
+ tmc->reserved = htonl (0);
+ GSC_TYPEMAP_hash (nmap,
+ &tmc->tm_hash);
+ GNUNET_CONTAINER_DLL_insert (session->sme_head,
+ session->sme_tail,
+ sme);
+ try_transmission (session);
GSC_CLIENTS_notify_clients_about_neighbour (peer,
- session->tmap, nmap);
+ session->tmap,
+ nmap);
GSC_TYPEMAP_destroy (session->tmap);
session->tmap = nmap;
}
@@ -776,7 +927,9 @@
struct Session *session;
struct GSC_TypeMap *nmap;
- if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct
GNUNET_PeerIdentity)))
+ if (0 == memcmp (peer,
+ &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
return;
session = find_session (peer);
GNUNET_assert (NULL != session);
@@ -796,12 +949,14 @@
void
GSC_SESSIONS_init ()
{
- sessions = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
+ sessions = GNUNET_CONTAINER_multipeermap_create (128,
+ GNUNET_YES);
}
/**
- * Helper function for GSC_SESSIONS_handle_client_iterate_peers.
+ * Helper function for #GSC_SESSIONS_done() to free all
+ * active sessions.
*
* @param cls NULL
* @param key identity of the connected peer
@@ -828,7 +983,8 @@
{
if (NULL != sessions)
{
- GNUNET_CONTAINER_multipeermap_iterate (sessions, &free_session_helper,
NULL);
+ GNUNET_CONTAINER_multipeermap_iterate (sessions,
+ &free_session_helper, NULL);
GNUNET_CONTAINER_multipeermap_destroy (sessions);
sessions = NULL;
}
Modified: gnunet/src/core/gnunet-service-core_sessions.h
===================================================================
--- gnunet/src/core/gnunet-service-core_sessions.h 2014-04-23 10:47:47 UTC
(rev 33126)
+++ gnunet/src/core/gnunet-service-core_sessions.h 2014-04-23 11:04:53 UTC
(rev 33127)
@@ -42,6 +42,29 @@
/**
+ * The other peer has indicated that he 'lost' the session
+ * (KX down), reinitialize the session on our end, in particular
+ * this means to restart the typemap transmission.
+ *
+ * @param peer peer that is now connected
+ */
+void
+GSC_SESSIONS_reinit (const struct GNUNET_PeerIdentity *peer);
+
+
+/**
+ * The other peer has confirmed receiving our type map,
+ * check if it is current and if so, stop retransmitting it.
+ *
+ * @param peer peer that confirmed the type map
+ * @param msg confirmation message we received
+ */
+void
+GSC_SESSIONS_confirm_typemap (const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_MessageHeader *msg);
+
+
+/**
* End the session with the given peer (we are no longer
* connected).
*
@@ -102,12 +125,13 @@
/**
- * Broadcast a message to all neighbours.
+ * Broadcast an updated typemap message to all neighbours.
+ * Restarts the retransmissions until the typemaps are confirmed.
*
* @param msg message to transmit
*/
void
-GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg);
+GSC_SESSIONS_broadcast_typemap (const struct GNUNET_MessageHeader *msg);
/**
Modified: gnunet/src/core/gnunet-service-core_typemap.c
===================================================================
--- gnunet/src/core/gnunet-service-core_typemap.c 2014-04-23 10:47:47 UTC
(rev 33126)
+++ gnunet/src/core/gnunet-service-core_typemap.c 2014-04-23 11:04:53 UTC
(rev 33127)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2011 Christian Grothoff (and other contributing authors)
+ (C) 2011-2014 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -51,8 +51,65 @@
*/
static uint8_t map_counters[UINT16_MAX + 1];
+/**
+ * Current hash of our (uncompressed) type map.
+ * Lazily computed when needed.
+ */
+static struct GNUNET_HashCode my_tm_hash;
/**
+ * Is #my_tm_hash() current with respect to our type map?
+ */
+static int hash_current;
+
+
+/**
+ * Our type map changed, recompute its hash.
+ */
+static void
+rehash_typemap ()
+{
+ hash_current = GNUNET_NO;
+}
+
+
+/**
+ * Hash the contents of a type map.
+ *
+ * @param tm map to hash
+ * @param hc where to store the hash code
+ */
+void
+GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm,
+ struct GNUNET_HashCode *hc)
+{
+ GNUNET_CRYPTO_hash (tm,
+ sizeof (struct GSC_TypeMap),
+ hc);
+}
+
+
+/**
+ * Check if the given hash matches our current type map.
+ *
+ * @param hc hash code to check if it matches our type map
+ * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
+ */
+int
+GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc)
+{
+ if (GNUNET_NO == hash_current)
+ {
+ GSC_TYPEMAP_hash (&my_type_map,
+ &my_tm_hash);
+ hash_current = GNUNET_YES;
+ }
+ return (0 == memcmp (hc, &my_tm_hash, sizeof (struct GNUNET_HashCode)))
+ ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
* Compute a type map message for this peer.
*
* @return this peers current type map message.
@@ -152,7 +209,7 @@
GNUNET_STATISTICS_update (GSC_stats,
gettext_noop ("# updates to my type map"), 1,
GNUNET_NO);
- GSC_SESSIONS_broadcast (hdr);
+ GSC_SESSIONS_broadcast_typemap (hdr);
GNUNET_free (hdr);
}
@@ -180,7 +237,10 @@
}
}
if (GNUNET_YES == changed)
+ {
+ rehash_typemap ();
broadcast_my_type_map ();
+ }
}
@@ -207,7 +267,10 @@
}
}
if (GNUNET_YES == changed)
+ {
+ rehash_typemap ();
broadcast_my_type_map ();
+ }
}
Modified: gnunet/src/core/gnunet-service-core_typemap.h
===================================================================
--- gnunet/src/core/gnunet-service-core_typemap.h 2014-04-23 10:47:47 UTC
(rev 33126)
+++ gnunet/src/core/gnunet-service-core_typemap.h 2014-04-23 11:04:53 UTC
(rev 33127)
@@ -67,6 +67,27 @@
/**
+ * Check if the given hash matches our current type map.
+ *
+ * @param hc hash code to check if it matches our type map
+ * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
+ */
+int
+GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc);
+
+
+/**
+ * Hash the contents of a type map.
+ *
+ * @param tm map to hash
+ * @param hc where to store the hash code
+ */
+void
+GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm,
+ struct GNUNET_HashCode *hc);
+
+
+/**
* Extract a type map from a
* #GNUNET_MESSAGE_TYPE_CORE_COMRESSED_TYPE_MAP or
* #GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP message.
Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h 2014-04-23 10:47:47 UTC (rev
33126)
+++ gnunet/src/include/gnunet_protocols.h 2014-04-23 11:04:53 UTC (rev
33127)
@@ -378,7 +378,12 @@
*/
#define GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY 88
+/**
+ * Other peer confirms having received the type map
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP 89
+
/*******************************************************************************
* DATASTORE message types
******************************************************************************/
@@ -636,7 +641,7 @@
#define GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT 162
/**
- * Trail Rejection Message.
+ * Trail Rejection Message.
*/
#define GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_REJECTION 163
/*******************************************************************************
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r33127 - in gnunet/src: core include,
gnunet <=