aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cadet/.gitignore4
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c7
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c7
-rwxr-xr-xsrc/gns/test_gns_cname_lookup.sh3
-rwxr-xr-xsrc/gns/test_gns_mx_lookup.sh4
-rw-r--r--src/include/gnunet_container_lib.h17
-rw-r--r--src/include/gnunet_core_service.h4
-rw-r--r--src/include/gnunet_protocols.h57
-rw-r--r--src/include/gnunet_transport_communication_service.h14
-rw-r--r--src/namestore/gnunet-service-namestore.c15
-rw-r--r--src/namestore/namestore_api.c81
-rw-r--r--src/namestore/namestore_api_monitor.c3
-rw-r--r--src/namestore/plugin_namestore_sqlite.c16
-rw-r--r--src/rps/Makefile.am1
-rw-r--r--src/rps/gnunet-rps-profiler.c12
-rw-r--r--src/rps/gnunet-service-rps.c164
-rw-r--r--src/rps/rps_api.c1
-rw-r--r--src/transport/transport.h257
-rw-r--r--src/transport/transport_api2_communication.c959
-rw-r--r--src/util/configuration.c25
-rw-r--r--src/util/container_multihashmap.c210
-rw-r--r--src/util/container_multihashmap32.c169
-rw-r--r--src/util/container_multipeermap.c282
-rw-r--r--src/util/container_multishortmap.c286
-rw-r--r--src/util/getopt.c8
-rw-r--r--src/util/getopt_helpers.c25
-rw-r--r--src/util/service.c8
-rw-r--r--src/util/strings.c43
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
21test_cadet_single 21test_cadet_single
22gnunet-service-cadet-new 22gnunet-service-cadet-new
23test_cadet_local_mq 23test_cadet_local_mq
24test_cadet_*_new \ No newline at end of file 24test_cadet_*_newtest_cadet_2_reopen
25test_cadet_5_reopen
26test_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
54gnunet-arm -e -c test_gns_lookup.conf 54gnunet-arm -e -c test_gns_lookup.conf
55rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` 55rm -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
58RES_CNAME_RAW=`echo $RES_CNAME_RAW | tr [A-Z] [a-z]`
59TESTEGOZONE=`echo $TESTEGOZONE | tr [A-Z] [a-z]`
57if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ] 60if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ]
58then 61then
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
31gnunet-arm -e -c test_gns_lookup.conf 31gnunet-arm -e -c test_gns_lookup.conf
32rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` 32rm -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
35RES_MX=`echo $RES_MX | tr [A-Z] [a-z]`
36WANT_MX=`echo $WANT_MX | tr [A-Z] [a-z]`
37
34if [ "$RES_MX" == "$WANT_MX" ] 38if [ "$RES_MX" == "$WANT_MX" ]
35then 39then
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 */
930int 930int
931GNUNET_CONTAINER_multihashmap_iterate (const struct GNUNET_CONTAINER_MultiHashMap *map, 931GNUNET_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 */
995int 995int
996GNUNET_CONTAINER_multihashmap_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap *map, 996GNUNET_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 */
1196int 1196int
1197GNUNET_CONTAINER_multipeermap_iterate (const struct GNUNET_CONTAINER_MultiPeerMap *map, 1197GNUNET_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 */
1262int 1262int
1263GNUNET_CONTAINER_multipeermap_get_multiple (const struct GNUNET_CONTAINER_MultiPeerMap *map, 1263GNUNET_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 */
1463int 1463int
1464GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map, 1464GNUNET_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 */
1531int 1531int
1532GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map, 1532GNUNET_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 */
1650int 1650int
1651GNUNET_CONTAINER_multihashmap32_iterate (const struct 1651GNUNET_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 */
1752int 1751int
1753GNUNET_CONTAINER_multihashmap32_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap32 *map, 1752GNUNET_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 */
92typedef void * 94typedef 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 */
104typedef void 108typedef 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 */
143int 143int
144GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, 144GNUNET_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 */
172struct GNUNET_TRANSPORT_QueueHandle * 172struct GNUNET_TRANSPORT_QueueHandle *
173GNUNET_TRANSPORT_communicator_mq_add (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, 173GNUNET_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 */
206struct GNUNET_TRANSPORT_AddressIdentifier * 206struct GNUNET_TRANSPORT_AddressIdentifier *
207GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorHandle *handle, 207GNUNET_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
523check_record_result (void *cls, 523check_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
566handle_record_result (void *cls, 574handle_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 */
650static void
651handle_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;
447struct GNUNET_CADET_Handle *cadet_handle; 448struct GNUNET_CADET_Handle *cadet_handle;
448 449
449/** 450/**
451 * Handle to CORE
452 */
453struct GNUNET_CORE_Handle *core_handle;
454
455/**
456 * @brief PeerMap to keep track of connected peers.
457 */
458struct GNUNET_CONTAINER_MultiPeerMap *map_single_hop;
459
460/**
450 * Our own identity. 461 * Our own identity.
451 */ 462 */
452static struct GNUNET_PeerIdentity own_identity; 463static 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 */
770static const struct GNUNET_PeerIdentity * 781static const struct GNUNET_PeerIdentity *
771get_random_peer_from_peermap (const struct 782get_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 */
1644static int 1661static int
1645get_valid_peers (const struct GNUNET_CONTAINER_MultiPeerMap *valid_peers, 1662get_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 */
2151static void 2168static void
2152insert_in_view_op (void *cls, 2169insert_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 */
3010void
3011core_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 */
3029void *
3030core_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 */
3051void
3052core_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 */
659struct 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 */
689struct 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 */
708struct 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 */
739struct 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 */
768struct 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 */
798struct 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 */
822struct 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 */
847struct 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 */
877struct 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
647GNUNET_NETWORK_STRUCT_END 904GNUNET_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 */
42struct 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 */
80struct 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 */
107struct 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 */
203struct 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 */
242struct 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 */
290static void
291reconnect (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 */
300static void
301send_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 */
327static void
328send_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 */
349static void
350send_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 */
377static void
378send_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 */
402static void
403disconnect (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 */
440static void
441error_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 */
461static void
462handle_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 */
500static int
501check_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 */
523static void
524handle_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 */
551static int
552check_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 */
576static void
577send_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 */
601static void
602send_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 */
624static void
625handle_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 */
673static void
674reconnect (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 */
721struct GNUNET_TRANSPORT_CommunicatorHandle *
722GNUNET_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 */
757void
758GNUNET_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 */
790int
791GNUNET_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 */
863struct GNUNET_TRANSPORT_QueueHandle *
864GNUNET_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 */
893void
894GNUNET_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 */
917struct GNUNET_TRANSPORT_AddressIdentifier *
918GNUNET_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 */
945void
946GNUNET_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 */
895int 895int
896GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle 896GNUNET_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 */
921int 926int
922GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle 927GNUNET_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 */
32struct BigMapEntry 41struct 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
132struct GNUNET_CONTAINER_MultiHashMapIterator 154struct 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 */
215void 237void
216GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap 238GNUNET_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 */
331int 357int
332GNUNET_CONTAINER_multihashmap_iterate (const struct 358GNUNET_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 */
430static void
431update_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 */
447static void
448update_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 */
633int 717int
634GNUNET_CONTAINER_multihashmap_contains_value (const struct 718GNUNET_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 */
816int 903int
817GNUNET_CONTAINER_multihashmap_get_multiple (const struct 904GNUNET_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
87struct GNUNET_CONTAINER_MultiHashMap32Iterator 109struct 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 */
137void 160void
138GNUNET_CONTAINER_multihashmap32_destroy (struct GNUNET_CONTAINER_MultiHashMap32 161GNUNET_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
165idx_of (const struct GNUNET_CONTAINER_MultiHashMap32 *m, 186idx_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 */
179unsigned int 200unsigned int
180GNUNET_CONTAINER_multihashmap32_size (const struct 201GNUNET_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 */
197void * 217void *
198GNUNET_CONTAINER_multihashmap32_get (const struct 218GNUNET_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 */
224int 243int
225GNUNET_CONTAINER_multihashmap32_iterate (const struct 244GNUNET_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 */
288static void
289update_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 */
266int 309int
267GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 310GNUNET_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 */
307int 352int
308GNUNET_CONTAINER_multihashmap32_remove_all (struct 353GNUNET_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 */
359int 404int
360GNUNET_CONTAINER_multihashmap32_contains (const struct 405GNUNET_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 */
387int 431int
388GNUNET_CONTAINER_multihashmap32_contains_value (const struct 432GNUNET_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 */
457int 499int
@@ -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 */
508int 550int
509GNUNET_CONTAINER_multihashmap32_get_multiple (const struct 551GNUNET_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 */
546struct GNUNET_CONTAINER_MultiHashMap32Iterator * 597struct GNUNET_CONTAINER_MultiHashMap32Iterator *
547GNUNET_CONTAINER_multihashmap32_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap32 *map) 598GNUNET_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 */
32struct BigMapEntry 40struct 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 */
193void 215void
194GNUNET_CONTAINER_multipeermap_destroy (struct GNUNET_CONTAINER_MultiPeerMap 216GNUNET_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 */
260unsigned int 283unsigned int
261GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap 284GNUNET_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 */
278void * 300void *
279GNUNET_CONTAINER_multipeermap_get (const struct GNUNET_CONTAINER_MultiPeerMap 301GNUNET_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 */
314int 336int
315GNUNET_CONTAINER_multipeermap_iterate (const struct 337GNUNET_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 */
409static void
410update_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 */
426static void
427update_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 */
381int 447int
@@ -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 */
449int 516int
450GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap 517GNUNET_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 */
535int 610int
536GNUNET_CONTAINER_multipeermap_contains (const struct 611GNUNET_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 */
573int 643int
574GNUNET_CONTAINER_multipeermap_contains_value (const struct 644GNUNET_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 */
670int 740int
@@ -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 */
751int 821int
752GNUNET_CONTAINER_multipeermap_get_multiple (const struct GNUNET_CONTAINER_MultiPeerMap *map, 822GNUNET_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 */
32struct BigMapEntry 41struct 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 */
193void 217void
194GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap 218GNUNET_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 */
313int 336int
314GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map, 337GNUNET_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 */
407static void
408update_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 */
424static void
425update_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 */
666int 739int
@@ -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 */
747int 820int
748GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map, 821GNUNET_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 */
871int 871int
872GNUNET_GETOPT_run (const char *binaryOptions, 872GNUNET_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,