diff options
Diffstat (limited to 'src')
28 files changed, 2257 insertions, 425 deletions
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore index 44382fde9..b556fa4c8 100644 --- a/src/cadet/.gitignore +++ b/src/cadet/.gitignore | |||
@@ -21,4 +21,6 @@ test_cadet_local | |||
21 | test_cadet_single | 21 | test_cadet_single |
22 | gnunet-service-cadet-new | 22 | gnunet-service-cadet-new |
23 | test_cadet_local_mq | 23 | test_cadet_local_mq |
24 | test_cadet_*_new \ No newline at end of file | 24 | test_cadet_*_newtest_cadet_2_reopen |
25 | test_cadet_5_reopen | ||
26 | test_cadet_2_reopen | ||
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c index 06711dc8b..8ef598132 100644 --- a/src/cadet/gnunet-service-cadet_channel.c +++ b/src/cadet/gnunet-service-cadet_channel.c | |||
@@ -500,6 +500,11 @@ channel_destroy (struct CadetChannel *ch) | |||
500 | GNUNET_free (crm->data_message); | 500 | GNUNET_free (crm->data_message); |
501 | GNUNET_free (crm); | 501 | GNUNET_free (crm); |
502 | } | 502 | } |
503 | if (CADET_CHANNEL_LOOSE == ch->state) | ||
504 | { | ||
505 | GSC_drop_loose_channel (&ch->h_port, | ||
506 | ch); | ||
507 | } | ||
503 | if (NULL != ch->owner) | 508 | if (NULL != ch->owner) |
504 | { | 509 | { |
505 | free_channel_client (ch->owner); | 510 | free_channel_client (ch->owner); |
@@ -1136,8 +1141,6 @@ GCCH_channel_local_destroy (struct CadetChannel *ch, | |||
1136 | target, but that never went anywhere. Nothing to do here. */ | 1141 | target, but that never went anywhere. Nothing to do here. */ |
1137 | break; | 1142 | break; |
1138 | case CADET_CHANNEL_LOOSE: | 1143 | case CADET_CHANNEL_LOOSE: |
1139 | GSC_drop_loose_channel (&ch->h_port, | ||
1140 | ch); | ||
1141 | break; | 1144 | break; |
1142 | default: | 1145 | default: |
1143 | GCT_send_channel_destroy (ch->t, | 1146 | GCT_send_channel_destroy (ch->t, |
diff --git a/src/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c index 593617ff6..40f464e9b 100644 --- a/src/cadet/gnunet-service-cadet_paths.c +++ b/src/cadet/gnunet-service-cadet_paths.c | |||
@@ -477,7 +477,6 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
477 | struct CadetPeer *cpath[get_path_length + put_path_length]; | 477 | struct CadetPeer *cpath[get_path_length + put_path_length]; |
478 | struct CheckMatchContext cm_ctx; | 478 | struct CheckMatchContext cm_ctx; |
479 | struct CadetPeerPath *path; | 479 | struct CadetPeerPath *path; |
480 | int i; | ||
481 | unsigned int skip; | 480 | unsigned int skip; |
482 | unsigned int total_len; | 481 | unsigned int total_len; |
483 | 482 | ||
@@ -527,7 +526,7 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
527 | cm_ctx.cpath_length = total_len; | 526 | cm_ctx.cpath_length = total_len; |
528 | cm_ctx.cpath = cpath; | 527 | cm_ctx.cpath = cpath; |
529 | cm_ctx.match = NULL; | 528 | cm_ctx.match = NULL; |
530 | for (i=total_len-1;i>=0;i--) | 529 | for (int i=total_len-1;i>=0;i--) |
531 | { | 530 | { |
532 | GCP_iterate_paths_at (cpath[i], | 531 | GCP_iterate_paths_at (cpath[i], |
533 | (unsigned int) i, | 532 | (unsigned int) i, |
@@ -562,7 +561,7 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
562 | path->entries_length = total_len; | 561 | path->entries_length = total_len; |
563 | path->entries = GNUNET_new_array (path->entries_length, | 562 | path->entries = GNUNET_new_array (path->entries_length, |
564 | struct CadetPeerPathEntry *); | 563 | struct CadetPeerPathEntry *); |
565 | for (i=path->entries_length-1;i>=0;i--) | 564 | for (int i=path->entries_length-1;i>=0;i--) |
566 | { | 565 | { |
567 | struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry); | 566 | struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry); |
568 | 567 | ||
@@ -570,7 +569,7 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
570 | entry->peer = cpath[i]; | 569 | entry->peer = cpath[i]; |
571 | entry->path = path; | 570 | entry->path = path; |
572 | } | 571 | } |
573 | for (i=path->entries_length-1;i>=0;i--) | 572 | for (int i=path->entries_length-1;i>=0;i--) |
574 | { | 573 | { |
575 | struct CadetPeerPathEntry *entry = path->entries[i]; | 574 | struct CadetPeerPathEntry *entry = path->entries[i]; |
576 | 575 | ||
diff --git a/src/gns/test_gns_cname_lookup.sh b/src/gns/test_gns_cname_lookup.sh index f6b7a842d..de575c561 100755 --- a/src/gns/test_gns_cname_lookup.sh +++ b/src/gns/test_gns_cname_lookup.sh | |||
@@ -54,6 +54,9 @@ gnunet-identity -D $MY_EGO -c test_gns_lookup.conf | |||
54 | gnunet-arm -e -c test_gns_lookup.conf | 54 | gnunet-arm -e -c test_gns_lookup.conf |
55 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` | 55 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` |
56 | 56 | ||
57 | # make cmp case-insensitive by converting to lower case first | ||
58 | RES_CNAME_RAW=`echo $RES_CNAME_RAW | tr [A-Z] [a-z]` | ||
59 | TESTEGOZONE=`echo $TESTEGOZONE | tr [A-Z] [a-z]` | ||
57 | if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ] | 60 | if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ] |
58 | then | 61 | then |
59 | echo "PASS: CNAME resolution from GNS" | 62 | echo "PASS: CNAME resolution from GNS" |
diff --git a/src/gns/test_gns_mx_lookup.sh b/src/gns/test_gns_mx_lookup.sh index 3a360494b..79ac37b0a 100755 --- a/src/gns/test_gns_mx_lookup.sh +++ b/src/gns/test_gns_mx_lookup.sh | |||
@@ -31,6 +31,10 @@ gnunet-identity -D $MY_EGO -c test_gns_lookup.conf | |||
31 | gnunet-arm -e -c test_gns_lookup.conf | 31 | gnunet-arm -e -c test_gns_lookup.conf |
32 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` | 32 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` |
33 | 33 | ||
34 | # make cmp case-insensitive by converting to lower case first | ||
35 | RES_MX=`echo $RES_MX | tr [A-Z] [a-z]` | ||
36 | WANT_MX=`echo $WANT_MX | tr [A-Z] [a-z]` | ||
37 | |||
34 | if [ "$RES_MX" == "$WANT_MX" ] | 38 | if [ "$RES_MX" == "$WANT_MX" ] |
35 | then | 39 | then |
36 | exit 0 | 40 | exit 0 |
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h index 2de65b2f1..bd9ce7bb2 100644 --- a/src/include/gnunet_container_lib.h +++ b/src/include/gnunet_container_lib.h | |||
@@ -928,7 +928,7 @@ GNUNET_CONTAINER_multihashmap_size (const struct GNUNET_CONTAINER_MultiHashMap * | |||
928 | * #GNUNET_SYSERR if it aborted iteration | 928 | * #GNUNET_SYSERR if it aborted iteration |
929 | */ | 929 | */ |
930 | int | 930 | int |
931 | GNUNET_CONTAINER_multihashmap_iterate (const struct GNUNET_CONTAINER_MultiHashMap *map, | 931 | GNUNET_CONTAINER_multihashmap_iterate (struct GNUNET_CONTAINER_MultiHashMap *map, |
932 | GNUNET_CONTAINER_HashMapIterator it, | 932 | GNUNET_CONTAINER_HashMapIterator it, |
933 | void *it_cls); | 933 | void *it_cls); |
934 | 934 | ||
@@ -993,7 +993,7 @@ GNUNET_CONTAINER_multihashmap_iterator_destroy (struct GNUNET_CONTAINER_MultiHas | |||
993 | * #GNUNET_SYSERR if it aborted iteration | 993 | * #GNUNET_SYSERR if it aborted iteration |
994 | */ | 994 | */ |
995 | int | 995 | int |
996 | GNUNET_CONTAINER_multihashmap_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap *map, | 996 | GNUNET_CONTAINER_multihashmap_get_multiple (struct GNUNET_CONTAINER_MultiHashMap *map, |
997 | const struct GNUNET_HashCode *key, | 997 | const struct GNUNET_HashCode *key, |
998 | GNUNET_CONTAINER_HashMapIterator it, | 998 | GNUNET_CONTAINER_HashMapIterator it, |
999 | void *it_cls); | 999 | void *it_cls); |
@@ -1194,7 +1194,7 @@ GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap * | |||
1194 | * #GNUNET_SYSERR if it aborted iteration | 1194 | * #GNUNET_SYSERR if it aborted iteration |
1195 | */ | 1195 | */ |
1196 | int | 1196 | int |
1197 | GNUNET_CONTAINER_multipeermap_iterate (const struct GNUNET_CONTAINER_MultiPeerMap *map, | 1197 | GNUNET_CONTAINER_multipeermap_iterate (struct GNUNET_CONTAINER_MultiPeerMap *map, |
1198 | GNUNET_CONTAINER_PeerMapIterator it, | 1198 | GNUNET_CONTAINER_PeerMapIterator it, |
1199 | void *it_cls); | 1199 | void *it_cls); |
1200 | 1200 | ||
@@ -1260,7 +1260,7 @@ GNUNET_CONTAINER_multipeermap_iterator_destroy (struct GNUNET_CONTAINER_MultiPee | |||
1260 | * #GNUNET_SYSERR if it aborted iteration | 1260 | * #GNUNET_SYSERR if it aborted iteration |
1261 | */ | 1261 | */ |
1262 | int | 1262 | int |
1263 | GNUNET_CONTAINER_multipeermap_get_multiple (const struct GNUNET_CONTAINER_MultiPeerMap *map, | 1263 | GNUNET_CONTAINER_multipeermap_get_multiple (struct GNUNET_CONTAINER_MultiPeerMap *map, |
1264 | const struct GNUNET_PeerIdentity *key, | 1264 | const struct GNUNET_PeerIdentity *key, |
1265 | GNUNET_CONTAINER_PeerMapIterator it, | 1265 | GNUNET_CONTAINER_PeerMapIterator it, |
1266 | void *it_cls); | 1266 | void *it_cls); |
@@ -1461,7 +1461,7 @@ GNUNET_CONTAINER_multishortmap_size (const struct GNUNET_CONTAINER_MultiShortmap | |||
1461 | * #GNUNET_SYSERR if it aborted iteration | 1461 | * #GNUNET_SYSERR if it aborted iteration |
1462 | */ | 1462 | */ |
1463 | int | 1463 | int |
1464 | GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map, | 1464 | GNUNET_CONTAINER_multishortmap_iterate (struct GNUNET_CONTAINER_MultiShortmap *map, |
1465 | GNUNET_CONTAINER_ShortmapIterator it, | 1465 | GNUNET_CONTAINER_ShortmapIterator it, |
1466 | void *it_cls); | 1466 | void *it_cls); |
1467 | 1467 | ||
@@ -1529,7 +1529,7 @@ GNUNET_CONTAINER_multishortmap_iterator_destroy (struct GNUNET_CONTAINER_MultiSh | |||
1529 | * #GNUNET_SYSERR if it aborted iteration | 1529 | * #GNUNET_SYSERR if it aborted iteration |
1530 | */ | 1530 | */ |
1531 | int | 1531 | int |
1532 | GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map, | 1532 | GNUNET_CONTAINER_multishortmap_get_multiple (struct GNUNET_CONTAINER_MultiShortmap *map, |
1533 | const struct GNUNET_ShortHashCode *key, | 1533 | const struct GNUNET_ShortHashCode *key, |
1534 | GNUNET_CONTAINER_ShortmapIterator it, | 1534 | GNUNET_CONTAINER_ShortmapIterator it, |
1535 | void *it_cls); | 1535 | void *it_cls); |
@@ -1648,8 +1648,7 @@ GNUNET_CONTAINER_multihashmap32_get (const struct | |||
1648 | * #GNUNET_SYSERR if it aborted iteration | 1648 | * #GNUNET_SYSERR if it aborted iteration |
1649 | */ | 1649 | */ |
1650 | int | 1650 | int |
1651 | GNUNET_CONTAINER_multihashmap32_iterate (const struct | 1651 | GNUNET_CONTAINER_multihashmap32_iterate (struct GNUNET_CONTAINER_MultiHashMap32 *map, |
1652 | GNUNET_CONTAINER_MultiHashMap32 *map, | ||
1653 | GNUNET_CONTAINER_HashMapIterator32 it, | 1652 | GNUNET_CONTAINER_HashMapIterator32 it, |
1654 | void *it_cls); | 1653 | void *it_cls); |
1655 | 1654 | ||
@@ -1750,7 +1749,7 @@ GNUNET_CONTAINER_multihashmap32_put (struct GNUNET_CONTAINER_MultiHashMap32 *map | |||
1750 | * #GNUNET_SYSERR if it aborted iteration | 1749 | * #GNUNET_SYSERR if it aborted iteration |
1751 | */ | 1750 | */ |
1752 | int | 1751 | int |
1753 | GNUNET_CONTAINER_multihashmap32_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap32 *map, | 1752 | GNUNET_CONTAINER_multihashmap32_get_multiple (struct GNUNET_CONTAINER_MultiHashMap32 *map, |
1754 | uint32_t key, | 1753 | uint32_t key, |
1755 | GNUNET_CONTAINER_HashMapIterator32 it, | 1754 | GNUNET_CONTAINER_HashMapIterator32 it, |
1756 | void *it_cls); | 1755 | void *it_cls); |
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h index b38f38b69..b8172c37d 100644 --- a/src/include/gnunet_core_service.h +++ b/src/include/gnunet_core_service.h | |||
@@ -88,6 +88,8 @@ struct GNUNET_CORE_Handle; | |||
88 | * | 88 | * |
89 | * @param cls closure | 89 | * @param cls closure |
90 | * @param peer peer identity this notification is about | 90 | * @param peer peer identity this notification is about |
91 | * @return closure associated with @a peer. given to mq callbacks and | ||
92 | * #GNUNET_CORE_DisconnectEventHandler | ||
91 | */ | 93 | */ |
92 | typedef void * | 94 | typedef void * |
93 | (*GNUNET_CORE_ConnectEventHandler) (void *cls, | 95 | (*GNUNET_CORE_ConnectEventHandler) (void *cls, |
@@ -100,6 +102,8 @@ typedef void * | |||
100 | * | 102 | * |
101 | * @param cls closure | 103 | * @param cls closure |
102 | * @param peer peer identity this notification is about | 104 | * @param peer peer identity this notification is about |
105 | * @param peer_cls closure associated with peer. given in | ||
106 | * #GNUNET_CORE_ConnectEventHandler | ||
103 | */ | 107 | */ |
104 | typedef void | 108 | typedef void |
105 | (*GNUNET_CORE_DisconnectEventHandler) (void *cls, | 109 | (*GNUNET_CORE_DisconnectEventHandler) (void *cls, |
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 03b13fd48..898ad6258 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -1352,6 +1352,12 @@ extern "C" | |||
1352 | */ | 1352 | */ |
1353 | #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 448 | 1353 | #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 448 |
1354 | 1354 | ||
1355 | /** | ||
1356 | * Service to client: end of list of results | ||
1357 | */ | ||
1358 | #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END 449 | ||
1359 | |||
1360 | |||
1355 | /******************************************************************************* | 1361 | /******************************************************************************* |
1356 | * LOCKMANAGER message types | 1362 | * LOCKMANAGER message types |
1357 | ******************************************************************************/ | 1363 | ******************************************************************************/ |
@@ -3005,9 +3011,58 @@ extern "C" | |||
3005 | #define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_CANCEL 1135 | 3011 | #define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_CANCEL 1135 |
3006 | 3012 | ||
3007 | 3013 | ||
3014 | /******************************************************* | ||
3015 | NEW (TNG) Transport service | ||
3016 | ******************************************************* */ | ||
3017 | |||
3018 | /** | ||
3019 | * @brief inform transport to add an address of this peer | ||
3020 | */ | ||
3021 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS 1200 | ||
3022 | |||
3023 | /** | ||
3024 | * @brief inform transport to delete an address of this peer | ||
3025 | */ | ||
3026 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS 1201 | ||
3027 | |||
3028 | /** | ||
3029 | * @brief inform transport about an incoming message | ||
3030 | */ | ||
3031 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG 1202 | ||
3032 | |||
3033 | /** | ||
3034 | * @brief transport acknowledges processing an incoming message | ||
3035 | */ | ||
3036 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK 1203 | ||
3037 | |||
3038 | /** | ||
3039 | * @brief inform transport that a queue was setup to talk to some peer | ||
3040 | */ | ||
3041 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP 1204 | ||
3042 | |||
3043 | /** | ||
3044 | * @brief inform transport that a queue was torn down | ||
3045 | */ | ||
3046 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN 1205 | ||
3047 | |||
3048 | /** | ||
3049 | * @brief transport tells communicator it wants a queue | ||
3050 | */ | ||
3051 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE 1206 | ||
3052 | |||
3053 | /** | ||
3054 | * @brief transport tells communicator it wants to transmit | ||
3055 | */ | ||
3056 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1207 | ||
3057 | |||
3058 | /** | ||
3059 | * @brief communicator tells transports that message was sent | ||
3060 | */ | ||
3061 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1208 | ||
3062 | |||
3008 | 3063 | ||
3009 | /** | 3064 | /** |
3010 | * Next available: 1200 | 3065 | * Next available: 1300 |
3011 | */ | 3066 | */ |
3012 | 3067 | ||
3013 | 3068 | ||
diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h index 94d15af22..d93d5134e 100644 --- a/src/include/gnunet_transport_communication_service.h +++ b/src/include/gnunet_transport_communication_service.h | |||
@@ -137,8 +137,8 @@ typedef void | |||
137 | * @return #GNUNET_OK if all is well, #GNUNET_NO if the message was | 137 | * @return #GNUNET_OK if all is well, #GNUNET_NO if the message was |
138 | * immediately dropped due to memory limitations (communicator | 138 | * immediately dropped due to memory limitations (communicator |
139 | * should try to apply back pressure), | 139 | * should try to apply back pressure), |
140 | * #GNUNET_SYSERR if the message is ill formed and communicator | 140 | * #GNUNET_SYSERR if the message could not be delivered because |
141 | * should try to reset stream | 141 | * the tranport service is not yet up |
142 | */ | 142 | */ |
143 | int | 143 | int |
144 | GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, | 144 | GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, |
@@ -162,7 +162,7 @@ struct GNUNET_TRANSPORT_QueueHandle; | |||
162 | * "inbound" connection or because the communicator discovered the | 162 | * "inbound" connection or because the communicator discovered the |
163 | * presence of another peer. | 163 | * presence of another peer. |
164 | * | 164 | * |
165 | * @param handle connection to transport service | 165 | * @param ch connection to transport service |
166 | * @param peer peer with which we can now communicate | 166 | * @param peer peer with which we can now communicate |
167 | * @param address address in human-readable format, 0-terminated, UTF-8 | 167 | * @param address address in human-readable format, 0-terminated, UTF-8 |
168 | * @param nt which network type does the @a address belong to? | 168 | * @param nt which network type does the @a address belong to? |
@@ -170,7 +170,7 @@ struct GNUNET_TRANSPORT_QueueHandle; | |||
170 | * @return API handle identifying the new MQ | 170 | * @return API handle identifying the new MQ |
171 | */ | 171 | */ |
172 | struct GNUNET_TRANSPORT_QueueHandle * | 172 | struct GNUNET_TRANSPORT_QueueHandle * |
173 | GNUNET_TRANSPORT_communicator_mq_add (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, | 173 | GNUNET_TRANSPORT_communicator_mq_add (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, |
174 | const struct GNUNET_PeerIdentity *peer, | 174 | const struct GNUNET_PeerIdentity *peer, |
175 | const char *address, | 175 | const char *address, |
176 | enum GNUNET_ATS_Network_Type nt, | 176 | enum GNUNET_ATS_Network_Type nt, |
@@ -198,16 +198,16 @@ struct GNUNET_TRANSPORT_AddressIdentifier; | |||
198 | * Notify transport service about an address that this communicator | 198 | * Notify transport service about an address that this communicator |
199 | * provides for this peer. | 199 | * provides for this peer. |
200 | * | 200 | * |
201 | * @param handle connection to transport service | 201 | * @param ch connection to transport service |
202 | * @param address our address in human-readable format, 0-terminated, UTF-8 | 202 | * @param address our address in human-readable format, 0-terminated, UTF-8 |
203 | * @param nt which network type does the address belong to? | 203 | * @param nt which network type does the address belong to? |
204 | * @param expiration when does the communicator forsee this address expiring? | 204 | * @param expiration when does the communicator forsee this address expiring? |
205 | */ | 205 | */ |
206 | struct GNUNET_TRANSPORT_AddressIdentifier * | 206 | struct GNUNET_TRANSPORT_AddressIdentifier * |
207 | GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, | 207 | GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, |
208 | const char *address, | 208 | const char *address, |
209 | enum GNUNET_ATS_Network_Type nt, | 209 | enum GNUNET_ATS_Network_Type nt, |
210 | struct GNUNET_TIME_Absolute expiration); | 210 | struct GNUNET_TIME_Relative expiration); |
211 | 211 | ||
212 | 212 | ||
213 | /** | 213 | /** |
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 6ad7354ad..cdd52cc42 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -11,7 +11,7 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
@@ -624,7 +624,6 @@ send_lookup_response (struct NamestoreClient *nc, | |||
624 | char *rd_ser; | 624 | char *rd_ser; |
625 | 625 | ||
626 | nick = get_nick_record (zone_key); | 626 | nick = get_nick_record (zone_key); |
627 | |||
628 | GNUNET_assert (-1 != | 627 | GNUNET_assert (-1 != |
629 | GNUNET_GNSRECORD_records_get_size (rd_count, | 628 | GNUNET_GNSRECORD_records_get_size (rd_count, |
630 | rd)); | 629 | rd)); |
@@ -925,7 +924,7 @@ continue_store_activity (struct StoreActivity *sa) | |||
925 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) ) | 924 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) ) |
926 | { | 925 | { |
927 | sa->zm_pos = zm->next; /* not interesting to this monitor */ | 926 | sa->zm_pos = zm->next; /* not interesting to this monitor */ |
928 | continue; // -- fails tests, but why not here? | 927 | continue; |
929 | } | 928 | } |
930 | if (zm->limit == zm->iteration_cnt) | 929 | if (zm->limit == zm->iteration_cnt) |
931 | { | 930 | { |
@@ -1733,7 +1732,7 @@ run_zone_iteration_round (struct ZoneIteration *zi, | |||
1733 | { | 1732 | { |
1734 | struct ZoneIterationProcResult proc; | 1733 | struct ZoneIterationProcResult proc; |
1735 | struct GNUNET_MQ_Envelope *env; | 1734 | struct GNUNET_MQ_Envelope *env; |
1736 | struct RecordResultMessage *rrm; | 1735 | struct GNUNET_NAMESTORE_Header *em; |
1737 | struct GNUNET_TIME_Absolute start; | 1736 | struct GNUNET_TIME_Absolute start; |
1738 | struct GNUNET_TIME_Relative duration; | 1737 | struct GNUNET_TIME_Relative duration; |
1739 | 1738 | ||
@@ -1771,16 +1770,16 @@ run_zone_iteration_round (struct ZoneIteration *zi, | |||
1771 | "Returned %llu results, more results available\n", | 1770 | "Returned %llu results, more results available\n", |
1772 | (unsigned long long) limit); | 1771 | (unsigned long long) limit); |
1773 | return; /* more results later after we get the | 1772 | return; /* more results later after we get the |
1774 | #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message */ | 1773 | #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message */ |
1775 | } | 1774 | } |
1776 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1775 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1777 | "Completed iteration after %llu/%llu results\n", | 1776 | "Completed iteration after %llu/%llu results\n", |
1778 | (unsigned long long) (limit - proc.limit), | 1777 | (unsigned long long) (limit - proc.limit), |
1779 | (unsigned long long) limit); | 1778 | (unsigned long long) limit); |
1780 | /* send empty response to indicate end of list */ | 1779 | /* send empty response to indicate end of list */ |
1781 | env = GNUNET_MQ_msg (rrm, | 1780 | env = GNUNET_MQ_msg (em, |
1782 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT); | 1781 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END); |
1783 | rrm->gns_header.r_id = htonl (zi->request_id); | 1782 | em->r_id = htonl (zi->request_id); |
1784 | GNUNET_MQ_send (zi->nc->mq, | 1783 | GNUNET_MQ_send (zi->nc->mq, |
1785 | env); | 1784 | env); |
1786 | GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, | 1785 | GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, |
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 55745d83d..527576718 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c | |||
@@ -11,7 +11,7 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
@@ -523,6 +523,7 @@ static int | |||
523 | check_record_result (void *cls, | 523 | check_record_result (void *cls, |
524 | const struct RecordResultMessage *msg) | 524 | const struct RecordResultMessage *msg) |
525 | { | 525 | { |
526 | static struct GNUNET_CRYPTO_EcdsaPrivateKey priv_dummy; | ||
526 | const char *name; | 527 | const char *name; |
527 | size_t msg_len; | 528 | size_t msg_len; |
528 | size_t name_len; | 529 | size_t name_len; |
@@ -543,12 +544,19 @@ check_record_result (void *cls, | |||
543 | return GNUNET_SYSERR; | 544 | return GNUNET_SYSERR; |
544 | } | 545 | } |
545 | name = (const char *) &msg[1]; | 546 | name = (const char *) &msg[1]; |
546 | if ( (name_len > 0) && | 547 | if ( (0 == name_len) || |
547 | ('\0' != name[name_len -1]) ) | 548 | ('\0' != name[name_len -1]) ) |
548 | { | 549 | { |
549 | GNUNET_break (0); | 550 | GNUNET_break (0); |
550 | return GNUNET_SYSERR; | 551 | return GNUNET_SYSERR; |
551 | } | 552 | } |
553 | if (0 == memcmp (&msg->private_key, | ||
554 | &priv_dummy, | ||
555 | sizeof (priv_dummy)) ) | ||
556 | { | ||
557 | GNUNET_break (0); | ||
558 | return GNUNET_SYSERR; | ||
559 | } | ||
552 | return check_rd (rd_len, | 560 | return check_rd (rd_len, |
553 | &name[name_len], | 561 | &name[name_len], |
554 | ntohs (msg->rd_count)); | 562 | ntohs (msg->rd_count)); |
@@ -566,7 +574,6 @@ static void | |||
566 | handle_record_result (void *cls, | 574 | handle_record_result (void *cls, |
567 | const struct RecordResultMessage *msg) | 575 | const struct RecordResultMessage *msg) |
568 | { | 576 | { |
569 | static struct GNUNET_CRYPTO_EcdsaPrivateKey priv_dummy; | ||
570 | struct GNUNET_NAMESTORE_Handle *h = cls; | 577 | struct GNUNET_NAMESTORE_Handle *h = cls; |
571 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 578 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
572 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | 579 | struct GNUNET_NAMESTORE_ZoneIterator *ze; |
@@ -595,25 +602,6 @@ handle_record_result (void *cls, | |||
595 | force_reconnect (h); | 602 | force_reconnect (h); |
596 | return; | 603 | return; |
597 | } | 604 | } |
598 | if ( (0 == name_len) && | ||
599 | (0 == (memcmp (&msg->private_key, | ||
600 | &priv_dummy, | ||
601 | sizeof (priv_dummy)))) ) | ||
602 | { | ||
603 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
604 | "Zone iteration completed!\n"); | ||
605 | if (NULL == ze) | ||
606 | { | ||
607 | GNUNET_break (0); | ||
608 | force_reconnect (h); | ||
609 | return; | ||
610 | } | ||
611 | if (NULL != ze->finish_cb) | ||
612 | ze->finish_cb (ze->finish_cb_cls); | ||
613 | free_ze (ze); | ||
614 | return; | ||
615 | } | ||
616 | |||
617 | name = (const char *) &msg[1]; | 605 | name = (const char *) &msg[1]; |
618 | rd_tmp = &name[name_len]; | 606 | rd_tmp = &name[name_len]; |
619 | { | 607 | { |
@@ -654,6 +642,51 @@ handle_record_result (void *cls, | |||
654 | 642 | ||
655 | /** | 643 | /** |
656 | * Handle an incoming message of type | 644 | * Handle an incoming message of type |
645 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END | ||
646 | * | ||
647 | * @param cls | ||
648 | * @param msg the message we received | ||
649 | */ | ||
650 | static void | ||
651 | handle_record_result_end (void *cls, | ||
652 | const struct GNUNET_NAMESTORE_Header *msg) | ||
653 | { | ||
654 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
655 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
656 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
657 | |||
658 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
659 | "Received RECORD_RESULT_END\n"); | ||
660 | ze = find_zi (h, | ||
661 | ntohl (msg->r_id)); | ||
662 | qe = find_qe (h, | ||
663 | ntohl (msg->r_id)); | ||
664 | if ( (NULL == ze) && | ||
665 | (NULL == qe) ) | ||
666 | return; /* rid not found */ | ||
667 | if ( (NULL != ze) && | ||
668 | (NULL != qe) ) | ||
669 | { | ||
670 | GNUNET_break (0); /* rid ambigous */ | ||
671 | force_reconnect (h); | ||
672 | return; | ||
673 | } | ||
674 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
675 | "Zone iteration completed!\n"); | ||
676 | if (NULL == ze) | ||
677 | { | ||
678 | GNUNET_break (0); | ||
679 | force_reconnect (h); | ||
680 | return; | ||
681 | } | ||
682 | if (NULL != ze->finish_cb) | ||
683 | ze->finish_cb (ze->finish_cb_cls); | ||
684 | free_ze (ze); | ||
685 | } | ||
686 | |||
687 | |||
688 | /** | ||
689 | * Handle an incoming message of type | ||
657 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. | 690 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. |
658 | * | 691 | * |
659 | * @param qe the respective entry in the message queue | 692 | * @param qe the respective entry in the message queue |
@@ -810,6 +843,10 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h) | |||
810 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, | 843 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, |
811 | struct RecordResultMessage, | 844 | struct RecordResultMessage, |
812 | h), | 845 | h), |
846 | GNUNET_MQ_hd_fixed_size (record_result_end, | ||
847 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END, | ||
848 | struct GNUNET_NAMESTORE_Header, | ||
849 | h), | ||
813 | GNUNET_MQ_hd_var_size (lookup_result, | 850 | GNUNET_MQ_hd_var_size (lookup_result, |
814 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, | 851 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, |
815 | struct LabelLookupResponseMessage, | 852 | struct LabelLookupResponseMessage, |
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c index 457da0b90..b26389718 100644 --- a/src/namestore/namestore_api_monitor.c +++ b/src/namestore/namestore_api_monitor.c | |||
@@ -11,7 +11,7 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
@@ -296,7 +296,6 @@ reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | |||
296 | } | 296 | } |
297 | 297 | ||
298 | 298 | ||
299 | |||
300 | /** | 299 | /** |
301 | * Begin monitoring a zone for changes. If @a iterate_first is set, | 300 | * Begin monitoring a zone for changes. If @a iterate_first is set, |
302 | * we Will first call the @a monitor function on all existing records | 301 | * we Will first call the @a monitor function on all existing records |
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c index d9bc5b212..23af3960d 100644 --- a/src/namestore/plugin_namestore_sqlite.c +++ b/src/namestore/plugin_namestore_sqlite.c | |||
@@ -162,7 +162,7 @@ database_setup (struct Plugin *plugin) | |||
162 | " ORDER BY uid ASC" | 162 | " ORDER BY uid ASC" |
163 | " LIMIT ?", | 163 | " LIMIT ?", |
164 | &plugin->iterate_all_zones), | 164 | &plugin->iterate_all_zones), |
165 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,zone_private_key" | 165 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" |
166 | " FROM ns098records" | 166 | " FROM ns098records" |
167 | " WHERE zone_private_key=? AND label=?", | 167 | " WHERE zone_private_key=? AND label=?", |
168 | &plugin->lookup_label), | 168 | &plugin->lookup_label), |
@@ -501,16 +501,10 @@ get_records_and_call_iterator (struct Plugin *plugin, | |||
501 | GNUNET_SQ_result_spec_end | 501 | GNUNET_SQ_result_spec_end |
502 | }; | 502 | }; |
503 | 503 | ||
504 | if (NULL == zone_key) | 504 | ret = GNUNET_SQ_extract_result (stmt, |
505 | { | 505 | (NULL == zone_key) |
506 | ret = GNUNET_SQ_extract_result (stmt, | 506 | ? rsx |
507 | rsx); | 507 | : rs); |
508 | } | ||
509 | else | ||
510 | { | ||
511 | ret = GNUNET_SQ_extract_result (stmt, | ||
512 | rs); | ||
513 | } | ||
514 | if ( (GNUNET_OK != ret) || | 508 | if ( (GNUNET_OK != ret) || |
515 | (record_count > 64 * 1024) ) | 509 | (record_count > 64 * 1024) ) |
516 | { | 510 | { |
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am index 3b5b1ef3e..a356d3dbc 100644 --- a/src/rps/Makefile.am +++ b/src/rps/Makefile.am | |||
@@ -72,6 +72,7 @@ gnunet_service_rps_LDADD = \ | |||
72 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | 72 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ |
73 | $(top_builddir)/src/nse/libgnunetnse.la \ | 73 | $(top_builddir)/src/nse/libgnunetnse.la \ |
74 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 74 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
75 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
75 | $(LIBGCRYPT_LIBS) \ | 76 | $(LIBGCRYPT_LIBS) \ |
76 | -lm -lgcrypt \ | 77 | -lm -lgcrypt \ |
77 | $(GN_LIBINTL) | 78 | $(GN_LIBINTL) |
diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index f2a8083e7..b17fb6a50 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c | |||
@@ -909,6 +909,7 @@ cancel_request (struct PendingReply *pending_rep) | |||
909 | rps_peer->num_pending_reps--; | 909 | rps_peer->num_pending_reps--; |
910 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 910 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
911 | "Cancelling rps get reply\n"); | 911 | "Cancelling rps get reply\n"); |
912 | GNUNET_assert (NULL != pending_rep->req_handle); | ||
912 | GNUNET_RPS_request_cancel (pending_rep->req_handle); | 913 | GNUNET_RPS_request_cancel (pending_rep->req_handle); |
913 | GNUNET_free (pending_rep); | 914 | GNUNET_free (pending_rep); |
914 | } | 915 | } |
@@ -1288,7 +1289,11 @@ rps_disconnect_adapter (void *cls, | |||
1288 | cancel_request (pending_rep); | 1289 | cancel_request (pending_rep); |
1289 | } | 1290 | } |
1290 | GNUNET_assert (h == peer->rps_handle); | 1291 | GNUNET_assert (h == peer->rps_handle); |
1291 | GNUNET_RPS_disconnect (h); | 1292 | if (NULL != h) |
1293 | { | ||
1294 | GNUNET_RPS_disconnect (h); | ||
1295 | h = NULL; | ||
1296 | } | ||
1292 | peer->rps_handle = NULL; | 1297 | peer->rps_handle = NULL; |
1293 | } | 1298 | } |
1294 | } | 1299 | } |
@@ -1788,6 +1793,7 @@ profiler_reply_handle (void *cls, | |||
1788 | unsigned int i; | 1793 | unsigned int i; |
1789 | struct PendingReply *pending_rep = (struct PendingReply *) cls; | 1794 | struct PendingReply *pending_rep = (struct PendingReply *) cls; |
1790 | 1795 | ||
1796 | pending_rep->req_handle = NULL; | ||
1791 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "profiler_reply_handle()\n"); | 1797 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "profiler_reply_handle()\n"); |
1792 | rps_peer = pending_rep->rps_peer; | 1798 | rps_peer = pending_rep->rps_peer; |
1793 | (void) GNUNET_asprintf (&file_name, | 1799 | (void) GNUNET_asprintf (&file_name, |
@@ -2426,10 +2432,10 @@ post_test_shutdown_ready_cb (void *cls, | |||
2426 | GNUNET_TESTBED_operation_done (rps_peer->stat_op); | 2432 | GNUNET_TESTBED_operation_done (rps_peer->stat_op); |
2427 | } | 2433 | } |
2428 | 2434 | ||
2429 | //write_final_stats (); | 2435 | write_final_stats (); |
2430 | if (GNUNET_YES == check_statistics_collect_completed()) | 2436 | if (GNUNET_YES == check_statistics_collect_completed()) |
2431 | { | 2437 | { |
2432 | write_final_stats (); | 2438 | //write_final_stats (); |
2433 | GNUNET_free (stat_cls); | 2439 | GNUNET_free (stat_cls); |
2434 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2435 | "Shutting down\n"); | 2441 | "Shutting down\n"); |
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 193e44411..20b314db3 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "gnunet_applications.h" | 25 | #include "gnunet_applications.h" |
26 | #include "gnunet_util_lib.h" | 26 | #include "gnunet_util_lib.h" |
27 | #include "gnunet_cadet_service.h" | 27 | #include "gnunet_cadet_service.h" |
28 | #include "gnunet_core_service.h" | ||
28 | #include "gnunet_peerinfo_service.h" | 29 | #include "gnunet_peerinfo_service.h" |
29 | #include "gnunet_nse_service.h" | 30 | #include "gnunet_nse_service.h" |
30 | #include "gnunet_statistics_service.h" | 31 | #include "gnunet_statistics_service.h" |
@@ -447,6 +448,16 @@ struct GNUNET_STATISTICS_Handle *stats; | |||
447 | struct GNUNET_CADET_Handle *cadet_handle; | 448 | struct GNUNET_CADET_Handle *cadet_handle; |
448 | 449 | ||
449 | /** | 450 | /** |
451 | * Handle to CORE | ||
452 | */ | ||
453 | struct GNUNET_CORE_Handle *core_handle; | ||
454 | |||
455 | /** | ||
456 | * @brief PeerMap to keep track of connected peers. | ||
457 | */ | ||
458 | struct GNUNET_CONTAINER_MultiPeerMap *map_single_hop; | ||
459 | |||
460 | /** | ||
450 | * Our own identity. | 461 | * Our own identity. |
451 | */ | 462 | */ |
452 | static struct GNUNET_PeerIdentity own_identity; | 463 | static struct GNUNET_PeerIdentity own_identity; |
@@ -768,8 +779,7 @@ get_rand_peer_iterator (void *cls, | |||
768 | * @return a random peer | 779 | * @return a random peer |
769 | */ | 780 | */ |
770 | static const struct GNUNET_PeerIdentity * | 781 | static const struct GNUNET_PeerIdentity * |
771 | get_random_peer_from_peermap (const struct | 782 | get_random_peer_from_peermap (struct GNUNET_CONTAINER_MultiPeerMap *valid_peers) |
772 | GNUNET_CONTAINER_MultiPeerMap *valid_peers) | ||
773 | { | 783 | { |
774 | struct GetRandPeerIteratorCls *iterator_cls; | 784 | struct GetRandPeerIteratorCls *iterator_cls; |
775 | const struct GNUNET_PeerIdentity *ret; | 785 | const struct GNUNET_PeerIdentity *ret; |
@@ -1366,6 +1376,13 @@ mq_notify_sent_cb (void *cls) | |||
1366 | GNUNET_STATISTICS_update(stats, "# pull requests sent", 1, GNUNET_NO); | 1376 | GNUNET_STATISTICS_update(stats, "# pull requests sent", 1, GNUNET_NO); |
1367 | if (0 == strncmp ("PUSH", pending_msg->type, 4)) | 1377 | if (0 == strncmp ("PUSH", pending_msg->type, 4)) |
1368 | GNUNET_STATISTICS_update(stats, "# pushes sent", 1, GNUNET_NO); | 1378 | GNUNET_STATISTICS_update(stats, "# pushes sent", 1, GNUNET_NO); |
1379 | if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12) && | ||
1380 | GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop, | ||
1381 | &pending_msg->peer_ctx->peer_id)) | ||
1382 | GNUNET_STATISTICS_update(stats, | ||
1383 | "# pull requests sent (multi-hop peer)", | ||
1384 | 1, | ||
1385 | GNUNET_NO); | ||
1369 | } | 1386 | } |
1370 | /* Do not cancle message */ | 1387 | /* Do not cancle message */ |
1371 | remove_pending_message (pending_msg, GNUNET_NO); | 1388 | remove_pending_message (pending_msg, GNUNET_NO); |
@@ -1642,7 +1659,7 @@ valid_peer_iterator (void *cls, | |||
1642 | * #GNUNET_SYSERR if it aborted iteration | 1659 | * #GNUNET_SYSERR if it aborted iteration |
1643 | */ | 1660 | */ |
1644 | static int | 1661 | static int |
1645 | get_valid_peers (const struct GNUNET_CONTAINER_MultiPeerMap *valid_peers, | 1662 | get_valid_peers (struct GNUNET_CONTAINER_MultiPeerMap *valid_peers, |
1646 | PeersIterator iterator, | 1663 | PeersIterator iterator, |
1647 | void *it_cls) | 1664 | void *it_cls) |
1648 | { | 1665 | { |
@@ -2150,7 +2167,7 @@ rem_from_list (struct GNUNET_PeerIdentity **peer_list, | |||
2150 | */ | 2167 | */ |
2151 | static void | 2168 | static void |
2152 | insert_in_view_op (void *cls, | 2169 | insert_in_view_op (void *cls, |
2153 | const struct GNUNET_PeerIdentity *peer); | 2170 | const struct GNUNET_PeerIdentity *peer); |
2154 | 2171 | ||
2155 | /** | 2172 | /** |
2156 | * Insert PeerID in #view | 2173 | * Insert PeerID in #view |
@@ -2177,7 +2194,7 @@ insert_in_view (struct Sub *sub, | |||
2177 | (GNUNET_SYSERR == online) ) /* peer is not even known */ | 2194 | (GNUNET_SYSERR == online) ) /* peer is not even known */ |
2178 | { | 2195 | { |
2179 | (void) issue_peer_online_check (sub, peer); | 2196 | (void) issue_peer_online_check (sub, peer); |
2180 | (void) schedule_operation (peer_ctx, insert_in_view_op, NULL); | 2197 | (void) schedule_operation (peer_ctx, insert_in_view_op, sub); |
2181 | return GNUNET_NO; | 2198 | return GNUNET_NO; |
2182 | } | 2199 | } |
2183 | /* Open channel towards peer to keep connection open */ | 2200 | /* Open channel towards peer to keep connection open */ |
@@ -2690,6 +2707,14 @@ clean_peer (struct Sub *sub, | |||
2690 | #endif /* ENABLE_MALICIOUS */ | 2707 | #endif /* ENABLE_MALICIOUS */ |
2691 | } | 2708 | } |
2692 | 2709 | ||
2710 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (sub->peer_map, peer)) | ||
2711 | { | ||
2712 | /* Peer was already removed by callback on destroyed channel */ | ||
2713 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2714 | "Peer was removed from our knowledge during cleanup\n"); | ||
2715 | return; | ||
2716 | } | ||
2717 | |||
2693 | if ( (GNUNET_NO == check_peer_send_intention (get_peer_ctx (sub->peer_map, | 2718 | if ( (GNUNET_NO == check_peer_send_intention (get_peer_ctx (sub->peer_map, |
2694 | peer))) && | 2719 | peer))) && |
2695 | (GNUNET_NO == View_contains_peer (sub->view, peer)) && | 2720 | (GNUNET_NO == View_contains_peer (sub->view, peer)) && |
@@ -2729,7 +2754,8 @@ cleanup_destroyed_channel (void *cls, | |||
2729 | channel_ctx->channel = NULL; | 2754 | channel_ctx->channel = NULL; |
2730 | remove_channel_ctx (channel_ctx); | 2755 | remove_channel_ctx (channel_ctx); |
2731 | if (NULL != peer_ctx && | 2756 | if (NULL != peer_ctx && |
2732 | peer_ctx->send_channel_ctx == channel_ctx) | 2757 | peer_ctx->send_channel_ctx == channel_ctx && |
2758 | GNUNET_YES == check_sending_channel_needed (channel_ctx->peer_ctx)) | ||
2733 | { | 2759 | { |
2734 | remove_peer (peer_ctx->sub, &peer_ctx->peer_id); | 2760 | remove_peer (peer_ctx->sub, &peer_ctx->peer_id); |
2735 | } | 2761 | } |
@@ -2814,6 +2840,25 @@ new_sub (const struct GNUNET_HashCode *hash, | |||
2814 | "rps", | 2840 | "rps", |
2815 | "FILENAME_VALID_PEERS"); | 2841 | "FILENAME_VALID_PEERS"); |
2816 | } | 2842 | } |
2843 | if (0 != strncmp ("DISABLE", sub->filename_valid_peers, 7)) | ||
2844 | { | ||
2845 | char *tmp_filename_valid_peers; | ||
2846 | char str_hash[105]; | ||
2847 | uint32_t len_filename_valid_peers; | ||
2848 | |||
2849 | (void) GNUNET_snprintf (str_hash, 105, GNUNET_h2s_full (hash)); | ||
2850 | tmp_filename_valid_peers = GNUNET_strdup (sub->filename_valid_peers); | ||
2851 | GNUNET_free (sub->filename_valid_peers); | ||
2852 | len_filename_valid_peers = strlen (tmp_filename_valid_peers) + 105; /* Len of full hash + 1 */ | ||
2853 | sub->filename_valid_peers = GNUNET_malloc (len_filename_valid_peers); | ||
2854 | strncat (sub->filename_valid_peers, | ||
2855 | tmp_filename_valid_peers, | ||
2856 | len_filename_valid_peers); | ||
2857 | strncat (sub->filename_valid_peers, | ||
2858 | str_hash, | ||
2859 | len_filename_valid_peers); | ||
2860 | GNUNET_free (tmp_filename_valid_peers); | ||
2861 | } | ||
2817 | sub->peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); | 2862 | sub->peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); |
2818 | 2863 | ||
2819 | /* Set up the sampler */ | 2864 | /* Set up the sampler */ |
@@ -2952,6 +2997,73 @@ destroy_sub (struct Sub *sub) | |||
2952 | ***********************************************************************/ | 2997 | ***********************************************************************/ |
2953 | 2998 | ||
2954 | 2999 | ||
3000 | /*********************************************************************** | ||
3001 | * Core handlers | ||
3002 | ***********************************************************************/ | ||
3003 | |||
3004 | /** | ||
3005 | * @brief Callback on initialisation of Core. | ||
3006 | * | ||
3007 | * @param cls - unused | ||
3008 | * @param my_identity - unused | ||
3009 | */ | ||
3010 | void | ||
3011 | core_init (void *cls, | ||
3012 | const struct GNUNET_PeerIdentity *my_identity) | ||
3013 | { | ||
3014 | (void) cls; | ||
3015 | (void) my_identity; | ||
3016 | |||
3017 | map_single_hop = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); | ||
3018 | } | ||
3019 | |||
3020 | |||
3021 | /** | ||
3022 | * @brief Callback for core. | ||
3023 | * Method called whenever a given peer connects. | ||
3024 | * | ||
3025 | * @param cls closure - unused | ||
3026 | * @param peer peer identity this notification is about | ||
3027 | * @return closure given to #core_disconnects as peer_cls | ||
3028 | */ | ||
3029 | void * | ||
3030 | core_connects (void *cls, | ||
3031 | const struct GNUNET_PeerIdentity *peer, | ||
3032 | struct GNUNET_MQ_Handle *mq) | ||
3033 | { | ||
3034 | (void) cls; | ||
3035 | (void) mq; | ||
3036 | |||
3037 | GNUNET_CONTAINER_multipeermap_put (map_single_hop, peer, NULL, | ||
3038 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
3039 | return NULL; | ||
3040 | } | ||
3041 | |||
3042 | |||
3043 | /** | ||
3044 | * @brief Callback for core. | ||
3045 | * Method called whenever a peer disconnects. | ||
3046 | * | ||
3047 | * @param cls closure - unused | ||
3048 | * @param peer peer identity this notification is about | ||
3049 | * @param peer_cls closure given in #core_connects - unused | ||
3050 | */ | ||
3051 | void | ||
3052 | core_disconnects (void *cls, | ||
3053 | const struct GNUNET_PeerIdentity *peer, | ||
3054 | void *peer_cls) | ||
3055 | { | ||
3056 | (void) cls; | ||
3057 | (void) peer_cls; | ||
3058 | |||
3059 | GNUNET_CONTAINER_multipeermap_remove_all (map_single_hop, peer); | ||
3060 | } | ||
3061 | |||
3062 | /*********************************************************************** | ||
3063 | * /Core handlers | ||
3064 | ***********************************************************************/ | ||
3065 | |||
3066 | |||
2955 | /** | 3067 | /** |
2956 | * @brief Destroy the context for a (connected) client | 3068 | * @brief Destroy the context for a (connected) client |
2957 | * | 3069 | * |
@@ -3395,6 +3507,14 @@ handle_peer_pull_request (void *cls, | |||
3395 | "# pull request message received", | 3507 | "# pull request message received", |
3396 | 1, | 3508 | 1, |
3397 | GNUNET_NO); | 3509 | GNUNET_NO); |
3510 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop, | ||
3511 | &peer_ctx->peer_id)) | ||
3512 | { | ||
3513 | GNUNET_STATISTICS_update (stats, | ||
3514 | "# pull request message received (multi-hop peer)", | ||
3515 | 1, | ||
3516 | GNUNET_NO); | ||
3517 | } | ||
3398 | } | 3518 | } |
3399 | 3519 | ||
3400 | #ifdef ENABLE_MALICIOUS | 3520 | #ifdef ENABLE_MALICIOUS |
@@ -3503,6 +3623,14 @@ handle_peer_pull_reply (void *cls, | |||
3503 | "# pull reply messages received", | 3623 | "# pull reply messages received", |
3504 | 1, | 3624 | 1, |
3505 | GNUNET_NO); | 3625 | GNUNET_NO); |
3626 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop, | ||
3627 | &channel_ctx->peer_ctx->peer_id)) | ||
3628 | { | ||
3629 | GNUNET_STATISTICS_update (stats, | ||
3630 | "# pull reply messages received (multi-hop peer)", | ||
3631 | 1, | ||
3632 | GNUNET_NO); | ||
3633 | } | ||
3506 | } | 3634 | } |
3507 | 3635 | ||
3508 | #ifdef ENABLE_MALICIOUS | 3636 | #ifdef ENABLE_MALICIOUS |
@@ -3650,6 +3778,14 @@ send_pull_request (struct PeerContext *peer_ctx) | |||
3650 | "# pull request send issued", | 3778 | "# pull request send issued", |
3651 | 1, | 3779 | 1, |
3652 | GNUNET_NO); | 3780 | GNUNET_NO); |
3781 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop, | ||
3782 | &peer_ctx->peer_id)) | ||
3783 | { | ||
3784 | GNUNET_STATISTICS_update (stats, | ||
3785 | "# pull request send issued (multi-hop peer)", | ||
3786 | 1, | ||
3787 | GNUNET_NO); | ||
3788 | } | ||
3653 | } | 3789 | } |
3654 | } | 3790 | } |
3655 | 3791 | ||
@@ -4384,6 +4520,15 @@ shutdown_task (void *cls) | |||
4384 | GNUNET_PEERINFO_disconnect (peerinfo_handle); | 4520 | GNUNET_PEERINFO_disconnect (peerinfo_handle); |
4385 | peerinfo_handle = NULL; | 4521 | peerinfo_handle = NULL; |
4386 | GNUNET_NSE_disconnect (nse); | 4522 | GNUNET_NSE_disconnect (nse); |
4523 | if (NULL != map_single_hop) | ||
4524 | { | ||
4525 | /* core_init was called - core was initialised */ | ||
4526 | /* disconnect first, so no callback tries to access missing peermap */ | ||
4527 | GNUNET_CORE_disconnect (core_handle); | ||
4528 | core_handle = NULL; | ||
4529 | GNUNET_CONTAINER_multipeermap_destroy (map_single_hop); | ||
4530 | map_single_hop = NULL; | ||
4531 | } | ||
4387 | 4532 | ||
4388 | if (NULL != stats) | 4533 | if (NULL != stats) |
4389 | { | 4534 | { |
@@ -4538,6 +4683,13 @@ run (void *cls, | |||
4538 | 4683 | ||
4539 | cadet_handle = GNUNET_CADET_connect (cfg); | 4684 | cadet_handle = GNUNET_CADET_connect (cfg); |
4540 | GNUNET_assert (NULL != cadet_handle); | 4685 | GNUNET_assert (NULL != cadet_handle); |
4686 | core_handle = GNUNET_CORE_connect (cfg, | ||
4687 | NULL, /* cls */ | ||
4688 | core_init, /* init */ | ||
4689 | core_connects, /* connects */ | ||
4690 | core_disconnects, /* disconnects */ | ||
4691 | NULL); /* handlers */ | ||
4692 | GNUNET_assert (NULL != core_handle); | ||
4541 | 4693 | ||
4542 | 4694 | ||
4543 | alpha = 0.45; | 4695 | alpha = 0.45; |
diff --git a/src/rps/rps_api.c b/src/rps/rps_api.c index bce567678..cfab06f17 100644 --- a/src/rps/rps_api.c +++ b/src/rps/rps_api.c | |||
@@ -854,6 +854,7 @@ GNUNET_RPS_request_cancel (struct GNUNET_RPS_Request_Handle *rh) | |||
854 | struct GNUNET_RPS_Handle *h; | 854 | struct GNUNET_RPS_Handle *h; |
855 | 855 | ||
856 | h = rh->rps_handle; | 856 | h = rh->rps_handle; |
857 | GNUNET_assert (NULL != rh); | ||
857 | GNUNET_assert (NULL != rh->srh); | 858 | GNUNET_assert (NULL != rh->srh); |
858 | remove_stream_request (rh->srh, | 859 | remove_stream_request (rh->srh, |
859 | h->stream_requests_head, | 860 | h->stream_requests_head, |
diff --git a/src/transport/transport.h b/src/transport/transport.h index 75726e462..e68536bcc 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h | |||
@@ -644,6 +644,263 @@ struct TransportPluginMonitorMessage | |||
644 | }; | 644 | }; |
645 | 645 | ||
646 | 646 | ||
647 | |||
648 | |||
649 | |||
650 | |||
651 | |||
652 | |||
653 | |||
654 | /* *********************** TNG messages ***************** */ | ||
655 | |||
656 | /** | ||
657 | * Add address to the list. | ||
658 | */ | ||
659 | struct GNUNET_TRANSPORT_AddAddressMessage | ||
660 | { | ||
661 | |||
662 | /** | ||
663 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS. | ||
664 | */ | ||
665 | struct GNUNET_MessageHeader header; | ||
666 | |||
667 | /** | ||
668 | * Address identifier (used during deletion). | ||
669 | */ | ||
670 | uint32_t aid GNUNET_PACKED; | ||
671 | |||
672 | /** | ||
673 | * When does the address expire? | ||
674 | */ | ||
675 | struct GNUNET_TIME_RelativeNBO expiration; | ||
676 | |||
677 | /** | ||
678 | * An `enum GNUNET_ATS_Network_Type` in NBO. | ||
679 | */ | ||
680 | uint32_t nt; | ||
681 | |||
682 | /* followed by UTF-8 encoded, 0-terminated human-readable address */ | ||
683 | }; | ||
684 | |||
685 | |||
686 | /** | ||
687 | * Remove address from the list. | ||
688 | */ | ||
689 | struct GNUNET_TRANSPORT_DelAddressMessage | ||
690 | { | ||
691 | |||
692 | /** | ||
693 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS. | ||
694 | */ | ||
695 | struct GNUNET_MessageHeader header; | ||
696 | |||
697 | /** | ||
698 | * Address identifier. | ||
699 | */ | ||
700 | uint32_t aid GNUNET_PACKED; | ||
701 | |||
702 | }; | ||
703 | |||
704 | |||
705 | /** | ||
706 | * Inform transport about an incoming message. | ||
707 | */ | ||
708 | struct GNUNET_TRANSPORT_IncomingMessage | ||
709 | { | ||
710 | |||
711 | /** | ||
712 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG. | ||
713 | */ | ||
714 | struct GNUNET_MessageHeader header; | ||
715 | |||
716 | /** | ||
717 | * Do we use flow control or not? | ||
718 | */ | ||
719 | uint32_t fc_on GNUNET_PACKED; | ||
720 | |||
721 | /** | ||
722 | * 64-bit number to identify the matching ACK. | ||
723 | */ | ||
724 | uint64_t fc_id GNUNET_PACKED; | ||
725 | |||
726 | /** | ||
727 | * Sender identifier. | ||
728 | */ | ||
729 | struct GNUNET_PeerIdentity sender; | ||
730 | |||
731 | /* followed by the message */ | ||
732 | }; | ||
733 | |||
734 | |||
735 | /** | ||
736 | * Transport informs us about being done with an incoming message. | ||
737 | * (only sent if fc_on was set). | ||
738 | */ | ||
739 | struct GNUNET_TRANSPORT_IncomingMessageAck | ||
740 | { | ||
741 | |||
742 | /** | ||
743 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK. | ||
744 | */ | ||
745 | struct GNUNET_MessageHeader header; | ||
746 | |||
747 | /** | ||
748 | * Reserved (0) | ||
749 | */ | ||
750 | uint32_t reserved GNUNET_PACKED; | ||
751 | |||
752 | /** | ||
753 | * Which message is being ACKed? | ||
754 | */ | ||
755 | uint64_t fc_id GNUNET_PACKED; | ||
756 | |||
757 | /** | ||
758 | * Sender identifier of the original message. | ||
759 | */ | ||
760 | struct GNUNET_PeerIdentity sender; | ||
761 | |||
762 | }; | ||
763 | |||
764 | |||
765 | /** | ||
766 | * Add queue to the transport | ||
767 | */ | ||
768 | struct GNUNET_TRANSPORT_AddQueueMessage | ||
769 | { | ||
770 | |||
771 | /** | ||
772 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE. | ||
773 | */ | ||
774 | struct GNUNET_MessageHeader header; | ||
775 | |||
776 | /** | ||
777 | * Queue identifier (used to identify the queue). | ||
778 | */ | ||
779 | uint32_t qid GNUNET_PACKED; | ||
780 | |||
781 | /** | ||
782 | * Receiver that can be addressed via the queue. | ||
783 | */ | ||
784 | struct GNUNET_PeerIdentity receiver; | ||
785 | |||
786 | /** | ||
787 | * An `enum GNUNET_ATS_Network_Type` in NBO. | ||
788 | */ | ||
789 | uint32_t nt; | ||
790 | |||
791 | /* followed by UTF-8 encoded, 0-terminated human-readable address */ | ||
792 | }; | ||
793 | |||
794 | |||
795 | /** | ||
796 | * Remove queue, it is no longer available. | ||
797 | */ | ||
798 | struct GNUNET_TRANSPORT_DelQueueMessage | ||
799 | { | ||
800 | |||
801 | /** | ||
802 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE. | ||
803 | */ | ||
804 | struct GNUNET_MessageHeader header; | ||
805 | |||
806 | /** | ||
807 | * Address identifier. | ||
808 | */ | ||
809 | uint32_t qid GNUNET_PACKED; | ||
810 | |||
811 | /** | ||
812 | * Receiver that can be addressed via the queue. | ||
813 | */ | ||
814 | struct GNUNET_PeerIdentity receiver; | ||
815 | |||
816 | }; | ||
817 | |||
818 | |||
819 | /** | ||
820 | * Transport tells communicator that it wants a new queue. | ||
821 | */ | ||
822 | struct GNUNET_TRANSPORT_CreateQueue | ||
823 | { | ||
824 | |||
825 | /** | ||
826 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE. | ||
827 | */ | ||
828 | struct GNUNET_MessageHeader header; | ||
829 | |||
830 | /** | ||
831 | * Always zero. | ||
832 | */ | ||
833 | uint32_t reserved GNUNET_PACKED; | ||
834 | |||
835 | /** | ||
836 | * Receiver that can be addressed via the queue. | ||
837 | */ | ||
838 | struct GNUNET_PeerIdentity receiver; | ||
839 | |||
840 | /* followed by UTF-8 encoded, 0-terminated human-readable address */ | ||
841 | }; | ||
842 | |||
843 | |||
844 | /** | ||
845 | * Inform communicator about transport's desire to send a message. | ||
846 | */ | ||
847 | struct GNUNET_TRANSPORT_SendMessageTo | ||
848 | { | ||
849 | |||
850 | /** | ||
851 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG. | ||
852 | */ | ||
853 | struct GNUNET_MessageHeader header; | ||
854 | |||
855 | /** | ||
856 | * Which queue should we use? | ||
857 | */ | ||
858 | uint32_t qid GNUNET_PACKED; | ||
859 | |||
860 | /** | ||
861 | * Message ID, used for flow control. | ||
862 | */ | ||
863 | uint64_t mid GNUNET_PACKED; | ||
864 | |||
865 | /** | ||
866 | * Receiver identifier. | ||
867 | */ | ||
868 | struct GNUNET_PeerIdentity receiver; | ||
869 | |||
870 | /* followed by the message */ | ||
871 | }; | ||
872 | |||
873 | |||
874 | /** | ||
875 | * Inform transport that message was sent. | ||
876 | */ | ||
877 | struct GNUNET_TRANSPORT_SendMessageToAck | ||
878 | { | ||
879 | |||
880 | /** | ||
881 | * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK. | ||
882 | */ | ||
883 | struct GNUNET_MessageHeader header; | ||
884 | |||
885 | /** | ||
886 | * Success (#GNUNET_OK), failure (#GNUNET_SYSERR). | ||
887 | */ | ||
888 | uint32_t status GNUNET_PACKED; | ||
889 | |||
890 | /** | ||
891 | * Message ID of the original message. | ||
892 | */ | ||
893 | uint64_t mid GNUNET_PACKED; | ||
894 | |||
895 | /** | ||
896 | * Receiver identifier. | ||
897 | */ | ||
898 | struct GNUNET_PeerIdentity receiver; | ||
899 | |||
900 | }; | ||
901 | |||
902 | |||
903 | |||
647 | GNUNET_NETWORK_STRUCT_END | 904 | GNUNET_NETWORK_STRUCT_END |
648 | 905 | ||
649 | /* end of transport.h */ | 906 | /* end of transport.h */ |
diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c new file mode 100644 index 000000000..d446516bd --- /dev/null +++ b/src/transport/transport_api2_communication.c | |||
@@ -0,0 +1,959 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @file transport/transport_api2_communication.c | ||
21 | * @brief implementation of the gnunet_transport_communication_service.h API | ||
22 | * @author Christian Grothoff | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_protocols.h" | ||
27 | #include "gnunet_transport_communication_service.h" | ||
28 | #include "transport.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * How many messages do we keep at most in the queue to the | ||
33 | * transport service before we start to drop (default, | ||
34 | * can be changed via the configuration file). | ||
35 | */ | ||
36 | #define DEFAULT_MAX_QUEUE_LENGTH 16 | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Information we track per packet to enable flow control. | ||
41 | */ | ||
42 | struct FlowControl | ||
43 | { | ||
44 | /** | ||
45 | * Kept in a DLL. | ||
46 | */ | ||
47 | struct FlowControl *next; | ||
48 | |||
49 | /** | ||
50 | * Kept in a DLL. | ||
51 | */ | ||
52 | struct FlowControl *prev; | ||
53 | |||
54 | /** | ||
55 | * Function to call once the message was processed. | ||
56 | */ | ||
57 | GNUNET_TRANSPORT_MessageCompletedCallback cb; | ||
58 | |||
59 | /** | ||
60 | * Closure for @e cb | ||
61 | */ | ||
62 | void *cb_cls; | ||
63 | |||
64 | /** | ||
65 | * Which peer is this about? | ||
66 | */ | ||
67 | struct GNUNET_PeerIdentity sender; | ||
68 | |||
69 | /** | ||
70 | * More-or-less unique ID for the message. | ||
71 | */ | ||
72 | uint64_t id; | ||
73 | }; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Information we track per message to tell the transport about | ||
78 | * success or failures. | ||
79 | */ | ||
80 | struct AckPending | ||
81 | { | ||
82 | /** | ||
83 | * Kept in a DLL. | ||
84 | */ | ||
85 | struct AckPending *next; | ||
86 | |||
87 | /** | ||
88 | * Kept in a DLL. | ||
89 | */ | ||
90 | struct AckPending *prev; | ||
91 | |||
92 | /** | ||
93 | * Which peer is this about? | ||
94 | */ | ||
95 | struct GNUNET_PeerIdentity receiver; | ||
96 | |||
97 | /** | ||
98 | * More-or-less unique ID for the message. | ||
99 | */ | ||
100 | uint64_t mid; | ||
101 | }; | ||
102 | |||
103 | |||
104 | /** | ||
105 | * Opaque handle to the transport service for communicators. | ||
106 | */ | ||
107 | struct GNUNET_TRANSPORT_CommunicatorHandle | ||
108 | { | ||
109 | /** | ||
110 | * Head of DLL of addresses this communicator offers to the transport service. | ||
111 | */ | ||
112 | struct GNUNET_TRANSPORT_AddressIdentifier *ai_head; | ||
113 | |||
114 | /** | ||
115 | * Tail of DLL of addresses this communicator offers to the transport service. | ||
116 | */ | ||
117 | struct GNUNET_TRANSPORT_AddressIdentifier *ai_tail; | ||
118 | |||
119 | /** | ||
120 | * DLL of messages awaiting flow control confirmation (ack). | ||
121 | */ | ||
122 | struct FlowControl *fc_head; | ||
123 | |||
124 | /** | ||
125 | * DLL of messages awaiting flow control confirmation (ack). | ||
126 | */ | ||
127 | struct FlowControl *fc_tail; | ||
128 | |||
129 | /** | ||
130 | * DLL of messages awaiting transmission confirmation (ack). | ||
131 | */ | ||
132 | struct AckPending *ap_head; | ||
133 | |||
134 | /** | ||
135 | * DLL of messages awaiting transmission confirmation (ack). | ||
136 | */ | ||
137 | struct AckPending *ac_tail; | ||
138 | |||
139 | /** | ||
140 | * DLL of queues we offer. | ||
141 | */ | ||
142 | struct QueueHandle *queue_head; | ||
143 | |||
144 | /** | ||
145 | * DLL of queues we offer. | ||
146 | */ | ||
147 | struct QueueHandle *queue_tail; | ||
148 | |||
149 | /** | ||
150 | * Our configuration. | ||
151 | */ | ||
152 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
153 | |||
154 | /** | ||
155 | * Name of the communicator. | ||
156 | */ | ||
157 | const char *name; | ||
158 | |||
159 | /** | ||
160 | * Function to call when the transport service wants us to initiate | ||
161 | * a communication channel with another peer. | ||
162 | */ | ||
163 | GNUNET_TRANSPORT_CommunicatorMqInit mq_init; | ||
164 | |||
165 | /** | ||
166 | * Closure for @e mq_init. | ||
167 | */ | ||
168 | void *mq_init_cls; | ||
169 | |||
170 | /** | ||
171 | * Maximum permissable queue length. | ||
172 | */ | ||
173 | unsigned long long max_queue_length; | ||
174 | |||
175 | /** | ||
176 | * Flow-control identifier generator. | ||
177 | */ | ||
178 | uint64_t fc_gen; | ||
179 | |||
180 | /** | ||
181 | * MTU of the communicator | ||
182 | */ | ||
183 | size_t mtu; | ||
184 | |||
185 | /** | ||
186 | * Internal UUID for the address used in communication with the | ||
187 | * transport service. | ||
188 | */ | ||
189 | uint32_t aid_gen; | ||
190 | |||
191 | /** | ||
192 | * Queue identifier generator. | ||
193 | */ | ||
194 | uint32_t queue_gen; | ||
195 | |||
196 | }; | ||
197 | |||
198 | |||
199 | /** | ||
200 | * Handle returned to identify the internal data structure the transport | ||
201 | * API has created to manage a message queue to a particular peer. | ||
202 | */ | ||
203 | struct GNUNET_TRANSPORT_QueueHandle | ||
204 | { | ||
205 | /** | ||
206 | * Handle this queue belongs to. | ||
207 | */ | ||
208 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch; | ||
209 | |||
210 | /** | ||
211 | * Which peer we can communciate with. | ||
212 | */ | ||
213 | struct GNUNET_PeerIdentity peer; | ||
214 | |||
215 | /** | ||
216 | * Address used by the communication queue. | ||
217 | */ | ||
218 | char *address; | ||
219 | |||
220 | /** | ||
221 | * Network type of the communciation queue. | ||
222 | */ | ||
223 | enum GNUNET_ATS_Network_Type nt; | ||
224 | |||
225 | /** | ||
226 | * The queue itself. | ||
227 | */ | ||
228 | struct GNUNET_MQ_Handle *mq; | ||
229 | |||
230 | /** | ||
231 | * ID for this queue when talking to the transport service. | ||
232 | */ | ||
233 | uint32_t queue_id; | ||
234 | |||
235 | }; | ||
236 | |||
237 | |||
238 | /** | ||
239 | * Internal representation of an address a communicator is | ||
240 | * currently providing for the transport service. | ||
241 | */ | ||
242 | struct GNUNET_TRANSPORT_AddressIdentifier | ||
243 | { | ||
244 | |||
245 | /** | ||
246 | * Kept in a DLL. | ||
247 | */ | ||
248 | struct GNUNET_TRANSPORT_AddressIdentifier *next; | ||
249 | |||
250 | /** | ||
251 | * Kept in a DLL. | ||
252 | */ | ||
253 | struct GNUNET_TRANSPORT_AddressIdentifier *prev; | ||
254 | |||
255 | /** | ||
256 | * Transport handle where the address was added. | ||
257 | */ | ||
258 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch; | ||
259 | |||
260 | /** | ||
261 | * The actual address. | ||
262 | */ | ||
263 | char *address; | ||
264 | |||
265 | /** | ||
266 | * When does the address expire? (Expected lifetime of the | ||
267 | * address.) | ||
268 | */ | ||
269 | struct GNUNET_TIME_Relative expiration; | ||
270 | |||
271 | /** | ||
272 | * Internal UUID for the address used in communication with the | ||
273 | * transport service. | ||
274 | */ | ||
275 | uint32_t aid; | ||
276 | |||
277 | /** | ||
278 | * Network type for the address. | ||
279 | */ | ||
280 | enum GNUNET_ATS_Network_Type nt; | ||
281 | |||
282 | }; | ||
283 | |||
284 | |||
285 | /** | ||
286 | * (re)connect our communicator to the transport service | ||
287 | * | ||
288 | * @param ch handle to reconnect | ||
289 | */ | ||
290 | static void | ||
291 | reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch); | ||
292 | |||
293 | |||
294 | /** | ||
295 | * Send message to the transport service about address @a ai | ||
296 | * being now available. | ||
297 | * | ||
298 | * @param ai address to add | ||
299 | */ | ||
300 | static void | ||
301 | send_add_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai) | ||
302 | { | ||
303 | struct GNUNET_MQ_Envelope *env; | ||
304 | struct GNUNET_TRANSPORT_AddAddressMessage *aam; | ||
305 | |||
306 | if (NULL == ai->ch->mq) | ||
307 | return; | ||
308 | env = GNUNET_MQ_msg_extra (aam, | ||
309 | strlen (ai->address) + 1, | ||
310 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS); | ||
311 | aam->expiration = GNUNET_TIME_relative_to_nbo (ai->expiration); | ||
312 | aam->nt = htonl ((uint32_t) ai->nt); | ||
313 | memcpy (&aam[1], | ||
314 | ai->address, | ||
315 | strlen (ai->address) + 1); | ||
316 | GNUNET_MQ_send (ai->ch->mq, | ||
317 | env); | ||
318 | } | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Send message to the transport service about address @a ai | ||
323 | * being no longer available. | ||
324 | * | ||
325 | * @param ai address to delete | ||
326 | */ | ||
327 | static void | ||
328 | send_del_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai) | ||
329 | { | ||
330 | struct GNUNET_MQ_Envelope *env; | ||
331 | struct GNUNET_TRANSPORT_DelAddressMessage *dam; | ||
332 | |||
333 | if (NULL == ai->ch->mq) | ||
334 | return; | ||
335 | env = GNUNET_MQ_msg (dam, | ||
336 | GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS); | ||
337 | dam.aid = htonl (ai->aid); | ||
338 | GNUNET_MQ_send (ai->ch->mq, | ||
339 | env); | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Send message to the transport service about queue @a qh | ||
345 | * being now available. | ||
346 | * | ||
347 | * @param qh queue to add | ||
348 | */ | ||
349 | static void | ||
350 | send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh) | ||
351 | { | ||
352 | struct GNUNET_MQ_Envelope *env; | ||
353 | struct GNUNET_TRANSPORT_AddQueueMessage *aqm; | ||
354 | |||
355 | if (NULL == ai->ch->mq) | ||
356 | return; | ||
357 | env = GNUNET_MQ_msg_extra (aqm, | ||
358 | strlen (ai->address) + 1, | ||
359 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE); | ||
360 | aqm.receiver = qh->peer; | ||
361 | aqm.nt = htonl ((uint32_t) qh->nt); | ||
362 | aqm.qid = htonl (qh->qid); | ||
363 | memcpy (&aqm[1], | ||
364 | ai->address, | ||
365 | strlen (ai->address) + 1); | ||
366 | GNUNET_MQ_send (ai->ch->mq, | ||
367 | env); | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Send message to the transport service about queue @a qh | ||
373 | * being no longer available. | ||
374 | * | ||
375 | * @param qh queue to delete | ||
376 | */ | ||
377 | static void | ||
378 | send_del_queue (struct GNUNET_TRANSPORT_QueueHandle *qh) | ||
379 | { | ||
380 | struct GNUNET_MQ_Envelope *env; | ||
381 | struct GNUNET_TRANSPORT_DelQueueMessage *dqm; | ||
382 | |||
383 | if (NULL == ai->ch->mq) | ||
384 | return; | ||
385 | env = GNUNET_MQ_msg (dqm, | ||
386 | GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE); | ||
387 | dqm.qid = htonl (qh->qid); | ||
388 | dqm.receiver = qh->peer; | ||
389 | GNUNET_MQ_send (ai->ch->mq, | ||
390 | env); | ||
391 | } | ||
392 | |||
393 | |||
394 | /** | ||
395 | * Disconnect from the transport service. Purges | ||
396 | * all flow control entries as we will no longer receive | ||
397 | * the ACKs. Purges the ack pending entries as the | ||
398 | * transport will no longer expect the confirmations. | ||
399 | * | ||
400 | * @param ch service to disconnect from | ||
401 | */ | ||
402 | static void | ||
403 | disconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) | ||
404 | { | ||
405 | struct FlowControl *fcn; | ||
406 | struct AckPending *apn; | ||
407 | |||
408 | for (struct FlowControl *fc = ch->fc_head; | ||
409 | NULL != fc; | ||
410 | fc = fcn) | ||
411 | { | ||
412 | fcn = fc->next; | ||
413 | GNUNET_CONTAINER_DLL_remove (ch->fc_head, | ||
414 | ch->fc_tail, | ||
415 | fc); | ||
416 | fc->cb (fc->cb_cls, | ||
417 | GNUNET_SYSERR); | ||
418 | GNUNET_free (fc); | ||
419 | } | ||
420 | for (struct AckPending *ap = ch->ap_head; | ||
421 | NULL != ap; | ||
422 | ap = apn) | ||
423 | { | ||
424 | apn = ap->next; | ||
425 | GNUNET_CONTAINER_DLL_remove (ch->ap_head, | ||
426 | ch->ap_tail, | ||
427 | ap); | ||
428 | GNUNET_free (ap); | ||
429 | } | ||
430 | if (NULL == ch->mq) | ||
431 | return; | ||
432 | GNUNET_MQ_destroy (ch->mq); | ||
433 | ch->mq = NULL; | ||
434 | } | ||
435 | |||
436 | |||
437 | /** | ||
438 | * Function called on MQ errors. | ||
439 | */ | ||
440 | static void | ||
441 | error_handler (void *cls, | ||
442 | enum GNUNET_MQ_Error error) | ||
443 | { | ||
444 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; | ||
445 | |||
446 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
447 | "MQ failure, reconnecting to transport service.\n"); | ||
448 | disconnect (ch); | ||
449 | /* TODO: maybe do this with exponential backoff/delay */ | ||
450 | reconnect (ch); | ||
451 | } | ||
452 | |||
453 | |||
454 | /** | ||
455 | * Transport service acknowledged a message we gave it | ||
456 | * (with flow control enabled). Tell the communicator. | ||
457 | * | ||
458 | * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *` | ||
459 | * @param incoming_ack the ack | ||
460 | */ | ||
461 | static void | ||
462 | handle_incoming_ack (void *cls, | ||
463 | struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack) | ||
464 | { | ||
465 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; | ||
466 | |||
467 | for (struct FlowControl *fc = ch->fc_head; | ||
468 | NULL != fc; | ||
469 | fc = fc->next) | ||
470 | { | ||
471 | if ( (fc->id == incoming_ack->fc_id) && | ||
472 | (0 == memcmp (&fc->sender, | ||
473 | incoming_ack->sender, | ||
474 | sizeof (struct GNUNET_PeerIdentity))) ) | ||
475 | { | ||
476 | GNUNET_CONTAINER_DLL_remove (ch->fc_head, | ||
477 | ch->fc_tail, | ||
478 | fc); | ||
479 | fc->cb (fc->cb_cls, | ||
480 | GNUNET_OK); | ||
481 | GNUNET_free (fc); | ||
482 | return; | ||
483 | } | ||
484 | } | ||
485 | GNUNET_break (0); | ||
486 | disconnect (ch); | ||
487 | /* TODO: maybe do this with exponential backoff/delay */ | ||
488 | reconnect (ch); | ||
489 | } | ||
490 | |||
491 | |||
492 | /** | ||
493 | * Transport service wants us to create a queue. Check if @a cq | ||
494 | * is well-formed. | ||
495 | * | ||
496 | * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *` | ||
497 | * @param cq the queue creation request | ||
498 | * @return #GNUNET_OK if @a smt is well-formed | ||
499 | */ | ||
500 | static int | ||
501 | check_create_queue (void *cls, | ||
502 | struct GNUNET_TRANSPORT_CreateQueue *cq) | ||
503 | { | ||
504 | uint16_t len = ntohs (cq->header.size) - sizeof (*cq); | ||
505 | const char *addr = (const char *) &cq[1]; | ||
506 | |||
507 | if ( (0 == len) || | ||
508 | ('\0' != addr[len-1]) ) | ||
509 | { | ||
510 | GNUNET_break (0); | ||
511 | return GNUNET_SYSERR; | ||
512 | } | ||
513 | return GNUNET_OK; | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
518 | * Transport service wants us to create a queue. Tell the communicator. | ||
519 | * | ||
520 | * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *` | ||
521 | * @param cq the queue creation request | ||
522 | */ | ||
523 | static void | ||
524 | handle_create_queue (void *cls, | ||
525 | struct GNUNET_TRANSPORT_CreateQueue *cq) | ||
526 | { | ||
527 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; | ||
528 | const char *addr = (const char *) &cq[1]; | ||
529 | |||
530 | if (GNUNET_OK != | ||
531 | ch->mq_init (ch->mq_init_cls, | ||
532 | &cq->receiver, | ||
533 | addr)) | ||
534 | { | ||
535 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
536 | "Address `%s' invalid for this communicator\n", | ||
537 | addr); | ||
538 | // TODO: do we notify the transport!? | ||
539 | } | ||
540 | } | ||
541 | |||
542 | |||
543 | /** | ||
544 | * Transport service wants us to send a message. Check if @a smt | ||
545 | * is well-formed. | ||
546 | * | ||
547 | * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *` | ||
548 | * @param smt the transmission request | ||
549 | * @return #GNUNET_OK if @a smt is well-formed | ||
550 | */ | ||
551 | static int | ||
552 | check_send_msg (void *cls, | ||
553 | struct GNUNET_TRANSPORT_SendMessageTo *smt) | ||
554 | { | ||
555 | uint16_t len = ntohs (smt->header.size) - sizeof (*smt); | ||
556 | const struct GNUNET_MessageHeader *mh = (const struct GNUNET_MessageHeader *) &smt[1]; | ||
557 | |||
558 | if (ntohs (mh->size) != len) | ||
559 | { | ||
560 | GNUNET_break (0); | ||
561 | return GNUNET_SYSERR; | ||
562 | } | ||
563 | return GNUNET_OK; | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * Notify transport service about @a status of a message with | ||
569 | * @a mid sent to @a receiver. | ||
570 | * | ||
571 | * @param ch handle | ||
572 | * @param status #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
573 | * @param receiver which peer was the receiver | ||
574 | * @param mid message that the ack is about | ||
575 | */ | ||
576 | static void | ||
577 | send_ack (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, | ||
578 | int status, | ||
579 | const struct GNUNET_PeerIdentity *receiver, | ||
580 | uint64_t mid) | ||
581 | { | ||
582 | struct GNUNET_MQ_Envelope *env; | ||
583 | struct GNUNET_TRANSPORT_SendMessageToAck *ack; | ||
584 | |||
585 | env = GNUNET_MQ_msg (ack, | ||
586 | GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK); | ||
587 | ack->status = htonl (GNUNET_OK); | ||
588 | ack->mid = ap->mid; | ||
589 | ack->receiver = ap->receiver; | ||
590 | GNUNET_MQ_send (ch->mq, | ||
591 | env); | ||
592 | } | ||
593 | |||
594 | |||
595 | /** | ||
596 | * Message queue transmission by communicator was successful, | ||
597 | * notify transport service. | ||
598 | * | ||
599 | * @param cls an `struct AckPending *` | ||
600 | */ | ||
601 | static void | ||
602 | send_ack_cb (void *cls) | ||
603 | { | ||
604 | struct AckPending *ap = cls; | ||
605 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ap->ch; | ||
606 | |||
607 | GNUNET_CONTAINER_DLL_remove (ch->ap_head, | ||
608 | ch->ap_tail, | ||
609 | ap); | ||
610 | send_ack (ch, | ||
611 | GNUNET_OK, | ||
612 | &ap->receiver, | ||
613 | ap->mid); | ||
614 | GNUNET_free (ap); | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * Transport service wants us to send a message. Tell the communicator. | ||
620 | * | ||
621 | * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *` | ||
622 | * @param smt the transmission request | ||
623 | */ | ||
624 | static void | ||
625 | handle_send_msg (void *cls, | ||
626 | struct GNUNET_TRANSPORT_SendMessageTo *smt) | ||
627 | { | ||
628 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; | ||
629 | const struct GNUNET_MessageHeader *mh; | ||
630 | struct GNUNET_MQ_Envelope *env; | ||
631 | struct AckPending *ap; | ||
632 | struct QueueHandle *qh; | ||
633 | |||
634 | for (qh = ch->queue_head;NULL != qh; qh = qh->next) | ||
635 | if ( (qh->queue_id == smt->qid) && | ||
636 | (0 == memcmp (&qh->peer, | ||
637 | &smt->target, | ||
638 | sizeof (struct GNUNET_PeerIdentity))) ) | ||
639 | break; | ||
640 | if (NULL == qh) | ||
641 | { | ||
642 | /* queue is already gone, tell transport this one failed */ | ||
643 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
644 | "Transmission failed, queue no longer exists.\n"); | ||
645 | send_ack (ch, | ||
646 | GNUNET_NO, | ||
647 | &smt->receiver, | ||
648 | smt->mid); | ||
649 | return; | ||
650 | } | ||
651 | ap = GNUNET_new (struct AckPending); | ||
652 | ap->ch = ch; | ||
653 | ap->receiver = smt->receiver; | ||
654 | ap->mid = smt->mid; | ||
655 | GNUNET_CONTAINER_DLL_insert (ch->ap_head, | ||
656 | cp->ap_tail, | ||
657 | ap); | ||
658 | mh = (const struct GNUNET_MessageHeader *) &smt[1]; | ||
659 | env = GNUNET_MQ_msg_copy (mh); | ||
660 | GNUNET_MQ_notify_sent (env, | ||
661 | &send_ack_cb, | ||
662 | ap); | ||
663 | GNUNET_MQ_send (qh->mq, | ||
664 | env); | ||
665 | } | ||
666 | |||
667 | |||
668 | /** | ||
669 | * (re)connect our communicator to the transport service | ||
670 | * | ||
671 | * @param ch handle to reconnect | ||
672 | */ | ||
673 | static void | ||
674 | reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) | ||
675 | { | ||
676 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
677 | GNUNET_MQ_hd_fixed_size (incoming_ack, | ||
678 | GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK, | ||
679 | struct GNUNET_TRANSPORT_IncomingMessageAck, | ||
680 | ch), | ||
681 | GNUNET_MQ_hd_var_size (create_queue, | ||
682 | GNUNET_MESSAGE_TYPE_TRANSPORT_CREATE_QUEUE, | ||
683 | struct GNUNET_TRANSPORT_CreateQueue, | ||
684 | ch), | ||
685 | GNUNET_MQ_hd_var_size (send_msg, | ||
686 | GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG, | ||
687 | struct GNUNET_TRANSPORT_SendMessageTo, | ||
688 | ch), | ||
689 | GNUNET_MQ_handler_end() | ||
690 | }; | ||
691 | |||
692 | ch->mq = GNUNET_CLIENT_connect (cfg, | ||
693 | "transport", | ||
694 | handlers, | ||
695 | &error_handler, | ||
696 | ch); | ||
697 | for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; | ||
698 | NULL != ai; | ||
699 | ai = ai->next) | ||
700 | send_add_address (ai); | ||
701 | for (struct GNUNET_TRANSPORT_QueueHandle *qh = ch->queue_head; | ||
702 | NULL != qh; | ||
703 | qh = qh->next) | ||
704 | send_add_queue (qh); | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * Connect to the transport service. | ||
710 | * | ||
711 | * @param cfg configuration to use | ||
712 | * @param name name of the communicator that is connecting | ||
713 | * @param mtu maximum message size supported by communicator, 0 if | ||
714 | * sending is not supported, SIZE_MAX for no MTU | ||
715 | * @param mq_init function to call to initialize a message queue given | ||
716 | * the address of another peer, can be NULL if the | ||
717 | * communicator only supports receiving messages | ||
718 | * @param mq_init_cls closure for @a mq_init | ||
719 | * @return NULL on error | ||
720 | */ | ||
721 | struct GNUNET_TRANSPORT_CommunicatorHandle * | ||
722 | GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
723 | const char *name, | ||
724 | size_t mtu, | ||
725 | GNUNET_TRANSPORT_CommunicatorMqInit mq_init, | ||
726 | void *mq_init_cls) | ||
727 | { | ||
728 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch; | ||
729 | |||
730 | ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle); | ||
731 | ch->cfg = cfg; | ||
732 | ch->name = name; | ||
733 | ch->mtu = mtu; | ||
734 | ch->mq_init = mq_init; | ||
735 | ch->mq_init_cls = mq_init_cls; | ||
736 | reconnect (ch); | ||
737 | if (GNUNET_OK != | ||
738 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
739 | name, | ||
740 | "MAX_QUEUE_LENGTH", | ||
741 | &ch->max_queue_length)) | ||
742 | ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; | ||
743 | if (NULL == ch->mq) | ||
744 | { | ||
745 | GNUNET_free (ch); | ||
746 | return NULL; | ||
747 | } | ||
748 | return ch; | ||
749 | } | ||
750 | |||
751 | |||
752 | /** | ||
753 | * Disconnect from the transport service. | ||
754 | * | ||
755 | * @param ch handle returned from connect | ||
756 | */ | ||
757 | void | ||
758 | GNUNET_TRANSPORT_communicator_disconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) | ||
759 | { | ||
760 | disconnect (ch); | ||
761 | while (NULL != ch->ai_head) | ||
762 | { | ||
763 | GNUNET_break (0); /* communicator forgot to remove address, warn! */ | ||
764 | GNUNET_TRANSPORT_communicator_address_remove (ch->ai_head); | ||
765 | } | ||
766 | GNUNET_free (ch); | ||
767 | } | ||
768 | |||
769 | |||
770 | /* ************************* Receiving *************************** */ | ||
771 | |||
772 | |||
773 | /** | ||
774 | * Notify transport service that the communicator has received | ||
775 | * a message. | ||
776 | * | ||
777 | * @param ch connection to transport service | ||
778 | * @param sender presumed sender of the message (details to be checked | ||
779 | * by higher layers) | ||
780 | * @param msg the message | ||
781 | * @param cb function to call once handling the message is done, NULL if | ||
782 | * flow control is not supported by this communicator | ||
783 | * @param cb_cls closure for @a cb | ||
784 | * @return #GNUNET_OK if all is well, #GNUNET_NO if the message was | ||
785 | * immediately dropped due to memory limitations (communicator | ||
786 | * should try to apply back pressure), | ||
787 | * #GNUNET_SYSERR if the message could not be delivered because | ||
788 | * the tranport service is not yet up | ||
789 | */ | ||
790 | int | ||
791 | GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, | ||
792 | const struct GNUNET_PeerIdentity *sender, | ||
793 | const struct GNUNET_MessageHeader *msg, | ||
794 | GNUNET_TRANSPORT_MessageCompletedCallback cb, | ||
795 | void *cb_cls) | ||
796 | { | ||
797 | struct GNUNET_MQ_Envelope *env; | ||
798 | struct GNUNET_TRANSPORT_IncomingMessage *im; | ||
799 | uint16_t msize; | ||
800 | |||
801 | if (NULL == ai->ch->mq) | ||
802 | return GNUNET_SYSERR; | ||
803 | if (NULL != cb) | ||
804 | { | ||
805 | struct FlowControl *fc; | ||
806 | |||
807 | im->fc_on = htonl (GNUNET_YES); | ||
808 | im->fc_id = ai->ch->fc_gen++; | ||
809 | fc = GNUNET_new (struct FlowControl); | ||
810 | fc->sender = *sender; | ||
811 | fc->id = im->fc_id; | ||
812 | fc->cb = cb; | ||
813 | fc->cb_cls = cb_cls; | ||
814 | GNUNET_CONTAINER_DLL_insert (ch->fc_head, | ||
815 | ch->fc_tail, | ||
816 | fc); | ||
817 | } | ||
818 | else | ||
819 | { | ||
820 | if (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) | ||
821 | { | ||
822 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
823 | "Dropping message: transprot is too slow, queue length %u exceeded\n", | ||
824 | ch->max_queue_length); | ||
825 | return GNUNET_NO; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | msize = ntohs (msg->size); | ||
830 | env = GNUNET_MQ_msg_extra (im, | ||
831 | msize, | ||
832 | GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG); | ||
833 | if (NULL == env) | ||
834 | { | ||
835 | GNUNET_break (0); | ||
836 | return GNUNET_SYSERR; | ||
837 | } | ||
838 | im->sender = *sender; | ||
839 | memcpy (&im[1], | ||
840 | msg, | ||
841 | msize); | ||
842 | GNUNET_MQ_send (ai->ch->mq, | ||
843 | env); | ||
844 | return GNUNET_OK; | ||
845 | } | ||
846 | |||
847 | |||
848 | /* ************************* Discovery *************************** */ | ||
849 | |||
850 | |||
851 | /** | ||
852 | * Notify transport service that an MQ became available due to an | ||
853 | * "inbound" connection or because the communicator discovered the | ||
854 | * presence of another peer. | ||
855 | * | ||
856 | * @param ch connection to transport service | ||
857 | * @param peer peer with which we can now communicate | ||
858 | * @param address address in human-readable format, 0-terminated, UTF-8 | ||
859 | * @param nt which network type does the @a address belong to? | ||
860 | * @param mq message queue of the @a peer | ||
861 | * @return API handle identifying the new MQ | ||
862 | */ | ||
863 | struct GNUNET_TRANSPORT_QueueHandle * | ||
864 | GNUNET_TRANSPORT_communicator_mq_add (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, | ||
865 | const struct GNUNET_PeerIdentity *peer, | ||
866 | const char *address, | ||
867 | enum GNUNET_ATS_Network_Type nt, | ||
868 | struct GNUNET_MQ_Handle *mq) | ||
869 | { | ||
870 | struct GNUNET_TRANSPORT_QueueHandle *qh; | ||
871 | |||
872 | qh = GNUNET_new (struct GNUNET_TRANSPORT_QueueHandle); | ||
873 | qh->ch = ch; | ||
874 | qh->peer = *peer; | ||
875 | qh->address = GNUNET_strdup (address); | ||
876 | qh->nt = nt; | ||
877 | qh->mq = mq; | ||
878 | qh->queue_id = ch->queue_gen++; | ||
879 | GNUNET_CONTAINER_DLL_insert (ch->queue_head, | ||
880 | ch->queue_tail, | ||
881 | qh); | ||
882 | send_add_queue (qh); | ||
883 | return qh; | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Notify transport service that an MQ became unavailable due to a | ||
889 | * disconnect or timeout. | ||
890 | * | ||
891 | * @param qh handle for the queue that must be invalidated | ||
892 | */ | ||
893 | void | ||
894 | GNUNET_TRANSPORT_communicator_mq_del (struct GNUNET_TRANSPORT_QueueHandle *qh) | ||
895 | { | ||
896 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = qh->ch; | ||
897 | |||
898 | send_del_queue (qh); | ||
899 | GNUNET_CONTAINER_DLL_remove (ch->queue_head, | ||
900 | ch->queue_tail, | ||
901 | qh); | ||
902 | GNUNET_MQ_destroy (qh->mq); | ||
903 | GNUNET_free (qh->address); | ||
904 | GNUNET_free (qh); | ||
905 | } | ||
906 | |||
907 | |||
908 | /** | ||
909 | * Notify transport service about an address that this communicator | ||
910 | * provides for this peer. | ||
911 | * | ||
912 | * @param ch connection to transport service | ||
913 | * @param address our address in human-readable format, 0-terminated, UTF-8 | ||
914 | * @param nt which network type does the address belong to? | ||
915 | * @param expiration when does the communicator forsee this address expiring? | ||
916 | */ | ||
917 | struct GNUNET_TRANSPORT_AddressIdentifier * | ||
918 | GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, | ||
919 | const char *address, | ||
920 | enum GNUNET_ATS_Network_Type nt, | ||
921 | struct GNUNET_TIME_Relative expiration) | ||
922 | { | ||
923 | struct GNUNET_TRANSPORT_AddressIdentifier *ai; | ||
924 | |||
925 | ai = GNUNET_new (struct GNUNET_TRANSPORT_AddressIdentifier); | ||
926 | ai->ch = ch; | ||
927 | ai->address = GNUNET_strdup (address); | ||
928 | ai->nt = nt; | ||
929 | ai->expiration = expiration; | ||
930 | ai->aid = handle->aid_gen++; | ||
931 | GNUNET_CONTAINER_DLL_insert (handle->ai_head, | ||
932 | handle->ai_tail, | ||
933 | ai); | ||
934 | send_add_address (ai); | ||
935 | return ai; | ||
936 | } | ||
937 | |||
938 | |||
939 | /** | ||
940 | * Notify transport service about an address that this communicator no | ||
941 | * longer provides for this peer. | ||
942 | * | ||
943 | * @param ai address that is no longer provided | ||
944 | */ | ||
945 | void | ||
946 | GNUNET_TRANSPORT_communicator_address_remove (struct GNUNET_TRANSPORT_AddressIdentifier *ai) | ||
947 | { | ||
948 | struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ai->ch; | ||
949 | |||
950 | send_del_address (ai); | ||
951 | GNUNET_CONTAINER_DLL_remove (ch->ai_head, | ||
952 | ch->ai_tail, | ||
953 | ai); | ||
954 | GNUNET_free (ai->address); | ||
955 | GNUNET_free (ai); | ||
956 | } | ||
957 | |||
958 | |||
959 | /* end of transport_api2_communication.c */ | ||
diff --git a/src/util/configuration.c b/src/util/configuration.c index e00bbd64a..41eb3188d 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c | |||
@@ -893,22 +893,27 @@ GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
893 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | 893 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error |
894 | */ | 894 | */ |
895 | int | 895 | int |
896 | GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle | 896 | GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg, |
897 | *cfg, const char *section, | 897 | const char *section, |
898 | const char *option, | 898 | const char *option, |
899 | unsigned long long *number) | 899 | unsigned long long *number) |
900 | { | 900 | { |
901 | struct ConfigEntry *e; | 901 | struct ConfigEntry *e; |
902 | char dummy[2]; | ||
902 | 903 | ||
903 | if (NULL == (e = find_entry (cfg, section, option))) | 904 | if (NULL == (e = find_entry (cfg, section, option))) |
904 | return GNUNET_SYSERR; | 905 | return GNUNET_SYSERR; |
905 | if (NULL == e->val) | 906 | if (NULL == e->val) |
906 | return GNUNET_SYSERR; | 907 | return GNUNET_SYSERR; |
907 | if (1 != SSCANF (e->val, "%llu", number)) | 908 | if (1 != SSCANF (e->val, |
909 | "%llu%1s", | ||
910 | number, | ||
911 | dummy)) | ||
908 | return GNUNET_SYSERR; | 912 | return GNUNET_SYSERR; |
909 | return GNUNET_OK; | 913 | return GNUNET_OK; |
910 | } | 914 | } |
911 | 915 | ||
916 | |||
912 | /** | 917 | /** |
913 | * Get a configuration value that should be a floating point number. | 918 | * Get a configuration value that should be a floating point number. |
914 | * | 919 | * |
@@ -919,18 +924,22 @@ GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle | |||
919 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | 924 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error |
920 | */ | 925 | */ |
921 | int | 926 | int |
922 | GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle | 927 | GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle *cfg, |
923 | *cfg, const char *section, | 928 | const char *section, |
924 | const char *option, | 929 | const char *option, |
925 | float *number) | 930 | float *number) |
926 | { | 931 | { |
927 | struct ConfigEntry *e; | 932 | struct ConfigEntry *e; |
928 | 933 | char dummy[2]; | |
934 | |||
929 | if (NULL == (e = find_entry (cfg, section, option))) | 935 | if (NULL == (e = find_entry (cfg, section, option))) |
930 | return GNUNET_SYSERR; | 936 | return GNUNET_SYSERR; |
931 | if (NULL == e->val) | 937 | if (NULL == e->val) |
932 | return GNUNET_SYSERR; | 938 | return GNUNET_SYSERR; |
933 | if (1 != SSCANF (e->val, "%f", number)) | 939 | if (1 != SSCANF (e->val, |
940 | "%f%1s", | ||
941 | number, | ||
942 | dummy)) | ||
934 | return GNUNET_SYSERR; | 943 | return GNUNET_SYSERR; |
935 | return GNUNET_OK; | 944 | return GNUNET_OK; |
936 | } | 945 | } |
diff --git a/src/util/container_multihashmap.c b/src/util/container_multihashmap.c index 1811f861f..e344c2aec 100644 --- a/src/util/container_multihashmap.c +++ b/src/util/container_multihashmap.c | |||
@@ -27,6 +27,15 @@ | |||
27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multihashmap", __VA_ARGS__) | 27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multihashmap", __VA_ARGS__) |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * Maximum recursion depth for callbacks of | ||
31 | * #GNUNET_CONTAINER_multihashmap_get_multiple() themselve s | ||
32 | * again calling #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
33 | * Should be totally excessive, but if violated we die. | ||
34 | */ | ||
35 | #define NEXT_CACHE_SIZE 16 | ||
36 | |||
37 | |||
38 | /** | ||
30 | * An entry in the hash map with the full key. | 39 | * An entry in the hash map with the full key. |
31 | */ | 40 | */ |
32 | struct BigMapEntry | 41 | struct BigMapEntry |
@@ -122,6 +131,19 @@ struct GNUNET_CONTAINER_MultiHashMap | |||
122 | * to the map, so that iterators can check if they are still valid. | 131 | * to the map, so that iterators can check if they are still valid. |
123 | */ | 132 | */ |
124 | unsigned int modification_counter; | 133 | unsigned int modification_counter; |
134 | |||
135 | /** | ||
136 | * Map entries indicating iteration positions currently | ||
137 | * in use by #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
138 | * Only used up to @e next_cache_off. | ||
139 | */ | ||
140 | union MapEntry next_cache[NEXT_CACHE_SIZE]; | ||
141 | |||
142 | /** | ||
143 | * Offset of @e next_cache entries in use, must be smaller | ||
144 | * than #NEXT_CACHE_SIZE. | ||
145 | */ | ||
146 | unsigned int next_cache_off; | ||
125 | }; | 147 | }; |
126 | 148 | ||
127 | 149 | ||
@@ -132,7 +154,7 @@ struct GNUNET_CONTAINER_MultiHashMap | |||
132 | struct GNUNET_CONTAINER_MultiHashMapIterator | 154 | struct GNUNET_CONTAINER_MultiHashMapIterator |
133 | { | 155 | { |
134 | /** | 156 | /** |
135 | * Position in the bucket 'idx' | 157 | * Position in the bucket @e idx |
136 | */ | 158 | */ |
137 | union MapEntry me; | 159 | union MapEntry me; |
138 | 160 | ||
@@ -207,15 +229,15 @@ GNUNET_CONTAINER_multihashmap_create (unsigned int len, | |||
207 | 229 | ||
208 | 230 | ||
209 | /** | 231 | /** |
210 | * Destroy a hash map. Will not free any values | 232 | * Destroy a hash map. Will not free any values stored in the hash |
211 | * stored in the hash map! | 233 | * map! |
212 | * | 234 | * |
213 | * @param map the map | 235 | * @param map the map |
214 | */ | 236 | */ |
215 | void | 237 | void |
216 | GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap | 238 | GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap *map) |
217 | *map) | ||
218 | { | 239 | { |
240 | GNUNET_assert (0 == map->next_cache_off); | ||
219 | for (unsigned int i = 0; i < map->map_length; i++) | 241 | for (unsigned int i = 0; i < map->map_length; i++) |
220 | { | 242 | { |
221 | union MapEntry me; | 243 | union MapEntry me; |
@@ -304,7 +326,9 @@ GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap *m | |||
304 | struct SmallMapEntry *sme; | 326 | struct SmallMapEntry *sme; |
305 | 327 | ||
306 | for (sme = me.sme; NULL != sme; sme = sme->next) | 328 | for (sme = me.sme; NULL != sme; sme = sme->next) |
307 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) | 329 | if (0 == memcmp (key, |
330 | sme->key, | ||
331 | sizeof (struct GNUNET_HashCode))) | ||
308 | return sme->value; | 332 | return sme->value; |
309 | } | 333 | } |
310 | else | 334 | else |
@@ -312,7 +336,9 @@ GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap *m | |||
312 | struct BigMapEntry *bme; | 336 | struct BigMapEntry *bme; |
313 | 337 | ||
314 | for (bme = me.bme; NULL != bme; bme = bme->next) | 338 | for (bme = me.bme; NULL != bme; bme = bme->next) |
315 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) | 339 | if (0 == memcmp (key, |
340 | &bme->key, | ||
341 | sizeof (struct GNUNET_HashCode))) | ||
316 | return bme->value; | 342 | return bme->value; |
317 | } | 343 | } |
318 | return NULL; | 344 | return NULL; |
@@ -329,34 +355,39 @@ GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap *m | |||
329 | * #GNUNET_SYSERR if it aborted iteration | 355 | * #GNUNET_SYSERR if it aborted iteration |
330 | */ | 356 | */ |
331 | int | 357 | int |
332 | GNUNET_CONTAINER_multihashmap_iterate (const struct | 358 | GNUNET_CONTAINER_multihashmap_iterate (struct GNUNET_CONTAINER_MultiHashMap *map, |
333 | GNUNET_CONTAINER_MultiHashMap *map, | ||
334 | GNUNET_CONTAINER_HashMapIterator it, | 359 | GNUNET_CONTAINER_HashMapIterator it, |
335 | void *it_cls) | 360 | void *it_cls) |
336 | { | 361 | { |
337 | int count; | 362 | int count; |
338 | unsigned int i; | ||
339 | union MapEntry me; | 363 | union MapEntry me; |
364 | union MapEntry *ce; | ||
340 | struct GNUNET_HashCode kc; | 365 | struct GNUNET_HashCode kc; |
341 | 366 | ||
342 | count = 0; | ||
343 | GNUNET_assert (NULL != map); | 367 | GNUNET_assert (NULL != map); |
344 | for (i = 0; i < map->map_length; i++) | 368 | ce = &map->next_cache[map->next_cache_off]; |
369 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
370 | count = 0; | ||
371 | for (unsigned i = 0; i < map->map_length; i++) | ||
345 | { | 372 | { |
346 | me = map->map[i]; | 373 | me = map->map[i]; |
347 | if (map->use_small_entries) | 374 | if (map->use_small_entries) |
348 | { | 375 | { |
349 | struct SmallMapEntry *sme; | 376 | struct SmallMapEntry *sme; |
350 | struct SmallMapEntry *nxt; | ||
351 | 377 | ||
352 | nxt = me.sme; | 378 | ce->sme = me.sme; |
353 | while (NULL != (sme = nxt)) | 379 | while (NULL != (sme = ce->sme)) |
354 | { | 380 | { |
355 | nxt = sme->next; | 381 | ce->sme = sme->next; |
356 | if (NULL != it) | 382 | if (NULL != it) |
357 | { | 383 | { |
358 | if (GNUNET_OK != it (it_cls, sme->key, sme->value)) | 384 | if (GNUNET_OK != it (it_cls, |
385 | sme->key, | ||
386 | sme->value)) | ||
387 | { | ||
388 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
359 | return GNUNET_SYSERR; | 389 | return GNUNET_SYSERR; |
390 | } | ||
360 | } | 391 | } |
361 | count++; | 392 | count++; |
362 | } | 393 | } |
@@ -364,27 +395,66 @@ GNUNET_CONTAINER_multihashmap_iterate (const struct | |||
364 | else | 395 | else |
365 | { | 396 | { |
366 | struct BigMapEntry *bme; | 397 | struct BigMapEntry *bme; |
367 | struct BigMapEntry *nxt; | ||
368 | 398 | ||
369 | nxt = me.bme; | 399 | ce->bme = me.bme; |
370 | while (NULL != (bme = nxt)) | 400 | while (NULL != (bme = ce->bme)) |
371 | { | 401 | { |
372 | nxt = bme->next; | 402 | ce->bme = bme->next; |
373 | if (NULL != it) | 403 | if (NULL != it) |
374 | { | 404 | { |
375 | kc = bme->key; | 405 | kc = bme->key; |
376 | if (GNUNET_OK != it (it_cls, &kc, bme->value)) | 406 | if (GNUNET_OK != it (it_cls, |
407 | &kc, | ||
408 | bme->value)) | ||
409 | { | ||
410 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
377 | return GNUNET_SYSERR; | 411 | return GNUNET_SYSERR; |
412 | } | ||
378 | } | 413 | } |
379 | count++; | 414 | count++; |
380 | } | 415 | } |
381 | } | 416 | } |
382 | } | 417 | } |
418 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
383 | return count; | 419 | return count; |
384 | } | 420 | } |
385 | 421 | ||
386 | 422 | ||
387 | /** | 423 | /** |
424 | * We are about to free() the @a bme, make sure it is not in | ||
425 | * the list of next values for any iterator in the @a map's next_cache. | ||
426 | * | ||
427 | * @param map the map to check | ||
428 | * @param bme the entry that is about to be free'd | ||
429 | */ | ||
430 | static void | ||
431 | update_next_cache_bme (struct GNUNET_CONTAINER_MultiHashMap *map, | ||
432 | const struct BigMapEntry *bme) | ||
433 | { | ||
434 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
435 | if (map->next_cache[i].bme == bme) | ||
436 | map->next_cache[i].bme = bme->next; | ||
437 | } | ||
438 | |||
439 | |||
440 | /** | ||
441 | * We are about to free() the @a sme, make sure it is not in | ||
442 | * the list of next values for any iterator in the @a map's next_cache. | ||
443 | * | ||
444 | * @param map the map to check | ||
445 | * @param sme the entry that is about to be free'd | ||
446 | */ | ||
447 | static void | ||
448 | update_next_cache_sme (struct GNUNET_CONTAINER_MultiHashMap *map, | ||
449 | const struct SmallMapEntry *sme) | ||
450 | { | ||
451 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
452 | if (map->next_cache[i].sme == sme) | ||
453 | map->next_cache[i].sme = sme->next; | ||
454 | } | ||
455 | |||
456 | |||
457 | /** | ||
388 | * Remove the given key-value pair from the map. Note that if the | 458 | * Remove the given key-value pair from the map. Note that if the |
389 | * key-value pair is in the map multiple times, only one of the pairs | 459 | * key-value pair is in the map multiple times, only one of the pairs |
390 | * will be removed. | 460 | * will be removed. |
@@ -409,19 +479,22 @@ GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map, | |||
409 | me = map->map[i]; | 479 | me = map->map[i]; |
410 | if (map->use_small_entries) | 480 | if (map->use_small_entries) |
411 | { | 481 | { |
412 | struct SmallMapEntry *sme; | ||
413 | struct SmallMapEntry *p; | 482 | struct SmallMapEntry *p; |
414 | 483 | ||
415 | p = NULL; | 484 | p = NULL; |
416 | for (sme = me.sme; NULL != sme; sme = sme->next) | 485 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
417 | { | 486 | { |
418 | if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) && | 487 | if ( (0 == memcmp (key, |
419 | (value == sme->value)) | 488 | sme->key, |
489 | sizeof (struct GNUNET_HashCode))) && | ||
490 | (value == sme->value) ) | ||
420 | { | 491 | { |
421 | if (NULL == p) | 492 | if (NULL == p) |
422 | map->map[i].sme = sme->next; | 493 | map->map[i].sme = sme->next; |
423 | else | 494 | else |
424 | p->next = sme->next; | 495 | p->next = sme->next; |
496 | update_next_cache_sme (map, | ||
497 | sme); | ||
425 | GNUNET_free (sme); | 498 | GNUNET_free (sme); |
426 | map->size--; | 499 | map->size--; |
427 | return GNUNET_YES; | 500 | return GNUNET_YES; |
@@ -431,19 +504,22 @@ GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map, | |||
431 | } | 504 | } |
432 | else | 505 | else |
433 | { | 506 | { |
434 | struct BigMapEntry *bme; | ||
435 | struct BigMapEntry *p; | 507 | struct BigMapEntry *p; |
436 | 508 | ||
437 | p = NULL; | 509 | p = NULL; |
438 | for (bme = me.bme; NULL != bme; bme = bme->next) | 510 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
439 | { | 511 | { |
440 | if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) && | 512 | if ( (0 == memcmp (key, |
441 | (value == bme->value)) | 513 | &bme->key, |
514 | sizeof (struct GNUNET_HashCode))) && | ||
515 | (value == bme->value) ) | ||
442 | { | 516 | { |
443 | if (NULL == p) | 517 | if (NULL == p) |
444 | map->map[i].bme = bme->next; | 518 | map->map[i].bme = bme->next; |
445 | else | 519 | else |
446 | p->next = bme->next; | 520 | p->next = bme->next; |
521 | update_next_cache_bme (map, | ||
522 | bme); | ||
447 | GNUNET_free (bme); | 523 | GNUNET_free (bme); |
448 | map->size--; | 524 | map->size--; |
449 | return GNUNET_YES; | 525 | return GNUNET_YES; |
@@ -485,12 +561,16 @@ GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap * | |||
485 | sme = me.sme; | 561 | sme = me.sme; |
486 | while (NULL != sme) | 562 | while (NULL != sme) |
487 | { | 563 | { |
488 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) | 564 | if (0 == memcmp (key, |
565 | sme->key, | ||
566 | sizeof (struct GNUNET_HashCode))) | ||
489 | { | 567 | { |
490 | if (NULL == p) | 568 | if (NULL == p) |
491 | map->map[i].sme = sme->next; | 569 | map->map[i].sme = sme->next; |
492 | else | 570 | else |
493 | p->next = sme->next; | 571 | p->next = sme->next; |
572 | update_next_cache_sme (map, | ||
573 | sme); | ||
494 | GNUNET_free (sme); | 574 | GNUNET_free (sme); |
495 | map->size--; | 575 | map->size--; |
496 | if (NULL == p) | 576 | if (NULL == p) |
@@ -515,12 +595,16 @@ GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap * | |||
515 | bme = me.bme; | 595 | bme = me.bme; |
516 | while (NULL != bme) | 596 | while (NULL != bme) |
517 | { | 597 | { |
518 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) | 598 | if (0 == memcmp (key, |
599 | &bme->key, | ||
600 | sizeof (struct GNUNET_HashCode))) | ||
519 | { | 601 | { |
520 | if (NULL == p) | 602 | if (NULL == p) |
521 | map->map[i].bme = bme->next; | 603 | map->map[i].bme = bme->next; |
522 | else | 604 | else |
523 | p->next = bme->next; | 605 | p->next = bme->next; |
606 | update_next_cache_bme (map, | ||
607 | bme); | ||
524 | GNUNET_free (bme); | 608 | GNUNET_free (bme); |
525 | map->size--; | 609 | map->size--; |
526 | if (NULL == p) | 610 | if (NULL == p) |
@@ -631,9 +715,8 @@ GNUNET_CONTAINER_multihashmap_contains (const struct | |||
631 | * #GNUNET_NO if not | 715 | * #GNUNET_NO if not |
632 | */ | 716 | */ |
633 | int | 717 | int |
634 | GNUNET_CONTAINER_multihashmap_contains_value (const struct | 718 | GNUNET_CONTAINER_multihashmap_contains_value (const struct GNUNET_CONTAINER_MultiHashMap *map, |
635 | GNUNET_CONTAINER_MultiHashMap | 719 | const struct GNUNET_HashCode *key, |
636 | *map, const struct GNUNET_HashCode *key, | ||
637 | const void *value) | 720 | const void *value) |
638 | { | 721 | { |
639 | union MapEntry me; | 722 | union MapEntry me; |
@@ -644,7 +727,9 @@ GNUNET_CONTAINER_multihashmap_contains_value (const struct | |||
644 | struct SmallMapEntry *sme; | 727 | struct SmallMapEntry *sme; |
645 | 728 | ||
646 | for (sme = me.sme; NULL != sme; sme = sme->next) | 729 | for (sme = me.sme; NULL != sme; sme = sme->next) |
647 | if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) && | 730 | if ( (0 == memcmp (key, |
731 | sme->key, | ||
732 | sizeof (struct GNUNET_HashCode))) && | ||
648 | (sme->value == value) ) | 733 | (sme->value == value) ) |
649 | return GNUNET_YES; | 734 | return GNUNET_YES; |
650 | } | 735 | } |
@@ -653,7 +738,9 @@ GNUNET_CONTAINER_multihashmap_contains_value (const struct | |||
653 | struct BigMapEntry *bme; | 738 | struct BigMapEntry *bme; |
654 | 739 | ||
655 | for (bme = me.bme; NULL != bme; bme = bme->next) | 740 | for (bme = me.bme; NULL != bme; bme = bme->next) |
656 | if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) && | 741 | if ( (0 == memcmp (key, |
742 | &bme->key, | ||
743 | sizeof (struct GNUNET_HashCode))) && | ||
657 | (bme->value == value) ) | 744 | (bme->value == value) ) |
658 | return GNUNET_YES; | 745 | return GNUNET_YES; |
659 | } | 746 | } |
@@ -814,49 +901,66 @@ GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map, | |||
814 | * #GNUNET_SYSERR if it aborted iteration | 901 | * #GNUNET_SYSERR if it aborted iteration |
815 | */ | 902 | */ |
816 | int | 903 | int |
817 | GNUNET_CONTAINER_multihashmap_get_multiple (const struct | 904 | GNUNET_CONTAINER_multihashmap_get_multiple (struct GNUNET_CONTAINER_MultiHashMap *map, |
818 | GNUNET_CONTAINER_MultiHashMap *map, | ||
819 | const struct GNUNET_HashCode *key, | 905 | const struct GNUNET_HashCode *key, |
820 | GNUNET_CONTAINER_HashMapIterator it, | 906 | GNUNET_CONTAINER_HashMapIterator it, |
821 | void *it_cls) | 907 | void *it_cls) |
822 | { | 908 | { |
823 | int count; | 909 | int count; |
824 | union MapEntry me; | 910 | union MapEntry *me; |
911 | union MapEntry *ce; | ||
825 | 912 | ||
913 | ce = &map->next_cache[map->next_cache_off]; | ||
914 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
826 | count = 0; | 915 | count = 0; |
827 | me = map->map[idx_of (map, key)]; | 916 | me = &map->map[idx_of (map, key)]; |
828 | if (map->use_small_entries) | 917 | if (map->use_small_entries) |
829 | { | 918 | { |
830 | struct SmallMapEntry *sme; | 919 | struct SmallMapEntry *sme; |
831 | struct SmallMapEntry *nxt; | ||
832 | 920 | ||
833 | nxt = me.sme; | 921 | ce->sme = me->sme; |
834 | while (NULL != (sme = nxt)) | 922 | while (NULL != (sme = ce->sme)) |
835 | { | 923 | { |
836 | nxt = sme->next; | 924 | ce->sme = sme->next; |
837 | if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) | 925 | if (0 != memcmp (key, |
926 | sme->key, | ||
927 | sizeof (struct GNUNET_HashCode))) | ||
838 | continue; | 928 | continue; |
839 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) | 929 | if ( (NULL != it) && |
930 | (GNUNET_OK != it (it_cls, | ||
931 | key, | ||
932 | sme->value))) | ||
933 | { | ||
934 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
840 | return GNUNET_SYSERR; | 935 | return GNUNET_SYSERR; |
936 | } | ||
841 | count++; | 937 | count++; |
842 | } | 938 | } |
843 | } | 939 | } |
844 | else | 940 | else |
845 | { | 941 | { |
846 | struct BigMapEntry *bme; | 942 | struct BigMapEntry *bme; |
847 | struct BigMapEntry *nxt; | ||
848 | 943 | ||
849 | nxt = me.bme; | 944 | ce->bme = me->bme; |
850 | while (NULL != (bme = nxt)) | 945 | while (NULL != (bme = ce->bme)) |
851 | { | 946 | { |
852 | nxt = bme->next; | 947 | ce->bme = bme->next; |
853 | if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) | 948 | if (0 != memcmp (key, |
949 | &bme->key, | ||
950 | sizeof (struct GNUNET_HashCode))) | ||
854 | continue; | 951 | continue; |
855 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) | 952 | if ( (NULL != it) && |
953 | (GNUNET_OK != it (it_cls, | ||
954 | key, | ||
955 | bme->value))) | ||
956 | { | ||
957 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
856 | return GNUNET_SYSERR; | 958 | return GNUNET_SYSERR; |
959 | } | ||
857 | count++; | 960 | count++; |
858 | } | 961 | } |
859 | } | 962 | } |
963 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
860 | return count; | 964 | return count; |
861 | } | 965 | } |
862 | 966 | ||
diff --git a/src/util/container_multihashmap32.c b/src/util/container_multihashmap32.c index daf5059b6..72940489e 100644 --- a/src/util/container_multihashmap32.c +++ b/src/util/container_multihashmap32.c | |||
@@ -28,6 +28,15 @@ | |||
28 | 28 | ||
29 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multihashmap32", __VA_ARGS__) | 29 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multihashmap32", __VA_ARGS__) |
30 | 30 | ||
31 | |||
32 | /** | ||
33 | * Maximum recursion depth for callbacks of | ||
34 | * #GNUNET_CONTAINER_multihashmap_get_multiple() themselves | ||
35 | * again calling #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
36 | * Should be totally excessive, but if violated we die. | ||
37 | */ | ||
38 | #define NEXT_CACHE_SIZE 16 | ||
39 | |||
31 | /** | 40 | /** |
32 | * An entry in the hash map. | 41 | * An entry in the hash map. |
33 | */ | 42 | */ |
@@ -68,7 +77,7 @@ struct GNUNET_CONTAINER_MultiHashMap32 | |||
68 | unsigned int size; | 77 | unsigned int size; |
69 | 78 | ||
70 | /** | 79 | /** |
71 | * Length of the "map" array. | 80 | * Length of the @e map array. |
72 | */ | 81 | */ |
73 | unsigned int map_length; | 82 | unsigned int map_length; |
74 | 83 | ||
@@ -77,6 +86,19 @@ struct GNUNET_CONTAINER_MultiHashMap32 | |||
77 | * to the map, so that iterators can check if they are still valid. | 86 | * to the map, so that iterators can check if they are still valid. |
78 | */ | 87 | */ |
79 | unsigned int modification_counter; | 88 | unsigned int modification_counter; |
89 | |||
90 | /** | ||
91 | * Map entries indicating iteration positions currently | ||
92 | * in use by #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
93 | * Only used up to @e next_cache_off. | ||
94 | */ | ||
95 | struct MapEntry *next_cache[NEXT_CACHE_SIZE]; | ||
96 | |||
97 | /** | ||
98 | * Offset of @e next_cache entries in use, must be smaller | ||
99 | * than #NEXT_CACHE_SIZE. | ||
100 | */ | ||
101 | unsigned int next_cache_off; | ||
80 | }; | 102 | }; |
81 | 103 | ||
82 | 104 | ||
@@ -87,7 +109,7 @@ struct GNUNET_CONTAINER_MultiHashMap32 | |||
87 | struct GNUNET_CONTAINER_MultiHashMap32Iterator | 109 | struct GNUNET_CONTAINER_MultiHashMap32Iterator |
88 | { | 110 | { |
89 | /** | 111 | /** |
90 | * Position in the bucket 'idx' | 112 | * Position in the bucket @e idx |
91 | */ | 113 | */ |
92 | struct MapEntry *me; | 114 | struct MapEntry *me; |
93 | 115 | ||
@@ -122,7 +144,8 @@ GNUNET_CONTAINER_multihashmap32_create (unsigned int len) | |||
122 | 144 | ||
123 | GNUNET_assert (len > 0); | 145 | GNUNET_assert (len > 0); |
124 | ret = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap32); | 146 | ret = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap32); |
125 | ret->map = GNUNET_malloc (len * sizeof (struct MapEntry *)); | 147 | ret->map = GNUNET_new_array (len, |
148 | struct MapEntry *); | ||
126 | ret->map_length = len; | 149 | ret->map_length = len; |
127 | return ret; | 150 | return ret; |
128 | } | 151 | } |
@@ -135,13 +158,11 @@ GNUNET_CONTAINER_multihashmap32_create (unsigned int len) | |||
135 | * @param map the map | 158 | * @param map the map |
136 | */ | 159 | */ |
137 | void | 160 | void |
138 | GNUNET_CONTAINER_multihashmap32_destroy (struct GNUNET_CONTAINER_MultiHashMap32 | 161 | GNUNET_CONTAINER_multihashmap32_destroy (struct GNUNET_CONTAINER_MultiHashMap32 *map) |
139 | *map) | ||
140 | { | 162 | { |
141 | unsigned int i; | ||
142 | struct MapEntry *e; | 163 | struct MapEntry *e; |
143 | 164 | ||
144 | for (i = 0; i < map->map_length; i++) | 165 | for (unsigned int i = 0; i < map->map_length; i++) |
145 | { | 166 | { |
146 | while (NULL != (e = map->map[i])) | 167 | while (NULL != (e = map->map[i])) |
147 | { | 168 | { |
@@ -165,7 +186,7 @@ static unsigned int | |||
165 | idx_of (const struct GNUNET_CONTAINER_MultiHashMap32 *m, | 186 | idx_of (const struct GNUNET_CONTAINER_MultiHashMap32 *m, |
166 | const uint32_t key) | 187 | const uint32_t key) |
167 | { | 188 | { |
168 | GNUNET_assert (m != NULL); | 189 | GNUNET_assert (NULL != m); |
169 | return ((unsigned int) key) % m->map_length; | 190 | return ((unsigned int) key) % m->map_length; |
170 | } | 191 | } |
171 | 192 | ||
@@ -177,8 +198,7 @@ idx_of (const struct GNUNET_CONTAINER_MultiHashMap32 *m, | |||
177 | * @return the number of key value pairs | 198 | * @return the number of key value pairs |
178 | */ | 199 | */ |
179 | unsigned int | 200 | unsigned int |
180 | GNUNET_CONTAINER_multihashmap32_size (const struct | 201 | GNUNET_CONTAINER_multihashmap32_size (const struct GNUNET_CONTAINER_MultiHashMap32 *map) |
181 | GNUNET_CONTAINER_MultiHashMap32 *map) | ||
182 | { | 202 | { |
183 | return map->size; | 203 | return map->size; |
184 | } | 204 | } |
@@ -195,14 +215,13 @@ GNUNET_CONTAINER_multihashmap32_size (const struct | |||
195 | * key-value pairs with value NULL | 215 | * key-value pairs with value NULL |
196 | */ | 216 | */ |
197 | void * | 217 | void * |
198 | GNUNET_CONTAINER_multihashmap32_get (const struct | 218 | GNUNET_CONTAINER_multihashmap32_get (const struct GNUNET_CONTAINER_MultiHashMap32 *map, |
199 | GNUNET_CONTAINER_MultiHashMap32 *map, | ||
200 | uint32_t key) | 219 | uint32_t key) |
201 | { | 220 | { |
202 | struct MapEntry *e; | 221 | struct MapEntry *e; |
203 | 222 | ||
204 | e = map->map[idx_of (map, key)]; | 223 | e = map->map[idx_of (map, key)]; |
205 | while (e != NULL) | 224 | while (NULL != e) |
206 | { | 225 | { |
207 | if (key == e->key) | 226 | if (key == e->key) |
208 | return e->value; | 227 | return e->value; |
@@ -222,37 +241,61 @@ GNUNET_CONTAINER_multihashmap32_get (const struct | |||
222 | * #GNUNET_SYSERR if it aborted iteration | 241 | * #GNUNET_SYSERR if it aborted iteration |
223 | */ | 242 | */ |
224 | int | 243 | int |
225 | GNUNET_CONTAINER_multihashmap32_iterate (const struct | 244 | GNUNET_CONTAINER_multihashmap32_iterate (struct GNUNET_CONTAINER_MultiHashMap32 *map, |
226 | GNUNET_CONTAINER_MultiHashMap32 *map, | 245 | GNUNET_CONTAINER_HashMapIterator32 it, |
227 | GNUNET_CONTAINER_HashMapIterator32 it, | ||
228 | void *it_cls) | 246 | void *it_cls) |
229 | { | 247 | { |
230 | int count; | 248 | int count; |
231 | unsigned int i; | 249 | struct MapEntry **ce; |
232 | struct MapEntry *e; | ||
233 | struct MapEntry *n; | ||
234 | 250 | ||
235 | count = 0; | 251 | count = 0; |
236 | GNUNET_assert (NULL != map); | 252 | GNUNET_assert (NULL != map); |
237 | for (i = 0; i < map->map_length; i++) | 253 | ce = &map->next_cache[map->next_cache_off]; |
254 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
255 | for (unsigned int i = 0; i < map->map_length; i++) | ||
238 | { | 256 | { |
239 | n = map->map[i]; | 257 | struct MapEntry *e; |
240 | while (NULL != (e = n)) | 258 | |
259 | *ce = map->map[i]; | ||
260 | while (NULL != (e = *ce)) | ||
241 | { | 261 | { |
242 | n = e->next; | 262 | *ce = e->next; |
243 | if (NULL != it) | 263 | if (NULL != it) |
244 | { | 264 | { |
245 | if (GNUNET_OK != it (it_cls, e->key, e->value)) | 265 | if (GNUNET_OK != it (it_cls, |
266 | e->key, | ||
267 | e->value)) | ||
268 | { | ||
269 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
246 | return GNUNET_SYSERR; | 270 | return GNUNET_SYSERR; |
271 | } | ||
247 | } | 272 | } |
248 | count++; | 273 | count++; |
249 | } | 274 | } |
250 | } | 275 | } |
276 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
251 | return count; | 277 | return count; |
252 | } | 278 | } |
253 | 279 | ||
254 | 280 | ||
255 | /** | 281 | /** |
282 | * We are about to free() the @a bme, make sure it is not in | ||
283 | * the list of next values for any iterator in the @a map's next_cache. | ||
284 | * | ||
285 | * @param map the map to check | ||
286 | * @param bme the entry that is about to be free'd | ||
287 | */ | ||
288 | static void | ||
289 | update_next_cache (struct GNUNET_CONTAINER_MultiHashMap32 *map, | ||
290 | const struct MapEntry *me) | ||
291 | { | ||
292 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
293 | if (map->next_cache[i] == me) | ||
294 | map->next_cache[i] = me->next; | ||
295 | } | ||
296 | |||
297 | |||
298 | /** | ||
256 | * Remove the given key-value pair from the map. Note that if the | 299 | * Remove the given key-value pair from the map. Note that if the |
257 | * key-value pair is in the map multiple times, only one of the pairs | 300 | * key-value pair is in the map multiple times, only one of the pairs |
258 | * will be removed. | 301 | * will be removed. |
@@ -260,13 +303,13 @@ GNUNET_CONTAINER_multihashmap32_iterate (const struct | |||
260 | * @param map the map | 303 | * @param map the map |
261 | * @param key key of the key-value pair | 304 | * @param key key of the key-value pair |
262 | * @param value value of the key-value pair | 305 | * @param value value of the key-value pair |
263 | * @return GNUNET_YES on success, GNUNET_NO if the key-value pair | 306 | * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair |
264 | * is not in the map | 307 | * is not in the map |
265 | */ | 308 | */ |
266 | int | 309 | int |
267 | GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 | 310 | GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 *map, |
268 | *map, | 311 | uint32_t key, |
269 | uint32_t key, const void *value) | 312 | const void *value) |
270 | { | 313 | { |
271 | struct MapEntry *e; | 314 | struct MapEntry *e; |
272 | struct MapEntry *p; | 315 | struct MapEntry *p; |
@@ -285,6 +328,8 @@ GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 | |||
285 | map->map[i] = e->next; | 328 | map->map[i] = e->next; |
286 | else | 329 | else |
287 | p->next = e->next; | 330 | p->next = e->next; |
331 | update_next_cache (map, | ||
332 | e); | ||
288 | GNUNET_free (e); | 333 | GNUNET_free (e); |
289 | map->size--; | 334 | map->size--; |
290 | return GNUNET_YES; | 335 | return GNUNET_YES; |
@@ -305,9 +350,7 @@ GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 | |||
305 | * @return number of values removed | 350 | * @return number of values removed |
306 | */ | 351 | */ |
307 | int | 352 | int |
308 | GNUNET_CONTAINER_multihashmap32_remove_all (struct | 353 | GNUNET_CONTAINER_multihashmap32_remove_all (struct GNUNET_CONTAINER_MultiHashMap32 *map, |
309 | GNUNET_CONTAINER_MultiHashMap32 | ||
310 | *map, | ||
311 | uint32_t key) | 354 | uint32_t key) |
312 | { | 355 | { |
313 | struct MapEntry *e; | 356 | struct MapEntry *e; |
@@ -329,6 +372,8 @@ GNUNET_CONTAINER_multihashmap32_remove_all (struct | |||
329 | map->map[i] = e->next; | 372 | map->map[i] = e->next; |
330 | else | 373 | else |
331 | p->next = e->next; | 374 | p->next = e->next; |
375 | update_next_cache (map, | ||
376 | e); | ||
332 | GNUNET_free (e); | 377 | GNUNET_free (e); |
333 | map->size--; | 378 | map->size--; |
334 | if (p == NULL) | 379 | if (p == NULL) |
@@ -353,12 +398,11 @@ GNUNET_CONTAINER_multihashmap32_remove_all (struct | |||
353 | * | 398 | * |
354 | * @param map the map | 399 | * @param map the map |
355 | * @param key the key to test if a value exists for it | 400 | * @param key the key to test if a value exists for it |
356 | * @return GNUNET_YES if such a value exists, | 401 | * @return #GNUNET_YES if such a value exists, |
357 | * GNUNET_NO if not | 402 | * #GNUNET_NO if not |
358 | */ | 403 | */ |
359 | int | 404 | int |
360 | GNUNET_CONTAINER_multihashmap32_contains (const struct | 405 | GNUNET_CONTAINER_multihashmap32_contains (const struct GNUNET_CONTAINER_MultiHashMap32 *map, |
361 | GNUNET_CONTAINER_MultiHashMap32 *map, | ||
362 | uint32_t key) | 406 | uint32_t key) |
363 | { | 407 | { |
364 | struct MapEntry *e; | 408 | struct MapEntry *e; |
@@ -381,13 +425,11 @@ GNUNET_CONTAINER_multihashmap32_contains (const struct | |||
381 | * @param map the map | 425 | * @param map the map |
382 | * @param key the key to test if a value exists for it | 426 | * @param key the key to test if a value exists for it |
383 | * @param value value to test for | 427 | * @param value value to test for |
384 | * @return GNUNET_YES if such a value exists, | 428 | * @return #GNUNET_YES if such a value exists, |
385 | * GNUNET_NO if not | 429 | * #GNUNET_NO if not |
386 | */ | 430 | */ |
387 | int | 431 | int |
388 | GNUNET_CONTAINER_multihashmap32_contains_value (const struct | 432 | GNUNET_CONTAINER_multihashmap32_contains_value (const struct GNUNET_CONTAINER_MultiHashMap32 *map, |
389 | GNUNET_CONTAINER_MultiHashMap32 | ||
390 | *map, | ||
391 | uint32_t key, | 433 | uint32_t key, |
392 | const void *value) | 434 | const void *value) |
393 | { | 435 | { |
@@ -418,17 +460,17 @@ grow (struct GNUNET_CONTAINER_MultiHashMap32 *map) | |||
418 | unsigned int old_len; | 460 | unsigned int old_len; |
419 | unsigned int new_len; | 461 | unsigned int new_len; |
420 | unsigned int idx; | 462 | unsigned int idx; |
421 | unsigned int i; | ||
422 | 463 | ||
423 | map->modification_counter++; | 464 | map->modification_counter++; |
424 | 465 | ||
425 | old_map = map->map; | 466 | old_map = map->map; |
426 | old_len = map->map_length; | 467 | old_len = map->map_length; |
427 | new_len = old_len * 2; | 468 | new_len = old_len * 2; |
428 | new_map = GNUNET_malloc (sizeof (struct MapEntry *) * new_len); | 469 | new_map = GNUNET_new_array (new_len, |
470 | struct MapEntry *); | ||
429 | map->map_length = new_len; | 471 | map->map_length = new_len; |
430 | map->map = new_map; | 472 | map->map = new_map; |
431 | for (i = 0; i < old_len; i++) | 473 | for (unsigned int i = 0; i < old_len; i++) |
432 | { | 474 | { |
433 | while (NULL != (e = old_map[i])) | 475 | while (NULL != (e = old_map[i])) |
434 | { | 476 | { |
@@ -449,9 +491,9 @@ grow (struct GNUNET_CONTAINER_MultiHashMap32 *map) | |||
449 | * @param key key to use | 491 | * @param key key to use |
450 | * @param value value to use | 492 | * @param value value to use |
451 | * @param opt options for put | 493 | * @param opt options for put |
452 | * @return GNUNET_OK on success, | 494 | * @return #GNUNET_OK on success, |
453 | * GNUNET_NO if a value was replaced (with REPLACE) | 495 | * #GNUNET_NO if a value was replaced (with REPLACE) |
454 | * GNUNET_SYSERR if UNIQUE_ONLY was the option and the | 496 | * #GNUNET_SYSERR if UNIQUE_ONLY was the option and the |
455 | * value already exists | 497 | * value already exists |
456 | */ | 498 | */ |
457 | int | 499 | int |
@@ -501,32 +543,41 @@ GNUNET_CONTAINER_multihashmap32_put (struct GNUNET_CONTAINER_MultiHashMap32 | |||
501 | * @param map the map | 543 | * @param map the map |
502 | * @param key key that the entries must correspond to | 544 | * @param key key that the entries must correspond to |
503 | * @param it function to call on each entry | 545 | * @param it function to call on each entry |
504 | * @param it_cls extra argument to it | 546 | * @param it_cls extra argument to @a it |
505 | * @return the number of key value pairs processed, | 547 | * @return the number of key value pairs processed, |
506 | * GNUNET_SYSERR if it aborted iteration | 548 | * GNUNET_SYSERR if it aborted iteration |
507 | */ | 549 | */ |
508 | int | 550 | int |
509 | GNUNET_CONTAINER_multihashmap32_get_multiple (const struct | 551 | GNUNET_CONTAINER_multihashmap32_get_multiple (struct GNUNET_CONTAINER_MultiHashMap32 *map, |
510 | GNUNET_CONTAINER_MultiHashMap32 | 552 | uint32_t key, |
511 | *map, uint32_t key, | 553 | GNUNET_CONTAINER_HashMapIterator32 it, |
512 | GNUNET_CONTAINER_HashMapIterator32 | 554 | void *it_cls) |
513 | it, void *it_cls) | ||
514 | { | 555 | { |
515 | int count; | 556 | int count; |
516 | struct MapEntry *e; | 557 | struct MapEntry *e; |
517 | struct MapEntry *n; | 558 | struct MapEntry **ce; |
518 | 559 | ||
519 | count = 0; | 560 | count = 0; |
520 | n = map->map[idx_of (map, key)]; | 561 | ce = &map->next_cache[map->next_cache_off]; |
521 | while (NULL != (e = n)) | 562 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); |
563 | |||
564 | *ce = map->map[idx_of (map, key)]; | ||
565 | while (NULL != (e = *ce)) | ||
522 | { | 566 | { |
523 | n = e->next; | 567 | *ce = e->next; |
524 | if (key != e->key) | 568 | if (key != e->key) |
525 | continue; | 569 | continue; |
526 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, e->value))) | 570 | if ( (NULL != it) && |
527 | return GNUNET_SYSERR; | 571 | (GNUNET_OK != it (it_cls, |
572 | key, | ||
573 | e->value)) ) | ||
574 | { | ||
575 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
576 | return GNUNET_SYSERR; | ||
577 | } | ||
528 | count++; | 578 | count++; |
529 | } | 579 | } |
580 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
530 | return count; | 581 | return count; |
531 | } | 582 | } |
532 | 583 | ||
@@ -541,7 +592,7 @@ GNUNET_CONTAINER_multihashmap32_get_multiple (const struct | |||
541 | * result in skipped or repeated elements. | 592 | * result in skipped or repeated elements. |
542 | * | 593 | * |
543 | * @param map the map to create an iterator for | 594 | * @param map the map to create an iterator for |
544 | * @return an iterator over the given multihashmap 'map' | 595 | * @return an iterator over the given multihashmap @a map |
545 | */ | 596 | */ |
546 | struct GNUNET_CONTAINER_MultiHashMap32Iterator * | 597 | struct GNUNET_CONTAINER_MultiHashMap32Iterator * |
547 | GNUNET_CONTAINER_multihashmap32_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap32 *map) | 598 | GNUNET_CONTAINER_multihashmap32_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap32 *map) |
diff --git a/src/util/container_multipeermap.c b/src/util/container_multipeermap.c index ede2fd8b7..67d6e1684 100644 --- a/src/util/container_multipeermap.c +++ b/src/util/container_multipeermap.c | |||
@@ -27,6 +27,14 @@ | |||
27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multipeermap", __VA_ARGS__) | 27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multipeermap", __VA_ARGS__) |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * Maximum recursion depth for callbacks of | ||
31 | * #GNUNET_CONTAINER_multihashmap_get_multiple() themselve s | ||
32 | * again calling #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
33 | * Should be totally excessive, but if violated we die. | ||
34 | */ | ||
35 | #define NEXT_CACHE_SIZE 16 | ||
36 | |||
37 | /** | ||
30 | * An entry in the hash map with the full key. | 38 | * An entry in the hash map with the full key. |
31 | */ | 39 | */ |
32 | struct BigMapEntry | 40 | struct BigMapEntry |
@@ -112,8 +120,8 @@ struct GNUNET_CONTAINER_MultiPeerMap | |||
112 | unsigned int map_length; | 120 | unsigned int map_length; |
113 | 121 | ||
114 | /** | 122 | /** |
115 | * GNUNET_NO if the map entries are of type 'struct BigMapEntry', | 123 | * #GNUNET_NO if the map entries are of type 'struct BigMapEntry', |
116 | * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. | 124 | * #GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. |
117 | */ | 125 | */ |
118 | int use_small_entries; | 126 | int use_small_entries; |
119 | 127 | ||
@@ -122,6 +130,19 @@ struct GNUNET_CONTAINER_MultiPeerMap | |||
122 | * to the map, so that iterators can check if they are still valid. | 130 | * to the map, so that iterators can check if they are still valid. |
123 | */ | 131 | */ |
124 | unsigned int modification_counter; | 132 | unsigned int modification_counter; |
133 | |||
134 | /** | ||
135 | * Map entries indicating iteration positions currently | ||
136 | * in use by #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
137 | * Only used up to @e next_cache_off. | ||
138 | */ | ||
139 | union MapEntry next_cache[NEXT_CACHE_SIZE]; | ||
140 | |||
141 | /** | ||
142 | * Offset of @e next_cache entries in use, must be smaller | ||
143 | * than #NEXT_CACHE_SIZE. | ||
144 | */ | ||
145 | unsigned int next_cache_off; | ||
125 | }; | 146 | }; |
126 | 147 | ||
127 | 148 | ||
@@ -177,7 +198,8 @@ GNUNET_CONTAINER_multipeermap_create (unsigned int len, | |||
177 | 198 | ||
178 | GNUNET_assert (len > 0); | 199 | GNUNET_assert (len > 0); |
179 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiPeerMap); | 200 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiPeerMap); |
180 | map->map = GNUNET_malloc (len * sizeof (union MapEntry)); | 201 | map->map = GNUNET_new_array (len, |
202 | union MapEntry); | ||
181 | map->map_length = len; | 203 | map->map_length = len; |
182 | map->use_small_entries = do_not_copy_keys; | 204 | map->use_small_entries = do_not_copy_keys; |
183 | return map; | 205 | return map; |
@@ -191,14 +213,13 @@ GNUNET_CONTAINER_multipeermap_create (unsigned int len, | |||
191 | * @param map the map | 213 | * @param map the map |
192 | */ | 214 | */ |
193 | void | 215 | void |
194 | GNUNET_CONTAINER_multipeermap_destroy (struct GNUNET_CONTAINER_MultiPeerMap | 216 | GNUNET_CONTAINER_multipeermap_destroy (struct GNUNET_CONTAINER_MultiPeerMap *map) |
195 | *map) | ||
196 | { | 217 | { |
197 | unsigned int i; | 218 | GNUNET_assert (0 == map->next_cache_off); |
198 | union MapEntry me; | 219 | for (unsigned int i = 0; i < map->map_length; i++) |
199 | |||
200 | for (i = 0; i < map->map_length; i++) | ||
201 | { | 220 | { |
221 | union MapEntry me; | ||
222 | |||
202 | me = map->map[i]; | 223 | me = map->map[i]; |
203 | if (map->use_small_entries) | 224 | if (map->use_small_entries) |
204 | { | 225 | { |
@@ -246,7 +267,9 @@ idx_of (const struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
246 | unsigned int kx; | 267 | unsigned int kx; |
247 | 268 | ||
248 | GNUNET_assert (NULL != map); | 269 | GNUNET_assert (NULL != map); |
249 | GNUNET_memcpy (&kx, key, sizeof (kx)); | 270 | GNUNET_memcpy (&kx, |
271 | key, | ||
272 | sizeof (kx)); | ||
250 | return kx % map->map_length; | 273 | return kx % map->map_length; |
251 | } | 274 | } |
252 | 275 | ||
@@ -258,8 +281,7 @@ idx_of (const struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
258 | * @return the number of key value pairs | 281 | * @return the number of key value pairs |
259 | */ | 282 | */ |
260 | unsigned int | 283 | unsigned int |
261 | GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap | 284 | GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap *map) |
262 | *map) | ||
263 | { | 285 | { |
264 | return map->size; | 286 | return map->size; |
265 | } | 287 | } |
@@ -276,26 +298,26 @@ GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap | |||
276 | * key-value pairs with value NULL | 298 | * key-value pairs with value NULL |
277 | */ | 299 | */ |
278 | void * | 300 | void * |
279 | GNUNET_CONTAINER_multipeermap_get (const struct GNUNET_CONTAINER_MultiPeerMap | 301 | GNUNET_CONTAINER_multipeermap_get (const struct GNUNET_CONTAINER_MultiPeerMap *map, |
280 | *map, const struct GNUNET_PeerIdentity *key) | 302 | const struct GNUNET_PeerIdentity *key) |
281 | { | 303 | { |
282 | union MapEntry me; | 304 | union MapEntry me; |
283 | 305 | ||
284 | me = map->map[idx_of (map, key)]; | 306 | me = map->map[idx_of (map, key)]; |
285 | if (map->use_small_entries) | 307 | if (map->use_small_entries) |
286 | { | 308 | { |
287 | struct SmallMapEntry *sme; | 309 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
288 | 310 | if (0 == memcmp (key, | |
289 | for (sme = me.sme; NULL != sme; sme = sme->next) | 311 | sme->key, |
290 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) | 312 | sizeof (struct GNUNET_PeerIdentity))) |
291 | return sme->value; | 313 | return sme->value; |
292 | } | 314 | } |
293 | else | 315 | else |
294 | { | 316 | { |
295 | struct BigMapEntry *bme; | 317 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
296 | 318 | if (0 == memcmp (key, | |
297 | for (bme = me.bme; NULL != bme; bme = bme->next) | 319 | &bme->key, |
298 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) | 320 | sizeof (struct GNUNET_PeerIdentity))) |
299 | return bme->value; | 321 | return bme->value; |
300 | } | 322 | } |
301 | return NULL; | 323 | return NULL; |
@@ -312,34 +334,39 @@ GNUNET_CONTAINER_multipeermap_get (const struct GNUNET_CONTAINER_MultiPeerMap | |||
312 | * #GNUNET_SYSERR if it aborted iteration | 334 | * #GNUNET_SYSERR if it aborted iteration |
313 | */ | 335 | */ |
314 | int | 336 | int |
315 | GNUNET_CONTAINER_multipeermap_iterate (const struct | 337 | GNUNET_CONTAINER_multipeermap_iterate (struct GNUNET_CONTAINER_MultiPeerMap *map, |
316 | GNUNET_CONTAINER_MultiPeerMap *map, | ||
317 | GNUNET_CONTAINER_PeerMapIterator it, | 338 | GNUNET_CONTAINER_PeerMapIterator it, |
318 | void *it_cls) | 339 | void *it_cls) |
319 | { | 340 | { |
320 | int count; | 341 | int count; |
321 | unsigned int i; | ||
322 | union MapEntry me; | 342 | union MapEntry me; |
343 | union MapEntry *ce; | ||
323 | struct GNUNET_PeerIdentity kc; | 344 | struct GNUNET_PeerIdentity kc; |
324 | 345 | ||
325 | count = 0; | 346 | count = 0; |
326 | GNUNET_assert (NULL != map); | 347 | GNUNET_assert (NULL != map); |
327 | for (i = 0; i < map->map_length; i++) | 348 | ce = &map->next_cache[map->next_cache_off]; |
349 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
350 | for (unsigned int i = 0; i < map->map_length; i++) | ||
328 | { | 351 | { |
329 | me = map->map[i]; | 352 | me = map->map[i]; |
330 | if (map->use_small_entries) | 353 | if (map->use_small_entries) |
331 | { | 354 | { |
332 | struct SmallMapEntry *sme; | 355 | struct SmallMapEntry *sme; |
333 | struct SmallMapEntry *nxt; | ||
334 | 356 | ||
335 | nxt = me.sme; | 357 | ce->sme = me.sme; |
336 | while (NULL != (sme = nxt)) | 358 | while (NULL != (sme = ce->sme)) |
337 | { | 359 | { |
338 | nxt = sme->next; | 360 | ce->sme = sme->next; |
339 | if (NULL != it) | 361 | if (NULL != it) |
340 | { | 362 | { |
341 | if (GNUNET_OK != it (it_cls, sme->key, sme->value)) | 363 | if (GNUNET_OK != it (it_cls, |
364 | sme->key, | ||
365 | sme->value)) | ||
366 | { | ||
367 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
342 | return GNUNET_SYSERR; | 368 | return GNUNET_SYSERR; |
369 | } | ||
343 | } | 370 | } |
344 | count++; | 371 | count++; |
345 | } | 372 | } |
@@ -347,27 +374,66 @@ GNUNET_CONTAINER_multipeermap_iterate (const struct | |||
347 | else | 374 | else |
348 | { | 375 | { |
349 | struct BigMapEntry *bme; | 376 | struct BigMapEntry *bme; |
350 | struct BigMapEntry *nxt; | ||
351 | 377 | ||
352 | nxt = me.bme; | 378 | ce->bme = me.bme; |
353 | while (NULL != (bme = nxt)) | 379 | while (NULL != (bme = ce->bme)) |
354 | { | 380 | { |
355 | nxt = bme->next; | 381 | ce->bme = bme->next; |
356 | if (NULL != it) | 382 | if (NULL != it) |
357 | { | 383 | { |
358 | kc = bme->key; | 384 | kc = bme->key; |
359 | if (GNUNET_OK != it (it_cls, &kc, bme->value)) | 385 | if (GNUNET_OK != it (it_cls, |
386 | &kc, | ||
387 | bme->value)) | ||
388 | { | ||
389 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
360 | return GNUNET_SYSERR; | 390 | return GNUNET_SYSERR; |
391 | } | ||
361 | } | 392 | } |
362 | count++; | 393 | count++; |
363 | } | 394 | } |
364 | } | 395 | } |
365 | } | 396 | } |
397 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
366 | return count; | 398 | return count; |
367 | } | 399 | } |
368 | 400 | ||
369 | 401 | ||
370 | /** | 402 | /** |
403 | * We are about to free() the @a bme, make sure it is not in | ||
404 | * the list of next values for any iterator in the @a map's next_cache. | ||
405 | * | ||
406 | * @param map the map to check | ||
407 | * @param bme the entry that is about to be free'd | ||
408 | */ | ||
409 | static void | ||
410 | update_next_cache_bme (struct GNUNET_CONTAINER_MultiPeerMap *map, | ||
411 | const struct BigMapEntry *bme) | ||
412 | { | ||
413 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
414 | if (map->next_cache[i].bme == bme) | ||
415 | map->next_cache[i].bme = bme->next; | ||
416 | } | ||
417 | |||
418 | |||
419 | /** | ||
420 | * We are about to free() the @a sme, make sure it is not in | ||
421 | * the list of next values for any iterator in the @a map's next_cache. | ||
422 | * | ||
423 | * @param map the map to check | ||
424 | * @param sme the entry that is about to be free'd | ||
425 | */ | ||
426 | static void | ||
427 | update_next_cache_sme (struct GNUNET_CONTAINER_MultiPeerMap *map, | ||
428 | const struct SmallMapEntry *sme) | ||
429 | { | ||
430 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
431 | if (map->next_cache[i].sme == sme) | ||
432 | map->next_cache[i].sme = sme->next; | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
371 | * Remove the given key-value pair from the map. Note that if the | 437 | * Remove the given key-value pair from the map. Note that if the |
372 | * key-value pair is in the map multiple times, only one of the pairs | 438 | * key-value pair is in the map multiple times, only one of the pairs |
373 | * will be removed. | 439 | * will be removed. |
@@ -375,7 +441,7 @@ GNUNET_CONTAINER_multipeermap_iterate (const struct | |||
375 | * @param map the map | 441 | * @param map the map |
376 | * @param key key of the key-value pair | 442 | * @param key key of the key-value pair |
377 | * @param value value of the key-value pair | 443 | * @param value value of the key-value pair |
378 | * @return GNUNET_YES on success, GNUNET_NO if the key-value pair | 444 | * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair |
379 | * is not in the map | 445 | * is not in the map |
380 | */ | 446 | */ |
381 | int | 447 | int |
@@ -387,16 +453,13 @@ GNUNET_CONTAINER_multipeermap_remove (struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
387 | unsigned int i; | 453 | unsigned int i; |
388 | 454 | ||
389 | map->modification_counter++; | 455 | map->modification_counter++; |
390 | |||
391 | i = idx_of (map, key); | 456 | i = idx_of (map, key); |
392 | me = map->map[i]; | 457 | me = map->map[i]; |
393 | if (map->use_small_entries) | 458 | if (map->use_small_entries) |
394 | { | 459 | { |
395 | struct SmallMapEntry *sme; | 460 | struct SmallMapEntry *p = NULL; |
396 | struct SmallMapEntry *p; | ||
397 | 461 | ||
398 | p = NULL; | 462 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
399 | for (sme = me.sme; NULL != sme; sme = sme->next) | ||
400 | { | 463 | { |
401 | if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) && | 464 | if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) && |
402 | (value == sme->value)) | 465 | (value == sme->value)) |
@@ -405,6 +468,8 @@ GNUNET_CONTAINER_multipeermap_remove (struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
405 | map->map[i].sme = sme->next; | 468 | map->map[i].sme = sme->next; |
406 | else | 469 | else |
407 | p->next = sme->next; | 470 | p->next = sme->next; |
471 | update_next_cache_sme (map, | ||
472 | sme); | ||
408 | GNUNET_free (sme); | 473 | GNUNET_free (sme); |
409 | map->size--; | 474 | map->size--; |
410 | return GNUNET_YES; | 475 | return GNUNET_YES; |
@@ -414,19 +479,21 @@ GNUNET_CONTAINER_multipeermap_remove (struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
414 | } | 479 | } |
415 | else | 480 | else |
416 | { | 481 | { |
417 | struct BigMapEntry *bme; | 482 | struct BigMapEntry *p = NULL; |
418 | struct BigMapEntry *p; | ||
419 | 483 | ||
420 | p = NULL; | 484 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
421 | for (bme = me.bme; NULL != bme; bme = bme->next) | ||
422 | { | 485 | { |
423 | if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) && | 486 | if ((0 == memcmp (key, |
487 | &bme->key, | ||
488 | sizeof (struct GNUNET_PeerIdentity))) && | ||
424 | (value == bme->value)) | 489 | (value == bme->value)) |
425 | { | 490 | { |
426 | if (NULL == p) | 491 | if (NULL == p) |
427 | map->map[i].bme = bme->next; | 492 | map->map[i].bme = bme->next; |
428 | else | 493 | else |
429 | p->next = bme->next; | 494 | p->next = bme->next; |
495 | update_next_cache_bme (map, | ||
496 | bme); | ||
430 | GNUNET_free (bme); | 497 | GNUNET_free (bme); |
431 | map->size--; | 498 | map->size--; |
432 | return GNUNET_YES; | 499 | return GNUNET_YES; |
@@ -447,8 +514,8 @@ GNUNET_CONTAINER_multipeermap_remove (struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
447 | * @return number of values removed | 514 | * @return number of values removed |
448 | */ | 515 | */ |
449 | int | 516 | int |
450 | GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap | 517 | GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap *map, |
451 | *map, const struct GNUNET_PeerIdentity *key) | 518 | const struct GNUNET_PeerIdentity *key) |
452 | { | 519 | { |
453 | union MapEntry me; | 520 | union MapEntry me; |
454 | unsigned int i; | 521 | unsigned int i; |
@@ -468,12 +535,16 @@ GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap | |||
468 | sme = me.sme; | 535 | sme = me.sme; |
469 | while (NULL != sme) | 536 | while (NULL != sme) |
470 | { | 537 | { |
471 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) | 538 | if (0 == memcmp (key, |
539 | sme->key, | ||
540 | sizeof (struct GNUNET_PeerIdentity))) | ||
472 | { | 541 | { |
473 | if (NULL == p) | 542 | if (NULL == p) |
474 | map->map[i].sme = sme->next; | 543 | map->map[i].sme = sme->next; |
475 | else | 544 | else |
476 | p->next = sme->next; | 545 | p->next = sme->next; |
546 | update_next_cache_sme (map, | ||
547 | sme); | ||
477 | GNUNET_free (sme); | 548 | GNUNET_free (sme); |
478 | map->size--; | 549 | map->size--; |
479 | if (NULL == p) | 550 | if (NULL == p) |
@@ -498,12 +569,16 @@ GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap | |||
498 | bme = me.bme; | 569 | bme = me.bme; |
499 | while (NULL != bme) | 570 | while (NULL != bme) |
500 | { | 571 | { |
501 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) | 572 | if (0 == memcmp (key, |
573 | &bme->key, | ||
574 | sizeof (struct GNUNET_PeerIdentity))) | ||
502 | { | 575 | { |
503 | if (NULL == p) | 576 | if (NULL == p) |
504 | map->map[i].bme = bme->next; | 577 | map->map[i].bme = bme->next; |
505 | else | 578 | else |
506 | p->next = bme->next; | 579 | p->next = bme->next; |
580 | update_next_cache_bme (map, | ||
581 | bme); | ||
507 | GNUNET_free (bme); | 582 | GNUNET_free (bme); |
508 | map->size--; | 583 | map->size--; |
509 | if (NULL == p) | 584 | if (NULL == p) |
@@ -529,12 +604,11 @@ GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap | |||
529 | * | 604 | * |
530 | * @param map the map | 605 | * @param map the map |
531 | * @param key the key to test if a value exists for it | 606 | * @param key the key to test if a value exists for it |
532 | * @return GNUNET_YES if such a value exists, | 607 | * @return #GNUNET_YES if such a value exists, |
533 | * GNUNET_NO if not | 608 | * #GNUNET_NO if not |
534 | */ | 609 | */ |
535 | int | 610 | int |
536 | GNUNET_CONTAINER_multipeermap_contains (const struct | 611 | GNUNET_CONTAINER_multipeermap_contains (const struct GNUNET_CONTAINER_MultiPeerMap *map, |
537 | GNUNET_CONTAINER_MultiPeerMap *map, | ||
538 | const struct GNUNET_PeerIdentity *key) | 612 | const struct GNUNET_PeerIdentity *key) |
539 | { | 613 | { |
540 | union MapEntry me; | 614 | union MapEntry me; |
@@ -542,17 +616,13 @@ GNUNET_CONTAINER_multipeermap_contains (const struct | |||
542 | me = map->map[idx_of (map, key)]; | 616 | me = map->map[idx_of (map, key)]; |
543 | if (map->use_small_entries) | 617 | if (map->use_small_entries) |
544 | { | 618 | { |
545 | struct SmallMapEntry *sme; | 619 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
546 | |||
547 | for (sme = me.sme; NULL != sme; sme = sme->next) | ||
548 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) | 620 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) |
549 | return GNUNET_YES; | 621 | return GNUNET_YES; |
550 | } | 622 | } |
551 | else | 623 | else |
552 | { | 624 | { |
553 | struct BigMapEntry *bme; | 625 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
554 | |||
555 | for (bme = me.bme; NULL != bme; bme = bme->next) | ||
556 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) | 626 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) |
557 | return GNUNET_YES; | 627 | return GNUNET_YES; |
558 | } | 628 | } |
@@ -567,13 +637,12 @@ GNUNET_CONTAINER_multipeermap_contains (const struct | |||
567 | * @param map the map | 637 | * @param map the map |
568 | * @param key the key to test if a value exists for it | 638 | * @param key the key to test if a value exists for it |
569 | * @param value value to test for | 639 | * @param value value to test for |
570 | * @return GNUNET_YES if such a value exists, | 640 | * @return #GNUNET_YES if such a value exists, |
571 | * GNUNET_NO if not | 641 | * #GNUNET_NO if not |
572 | */ | 642 | */ |
573 | int | 643 | int |
574 | GNUNET_CONTAINER_multipeermap_contains_value (const struct | 644 | GNUNET_CONTAINER_multipeermap_contains_value (const struct GNUNET_CONTAINER_MultiPeerMap *map, |
575 | GNUNET_CONTAINER_MultiPeerMap | 645 | const struct GNUNET_PeerIdentity *key, |
576 | *map, const struct GNUNET_PeerIdentity *key, | ||
577 | const void *value) | 646 | const void *value) |
578 | { | 647 | { |
579 | union MapEntry me; | 648 | union MapEntry me; |
@@ -581,19 +650,19 @@ GNUNET_CONTAINER_multipeermap_contains_value (const struct | |||
581 | me = map->map[idx_of (map, key)]; | 650 | me = map->map[idx_of (map, key)]; |
582 | if (map->use_small_entries) | 651 | if (map->use_small_entries) |
583 | { | 652 | { |
584 | struct SmallMapEntry *sme; | 653 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
585 | 654 | if ( (0 == memcmp (key, | |
586 | for (sme = me.sme; NULL != sme; sme = sme->next) | 655 | sme->key, |
587 | if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) && | 656 | sizeof (struct GNUNET_PeerIdentity))) && |
588 | (sme->value == value) ) | 657 | (sme->value == value) ) |
589 | return GNUNET_YES; | 658 | return GNUNET_YES; |
590 | } | 659 | } |
591 | else | 660 | else |
592 | { | 661 | { |
593 | struct BigMapEntry *bme; | 662 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
594 | 663 | if ( (0 == memcmp (key, | |
595 | for (bme = me.bme; NULL != bme; bme = bme->next) | 664 | &bme->key, |
596 | if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) && | 665 | sizeof (struct GNUNET_PeerIdentity))) && |
597 | (bme->value == value) ) | 666 | (bme->value == value) ) |
598 | return GNUNET_YES; | 667 | return GNUNET_YES; |
599 | } | 668 | } |
@@ -621,7 +690,8 @@ grow (struct GNUNET_CONTAINER_MultiPeerMap *map) | |||
621 | old_map = map->map; | 690 | old_map = map->map; |
622 | old_len = map->map_length; | 691 | old_len = map->map_length; |
623 | new_len = old_len * 2; | 692 | new_len = old_len * 2; |
624 | new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len); | 693 | new_map = GNUNET_new_array (new_len, |
694 | union MapEntry); | ||
625 | map->map_length = new_len; | 695 | map->map_length = new_len; |
626 | map->map = new_map; | 696 | map->map = new_map; |
627 | for (i = 0; i < old_len; i++) | 697 | for (i = 0; i < old_len; i++) |
@@ -664,7 +734,7 @@ grow (struct GNUNET_CONTAINER_MultiPeerMap *map) | |||
664 | * @param opt options for put | 734 | * @param opt options for put |
665 | * @return #GNUNET_OK on success, | 735 | * @return #GNUNET_OK on success, |
666 | * #GNUNET_NO if a value was replaced (with REPLACE) | 736 | * #GNUNET_NO if a value was replaced (with REPLACE) |
667 | * #GNUNET_SYSERR if GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the | 737 | * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the |
668 | * value already exists | 738 | * value already exists |
669 | */ | 739 | */ |
670 | int | 740 | int |
@@ -749,48 +819,66 @@ GNUNET_CONTAINER_multipeermap_put (struct GNUNET_CONTAINER_MultiPeerMap *map, | |||
749 | * #GNUNET_SYSERR if it aborted iteration | 819 | * #GNUNET_SYSERR if it aborted iteration |
750 | */ | 820 | */ |
751 | int | 821 | int |
752 | GNUNET_CONTAINER_multipeermap_get_multiple (const struct GNUNET_CONTAINER_MultiPeerMap *map, | 822 | GNUNET_CONTAINER_multipeermap_get_multiple (struct GNUNET_CONTAINER_MultiPeerMap *map, |
753 | const struct GNUNET_PeerIdentity *key, | 823 | const struct GNUNET_PeerIdentity *key, |
754 | GNUNET_CONTAINER_PeerMapIterator it, | 824 | GNUNET_CONTAINER_PeerMapIterator it, |
755 | void *it_cls) | 825 | void *it_cls) |
756 | { | 826 | { |
757 | int count; | 827 | int count; |
758 | union MapEntry me; | 828 | union MapEntry me; |
759 | 829 | union MapEntry *ce; | |
830 | |||
831 | ce = &map->next_cache[map->next_cache_off]; | ||
832 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
760 | count = 0; | 833 | count = 0; |
761 | me = map->map[idx_of (map, key)]; | 834 | me = map->map[idx_of (map, key)]; |
762 | if (map->use_small_entries) | 835 | if (map->use_small_entries) |
763 | { | 836 | { |
764 | struct SmallMapEntry *sme; | 837 | struct SmallMapEntry *sme; |
765 | struct SmallMapEntry *nxt; | ||
766 | 838 | ||
767 | nxt = me.sme; | 839 | ce->sme = me.sme; |
768 | while (NULL != (sme = nxt)) | 840 | while (NULL != (sme = ce->sme)) |
769 | { | 841 | { |
770 | nxt = sme->next; | 842 | ce->sme = sme->next; |
771 | if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) | 843 | if (0 != memcmp (key, |
844 | sme->key, | ||
845 | sizeof (struct GNUNET_PeerIdentity))) | ||
772 | continue; | 846 | continue; |
773 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) | 847 | if ( (NULL != it) && |
848 | (GNUNET_OK != it (it_cls, | ||
849 | key, | ||
850 | sme->value))) | ||
851 | { | ||
852 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
774 | return GNUNET_SYSERR; | 853 | return GNUNET_SYSERR; |
854 | } | ||
775 | count++; | 855 | count++; |
776 | } | 856 | } |
777 | } | 857 | } |
778 | else | 858 | else |
779 | { | 859 | { |
780 | struct BigMapEntry *bme; | 860 | struct BigMapEntry *bme; |
781 | struct BigMapEntry *nxt; | ||
782 | 861 | ||
783 | nxt = me.bme; | 862 | ce->bme = me.bme; |
784 | while (NULL != (bme = nxt)) | 863 | while (NULL != (bme = ce->bme)) |
785 | { | 864 | { |
786 | nxt = bme->next; | 865 | ce->bme = bme->next; |
787 | if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) | 866 | if (0 != memcmp (key, |
867 | &bme->key, | ||
868 | sizeof (struct GNUNET_PeerIdentity))) | ||
788 | continue; | 869 | continue; |
789 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) | 870 | if ( (NULL != it) && |
871 | (GNUNET_OK != it (it_cls, | ||
872 | key, | ||
873 | bme->value))) | ||
874 | { | ||
875 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
790 | return GNUNET_SYSERR; | 876 | return GNUNET_SYSERR; |
877 | } | ||
791 | count++; | 878 | count++; |
792 | } | 879 | } |
793 | } | 880 | } |
881 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
794 | return count; | 882 | return count; |
795 | } | 883 | } |
796 | 884 | ||
@@ -812,16 +900,15 @@ GNUNET_CONTAINER_multipeermap_get_random (const struct GNUNET_CONTAINER_MultiPee | |||
812 | void *it_cls) | 900 | void *it_cls) |
813 | { | 901 | { |
814 | unsigned int off; | 902 | unsigned int off; |
815 | unsigned int idx; | ||
816 | union MapEntry me; | 903 | union MapEntry me; |
817 | 904 | ||
818 | if (0 == map->size) | 905 | if (0 == map->size) |
819 | return 0; | 906 | return 0; |
820 | if (NULL == it) | 907 | if (NULL == it) |
821 | return 1; | 908 | return 1; |
822 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | 909 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, |
823 | map->size); | 910 | map->size); |
824 | for (idx = 0; idx < map->map_length; idx++) | 911 | for (unsigned int idx = 0; idx < map->map_length; idx++) |
825 | { | 912 | { |
826 | me = map->map[idx]; | 913 | me = map->map[idx]; |
827 | if (map->use_small_entries) | 914 | if (map->use_small_entries) |
@@ -856,9 +943,10 @@ GNUNET_CONTAINER_multipeermap_get_random (const struct GNUNET_CONTAINER_MultiPee | |||
856 | if (0 == off) | 943 | if (0 == off) |
857 | { | 944 | { |
858 | if (GNUNET_OK != it (it_cls, | 945 | if (GNUNET_OK != it (it_cls, |
859 | &bme->key, bme->value)) | 946 | &bme->key, |
860 | return GNUNET_SYSERR; | 947 | bme->value)) |
861 | return 1; | 948 | return GNUNET_SYSERR; |
949 | return 1; | ||
862 | } | 950 | } |
863 | off--; | 951 | off--; |
864 | } | 952 | } |
diff --git a/src/util/container_multishortmap.c b/src/util/container_multishortmap.c index f815b6238..050fd21f9 100644 --- a/src/util/container_multishortmap.c +++ b/src/util/container_multishortmap.c | |||
@@ -27,6 +27,15 @@ | |||
27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multishortmap", __VA_ARGS__) | 27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multishortmap", __VA_ARGS__) |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * Maximum recursion depth for callbacks of | ||
31 | * #GNUNET_CONTAINER_multihashmap_get_multiple() themselve s | ||
32 | * again calling #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
33 | * Should be totally excessive, but if violated we die. | ||
34 | */ | ||
35 | #define NEXT_CACHE_SIZE 16 | ||
36 | |||
37 | |||
38 | /** | ||
30 | * An entry in the hash map with the full key. | 39 | * An entry in the hash map with the full key. |
31 | */ | 40 | */ |
32 | struct BigMapEntry | 41 | struct BigMapEntry |
@@ -112,8 +121,8 @@ struct GNUNET_CONTAINER_MultiShortmap | |||
112 | unsigned int map_length; | 121 | unsigned int map_length; |
113 | 122 | ||
114 | /** | 123 | /** |
115 | * GNUNET_NO if the map entries are of type 'struct BigMapEntry', | 124 | * #GNUNET_NO if the map entries are of type 'struct BigMapEntry', |
116 | * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. | 125 | * #GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. |
117 | */ | 126 | */ |
118 | int use_small_entries; | 127 | int use_small_entries; |
119 | 128 | ||
@@ -122,6 +131,20 @@ struct GNUNET_CONTAINER_MultiShortmap | |||
122 | * to the map, so that iterators can check if they are still valid. | 131 | * to the map, so that iterators can check if they are still valid. |
123 | */ | 132 | */ |
124 | unsigned int modification_counter; | 133 | unsigned int modification_counter; |
134 | |||
135 | /** | ||
136 | * Map entries indicating iteration positions currently | ||
137 | * in use by #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
138 | * Only used up to @e next_cache_off. | ||
139 | */ | ||
140 | union MapEntry next_cache[NEXT_CACHE_SIZE]; | ||
141 | |||
142 | /** | ||
143 | * Offset of @e next_cache entries in use, must be smaller | ||
144 | * than #NEXT_CACHE_SIZE. | ||
145 | */ | ||
146 | unsigned int next_cache_off; | ||
147 | |||
125 | }; | 148 | }; |
126 | 149 | ||
127 | 150 | ||
@@ -177,7 +200,8 @@ GNUNET_CONTAINER_multishortmap_create (unsigned int len, | |||
177 | 200 | ||
178 | GNUNET_assert (len > 0); | 201 | GNUNET_assert (len > 0); |
179 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmap); | 202 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmap); |
180 | map->map = GNUNET_malloc (len * sizeof (union MapEntry)); | 203 | map->map = GNUNET_new_array (len, |
204 | union MapEntry); | ||
181 | map->map_length = len; | 205 | map->map_length = len; |
182 | map->use_small_entries = do_not_copy_keys; | 206 | map->use_small_entries = do_not_copy_keys; |
183 | return map; | 207 | return map; |
@@ -191,14 +215,13 @@ GNUNET_CONTAINER_multishortmap_create (unsigned int len, | |||
191 | * @param map the map | 215 | * @param map the map |
192 | */ | 216 | */ |
193 | void | 217 | void |
194 | GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap | 218 | GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap *map) |
195 | *map) | ||
196 | { | 219 | { |
197 | unsigned int i; | 220 | GNUNET_assert (0 == map->next_cache_off); |
198 | union MapEntry me; | 221 | for (unsigned int i = 0; i < map->map_length; i++) |
199 | |||
200 | for (i = 0; i < map->map_length; i++) | ||
201 | { | 222 | { |
223 | union MapEntry me; | ||
224 | |||
202 | me = map->map[i]; | 225 | me = map->map[i]; |
203 | if (map->use_small_entries) | 226 | if (map->use_small_entries) |
204 | { | 227 | { |
@@ -283,18 +306,18 @@ GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap | |||
283 | me = map->map[idx_of (map, key)]; | 306 | me = map->map[idx_of (map, key)]; |
284 | if (map->use_small_entries) | 307 | if (map->use_small_entries) |
285 | { | 308 | { |
286 | struct SmallMapEntry *sme; | 309 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
287 | 310 | if (0 == memcmp (key, | |
288 | for (sme = me.sme; NULL != sme; sme = sme->next) | 311 | sme->key, |
289 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 312 | sizeof (struct GNUNET_ShortHashCode))) |
290 | return sme->value; | 313 | return sme->value; |
291 | } | 314 | } |
292 | else | 315 | else |
293 | { | 316 | { |
294 | struct BigMapEntry *bme; | 317 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
295 | 318 | if (0 == memcmp (key, | |
296 | for (bme = me.bme; NULL != bme; bme = bme->next) | 319 | &bme->key, |
297 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 320 | sizeof (struct GNUNET_ShortHashCode))) |
298 | return bme->value; | 321 | return bme->value; |
299 | } | 322 | } |
300 | return NULL; | 323 | return NULL; |
@@ -311,33 +334,37 @@ GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap | |||
311 | * #GNUNET_SYSERR if it aborted iteration | 334 | * #GNUNET_SYSERR if it aborted iteration |
312 | */ | 335 | */ |
313 | int | 336 | int |
314 | GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map, | 337 | GNUNET_CONTAINER_multishortmap_iterate (struct GNUNET_CONTAINER_MultiShortmap *map, |
315 | GNUNET_CONTAINER_ShortmapIterator it, | 338 | GNUNET_CONTAINER_ShortmapIterator it, |
316 | void *it_cls) | 339 | void *it_cls) |
317 | { | 340 | { |
318 | int count; | 341 | int count; |
319 | unsigned int i; | ||
320 | union MapEntry me; | 342 | union MapEntry me; |
343 | union MapEntry *ce; | ||
321 | struct GNUNET_ShortHashCode kc; | 344 | struct GNUNET_ShortHashCode kc; |
322 | 345 | ||
323 | count = 0; | 346 | count = 0; |
324 | GNUNET_assert (NULL != map); | 347 | GNUNET_assert (NULL != map); |
325 | for (i = 0; i < map->map_length; i++) | 348 | ce = &map->next_cache[map->next_cache_off]; |
349 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
350 | for (unsigned int i = 0; i < map->map_length; i++) | ||
326 | { | 351 | { |
327 | me = map->map[i]; | 352 | me = map->map[i]; |
328 | if (map->use_small_entries) | 353 | if (map->use_small_entries) |
329 | { | 354 | { |
330 | struct SmallMapEntry *sme; | 355 | struct SmallMapEntry *sme; |
331 | struct SmallMapEntry *nxt; | 356 | |
332 | 357 | ce->sme = me.sme; | |
333 | nxt = me.sme; | 358 | while (NULL != (sme = ce->sme)) |
334 | while (NULL != (sme = nxt)) | ||
335 | { | 359 | { |
336 | nxt = sme->next; | 360 | ce->sme = sme->next; |
337 | if (NULL != it) | 361 | if ( (NULL != it) && |
362 | (GNUNET_OK != it (it_cls, | ||
363 | sme->key, | ||
364 | sme->value)) ) | ||
338 | { | 365 | { |
339 | if (GNUNET_OK != it (it_cls, sme->key, sme->value)) | 366 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); |
340 | return GNUNET_SYSERR; | 367 | return GNUNET_SYSERR; |
341 | } | 368 | } |
342 | count++; | 369 | count++; |
343 | } | 370 | } |
@@ -345,27 +372,66 @@ GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShort | |||
345 | else | 372 | else |
346 | { | 373 | { |
347 | struct BigMapEntry *bme; | 374 | struct BigMapEntry *bme; |
348 | struct BigMapEntry *nxt; | ||
349 | 375 | ||
350 | nxt = me.bme; | 376 | ce->bme = me.bme; |
351 | while (NULL != (bme = nxt)) | 377 | while (NULL != (bme = ce->bme)) |
352 | { | 378 | { |
353 | nxt = bme->next; | 379 | ce->bme = bme->next; |
354 | if (NULL != it) | 380 | if (NULL != it) |
355 | { | 381 | { |
356 | kc = bme->key; | 382 | kc = bme->key; |
357 | if (GNUNET_OK != it (it_cls, &kc, bme->value)) | 383 | if (GNUNET_OK != it (it_cls, |
384 | &kc, | ||
385 | bme->value)) | ||
386 | { | ||
387 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
358 | return GNUNET_SYSERR; | 388 | return GNUNET_SYSERR; |
389 | } | ||
359 | } | 390 | } |
360 | count++; | 391 | count++; |
361 | } | 392 | } |
362 | } | 393 | } |
363 | } | 394 | } |
395 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
364 | return count; | 396 | return count; |
365 | } | 397 | } |
366 | 398 | ||
367 | 399 | ||
368 | /** | 400 | /** |
401 | * We are about to free() the @a bme, make sure it is not in | ||
402 | * the list of next values for any iterator in the @a map's next_cache. | ||
403 | * | ||
404 | * @param map the map to check | ||
405 | * @param bme the entry that is about to be free'd | ||
406 | */ | ||
407 | static void | ||
408 | update_next_cache_bme (struct GNUNET_CONTAINER_MultiShortmap *map, | ||
409 | const struct BigMapEntry *bme) | ||
410 | { | ||
411 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
412 | if (map->next_cache[i].bme == bme) | ||
413 | map->next_cache[i].bme = bme->next; | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * We are about to free() the @a sme, make sure it is not in | ||
419 | * the list of next values for any iterator in the @a map's next_cache. | ||
420 | * | ||
421 | * @param map the map to check | ||
422 | * @param sme the entry that is about to be free'd | ||
423 | */ | ||
424 | static void | ||
425 | update_next_cache_sme (struct GNUNET_CONTAINER_MultiShortmap *map, | ||
426 | const struct SmallMapEntry *sme) | ||
427 | { | ||
428 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
429 | if (map->next_cache[i].sme == sme) | ||
430 | map->next_cache[i].sme = sme->next; | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
369 | * Remove the given key-value pair from the map. Note that if the | 435 | * Remove the given key-value pair from the map. Note that if the |
370 | * key-value pair is in the map multiple times, only one of the pairs | 436 | * key-value pair is in the map multiple times, only one of the pairs |
371 | * will be removed. | 437 | * will be removed. |
@@ -385,24 +451,25 @@ GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *ma | |||
385 | unsigned int i; | 451 | unsigned int i; |
386 | 452 | ||
387 | map->modification_counter++; | 453 | map->modification_counter++; |
388 | |||
389 | i = idx_of (map, key); | 454 | i = idx_of (map, key); |
390 | me = map->map[i]; | 455 | me = map->map[i]; |
391 | if (map->use_small_entries) | 456 | if (map->use_small_entries) |
392 | { | 457 | { |
393 | struct SmallMapEntry *sme; | 458 | struct SmallMapEntry *p = NULL; |
394 | struct SmallMapEntry *p; | 459 | |
395 | 460 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | |
396 | p = NULL; | ||
397 | for (sme = me.sme; NULL != sme; sme = sme->next) | ||
398 | { | 461 | { |
399 | if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) && | 462 | if ((0 == memcmp (key, |
463 | sme->key, | ||
464 | sizeof (struct GNUNET_ShortHashCode))) && | ||
400 | (value == sme->value)) | 465 | (value == sme->value)) |
401 | { | 466 | { |
402 | if (NULL == p) | 467 | if (NULL == p) |
403 | map->map[i].sme = sme->next; | 468 | map->map[i].sme = sme->next; |
404 | else | 469 | else |
405 | p->next = sme->next; | 470 | p->next = sme->next; |
471 | update_next_cache_sme (map, | ||
472 | sme); | ||
406 | GNUNET_free (sme); | 473 | GNUNET_free (sme); |
407 | map->size--; | 474 | map->size--; |
408 | return GNUNET_YES; | 475 | return GNUNET_YES; |
@@ -412,19 +479,21 @@ GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *ma | |||
412 | } | 479 | } |
413 | else | 480 | else |
414 | { | 481 | { |
415 | struct BigMapEntry *bme; | 482 | struct BigMapEntry *p = NULL; |
416 | struct BigMapEntry *p; | 483 | |
417 | 484 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | |
418 | p = NULL; | ||
419 | for (bme = me.bme; NULL != bme; bme = bme->next) | ||
420 | { | 485 | { |
421 | if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) && | 486 | if ((0 == memcmp (key, |
487 | &bme->key, | ||
488 | sizeof (struct GNUNET_ShortHashCode))) && | ||
422 | (value == bme->value)) | 489 | (value == bme->value)) |
423 | { | 490 | { |
424 | if (NULL == p) | 491 | if (NULL == p) |
425 | map->map[i].bme = bme->next; | 492 | map->map[i].bme = bme->next; |
426 | else | 493 | else |
427 | p->next = bme->next; | 494 | p->next = bme->next; |
495 | update_next_cache_bme (map, | ||
496 | bme); | ||
428 | GNUNET_free (bme); | 497 | GNUNET_free (bme); |
429 | map->size--; | 498 | map->size--; |
430 | return GNUNET_YES; | 499 | return GNUNET_YES; |
@@ -472,6 +541,8 @@ GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap | |||
472 | map->map[i].sme = sme->next; | 541 | map->map[i].sme = sme->next; |
473 | else | 542 | else |
474 | p->next = sme->next; | 543 | p->next = sme->next; |
544 | update_next_cache_sme (map, | ||
545 | sme); | ||
475 | GNUNET_free (sme); | 546 | GNUNET_free (sme); |
476 | map->size--; | 547 | map->size--; |
477 | if (NULL == p) | 548 | if (NULL == p) |
@@ -502,6 +573,8 @@ GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap | |||
502 | map->map[i].bme = bme->next; | 573 | map->map[i].bme = bme->next; |
503 | else | 574 | else |
504 | p->next = bme->next; | 575 | p->next = bme->next; |
576 | update_next_cache_bme (map, | ||
577 | bme); | ||
505 | GNUNET_free (bme); | 578 | GNUNET_free (bme); |
506 | map->size--; | 579 | map->size--; |
507 | if (NULL == p) | 580 | if (NULL == p) |
@@ -539,18 +612,18 @@ GNUNET_CONTAINER_multishortmap_contains (const struct GNUNET_CONTAINER_MultiShor | |||
539 | me = map->map[idx_of (map, key)]; | 612 | me = map->map[idx_of (map, key)]; |
540 | if (map->use_small_entries) | 613 | if (map->use_small_entries) |
541 | { | 614 | { |
542 | struct SmallMapEntry *sme; | 615 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
543 | 616 | if (0 == memcmp (key, | |
544 | for (sme = me.sme; NULL != sme; sme = sme->next) | 617 | sme->key, |
545 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 618 | sizeof (struct GNUNET_ShortHashCode))) |
546 | return GNUNET_YES; | 619 | return GNUNET_YES; |
547 | } | 620 | } |
548 | else | 621 | else |
549 | { | 622 | { |
550 | struct BigMapEntry *bme; | 623 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
551 | 624 | if (0 == memcmp (key, | |
552 | for (bme = me.bme; NULL != bme; bme = bme->next) | 625 | &bme->key, |
553 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 626 | sizeof (struct GNUNET_ShortHashCode))) |
554 | return GNUNET_YES; | 627 | return GNUNET_YES; |
555 | } | 628 | } |
556 | return GNUNET_NO; | 629 | return GNUNET_NO; |
@@ -577,19 +650,19 @@ GNUNET_CONTAINER_multishortmap_contains_value (const struct GNUNET_CONTAINER_Mul | |||
577 | me = map->map[idx_of (map, key)]; | 650 | me = map->map[idx_of (map, key)]; |
578 | if (map->use_small_entries) | 651 | if (map->use_small_entries) |
579 | { | 652 | { |
580 | struct SmallMapEntry *sme; | 653 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
581 | 654 | if ( (0 == memcmp (key, | |
582 | for (sme = me.sme; NULL != sme; sme = sme->next) | 655 | sme->key, |
583 | if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) && | 656 | sizeof (struct GNUNET_ShortHashCode))) && |
584 | (sme->value == value) ) | 657 | (sme->value == value) ) |
585 | return GNUNET_YES; | 658 | return GNUNET_YES; |
586 | } | 659 | } |
587 | else | 660 | else |
588 | { | 661 | { |
589 | struct BigMapEntry *bme; | 662 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
590 | 663 | if ( (0 == memcmp (key, | |
591 | for (bme = me.bme; NULL != bme; bme = bme->next) | 664 | &bme->key, |
592 | if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) && | 665 | sizeof (struct GNUNET_ShortHashCode))) && |
593 | (bme->value == value) ) | 666 | (bme->value == value) ) |
594 | return GNUNET_YES; | 667 | return GNUNET_YES; |
595 | } | 668 | } |
@@ -610,17 +683,17 @@ grow (struct GNUNET_CONTAINER_MultiShortmap *map) | |||
610 | unsigned int old_len; | 683 | unsigned int old_len; |
611 | unsigned int new_len; | 684 | unsigned int new_len; |
612 | unsigned int idx; | 685 | unsigned int idx; |
613 | unsigned int i; | ||
614 | 686 | ||
615 | map->modification_counter++; | 687 | map->modification_counter++; |
616 | 688 | ||
617 | old_map = map->map; | 689 | old_map = map->map; |
618 | old_len = map->map_length; | 690 | old_len = map->map_length; |
619 | new_len = old_len * 2; | 691 | new_len = old_len * 2; |
620 | new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len); | 692 | new_map = GNUNET_new_array (new_len, |
693 | union MapEntry); | ||
621 | map->map_length = new_len; | 694 | map->map_length = new_len; |
622 | map->map = new_map; | 695 | map->map = new_map; |
623 | for (i = 0; i < old_len; i++) | 696 | for (unsigned int i = 0; i < old_len; i++) |
624 | { | 697 | { |
625 | if (map->use_small_entries) | 698 | if (map->use_small_entries) |
626 | { | 699 | { |
@@ -660,7 +733,7 @@ grow (struct GNUNET_CONTAINER_MultiShortmap *map) | |||
660 | * @param opt options for put | 733 | * @param opt options for put |
661 | * @return #GNUNET_OK on success, | 734 | * @return #GNUNET_OK on success, |
662 | * #GNUNET_NO if a value was replaced (with REPLACE) | 735 | * #GNUNET_NO if a value was replaced (with REPLACE) |
663 | * #GNUNET_SYSERR if GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the | 736 | * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the |
664 | * value already exists | 737 | * value already exists |
665 | */ | 738 | */ |
666 | int | 739 | int |
@@ -679,10 +752,10 @@ GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map, | |||
679 | me = map->map[i]; | 752 | me = map->map[i]; |
680 | if (map->use_small_entries) | 753 | if (map->use_small_entries) |
681 | { | 754 | { |
682 | struct SmallMapEntry *sme; | 755 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
683 | 756 | if (0 == memcmp (key, | |
684 | for (sme = me.sme; NULL != sme; sme = sme->next) | 757 | sme->key, |
685 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 758 | sizeof (struct GNUNET_ShortHashCode))) |
686 | { | 759 | { |
687 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) | 760 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) |
688 | return GNUNET_SYSERR; | 761 | return GNUNET_SYSERR; |
@@ -692,10 +765,10 @@ GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map, | |||
692 | } | 765 | } |
693 | else | 766 | else |
694 | { | 767 | { |
695 | struct BigMapEntry *bme; | 768 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
696 | 769 | if (0 == memcmp (key, | |
697 | for (bme = me.bme; NULL != bme; bme = bme->next) | 770 | &bme->key, |
698 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 771 | sizeof (struct GNUNET_ShortHashCode))) |
699 | { | 772 | { |
700 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) | 773 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) |
701 | return GNUNET_SYSERR; | 774 | return GNUNET_SYSERR; |
@@ -745,48 +818,66 @@ GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map, | |||
745 | * #GNUNET_SYSERR if it aborted iteration | 818 | * #GNUNET_SYSERR if it aborted iteration |
746 | */ | 819 | */ |
747 | int | 820 | int |
748 | GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map, | 821 | GNUNET_CONTAINER_multishortmap_get_multiple (struct GNUNET_CONTAINER_MultiShortmap *map, |
749 | const struct GNUNET_ShortHashCode *key, | 822 | const struct GNUNET_ShortHashCode *key, |
750 | GNUNET_CONTAINER_ShortmapIterator it, | 823 | GNUNET_CONTAINER_ShortmapIterator it, |
751 | void *it_cls) | 824 | void *it_cls) |
752 | { | 825 | { |
753 | int count; | 826 | int count; |
754 | union MapEntry me; | 827 | union MapEntry me; |
828 | union MapEntry *ce; | ||
755 | 829 | ||
830 | ce = &map->next_cache[map->next_cache_off]; | ||
831 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
756 | count = 0; | 832 | count = 0; |
757 | me = map->map[idx_of (map, key)]; | 833 | me = map->map[idx_of (map, key)]; |
758 | if (map->use_small_entries) | 834 | if (map->use_small_entries) |
759 | { | 835 | { |
760 | struct SmallMapEntry *sme; | 836 | struct SmallMapEntry *sme; |
761 | struct SmallMapEntry *nxt; | ||
762 | 837 | ||
763 | nxt = me.sme; | 838 | ce->sme = me.sme; |
764 | while (NULL != (sme = nxt)) | 839 | while (NULL != (sme = ce->sme)) |
765 | { | 840 | { |
766 | nxt = sme->next; | 841 | ce->sme = sme->next; |
767 | if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 842 | if (0 != memcmp (key, |
843 | sme->key, | ||
844 | sizeof (struct GNUNET_ShortHashCode))) | ||
768 | continue; | 845 | continue; |
769 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) | 846 | if ( (NULL != it) && |
847 | (GNUNET_OK != it (it_cls, | ||
848 | key, | ||
849 | sme->value)) ) | ||
850 | { | ||
851 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
770 | return GNUNET_SYSERR; | 852 | return GNUNET_SYSERR; |
853 | } | ||
771 | count++; | 854 | count++; |
772 | } | 855 | } |
773 | } | 856 | } |
774 | else | 857 | else |
775 | { | 858 | { |
776 | struct BigMapEntry *bme; | 859 | struct BigMapEntry *bme; |
777 | struct BigMapEntry *nxt; | ||
778 | 860 | ||
779 | nxt = me.bme; | 861 | ce->bme = me.bme; |
780 | while (NULL != (bme = nxt)) | 862 | while (NULL != (bme = ce->bme)) |
781 | { | 863 | { |
782 | nxt = bme->next; | 864 | ce->bme = bme->next; |
783 | if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 865 | if (0 != memcmp (key, |
866 | &bme->key, | ||
867 | sizeof (struct GNUNET_ShortHashCode))) | ||
784 | continue; | 868 | continue; |
785 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) | 869 | if ( (NULL != it) && |
870 | (GNUNET_OK != it (it_cls, | ||
871 | key, | ||
872 | bme->value)) ) | ||
873 | { | ||
874 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
786 | return GNUNET_SYSERR; | 875 | return GNUNET_SYSERR; |
876 | } | ||
787 | count++; | 877 | count++; |
788 | } | 878 | } |
789 | } | 879 | } |
880 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
790 | return count; | 881 | return count; |
791 | } | 882 | } |
792 | 883 | ||
@@ -808,7 +899,6 @@ GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiSh | |||
808 | void *it_cls) | 899 | void *it_cls) |
809 | { | 900 | { |
810 | unsigned int off; | 901 | unsigned int off; |
811 | unsigned int idx; | ||
812 | union MapEntry me; | 902 | union MapEntry me; |
813 | 903 | ||
814 | if (0 == map->size) | 904 | if (0 == map->size) |
@@ -817,18 +907,13 @@ GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiSh | |||
817 | return 1; | 907 | return 1; |
818 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | 908 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, |
819 | map->size); | 909 | map->size); |
820 | for (idx = 0; idx < map->map_length; idx++) | 910 | for (unsigned int idx = 0; idx < map->map_length; idx++) |
821 | { | 911 | { |
822 | me = map->map[idx]; | 912 | me = map->map[idx]; |
823 | if (map->use_small_entries) | 913 | if (map->use_small_entries) |
824 | { | 914 | { |
825 | struct SmallMapEntry *sme; | 915 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
826 | struct SmallMapEntry *nxt; | ||
827 | |||
828 | nxt = me.sme; | ||
829 | while (NULL != (sme = nxt)) | ||
830 | { | 916 | { |
831 | nxt = sme->next; | ||
832 | if (0 == off) | 917 | if (0 == off) |
833 | { | 918 | { |
834 | if (GNUNET_OK != it (it_cls, | 919 | if (GNUNET_OK != it (it_cls, |
@@ -842,13 +927,8 @@ GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiSh | |||
842 | } | 927 | } |
843 | else | 928 | else |
844 | { | 929 | { |
845 | struct BigMapEntry *bme; | 930 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
846 | struct BigMapEntry *nxt; | ||
847 | |||
848 | nxt = me.bme; | ||
849 | while (NULL != (bme = nxt)) | ||
850 | { | 931 | { |
851 | nxt = bme->next; | ||
852 | if (0 == off) | 932 | if (0 == off) |
853 | { | 933 | { |
854 | if (GNUNET_OK != it (it_cls, | 934 | if (GNUNET_OK != it (it_cls, |
diff --git a/src/util/getopt.c b/src/util/getopt.c index 036e0f4be..4a7f35f51 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c | |||
@@ -866,7 +866,7 @@ GNgetopt_long (int argc, | |||
866 | * @param argc number of arguments | 866 | * @param argc number of arguments |
867 | * @param argv actual arguments | 867 | * @param argv actual arguments |
868 | * @return index into argv with first non-option | 868 | * @return index into argv with first non-option |
869 | * argument, or -1 on error | 869 | * argument, or #GNUNET_SYSERR on error |
870 | */ | 870 | */ |
871 | int | 871 | int |
872 | GNUNET_GETOPT_run (const char *binaryOptions, | 872 | GNUNET_GETOPT_run (const char *binaryOptions, |
@@ -967,9 +967,9 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
967 | GNUNET_free (seen); | 967 | GNUNET_free (seen); |
968 | 968 | ||
969 | /* call cleaners, if available */ | 969 | /* call cleaners, if available */ |
970 | for (count = 0; NULL != allOptions[count].name; count++) | 970 | for (unsigned int i = 0; NULL != allOptions[i].name; i++) |
971 | if (NULL != allOptions[count].cleaner) | 971 | if (NULL != allOptions[i].cleaner) |
972 | allOptions[count].cleaner (allOptions[count].scls); | 972 | allOptions[i].cleaner (allOptions[i].scls); |
973 | 973 | ||
974 | if (GNUNET_OK != cont) | 974 | if (GNUNET_OK != cont) |
975 | return cont; | 975 | return cont; |
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c index 32cce65dd..661521c45 100644 --- a/src/util/getopt_helpers.c +++ b/src/util/getopt_helpers.c | |||
@@ -108,9 +108,10 @@ format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
108 | (void) value; | 108 | (void) value; |
109 | if (NULL != about) | 109 | if (NULL != about) |
110 | { | 110 | { |
111 | printf ("%s\n%s\n", ctx->binaryOptions, gettext (about)); | 111 | printf ("%s\n%s\n", |
112 | printf (_ | 112 | ctx->binaryOptions, |
113 | ("Arguments mandatory for long options are also mandatory for short options.\n")); | 113 | gettext (about)); |
114 | printf (_("Arguments mandatory for long options are also mandatory for short options.\n")); | ||
114 | } | 115 | } |
115 | i = 0; | 116 | i = 0; |
116 | opt = ctx->allOptions; | 117 | opt = ctx->allOptions; |
@@ -549,11 +550,13 @@ set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
549 | const char *value) | 550 | const char *value) |
550 | { | 551 | { |
551 | unsigned long long *val = scls; | 552 | unsigned long long *val = scls; |
553 | char dummy[2]; | ||
552 | 554 | ||
553 | (void) ctx; | 555 | (void) ctx; |
554 | if (1 != SSCANF (value, | 556 | if (1 != SSCANF (value, |
555 | "%llu", | 557 | "%llu%1s", |
556 | val)) | 558 | val, |
559 | dummy)) | ||
557 | { | 560 | { |
558 | FPRINTF (stderr, | 561 | FPRINTF (stderr, |
559 | _("You must pass a number to the `%s' option.\n"), | 562 | _("You must pass a number to the `%s' option.\n"), |
@@ -746,6 +749,7 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
746 | const char *value) | 749 | const char *value) |
747 | { | 750 | { |
748 | unsigned int *val = scls; | 751 | unsigned int *val = scls; |
752 | char dummy[2]; | ||
749 | 753 | ||
750 | (void) ctx; | 754 | (void) ctx; |
751 | if('-' == *value) | 755 | if('-' == *value) |
@@ -756,8 +760,9 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
756 | return GNUNET_SYSERR; | 760 | return GNUNET_SYSERR; |
757 | } | 761 | } |
758 | if (1 != SSCANF (value, | 762 | if (1 != SSCANF (value, |
759 | "%u", | 763 | "%u%1s", |
760 | val)) | 764 | val, |
765 | dummy)) | ||
761 | { | 766 | { |
762 | FPRINTF (stderr, | 767 | FPRINTF (stderr, |
763 | _("You must pass a number to the `%s' option.\n"), | 768 | _("You must pass a number to the `%s' option.\n"), |
@@ -820,11 +825,13 @@ set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
820 | { | 825 | { |
821 | uint16_t *val = scls; | 826 | uint16_t *val = scls; |
822 | unsigned int v; | 827 | unsigned int v; |
828 | char dummy[2]; | ||
823 | 829 | ||
824 | (void) ctx; | 830 | (void) ctx; |
825 | if (1 != SSCANF (value, | 831 | if (1 != SSCANF (value, |
826 | "%u", | 832 | "%u%1s", |
827 | &v)) | 833 | &v, |
834 | dummy)) | ||
828 | { | 835 | { |
829 | FPRINTF (stderr, | 836 | FPRINTF (stderr, |
830 | _("You must pass a number to the `%s' option.\n"), | 837 | _("You must pass a number to the `%s' option.\n"), |
diff --git a/src/util/service.c b/src/util/service.c index 20cc1036d..ea34abc6c 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -1175,8 +1175,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1175 | const char *nfds; | 1175 | const char *nfds; |
1176 | unsigned int cnt; | 1176 | unsigned int cnt; |
1177 | int flags; | 1177 | int flags; |
1178 | char dummy[2]; | ||
1178 | #endif | 1179 | #endif |
1179 | 1180 | ||
1180 | if (GNUNET_CONFIGURATION_have_value | 1181 | if (GNUNET_CONFIGURATION_have_value |
1181 | (sh->cfg, | 1182 | (sh->cfg, |
1182 | sh->service_name, | 1183 | sh->service_name, |
@@ -1203,8 +1204,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1203 | errno = 0; | 1204 | errno = 0; |
1204 | if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) && | 1205 | if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) && |
1205 | (1 == SSCANF (nfds, | 1206 | (1 == SSCANF (nfds, |
1206 | "%u", | 1207 | "%u%1s", |
1207 | &cnt)) && | 1208 | &cnt, |
1209 | dummy)) && | ||
1208 | (cnt > 0) && | 1210 | (cnt > 0) && |
1209 | (cnt < FD_SETSIZE) && | 1211 | (cnt < FD_SETSIZE) && |
1210 | (cnt + 4 < FD_SETSIZE) ) | 1212 | (cnt + 4 < FD_SETSIZE) ) |
diff --git a/src/util/strings.c b/src/util/strings.c index b7a7fcb8b..3f85384e1 100644 --- a/src/util/strings.c +++ b/src/util/strings.c | |||
@@ -1262,6 +1262,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, | |||
1262 | int ret; | 1262 | int ret; |
1263 | char *port_colon; | 1263 | char *port_colon; |
1264 | unsigned int port; | 1264 | unsigned int port; |
1265 | char dummy[2]; | ||
1265 | 1266 | ||
1266 | if (addrlen < 6) | 1267 | if (addrlen < 6) |
1267 | return GNUNET_SYSERR; | 1268 | return GNUNET_SYSERR; |
@@ -1286,7 +1287,10 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, | |||
1286 | _("IPv6 address did contain ']' before ':' to separate port number\n")); | 1287 | _("IPv6 address did contain ']' before ':' to separate port number\n")); |
1287 | return GNUNET_SYSERR; | 1288 | return GNUNET_SYSERR; |
1288 | } | 1289 | } |
1289 | ret = SSCANF (port_colon, ":%u", &port); | 1290 | ret = SSCANF (port_colon, |
1291 | ":%u%1s", | ||
1292 | &port, | ||
1293 | dummy); | ||
1290 | if ( (1 != ret) || (port > 65535) ) | 1294 | if ( (1 != ret) || (port > 65535) ) |
1291 | { | 1295 | { |
1292 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1296 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
@@ -1332,16 +1336,18 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, | |||
1332 | unsigned int temps[4]; | 1336 | unsigned int temps[4]; |
1333 | unsigned int port; | 1337 | unsigned int port; |
1334 | unsigned int cnt; | 1338 | unsigned int cnt; |
1339 | char dummy[2]; | ||
1335 | 1340 | ||
1336 | if (addrlen < 9) | 1341 | if (addrlen < 9) |
1337 | return GNUNET_SYSERR; | 1342 | return GNUNET_SYSERR; |
1338 | cnt = SSCANF (zt_addr, | 1343 | cnt = SSCANF (zt_addr, |
1339 | "%u.%u.%u.%u:%u", | 1344 | "%u.%u.%u.%u:%u%1s", |
1340 | &temps[0], | 1345 | &temps[0], |
1341 | &temps[1], | 1346 | &temps[1], |
1342 | &temps[2], | 1347 | &temps[2], |
1343 | &temps[3], | 1348 | &temps[3], |
1344 | &port); | 1349 | &port, |
1350 | dummy); | ||
1345 | if (5 != cnt) | 1351 | if (5 != cnt) |
1346 | return GNUNET_SYSERR; | 1352 | return GNUNET_SYSERR; |
1347 | for (cnt = 0; cnt < 4; cnt++) | 1353 | for (cnt = 0; cnt < 4; cnt++) |
@@ -1563,7 +1569,9 @@ parse_port_policy (const char *port_policy, | |||
1563 | } | 1569 | } |
1564 | if (2 == sscanf (pos, | 1570 | if (2 == sscanf (pos, |
1565 | "%u-%u%1s", | 1571 | "%u-%u%1s", |
1566 | &s, &e, eol)) | 1572 | &s, |
1573 | &e, | ||
1574 | eol)) | ||
1567 | { | 1575 | { |
1568 | if ( (0 == s) || | 1576 | if ( (0 == s) || |
1569 | (s > 0xFFFF) || | 1577 | (s > 0xFFFF) || |
@@ -1629,7 +1637,8 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) | |||
1629 | int colon; | 1637 | int colon; |
1630 | int end; | 1638 | int end; |
1631 | char *routeList; | 1639 | char *routeList; |
1632 | 1640 | char dummy[2]; | |
1641 | |||
1633 | if (NULL == routeListX) | 1642 | if (NULL == routeListX) |
1634 | return NULL; | 1643 | return NULL; |
1635 | len = strlen (routeListX); | 1644 | len = strlen (routeListX); |
@@ -1664,7 +1673,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) | |||
1664 | } | 1673 | } |
1665 | cnt = | 1674 | cnt = |
1666 | SSCANF (&routeList[pos], | 1675 | SSCANF (&routeList[pos], |
1667 | "%u.%u.%u.%u/%u.%u.%u.%u", | 1676 | "%u.%u.%u.%u/%u.%u.%u.%u%1s", |
1668 | &temps[0], | 1677 | &temps[0], |
1669 | &temps[1], | 1678 | &temps[1], |
1670 | &temps[2], | 1679 | &temps[2], |
@@ -1672,7 +1681,8 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) | |||
1672 | &temps[4], | 1681 | &temps[4], |
1673 | &temps[5], | 1682 | &temps[5], |
1674 | &temps[6], | 1683 | &temps[6], |
1675 | &temps[7]); | 1684 | &temps[7], |
1685 | dummy); | ||
1676 | if (8 == cnt) | 1686 | if (8 == cnt) |
1677 | { | 1687 | { |
1678 | for (j = 0; j < 8; j++) | 1688 | for (j = 0; j < 8; j++) |
@@ -1698,12 +1708,13 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) | |||
1698 | /* try second notation */ | 1708 | /* try second notation */ |
1699 | cnt = | 1709 | cnt = |
1700 | SSCANF (&routeList[pos], | 1710 | SSCANF (&routeList[pos], |
1701 | "%u.%u.%u.%u/%u", | 1711 | "%u.%u.%u.%u/%u%1s", |
1702 | &temps[0], | 1712 | &temps[0], |
1703 | &temps[1], | 1713 | &temps[1], |
1704 | &temps[2], | 1714 | &temps[2], |
1705 | &temps[3], | 1715 | &temps[3], |
1706 | &slash); | 1716 | &slash, |
1717 | dummy); | ||
1707 | if (5 == cnt) | 1718 | if (5 == cnt) |
1708 | { | 1719 | { |
1709 | for (j = 0; j < 4; j++) | 1720 | for (j = 0; j < 4; j++) |
@@ -1747,11 +1758,12 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) | |||
1747 | slash = 32; | 1758 | slash = 32; |
1748 | cnt = | 1759 | cnt = |
1749 | SSCANF (&routeList[pos], | 1760 | SSCANF (&routeList[pos], |
1750 | "%u.%u.%u.%u", | 1761 | "%u.%u.%u.%u%1s", |
1751 | &temps[0], | 1762 | &temps[0], |
1752 | &temps[1], | 1763 | &temps[1], |
1753 | &temps[2], | 1764 | &temps[2], |
1754 | &temps[3]); | 1765 | &temps[3], |
1766 | dummy); | ||
1755 | if (4 == cnt) | 1767 | if (4 == cnt) |
1756 | { | 1768 | { |
1757 | for (j = 0; j < 4; j++) | 1769 | for (j = 0; j < 4; j++) |
@@ -1826,7 +1838,8 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) | |||
1826 | unsigned int off; | 1838 | unsigned int off; |
1827 | int save; | 1839 | int save; |
1828 | int colon; | 1840 | int colon; |
1829 | 1841 | char dummy[2]; | |
1842 | |||
1830 | if (NULL == routeListX) | 1843 | if (NULL == routeListX) |
1831 | return NULL; | 1844 | return NULL; |
1832 | len = strlen (routeListX); | 1845 | len = strlen (routeListX); |
@@ -1886,7 +1899,11 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) | |||
1886 | if (ret <= 0) | 1899 | if (ret <= 0) |
1887 | { | 1900 | { |
1888 | save = errno; | 1901 | save = errno; |
1889 | if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128)) | 1902 | if ( (1 != SSCANF (&routeList[slash + 1], |
1903 | "%u%1s", | ||
1904 | &bits, | ||
1905 | dummy)) || | ||
1906 | (bits > 128) ) | ||
1890 | { | 1907 | { |
1891 | if (0 == ret) | 1908 | if (0 == ret) |
1892 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1909 | LOG (GNUNET_ERROR_TYPE_WARNING, |