diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-08-27 11:14:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-08-27 11:14:19 +0000 |
commit | 57df0fbf8398720fbd4a9cf34934c212ea00ee54 (patch) | |
tree | a00d5740b2a35e21d4cff044c4ce941995b1bdff /src | |
parent | 2f7e69f969a822a38f9e311f79358e0fe8bda9d8 (diff) | |
download | gnunet-57df0fbf8398720fbd4a9cf34934c212ea00ee54.tar.gz gnunet-57df0fbf8398720fbd4a9cf34934c212ea00ee54.zip |
syn
Diffstat (limited to 'src')
-rw-r--r-- | src/fs/fs.h | 78 | ||||
-rw-r--r-- | src/fs/fs_directory.c | 332 | ||||
-rw-r--r-- | src/fs/fs_file_information.c | 3 | ||||
-rw-r--r-- | src/fs/fs_publish.c | 853 | ||||
-rw-r--r-- | src/include/gnunet_constants.h | 7 | ||||
-rw-r--r-- | src/include/gnunet_container_lib.h | 27 | ||||
-rw-r--r-- | src/include/gnunet_crypto_lib.h | 2 | ||||
-rw-r--r-- | src/include/gnunet_datastore_service.h | 6 | ||||
-rw-r--r-- | src/include/gnunet_fs_service.h | 46 | ||||
-rw-r--r-- | src/util/container_meta_data.c | 32 | ||||
-rw-r--r-- | src/util/crypto_hash.c | 2 |
11 files changed, 812 insertions, 576 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h index 4743a594b..c66249613 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -26,11 +26,33 @@ | |||
26 | #ifndef FS_H | 26 | #ifndef FS_H |
27 | #define FS_H | 27 | #define FS_H |
28 | 28 | ||
29 | #include "gnunet_datastore_service.h" | ||
30 | #include "gnunet_fs_service.h" | ||
31 | |||
29 | /** | 32 | /** |
30 | * Size of the individual blocks used for file-sharing. | 33 | * Size of the individual blocks used for file-sharing. |
31 | */ | 34 | */ |
32 | #define GNUNET_FS_DBLOCK_SIZE (32*1024) | 35 | #define GNUNET_FS_DBLOCK_SIZE (32*1024) |
33 | 36 | ||
37 | |||
38 | /** | ||
39 | * Pick a multiple of 2 here to achive 8-byte alignment! | ||
40 | * We also probably want DBlocks to have (roughly) the | ||
41 | * same size as IBlocks. With SHA-512, the optimal | ||
42 | * value is 32768 byte / 128 byte = 256 | ||
43 | * (128 byte = 2 * 512 bits). DO NOT CHANGE! | ||
44 | */ | ||
45 | #define GNUNET_FS_CHK_PER_INODE 256 | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Maximum size for a file to be considered for | ||
50 | * inlining in a directory. | ||
51 | */ | ||
52 | #define GNUNET_FS_MAX_INLINE_SIZE 65536 | ||
53 | |||
54 | |||
55 | |||
34 | /** | 56 | /** |
35 | * @brief content hash key | 57 | * @brief content hash key |
36 | */ | 58 | */ |
@@ -51,7 +73,7 @@ struct FileIdentifier | |||
51 | /** | 73 | /** |
52 | * Total size of the file in bytes. (network byte order (!)) | 74 | * Total size of the file in bytes. (network byte order (!)) |
53 | */ | 75 | */ |
54 | unsigned long long file_length; | 76 | uint64_t file_length; |
55 | 77 | ||
56 | /** | 78 | /** |
57 | * Query and key of the top GNUNET_EC_IBlock. | 79 | * Query and key of the top GNUNET_EC_IBlock. |
@@ -187,6 +209,12 @@ struct GNUNET_FS_FileInformation | |||
187 | struct GNUNET_FS_Uri *keywords; | 209 | struct GNUNET_FS_Uri *keywords; |
188 | 210 | ||
189 | /** | 211 | /** |
212 | * CHK for this file or directory. NULL if | ||
213 | * we have not yet computed it. | ||
214 | */ | ||
215 | struct GNUNET_FS_Uri *chk_uri; | ||
216 | |||
217 | /** | ||
190 | * At what time should the content expire? | 218 | * At what time should the content expire? |
191 | */ | 219 | */ |
192 | struct GNUNET_TIME_Absolute expirationTime; | 220 | struct GNUNET_TIME_Absolute expirationTime; |
@@ -198,6 +226,31 @@ struct GNUNET_FS_FileInformation | |||
198 | char *serialization; | 226 | char *serialization; |
199 | 227 | ||
200 | /** | 228 | /** |
229 | * In-memory cache of the current CHK tree. | ||
230 | * This struct will contain the CHK values | ||
231 | * from the root to the currently processed | ||
232 | * node in the tree as identified by | ||
233 | * "current_depth" and "publish_offset". | ||
234 | * The "chktree" will be initially NULL, | ||
235 | * then allocated to a sufficient number of | ||
236 | * entries for the size of the file and | ||
237 | * finally freed once the upload is complete. | ||
238 | */ | ||
239 | struct ContentHashKey *chk_tree; | ||
240 | |||
241 | /** | ||
242 | * Number of entries in "chk_tree". | ||
243 | */ | ||
244 | unsigned int chk_tree_depth; | ||
245 | |||
246 | /** | ||
247 | * Depth in the CHK-tree at which we are | ||
248 | * currently publishing. 0 is the root | ||
249 | * of the tree. | ||
250 | */ | ||
251 | unsigned int current_depth; | ||
252 | |||
253 | /** | ||
201 | * How many bytes of this file or directory have been | 254 | * How many bytes of this file or directory have been |
202 | * published so far? | 255 | * published so far? |
203 | */ | 256 | */ |
@@ -257,6 +310,12 @@ struct GNUNET_FS_FileInformation | |||
257 | */ | 310 | */ |
258 | uint64_t dir_size; | 311 | uint64_t dir_size; |
259 | 312 | ||
313 | /** | ||
314 | * Pointer to the data for the directory (or NULL if not | ||
315 | * available). | ||
316 | */ | ||
317 | char *dir_data; | ||
318 | |||
260 | } dir; | 319 | } dir; |
261 | 320 | ||
262 | } data; | 321 | } data; |
@@ -358,6 +417,23 @@ struct GNUNET_FS_PublishContext | |||
358 | * if the upload has completed. | 417 | * if the upload has completed. |
359 | */ | 418 | */ |
360 | GNUNET_SCHEDULER_TaskIdentifier upload_task; | 419 | GNUNET_SCHEDULER_TaskIdentifier upload_task; |
420 | |||
421 | /** | ||
422 | * Current position in the file-tree for the | ||
423 | * upload. | ||
424 | */ | ||
425 | struct GNUNET_FS_FileInformation *fi_pos; | ||
426 | |||
427 | /** | ||
428 | * Connection to the datastore service. | ||
429 | */ | ||
430 | struct GNUNET_DATASTORE_Handle *dsh; | ||
431 | |||
432 | /** | ||
433 | * Space reservation ID with datastore service | ||
434 | * for this upload. | ||
435 | */ | ||
436 | int rid; | ||
361 | }; | 437 | }; |
362 | 438 | ||
363 | 439 | ||
diff --git a/src/fs/fs_directory.c b/src/fs/fs_directory.c index 3eb3af50d..e5a9f963f 100644 --- a/src/fs/fs_directory.c +++ b/src/fs/fs_directory.c | |||
@@ -25,7 +25,6 @@ | |||
25 | * | 25 | * |
26 | * TODO: | 26 | * TODO: |
27 | * - add support for embedded file data (use padding room!) | 27 | * - add support for embedded file data (use padding room!) |
28 | * - add directory builder API to gnunet_fs_service | ||
29 | * - modify directory builder API to support incremental | 28 | * - modify directory builder API to support incremental |
30 | * generation of directories (to allow directories that | 29 | * generation of directories (to allow directories that |
31 | * would not fit into memory to be created) | 30 | * would not fit into memory to be created) |
@@ -38,6 +37,9 @@ | |||
38 | #include "gnunet_fs_service.h" | 37 | #include "gnunet_fs_service.h" |
39 | #include "fs.h" | 38 | #include "fs.h" |
40 | 39 | ||
40 | #ifndef EXTRACTOR_GNUNET_FULL_DATA | ||
41 | #define EXTRACTOR_GNUNET_FULL_DATA 137 | ||
42 | #endif | ||
41 | 43 | ||
42 | /** | 44 | /** |
43 | * Does the meta-data claim that this is a directory? | 45 | * Does the meta-data claim that this is a directory? |
@@ -215,6 +217,7 @@ GNUNET_FS_directory_list_contents (size_t size, | |||
215 | return; /* malformed ! */ | 217 | return; /* malformed ! */ |
216 | } | 218 | } |
217 | pos += mdSize; | 219 | pos += mdSize; |
220 | // EXTRACTOR_GNUNET_FULL_DATA | ||
218 | /* FIXME: add support for embedded data */ | 221 | /* FIXME: add support for embedded data */ |
219 | filename = GNUNET_CONTAINER_meta_data_get_by_type (md, | 222 | filename = GNUNET_CONTAINER_meta_data_get_by_type (md, |
220 | EXTRACTOR_FILENAME); | 223 | EXTRACTOR_FILENAME); |
@@ -231,14 +234,150 @@ GNUNET_FS_directory_list_contents (size_t size, | |||
231 | } | 234 | } |
232 | } | 235 | } |
233 | 236 | ||
237 | /** | ||
238 | * Entries in the directory (builder). | ||
239 | */ | ||
240 | struct BuilderEntry | ||
241 | { | ||
242 | /** | ||
243 | * This is a linked list. | ||
244 | */ | ||
245 | struct BuilderEntry *next; | ||
246 | |||
247 | /** | ||
248 | * Length of this entry. | ||
249 | */ | ||
250 | size_t len; | ||
251 | }; | ||
234 | 252 | ||
235 | void | 253 | /** |
236 | GNUNET_FS_directory_create () | 254 | * Internal state of a directory builder. |
255 | */ | ||
256 | struct GNUNET_FS_DirectoryBuilder | ||
237 | { | 257 | { |
258 | /** | ||
259 | * Meta-data for the directory itself. | ||
260 | */ | ||
261 | struct GNUNET_CONTAINER_MetaData *meta; | ||
262 | |||
263 | /** | ||
264 | * Head of linked list of entries. | ||
265 | */ | ||
266 | struct BuilderEntry *head; | ||
267 | |||
268 | /** | ||
269 | * Number of entires in the directory. | ||
270 | */ | ||
271 | unsigned int count; | ||
272 | }; | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Create a directory builder. | ||
277 | * | ||
278 | * @param mdir metadata for the directory | ||
279 | */ | ||
280 | struct GNUNET_FS_DirectoryBuilder * | ||
281 | GNUNET_FS_directory_builder_create (const struct GNUNET_CONTAINER_MetaData *mdir) | ||
282 | { | ||
283 | struct GNUNET_FS_DirectoryBuilder *ret; | ||
284 | |||
285 | ret = GNUNET_malloc(sizeof(struct GNUNET_FS_DirectoryBuilder)); | ||
286 | ret->meta = GNUNET_CONTAINER_meta_data_duplicate (mdir); | ||
287 | GNUNET_FS_meta_data_make_directory (ret->meta); | ||
288 | return ret; | ||
238 | } | 289 | } |
239 | 290 | ||
240 | 291 | ||
241 | #if 0 | 292 | /** |
293 | * Add an entry to a directory. | ||
294 | * | ||
295 | * @param bld directory to extend | ||
296 | * @param uri uri of the entry (must not be a KSK) | ||
297 | * @param md metadata of the entry | ||
298 | * @param data raw data of the entry, can be NULL, otherwise | ||
299 | * data must point to exactly the number of bytes specified | ||
300 | * by the uri which must be of type LOC or CHK | ||
301 | */ | ||
302 | void | ||
303 | GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld, | ||
304 | const struct GNUNET_FS_Uri *uri, | ||
305 | const struct GNUNET_CONTAINER_MetaData *md, | ||
306 | const void *data) | ||
307 | { | ||
308 | struct BuilderEntry *e; | ||
309 | uint64_t fsize; | ||
310 | uint32_t big; | ||
311 | size_t mds; | ||
312 | size_t mdxs; | ||
313 | char *uris; | ||
314 | char *ser; | ||
315 | size_t slen; | ||
316 | struct GNUNET_CONTAINER_MetaData *meta; | ||
317 | const struct GNUNET_CONTAINER_MetaData *meta_use; | ||
318 | |||
319 | GNUNET_assert (! GNUNET_FS_uri_ksk_test (uri)); | ||
320 | if (NULL != data) | ||
321 | if (GNUNET_FS_uri_chk_test (uri)) | ||
322 | fsize = GNUNET_FS_uri_chk_get_size (uri); | ||
323 | else | ||
324 | fsize = GNUNET_FS_uri_chk_get_size (GNUNET_FS_uri_loc_get_uri (uri)); | ||
325 | else | ||
326 | fsize = 0; /* not given */ | ||
327 | if (fsize > GNUNET_FS_MAX_INLINE_SIZE) | ||
328 | fsize = 0; /* too large */ | ||
329 | if (memchr (data, fsize, '\0')) // FIXME: check memchr args! | ||
330 | fsize = 0; /* must not have 0's in data! */ | ||
331 | uris = GNUNET_FS_uri_to_string (uri); | ||
332 | slen = strlen (uris) + 1; | ||
333 | mds = | ||
334 | GNUNET_CONTAINER_meta_data_get_serialized_size (md, | ||
335 | GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); | ||
336 | meta_use = md; | ||
337 | meta = NULL; | ||
338 | if (fsize > 0) | ||
339 | { | ||
340 | meta = GNUNET_CONTAINER_meta_data_duplicate (md); | ||
341 | GNUNET_CONTAINER_meta_data_insert (meta, | ||
342 | EXTRACTOR_GNUNET_FULL_DATA, | ||
343 | data); | ||
344 | mdxs = | ||
345 | GNUNET_CONTAINER_meta_data_get_serialized_size (meta, | ||
346 | GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); | ||
347 | if ( (slen + sizeof (uint32_t) + mdxs - 1) / GNUNET_FS_DBLOCK_SIZE == | ||
348 | (slen + sizeof (uint32_t) + mds - 1) / GNUNET_FS_DBLOCK_SIZE) | ||
349 | { | ||
350 | /* adding full data would not cause us to cross | ||
351 | additional blocks, so add it! */ | ||
352 | meta_use = meta; | ||
353 | mds = mdxs; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | if (mds > GNUNET_MAX_MALLOC_CHECKED / 2) | ||
358 | mds = GNUNET_MAX_MALLOC_CHECKED / 2; | ||
359 | e = GNUNET_malloc (sizeof(struct BuilderEntry) + | ||
360 | slen + mds + sizeof (uint32_t)); | ||
361 | ser = (char*) &e[1]; | ||
362 | memcpy (ser, uris, slen); | ||
363 | GNUNET_free (uris); | ||
364 | ret = GNUNET_CONTAINER_meta_data_serialize (meta_use, | ||
365 | &ser[slen + sizeof(uint32_t)], | ||
366 | mds, | ||
367 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); | ||
368 | if (NULL != meta) | ||
369 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
370 | if (ret == -1) | ||
371 | mds = 0; | ||
372 | else | ||
373 | mds = ret; | ||
374 | big = htonl (mds); | ||
375 | memcpy (&ser[slen], &big, sizeof (uint32_t)); | ||
376 | e->len = slen + sizeof (uint32_t) + mds; | ||
377 | e->next = bld->head; | ||
378 | bld->head = e; | ||
379 | bld->count++; | ||
380 | } | ||
242 | 381 | ||
243 | 382 | ||
244 | /** | 383 | /** |
@@ -246,11 +385,11 @@ GNUNET_FS_directory_create () | |||
246 | * data, return the end position of that data | 385 | * data, return the end position of that data |
247 | * after alignment to the GNUNET_FS_DBLOCK_SIZE. | 386 | * after alignment to the GNUNET_FS_DBLOCK_SIZE. |
248 | */ | 387 | */ |
249 | static uint64_t | 388 | static size_t |
250 | do_align (uint64_t start_position, | 389 | do_align (size_t start_position, |
251 | uint64_t end_position) | 390 | size_t end_position) |
252 | { | 391 | { |
253 | uint64_t align; | 392 | size_t align; |
254 | 393 | ||
255 | align = (end_position / GNUNET_FS_DBLOCK_SIZE) * GNUNET_FS_DBLOCK_SIZE; | 394 | align = (end_position / GNUNET_FS_DBLOCK_SIZE) * GNUNET_FS_DBLOCK_SIZE; |
256 | if ((start_position < align) && (end_position > align)) | 395 | if ((start_position < align) && (end_position > align)) |
@@ -269,19 +408,19 @@ do_align (uint64_t start_position, | |||
269 | * @param perm the permutation of the blocks (updated) | 408 | * @param perm the permutation of the blocks (updated) |
270 | */ | 409 | */ |
271 | static void | 410 | static void |
272 | block_align (uint64_t start, | 411 | block_align (size_t start, |
273 | unsigned int count, | 412 | unsigned int count, |
274 | const uint64_t *sizes, | 413 | const size_t *sizes, |
275 | unsigned int *perm) | 414 | unsigned int *perm) |
276 | { | 415 | { |
277 | unsigned int i; | 416 | unsigned int i; |
278 | unsigned int j; | 417 | unsigned int j; |
279 | unsigned int tmp; | 418 | unsigned int tmp; |
280 | unsigned int best; | 419 | unsigned int best; |
281 | int64_t badness; | 420 | ssize_t badness; |
282 | uint64_t cpos; | 421 | size_t cpos; |
283 | uint64_t cend; | 422 | size_t cend; |
284 | int64_t cbad; | 423 | ssize_t cbad; |
285 | unsigned int cval; | 424 | unsigned int cval; |
286 | 425 | ||
287 | cpos = start; | 426 | cpos = start; |
@@ -334,135 +473,94 @@ block_align (uint64_t start, | |||
334 | 473 | ||
335 | 474 | ||
336 | /** | 475 | /** |
337 | * Create a directory. We allow packing more than one variable | 476 | * Finish building the directory. Frees the |
338 | * size entry into one block (and an entry could also span more | 477 | * builder context and returns the directory |
339 | * than one block), but an entry that is smaller than a single | 478 | * in-memory. |
340 | * block will never cross the block boundary. This is done to | ||
341 | * allow processing entries of a directory already even if the | ||
342 | * download is still partial.<p> | ||
343 | * | ||
344 | * The first block begins with the directories MAGIC signature, | ||
345 | * followed by the meta-data about the directory itself.<p> | ||
346 | * | 479 | * |
347 | * After that, the directory consists of block-aligned pairs | 480 | * @param bld directory to finish |
348 | * of URIs (0-terminated strings) and serialized meta-data. | 481 | * @param rsize set to the number of bytes needed |
349 | * | 482 | * @param rdata set to the encoded directory |
350 | * @param data pointer set to the beginning of the directory | ||
351 | * @param len set to number of bytes in data | ||
352 | * @param count number of entries in uris and mds | ||
353 | * @param uris URIs of the files in the directory | ||
354 | * @param mds meta-data for the files (must match | ||
355 | * respective values at same offset in in uris) | ||
356 | * @param mdir meta-data for the directory | ||
357 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
358 | */ | 483 | */ |
359 | int | 484 | void |
360 | GNUNET_FS_directory_create (char **data, | 485 | GNUNET_FS_directory_builder_finish (struct GNUNET_FS_DirectoryBuilder *bld, |
361 | size_t *len, | 486 | size_t *rsize, |
362 | unsigned int count, | 487 | void **rdata) |
363 | const struct GNUNET_FS_Uri **uris, | ||
364 | const struct GNUNET_CONTAINER_MetaData **mds, | ||
365 | const struct GNUNET_CONTAINER_MetaData *mdir) | ||
366 | { | 488 | { |
489 | char *data; | ||
490 | size_t *sizes; | ||
491 | unsigned int *perm; | ||
367 | unsigned int i; | 492 | unsigned int i; |
368 | unsigned int j; | 493 | unsigned int j; |
369 | uint64_t psize; | 494 | struct BuilderEntry *pos; |
370 | uint64_t size; | 495 | struct BuilderEntry **bes; |
371 | uint64_t pos; | 496 | size_t size; |
372 | char **ucs; | 497 | size_t psize; |
373 | int ret; | 498 | size_t off; |
374 | uint64_t *sizes; | 499 | ssize_t ret; |
375 | unsigned int *perm; | 500 | uint32_t big; |
376 | 501 | ||
377 | for (i = 0; i < count; i++) | 502 | size = 8 + sizeof (uint32_t); |
378 | { | 503 | size += GNUNET_meta_data_get_serialized_size (bld->meta, |
379 | if (GNUNET_FS_uri_test_ksk (fis[i].uri)) | 504 | GNUNET_SERIALIZE_FULL); |
380 | { | 505 | if (bld->count > 0) |
381 | GNUNET_break (0); | ||
382 | return GNUNET_SYSERR; /* illegal in directory! */ | ||
383 | } | ||
384 | } | ||
385 | ucs = GNUNET_malloc (sizeof (char *) * count); | ||
386 | size = 8 + sizeof (unsigned int); | ||
387 | size += GNUNET_meta_data_get_serialized_size (meta, GNUNET_SERIALIZE_FULL); | ||
388 | sizes = GNUNET_malloc (count * sizeof (unsigned long long)); | ||
389 | perm = GNUNET_malloc (count * sizeof (int)); | ||
390 | for (i = 0; i < count; i++) | ||
391 | { | 506 | { |
392 | perm[i] = i; | 507 | sizes = GNUNET_malloc (bld->count * sizeof (size_t)); |
393 | ucs[i] = GNUNET_FS_uri_to_string (fis[i].uri); | 508 | perm = GNUNET_malloc (bld->count * sizeof (unsigned int)); |
394 | GNUNET_assert (ucs[i] != NULL); | 509 | bes = GNUNET_malloc (bld->count * sizeof (struct BuilderEntry *)); |
395 | psize = | 510 | pos = bld->head; |
396 | GNUNET_meta_data_get_serialized_size (fis[i].meta, | 511 | for (i = 0; i < bld->count; i++) |
397 | GNUNET_SERIALIZE_FULL); | 512 | { |
398 | if (psize == -1) | 513 | perm[i] = i; |
399 | { | 514 | bes[i] = pos; |
400 | GNUNET_break (0); | 515 | sizes[i] = pos->size; |
401 | GNUNET_free (sizes); | 516 | pos = pos->next; |
402 | GNUNET_free (perm); | 517 | } |
403 | while (i >= 0) | 518 | } |
404 | GNUNET_free (ucs[i--]); | 519 | block_align (size, |
405 | GNUNET_free (ucs); | 520 | bld->count, |
406 | return GNUNET_SYSERR; | 521 | sizes, |
407 | } | 522 | perm); |
408 | sizes[i] = psize + sizeof (unsigned int) + strlen (ucs[i]) + 1; | ||
409 | } | ||
410 | /* permutate entries to minimize alignment cost */ | ||
411 | block_align (size, count, sizes, perm); | ||
412 | 523 | ||
413 | /* compute final size with alignment */ | 524 | /* compute final size with alignment */ |
414 | for (i = 0; i < count; i++) | 525 | for (i = 0; i < bld->count; i++) |
415 | { | 526 | { |
416 | psize = size; | 527 | psize = size; |
417 | size += sizes[perm[i]]; | 528 | size += sizes[perm[i]]; |
418 | size = do_align (psize, size); | 529 | size = do_align (psize, size); |
419 | } | 530 | } |
420 | *len = size; | 531 | *rsize = size; |
421 | *data = GNUNET_malloc (size); | 532 | data = GNUNET_malloc (size); |
422 | memset (*data, 0, size); | 533 | *rdata = data; |
423 | 534 | memcpy (data, GNUNET_DIRECTORY_MAGIC, 8); | |
424 | pos = 8; | 535 | off = 8; |
425 | memcpy (*data, GNUNET_DIRECTORY_MAGIC, 8); | ||
426 | 536 | ||
427 | ret = GNUNET_CONTAINER_meta_data_serialize (meta, | 537 | ret = GNUNET_CONTAINER_meta_data_serialize (meta, |
428 | &(*data)[pos + | 538 | &(*data)[off + |
429 | sizeof (unsigned int)], | 539 | sizeof (uint32_t)], |
430 | size - pos - sizeof (unsigned int), | 540 | size - pos - sizeof (uint32_t), |
431 | GNUNET_SERIALIZE_FULL); | 541 | GNUNET_SERIALIZE_FULL); |
432 | GNUNET_assert (ret != GNUNET_SYSERR); | 542 | GNUNET_assert (ret != -1); |
433 | ret = htonl (ret); | 543 | big = htonl (ret); |
434 | memcpy (&(*data)[pos], &ret, sizeof (unsigned int)); | 544 | memcpy (&(*data)[8], &big, sizeof (uint32_t)); |
435 | pos += ntohl (ret) + sizeof (unsigned int); | 545 | pos += sizeof (uint32_t) + ret; |
436 | |||
437 | for (j = 0; j < count; j++) | 546 | for (j = 0; j < count; j++) |
438 | { | 547 | { |
439 | i = perm[j]; | 548 | i = perm[j]; |
440 | psize = pos; | 549 | psize = pos; |
441 | pos += sizes[i]; | 550 | pos += sizes[i]; |
442 | pos = do_align (psize, pos); | 551 | pos = do_align (psize, pos); |
443 | pos -= sizes[i]; /* go back to beginning */ | 552 | memcpy (&data[pos - sizes[i]], |
444 | memcpy (&(*data)[pos], ucs[i], strlen (ucs[i]) + 1); | 553 | &(bes[i])[1], |
445 | pos += strlen (ucs[i]) + 1; | 554 | sizes[i]); |
446 | GNUNET_free (ucs[i]); | 555 | GNUNET_free (bes[i]); |
447 | ret = GNUNET_CONTAINER_meta_data_serialize (mds[i], | ||
448 | &(*data)[pos + | ||
449 | sizeof (unsigned int)], | ||
450 | size - pos - | ||
451 | sizeof (unsigned int), | ||
452 | GNUNET_SERIALIZE_FULL); | ||
453 | GNUNET_assert (ret != GNUNET_SYSERR); | ||
454 | ret = htonl (ret); | ||
455 | memcpy (&(*data)[pos], &ret, sizeof (unsigned int)); | ||
456 | pos += ntohl (ret) + sizeof (unsigned int); | ||
457 | } | 556 | } |
458 | GNUNET_free (sizes); | 557 | GNUNET_free (sizes); |
459 | GNUNET_free (perm); | 558 | GNUNET_free (perm); |
460 | GNUNET_free (ucs); | 559 | GNUNET_free (bes); |
461 | GNUNET_assert (pos == size); | 560 | GNUNET_assert (pos == size); |
462 | return GNUNET_OK; | 561 | GNUNET_CONTAINER_meta_data_destroy (bld->meta); |
562 | GNUNET_free (bld); | ||
463 | } | 563 | } |
464 | 564 | ||
465 | 565 | ||
466 | #endif | ||
467 | |||
468 | /* end of fs_directory.c */ | 566 | /* end of fs_directory.c */ |
diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c index 540b518dc..60bcc2529 100644 --- a/src/fs/fs_file_information.c +++ b/src/fs/fs_file_information.c | |||
@@ -804,6 +804,7 @@ GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi, | |||
804 | &fi->priority, | 804 | &fi->priority, |
805 | &fi->expirationTime, | 805 | &fi->expirationTime, |
806 | &fi->client_info); | 806 | &fi->client_info); |
807 | GNUNET_free_non_null (fi->data.dir.dir_data); | ||
807 | GNUNET_free (fi->data.dir.dirname); | 808 | GNUNET_free (fi->data.dir.dirname); |
808 | } | 809 | } |
809 | else | 810 | else |
@@ -821,7 +822,7 @@ GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi, | |||
821 | &fi->expirationTime, | 822 | &fi->expirationTime, |
822 | &fi->client_info); | 823 | &fi->client_info); |
823 | } | 824 | } |
824 | 825 | GNUNET_free_non_null (fi->chk_tree); | |
825 | /* clean up serialization */ | 826 | /* clean up serialization */ |
826 | if (0 != UNLINK (fi->serialization)) | 827 | if (0 != UNLINK (fi->serialization)) |
827 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 828 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, |
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 7696dd940..0078d0d32 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.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, 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 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 |
@@ -24,15 +24,394 @@ | |||
24 | * @see http://gnunet.org/encoding.php3 | 24 | * @see http://gnunet.org/encoding.php3 |
25 | * @author Krista Bennett | 25 | * @author Krista Bennett |
26 | * @author Christian Grothoff | 26 | * @author Christian Grothoff |
27 | * | ||
28 | * TODO: | ||
29 | * - directory creation | ||
30 | * - KBlocks | ||
31 | * - SBlocks | ||
32 | * - indexing support | ||
33 | * - calling of progress function | ||
34 | * - handling of IO errors (emsg) | ||
35 | * - code-sharing with unindex | ||
36 | * - datastore reservation support | ||
37 | * - persistence support | ||
27 | */ | 38 | */ |
28 | 39 | ||
29 | #include "platform.h" | 40 | #include "platform.h" |
41 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_util_lib.h" | 42 | #include "gnunet_util_lib.h" |
31 | #include "gnunet_fs_service.h" | 43 | #include "gnunet_fs_service.h" |
32 | #include "fs.h" | 44 | #include "fs.h" |
33 | 45 | ||
34 | #define DEBUG_PUBLISH GNUNET_YES | 46 | #define DEBUG_PUBLISH GNUNET_YES |
35 | 47 | ||
48 | /** | ||
49 | * Main function that performs the upload. | ||
50 | * @param cls "struct GNUNET_FS_PublishContext" identifies the upload | ||
51 | * @param tc task context | ||
52 | */ | ||
53 | static void | ||
54 | do_upload (void *cls, | ||
55 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Context for "ds_put_cont". | ||
60 | */ | ||
61 | struct PutContCtx | ||
62 | { | ||
63 | /** | ||
64 | * Publishing context for which the datastore | ||
65 | * PUT request was executed. | ||
66 | */ | ||
67 | struct GNUNET_FS_PublishContext *sc; | ||
68 | |||
69 | /** | ||
70 | * Specific file with the block. | ||
71 | */ | ||
72 | struct GNUNET_FS_FileInformation *p; | ||
73 | |||
74 | /** | ||
75 | * Function to run next, if any (can be NULL). | ||
76 | */ | ||
77 | GNUNET_SCHEDULER_Task cont; | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * Function called by the datastore API with | ||
82 | * the result from the PUT request. | ||
83 | * | ||
84 | * @param cls our closure | ||
85 | * @param success GNUNET_OK on success | ||
86 | * @param msg error message (or NULL) | ||
87 | */ | ||
88 | static void | ||
89 | ds_put_cont (void *cls, | ||
90 | int success, | ||
91 | const char *msg) | ||
92 | { | ||
93 | struct PutContCtx *pcc = cls; | ||
94 | |||
95 | if (GNUNET_OK != success) | ||
96 | { | ||
97 | // FIXME: call progress CB with error | ||
98 | // FIXME: update pcc->p to indicate abort | ||
99 | GNUNET_FS_file_information_sync (pcc->p); | ||
100 | return; | ||
101 | } | ||
102 | GNUNET_FS_file_information_sync (pcc->p); | ||
103 | if (NULL != pcc->cont) | ||
104 | pcc->sc->upload_task | ||
105 | = GNUNET_SCHEDULER_add_delayed (pcc->sc->h->sched, | ||
106 | GNUNET_NO, | ||
107 | GNUNET_SCHEDULER_PRIORITY_BACKGROUND, | ||
108 | GNUNET_SCHEDULER_NO_TASK, | ||
109 | GNUNET_TIME_UNIT_ZERO, | ||
110 | pcc->cont, | ||
111 | pcc->sc); | ||
112 | GNUNET_free (pcc); | ||
113 | } | ||
114 | |||
115 | |||
116 | /** | ||
117 | * We need to publish a specific block. Do it. Then continue with | ||
118 | * the main task. | ||
119 | * | ||
120 | * @param sc overall upload data | ||
121 | * @param p file that the block belongs to (needed for options!) | ||
122 | * @param blk encoded block to publish | ||
123 | * @param blk_size size of the block | ||
124 | * @param blk_type type of the block | ||
125 | * @param cont function to run when done | ||
126 | */ | ||
127 | static void | ||
128 | publish_block (struct GNUNET_FS_PublishContext *sc, | ||
129 | struct GNUNET_FS_FileInformation *p, | ||
130 | const void* blk, | ||
131 | uint16_t blk_size, | ||
132 | uint32_t blk_type, | ||
133 | GNUNET_SCHEDULER_Task cont) | ||
134 | { | ||
135 | struct GNUNET_HashCode key; | ||
136 | |||
137 | // FIXME: GNUNET_FS_get_key (blk_type, blk, blk_size, &key); | ||
138 | // (or add "key" as argument to reduce hashing?) | ||
139 | dpc_cls = GNUNET_malloc(sizeof(struct PutContCtx)); | ||
140 | dpc_cls->cont = cont; | ||
141 | dpc_cls->sc = sc; | ||
142 | dpc_cls->p = p; | ||
143 | // FIXME: need to do something to "sc" to mark | ||
144 | // that "sc" can not be freed right now due to this | ||
145 | // pending, scheduled operation for which we don't have | ||
146 | // a task ID! | ||
147 | GNUNET_DATASTORE_put (sc->dsh, | ||
148 | sc->rid, | ||
149 | &key, | ||
150 | blk_size, | ||
151 | blk_type, | ||
152 | p->priority, | ||
153 | p->anonymity, | ||
154 | p->expirationTime, | ||
155 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
156 | &ds_put_cont, | ||
157 | dpc_cls); | ||
158 | } | ||
159 | |||
160 | |||
161 | /** | ||
162 | * We are almost done publishing the structure, | ||
163 | * add SBlocks (if needed). | ||
164 | * | ||
165 | * @param sc overall upload data | ||
166 | */ | ||
167 | static void | ||
168 | publish_sblock (struct GNUNET_FS_PublishContext *sc) | ||
169 | { | ||
170 | struct GNUNET_FS_FileInformation *p; | ||
171 | p = sc->fi; | ||
172 | |||
173 | // FIXME: build sblock & call publish_block! | ||
174 | |||
175 | // FIXME: continuation should | ||
176 | // be releasing the datastore reserve | ||
177 | // (once implemented) | ||
178 | } | ||
179 | |||
180 | |||
181 | /** | ||
182 | * We have uploaded a file or directory; now publish | ||
183 | * the KBlocks in the global keyword space so that | ||
184 | * it can be found. Then continue with the | ||
185 | * main task. | ||
186 | * | ||
187 | * @param sc overall upload data | ||
188 | * @param p specific file or directory for which kblocks | ||
189 | * should be created | ||
190 | */ | ||
191 | static void | ||
192 | publish_kblocks (struct GNUNET_FS_PublishContext *sc, | ||
193 | struct GNUNET_FS_FileInformation *p) | ||
194 | { | ||
195 | // FIXME: build all kblocks | ||
196 | // call publish_kblock on each | ||
197 | // last continuation should then call the main continuation again | ||
198 | } | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Compute the depth of the CHK tree. | ||
203 | * | ||
204 | * @param flen file length for which to compute the depth | ||
205 | * @return depth of the tree | ||
206 | */ | ||
207 | static unsigned int | ||
208 | compute_depth (uint64_t flen) | ||
209 | { | ||
210 | unsigned int treeDepth; | ||
211 | uint64_t fl; | ||
212 | |||
213 | treeDepth = 1; | ||
214 | fl = GNUNET_FS_DBLOCK_SIZE; | ||
215 | while (fl < flen) | ||
216 | { | ||
217 | treeDepth++; | ||
218 | if (fl * GNUNET_FS_CHK_PER_INODE < fl) | ||
219 | { | ||
220 | /* integer overflow, this is a HUGE file... */ | ||
221 | return treeDepth; | ||
222 | } | ||
223 | fl = fl * GNUNET_FS_CHK_PER_INODE; | ||
224 | } | ||
225 | return treeDepth; | ||
226 | } | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Compute the size of the current IBlock. | ||
231 | * | ||
232 | * @param height height of the IBlock in the tree (aka overall | ||
233 | * number of tree levels minus depth); 0 == DBlock | ||
234 | * @param offset current offset in the overall file | ||
235 | * @return size of the corresponding IBlock | ||
236 | */ | ||
237 | static uint16_t | ||
238 | compute_iblock_size (unsigned int height, | ||
239 | uint64_t offset) | ||
240 | { | ||
241 | unsigned int ret; | ||
242 | unsigned int i; | ||
243 | uint64_t mod; | ||
244 | uint64_t bds; | ||
245 | |||
246 | GNUNET_assert (height > 0); | ||
247 | bds = GNUNET_FS_DBLOCK_SIZE; /* number of bytes each CHK at level "i" | ||
248 | corresponds to */ | ||
249 | for (i=0;i<height;i++) | ||
250 | bds *= GNUNET_FS_CHK_PER_INODE; | ||
251 | mod = offset % bds; | ||
252 | if (0 == mod) | ||
253 | { | ||
254 | /* we were triggered at the end of a full block */ | ||
255 | ret = GNUNET_FS_CHK_PER_INODE; | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | /* we were triggered at the end of the file */ | ||
260 | bds /= GNUNET_FS_CHK_PER_INODE; | ||
261 | ret = mod / bds; | ||
262 | if (0 != mod % bds) | ||
263 | ret++; | ||
264 | } | ||
265 | return (uint16_t) (ret * sizeof(struct ContentHashKey)); | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Compute the offset of the CHK for the | ||
271 | * current block in the IBlock above. | ||
272 | * | ||
273 | * @param height height of the IBlock in the tree (aka overall | ||
274 | * number of tree levels minus depth); 0 == DBlock | ||
275 | * @param offset current offset in the overall file | ||
276 | * @return (array of CHKs') offset in the above IBlock | ||
277 | */ | ||
278 | static unsigned int | ||
279 | compute_chk_offset (unsigned int height, | ||
280 | uint64_t offset) | ||
281 | { | ||
282 | uint64_t bds; | ||
283 | unsigned int ret; | ||
284 | |||
285 | bds = GNUNET_FS_DBLOCK_SIZE; /* number of bytes each CHK at level "i" | ||
286 | corresponds to */ | ||
287 | for (i=0;i<height;i++) | ||
288 | bds *= GNUNET_FS_CHK_PER_INODE; | ||
289 | GNUNET_assert (0 == (offset % bds)); | ||
290 | ret = offset / bds; | ||
291 | return ret % GNUNET_FS_CHK_PER_INODE; | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * We are uploading a file or directory; load (if necessary) the next | ||
297 | * block into memory, encrypt it and send it to the FS service. Then | ||
298 | * continue with the main task. | ||
299 | * | ||
300 | * @param sc overall upload data | ||
301 | * @param p specific file or directory for which kblocks | ||
302 | * should be created | ||
303 | */ | ||
304 | static void | ||
305 | publish_content (struct GNUNET_FS_PublishContext *sc, | ||
306 | struct GNUNET_FS_FileInformation *p) | ||
307 | { | ||
308 | struct ContentHashKey *chk; | ||
309 | const void *pt_block; | ||
310 | uint16_t pt_size; | ||
311 | char *emsg; | ||
312 | char iob[GNUNET_FS_DBLOCK_SIZE]; | ||
313 | char enc[GNUNET_FS_DBLOCK_SIZE]; | ||
314 | struct GNUNET_CRYPTO_AesSessionKey sk; | ||
315 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
316 | uint64_t size; | ||
317 | unsigned int off; | ||
318 | |||
319 | // FIXME: figure out how to share this code | ||
320 | // with unindex! | ||
321 | size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; | ||
322 | if (NULL == p->chk_tree) | ||
323 | { | ||
324 | if (p->is_directory) | ||
325 | { | ||
326 | /* FIXME: create function to create directory | ||
327 | and use that API here! */ | ||
328 | GNUNET_FS_directory_create (&p->data.dir.dir_size, | ||
329 | &p->data.dir.dir_data, | ||
330 | p->meta, | ||
331 | &directory_entry_lister, | ||
332 | p->data.dir.entries); | ||
333 | size = p->data.dir.data_size; | ||
334 | } | ||
335 | p->chk_tree_depth = compute_depth (size); | ||
336 | p->chk_tree = GNUNET_malloc (p->chk_tree_depth * | ||
337 | sizeof (struct ContentHashKey) * | ||
338 | GNUNET_FS_CHK_PER_INODE); | ||
339 | p->current_depth = p->chk_tree_depth; | ||
340 | } | ||
341 | if (p->current_depth == p->chk_tree_depth) | ||
342 | { | ||
343 | if (p->is_directory) | ||
344 | { | ||
345 | pt_size = GNUNET_MIN(GNUNET_FS_DBLOCK_SIZE, | ||
346 | p->data.dir.dir_size - p->publish_offset); | ||
347 | pt_block = &p->data.dir.dir_data[p->publish_offset]; | ||
348 | } | ||
349 | else | ||
350 | { | ||
351 | pt_size = GNUNET_MIN(GNUNET_FS_DBLOCK_SIZE, | ||
352 | p->data.file.file_size - p->publish_offset); | ||
353 | p->data.file.reader (p->data.file.reader_cls, | ||
354 | p->publish_offset, | ||
355 | pt_size, | ||
356 | iob, | ||
357 | &emsg); | ||
358 | pt_block = iob; | ||
359 | } | ||
360 | } | ||
361 | else | ||
362 | { | ||
363 | pt_size = compute_iblock_size (p->chk_tree_depth - p->current_depth, | ||
364 | p->publish_offset); | ||
365 | pt_block = &p->chk_tree[p->current_depth * | ||
366 | GNUNET_FS_CHK_PER_INODE]; | ||
367 | } | ||
368 | off = compute_chk_offset (p->chk_tree_depth - p->current_depth, | ||
369 | p->publish_offset); | ||
370 | chk = &p->chk_tree[(p->current_depth-1)*GNUNET_FS_CHK_PER_INODE+off]; | ||
371 | GNUNET_CRYPTO_hash (pt_block, pt_size, &chk->key); | ||
372 | GNUNET_CRYPTO_hash_to_aes_key (&chk->key, &sk, &iv); | ||
373 | GNUNET_CRYPTO_aes_encrypt (pt_block, | ||
374 | pt_size, | ||
375 | &sk, | ||
376 | &iv, | ||
377 | enc); | ||
378 | // NOTE: this call (and progress below) is all that really differs | ||
379 | // between publish/unindex! Parameterize & move this code! | ||
380 | // FIXME: something around here would need to change | ||
381 | // for indexing! | ||
382 | publish_block (sc, p, enc, pt_size, | ||
383 | (p->current_depth == p->chk_tree_depth) | ||
384 | ? GNUNET_DATASTORE_BLOCKTYPE_DBLOCK | ||
385 | : GNUNET_DATASTORE_BLOCKTYPE_IBLOCK, | ||
386 | &do_upload); | ||
387 | // FIXME: should call progress function somewhere here! | ||
388 | GNUNET_CRYPTO_hash (enc, pt_size, &chk->query); | ||
389 | if (p->current_depth == p->chk_tree_depth) | ||
390 | { | ||
391 | p->publish_offset += pt_size; | ||
392 | if ( (p->publish_offset == size) || | ||
393 | (0 == p->publish_offset % (GNUNET_FS_CHK_PER_INODE * GNUNET_FS_DBLOCK_SIZE) ) ) | ||
394 | p->current_depth--; | ||
395 | } | ||
396 | else | ||
397 | { | ||
398 | if ( (off == GNUNET_FS_CHK_PER_INODE) || | ||
399 | (p->publish_offset == size) ) | ||
400 | p->current_depth--; | ||
401 | else | ||
402 | p->current_depth = p->chk_tree_depth; | ||
403 | } | ||
404 | if (0 == p->current_depth) | ||
405 | { | ||
406 | p->chk_uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); | ||
407 | p->chk_uri.type = chk; | ||
408 | p->chk_uri.data.chk.chk = p->chk_tree[0]; | ||
409 | p->chk_uri.data.chk.file_length = size; | ||
410 | GNUNET_free (p->chk_tree); | ||
411 | p->chk_tree = NULL; | ||
412 | } | ||
413 | } | ||
414 | |||
36 | 415 | ||
37 | /** | 416 | /** |
38 | * Main function that performs the upload. | 417 | * Main function that performs the upload. |
@@ -44,11 +423,36 @@ do_upload (void *cls, | |||
44 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 423 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
45 | { | 424 | { |
46 | struct GNUNET_FS_PublishContext *sc = cls; | 425 | struct GNUNET_FS_PublishContext *sc = cls; |
426 | struct GNUNET_FS_FileInformation *p; | ||
47 | 427 | ||
48 | sc->upload_task = GNUNET_SCHEDULER_NO_TASK; | 428 | sc->upload_task = GNUNET_SCHEDULER_NO_TASK; |
49 | 429 | p = sc->fi_pos; | |
50 | // FIXME: find next block, process, schedule | 430 | if (NULL == p) |
51 | // transmission to FS service | 431 | { |
432 | /* upload of entire hierarchy complete, | ||
433 | publish namespace entries */ | ||
434 | publish_sblock (sc); | ||
435 | return; | ||
436 | } | ||
437 | if (NULL != p->chk_uri) | ||
438 | { | ||
439 | /* move on to next file */ | ||
440 | if (NULL != p->next) | ||
441 | sc->fi_pos = p->next; | ||
442 | else | ||
443 | sc->fi_pos = p->dir; | ||
444 | /* upload of "p" complete, publish KBlocks! */ | ||
445 | publish_kblocks (sc, p); | ||
446 | return; | ||
447 | } | ||
448 | if (p->do_index) | ||
449 | { | ||
450 | // FIXME: need to pre-compute hash over | ||
451 | // the entire file and ask FS to prepare | ||
452 | // for indexing! | ||
453 | return; | ||
454 | } | ||
455 | publish_content (sc, p); | ||
52 | } | 456 | } |
53 | 457 | ||
54 | 458 | ||
@@ -75,8 +479,15 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, | |||
75 | const char *nuid) | 479 | const char *nuid) |
76 | { | 480 | { |
77 | struct GNUNET_FS_PublishContext *ret; | 481 | struct GNUNET_FS_PublishContext *ret; |
482 | struct GNUNET_FS_FileInformation *p; | ||
483 | struct GNUNET_DATASTORE_Handle *dsh; | ||
78 | 484 | ||
485 | dsh = GNUNET_DATASTORE_connect (h->cfg, | ||
486 | h->sched); | ||
487 | if (NULL == dsh) | ||
488 | return NULL; | ||
79 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); | 489 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); |
490 | ret->dsh = dsh; | ||
80 | ret->h = h; | 491 | ret->h = h; |
81 | ret->client_ctx = ctx; | 492 | ret->client_ctx = ctx; |
82 | ret->fi = fi; | 493 | ret->fi = fi; |
@@ -90,6 +501,17 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, | |||
90 | ret->nuid = GNUNET_strdup (nuid); | 501 | ret->nuid = GNUNET_strdup (nuid); |
91 | } | 502 | } |
92 | // FIXME: make upload persistent! | 503 | // FIXME: make upload persistent! |
504 | |||
505 | /* find first leaf, DFS */ | ||
506 | p = ret->fi; | ||
507 | while ( (p->is_directory) && | ||
508 | (NULL != p->data.dir.entries) ) | ||
509 | p = p->data.dir.entries; | ||
510 | ret->fi_pos = p; | ||
511 | |||
512 | // FIXME: calculate space needed for "fi" | ||
513 | // and reserve as first task (then trigger | ||
514 | // "do_upload" from that continuation)! | ||
93 | ret->upload_task | 515 | ret->upload_task |
94 | = GNUNET_SCHEDULER_add_delayed (h->sched, | 516 | = GNUNET_SCHEDULER_add_delayed (h->sched, |
95 | GNUNET_NO, | 517 | GNUNET_NO, |
@@ -120,429 +542,8 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *sc) | |||
120 | GNUNET_FS_namespace_delete (sc->namespace, GNUNET_NO); | 542 | GNUNET_FS_namespace_delete (sc->namespace, GNUNET_NO); |
121 | GNUNET_free_non_null (sc->nid); | 543 | GNUNET_free_non_null (sc->nid); |
122 | GNUNET_free_non_null (sc->nuid); | 544 | GNUNET_free_non_null (sc->nuid); |
545 | GNUNET_DATASTORE_disconnect (sc->dsh); | ||
123 | GNUNET_free (sc); | 546 | GNUNET_free (sc); |
124 | } | 547 | } |
125 | 548 | ||
126 | |||
127 | #if 0 | ||
128 | |||
129 | /** | ||
130 | * Append the given key and query to the iblock[level]. If | ||
131 | * iblock[level] is already full, compute its chk and push it to | ||
132 | * level+1 and clear the level. iblocks is guaranteed to be big | ||
133 | * enough. | ||
134 | */ | ||
135 | static int | ||
136 | pushBlock (struct GNUNET_ClientServerConnection *sock, | ||
137 | const GNUNET_EC_ContentHashKey * chk, | ||
138 | unsigned int level, | ||
139 | GNUNET_DatastoreValue ** iblocks, | ||
140 | unsigned int prio, GNUNET_CronTime expirationTime) | ||
141 | { | ||
142 | unsigned int size; | ||
143 | unsigned int present; | ||
144 | GNUNET_DatastoreValue *value; | ||
145 | GNUNET_EC_DBlock *db; | ||
146 | GNUNET_EC_ContentHashKey ichk; | ||
147 | |||
148 | size = ntohl (iblocks[level]->size); | ||
149 | GNUNET_GE_ASSERT (NULL, size > sizeof (GNUNET_DatastoreValue)); | ||
150 | size -= sizeof (GNUNET_DatastoreValue); | ||
151 | GNUNET_GE_ASSERT (NULL, | ||
152 | size - sizeof (GNUNET_EC_DBlock) <= | ||
153 | GNUNET_ECRS_IBLOCK_SIZE); | ||
154 | present = | ||
155 | (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey); | ||
156 | db = (GNUNET_EC_DBlock *) & iblocks[level][1]; | ||
157 | if (present == GNUNET_ECRS_CHK_PER_INODE) | ||
158 | { | ||
159 | GNUNET_EC_file_block_get_key (db, size, &ichk.key); | ||
160 | GNUNET_EC_file_block_get_query (db, size, &ichk.query); | ||
161 | if (GNUNET_OK != pushBlock (sock, | ||
162 | &ichk, level + 1, iblocks, prio, | ||
163 | expirationTime)) | ||
164 | return GNUNET_SYSERR; | ||
165 | GNUNET_EC_file_block_encode (db, size, &ichk.query, &value); | ||
166 | if (value == NULL) | ||
167 | { | ||
168 | GNUNET_GE_BREAK (NULL, 0); | ||
169 | return GNUNET_SYSERR; | ||
170 | } | ||
171 | value->priority = htonl (prio); | ||
172 | value->expiration_time = GNUNET_htonll (expirationTime); | ||
173 | if (GNUNET_OK != GNUNET_FS_insert (sock, value)) | ||
174 | { | ||
175 | GNUNET_free (value); | ||
176 | return GNUNET_SYSERR; | ||
177 | } | ||
178 | GNUNET_free (value); | ||
179 | size = sizeof (GNUNET_EC_DBlock); /* type */ | ||
180 | } | ||
181 | /* append GNUNET_EC_ContentHashKey */ | ||
182 | memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey)); | ||
183 | size += sizeof (GNUNET_EC_ContentHashKey) + sizeof (GNUNET_DatastoreValue); | ||
184 | GNUNET_GE_ASSERT (NULL, size < GNUNET_MAX_BUFFER_SIZE); | ||
185 | iblocks[level]->size = htonl (size); | ||
186 | |||
187 | return GNUNET_OK; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Index or insert a file. | ||
192 | * | ||
193 | * @param priority what is the priority for OUR node to | ||
194 | * keep this file available? Use 0 for maximum anonymity and | ||
195 | * minimum reliability... | ||
196 | * @param doIndex GNUNET_YES for index, GNUNET_NO for insertion, | ||
197 | * GNUNET_SYSERR for simulation | ||
198 | * @param uri set to the URI of the uploaded file | ||
199 | * @return GNUNET_SYSERR if the upload failed (i.e. not enough space | ||
200 | * or gnunetd not running) | ||
201 | */ | ||
202 | int | ||
203 | GNUNET_ECRS_file_upload (struct GNUNET_GE_Context *ectx, | ||
204 | struct GNUNET_GC_Configuration *cfg, | ||
205 | const char *filename, | ||
206 | int doIndex, | ||
207 | unsigned int anonymityLevel, | ||
208 | unsigned int priority, | ||
209 | GNUNET_CronTime expirationTime, | ||
210 | GNUNET_ECRS_UploadProgressCallback upcb, | ||
211 | void *upcbClosure, | ||
212 | GNUNET_ECRS_TestTerminate tt, | ||
213 | void *ttClosure, struct GNUNET_ECRS_URI **uri) | ||
214 | { | ||
215 | unsigned long long filesize; | ||
216 | unsigned long long pos; | ||
217 | unsigned int treedepth; | ||
218 | int fd; | ||
219 | int i; | ||
220 | int ret; | ||
221 | unsigned int size; | ||
222 | GNUNET_DatastoreValue **iblocks; | ||
223 | GNUNET_DatastoreValue *dblock; | ||
224 | GNUNET_EC_DBlock *db; | ||
225 | GNUNET_DatastoreValue *value; | ||
226 | struct GNUNET_ClientServerConnection *sock; | ||
227 | GNUNET_HashCode fileId; | ||
228 | GNUNET_EC_ContentHashKey mchk; | ||
229 | GNUNET_CronTime eta; | ||
230 | GNUNET_CronTime start; | ||
231 | GNUNET_CronTime now; | ||
232 | GNUNET_EC_FileIdentifier fid; | ||
233 | #if DEBUG_UPLOAD | ||
234 | GNUNET_EncName enc; | ||
235 | #endif | ||
236 | |||
237 | GNUNET_GE_ASSERT (ectx, cfg != NULL); | ||
238 | start = GNUNET_get_time (); | ||
239 | memset (&mchk, 0, sizeof (GNUNET_EC_ContentHashKey)); | ||
240 | if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename)) | ||
241 | { | ||
242 | GNUNET_GE_LOG (ectx, | ||
243 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
244 | _("`%s' is not a file.\n"), filename); | ||
245 | return GNUNET_SYSERR; | ||
246 | } | ||
247 | if (GNUNET_OK != | ||
248 | GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES)) | ||
249 | { | ||
250 | GNUNET_GE_LOG (ectx, | ||
251 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
252 | _("Cannot get size of file `%s'"), filename); | ||
253 | |||
254 | return GNUNET_SYSERR; | ||
255 | } | ||
256 | sock = GNUNET_client_connection_create (ectx, cfg); | ||
257 | if (sock == NULL) | ||
258 | { | ||
259 | GNUNET_GE_LOG (ectx, | ||
260 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
261 | _("Failed to connect to gnunetd.")); | ||
262 | return GNUNET_SYSERR; | ||
263 | } | ||
264 | eta = 0; | ||
265 | if (upcb != NULL) | ||
266 | upcb (filesize, 0, eta, upcbClosure); | ||
267 | if (doIndex == GNUNET_YES) | ||
268 | { | ||
269 | if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId)) | ||
270 | { | ||
271 | GNUNET_GE_LOG (ectx, | ||
272 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
273 | _("Cannot hash `%s'.\n"), filename); | ||
274 | |||
275 | GNUNET_client_connection_destroy (sock); | ||
276 | return GNUNET_SYSERR; | ||
277 | } | ||
278 | if (GNUNET_YES == GNUNET_FS_test_indexed (sock, &fileId)) | ||
279 | { | ||
280 | /* file already indexed; simulate only to get the URI! */ | ||
281 | doIndex = GNUNET_SYSERR; | ||
282 | } | ||
283 | } | ||
284 | if (doIndex == GNUNET_YES) | ||
285 | { | ||
286 | now = GNUNET_get_time (); | ||
287 | eta = now + 2 * (now - start); | ||
288 | /* very rough estimate: GNUNET_hash reads once through the file, | ||
289 | we'll do that once more and write it. But of course | ||
290 | the second read may be cached, and we have the encryption, | ||
291 | so a factor of two is really, really just a rough estimate */ | ||
292 | start = now; | ||
293 | /* reset the counter since the formula later does not | ||
294 | take the time for GNUNET_hash_file into account */ | ||
295 | |||
296 | switch (GNUNET_FS_prepare_to_index (sock, &fileId, filename)) | ||
297 | { | ||
298 | case GNUNET_SYSERR: | ||
299 | GNUNET_GE_LOG (ectx, | ||
300 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
301 | _("Initialization for indexing file `%s' failed.\n"), | ||
302 | filename); | ||
303 | GNUNET_client_connection_destroy (sock); | ||
304 | return GNUNET_SYSERR; | ||
305 | case GNUNET_NO: | ||
306 | GNUNET_GE_LOG (ectx, | ||
307 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
308 | _ | ||
309 | ("Indexing file `%s' failed. Suggestion: try to insert the file.\n"), | ||
310 | filename); | ||
311 | GNUNET_client_connection_destroy (sock); | ||
312 | return GNUNET_SYSERR; | ||
313 | default: | ||
314 | break; | ||
315 | } | ||
316 | } | ||
317 | treedepth = GNUNET_ECRS_compute_depth (filesize); | ||
318 | fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE); | ||
319 | if (fd == -1) | ||
320 | { | ||
321 | GNUNET_GE_LOG (ectx, | ||
322 | GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, | ||
323 | _("Cannot open file `%s': `%s'"), filename, | ||
324 | STRERROR (errno)); | ||
325 | |||
326 | GNUNET_client_connection_destroy (sock); | ||
327 | return GNUNET_SYSERR; | ||
328 | } | ||
329 | |||
330 | dblock = | ||
331 | GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE + | ||
332 | sizeof (GNUNET_EC_DBlock)); | ||
333 | dblock->size = | ||
334 | htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE + | ||
335 | sizeof (GNUNET_EC_DBlock)); | ||
336 | dblock->anonymity_level = htonl (anonymityLevel); | ||
337 | dblock->priority = htonl (priority); | ||
338 | dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA); | ||
339 | dblock->expiration_time = GNUNET_htonll (expirationTime); | ||
340 | db = (GNUNET_EC_DBlock *) & dblock[1]; | ||
341 | db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA); | ||
342 | iblocks = | ||
343 | GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1)); | ||
344 | for (i = 0; i <= treedepth; i++) | ||
345 | { | ||
346 | iblocks[i] = | ||
347 | GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + | ||
348 | GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock)); | ||
349 | iblocks[i]->size = | ||
350 | htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock)); | ||
351 | iblocks[i]->anonymity_level = htonl (anonymityLevel); | ||
352 | iblocks[i]->priority = htonl (priority); | ||
353 | iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA); | ||
354 | iblocks[i]->expiration_time = GNUNET_htonll (expirationTime); | ||
355 | ((GNUNET_EC_DBlock *) & iblocks[i][1])->type = | ||
356 | htonl (GNUNET_ECRS_BLOCKTYPE_DATA); | ||
357 | } | ||
358 | |||
359 | pos = 0; | ||
360 | while (pos < filesize) | ||
361 | { | ||
362 | if (upcb != NULL) | ||
363 | upcb (filesize, pos, eta, upcbClosure); | ||
364 | if (tt != NULL) | ||
365 | if (GNUNET_OK != tt (ttClosure)) | ||
366 | goto FAILURE; | ||
367 | size = GNUNET_ECRS_DBLOCK_SIZE; | ||
368 | if (size > filesize - pos) | ||
369 | { | ||
370 | size = filesize - pos; | ||
371 | memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE); | ||
372 | } | ||
373 | GNUNET_GE_ASSERT (ectx, | ||
374 | sizeof (GNUNET_DatastoreValue) + size + | ||
375 | sizeof (GNUNET_EC_DBlock) < GNUNET_MAX_BUFFER_SIZE); | ||
376 | dblock->size = | ||
377 | htonl (sizeof (GNUNET_DatastoreValue) + size + | ||
378 | sizeof (GNUNET_EC_DBlock)); | ||
379 | if (size != READ (fd, &db[1], size)) | ||
380 | { | ||
381 | GNUNET_GE_LOG_STRERROR_FILE (ectx, | ||
382 | GNUNET_GE_ERROR | GNUNET_GE_BULK | | ||
383 | GNUNET_GE_ADMIN | GNUNET_GE_USER, | ||
384 | "READ", filename); | ||
385 | goto FAILURE; | ||
386 | } | ||
387 | if (tt != NULL) | ||
388 | if (GNUNET_OK != tt (ttClosure)) | ||
389 | goto FAILURE; | ||
390 | GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock), | ||
391 | &mchk.key); | ||
392 | GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock), | ||
393 | &mchk.query); | ||
394 | #if DEBUG_UPLOAD | ||
395 | GNUNET_hash_to_enc (&mchk.query, &enc); | ||
396 | fprintf (stderr, | ||
397 | "Query for current block of size %u is `%s'\n", size, | ||
398 | (const char *) &enc); | ||
399 | #endif | ||
400 | if (doIndex == GNUNET_YES) | ||
401 | { | ||
402 | if (GNUNET_SYSERR == GNUNET_FS_index (sock, &fileId, dblock, pos)) | ||
403 | { | ||
404 | GNUNET_GE_LOG (ectx, | ||
405 | GNUNET_GE_ERROR | GNUNET_GE_BULK | | ||
406 | GNUNET_GE_USER, | ||
407 | _ | ||
408 | ("Indexing data of file `%s' failed at position %llu.\n"), | ||
409 | filename, pos); | ||
410 | goto FAILURE; | ||
411 | } | ||
412 | } | ||
413 | else | ||
414 | { | ||
415 | value = NULL; | ||
416 | if (GNUNET_OK != | ||
417 | GNUNET_EC_file_block_encode (db, | ||
418 | size + sizeof (GNUNET_EC_DBlock), | ||
419 | &mchk.query, &value)) | ||
420 | { | ||
421 | GNUNET_GE_BREAK (ectx, 0); | ||
422 | goto FAILURE; | ||
423 | } | ||
424 | GNUNET_GE_ASSERT (ectx, value != NULL); | ||
425 | *value = *dblock; /* copy options! */ | ||
426 | if ((doIndex == GNUNET_NO) && | ||
427 | (GNUNET_OK != (ret = GNUNET_FS_insert (sock, value)))) | ||
428 | { | ||
429 | GNUNET_GE_BREAK (ectx, ret == GNUNET_NO); | ||
430 | GNUNET_free (value); | ||
431 | goto FAILURE; | ||
432 | } | ||
433 | GNUNET_free (value); | ||
434 | } | ||
435 | pos += size; | ||
436 | now = GNUNET_get_time (); | ||
437 | if (pos > 0) | ||
438 | { | ||
439 | eta = (GNUNET_CronTime) (start + | ||
440 | (((double) (now - start) / (double) pos)) | ||
441 | * (double) filesize); | ||
442 | } | ||
443 | if (GNUNET_OK != pushBlock (sock, &mchk, 0, /* dblocks are on level 0 */ | ||
444 | iblocks, priority, expirationTime)) | ||
445 | goto FAILURE; | ||
446 | } | ||
447 | if (tt != NULL) | ||
448 | if (GNUNET_OK != tt (ttClosure)) | ||
449 | goto FAILURE; | ||
450 | #if DEBUG_UPLOAD | ||
451 | GNUNET_GE_LOG (ectx, | ||
452 | GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
453 | "Tree depth is %u, walking up tree.\n", treedepth); | ||
454 | #endif | ||
455 | for (i = 0; i < treedepth; i++) | ||
456 | { | ||
457 | size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue); | ||
458 | GNUNET_GE_ASSERT (ectx, size < GNUNET_MAX_BUFFER_SIZE); | ||
459 | if (size == sizeof (GNUNET_EC_DBlock)) | ||
460 | { | ||
461 | #if DEBUG_UPLOAD | ||
462 | GNUNET_GE_LOG (ectx, | ||
463 | GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
464 | "Level %u is empty\n", i); | ||
465 | #endif | ||
466 | continue; | ||
467 | } | ||
468 | db = (GNUNET_EC_DBlock *) & iblocks[i][1]; | ||
469 | GNUNET_EC_file_block_get_key (db, size, &mchk.key); | ||
470 | #if DEBUG_UPLOAD | ||
471 | GNUNET_GE_LOG (ectx, | ||
472 | GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
473 | "Computing query for %u bytes content.\n", size); | ||
474 | #endif | ||
475 | GNUNET_EC_file_block_get_query (db, size, &mchk.query); | ||
476 | #if DEBUG_UPLOAD | ||
477 | IF_GELOG (ectx, | ||
478 | GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
479 | GNUNET_hash_to_enc (&mchk.query, &enc)); | ||
480 | GNUNET_GE_LOG (ectx, | ||
481 | GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
482 | "Query for current block at level %u is `%s'.\n", i, | ||
483 | &enc); | ||
484 | #endif | ||
485 | if (GNUNET_OK != pushBlock (sock, | ||
486 | &mchk, i + 1, iblocks, priority, | ||
487 | expirationTime)) | ||
488 | { | ||
489 | GNUNET_GE_BREAK (ectx, 0); | ||
490 | goto FAILURE; | ||
491 | } | ||
492 | GNUNET_EC_file_block_encode (db, size, &mchk.query, &value); | ||
493 | if (value == NULL) | ||
494 | { | ||
495 | GNUNET_GE_BREAK (ectx, 0); | ||
496 | goto FAILURE; | ||
497 | } | ||
498 | value->expiration_time = GNUNET_htonll (expirationTime); | ||
499 | value->priority = htonl (priority); | ||
500 | if ((doIndex != GNUNET_SYSERR) && | ||
501 | (GNUNET_SYSERR == GNUNET_FS_insert (sock, value))) | ||
502 | { | ||
503 | GNUNET_GE_BREAK (ectx, 0); | ||
504 | GNUNET_free (value); | ||
505 | goto FAILURE; | ||
506 | } | ||
507 | GNUNET_free (value); | ||
508 | GNUNET_free (iblocks[i]); | ||
509 | iblocks[i] = NULL; | ||
510 | } | ||
511 | #if DEBUG_UPLOAD | ||
512 | IF_GELOG (ectx, | ||
513 | GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
514 | GNUNET_hash_to_enc (&mchk.query, &enc)); | ||
515 | GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, | ||
516 | "Query for top block is %s\n", &enc); | ||
517 | #endif | ||
518 | /* build URI */ | ||
519 | fid.file_length = GNUNET_htonll (filesize); | ||
520 | db = (GNUNET_EC_DBlock *) & iblocks[treedepth][1]; | ||
521 | |||
522 | fid.chk = *(GNUNET_EC_ContentHashKey *) & (db[1]); | ||
523 | *uri = GNUNET_malloc (sizeof (URI)); | ||
524 | (*uri)->type = chk; | ||
525 | (*uri)->data.fi = fid; | ||
526 | |||
527 | /* free resources */ | ||
528 | GNUNET_free_non_null (iblocks[treedepth]); | ||
529 | GNUNET_free (iblocks); | ||
530 | GNUNET_free (dblock); | ||
531 | if (upcb != NULL) | ||
532 | upcb (filesize, filesize, eta, upcbClosure); | ||
533 | CLOSE (fd); | ||
534 | GNUNET_client_connection_destroy (sock); | ||
535 | return GNUNET_OK; | ||
536 | FAILURE: | ||
537 | for (i = 0; i <= treedepth; i++) | ||
538 | GNUNET_free_non_null (iblocks[i]); | ||
539 | GNUNET_free (iblocks); | ||
540 | GNUNET_free (dblock); | ||
541 | CLOSE (fd); | ||
542 | GNUNET_client_connection_destroy (sock); | ||
543 | return GNUNET_SYSERR; | ||
544 | } | ||
545 | |||
546 | #endif | ||
547 | |||
548 | /* end of fs_publish.c */ | 549 | /* end of fs_publish.c */ |
diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h index 2c917cc59..bb122eb64 100644 --- a/src/include/gnunet_constants.h +++ b/src/include/gnunet_constants.h | |||
@@ -55,6 +55,13 @@ extern "C" | |||
55 | */ | 55 | */ |
56 | #define GNUNET_CONSTANTS_EXEC_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) | 56 | #define GNUNET_CONSTANTS_EXEC_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) |
57 | 57 | ||
58 | /** | ||
59 | * After how long do we consider a service irresponsive | ||
60 | * even if we assume that the service commonly does not | ||
61 | * respond instantly (DNS, Database, etc.). | ||
62 | */ | ||
63 | #define GNUNET_CONSTANTS_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10) | ||
64 | |||
58 | 65 | ||
59 | #if 0 /* keep Emacsens' auto-indent happy */ | 66 | #if 0 /* keep Emacsens' auto-indent happy */ |
60 | { | 67 | { |
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h index 291b99fa2..e2a0787c8 100644 --- a/src/include/gnunet_container_lib.h +++ b/src/include/gnunet_container_lib.h | |||
@@ -305,8 +305,8 @@ int GNUNET_CONTAINER_meta_data_extract_from_file (struct | |||
305 | 305 | ||
306 | enum GNUNET_CONTAINER_MetaDataSerializationOptions | 306 | enum GNUNET_CONTAINER_MetaDataSerializationOptions |
307 | { | 307 | { |
308 | GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL = GNUNET_NO, | 308 | GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL = 0, |
309 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART = GNUNET_YES, | 309 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART = 1, |
310 | GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS = 2 | 310 | GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS = 2 |
311 | }; | 311 | }; |
312 | 312 | ||
@@ -323,10 +323,11 @@ enum GNUNET_CONTAINER_MetaDataSerializationOptions | |||
323 | * GNUNET_SYSERR on error (typically: not enough | 323 | * GNUNET_SYSERR on error (typically: not enough |
324 | * space) | 324 | * space) |
325 | */ | 325 | */ |
326 | int GNUNET_CONTAINER_meta_data_serialize (const struct | 326 | ssize_t GNUNET_CONTAINER_meta_data_serialize (const struct |
327 | GNUNET_CONTAINER_MetaData *md, | 327 | GNUNET_CONTAINER_MetaData *md, |
328 | char *target, unsigned int size, | 328 | char *target, |
329 | enum | 329 | size_t size, |
330 | enum | ||
330 | GNUNET_CONTAINER_MetaDataSerializationOptions | 331 | GNUNET_CONTAINER_MetaDataSerializationOptions |
331 | opt); | 332 | opt); |
332 | 333 | ||
@@ -337,12 +338,12 @@ int GNUNET_CONTAINER_meta_data_serialize (const struct | |||
337 | * meta-data to match the size constraint, | 338 | * meta-data to match the size constraint, |
338 | * possibly discarding some data? | 339 | * possibly discarding some data? |
339 | */ | 340 | */ |
340 | unsigned int GNUNET_CONTAINER_meta_data_get_serialized_size (const struct | 341 | ssize_t GNUNET_CONTAINER_meta_data_get_serialized_size (const struct |
341 | GNUNET_CONTAINER_MetaData | 342 | GNUNET_CONTAINER_MetaData |
342 | *md, | 343 | *md, |
343 | enum | 344 | enum |
344 | GNUNET_CONTAINER_MetaDataSerializationOptions | 345 | GNUNET_CONTAINER_MetaDataSerializationOptions |
345 | opt); | 346 | opt); |
346 | 347 | ||
347 | /** | 348 | /** |
348 | * Deserialize meta-data. Initializes md. | 349 | * Deserialize meta-data. Initializes md. |
@@ -352,7 +353,7 @@ unsigned int GNUNET_CONTAINER_meta_data_get_serialized_size (const struct | |||
352 | */ | 353 | */ |
353 | struct GNUNET_CONTAINER_MetaData | 354 | struct GNUNET_CONTAINER_MetaData |
354 | *GNUNET_CONTAINER_meta_data_deserialize (const char *input, | 355 | *GNUNET_CONTAINER_meta_data_deserialize (const char *input, |
355 | unsigned int size); | 356 | size_t size); |
356 | 357 | ||
357 | /** | 358 | /** |
358 | * Does the meta-data claim that this is a directory? | 359 | * Does the meta-data claim that this is a directory? |
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 361d244e2..168c79b2a 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h | |||
@@ -394,7 +394,7 @@ void GNUNET_CRYPTO_hash_xor (const GNUNET_HashCode * a, | |||
394 | /** | 394 | /** |
395 | * Convert a hashcode into a key. | 395 | * Convert a hashcode into a key. |
396 | */ | 396 | */ |
397 | void GNUNET_CRYPTO_hash_to_AES_key (const GNUNET_HashCode * hc, | 397 | void GNUNET_CRYPTO_hash_to_aes_key (const GNUNET_HashCode * hc, |
398 | struct GNUNET_CRYPTO_AesSessionKey *skey, | 398 | struct GNUNET_CRYPTO_AesSessionKey *skey, |
399 | struct | 399 | struct |
400 | GNUNET_CRYPTO_AesInitializationVector | 400 | GNUNET_CRYPTO_AesInitializationVector |
diff --git a/src/include/gnunet_datastore_service.h b/src/include/gnunet_datastore_service.h index 28419126f..3805dea97 100644 --- a/src/include/gnunet_datastore_service.h +++ b/src/include/gnunet_datastore_service.h | |||
@@ -41,6 +41,12 @@ extern "C" | |||
41 | #endif | 41 | #endif |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #define GNUNET_DATASTORE_BLOCKTYPE_ANY 0 | ||
45 | #define GNUNET_DATASTORE_BLOCKTYPE_DBLOCK 1 | ||
46 | #define GNUNET_DATASTORE_BLOCKTYPE_IBLOCK 2 | ||
47 | #define GNUNET_DATASTORE_BLOCKTYPE_KBLOCK 3 | ||
48 | #define GNUNET_DATASTORE_BLOCKTYPE_SBLOCK 4 | ||
49 | #define GNUNET_DATASTORE_BLOCKTYPE_SKBLOCK 5 | ||
44 | 50 | ||
45 | /** | 51 | /** |
46 | * Handle to the datastore service. | 52 | * Handle to the datastore service. |
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index 4664c4cee..3c71d40e7 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h | |||
@@ -2169,6 +2169,52 @@ GNUNET_FS_directory_list_contents (size_t size, | |||
2169 | void *dep_cls); | 2169 | void *dep_cls); |
2170 | 2170 | ||
2171 | 2171 | ||
2172 | /** | ||
2173 | * Opaque handle to a directory builder. | ||
2174 | */ | ||
2175 | struct GNUNET_FS_DirectoryBuilder; | ||
2176 | |||
2177 | /** | ||
2178 | * Create a directory builder. | ||
2179 | * | ||
2180 | * @param mdir metadata for the directory | ||
2181 | */ | ||
2182 | struct GNUNET_FS_DirectoryBuilder * | ||
2183 | GNUNET_FS_directory_builder_create (const struct GNUNET_CONTAINER_MetaData *mdir); | ||
2184 | |||
2185 | |||
2186 | /** | ||
2187 | * Add an entry to a directory. | ||
2188 | * | ||
2189 | * @param bld directory to extend | ||
2190 | * @param uri uri of the entry (must not be a KSK) | ||
2191 | * @param md metadata of the entry | ||
2192 | * @param data raw data of the entry, can be NULL, otherwise | ||
2193 | * data must point to exactly the number of bytes specified | ||
2194 | * by the uri | ||
2195 | */ | ||
2196 | void | ||
2197 | GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld, | ||
2198 | const struct GNUNET_FS_Uri *uri, | ||
2199 | const struct GNUNET_CONTAINER_MetaData *md, | ||
2200 | const void *data); | ||
2201 | |||
2202 | |||
2203 | /** | ||
2204 | * Finish building the directory. Frees the | ||
2205 | * builder context and returns the directory | ||
2206 | * in-memory. | ||
2207 | * | ||
2208 | * @param bld directory to finish | ||
2209 | * @param size set to the number of bytes needed | ||
2210 | * @param data set to the encoded directory | ||
2211 | */ | ||
2212 | void | ||
2213 | GNUNET_FS_directory_builder_finish (struct GNUNET_FS_DirectoryBuilder *bld, | ||
2214 | size_t *size, | ||
2215 | void **data); | ||
2216 | |||
2217 | |||
2172 | #if 0 /* keep Emacsens' auto-indent happy */ | 2218 | #if 0 /* keep Emacsens' auto-indent happy */ |
2173 | { | 2219 | { |
2174 | #endif | 2220 | #endif |
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c index 6265fc142..d80c5fd2b 100644 --- a/src/util/container_meta_data.c +++ b/src/util/container_meta_data.c | |||
@@ -442,9 +442,9 @@ struct MetaDataHeader | |||
442 | * GNUNET_SYSERR on error (typically: not enough | 442 | * GNUNET_SYSERR on error (typically: not enough |
443 | * space) | 443 | * space) |
444 | */ | 444 | */ |
445 | int | 445 | ssize_t |
446 | GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData | 446 | GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData |
447 | *md, char *target, unsigned int max, | 447 | *md, char *target, size_t max, |
448 | enum | 448 | enum |
449 | GNUNET_CONTAINER_MetaDataSerializationOptions | 449 | GNUNET_CONTAINER_MetaDataSerializationOptions |
450 | part) | 450 | part) |
@@ -463,7 +463,7 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData | |||
463 | while (1) | 463 | while (1) |
464 | { | 464 | { |
465 | size = sizeof (struct MetaDataHeader); | 465 | size = sizeof (struct MetaDataHeader); |
466 | size += sizeof (unsigned int) * ic; | 466 | size += sizeof (uint32_t) * ic; |
467 | for (i = 0; i < ic; i++) | 467 | for (i = 0; i < ic; i++) |
468 | size += 1 + strlen (md->items[i].data); | 468 | size += 1 + strlen (md->items[i].data); |
469 | while (size % 8 != 0) | 469 | while (size % 8 != 0) |
@@ -472,8 +472,8 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData | |||
472 | hdr->version = htonl (md == NULL ? 1 : 0); | 472 | hdr->version = htonl (md == NULL ? 1 : 0); |
473 | hdr->entries = htonl (ic); | 473 | hdr->entries = htonl (ic); |
474 | for (i = 0; i < ic; i++) | 474 | for (i = 0; i < ic; i++) |
475 | ((unsigned int *) &hdr[1])[i] = | 475 | ((uint32_t *) &hdr[1])[i] = |
476 | htonl ((unsigned int) md->items[i].type); | 476 | htonl ((uint32_t) md->items[i].type); |
477 | pos = sizeof (struct MetaDataHeader); | 477 | pos = sizeof (struct MetaDataHeader); |
478 | pos += sizeof (unsigned int) * ic; | 478 | pos += sizeof (unsigned int) * ic; |
479 | for (i = 0; i < ic; i++) | 479 | for (i = 0; i < ic; i++) |
@@ -533,7 +533,7 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData | |||
533 | * serialized form. The estimate MAY be higher | 533 | * serialized form. The estimate MAY be higher |
534 | * than what is strictly needed. | 534 | * than what is strictly needed. |
535 | */ | 535 | */ |
536 | unsigned int | 536 | ssize_t |
537 | GNUNET_CONTAINER_meta_data_get_serialized_size (const struct | 537 | GNUNET_CONTAINER_meta_data_get_serialized_size (const struct |
538 | GNUNET_CONTAINER_MetaData *md, | 538 | GNUNET_CONTAINER_MetaData *md, |
539 | enum | 539 | enum |
@@ -549,7 +549,7 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct | |||
549 | 549 | ||
550 | ic = md ? md->itemCount : 0; | 550 | ic = md ? md->itemCount : 0; |
551 | size = sizeof (struct MetaDataHeader); | 551 | size = sizeof (struct MetaDataHeader); |
552 | size += sizeof (unsigned int) * ic; | 552 | size += sizeof (uint32_t) * ic; |
553 | for (i = 0; i < ic; i++) | 553 | for (i = 0; i < ic; i++) |
554 | size += 1 + strlen (md->items[i].data); | 554 | size += 1 + strlen (md->items[i].data); |
555 | while (size % 8 != 0) | 555 | while (size % 8 != 0) |
@@ -558,9 +558,9 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct | |||
558 | hdr->version = htonl (md == NULL ? 1 : 0); | 558 | hdr->version = htonl (md == NULL ? 1 : 0); |
559 | hdr->entries = htonl (ic); | 559 | hdr->entries = htonl (ic); |
560 | for (i = 0; i < ic; i++) | 560 | for (i = 0; i < ic; i++) |
561 | ((unsigned int *) &hdr[1])[i] = htonl ((unsigned int) md->items[i].type); | 561 | ((uint32_t *) &hdr[1])[i] = htonl ((uint32_t) md->items[i].type); |
562 | pos = sizeof (struct MetaDataHeader); | 562 | pos = sizeof (struct MetaDataHeader); |
563 | pos += sizeof (unsigned int) * ic; | 563 | pos += sizeof (uint32_t) * ic; |
564 | for (i = 0; i < ic; i++) | 564 | for (i = 0; i < ic; i++) |
565 | { | 565 | { |
566 | len = strlen (md->items[i].data) + 1; | 566 | len = strlen (md->items[i].data) + 1; |
@@ -590,7 +590,7 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct | |||
590 | * bad format) | 590 | * bad format) |
591 | */ | 591 | */ |
592 | struct GNUNET_CONTAINER_MetaData * | 592 | struct GNUNET_CONTAINER_MetaData * |
593 | GNUNET_CONTAINER_meta_data_deserialize (const char *input, unsigned int size) | 593 | GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) |
594 | { | 594 | { |
595 | struct GNUNET_CONTAINER_MetaData *md; | 595 | struct GNUNET_CONTAINER_MetaData *md; |
596 | const struct MetaDataHeader *hdr; | 596 | const struct MetaDataHeader *hdr; |
@@ -599,9 +599,9 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, unsigned int size) | |||
599 | const char *cdata; | 599 | const char *cdata; |
600 | uint32_t dataSize; | 600 | uint32_t dataSize; |
601 | int compressed; | 601 | int compressed; |
602 | int i; | 602 | uint32_t i; |
603 | unsigned int pos; | 603 | size_t pos; |
604 | int len; | 604 | size_t len; |
605 | uint32_t version; | 605 | uint32_t version; |
606 | 606 | ||
607 | if (size < sizeof (struct MetaDataHeader)) | 607 | if (size < sizeof (struct MetaDataHeader)) |
@@ -651,7 +651,7 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, unsigned int size) | |||
651 | } | 651 | } |
652 | } | 652 | } |
653 | 653 | ||
654 | if ((sizeof (unsigned int) * ic + ic) > dataSize) | 654 | if ((sizeof (uint32_t) * ic + ic) > dataSize) |
655 | { | 655 | { |
656 | GNUNET_break (0); | 656 | GNUNET_break (0); |
657 | goto FAILURE; | 657 | goto FAILURE; |
@@ -665,12 +665,12 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, unsigned int size) | |||
665 | md = GNUNET_CONTAINER_meta_data_create (); | 665 | md = GNUNET_CONTAINER_meta_data_create (); |
666 | GNUNET_array_grow (md->items, md->itemCount, ic); | 666 | GNUNET_array_grow (md->items, md->itemCount, ic); |
667 | i = 0; | 667 | i = 0; |
668 | pos = sizeof (unsigned int) * ic; | 668 | pos = sizeof (uint32_t) * ic; |
669 | while ((pos < dataSize) && (i < ic)) | 669 | while ((pos < dataSize) && (i < ic)) |
670 | { | 670 | { |
671 | len = strlen (&cdata[pos]) + 1; | 671 | len = strlen (&cdata[pos]) + 1; |
672 | md->items[i].type = (EXTRACTOR_KeywordType) | 672 | md->items[i].type = (EXTRACTOR_KeywordType) |
673 | ntohl (MAKE_UNALIGNED (((const unsigned int *) cdata)[i])); | 673 | ntohl (MAKE_UNALIGNED (((const uint32_t *) cdata)[i])); |
674 | md->items[i].data = GNUNET_strdup (&cdata[pos]); | 674 | md->items[i].data = GNUNET_strdup (&cdata[pos]); |
675 | pos += len; | 675 | pos += len; |
676 | i++; | 676 | i++; |
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index fc4d24320..a8843b5b7 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c | |||
@@ -709,7 +709,7 @@ GNUNET_CRYPTO_hash_xor (const GNUNET_HashCode * a, | |||
709 | * Convert a hashcode into a key. | 709 | * Convert a hashcode into a key. |
710 | */ | 710 | */ |
711 | void | 711 | void |
712 | GNUNET_CRYPTO_hash_to_AES_key (const GNUNET_HashCode * hc, | 712 | GNUNET_CRYPTO_hash_to_aes_key (const GNUNET_HashCode * hc, |
713 | struct GNUNET_CRYPTO_AesSessionKey *skey, | 713 | struct GNUNET_CRYPTO_AesSessionKey *skey, |
714 | struct GNUNET_CRYPTO_AesInitializationVector | 714 | struct GNUNET_CRYPTO_AesInitializationVector |
715 | *iv) | 715 | *iv) |