diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-09-05 20:40:29 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-09-05 20:40:29 +0000 |
commit | 0b90310c9a26ffa0e195759b7a5d5c07fa33f642 (patch) | |
tree | de64994c81c9b7490b7fb4a6a7f64b664896227f /src | |
parent | ba388145e2a982d25fb27af1ea80231625f56ded (diff) | |
download | gnunet-0b90310c9a26ffa0e195759b7a5d5c07fa33f642.tar.gz gnunet-0b90310c9a26ffa0e195759b7a5d5c07fa33f642.zip |
towards having download
Diffstat (limited to 'src')
-rw-r--r-- | src/fs/fs.h | 155 | ||||
-rw-r--r-- | src/fs/fs_download.c | 386 |
2 files changed, 508 insertions, 33 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h index ed925d9c8..3dc60a5dc 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -337,12 +337,12 @@ struct GNUNET_FS_FileInformation | |||
337 | /** | 337 | /** |
338 | * Desired anonymity level. | 338 | * Desired anonymity level. |
339 | */ | 339 | */ |
340 | unsigned int anonymity; | 340 | uint32_t anonymity; |
341 | 341 | ||
342 | /** | 342 | /** |
343 | * Desired priority (for keeping the content in the DB). | 343 | * Desired priority (for keeping the content in the DB). |
344 | */ | 344 | */ |
345 | unsigned int priority; | 345 | uint32_t priority; |
346 | 346 | ||
347 | }; | 347 | }; |
348 | 348 | ||
@@ -428,12 +428,6 @@ struct GNUNET_FS_PublishContext | |||
428 | char *nuid; | 428 | char *nuid; |
429 | 429 | ||
430 | /** | 430 | /** |
431 | * ID of the task performing the upload. NO_TASK | ||
432 | * if the upload has completed. | ||
433 | */ | ||
434 | GNUNET_SCHEDULER_TaskIdentifier upload_task; | ||
435 | |||
436 | /** | ||
437 | * Our own client handle for the FS service; | 431 | * Our own client handle for the FS service; |
438 | * only briefly used when we start to index a | 432 | * only briefly used when we start to index a |
439 | * file, otherwise NULL. | 433 | * file, otherwise NULL. |
@@ -441,6 +435,23 @@ struct GNUNET_FS_PublishContext | |||
441 | struct GNUNET_CLIENT_Connection *client; | 435 | struct GNUNET_CLIENT_Connection *client; |
442 | 436 | ||
443 | /** | 437 | /** |
438 | * Current position in the file-tree for the | ||
439 | * upload. | ||
440 | */ | ||
441 | struct GNUNET_FS_FileInformation *fi_pos; | ||
442 | |||
443 | /** | ||
444 | * Connection to the datastore service. | ||
445 | */ | ||
446 | struct GNUNET_DATASTORE_Handle *dsh; | ||
447 | |||
448 | /** | ||
449 | * ID of the task performing the upload. NO_TASK | ||
450 | * if the upload has completed. | ||
451 | */ | ||
452 | GNUNET_SCHEDULER_TaskIdentifier upload_task; | ||
453 | |||
454 | /** | ||
444 | * Typically GNUNET_NO. Set to GNUNET_YES if | 455 | * Typically GNUNET_NO. Set to GNUNET_YES if |
445 | * "upload_task" is GNUNET_SCHEDULER_NO_TASK | 456 | * "upload_task" is GNUNET_SCHEDULER_NO_TASK |
446 | * and we're waiting for a response from the | 457 | * and we're waiting for a response from the |
@@ -461,17 +472,6 @@ struct GNUNET_FS_PublishContext | |||
461 | enum GNUNET_FS_PublishOptions options; | 472 | enum GNUNET_FS_PublishOptions options; |
462 | 473 | ||
463 | /** | 474 | /** |
464 | * Current position in the file-tree for the | ||
465 | * upload. | ||
466 | */ | ||
467 | struct GNUNET_FS_FileInformation *fi_pos; | ||
468 | |||
469 | /** | ||
470 | * Connection to the datastore service. | ||
471 | */ | ||
472 | struct GNUNET_DATASTORE_Handle *dsh; | ||
473 | |||
474 | /** | ||
475 | * Space reservation ID with datastore service | 475 | * Space reservation ID with datastore service |
476 | * for this upload. | 476 | * for this upload. |
477 | */ | 477 | */ |
@@ -765,10 +765,127 @@ struct GNUNET_FS_SearchContext | |||
765 | 765 | ||
766 | 766 | ||
767 | /** | 767 | /** |
768 | * Information about an active download request. | ||
769 | */ | ||
770 | struct DownloadRequest | ||
771 | { | ||
772 | /** | ||
773 | * While pending, we keep all download requests | ||
774 | * in a linked list. | ||
775 | */ | ||
776 | struct DownloadRequest *next; | ||
777 | |||
778 | /** | ||
779 | * CHK for the request. | ||
780 | */ | ||
781 | struct ContentHashKey chk; | ||
782 | |||
783 | /** | ||
784 | * Offset of the corresponding block. | ||
785 | */ | ||
786 | uint64_t offset; | ||
787 | |||
788 | /** | ||
789 | * Depth of the corresponding block in the tree. | ||
790 | */ | ||
791 | unsigned int depth; | ||
792 | |||
793 | /** | ||
794 | * Set if this request is currently in the linked list of pending | ||
795 | * requests. Needed in case we get a response for a request that we | ||
796 | * have not yet send (due to FS bug or two blocks with identical | ||
797 | * content); in this case, we would need to remove the block from | ||
798 | * the pending list (and need a fast way to check if the block is on | ||
799 | * it). | ||
800 | */ | ||
801 | int is_pending; | ||
802 | |||
803 | }; | ||
804 | |||
805 | |||
806 | /** | ||
768 | * Context for controlling a download. | 807 | * Context for controlling a download. |
769 | */ | 808 | */ |
770 | struct GNUNET_FS_DownloadContext | 809 | struct GNUNET_FS_DownloadContext |
771 | { | 810 | { |
811 | |||
812 | /** | ||
813 | * Global FS context. | ||
814 | */ | ||
815 | struct GNUNET_FS_Handle *h; | ||
816 | |||
817 | /** | ||
818 | * Connection to the FS service. | ||
819 | */ | ||
820 | struct GNUNET_CLIENT_Connection *client; | ||
821 | |||
822 | /** | ||
823 | * Parent download (used when downloading files | ||
824 | * in directories). | ||
825 | */ | ||
826 | struct GNUNET_FS_DownloadContext *parent; | ||
827 | |||
828 | /** | ||
829 | * Context kept for the client. | ||
830 | */ | ||
831 | void *client_info; | ||
832 | |||
833 | /** | ||
834 | * URI that identifies the file that | ||
835 | * we are downloading. | ||
836 | */ | ||
837 | struct GNUNET_FS_Uri *uri; | ||
838 | |||
839 | /** | ||
840 | * Where are we writing the data (name of the | ||
841 | * file, can be NULL!). | ||
842 | */ | ||
843 | char *filename; | ||
844 | |||
845 | /** | ||
846 | * Map of active requests (those waiting | ||
847 | * for a response). The key is the hash | ||
848 | * of the encryped block (aka query). | ||
849 | */ | ||
850 | struct GNUNET_CONTAINER_MultiHashMap *active; | ||
851 | |||
852 | /** | ||
853 | * Linked list of pending requests. | ||
854 | */ | ||
855 | struct DownloadRequest *pending; | ||
856 | |||
857 | /** | ||
858 | * ID of a task that is using this struct | ||
859 | * and that must be cancelled when the download | ||
860 | * is being stopped (if not GNUNET_SCHEDULER_NO_TASK). | ||
861 | * Used for the task that adds some artificial | ||
862 | * delay when trying to reconnect to the FS | ||
863 | * service. | ||
864 | */ | ||
865 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
866 | |||
867 | /** | ||
868 | * What is the first offset that we're interested | ||
869 | * in? | ||
870 | */ | ||
871 | uint64_t offset; | ||
872 | |||
873 | /** | ||
874 | * How many bytes starting from offset are desired? | ||
875 | * This is NOT the overall length of the file! | ||
876 | */ | ||
877 | uint64_t length; | ||
878 | |||
879 | /** | ||
880 | * Desired level of anonymity. | ||
881 | */ | ||
882 | uint32_t anonymity; | ||
883 | |||
884 | /** | ||
885 | * Options for the download. | ||
886 | */ | ||
887 | enum GNUNET_FS_DownloadOptions options; | ||
888 | |||
772 | }; | 889 | }; |
773 | 890 | ||
774 | struct GNUNET_FS_Namespace | 891 | struct GNUNET_FS_Namespace |
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index f1954ea89..06c4672a2 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors) | 3 | (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 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 |
@@ -19,17 +19,288 @@ | |||
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file fs/fs_download.c | 21 | * @file fs/fs_download.c |
22 | * @brief DOWNLOAD helper methods (which do the real work). | 22 | * @brief download methods |
23 | * @author Christian Grothoff | 23 | * @author Christian Grothoff |
24 | * | ||
25 | * TODO: | ||
26 | * - process replies | ||
27 | * - callback signaling | ||
28 | * - location URI suppport (can wait) | ||
29 | * - persistence (can wait) | ||
24 | */ | 30 | */ |
25 | |||
26 | #include "platform.h" | 31 | #include "platform.h" |
32 | #include "gnunet_constants.h" | ||
27 | #include "gnunet_fs_service.h" | 33 | #include "gnunet_fs_service.h" |
28 | #include "fs.h" | 34 | #include "fs.h" |
29 | 35 | ||
30 | #define DEBUG_DOWNLOAD GNUNET_YES | 36 | #define DEBUG_DOWNLOAD GNUNET_YES |
31 | 37 | ||
32 | 38 | ||
39 | /** | ||
40 | * Schedule the download of the specified | ||
41 | * block in the tree. | ||
42 | * | ||
43 | * @param dc overall download this block belongs to | ||
44 | * @param chk content-hash-key of the block | ||
45 | * @param offset offset of the block in the file | ||
46 | * (for IBlocks, the offset is the lowest | ||
47 | * offset of any DBlock in the subtree under | ||
48 | * the IBlock) | ||
49 | * @param depth depth of the block, 0 is the root of the tree | ||
50 | */ | ||
51 | static void | ||
52 | schedule_block_download (struct GNUNET_FS_DownloadContext *dc, | ||
53 | const struct ContentHashKey *chk, | ||
54 | uint64_t offset, | ||
55 | unsigned int depth) | ||
56 | { | ||
57 | struct DownloadRequest *sm; | ||
58 | |||
59 | sm = GNUNET_malloc (sizeof (struct DownloadRequest)); | ||
60 | sm->chk = *chk; | ||
61 | sm->offset = offset; | ||
62 | sm->depth = depth; | ||
63 | sm->is_pending = GNUNET_YES; | ||
64 | sm->next = dc->pending; | ||
65 | dc->pending = sm; | ||
66 | GNUNET_CONTAINER_multihashmap_put (dc->active, | ||
67 | &chk->query, | ||
68 | sm, | ||
69 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
70 | } | ||
71 | |||
72 | |||
73 | /** | ||
74 | * We've lost our connection with the FS service. | ||
75 | * Re-establish it and re-transmit all of our | ||
76 | * pending requests. | ||
77 | * | ||
78 | * @param dc download context that is having trouble | ||
79 | */ | ||
80 | static void | ||
81 | try_reconnect (struct GNUNET_FS_DownloadContext *dc); | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Process a search result. | ||
86 | * | ||
87 | * @param sc our search context | ||
88 | * @param type type of the result | ||
89 | * @param data the (encrypted) response | ||
90 | * @param size size of data | ||
91 | */ | ||
92 | static void | ||
93 | process_result (struct GNUNET_FS_DownloadContext *dc, | ||
94 | uint32_t type, | ||
95 | const void *data, | ||
96 | size_t size) | ||
97 | { | ||
98 | GNUNET_HashCode query; | ||
99 | struct DownloadRequest *sm; | ||
100 | struct GNUNET_CRYPTO_AesSessionKey skey; | ||
101 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
102 | char pt[size]; | ||
103 | |||
104 | GNUNET_CRYPTO_hash (data, size, &query); | ||
105 | sm = GNUNET_CONTAINER_multihashmap_get (dc->active, | ||
106 | &query); | ||
107 | if (NULL == sm) | ||
108 | { | ||
109 | GNUNET_break (0); | ||
110 | return; | ||
111 | } | ||
112 | GNUNET_assert (GNUNET_YES == | ||
113 | GNUNET_CONTAINER_multihashmap_remove (dc->active, | ||
114 | &query, | ||
115 | sm)); | ||
116 | GNUNET_CRYPTO_hash_to_aes_key (&sm->chk.key, &skey, &iv); | ||
117 | GNUNET_CRYPTO_aes_decrypt (data, | ||
118 | size, | ||
119 | &skey, | ||
120 | &iv, | ||
121 | pt); | ||
122 | // FIXME: save to disk | ||
123 | // FIXME: make persistent | ||
124 | // FIXME: call progress callback | ||
125 | // FIXME: trigger next block (if applicable) | ||
126 | } | ||
127 | |||
128 | |||
129 | /** | ||
130 | * Type of a function to call when we receive a message | ||
131 | * from the service. | ||
132 | * | ||
133 | * @param cls closure | ||
134 | * @param msg message received, NULL on timeout or fatal error | ||
135 | */ | ||
136 | static void | ||
137 | receive_results (void *cls, | ||
138 | const struct GNUNET_MessageHeader * msg) | ||
139 | { | ||
140 | struct GNUNET_FS_DownloadContext *dc = cls; | ||
141 | const struct ContentMessage *cm; | ||
142 | uint16_t msize; | ||
143 | |||
144 | if ( (NULL == msg) || | ||
145 | (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_CONTENT) || | ||
146 | (ntohs (msg->size) <= sizeof (struct ContentMessage)) ) | ||
147 | { | ||
148 | try_reconnect (dc); | ||
149 | return; | ||
150 | } | ||
151 | msize = ntohs (msg->size); | ||
152 | cm = (const struct ContentMessage*) msg; | ||
153 | process_result (dc, | ||
154 | ntohl (cm->type), | ||
155 | &cm[1], | ||
156 | msize - sizeof (struct ContentMessage)); | ||
157 | /* continue receiving */ | ||
158 | GNUNET_CLIENT_receive (dc->client, | ||
159 | &receive_results, | ||
160 | dc, | ||
161 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
162 | } | ||
163 | |||
164 | |||
165 | |||
166 | /** | ||
167 | * We're ready to transmit a search request to the | ||
168 | * file-sharing service. Do it. If there is | ||
169 | * more than one request pending, try to send | ||
170 | * multiple or request another transmission. | ||
171 | * | ||
172 | * @param cls closure | ||
173 | * @param size number of bytes available in buf | ||
174 | * @param buf where the callee should write the message | ||
175 | * @return number of bytes written to buf | ||
176 | */ | ||
177 | static size_t | ||
178 | transmit_download_request (void *cls, | ||
179 | size_t size, | ||
180 | void *buf) | ||
181 | { | ||
182 | struct GNUNET_FS_DownloadContext *dc = cls; | ||
183 | size_t msize; | ||
184 | struct SearchMessage *sm; | ||
185 | |||
186 | if (NULL == buf) | ||
187 | { | ||
188 | try_reconnect (dc); | ||
189 | return 0; | ||
190 | } | ||
191 | GNUNET_assert (size >= sizeof (struct SearchMessage)); | ||
192 | msize = 0; | ||
193 | sm = buf; | ||
194 | while ( (dc->pending == NULL) && | ||
195 | (size > msize + sizeof (struct SearchMessage)) ) | ||
196 | { | ||
197 | memset (sm, 0, sizeof (struct SearchMessage)); | ||
198 | sm->header.size = htons (sizeof (struct SearchMessage)); | ||
199 | sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); | ||
200 | sm->anonymity_level = htonl (dc->anonymity); | ||
201 | // FIXME: support 'loc' URIs (set sm->target) | ||
202 | sm->query = dc->pending->chk.query; | ||
203 | dc->pending->is_pending = GNUNET_NO; | ||
204 | dc->pending = dc->pending->next; | ||
205 | msize += sizeof (struct SearchMessage); | ||
206 | sm++; | ||
207 | } | ||
208 | return msize; | ||
209 | } | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Reconnect to the FS service and transmit | ||
214 | * our queries NOW. | ||
215 | * | ||
216 | * @param cls our download context | ||
217 | * @param tc unused | ||
218 | */ | ||
219 | static void | ||
220 | do_reconnect (void *cls, | ||
221 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
222 | { | ||
223 | struct GNUNET_FS_DownloadContext *dc = cls; | ||
224 | struct GNUNET_CLIENT_Connection *client; | ||
225 | |||
226 | dc->task = GNUNET_SCHEDULER_NO_TASK; | ||
227 | client = GNUNET_CLIENT_connect (dc->h->sched, | ||
228 | "fs", | ||
229 | dc->h->cfg); | ||
230 | if (NULL == client) | ||
231 | { | ||
232 | try_reconnect (dc); | ||
233 | return; | ||
234 | } | ||
235 | dc->client = client; | ||
236 | GNUNET_CLIENT_notify_transmit_ready (client, | ||
237 | sizeof (struct SearchMessage), | ||
238 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
239 | &transmit_download_request, | ||
240 | dc); | ||
241 | GNUNET_CLIENT_receive (client, | ||
242 | &receive_results, | ||
243 | dc, | ||
244 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
245 | } | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Add entries that are not yet pending back to | ||
250 | * the pending list. | ||
251 | * | ||
252 | * @param cls our download context | ||
253 | * @param key unused | ||
254 | * @param entry entry of type "struct DownloadRequest" | ||
255 | * @return GNUNET_OK | ||
256 | */ | ||
257 | static int | ||
258 | retry_entry (void *cls, | ||
259 | const GNUNET_HashCode *key, | ||
260 | void *entry) | ||
261 | { | ||
262 | struct GNUNET_FS_DownloadContext *dc = cls; | ||
263 | struct DownloadRequest *dr = entry; | ||
264 | |||
265 | if (! dr->is_pending) | ||
266 | { | ||
267 | dr->next = dc->pending; | ||
268 | dr->is_pending = GNUNET_YES; | ||
269 | dc->pending = entry; | ||
270 | } | ||
271 | return GNUNET_OK; | ||
272 | } | ||
273 | |||
274 | |||
275 | /** | ||
276 | * We've lost our connection with the FS service. | ||
277 | * Re-establish it and re-transmit all of our | ||
278 | * pending requests. | ||
279 | * | ||
280 | * @param dc download context that is having trouble | ||
281 | */ | ||
282 | static void | ||
283 | try_reconnect (struct GNUNET_FS_DownloadContext *dc) | ||
284 | { | ||
285 | |||
286 | if (NULL != dc->client) | ||
287 | { | ||
288 | GNUNET_CONTAINER_multihashmap_iterate (dc->active, | ||
289 | &retry_entry, | ||
290 | dc); | ||
291 | GNUNET_CLIENT_disconnect (dc->client); | ||
292 | dc->client = NULL; | ||
293 | } | ||
294 | dc->task | ||
295 | = GNUNET_SCHEDULER_add_delayed (dc->h->sched, | ||
296 | GNUNET_NO, | ||
297 | GNUNET_SCHEDULER_PRIORITY_IDLE, | ||
298 | GNUNET_SCHEDULER_NO_TASK, | ||
299 | GNUNET_TIME_UNIT_SECONDS, | ||
300 | &do_reconnect, | ||
301 | dc); | ||
302 | } | ||
303 | |||
33 | 304 | ||
34 | /** | 305 | /** |
35 | * Download parts of a file. Note that this will store | 306 | * Download parts of a file. Note that this will store |
@@ -50,9 +321,7 @@ | |||
50 | * @param offset at what offset should we start the download (typically 0) | 321 | * @param offset at what offset should we start the download (typically 0) |
51 | * @param length how many bytes should be downloaded starting at offset | 322 | * @param length how many bytes should be downloaded starting at offset |
52 | * @param anonymity anonymity level to use for the download | 323 | * @param anonymity anonymity level to use for the download |
53 | * @param no_temporaries set to GNUNET_YES to disallow generation of temporary files | 324 | * @param options various options |
54 | * @param recursive should this be a recursive download (useful for directories | ||
55 | * to automatically trigger download of files in the directories) | ||
56 | * @param parent parent download to associate this download with (use NULL | 325 | * @param parent parent download to associate this download with (use NULL |
57 | * for top-level downloads; useful for manually-triggered recursive downloads) | 326 | * for top-level downloads; useful for manually-triggered recursive downloads) |
58 | * @return context that can be used to control this download | 327 | * @return context that can be used to control this download |
@@ -61,31 +330,120 @@ struct GNUNET_FS_DownloadContext * | |||
61 | GNUNET_FS_file_download_start (struct GNUNET_FS_Handle *h, | 330 | GNUNET_FS_file_download_start (struct GNUNET_FS_Handle *h, |
62 | const struct GNUNET_FS_Uri *uri, | 331 | const struct GNUNET_FS_Uri *uri, |
63 | const char *filename, | 332 | const char *filename, |
64 | unsigned long long offset, | 333 | uint64_t offset, |
65 | unsigned long long length, | 334 | uint64_t length, |
66 | unsigned int anonymity, | 335 | uint32_t anonymity, |
67 | int no_temporaries, | 336 | enum GNUNET_FS_DownloadOptions options, |
68 | int recursive, | ||
69 | struct GNUNET_FS_DownloadContext *parent) | 337 | struct GNUNET_FS_DownloadContext *parent) |
70 | { | 338 | { |
71 | return NULL; | 339 | struct GNUNET_FS_DownloadContext *dc; |
340 | struct GNUNET_CLIENT_Connection *client; | ||
341 | |||
342 | client = GNUNET_CLIENT_connect (h->sched, | ||
343 | "fs", | ||
344 | h->cfg); | ||
345 | if (NULL == client) | ||
346 | return NULL; | ||
347 | // FIXME: add support for "loc" URIs! | ||
348 | GNUNET_assert (GNUNET_FS_uri_test_chk (uri)); | ||
349 | if ( (dc->offset + dc->length < dc->offset) || | ||
350 | (dc->offset + dc->length > uri->data.chk.file_length) ) | ||
351 | { | ||
352 | GNUNET_break (0); | ||
353 | return NULL; | ||
354 | } | ||
355 | dc = GNUNET_malloc (sizeof(struct GNUNET_FS_DownloadContext)); | ||
356 | dc->h = h; | ||
357 | dc->client = client; | ||
358 | dc->parent = parent; | ||
359 | dc->uri = GNUNET_FS_uri_dup (uri); | ||
360 | dc->filename = (NULL == filename) ? NULL : GNUNET_strdup (filename); | ||
361 | dc->offset = offset; | ||
362 | dc->length = length; | ||
363 | dc->anonymity = anonymity; | ||
364 | dc->options = options; | ||
365 | dc->active = GNUNET_CONTAINER_multihashmap_create (1 + (length / DBLOCK_SIZE)); | ||
366 | // FIXME: make persistent | ||
367 | schedule_block_download (dc, | ||
368 | &dc->uri->data.chk.chk, | ||
369 | 0, | ||
370 | 0); | ||
371 | GNUNET_CLIENT_notify_transmit_ready (client, | ||
372 | sizeof (struct SearchMessage), | ||
373 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
374 | &transmit_download_request, | ||
375 | dc); | ||
376 | GNUNET_CLIENT_receive (client, | ||
377 | &receive_results, | ||
378 | dc, | ||
379 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
380 | // FIXME: signal download start | ||
381 | return dc; | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * Free entries in the map. | ||
387 | * | ||
388 | * @param cls unused (NULL) | ||
389 | * @param key unused | ||
390 | * @param entry entry of type "struct DownloadRequest" which is freed | ||
391 | * @return GNUNET_OK | ||
392 | */ | ||
393 | static int | ||
394 | free_entry (void *cls, | ||
395 | const GNUNET_HashCode *key, | ||
396 | void *entry) | ||
397 | { | ||
398 | GNUNET_free (entry); | ||
399 | return GNUNET_OK; | ||
72 | } | 400 | } |
73 | 401 | ||
402 | |||
74 | /** | 403 | /** |
75 | * Stop a download (aborts if download is incomplete). | 404 | * Stop a download (aborts if download is incomplete). |
76 | * | 405 | * |
77 | * @param rm handle for the download | 406 | * @param dc handle for the download |
78 | * @param do_delete delete files of incomplete downloads | 407 | * @param do_delete delete files of incomplete downloads |
79 | */ | 408 | */ |
80 | void | 409 | void |
81 | GNUNET_FS_file_download_stop (struct GNUNET_FS_DownloadContext *rm, | 410 | GNUNET_FS_file_download_stop (struct GNUNET_FS_DownloadContext *dc, |
82 | int do_delete) | 411 | int do_delete) |
83 | { | 412 | { |
413 | // FIXME: make unpersistent | ||
414 | // FIXME: signal download end | ||
415 | |||
416 | if (GNUNET_SCHEDULER_NO_TASK != dc->task) | ||
417 | GNUNET_SCHEDULER_cancel (dc->h->sched, | ||
418 | dc->task); | ||
419 | if (NULL != dc->client) | ||
420 | GNUNET_CLIENT_disconnect (dc->client); | ||
421 | GNUNET_CONTAINER_multihashmap_iterate (dc->active, | ||
422 | &free_entry, | ||
423 | NULL); | ||
424 | GNUNET_CONTAINER_multihashmap_destroy (dc->active); | ||
425 | GNUNET_FS_uri_destroy (dc->uri); | ||
426 | GNUNET_free_non_null (dc->filename); | ||
427 | GNUNET_free (dc); | ||
84 | } | 428 | } |
85 | 429 | ||
86 | 430 | ||
87 | 431 | ||
88 | 432 | ||
433 | |||
434 | |||
435 | |||
436 | |||
437 | |||
438 | |||
439 | |||
440 | |||
441 | |||
442 | |||
443 | |||
444 | |||
445 | |||
446 | |||
89 | #if 0 | 447 | #if 0 |
90 | 448 | ||
91 | /** | 449 | /** |