aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-04-23 11:04:53 +0000
committerChristian Grothoff <christian@grothoff.org>2014-04-23 11:04:53 +0000
commita19683a4b76e10843c4e75db928bac5750c6430a (patch)
tree7aeff0c4d49b5f3750c569216e77912016fd5a81 /src/core
parent21bac846638fbbbe2b03672295d4f14fc3ceb839 (diff)
downloadgnunet-a19683a4b76e10843c4e75db928bac5750c6430a.tar.gz
gnunet-a19683a4b76e10843c4e75db928bac5750c6430a.zip
fix #3348: send typemap confirmation messages, perform faster typemap retransmissions for unconfirmed typemaps, restart retransmissions on reconnect
Diffstat (limited to 'src/core')
-rw-r--r--src/core/gnunet-service-core_kx.c17
-rw-r--r--src/core/gnunet-service-core_sessions.c232
-rw-r--r--src/core/gnunet-service-core_sessions.h28
-rw-r--r--src/core/gnunet-service-core_typemap.c67
-rw-r--r--src/core/gnunet-service-core_typemap.h21
5 files changed, 320 insertions, 45 deletions
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
index 79155a660..8f13dd111 100644
--- a/src/core/gnunet-service-core_kx.c
+++ b/src/core/gnunet-service-core_kx.c
@@ -821,13 +821,15 @@ GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
821 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) && 821 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
822 (end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) ) 822 (end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) )
823 { 823 {
824 GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys ignored"), 824 GNUNET_STATISTICS_update (GSC_stats,
825 gettext_noop ("# old ephemeral keys ignored"),
825 1, GNUNET_NO); 826 1, GNUNET_NO);
826 return; 827 return;
827 } 828 }
828 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time); 829 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
829 830
830 GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# ephemeral keys received"), 831 GNUNET_STATISTICS_update (GSC_stats,
832 gettext_noop ("# ephemeral keys received"),
831 1, GNUNET_NO); 833 1, GNUNET_NO);
832 834
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -884,11 +886,17 @@ GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
884 break; 886 break;
885 case GNUNET_CORE_KX_STATE_KEY_SENT: 887 case GNUNET_CORE_KX_STATE_KEY_SENT:
886 /* fine, need to send our key after updating our status, see below */ 888 /* fine, need to send our key after updating our status, see below */
889 GSC_SESSIONS_reinit (&kx->peer);
887 break; 890 break;
888 case GNUNET_CORE_KX_STATE_KEY_RECEIVED: 891 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
892 /* other peer already got our key, but typemap did go down */
893 GSC_SESSIONS_reinit (&kx->peer);
894 break;
889 case GNUNET_CORE_KX_STATE_UP: 895 case GNUNET_CORE_KX_STATE_UP:
896 /* other peer already got our key, typemap NOT down */
897 break;
890 case GNUNET_CORE_KX_STATE_REKEY_SENT: 898 case GNUNET_CORE_KX_STATE_REKEY_SENT:
891 /* other peer already got our key */ 899 /* other peer already got our key, typemap NOT down */
892 break; 900 break;
893 default: 901 default:
894 GNUNET_break (0); 902 GNUNET_break (0);
@@ -1509,6 +1517,9 @@ deliver_message (void *cls,
1509 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP: 1517 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
1510 GSC_SESSIONS_set_typemap (dmc->peer, m); 1518 GSC_SESSIONS_set_typemap (dmc->peer, m);
1511 return GNUNET_OK; 1519 return GNUNET_OK;
1520 case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
1521 GSC_SESSIONS_confirm_typemap (dmc->peer, m);
1522 return GNUNET_OK;
1512 default: 1523 default:
1513 GSC_CLIENTS_deliver_message (dmc->peer, m, 1524 GSC_CLIENTS_deliver_message (dmc->peer, m,
1514 ntohs (m->size), 1525 ntohs (m->size),
diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c
index eb0013790..09bb3d6c4 100644
--- a/src/core/gnunet-service-core_sessions.c
+++ b/src/core/gnunet-service-core_sessions.c
@@ -137,6 +137,12 @@ struct Session
137 GNUNET_SCHEDULER_TaskIdentifier typemap_task; 137 GNUNET_SCHEDULER_TaskIdentifier typemap_task;
138 138
139 /** 139 /**
140 * Retransmission delay we currently use for the typemap
141 * transmissions (if not confirmed).
142 */
143 struct GNUNET_TIME_Relative typemap_delay;
144
145 /**
140 * Is the neighbour queue empty and thus ready for us 146 * Is the neighbour queue empty and thus ready for us
141 * to transmit an encrypted message? 147 * to transmit an encrypted message?
142 */ 148 */
@@ -151,6 +157,34 @@ struct Session
151}; 157};
152 158
153 159
160GNUNET_NETWORK_STRUCT_BEGIN
161
162/**
163 * Message sent to confirm that a typemap was received.
164 */
165struct TypeMapConfirmationMessage
166{
167
168 /**
169 * Header with type #GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP.
170 */
171 struct GNUNET_MessageHeader header;
172
173 /**
174 * Reserved, always zero.
175 */
176 uint32_t reserved GNUNET_PACKED;
177
178 /**
179 * Hash of the (decompressed) type map that was received.
180 */
181 struct GNUNET_HashCode tm_hash;
182
183};
184
185GNUNET_NETWORK_STRUCT_END
186
187
154/** 188/**
155 * Map of peer identities to `struct Session`. 189 * Map of peer identities to `struct Session`.
156 */ 190 */
@@ -203,10 +237,16 @@ GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
203 } 237 }
204 while (NULL != (sme = session->sme_head)) 238 while (NULL != (sme = session->sme_head))
205 { 239 {
206 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme); 240 GNUNET_CONTAINER_DLL_remove (session->sme_head,
241 session->sme_tail,
242 sme);
207 GNUNET_free (sme); 243 GNUNET_free (sme);
208 } 244 }
209 GNUNET_SCHEDULER_cancel (session->typemap_task); 245 if (GNUNET_SCHEDULER_NO_TASK != session->typemap_task)
246 {
247 GNUNET_SCHEDULER_cancel (session->typemap_task);
248 session->typemap_task = GNUNET_SCHEDULER_NO_TASK;
249 }
210 GSC_CLIENTS_notify_clients_about_neighbour (&session->peer, 250 GSC_CLIENTS_notify_clients_about_neighbour (&session->peer,
211 session->tmap, NULL); 251 session->tmap, NULL);
212 GNUNET_assert (GNUNET_YES == 252 GNUNET_assert (GNUNET_YES ==
@@ -224,7 +264,7 @@ GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
224 264
225/** 265/**
226 * Transmit our current typemap message to the other peer. 266 * Transmit our current typemap message to the other peer.
227 * (Done periodically in case an update got lost). 267 * (Done periodically until the typemap is confirmed).
228 * 268 *
229 * @param cls the `struct Session *` 269 * @param cls the `struct Session *`
230 * @param tc unused 270 * @param tc unused
@@ -237,20 +277,14 @@ transmit_typemap_task (void *cls,
237 struct GNUNET_MessageHeader *hdr; 277 struct GNUNET_MessageHeader *hdr;
238 struct GNUNET_TIME_Relative delay; 278 struct GNUNET_TIME_Relative delay;
239 279
240 if (0 == session->first_typemap) 280 session->typemap_delay = GNUNET_TIME_STD_BACKOFF (session->typemap_delay);
241 { 281 delay = session->typemap_delay;
242 delay = TYPEMAP_FREQUENCY_FIRST;
243 session->first_typemap = 1;
244 }
245 else
246 {
247 delay = TYPEMAP_FREQUENCY;
248 }
249 /* randomize a bit to avoid spont. sync */ 282 /* randomize a bit to avoid spont. sync */
250 delay.rel_value_us += 283 delay.rel_value_us +=
251 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000 * 1000); 284 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000 * 1000);
252 session->typemap_task = 285 session->typemap_task =
253 GNUNET_SCHEDULER_add_delayed (delay, &transmit_typemap_task, session); 286 GNUNET_SCHEDULER_add_delayed (delay,
287 &transmit_typemap_task, session);
254 GNUNET_STATISTICS_update (GSC_stats, 288 GNUNET_STATISTICS_update (GSC_stats,
255 gettext_noop ("# type map refreshes sent"), 1, 289 gettext_noop ("# type map refreshes sent"), 1,
256 GNUNET_NO); 290 GNUNET_NO);
@@ -261,6 +295,24 @@ transmit_typemap_task (void *cls,
261 295
262 296
263/** 297/**
298 * Restart the typemap task for the given session.
299 *
300 * @param session session to restart typemap transmission for
301 */
302static void
303start_typemap_task (struct Session *session)
304{
305 if (GNUNET_SCHEDULER_NO_TASK != session->typemap_task)
306 GNUNET_SCHEDULER_cancel (session->typemap_task);
307 session->typemap_delay = GNUNET_TIME_UNIT_SECONDS;
308 session->typemap_task =
309 GNUNET_SCHEDULER_add_delayed (session->typemap_delay,
310 &transmit_typemap_task,
311 session);
312}
313
314
315/**
264 * Create a session, a key exchange was just completed. 316 * Create a session, a key exchange was just completed.
265 * 317 *
266 * @param peer peer that is now connected 318 * @param peer peer that is now connected
@@ -279,10 +331,9 @@ GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
279 session->tmap = GSC_TYPEMAP_create (); 331 session->tmap = GSC_TYPEMAP_create ();
280 session->peer = *peer; 332 session->peer = *peer;
281 session->kxinfo = kx; 333 session->kxinfo = kx;
282 session->typemap_task =
283 GNUNET_SCHEDULER_add_now (&transmit_typemap_task, session);
284 GNUNET_assert (GNUNET_OK == 334 GNUNET_assert (GNUNET_OK ==
285 GNUNET_CONTAINER_multipeermap_put (sessions, peer, 335 GNUNET_CONTAINER_multipeermap_put (sessions,
336 &session->peer,
286 session, 337 session,
287 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 338 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
288 GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"), 339 GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"),
@@ -290,6 +341,79 @@ GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
290 GNUNET_NO); 341 GNUNET_NO);
291 GSC_CLIENTS_notify_clients_about_neighbour (peer, 342 GSC_CLIENTS_notify_clients_about_neighbour (peer,
292 NULL, session->tmap); 343 NULL, session->tmap);
344 start_typemap_task (session);
345}
346
347
348/**
349 * The other peer has indicated that he 'lost' the session
350 * (KX down), reinitialize the session on our end, in particular
351 * this means to restart the typemap transmission.
352 *
353 * @param peer peer that is now connected
354 */
355void
356GSC_SESSIONS_reinit (const struct GNUNET_PeerIdentity *peer)
357{
358 struct Session *session;
359
360 session = find_session (peer);
361 if (NULL == session)
362 {
363 /* KX/session is new for both sides; thus no need to restart what
364 has not yet begun */
365 return;
366 }
367 start_typemap_task (session);
368}
369
370
371/**
372 * The other peer has confirmed receiving our type map,
373 * check if it is current and if so, stop retransmitting it.
374 *
375 * @param peer peer that confirmed the type map
376 * @param msg confirmation message we received
377 */
378void
379GSC_SESSIONS_confirm_typemap (const struct GNUNET_PeerIdentity *peer,
380 const struct GNUNET_MessageHeader *msg)
381{
382 const struct TypeMapConfirmationMessage *cmsg;
383 struct Session *session;
384
385 session = find_session (peer);
386 if (NULL == session)
387 {
388 GNUNET_break (0);
389 return;
390 }
391 if (ntohs (msg->size) != sizeof (struct TypeMapConfirmationMessage))
392 {
393 GNUNET_break_op (0);
394 return;
395 }
396 cmsg = (const struct TypeMapConfirmationMessage *) msg;
397 if (GNUNET_YES !=
398 GSC_TYPEMAP_check_hash (&cmsg->tm_hash))
399 {
400 /* our typemap has changed in the meantime, do not
401 accept confirmation */
402 GNUNET_STATISTICS_update (GSC_stats,
403 gettext_noop
404 ("# outdated typemap confirmations received"),
405 1, GNUNET_NO);
406 return;
407 }
408 if (GNUNET_SCHEDULER_NO_TASK != session->typemap_task)
409 {
410 GNUNET_SCHEDULER_cancel (session->typemap_task);
411 session->typemap_task = GNUNET_SCHEDULER_NO_TASK;
412 }
413 GNUNET_STATISTICS_update (GSC_stats,
414 gettext_noop
415 ("# valid typemap confirmations received"),
416 1, GNUNET_NO);
293} 417}
294 418
295 419
@@ -325,7 +449,8 @@ void
325GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client) 449GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client)
326{ 450{
327 /* notify new client about existing sessions */ 451 /* notify new client about existing sessions */
328 GNUNET_CONTAINER_multipeermap_iterate (sessions, &notify_client_about_session, 452 GNUNET_CONTAINER_multipeermap_iterate (sessions,
453 &notify_client_about_session,
329 client); 454 client);
330} 455}
331 456
@@ -592,11 +717,14 @@ try_transmission (struct Session *session)
592 size_t used; 717 size_t used;
593 718
594 used = 0; 719 used = 0;
595 while ((NULL != (pos = session->sme_head)) && (used + pos->size <= msize)) 720 while ( (NULL != (pos = session->sme_head)) &&
721 (used + pos->size <= msize) )
596 { 722 {
597 memcpy (&pbuf[used], &pos[1], pos->size); 723 memcpy (&pbuf[used], &pos[1], pos->size);
598 used += pos->size; 724 used += pos->size;
599 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, pos); 725 GNUNET_CONTAINER_DLL_remove (session->sme_head,
726 session->sme_tail,
727 pos);
600 GNUNET_free (pos); 728 GNUNET_free (pos);
601 } 729 }
602 /* compute average payload size */ 730 /* compute average payload size */
@@ -619,7 +747,8 @@ try_transmission (struct Session *session)
619 747
620 748
621/** 749/**
622 * Send a message to the neighbour now. 750 * Send an updated typemap message to the neighbour now,
751 * and restart typemap transmissions.
623 * 752 *
624 * @param cls the message 753 * @param cls the message
625 * @param key neighbour's identity 754 * @param key neighbour's identity
@@ -627,38 +756,42 @@ try_transmission (struct Session *session)
627 * @return always #GNUNET_OK 756 * @return always #GNUNET_OK
628 */ 757 */
629static int 758static int
630do_send_message (void *cls, 759do_restart_typemap_message (void *cls,
631 const struct GNUNET_PeerIdentity *key, 760 const struct GNUNET_PeerIdentity *key,
632 void *value) 761 void *value)
633{ 762{
634 const struct GNUNET_MessageHeader *hdr = cls; 763 const struct GNUNET_MessageHeader *hdr = cls;
635 struct Session *session = value; 764 struct Session *session = value;
636 struct SessionMessageEntry *m; 765 struct SessionMessageEntry *sme;
637 uint16_t size; 766 uint16_t size;
638 767
639 size = ntohs (hdr->size); 768 size = ntohs (hdr->size);
640 m = GNUNET_malloc (sizeof (struct SessionMessageEntry) + size); 769 sme = GNUNET_malloc (sizeof (struct SessionMessageEntry) + size);
641 memcpy (&m[1], hdr, size); 770 memcpy (&sme[1], hdr, size);
642 m->size = size; 771 sme->size = size;
643 m->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL; 772 sme->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
644 GNUNET_CONTAINER_DLL_insert_tail (session->sme_head, session->sme_tail, m); 773 GNUNET_CONTAINER_DLL_insert (session->sme_head,
774 session->sme_tail,
775 sme);
645 try_transmission (session); 776 try_transmission (session);
777 start_typemap_task (session);
646 return GNUNET_OK; 778 return GNUNET_OK;
647} 779}
648 780
649 781
650/** 782/**
651 * Broadcast a message to all neighbours. 783 * Broadcast an updated typemap message to all neighbours.
784 * Restarts the retransmissions until the typemaps are confirmed.
652 * 785 *
653 * @param msg message to transmit 786 * @param msg message to transmit
654 */ 787 */
655void 788void
656GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg) 789GSC_SESSIONS_broadcast_typemap (const struct GNUNET_MessageHeader *msg)
657{ 790{
658 if (NULL == sessions) 791 if (NULL == sessions)
659 return; 792 return;
660 GNUNET_CONTAINER_multipeermap_iterate (sessions, 793 GNUNET_CONTAINER_multipeermap_iterate (sessions,
661 &do_send_message, 794 &do_restart_typemap_message,
662 (void *) msg); 795 (void *) msg);
663} 796}
664 797
@@ -732,7 +865,7 @@ GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
732 865
733 866
734/** 867/**
735 * We've received a typemap message from a peer, update ours. 868 * We have received a typemap message from a peer, update ours.
736 * Notifies clients about the session. 869 * Notifies clients about the session.
737 * 870 *
738 * @param peer peer this is about 871 * @param peer peer this is about
@@ -744,6 +877,8 @@ GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
744{ 877{
745 struct Session *session; 878 struct Session *session;
746 struct GSC_TypeMap *nmap; 879 struct GSC_TypeMap *nmap;
880 struct SessionMessageEntry *sme;
881 struct TypeMapConfirmationMessage *tmc;
747 882
748 nmap = GSC_TYPEMAP_get_from_message (msg); 883 nmap = GSC_TYPEMAP_get_from_message (msg);
749 if (NULL == nmap) 884 if (NULL == nmap)
@@ -754,8 +889,24 @@ GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
754 GNUNET_break (0); 889 GNUNET_break (0);
755 return; 890 return;
756 } 891 }
892 sme = GNUNET_malloc (sizeof (struct SessionMessageEntry) +
893 sizeof (struct TypeMapConfirmationMessage));
894 sme->deadline = GNUNET_TIME_absolute_get ();
895 sme->size = sizeof (struct TypeMapConfirmationMessage);
896 sme->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
897 tmc = (struct TypeMapConfirmationMessage *) &sme[1];
898 tmc->header.size = htons (sizeof (struct TypeMapConfirmationMessage));
899 tmc->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP);
900 tmc->reserved = htonl (0);
901 GSC_TYPEMAP_hash (nmap,
902 &tmc->tm_hash);
903 GNUNET_CONTAINER_DLL_insert (session->sme_head,
904 session->sme_tail,
905 sme);
906 try_transmission (session);
757 GSC_CLIENTS_notify_clients_about_neighbour (peer, 907 GSC_CLIENTS_notify_clients_about_neighbour (peer,
758 session->tmap, nmap); 908 session->tmap,
909 nmap);
759 GSC_TYPEMAP_destroy (session->tmap); 910 GSC_TYPEMAP_destroy (session->tmap);
760 session->tmap = nmap; 911 session->tmap = nmap;
761} 912}
@@ -776,7 +927,9 @@ GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
776 struct Session *session; 927 struct Session *session;
777 struct GSC_TypeMap *nmap; 928 struct GSC_TypeMap *nmap;
778 929
779 if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) 930 if (0 == memcmp (peer,
931 &GSC_my_identity,
932 sizeof (struct GNUNET_PeerIdentity)))
780 return; 933 return;
781 session = find_session (peer); 934 session = find_session (peer);
782 GNUNET_assert (NULL != session); 935 GNUNET_assert (NULL != session);
@@ -796,12 +949,14 @@ GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
796void 949void
797GSC_SESSIONS_init () 950GSC_SESSIONS_init ()
798{ 951{
799 sessions = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); 952 sessions = GNUNET_CONTAINER_multipeermap_create (128,
953 GNUNET_YES);
800} 954}
801 955
802 956
803/** 957/**
804 * Helper function for GSC_SESSIONS_handle_client_iterate_peers. 958 * Helper function for #GSC_SESSIONS_done() to free all
959 * active sessions.
805 * 960 *
806 * @param cls NULL 961 * @param cls NULL
807 * @param key identity of the connected peer 962 * @param key identity of the connected peer
@@ -828,7 +983,8 @@ GSC_SESSIONS_done ()
828{ 983{
829 if (NULL != sessions) 984 if (NULL != sessions)
830 { 985 {
831 GNUNET_CONTAINER_multipeermap_iterate (sessions, &free_session_helper, NULL); 986 GNUNET_CONTAINER_multipeermap_iterate (sessions,
987 &free_session_helper, NULL);
832 GNUNET_CONTAINER_multipeermap_destroy (sessions); 988 GNUNET_CONTAINER_multipeermap_destroy (sessions);
833 sessions = NULL; 989 sessions = NULL;
834 } 990 }
diff --git a/src/core/gnunet-service-core_sessions.h b/src/core/gnunet-service-core_sessions.h
index 81581e84d..793d7af8c 100644
--- a/src/core/gnunet-service-core_sessions.h
+++ b/src/core/gnunet-service-core_sessions.h
@@ -42,6 +42,29 @@ GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
42 42
43 43
44/** 44/**
45 * The other peer has indicated that he 'lost' the session
46 * (KX down), reinitialize the session on our end, in particular
47 * this means to restart the typemap transmission.
48 *
49 * @param peer peer that is now connected
50 */
51void
52GSC_SESSIONS_reinit (const struct GNUNET_PeerIdentity *peer);
53
54
55/**
56 * The other peer has confirmed receiving our type map,
57 * check if it is current and if so, stop retransmitting it.
58 *
59 * @param peer peer that confirmed the type map
60 * @param msg confirmation message we received
61 */
62void
63GSC_SESSIONS_confirm_typemap (const struct GNUNET_PeerIdentity *peer,
64 const struct GNUNET_MessageHeader *msg);
65
66
67/**
45 * End the session with the given peer (we are no longer 68 * End the session with the given peer (we are no longer
46 * connected). 69 * connected).
47 * 70 *
@@ -102,12 +125,13 @@ GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
102 125
103 126
104/** 127/**
105 * Broadcast a message to all neighbours. 128 * Broadcast an updated typemap message to all neighbours.
129 * Restarts the retransmissions until the typemaps are confirmed.
106 * 130 *
107 * @param msg message to transmit 131 * @param msg message to transmit
108 */ 132 */
109void 133void
110GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg); 134GSC_SESSIONS_broadcast_typemap (const struct GNUNET_MessageHeader *msg);
111 135
112 136
113/** 137/**
diff --git a/src/core/gnunet-service-core_typemap.c b/src/core/gnunet-service-core_typemap.c
index 8d9fcbec7..13f5309fb 100644
--- a/src/core/gnunet-service-core_typemap.c
+++ b/src/core/gnunet-service-core_typemap.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors) 3 (C) 2011-2014 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -51,6 +51,63 @@ static struct GSC_TypeMap my_type_map;
51 */ 51 */
52static uint8_t map_counters[UINT16_MAX + 1]; 52static uint8_t map_counters[UINT16_MAX + 1];
53 53
54/**
55 * Current hash of our (uncompressed) type map.
56 * Lazily computed when needed.
57 */
58static struct GNUNET_HashCode my_tm_hash;
59
60/**
61 * Is #my_tm_hash() current with respect to our type map?
62 */
63static int hash_current;
64
65
66/**
67 * Our type map changed, recompute its hash.
68 */
69static void
70rehash_typemap ()
71{
72 hash_current = GNUNET_NO;
73}
74
75
76/**
77 * Hash the contents of a type map.
78 *
79 * @param tm map to hash
80 * @param hc where to store the hash code
81 */
82void
83GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm,
84 struct GNUNET_HashCode *hc)
85{
86 GNUNET_CRYPTO_hash (tm,
87 sizeof (struct GSC_TypeMap),
88 hc);
89}
90
91
92/**
93 * Check if the given hash matches our current type map.
94 *
95 * @param hc hash code to check if it matches our type map
96 * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
97 */
98int
99GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc)
100{
101 if (GNUNET_NO == hash_current)
102 {
103 GSC_TYPEMAP_hash (&my_type_map,
104 &my_tm_hash);
105 hash_current = GNUNET_YES;
106 }
107 return (0 == memcmp (hc, &my_tm_hash, sizeof (struct GNUNET_HashCode)))
108 ? GNUNET_YES : GNUNET_NO;
109}
110
54 111
55/** 112/**
56 * Compute a type map message for this peer. 113 * Compute a type map message for this peer.
@@ -152,7 +209,7 @@ broadcast_my_type_map ()
152 GNUNET_STATISTICS_update (GSC_stats, 209 GNUNET_STATISTICS_update (GSC_stats,
153 gettext_noop ("# updates to my type map"), 1, 210 gettext_noop ("# updates to my type map"), 1,
154 GNUNET_NO); 211 GNUNET_NO);
155 GSC_SESSIONS_broadcast (hdr); 212 GSC_SESSIONS_broadcast_typemap (hdr);
156 GNUNET_free (hdr); 213 GNUNET_free (hdr);
157} 214}
158 215
@@ -180,7 +237,10 @@ GSC_TYPEMAP_add (const uint16_t *types,
180 } 237 }
181 } 238 }
182 if (GNUNET_YES == changed) 239 if (GNUNET_YES == changed)
240 {
241 rehash_typemap ();
183 broadcast_my_type_map (); 242 broadcast_my_type_map ();
243 }
184} 244}
185 245
186 246
@@ -207,7 +267,10 @@ GSC_TYPEMAP_remove (const uint16_t *types,
207 } 267 }
208 } 268 }
209 if (GNUNET_YES == changed) 269 if (GNUNET_YES == changed)
270 {
271 rehash_typemap ();
210 broadcast_my_type_map (); 272 broadcast_my_type_map ();
273 }
211} 274}
212 275
213 276
diff --git a/src/core/gnunet-service-core_typemap.h b/src/core/gnunet-service-core_typemap.h
index 7572d39db..1cf6972e9 100644
--- a/src/core/gnunet-service-core_typemap.h
+++ b/src/core/gnunet-service-core_typemap.h
@@ -67,6 +67,27 @@ GSC_TYPEMAP_compute_type_map_message (void);
67 67
68 68
69/** 69/**
70 * Check if the given hash matches our current type map.
71 *
72 * @param hc hash code to check if it matches our type map
73 * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
74 */
75int
76GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc);
77
78
79/**
80 * Hash the contents of a type map.
81 *
82 * @param tm map to hash
83 * @param hc where to store the hash code
84 */
85void
86GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm,
87 struct GNUNET_HashCode *hc);
88
89
90/**
70 * Extract a type map from a 91 * Extract a type map from a
71 * #GNUNET_MESSAGE_TYPE_CORE_COMRESSED_TYPE_MAP or 92 * #GNUNET_MESSAGE_TYPE_CORE_COMRESSED_TYPE_MAP or
72 * #GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP message. 93 * #GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP message.