diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-09-05 13:19:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-09-05 13:19:01 +0000 |
commit | 32e19a47f4e6bd369e99e3d292be7b01c009edac (patch) | |
tree | 7a43fdac918d23415b515d47ff837c28ede108fd /src | |
parent | 3de7118c925ac03b973655af6bfedc606aa097b4 (diff) | |
download | gnunet-32e19a47f4e6bd369e99e3d292be7b01c009edac.tar.gz gnunet-32e19a47f4e6bd369e99e3d292be7b01c009edac.zip |
seach
Diffstat (limited to 'src')
-rw-r--r-- | src/fs/fs.h | 120 | ||||
-rw-r--r-- | src/fs/fs_search.c | 449 | ||||
-rw-r--r-- | src/include/gnunet_container_lib.h | 7 | ||||
-rw-r--r-- | src/include/gnunet_fs_service.h | 41 | ||||
-rw-r--r-- | src/util/container_multihashmap.c | 2 |
5 files changed, 541 insertions, 78 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h index 6e793bf8d..ed925d9c8 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -382,6 +382,12 @@ struct GNUNET_FS_Handle | |||
382 | */ | 382 | */ |
383 | struct GNUNET_CLIENT_Connection *client; | 383 | struct GNUNET_CLIENT_Connection *client; |
384 | 384 | ||
385 | /** | ||
386 | * How many downloads probing availability | ||
387 | * of search results do we have running | ||
388 | * right now? | ||
389 | */ | ||
390 | unsigned int active_probes; | ||
385 | 391 | ||
386 | }; | 392 | }; |
387 | 393 | ||
@@ -583,6 +589,72 @@ struct GNUNET_FS_UnindexContext | |||
583 | 589 | ||
584 | 590 | ||
585 | /** | 591 | /** |
592 | * Information we store for each search result. | ||
593 | */ | ||
594 | struct SearchResult | ||
595 | { | ||
596 | |||
597 | /** | ||
598 | * URI to which this search result | ||
599 | * refers to. | ||
600 | */ | ||
601 | struct GNUNET_FS_Uri *uri; | ||
602 | |||
603 | /** | ||
604 | * Metadata for the search result. | ||
605 | */ | ||
606 | struct GNUNET_CONTAINER_MetaData *meta; | ||
607 | |||
608 | /** | ||
609 | * Client info for this search result. | ||
610 | */ | ||
611 | void *client_info; | ||
612 | |||
613 | /** | ||
614 | * ID of a job that is currently probing | ||
615 | * this results' availability (NULL if we | ||
616 | * are not currently probing). | ||
617 | */ | ||
618 | struct GNUNET_FS_DownloadContext *probe_ctx; | ||
619 | |||
620 | /** | ||
621 | * ID of the task that will clean up the probe_ctx | ||
622 | * should it not complete on time (and that will | ||
623 | * need to be cancelled if we clean up the search | ||
624 | * result before then). | ||
625 | */ | ||
626 | GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; | ||
627 | |||
628 | /** | ||
629 | * Number of mandatory keywords for which | ||
630 | * we have NOT yet found the search result; | ||
631 | * when this value hits zero, the search | ||
632 | * result is given to the callback. | ||
633 | */ | ||
634 | uint32_t mandatory_missing; | ||
635 | |||
636 | /** | ||
637 | * Number of optional keywords under which | ||
638 | * this result was also found. | ||
639 | */ | ||
640 | uint32_t optional_support; | ||
641 | |||
642 | /** | ||
643 | * Number of availability tests that | ||
644 | * have succeeded for this result. | ||
645 | */ | ||
646 | uint32_t availability_success; | ||
647 | |||
648 | /** | ||
649 | * Number of availability trials that we | ||
650 | * have performed for this search result. | ||
651 | */ | ||
652 | uint32_t availability_trials; | ||
653 | |||
654 | }; | ||
655 | |||
656 | |||
657 | /** | ||
586 | * Information we keep for each keyword in | 658 | * Information we keep for each keyword in |
587 | * a keyword search. | 659 | * a keyword search. |
588 | */ | 660 | */ |
@@ -597,7 +669,24 @@ struct SearchRequestEntry | |||
597 | /** | 669 | /** |
598 | * Hash of the public key, also known as the query. | 670 | * Hash of the public key, also known as the query. |
599 | */ | 671 | */ |
600 | GNUNET_HashCode query; | 672 | GNUNET_HashCode query; |
673 | |||
674 | /** | ||
675 | * Map that contains a "struct SearchResult" for each result that | ||
676 | * was found under this keyword. Note that the entries will point | ||
677 | * to the same locations as those in the master result map (in | ||
678 | * "struct GNUNET_FS_SearchContext"), so they should not be freed. | ||
679 | * The key for each entry is the XOR of the key and query in the CHK | ||
680 | * URI (as a unique identifier for the search result). | ||
681 | */ | ||
682 | struct GNUNET_CONTAINER_MultiHashMap *results; | ||
683 | |||
684 | /** | ||
685 | * Is this keyword a mandatory keyword | ||
686 | * (started with '+')? | ||
687 | */ | ||
688 | int mandatory; | ||
689 | |||
601 | }; | 690 | }; |
602 | 691 | ||
603 | 692 | ||
@@ -617,12 +706,34 @@ struct GNUNET_FS_SearchContext | |||
617 | struct GNUNET_FS_Uri *uri; | 706 | struct GNUNET_FS_Uri *uri; |
618 | 707 | ||
619 | /** | 708 | /** |
709 | * For update-searches, link to the | ||
710 | * base-SKS search that triggered the | ||
711 | * update search; otherwise NULL. | ||
712 | */ | ||
713 | struct GNUNET_FS_SearchContext *parent; | ||
714 | |||
715 | /** | ||
620 | * Connection to the FS service. | 716 | * Connection to the FS service. |
621 | */ | 717 | */ |
622 | struct GNUNET_CLIENT_Connection *client; | 718 | struct GNUNET_CLIENT_Connection *client; |
623 | 719 | ||
624 | /** | 720 | /** |
721 | * Pointer we keep for the client. | ||
722 | */ | ||
723 | void *client_info; | ||
724 | |||
725 | /** | ||
726 | * Map that contains a "struct SearchResult" for each result that | ||
727 | * was found in the search. The key for each entry is the XOR of | ||
728 | * the key and query in the CHK URI (as a unique identifier for the | ||
729 | * search result). | ||
730 | */ | ||
731 | struct GNUNET_CONTAINER_MultiHashMap *master_result_map; | ||
732 | |||
733 | /** | ||
625 | * Per-keyword information for a keyword search. | 734 | * Per-keyword information for a keyword search. |
735 | * This array will have exactly as many entries | ||
736 | * as there were keywords. | ||
626 | */ | 737 | */ |
627 | struct SearchRequestEntry *requests; | 738 | struct SearchRequestEntry *requests; |
628 | 739 | ||
@@ -644,9 +755,12 @@ struct GNUNET_FS_SearchContext | |||
644 | /** | 755 | /** |
645 | * Anonymity level for the search. | 756 | * Anonymity level for the search. |
646 | */ | 757 | */ |
647 | unsigned int anonymity; | 758 | uint32_t anonymity; |
648 | |||
649 | 759 | ||
760 | /** | ||
761 | * Number of mandatory keywords in this query. | ||
762 | */ | ||
763 | uint32_t mandatory_count; | ||
650 | }; | 764 | }; |
651 | 765 | ||
652 | 766 | ||
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index e855a4d30..109a76791 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c | |||
@@ -24,9 +24,10 @@ | |||
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | 25 | * |
26 | * TODO: | 26 | * TODO: |
27 | * - aggregate and process results (FSUI-style) | 27 | * - handle SKS updates searches nicely (can wait) |
28 | * - call progress callbacks | 28 | * - handle availability probes (can wait) |
29 | * - make operations persistent (can wait) | 29 | * - make operations persistent (can wait) |
30 | * - handle namespace advertisements (can wait) | ||
30 | * - add support for pushing "already seen" information | 31 | * - add support for pushing "already seen" information |
31 | * to FS service for bloomfilter (can wait) | 32 | * to FS service for bloomfilter (can wait) |
32 | */ | 33 | */ |
@@ -40,6 +41,150 @@ | |||
40 | #define DEBUG_SEARCH GNUNET_YES | 41 | #define DEBUG_SEARCH GNUNET_YES |
41 | 42 | ||
42 | 43 | ||
44 | |||
45 | /** | ||
46 | * Fill in all of the generic fields for | ||
47 | * a search event. | ||
48 | * | ||
49 | * @param pc structure to fill in | ||
50 | * @param sc overall search context | ||
51 | */ | ||
52 | static void | ||
53 | make_search_status (struct GNUNET_FS_ProgressInfo *pi, | ||
54 | struct GNUNET_FS_SearchContext *sc) | ||
55 | { | ||
56 | pi->value.search.sc = sc; | ||
57 | pi->value.search.cctx | ||
58 | = sc->client_info; | ||
59 | pi->value.search.pctx | ||
60 | = (sc->parent == NULL) ? NULL : sc->parent->client_info; | ||
61 | pi->value.search.query | ||
62 | = sc->uri; | ||
63 | pi->value.search.duration = GNUNET_TIME_absolute_get_duration (sc->start_time); | ||
64 | pi->value.search.anonymity = sc->anonymity; | ||
65 | } | ||
66 | |||
67 | |||
68 | /** | ||
69 | * Check if the given result is identical | ||
70 | * to the given URI. | ||
71 | * | ||
72 | * @param cls points to the URI we check against | ||
73 | * @param key not used | ||
74 | * @param value a "struct SearchResult" who's URI we | ||
75 | * should compare with | ||
76 | * @return GNUNET_SYSERR if the result is present, | ||
77 | * GNUNET_OK otherwise | ||
78 | */ | ||
79 | static int | ||
80 | test_result_present (void *cls, | ||
81 | const GNUNET_HashCode * key, | ||
82 | void *value) | ||
83 | { | ||
84 | const struct GNUNET_FS_Uri *uri = cls; | ||
85 | struct SearchResult *sr = value; | ||
86 | |||
87 | if (GNUNET_FS_uri_test_equal (uri, | ||
88 | sr->uri)) | ||
89 | return GNUNET_SYSERR; | ||
90 | return GNUNET_OK; | ||
91 | } | ||
92 | |||
93 | |||
94 | /** | ||
95 | * We've found a new CHK result. Let the client | ||
96 | * know about it. | ||
97 | * | ||
98 | * @param sc the search context | ||
99 | * @param sr the specific result | ||
100 | */ | ||
101 | static void | ||
102 | notify_client_chk_result (struct GNUNET_FS_SearchContext *sc, | ||
103 | struct SearchResult *sr) | ||
104 | { | ||
105 | struct GNUNET_FS_ProgressInfo pi; | ||
106 | |||
107 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT; | ||
108 | make_search_status (&pi, sc); | ||
109 | pi.value.search.specifics.result.meta = sr->meta; | ||
110 | pi.value.search.specifics.result.uri = sr->uri; | ||
111 | sr->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
112 | &pi); | ||
113 | } | ||
114 | |||
115 | |||
116 | /** | ||
117 | * We've found new information about an existing CHK result. Let the | ||
118 | * client know about it. | ||
119 | * | ||
120 | * @param sc the search context | ||
121 | * @param sr the specific result | ||
122 | */ | ||
123 | static void | ||
124 | notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, | ||
125 | struct SearchResult *sr) | ||
126 | { | ||
127 | struct GNUNET_FS_ProgressInfo pi; | ||
128 | |||
129 | pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; | ||
130 | make_search_status (&pi, sc); | ||
131 | pi.value.search.specifics.update.cctx = sr->client_info; | ||
132 | pi.value.search.specifics.update.meta = sr->meta; | ||
133 | pi.value.search.specifics.update.uri = sr->uri; | ||
134 | pi.value.search.specifics.update.availability_rank | ||
135 | = 2*sr->availability_success - sr->availability_trials; | ||
136 | pi.value.search.specifics.update.availability_certainty | ||
137 | = sr->availability_trials; | ||
138 | pi.value.search.specifics.update.applicability_rank | ||
139 | = sr->optional_support; | ||
140 | sr->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
141 | &pi); | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Context for "get_result_present". | ||
147 | */ | ||
148 | struct GetResultContext | ||
149 | { | ||
150 | /** | ||
151 | * The URI we're looking for. | ||
152 | */ | ||
153 | const struct GNUNET_FS_Uri *uri; | ||
154 | |||
155 | /** | ||
156 | * Where to store a pointer to the search | ||
157 | * result struct if we found a match. | ||
158 | */ | ||
159 | struct SearchResult *sr; | ||
160 | }; | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Check if the given result is identical | ||
165 | * to the given URI and if so return it. | ||
166 | * | ||
167 | * @param cls a "struct GetResultContext" | ||
168 | * @param key not used | ||
169 | * @param value a "struct SearchResult" who's URI we | ||
170 | * should compare with | ||
171 | * @return GNUNET_OK | ||
172 | */ | ||
173 | static int | ||
174 | get_result_present (void *cls, | ||
175 | const GNUNET_HashCode * key, | ||
176 | void *value) | ||
177 | { | ||
178 | struct GetResultContext *grc = cls; | ||
179 | struct SearchResult *sr = value; | ||
180 | |||
181 | if (GNUNET_FS_uri_test_equal (grc->uri, | ||
182 | sr->uri)) | ||
183 | grc->sr = sr; | ||
184 | return GNUNET_OK; | ||
185 | } | ||
186 | |||
187 | |||
43 | /** | 188 | /** |
44 | * We have received a KSK result. Check | 189 | * We have received a KSK result. Check |
45 | * how it fits in with the overall query | 190 | * how it fits in with the overall query |
@@ -57,13 +202,83 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, | |||
57 | const struct GNUNET_FS_Uri *uri, | 202 | const struct GNUNET_FS_Uri *uri, |
58 | const struct GNUNET_CONTAINER_MetaData *meta) | 203 | const struct GNUNET_CONTAINER_MetaData *meta) |
59 | { | 204 | { |
60 | // FIXME: check if new | 205 | GNUNET_HashCode key; |
61 | // FIXME: check if mandatory satisfied | 206 | struct SearchResult *sr; |
62 | // FIXME: notify client! | 207 | struct GetResultContext grc; |
208 | int is_new; | ||
209 | |||
210 | /* check if new */ | ||
211 | if (! GNUNET_FS_uri_test_ksk (uri)) | ||
212 | { | ||
213 | GNUNET_break_op (0); | ||
214 | return; | ||
215 | } | ||
216 | GNUNET_CRYPTO_hash_xor (&uri->data.chk.chk.key, | ||
217 | &uri->data.chk.chk.query, | ||
218 | &key); | ||
219 | if (GNUNET_SYSERR == | ||
220 | GNUNET_CONTAINER_multihashmap_get_multiple (ent->results, | ||
221 | &key, | ||
222 | &test_result_present, | ||
223 | (void*) uri)) | ||
224 | return; /* duplicate result */ | ||
225 | /* try to find search result in master map */ | ||
226 | grc.sr = NULL; | ||
227 | grc.uri = uri; | ||
228 | GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, | ||
229 | &key, | ||
230 | &get_result_present, | ||
231 | &grc); | ||
232 | sr = grc.sr; | ||
233 | is_new = (NULL == sr) || (sr->mandatory_missing > 0); | ||
234 | if (NULL == sr) | ||
235 | { | ||
236 | sr = GNUNET_malloc (sizeof (struct SearchResult)); | ||
237 | sr->uri = GNUNET_FS_uri_dup (uri); | ||
238 | sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); | ||
239 | sr->mandatory_missing = sc->mandatory_count; | ||
240 | GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, | ||
241 | &key, | ||
242 | sr, | ||
243 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | /* FIXME: consider combining the meta data */ | ||
248 | } | ||
249 | /* check if mandatory satisfied */ | ||
250 | if (ent->mandatory) | ||
251 | sr->mandatory_missing--; | ||
252 | else | ||
253 | sr->optional_support++; | ||
254 | if (0 != sr->mandatory_missing) | ||
255 | return; | ||
256 | if (is_new) | ||
257 | notify_client_chk_result (sc, sr); | ||
258 | else | ||
259 | notify_client_chk_update (sc, sr); | ||
260 | /* FIXME: consider starting probes for "sr" */ | ||
63 | } | 261 | } |
64 | 262 | ||
65 | 263 | ||
66 | /** | 264 | /** |
265 | * Start search for content, internal API. | ||
266 | * | ||
267 | * @param h handle to the file sharing subsystem | ||
268 | * @param uri specifies the search parameters; can be | ||
269 | * a KSK URI or an SKS URI. | ||
270 | * @param anonymity desired level of anonymity | ||
271 | * @param parent parent search (for namespace update searches) | ||
272 | * @return context that can be used to control the search | ||
273 | */ | ||
274 | static struct GNUNET_FS_SearchContext * | ||
275 | search_start (struct GNUNET_FS_Handle *h, | ||
276 | const struct GNUNET_FS_Uri *uri, | ||
277 | unsigned int anonymity, | ||
278 | struct GNUNET_FS_SearchContext *parent); | ||
279 | |||
280 | |||
281 | /** | ||
67 | * We have received an SKS result. Start | 282 | * We have received an SKS result. Start |
68 | * searching for updates and notify the | 283 | * searching for updates and notify the |
69 | * client if it is a new result. | 284 | * client if it is a new result. |
@@ -79,21 +294,49 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, | |||
79 | const struct GNUNET_FS_Uri *uri, | 294 | const struct GNUNET_FS_Uri *uri, |
80 | const struct GNUNET_CONTAINER_MetaData *meta) | 295 | const struct GNUNET_CONTAINER_MetaData *meta) |
81 | { | 296 | { |
82 | // FIXME: check if new | 297 | struct GNUNET_FS_Uri uu; |
83 | // FIXME: notify client | 298 | GNUNET_HashCode key; |
299 | struct SearchResult *sr; | ||
84 | 300 | ||
85 | if (strlen (id_update) > 0) | 301 | /* check if new */ |
302 | if (! GNUNET_FS_uri_test_ksk (uri)) | ||
86 | { | 303 | { |
87 | // FIXME: search for updates! | 304 | GNUNET_break_op (0); |
88 | #if 0 | 305 | return; |
89 | updateURI.type = sks; | ||
90 | GNUNET_hash (&sb->subspace, | ||
91 | sizeof (GNUNET_RSA_PublicKey), | ||
92 | &updateURI.data.sks.namespace); | ||
93 | updateURI.data.sks.identifier = GNUNET_strdup (id); | ||
94 | add_search_for_uri (&updateURI, sqc); | ||
95 | #endif | ||
96 | } | 306 | } |
307 | GNUNET_CRYPTO_hash_xor (&uri->data.chk.chk.key, | ||
308 | &uri->data.chk.chk.query, | ||
309 | &key); | ||
310 | if (GNUNET_SYSERR == | ||
311 | GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, | ||
312 | &key, | ||
313 | &test_result_present, | ||
314 | (void*) uri)) | ||
315 | return; /* duplicate result */ | ||
316 | sr = GNUNET_malloc (sizeof (struct SearchResult)); | ||
317 | sr->uri = GNUNET_FS_uri_dup (uri); | ||
318 | sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); | ||
319 | GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, | ||
320 | &key, | ||
321 | sr, | ||
322 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
323 | /* FIXME: consider starting probes for "sr" */ | ||
324 | |||
325 | /* notify client */ | ||
326 | notify_client_chk_result (sc, sr); | ||
327 | /* search for updates */ | ||
328 | if (strlen (id_update) == 0) | ||
329 | return; /* no updates */ | ||
330 | uu.type = sks; | ||
331 | uu.data.sks.namespace = sc->uri->data.sks.namespace; | ||
332 | uu.data.sks.identifier = GNUNET_strdup (id_update); | ||
333 | /* FIXME: should attach update search | ||
334 | to the individual result, not | ||
335 | the entire SKS search! */ | ||
336 | search_start (sc->h, | ||
337 | &uu, | ||
338 | sc->anonymity, | ||
339 | sc); | ||
97 | } | 340 | } |
98 | 341 | ||
99 | 342 | ||
@@ -371,12 +614,8 @@ transmit_search_request (void *cls, | |||
371 | size_t msize; | 614 | size_t msize; |
372 | struct SearchMessage *sm; | 615 | struct SearchMessage *sm; |
373 | unsigned int i; | 616 | unsigned int i; |
374 | const char *keyword; | ||
375 | const char *identifier; | 617 | const char *identifier; |
376 | GNUNET_HashCode idh; | 618 | GNUNET_HashCode idh; |
377 | GNUNET_HashCode hc; | ||
378 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; | ||
379 | struct GNUNET_CRYPTO_RsaPrivateKey *pk; | ||
380 | 619 | ||
381 | if (NULL == buf) | 620 | if (NULL == buf) |
382 | { | 621 | { |
@@ -389,26 +628,12 @@ transmit_search_request (void *cls, | |||
389 | GNUNET_assert (size >= msize); | 628 | GNUNET_assert (size >= msize); |
390 | sm = buf; | 629 | sm = buf; |
391 | memset (sm, 0, msize); | 630 | memset (sm, 0, msize); |
392 | sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * | ||
393 | sc->uri->data.ksk.keywordCount); | ||
394 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) | 631 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) |
395 | { | 632 | { |
396 | sm[i].header.size = htons (sizeof (struct SearchMessage)); | 633 | sm[i].header.size = htons (sizeof (struct SearchMessage)); |
397 | sm[i].header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); | 634 | sm[i].header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); |
398 | sm[i].anonymity_level = htonl (sc->anonymity); | 635 | sm[i].anonymity_level = htonl (sc->anonymity); |
399 | keyword = &sc->uri->data.ksk.keywords[i][1]; | 636 | sm[i].query = sc->requests[i].query; |
400 | |||
401 | GNUNET_CRYPTO_hash (keyword, strlen (keyword), &hc); | ||
402 | pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&hc); | ||
403 | GNUNET_CRYPTO_rsa_key_get_public (pk, &pub); | ||
404 | GNUNET_CRYPTO_rsa_key_free (pk); | ||
405 | GNUNET_CRYPTO_hash (&pub, | ||
406 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
407 | &sm[i].query); | ||
408 | sc->requests[i].query = sm[i].query; | ||
409 | GNUNET_CRYPTO_hash (keyword, | ||
410 | strlen (keyword), | ||
411 | &sc->requests[i].key); | ||
412 | } | 637 | } |
413 | } | 638 | } |
414 | else | 639 | else |
@@ -501,22 +726,30 @@ try_reconnect (struct GNUNET_FS_SearchContext *sc) | |||
501 | 726 | ||
502 | 727 | ||
503 | /** | 728 | /** |
504 | * Start search for content. | 729 | * Start search for content, internal API. |
505 | * | 730 | * |
506 | * @param h handle to the file sharing subsystem | 731 | * @param h handle to the file sharing subsystem |
507 | * @param uri specifies the search parameters; can be | 732 | * @param uri specifies the search parameters; can be |
508 | * a KSK URI or an SKS URI. | 733 | * a KSK URI or an SKS URI. |
509 | * @param anonymity desired level of anonymity | 734 | * @param anonymity desired level of anonymity |
735 | * @param parent parent search (for namespace update searches) | ||
510 | * @return context that can be used to control the search | 736 | * @return context that can be used to control the search |
511 | */ | 737 | */ |
512 | struct GNUNET_FS_SearchContext * | 738 | static struct GNUNET_FS_SearchContext * |
513 | GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, | 739 | search_start (struct GNUNET_FS_Handle *h, |
514 | const struct GNUNET_FS_Uri *uri, | 740 | const struct GNUNET_FS_Uri *uri, |
515 | unsigned int anonymity) | 741 | unsigned int anonymity, |
742 | struct GNUNET_FS_SearchContext *parent) | ||
516 | { | 743 | { |
517 | struct GNUNET_FS_SearchContext *sc; | 744 | struct GNUNET_FS_SearchContext *sc; |
518 | struct GNUNET_CLIENT_Connection *client; | 745 | struct GNUNET_CLIENT_Connection *client; |
746 | struct GNUNET_FS_ProgressInfo pi; | ||
519 | size_t size; | 747 | size_t size; |
748 | unsigned int i; | ||
749 | const char *keyword; | ||
750 | GNUNET_HashCode hc; | ||
751 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; | ||
752 | struct GNUNET_CRYPTO_RsaPrivateKey *pk; | ||
520 | 753 | ||
521 | if (GNUNET_FS_uri_test_ksk (uri)) | 754 | if (GNUNET_FS_uri_test_ksk (uri)) |
522 | { | 755 | { |
@@ -544,7 +777,38 @@ GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, | |||
544 | sc->anonymity = anonymity; | 777 | sc->anonymity = anonymity; |
545 | sc->start_time = GNUNET_TIME_absolute_get (); | 778 | sc->start_time = GNUNET_TIME_absolute_get (); |
546 | sc->client = client; | 779 | sc->client = client; |
547 | // FIXME: call callback! | 780 | sc->parent = parent; |
781 | sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16); | ||
782 | |||
783 | sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * | ||
784 | sc->uri->data.ksk.keywordCount); | ||
785 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) | ||
786 | { | ||
787 | keyword = &sc->uri->data.ksk.keywords[i][1]; | ||
788 | GNUNET_CRYPTO_hash (keyword, strlen (keyword), &hc); | ||
789 | pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&hc); | ||
790 | GNUNET_CRYPTO_rsa_key_get_public (pk, &pub); | ||
791 | GNUNET_CRYPTO_rsa_key_free (pk); | ||
792 | GNUNET_CRYPTO_hash (&pub, | ||
793 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
794 | &sc->requests[i].query); | ||
795 | sc->requests[i].mandatory = (sc->uri->data.ksk.keywords[i][0] == '+'); | ||
796 | if (sc->requests[i].mandatory) | ||
797 | sc->mandatory_count++; | ||
798 | sc->requests[i].results = GNUNET_CONTAINER_multihashmap_create (4); | ||
799 | GNUNET_CRYPTO_hash (keyword, | ||
800 | strlen (keyword), | ||
801 | &sc->requests[i].key); | ||
802 | } | ||
803 | if (NULL != parent) | ||
804 | { | ||
805 | // FIXME: need to track children | ||
806 | // in parent in case parent is stopped! | ||
807 | } | ||
808 | pi.status = GNUNET_FS_STATUS_SEARCH_START; | ||
809 | make_search_status (&pi, sc); | ||
810 | sc->client_info = h->upcb (h->upcb_cls, | ||
811 | &pi); | ||
548 | GNUNET_CLIENT_notify_transmit_ready (client, | 812 | GNUNET_CLIENT_notify_transmit_ready (client, |
549 | size, | 813 | size, |
550 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | 814 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, |
@@ -555,6 +819,24 @@ GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, | |||
555 | 819 | ||
556 | 820 | ||
557 | /** | 821 | /** |
822 | * Start search for content. | ||
823 | * | ||
824 | * @param h handle to the file sharing subsystem | ||
825 | * @param uri specifies the search parameters; can be | ||
826 | * a KSK URI or an SKS URI. | ||
827 | * @param anonymity desired level of anonymity | ||
828 | * @return context that can be used to control the search | ||
829 | */ | ||
830 | struct GNUNET_FS_SearchContext * | ||
831 | GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, | ||
832 | const struct GNUNET_FS_Uri *uri, | ||
833 | unsigned int anonymity) | ||
834 | { | ||
835 | return search_start (h, uri, anonymity, NULL); | ||
836 | } | ||
837 | |||
838 | |||
839 | /** | ||
558 | * Pause search. | 840 | * Pause search. |
559 | * | 841 | * |
560 | * @param sc context for the search that should be paused | 842 | * @param sc context for the search that should be paused |
@@ -562,6 +844,8 @@ GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, | |||
562 | void | 844 | void |
563 | GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) | 845 | GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) |
564 | { | 846 | { |
847 | struct GNUNET_FS_ProgressInfo pi; | ||
848 | |||
565 | if (sc->task != GNUNET_SCHEDULER_NO_TASK) | 849 | if (sc->task != GNUNET_SCHEDULER_NO_TASK) |
566 | GNUNET_SCHEDULER_cancel (sc->h->sched, | 850 | GNUNET_SCHEDULER_cancel (sc->h->sched, |
567 | sc->task); | 851 | sc->task); |
@@ -570,7 +854,11 @@ GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) | |||
570 | GNUNET_CLIENT_disconnect (sc->client); | 854 | GNUNET_CLIENT_disconnect (sc->client); |
571 | sc->client = NULL; | 855 | sc->client = NULL; |
572 | // FIXME: make persistent! | 856 | // FIXME: make persistent! |
573 | // FIXME: call callback! | 857 | // FIXME: should this freeze all active probes? |
858 | pi.status = GNUNET_FS_STATUS_SEARCH_PAUSED; | ||
859 | make_search_status (&pi, sc); | ||
860 | sc->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
861 | &pi); | ||
574 | } | 862 | } |
575 | 863 | ||
576 | 864 | ||
@@ -582,11 +870,64 @@ GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) | |||
582 | void | 870 | void |
583 | GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) | 871 | GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) |
584 | { | 872 | { |
873 | struct GNUNET_FS_ProgressInfo pi; | ||
874 | |||
585 | GNUNET_assert (sc->client == NULL); | 875 | GNUNET_assert (sc->client == NULL); |
586 | GNUNET_assert (sc->task == GNUNET_SCHEDULER_NO_TASK); | 876 | GNUNET_assert (sc->task == GNUNET_SCHEDULER_NO_TASK); |
587 | do_reconnect (sc, NULL); | 877 | do_reconnect (sc, NULL); |
588 | // FIXME: make persistent! | 878 | // FIXME: make persistent! |
589 | // FIXME: call callback! | 879 | pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; |
880 | make_search_status (&pi, sc); | ||
881 | sc->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
882 | &pi); | ||
883 | } | ||
884 | |||
885 | |||
886 | /** | ||
887 | * Free the given search result. | ||
888 | * | ||
889 | * @param cls the global FS handle | ||
890 | * @param key the key for the search result (unused) | ||
891 | * @param value the search result to free | ||
892 | * @return GNUNET_OK | ||
893 | */ | ||
894 | static int | ||
895 | search_result_free (void *cls, | ||
896 | const GNUNET_HashCode * key, | ||
897 | void *value) | ||
898 | { | ||
899 | struct GNUNET_FS_SearchContext *sc = cls; | ||
900 | struct GNUNET_FS_Handle *h = sc->h; | ||
901 | struct SearchResult *sr = value; | ||
902 | struct GNUNET_FS_ProgressInfo pi; | ||
903 | |||
904 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; | ||
905 | make_search_status (&pi, sc); | ||
906 | pi.value.search.specifics.result_stopped.cctx = sr->client_info; | ||
907 | pi.value.search.specifics.result_stopped.meta = sr->meta; | ||
908 | pi.value.search.specifics.result_stopped.uri = sr->uri; | ||
909 | sr->client_info = h->upcb (h->upcb_cls, | ||
910 | &pi); | ||
911 | GNUNET_break (NULL == sr->client_info); | ||
912 | |||
913 | GNUNET_FS_uri_destroy (sr->uri); | ||
914 | GNUNET_CONTAINER_meta_data_destroy (sr->meta); | ||
915 | if (sr->probe_ctx != NULL) | ||
916 | { | ||
917 | GNUNET_FS_file_download_stop (sr->probe_ctx, GNUNET_YES); | ||
918 | h->active_probes--; | ||
919 | /* FIXME: trigger starting of new | ||
920 | probes here!? Maybe not -- could | ||
921 | cause new probes to be immediately | ||
922 | stopped again... */ | ||
923 | } | ||
924 | if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) | ||
925 | { | ||
926 | GNUNET_SCHEDULER_cancel (h->sched, | ||
927 | sr->probe_cancel_task); | ||
928 | } | ||
929 | GNUNET_free (sr); | ||
930 | return GNUNET_OK; | ||
590 | } | 931 | } |
591 | 932 | ||
592 | 933 | ||
@@ -598,13 +939,31 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) | |||
598 | void | 939 | void |
599 | GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) | 940 | GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) |
600 | { | 941 | { |
942 | struct GNUNET_FS_ProgressInfo pi; | ||
943 | unsigned int i; | ||
944 | |||
601 | // FIXME: make un-persistent! | 945 | // FIXME: make un-persistent! |
602 | // FIXME: call callback! | 946 | if (NULL != sc->parent) |
947 | { | ||
948 | // FIXME: need to untrack sc | ||
949 | // in parent! | ||
950 | } | ||
951 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | ||
952 | &search_result_free, | ||
953 | sc); | ||
954 | pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; | ||
955 | make_search_status (&pi, sc); | ||
956 | sc->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
957 | &pi); | ||
958 | GNUNET_break (NULL == sc->client_info); | ||
603 | if (sc->task != GNUNET_SCHEDULER_NO_TASK) | 959 | if (sc->task != GNUNET_SCHEDULER_NO_TASK) |
604 | GNUNET_SCHEDULER_cancel (sc->h->sched, | 960 | GNUNET_SCHEDULER_cancel (sc->h->sched, |
605 | sc->task); | 961 | sc->task); |
606 | if (NULL != sc->client) | 962 | if (NULL != sc->client) |
607 | GNUNET_CLIENT_disconnect (sc->client); | 963 | GNUNET_CLIENT_disconnect (sc->client); |
964 | GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); | ||
965 | for (i=0;i<sc->uri->data.ksk.keywordCount;i++) | ||
966 | GNUNET_CONTAINER_multihashmap_destroy (sc->requests[i].results); | ||
608 | GNUNET_free_non_null (sc->requests); | 967 | GNUNET_free_non_null (sc->requests); |
609 | GNUNET_FS_uri_destroy (sc->uri); | 968 | GNUNET_FS_uri_destroy (sc->uri); |
610 | GNUNET_free (sc); | 969 | GNUNET_free (sc); |
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h index 087324174..279d7df59 100644 --- a/src/include/gnunet_container_lib.h +++ b/src/include/gnunet_container_lib.h | |||
@@ -455,15 +455,16 @@ enum GNUNET_CONTAINER_MultiHashMapOption | |||
455 | /** | 455 | /** |
456 | * Iterator over HashCodes. | 456 | * Iterator over HashCodes. |
457 | * | 457 | * |
458 | * @param cls closure | ||
458 | * @param key current key code | 459 | * @param key current key code |
459 | * @param value value in the hash map | 460 | * @param value value in the hash map |
460 | * @param cls client-defined argument | ||
461 | * @return GNUNET_YES if we should continue to | 461 | * @return GNUNET_YES if we should continue to |
462 | * iterate, | 462 | * iterate, |
463 | * GNUNET_NO if not. | 463 | * GNUNET_NO if not. |
464 | */ | 464 | */ |
465 | typedef int (*GNUNET_CONTAINER_HashMapIterator) (const GNUNET_HashCode * key, | 465 | typedef int (*GNUNET_CONTAINER_HashMapIterator) (void *cls, |
466 | void *value, void *cls); | 466 | const GNUNET_HashCode * key, |
467 | void *value); | ||
467 | 468 | ||
468 | 469 | ||
469 | /** | 470 | /** |
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index e8b8d0ba0..15aa85aa0 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h | |||
@@ -748,7 +748,7 @@ struct GNUNET_FS_ProgressInfo | |||
748 | /** | 748 | /** |
749 | * What anonymity level is used for this upload? | 749 | * What anonymity level is used for this upload? |
750 | */ | 750 | */ |
751 | unsigned int anonymity; | 751 | uint32_t anonymity; |
752 | 752 | ||
753 | /** | 753 | /** |
754 | * Additional values for specific events. | 754 | * Additional values for specific events. |
@@ -891,7 +891,7 @@ struct GNUNET_FS_ProgressInfo | |||
891 | /** | 891 | /** |
892 | * What anonymity level is used for this download? | 892 | * What anonymity level is used for this download? |
893 | */ | 893 | */ |
894 | unsigned int anonymity; | 894 | uint32_t anonymity; |
895 | 895 | ||
896 | /** | 896 | /** |
897 | * Additional values for specific events. | 897 | * Additional values for specific events. |
@@ -927,11 +927,6 @@ struct GNUNET_FS_ProgressInfo | |||
927 | */ | 927 | */ |
928 | unsigned int depth; | 928 | unsigned int depth; |
929 | 929 | ||
930 | /** | ||
931 | * Amount of trust we offered to get the block. | ||
932 | */ | ||
933 | unsigned int trust_offered; | ||
934 | |||
935 | } progress; | 930 | } progress; |
936 | 931 | ||
937 | /** | 932 | /** |
@@ -1027,13 +1022,7 @@ struct GNUNET_FS_ProgressInfo | |||
1027 | /** | 1022 | /** |
1028 | * What anonymity level is used for this search? | 1023 | * What anonymity level is used for this search? |
1029 | */ | 1024 | */ |
1030 | unsigned int anonymity; | 1025 | uint32_t anonymity; |
1031 | |||
1032 | /** | ||
1033 | * How much trust have we been offering for this search | ||
1034 | * so far? | ||
1035 | */ | ||
1036 | unsigned int trust_offered; | ||
1037 | 1026 | ||
1038 | /** | 1027 | /** |
1039 | * Additional values for specific events. | 1028 | * Additional values for specific events. |
@@ -1049,7 +1038,7 @@ struct GNUNET_FS_ProgressInfo | |||
1049 | /** | 1038 | /** |
1050 | * Metadata for the search result. | 1039 | * Metadata for the search result. |
1051 | */ | 1040 | */ |
1052 | const struct GNUNET_MetaData *meta; | 1041 | const struct GNUNET_CONTAINER_MetaData *meta; |
1053 | 1042 | ||
1054 | /** | 1043 | /** |
1055 | * URI for the search result. | 1044 | * URI for the search result. |
@@ -1067,7 +1056,7 @@ struct GNUNET_FS_ProgressInfo | |||
1067 | /** | 1056 | /** |
1068 | * Metadata for the search result. | 1057 | * Metadata for the search result. |
1069 | */ | 1058 | */ |
1070 | const struct GNUNET_MetaData *meta; | 1059 | const struct GNUNET_CONTAINER_MetaData *meta; |
1071 | 1060 | ||
1072 | /** | 1061 | /** |
1073 | * URI for the search result. | 1062 | * URI for the search result. |
@@ -1078,20 +1067,20 @@ struct GNUNET_FS_ProgressInfo | |||
1078 | * Current availability rank (negative: | 1067 | * Current availability rank (negative: |
1079 | * unavailable, positive: available) | 1068 | * unavailable, positive: available) |
1080 | */ | 1069 | */ |
1081 | int availability_rank; | 1070 | int32_t availability_rank; |
1082 | 1071 | ||
1083 | /** | 1072 | /** |
1084 | * On how many total queries is the given | 1073 | * On how many total queries is the given |
1085 | * availability_rank based? | 1074 | * availability_rank based? |
1086 | */ | 1075 | */ |
1087 | unsigned int availabiliy_certainty; | 1076 | uint32_t availabiliy_certainty; |
1088 | 1077 | ||
1089 | /** | 1078 | /** |
1090 | * Updated applicability rank (the larger, | 1079 | * Updated applicability rank (the larger, |
1091 | * the better the result fits the search | 1080 | * the better the result fits the search |
1092 | * criteria). | 1081 | * criteria). |
1093 | */ | 1082 | */ |
1094 | unsigned int applicabiliy_rank; | 1083 | uint32_t applicabiliy_rank; |
1095 | 1084 | ||
1096 | } resume_result; | 1085 | } resume_result; |
1097 | 1086 | ||
@@ -1110,7 +1099,7 @@ struct GNUNET_FS_ProgressInfo | |||
1110 | /** | 1099 | /** |
1111 | * Metadata for the search result. | 1100 | * Metadata for the search result. |
1112 | */ | 1101 | */ |
1113 | const struct GNUNET_MetaData *meta; | 1102 | const struct GNUNET_CONTAINER_MetaData *meta; |
1114 | 1103 | ||
1115 | /** | 1104 | /** |
1116 | * URI for the search result. | 1105 | * URI for the search result. |
@@ -1121,20 +1110,20 @@ struct GNUNET_FS_ProgressInfo | |||
1121 | * Current availability rank (negative: | 1110 | * Current availability rank (negative: |
1122 | * unavailable, positive: available) | 1111 | * unavailable, positive: available) |
1123 | */ | 1112 | */ |
1124 | int availability_rank; | 1113 | int32_t availability_rank; |
1125 | 1114 | ||
1126 | /** | 1115 | /** |
1127 | * On how many total queries is the given | 1116 | * On how many total queries is the given |
1128 | * availability_rank based? | 1117 | * availability_rank based? |
1129 | */ | 1118 | */ |
1130 | unsigned int availabiliy_certainty; | 1119 | uint32_t availability_certainty; |
1131 | 1120 | ||
1132 | /** | 1121 | /** |
1133 | * Updated applicability rank (the larger, | 1122 | * Updated applicability rank (the larger, |
1134 | * the better the result fits the search | 1123 | * the better the result fits the search |
1135 | * criteria). | 1124 | * criteria). |
1136 | */ | 1125 | */ |
1137 | unsigned int applicabiliy_rank; | 1126 | uint32_t applicability_rank; |
1138 | 1127 | ||
1139 | } update; | 1128 | } update; |
1140 | 1129 | ||
@@ -1158,7 +1147,7 @@ struct GNUNET_FS_ProgressInfo | |||
1158 | /** | 1147 | /** |
1159 | * Metadata for the search result. | 1148 | * Metadata for the search result. |
1160 | */ | 1149 | */ |
1161 | const struct GNUNET_MetaData *meta; | 1150 | const struct GNUNET_CONTAINER_MetaData *meta; |
1162 | 1151 | ||
1163 | /** | 1152 | /** |
1164 | * URI for the search result. | 1153 | * URI for the search result. |
@@ -1187,7 +1176,7 @@ struct GNUNET_FS_ProgressInfo | |||
1187 | /** | 1176 | /** |
1188 | * Metadata for the search result. | 1177 | * Metadata for the search result. |
1189 | */ | 1178 | */ |
1190 | const struct GNUNET_MetaData *meta; | 1179 | const struct GNUNET_CONTAINER_MetaData *meta; |
1191 | 1180 | ||
1192 | /** | 1181 | /** |
1193 | * URI for the search result. | 1182 | * URI for the search result. |
@@ -1228,7 +1217,7 @@ struct GNUNET_FS_ProgressInfo | |||
1228 | } error; | 1217 | } error; |
1229 | 1218 | ||
1230 | /** | 1219 | /** |
1231 | * Values for all "GNUNET_FS_STATUS_RESULT_NAMESPACE" events. | 1220 | * Values for all "GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE" events. |
1232 | */ | 1221 | */ |
1233 | struct { | 1222 | struct { |
1234 | 1223 | ||
diff --git a/src/util/container_multihashmap.c b/src/util/container_multihashmap.c index a84955eb3..410564a48 100644 --- a/src/util/container_multihashmap.c +++ b/src/util/container_multihashmap.c | |||
@@ -123,7 +123,7 @@ GNUNET_CONTAINER_multihashmap_iterate (const struct | |||
123 | e = map->map[i]; | 123 | e = map->map[i]; |
124 | while (e != NULL) | 124 | while (e != NULL) |
125 | { | 125 | { |
126 | if ((NULL != it) && (GNUNET_OK != it (&e->key, e->value, cls))) | 126 | if ((NULL != it) && (GNUNET_OK != it (cls, &e->key, e->value))) |
127 | return GNUNET_SYSERR; | 127 | return GNUNET_SYSERR; |
128 | count++; | 128 | count++; |
129 | e = e->next; | 129 | e = e->next; |