aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_search.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-12-03 03:11:42 +0000
committerChristian Grothoff <christian@grothoff.org>2010-12-03 03:11:42 +0000
commit03b10ac22fb7e80a02568af591e0ead6c76d8563 (patch)
tree42407bad847b7faa622070975d15cce29a7504d9 /src/fs/fs_search.c
parentb15e5e6fbee9941cd17218771e78412a3b50ed8b (diff)
downloadgnunet-03b10ac22fb7e80a02568af591e0ead6c76d8563.tar.gz
gnunet-03b10ac22fb7e80a02568af591e0ead6c76d8563.zip
air plane hacking
Diffstat (limited to 'src/fs/fs_search.c')
-rw-r--r--src/fs/fs_search.c269
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 */
917static void
918schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc);
919
920
921/**
922 * Closure for 'build_result_set'.
923 */
924struct 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 */
963static int
964build_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 */
998static int
999find_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 */
1148static void
1149schedule_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