diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-12-03 03:11:42 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-12-03 03:11:42 +0000 |
commit | 03b10ac22fb7e80a02568af591e0ead6c76d8563 (patch) | |
tree | 42407bad847b7faa622070975d15cce29a7504d9 /src/fs/fs_search.c | |
parent | b15e5e6fbee9941cd17218771e78412a3b50ed8b (diff) | |
download | gnunet-03b10ac22fb7e80a02568af591e0ead6c76d8563.tar.gz gnunet-03b10ac22fb7e80a02568af591e0ead6c76d8563.zip |
air plane hacking
Diffstat (limited to 'src/fs/fs_search.c')
-rw-r--r-- | src/fs/fs_search.c | 269 |
1 files changed, 205 insertions, 64 deletions
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 1ffd681aa..109fc3272 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c | |||
@@ -22,10 +22,6 @@ | |||
22 | * @file fs/fs_search.c | 22 | * @file fs/fs_search.c |
23 | * @brief Helper functions for searching. | 23 | * @brief Helper functions for searching. |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | ||
26 | * TODO: | ||
27 | * - add support for pushing "already seen" information | ||
28 | * to FS service for bloomfilter (can wait) | ||
29 | */ | 25 | */ |
30 | 26 | ||
31 | #include "platform.h" | 27 | #include "platform.h" |
@@ -913,6 +909,110 @@ receive_results (void *cls, | |||
913 | 909 | ||
914 | 910 | ||
915 | /** | 911 | /** |
912 | * Schedule the transmission of the (next) search request | ||
913 | * to the service. | ||
914 | * | ||
915 | * @param sc context for the search | ||
916 | */ | ||
917 | static void | ||
918 | schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc); | ||
919 | |||
920 | |||
921 | /** | ||
922 | * Closure for 'build_result_set'. | ||
923 | */ | ||
924 | struct MessageBuilderContext | ||
925 | { | ||
926 | /** | ||
927 | * How many entries can we store to xoff. | ||
928 | */ | ||
929 | unsigned int put_cnt; | ||
930 | |||
931 | /** | ||
932 | * How many entries should we skip. | ||
933 | */ | ||
934 | unsigned int skip_cnt; | ||
935 | |||
936 | /** | ||
937 | * Where to store the keys. | ||
938 | */ | ||
939 | GNUNET_HashCode *xoff; | ||
940 | |||
941 | /** | ||
942 | * Search context we are iterating for. | ||
943 | */ | ||
944 | struct GNUNET_FS_SearchContext *sc; | ||
945 | |||
946 | /** | ||
947 | * URI the search result must match, NULL for any | ||
948 | */ | ||
949 | struct GNUNET_FS_Uri *uri; | ||
950 | }; | ||
951 | |||
952 | |||
953 | /** | ||
954 | * Iterating over the known results, pick those | ||
955 | * matching the given result range and store | ||
956 | * their keys at 'xoff'. | ||
957 | * | ||
958 | * @param cls the 'struct MessageBuilderContext' | ||
959 | * @param key key for a result | ||
960 | * @param value the search result | ||
961 | * @return GNUNET_OK to continue iterating | ||
962 | */ | ||
963 | static int | ||
964 | build_result_set (void *cls, | ||
965 | const GNUNET_HashCode *key, | ||
966 | void *value) | ||
967 | { | ||
968 | struct MessageBuilderContext *mbc = cls; | ||
969 | struct GNUNET_FS_SearchResult *sr = value; | ||
970 | |||
971 | if ( (mbc->uri != NULL) && | ||
972 | (GNUNET_YES != GNUNET_FS_uri_test_equal (mbc->uri, | ||
973 | sr->uri)) ) | ||
974 | return GNUNET_OK; | ||
975 | if (mbc->skip_cnt > 0) | ||
976 | { | ||
977 | mbc->skip_cnt--; | ||
978 | return GNUNET_OK; | ||
979 | } | ||
980 | if (mbc->put_cnt == 0) | ||
981 | return GNUNET_SYSERR; | ||
982 | mbc->sc->search_request_map_offset++; | ||
983 | mbc->xoff[--mbc->put_cnt] = *key; | ||
984 | return GNUNET_OK; | ||
985 | } | ||
986 | |||
987 | |||
988 | /** | ||
989 | * Iterating over the known results, count those | ||
990 | * matching the given result range and increment | ||
991 | * put count for each. | ||
992 | * | ||
993 | * @param cls the 'struct MessageBuilderContext' | ||
994 | * @param key key for a result | ||
995 | * @param value the search result | ||
996 | * @return GNUNET_OK to continue iterating | ||
997 | */ | ||
998 | static int | ||
999 | find_result_set (void *cls, | ||
1000 | const GNUNET_HashCode *key, | ||
1001 | void *value) | ||
1002 | { | ||
1003 | struct MessageBuilderContext *mbc = cls; | ||
1004 | struct GNUNET_FS_SearchResult *sr = value; | ||
1005 | |||
1006 | if ( (mbc->uri != NULL) && | ||
1007 | (GNUNET_YES != GNUNET_FS_uri_test_equal (mbc->uri, | ||
1008 | sr->uri)) ) | ||
1009 | return GNUNET_OK; | ||
1010 | mbc->put_cnt++; | ||
1011 | return GNUNET_OK; | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | /** | ||
916 | * We're ready to transmit the search request to the | 1016 | * We're ready to transmit the search request to the |
917 | * file-sharing service. Do it. | 1017 | * file-sharing service. Do it. |
918 | * | 1018 | * |
@@ -927,38 +1027,66 @@ transmit_search_request (void *cls, | |||
927 | void *buf) | 1027 | void *buf) |
928 | { | 1028 | { |
929 | struct GNUNET_FS_SearchContext *sc = cls; | 1029 | struct GNUNET_FS_SearchContext *sc = cls; |
1030 | struct MessageBuilderContext mbc; | ||
930 | size_t msize; | 1031 | size_t msize; |
931 | struct SearchMessage *sm; | 1032 | struct SearchMessage *sm; |
932 | unsigned int i; | ||
933 | const char *identifier; | 1033 | const char *identifier; |
934 | GNUNET_HashCode key; | 1034 | GNUNET_HashCode key; |
935 | GNUNET_HashCode idh; | 1035 | GNUNET_HashCode idh; |
1036 | unsigned int sqms; | ||
936 | 1037 | ||
937 | if (NULL == buf) | 1038 | if (NULL == buf) |
938 | { | 1039 | { |
939 | try_reconnect (sc); | 1040 | try_reconnect (sc); |
940 | return 0; | 1041 | return 0; |
941 | } | 1042 | } |
1043 | mbc.sc = sc; | ||
1044 | mbc.skip_cnt = sc->search_request_map_offset; | ||
1045 | sm = buf; | ||
1046 | sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); | ||
1047 | mbc.xoff = (GNUNET_HashCode* ) &sm[1]; | ||
942 | if (GNUNET_FS_uri_test_ksk (sc->uri)) | 1048 | if (GNUNET_FS_uri_test_ksk (sc->uri)) |
943 | { | 1049 | { |
944 | msize = sizeof (struct SearchMessage) * sc->uri->data.ksk.keywordCount; | 1050 | msize = sizeof (struct SearchMessage); |
945 | GNUNET_assert (size >= msize); | 1051 | GNUNET_assert (size >= msize); |
946 | sm = buf; | 1052 | mbc.uri = NULL; |
947 | memset (sm, 0, msize); | 1053 | mbc.put_cnt = 0; |
948 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) | 1054 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, |
1055 | &find_result_set, | ||
1056 | &mbc); | ||
1057 | sqms = mbc.put_cnt; | ||
1058 | mbc.put_cnt = (size - msize) / sizeof (GNUNET_HashCode); | ||
1059 | mbc.put_cnt = GNUNET_MIN (mbc.put_cnt, | ||
1060 | sqms - mbc.skip_cnt); | ||
1061 | if (sc->search_request_map_offset < sqms) | ||
1062 | GNUNET_assert (mbc.put_cnt > 0); | ||
1063 | |||
1064 | sm->header.size = htons (msize); | ||
1065 | if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) | ||
1066 | sm->options = htonl (1); | ||
1067 | else | ||
1068 | sm->options = htonl (0); | ||
1069 | sm->type = htonl (GNUNET_BLOCK_TYPE_ANY); | ||
1070 | sm->anonymity_level = htonl (sc->anonymity); | ||
1071 | sm->query = sc->requests[sc->keyword_offset].query; | ||
1072 | msize += sizeof (GNUNET_HashCode) * mbc.put_cnt; | ||
1073 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | ||
1074 | &build_result_set, | ||
1075 | &mbc); | ||
1076 | sm->header.size = htons (msize); | ||
1077 | if (sqms != sc->search_request_map_offset) | ||
949 | { | 1078 | { |
950 | sm[i].header.size = htons (sizeof (struct SearchMessage)); | 1079 | /* more requesting to be done... */ |
951 | sm[i].header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); | 1080 | schedule_transmit_search_request (sc); |
952 | if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) | 1081 | return msize; |
953 | sm[i].options = htonl (1); | 1082 | } |
954 | else | 1083 | sc->keyword_offset++; |
955 | sm[i].options = htonl (0); | 1084 | if (sc->uri->data.ksk.keywordCount != |
956 | sm[i].type = htonl (GNUNET_BLOCK_TYPE_ANY); | 1085 | sc->keyword_offset) |
957 | sm[i].anonymity_level = htonl (sc->anonymity); | 1086 | { |
958 | sm[i].query = sc->requests[i].query; | 1087 | /* more requesting to be done... */ |
959 | /* FIXME: should transmit hash codes of all already-known results here! | 1088 | schedule_transmit_search_request (sc); |
960 | (and if they do not fit, add another message with the same | 1089 | return msize; |
961 | header and additional already-seen results!) */ | ||
962 | } | 1090 | } |
963 | } | 1091 | } |
964 | else | 1092 | else |
@@ -966,10 +1094,6 @@ transmit_search_request (void *cls, | |||
966 | GNUNET_assert (GNUNET_FS_uri_test_sks (sc->uri)); | 1094 | GNUNET_assert (GNUNET_FS_uri_test_sks (sc->uri)); |
967 | msize = sizeof (struct SearchMessage); | 1095 | msize = sizeof (struct SearchMessage); |
968 | GNUNET_assert (size >= msize); | 1096 | GNUNET_assert (size >= msize); |
969 | sm = buf; | ||
970 | memset (sm, 0, msize); | ||
971 | sm->header.size = htons (sizeof (struct SearchMessage)); | ||
972 | sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); | ||
973 | if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) | 1097 | if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) |
974 | sm->options = htonl (1); | 1098 | sm->options = htonl (1); |
975 | else | 1099 | else |
@@ -987,10 +1111,26 @@ transmit_search_request (void *cls, | |||
987 | GNUNET_CRYPTO_hash_xor (&idh, | 1111 | GNUNET_CRYPTO_hash_xor (&idh, |
988 | &sm->target, | 1112 | &sm->target, |
989 | &sm->query); | 1113 | &sm->query); |
990 | /* FIXME: should transmit hash codes of all already-known results here! | 1114 | mbc.skip_cnt = sc->search_request_map_offset; |
991 | (and if they do not fit, add another message with the same | 1115 | mbc.put_cnt = (size - msize) / sizeof (GNUNET_HashCode); |
992 | header and additional already-seen results!) */ | 1116 | sqms = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map); |
993 | } | 1117 | mbc.put_cnt = GNUNET_MIN (mbc.put_cnt, |
1118 | sqms - mbc.skip_cnt); | ||
1119 | mbc.uri = NULL; | ||
1120 | if (sc->search_request_map_offset < sqms) | ||
1121 | GNUNET_assert (mbc.put_cnt > 0); | ||
1122 | msize += sizeof (GNUNET_HashCode) * mbc.put_cnt; | ||
1123 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | ||
1124 | &build_result_set, | ||
1125 | &mbc); | ||
1126 | sm->header.size = htons (msize); | ||
1127 | if (sqms != sc->search_request_map_offset) | ||
1128 | { | ||
1129 | /* more requesting to be done... */ | ||
1130 | schedule_transmit_search_request (sc); | ||
1131 | return msize; | ||
1132 | } | ||
1133 | } | ||
994 | GNUNET_CLIENT_receive (sc->client, | 1134 | GNUNET_CLIENT_receive (sc->client, |
995 | &receive_results, | 1135 | &receive_results, |
996 | sc, | 1136 | sc, |
@@ -1000,6 +1140,34 @@ transmit_search_request (void *cls, | |||
1000 | 1140 | ||
1001 | 1141 | ||
1002 | /** | 1142 | /** |
1143 | * Schedule the transmission of the (next) search request | ||
1144 | * to the service. | ||
1145 | * | ||
1146 | * @param sc context for the search | ||
1147 | */ | ||
1148 | static void | ||
1149 | schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc) | ||
1150 | { | ||
1151 | size_t size; | ||
1152 | unsigned int sqms; | ||
1153 | unsigned int fit; | ||
1154 | |||
1155 | size = sizeof (struct SearchMessage); | ||
1156 | sqms = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map) - sc->search_request_map_offset; | ||
1157 | fit = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - size) / sizeof (GNUNET_HashCode); | ||
1158 | fit = GNUNET_MIN (fit, sqms); | ||
1159 | size += sizeof (GNUNET_HashCode) * fit; | ||
1160 | GNUNET_CLIENT_notify_transmit_ready (sc->client, | ||
1161 | size, | ||
1162 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
1163 | GNUNET_NO, | ||
1164 | &transmit_search_request, | ||
1165 | sc); | ||
1166 | |||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /** | ||
1003 | * Reconnect to the FS service and transmit | 1171 | * Reconnect to the FS service and transmit |
1004 | * our queries NOW. | 1172 | * our queries NOW. |
1005 | * | 1173 | * |
@@ -1012,8 +1180,7 @@ do_reconnect (void *cls, | |||
1012 | { | 1180 | { |
1013 | struct GNUNET_FS_SearchContext *sc = cls; | 1181 | struct GNUNET_FS_SearchContext *sc = cls; |
1014 | struct GNUNET_CLIENT_Connection *client; | 1182 | struct GNUNET_CLIENT_Connection *client; |
1015 | size_t size; | 1183 | |
1016 | |||
1017 | sc->task = GNUNET_SCHEDULER_NO_TASK; | 1184 | sc->task = GNUNET_SCHEDULER_NO_TASK; |
1018 | client = GNUNET_CLIENT_connect ("fs", | 1185 | client = GNUNET_CLIENT_connect ("fs", |
1019 | sc->h->cfg); | 1186 | sc->h->cfg); |
@@ -1023,16 +1190,9 @@ do_reconnect (void *cls, | |||
1023 | return; | 1190 | return; |
1024 | } | 1191 | } |
1025 | sc->client = client; | 1192 | sc->client = client; |
1026 | if (GNUNET_FS_uri_test_ksk (sc->uri)) | 1193 | sc->search_request_map_offset = 0; |
1027 | size = sizeof (struct SearchMessage) * sc->uri->data.ksk.keywordCount; | 1194 | sc->keyword_offset = 0; |
1028 | else | 1195 | schedule_transmit_search_request (sc); |
1029 | size = sizeof (struct SearchMessage); | ||
1030 | GNUNET_CLIENT_notify_transmit_ready (client, | ||
1031 | size, | ||
1032 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
1033 | GNUNET_NO, | ||
1034 | &transmit_search_request, | ||
1035 | sc); | ||
1036 | } | 1196 | } |
1037 | 1197 | ||
1038 | 1198 | ||
@@ -1124,33 +1284,19 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) | |||
1124 | GNUNET_HashCode hc; | 1284 | GNUNET_HashCode hc; |
1125 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; | 1285 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; |
1126 | struct GNUNET_CRYPTO_RsaPrivateKey *pk; | 1286 | struct GNUNET_CRYPTO_RsaPrivateKey *pk; |
1127 | size_t size; | ||
1128 | 1287 | ||
1129 | GNUNET_assert (NULL == sc->client); | 1288 | GNUNET_assert (NULL == sc->client); |
1130 | if (GNUNET_FS_uri_test_ksk (sc->uri)) | 1289 | if (GNUNET_FS_uri_test_ksk (sc->uri)) |
1131 | { | 1290 | { |
1132 | size = sizeof (struct SearchMessage) * sc->uri->data.ksk.keywordCount; | ||
1133 | } | ||
1134 | else | ||
1135 | { | ||
1136 | GNUNET_assert (GNUNET_FS_uri_test_sks (sc->uri)); | ||
1137 | size = sizeof (struct SearchMessage); | ||
1138 | } | ||
1139 | if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | ||
1140 | { | ||
1141 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1142 | _("Too many keywords specified for a single search.")); | ||
1143 | return GNUNET_SYSERR; | ||
1144 | } | ||
1145 | if (GNUNET_FS_uri_test_ksk (sc->uri)) | ||
1146 | { | ||
1147 | GNUNET_assert (0 != sc->uri->data.ksk.keywordCount); | 1291 | GNUNET_assert (0 != sc->uri->data.ksk.keywordCount); |
1148 | sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * | 1292 | sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * |
1149 | sc->uri->data.ksk.keywordCount); | 1293 | sc->uri->data.ksk.keywordCount); |
1150 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) | 1294 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) |
1151 | { | 1295 | { |
1152 | keyword = &sc->uri->data.ksk.keywords[i][1]; | 1296 | keyword = &sc->uri->data.ksk.keywords[i][1]; |
1153 | GNUNET_CRYPTO_hash (keyword, strlen (keyword), &hc); | 1297 | GNUNET_CRYPTO_hash (keyword, |
1298 | strlen (keyword), | ||
1299 | &hc); | ||
1154 | pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&hc); | 1300 | pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&hc); |
1155 | GNUNET_assert (pk != NULL); | 1301 | GNUNET_assert (pk != NULL); |
1156 | GNUNET_CRYPTO_rsa_key_get_public (pk, &pub); | 1302 | GNUNET_CRYPTO_rsa_key_get_public (pk, &pub); |
@@ -1171,12 +1317,7 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) | |||
1171 | sc->h->cfg); | 1317 | sc->h->cfg); |
1172 | if (NULL == sc->client) | 1318 | if (NULL == sc->client) |
1173 | return GNUNET_SYSERR; | 1319 | return GNUNET_SYSERR; |
1174 | GNUNET_CLIENT_notify_transmit_ready (sc->client, | 1320 | schedule_transmit_search_request (sc); |
1175 | size, | ||
1176 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
1177 | GNUNET_NO, | ||
1178 | &transmit_search_request, | ||
1179 | sc); | ||
1180 | return GNUNET_OK; | 1321 | return GNUNET_OK; |
1181 | } | 1322 | } |
1182 | 1323 | ||