diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-11-02 11:24:37 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-11-02 11:24:37 +0000 |
commit | 6ee12e6c9d2a7b6596b20b918f761702bfbf05eb (patch) | |
tree | abb298b97798d4ba4d58a94441d0baa03a9d86d6 /src/fs | |
parent | 6c4dab891b8ce1a5a7291d1685b2913412571846 (diff) | |
download | gnunet-6ee12e6c9d2a7b6596b20b918f761702bfbf05eb.tar.gz gnunet-6ee12e6c9d2a7b6596b20b918f761702bfbf05eb.zip |
-fix #3556
Diffstat (limited to 'src/fs')
-rw-r--r-- | src/fs/fs_search.c | 72 |
1 files changed, 42 insertions, 30 deletions
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index be7f4bdc5..c79328834 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2001-2013 Christian Grothoff (and other contributing authors) | 3 | (C) 2001-2014 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -1006,7 +1006,9 @@ struct MessageBuilderContext | |||
1006 | * @return #GNUNET_OK to continue iterating | 1006 | * @return #GNUNET_OK to continue iterating |
1007 | */ | 1007 | */ |
1008 | static int | 1008 | static int |
1009 | build_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) | 1009 | build_result_set (void *cls, |
1010 | const struct GNUNET_HashCode *key, | ||
1011 | void *value) | ||
1010 | { | 1012 | { |
1011 | struct MessageBuilderContext *mbc = cls; | 1013 | struct MessageBuilderContext *mbc = cls; |
1012 | struct GNUNET_FS_SearchResult *sr = value; | 1014 | struct GNUNET_FS_SearchResult *sr = value; |
@@ -1029,9 +1031,8 @@ build_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
1029 | 1031 | ||
1030 | 1032 | ||
1031 | /** | 1033 | /** |
1032 | * Iterating over the known results, count those | 1034 | * Iterating over the known results, count those matching the given |
1033 | * matching the given result range and increment | 1035 | * result range and increment put count for each. |
1034 | * put count for each. | ||
1035 | * | 1036 | * |
1036 | * @param cls the `struct MessageBuilderContext` | 1037 | * @param cls the `struct MessageBuilderContext` |
1037 | * @param key key for a result | 1038 | * @param key key for a result |
@@ -1039,7 +1040,9 @@ build_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
1039 | * @return #GNUNET_OK to continue iterating | 1040 | * @return #GNUNET_OK to continue iterating |
1040 | */ | 1041 | */ |
1041 | static int | 1042 | static int |
1042 | find_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) | 1043 | find_result_set (void *cls, |
1044 | const struct GNUNET_HashCode *key, | ||
1045 | void *value) | ||
1043 | { | 1046 | { |
1044 | struct MessageBuilderContext *mbc = cls; | 1047 | struct MessageBuilderContext *mbc = cls; |
1045 | struct GNUNET_FS_SearchResult *sr = value; | 1048 | struct GNUNET_FS_SearchResult *sr = value; |
@@ -1053,8 +1056,9 @@ find_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
1053 | 1056 | ||
1054 | 1057 | ||
1055 | /** | 1058 | /** |
1056 | * We're ready to transmit the search request to the | 1059 | * We're ready to transmit the search request to the file-sharing |
1057 | * file-sharing service. Do it. | 1060 | * service. Do it. If the request is too large to fit into a single |
1061 | * message, transmit in increments. | ||
1058 | * | 1062 | * |
1059 | * @param cls closure | 1063 | * @param cls closure |
1060 | * @param size number of bytes available in @a buf | 1064 | * @param size number of bytes available in @a buf |
@@ -1069,7 +1073,8 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1069 | size_t msize; | 1073 | size_t msize; |
1070 | struct SearchMessage *sm; | 1074 | struct SearchMessage *sm; |
1071 | struct GNUNET_CRYPTO_EcdsaPublicKey dpub; | 1075 | struct GNUNET_CRYPTO_EcdsaPublicKey dpub; |
1072 | unsigned int sqms; | 1076 | unsigned int total_seen_results; /* total number of result hashes to send */ |
1077 | unsigned int message_size_limit; | ||
1073 | uint32_t options; | 1078 | uint32_t options; |
1074 | 1079 | ||
1075 | if (NULL == buf) | 1080 | if (NULL == buf) |
@@ -1081,7 +1086,7 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1081 | mbc.skip_cnt = sc->search_request_map_offset; | 1086 | mbc.skip_cnt = sc->search_request_map_offset; |
1082 | sm = buf; | 1087 | sm = buf; |
1083 | sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); | 1088 | sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); |
1084 | mbc.xoff = (struct GNUNET_HashCode *) & sm[1]; | 1089 | mbc.xoff = (struct GNUNET_HashCode *) &sm[1]; |
1085 | options = SEARCH_MESSAGE_OPTION_NONE; | 1090 | options = SEARCH_MESSAGE_OPTION_NONE; |
1086 | if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) | 1091 | if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) |
1087 | options |= SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY; | 1092 | options |= SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY; |
@@ -1090,15 +1095,16 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1090 | msize = sizeof (struct SearchMessage); | 1095 | msize = sizeof (struct SearchMessage); |
1091 | GNUNET_assert (size >= msize); | 1096 | GNUNET_assert (size >= msize); |
1092 | mbc.keyword_offset = sc->keyword_offset; | 1097 | mbc.keyword_offset = sc->keyword_offset; |
1093 | /* calculate total number of known results (in put_cnt => sqms) */ | 1098 | /* calculate total number of known results (in put_cnt => total_seen_results) */ |
1094 | mbc.put_cnt = 0; | 1099 | mbc.put_cnt = 0; |
1095 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | 1100 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, |
1096 | &find_result_set, &mbc); | 1101 | &find_result_set, &mbc); |
1097 | sqms = mbc.put_cnt; | 1102 | total_seen_results = mbc.put_cnt; |
1098 | /* calculate how many results we can send in this message */ | 1103 | /* calculate how many results we can send in this message */ |
1099 | mbc.put_cnt = (size - msize) / sizeof (struct GNUNET_HashCode); | 1104 | message_size_limit = (size - msize) / sizeof (struct GNUNET_HashCode); |
1100 | mbc.put_cnt = GNUNET_MIN (mbc.put_cnt, sqms - mbc.skip_cnt); | 1105 | mbc.put_cnt = GNUNET_MIN (message_size_limit, |
1101 | if (sc->search_request_map_offset < sqms) | 1106 | total_seen_results - mbc.skip_cnt); |
1107 | if (sc->search_request_map_offset < total_seen_results) | ||
1102 | GNUNET_assert (mbc.put_cnt > 0); | 1108 | GNUNET_assert (mbc.put_cnt > 0); |
1103 | 1109 | ||
1104 | /* now build message */ | 1110 | /* now build message */ |
@@ -1110,8 +1116,9 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1110 | sm->query = sc->requests[sc->keyword_offset].uquery; | 1116 | sm->query = sc->requests[sc->keyword_offset].uquery; |
1111 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | 1117 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, |
1112 | &build_result_set, &mbc); | 1118 | &build_result_set, &mbc); |
1113 | GNUNET_assert (sqms >= sc->search_request_map_offset); | 1119 | GNUNET_assert (0 == mbc->put_cnt); |
1114 | if (sqms != sc->search_request_map_offset) | 1120 | GNUNET_assert (total_seen_results >= sc->search_request_map_offset); |
1121 | if (total_seen_results != sc->search_request_map_offset) | ||
1115 | { | 1122 | { |
1116 | /* more requesting to be done... */ | 1123 | /* more requesting to be done... */ |
1117 | sm->options = htonl (options | SEARCH_MESSAGE_OPTION_CONTINUED); | 1124 | sm->options = htonl (options | SEARCH_MESSAGE_OPTION_CONTINUED); |
@@ -1120,6 +1127,7 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1120 | } | 1127 | } |
1121 | sm->options = htonl (options); | 1128 | sm->options = htonl (options); |
1122 | sc->keyword_offset++; | 1129 | sc->keyword_offset++; |
1130 | sc->search_request_map_offset = 0; | ||
1123 | if (sc->uri->data.ksk.keywordCount != sc->keyword_offset) | 1131 | if (sc->uri->data.ksk.keywordCount != sc->keyword_offset) |
1124 | { | 1132 | { |
1125 | /* more requesting to be done... */ | 1133 | /* more requesting to be done... */ |
@@ -1142,18 +1150,19 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1142 | GNUNET_CRYPTO_hash (&dpub, | 1150 | GNUNET_CRYPTO_hash (&dpub, |
1143 | sizeof (dpub), | 1151 | sizeof (dpub), |
1144 | &sm->query); | 1152 | &sm->query); |
1145 | mbc.put_cnt = (size - msize) / sizeof (struct GNUNET_HashCode); | 1153 | message_size_limit = (size - msize) / sizeof (struct GNUNET_HashCode); |
1146 | sqms = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map); | 1154 | total_seen_results = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map); |
1147 | mbc.put_cnt = GNUNET_MIN (mbc.put_cnt, sqms - mbc.skip_cnt); | 1155 | mbc.put_cnt = GNUNET_MIN (message_size_limit, |
1156 | total_seen_results - mbc.skip_cnt); | ||
1148 | mbc.keyword_offset = 0; | 1157 | mbc.keyword_offset = 0; |
1149 | if (sc->search_request_map_offset < sqms) | 1158 | if (sc->search_request_map_offset < total_seen_results) |
1150 | GNUNET_assert (mbc.put_cnt > 0); | 1159 | GNUNET_assert (mbc.put_cnt > 0); |
1151 | msize += sizeof (struct GNUNET_HashCode) * mbc.put_cnt; | 1160 | msize += sizeof (struct GNUNET_HashCode) * mbc.put_cnt; |
1152 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | 1161 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, |
1153 | &build_result_set, &mbc); | 1162 | &build_result_set, &mbc); |
1154 | sm->header.size = htons (msize); | 1163 | sm->header.size = htons (msize); |
1155 | GNUNET_assert (sqms >= sc->search_request_map_offset); | 1164 | GNUNET_assert (total_seen_results >= sc->search_request_map_offset); |
1156 | if (sqms != sc->search_request_map_offset) | 1165 | if (total_seen_results != sc->search_request_map_offset) |
1157 | { | 1166 | { |
1158 | /* more requesting to be done... */ | 1167 | /* more requesting to be done... */ |
1159 | sm->options = htonl (options | SEARCH_MESSAGE_OPTION_CONTINUED); | 1168 | sm->options = htonl (options | SEARCH_MESSAGE_OPTION_CONTINUED); |
@@ -1162,7 +1171,8 @@ transmit_search_request (void *cls, size_t size, void *buf) | |||
1162 | } | 1171 | } |
1163 | sm->options = htonl (options); | 1172 | sm->options = htonl (options); |
1164 | } | 1173 | } |
1165 | GNUNET_CLIENT_receive (sc->client, &receive_results, sc, | 1174 | GNUNET_CLIENT_receive (sc->client, |
1175 | &receive_results, sc, | ||
1166 | GNUNET_TIME_UNIT_FOREVER_REL); | 1176 | GNUNET_TIME_UNIT_FOREVER_REL); |
1167 | return msize; | 1177 | return msize; |
1168 | } | 1178 | } |
@@ -1178,20 +1188,21 @@ static void | |||
1178 | schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc) | 1188 | schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc) |
1179 | { | 1189 | { |
1180 | size_t size; | 1190 | size_t size; |
1181 | unsigned int sqms; | 1191 | unsigned int left; |
1182 | unsigned int fit; | 1192 | unsigned int fit; |
1193 | unsigned int request; | ||
1183 | 1194 | ||
1184 | size = sizeof (struct SearchMessage); | 1195 | size = sizeof (struct SearchMessage); |
1185 | sqms = | 1196 | left = |
1186 | GNUNET_CONTAINER_multihashmap_size (sc->master_result_map) - | 1197 | GNUNET_CONTAINER_multihashmap_size (sc->master_result_map) - |
1187 | sc->search_request_map_offset; | 1198 | sc->search_request_map_offset; |
1188 | fit = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - size) / sizeof (struct GNUNET_HashCode); | 1199 | fit = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - size) / sizeof (struct GNUNET_HashCode); |
1189 | fit = GNUNET_MIN (fit, sqms); | 1200 | request = GNUNET_MIN (fit, left); |
1190 | size += sizeof (struct GNUNET_HashCode) * fit; | 1201 | size += sizeof (struct GNUNET_HashCode) * request; |
1191 | GNUNET_CLIENT_notify_transmit_ready (sc->client, size, | 1202 | GNUNET_CLIENT_notify_transmit_ready (sc->client, size, |
1192 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | 1203 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, |
1193 | GNUNET_NO, &transmit_search_request, sc); | 1204 | GNUNET_NO, |
1194 | 1205 | &transmit_search_request, sc); | |
1195 | } | 1206 | } |
1196 | 1207 | ||
1197 | 1208 | ||
@@ -1374,6 +1385,7 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) | |||
1374 | sc->client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); | 1385 | sc->client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); |
1375 | if (NULL == sc->client) | 1386 | if (NULL == sc->client) |
1376 | return GNUNET_SYSERR; | 1387 | return GNUNET_SYSERR; |
1388 | sc->search_request_map_offset = 0; | ||
1377 | schedule_transmit_search_request (sc); | 1389 | schedule_transmit_search_request (sc); |
1378 | return GNUNET_OK; | 1390 | return GNUNET_OK; |
1379 | } | 1391 | } |