aboutsummaryrefslogtreecommitdiff
path: root/src/fs
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-18 19:03:26 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-18 19:03:26 +0000
commitc456c5bb7f9b95d1800ad6e2892a77f40a08493e (patch)
tree8b04e75f8a65225848816d8e588b28413ff9d758 /src/fs
parent6d0a62078edfa5c0001acb93d517c674c5124f4e (diff)
downloadgnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.tar.gz
gnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.zip
make all (?) asynchronously operating FS operations actually cancel-able
Diffstat (limited to 'src/fs')
-rw-r--r--src/fs/Makefile.am2
-rw-r--r--src/fs/fs_api.h23
-rw-r--r--src/fs/fs_list_indexed.c65
-rw-r--r--src/fs/fs_namespace.c439
-rw-r--r--src/fs/fs_namespace_advertise.c323
-rw-r--r--src/fs/fs_publish.c397
-rw-r--r--src/fs/fs_publish_ksk.c342
-rw-r--r--src/fs/fs_tree.c3
-rw-r--r--src/fs/gnunet-fs.c28
-rw-r--r--src/fs/gnunet-publish.c2
10 files changed, 854 insertions, 770 deletions
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am
index c4db16fb0..d9b0fbadd 100644
--- a/src/fs/Makefile.am
+++ b/src/fs/Makefile.am
@@ -33,8 +33,10 @@ libgnunetfs_la_SOURCES = \
33 fs_getopt.c \ 33 fs_getopt.c \
34 fs_list_indexed.c \ 34 fs_list_indexed.c \
35 fs_publish.c \ 35 fs_publish.c \
36 fs_publish_ksk.c \
36 fs_misc.c \ 37 fs_misc.c \
37 fs_namespace.c \ 38 fs_namespace.c \
39 fs_namespace_advertise.c \
38 fs_search.c \ 40 fs_search.c \
39 fs_sharetree.c \ 41 fs_sharetree.c \
40 fs_tree.c fs_tree.h \ 42 fs_tree.c fs_tree.h \
diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h
index 42daa7bc2..de66ac661 100644
--- a/src/fs/fs_api.h
+++ b/src/fs/fs_api.h
@@ -1161,6 +1161,18 @@ struct GNUNET_FS_PublishContext
1161 struct GNUNET_DATASTORE_QueueEntry *qre; 1161 struct GNUNET_DATASTORE_QueueEntry *qre;
1162 1162
1163 /** 1163 /**
1164 * Context for SKS publishing operation that is part of this publishing operation
1165 * (NULL if not active).
1166 */
1167 struct GNUNET_FS_PublishSksContext *sks_pc;
1168
1169 /**
1170 * Context for KSK publishing operation that is part of this publishing operation
1171 * (NULL if not active).
1172 */
1173 struct GNUNET_FS_PublishKskContext *ksk_pc;
1174
1175 /**
1164 * ID of the task performing the upload. NO_TASK if the upload has 1176 * ID of the task performing the upload. NO_TASK if the upload has
1165 * completed. 1177 * completed.
1166 */ 1178 */
@@ -1178,17 +1190,6 @@ struct GNUNET_FS_PublishContext
1178 uint32_t reserve_entries; 1190 uint32_t reserve_entries;
1179 1191
1180 /** 1192 /**
1181 * Typically GNUNET_NO. Set to GNUNET_YES if "upload_task" is
1182 * GNUNET_SCHEDULER_NO_TASK and we're waiting for a response from
1183 * the datastore service (in which case this struct must not be
1184 * freed until we have that response). If someone tries to stop the
1185 * download for good during this period, "in_network_wait" is set to
1186 * GNUNET_SYSERR which will cause the struct to be destroyed right
1187 * after we have the reply (or timeout) from the datastore service.
1188 */
1189 int in_network_wait;
1190
1191 /**
1192 * Options for publishing. 1193 * Options for publishing.
1193 */ 1194 */
1194 enum GNUNET_FS_PublishOptions options; 1195 enum GNUNET_FS_PublishOptions options;
diff --git a/src/fs/fs_list_indexed.c b/src/fs/fs_list_indexed.c
index 0896de347..784c9881a 100644
--- a/src/fs/fs_list_indexed.c
+++ b/src/fs/fs_list_indexed.c
@@ -34,7 +34,7 @@
34/** 34/**
35 * Context for "GNUNET_FS_get_indexed_files". 35 * Context for "GNUNET_FS_get_indexed_files".
36 */ 36 */
37struct GetIndexedContext 37struct GNUNET_FS_GetIndexedContext
38{ 38{
39 /** 39 /**
40 * Handle to global FS context. 40 * Handle to global FS context.
@@ -72,13 +72,13 @@ struct GetIndexedContext
72 * Function called on each response from the FS 72 * Function called on each response from the FS
73 * service with information about indexed files. 73 * service with information about indexed files.
74 * 74 *
75 * @param cls closure (of type "struct GetIndexedContext*") 75 * @param cls closure (of type "struct GNUNET_FS_GetIndexedContext*")
76 * @param msg message with indexing information 76 * @param msg message with indexing information
77 */ 77 */
78static void 78static void
79handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg) 79handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg)
80{ 80{
81 struct GetIndexedContext *gic = cls; 81 struct GNUNET_FS_GetIndexedContext *gic = cls;
82 const struct IndexInfoMessage *iim; 82 const struct IndexInfoMessage *iim;
83 uint16_t msize; 83 uint16_t msize;
84 const char *filename; 84 const char *filename;
@@ -89,19 +89,15 @@ handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg)
89 _ 89 _
90 ("Failed to receive response for `%s' request from `%s' service.\n"), 90 ("Failed to receive response for `%s' request from `%s' service.\n"),
91 "GET_INDEXED", "fs"); 91 "GET_INDEXED", "fs");
92 GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls, 92 (void) gic->iterator (gic->iterator_cls, NULL, NULL);
93 GNUNET_SCHEDULER_REASON_TIMEOUT); 93 GNUNET_FS_get_indexed_files_cancel (gic);
94 GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
95 GNUNET_free (gic);
96 return; 94 return;
97 } 95 }
98 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END) 96 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END)
99 { 97 {
100 /* normal end-of-list */ 98 /* normal end-of-list */
101 GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls, 99 (void) gic->iterator (gic->iterator_cls, NULL, NULL);
102 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 100 GNUNET_FS_get_indexed_files_cancel (gic);
103 GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
104 GNUNET_free (gic);
105 return; 101 return;
106 } 102 }
107 msize = ntohs (msg->size); 103 msize = ntohs (msg->size);
@@ -116,18 +112,13 @@ handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg)
116 _ 112 _
117 ("Failed to receive valid response for `%s' request from `%s' service.\n"), 113 ("Failed to receive valid response for `%s' request from `%s' service.\n"),
118 "GET_INDEXED", "fs"); 114 "GET_INDEXED", "fs");
119 GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls, 115 (void) gic->iterator (gic->iterator_cls, NULL, NULL);
120 GNUNET_SCHEDULER_REASON_TIMEOUT); 116 GNUNET_FS_get_indexed_files_cancel (gic);
121 GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
122 GNUNET_free (gic);
123 return; 117 return;
124 } 118 }
125 if (GNUNET_OK != gic->iterator (gic->iterator_cls, filename, &iim->file_id)) 119 if (GNUNET_OK != gic->iterator (gic->iterator_cls, filename, &iim->file_id))
126 { 120 {
127 GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls, 121 GNUNET_FS_get_indexed_files_cancel (gic);
128 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
129 GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
130 GNUNET_free (gic);
131 return; 122 return;
132 } 123 }
133 /* get more */ 124 /* get more */
@@ -142,19 +133,15 @@ handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg)
142 * @param h handle to the file sharing subsystem 133 * @param h handle to the file sharing subsystem
143 * @param iterator function to call on each indexed file 134 * @param iterator function to call on each indexed file
144 * @param iterator_cls closure for iterator 135 * @param iterator_cls closure for iterator
145 * @param cont continuation to call when done; 136 * @return NULL on error ('iter' is not called)
146 * reason should be "TIMEOUT" (on
147 * error) or "PREREQ_DONE" (on success)
148 * @param cont_cls closure for cont
149 */ 137 */
150void 138struct GNUNET_FS_GetIndexedContext *
151GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h, 139GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
152 GNUNET_FS_IndexedFileProcessor iterator, 140 GNUNET_FS_IndexedFileProcessor iterator,
153 void *iterator_cls, GNUNET_SCHEDULER_Task cont, 141 void *iterator_cls)
154 void *cont_cls)
155{ 142{
156 struct GNUNET_CLIENT_Connection *client; 143 struct GNUNET_CLIENT_Connection *client;
157 struct GetIndexedContext *gic; 144 struct GNUNET_FS_GetIndexedContext *gic;
158 struct GNUNET_MessageHeader msg; 145 struct GNUNET_MessageHeader msg;
159 146
160 client = GNUNET_CLIENT_connect ("fs", h->cfg); 147 client = GNUNET_CLIENT_connect ("fs", h->cfg);
@@ -162,18 +149,13 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
162 { 149 {
163 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 150 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
164 _("Failed to not connect to `%s' service.\n"), "fs"); 151 _("Failed to not connect to `%s' service.\n"), "fs");
165 GNUNET_SCHEDULER_add_continuation (cont, cont_cls, 152 return NULL;
166 GNUNET_SCHEDULER_REASON_TIMEOUT);
167 return;
168 } 153 }
169 154 gic = GNUNET_malloc (sizeof (struct GNUNET_FS_GetIndexedContext));
170 gic = GNUNET_malloc (sizeof (struct GetIndexedContext));
171 gic->h = h; 155 gic->h = h;
172 gic->client = client; 156 gic->client = client;
173 gic->iterator = iterator; 157 gic->iterator = iterator;
174 gic->iterator_cls = iterator_cls; 158 gic->iterator_cls = iterator_cls;
175 gic->cont = cont;
176 gic->cont_cls = cont_cls;
177 msg.size = htons (sizeof (struct GNUNET_MessageHeader)); 159 msg.size = htons (sizeof (struct GNUNET_MessageHeader));
178 msg.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET); 160 msg.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET);
179 GNUNET_assert (GNUNET_OK == 161 GNUNET_assert (GNUNET_OK ==
@@ -182,6 +164,21 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
182 GNUNET_YES, 164 GNUNET_YES,
183 &handle_index_info, 165 &handle_index_info,
184 gic)); 166 gic));
167 return gic;
168}
169
170
171/**
172 * Cancel iteration over all indexed files.
173 *
174 * @param gic operation to cancel
175 */
176void
177GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic)
178{
179 GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
180 GNUNET_free (gic);
185} 181}
186 182
183
187/* end of fs_list_indexed.c */ 184/* end of fs_list_indexed.c */
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c
index 9cb8cd5a4..e7cf38800 100644
--- a/src/fs/fs_namespace.c
+++ b/src/fs/fs_namespace.c
@@ -30,19 +30,12 @@
30#include "gnunet_fs_service.h" 30#include "gnunet_fs_service.h"
31#include "fs_api.h" 31#include "fs_api.h"
32 32
33#define DEBUG_NAMESPACE GNUNET_EXTRA_LOGGING
34
35 33
36/** 34/**
37 * Maximum legal size for an sblock. 35 * Maximum legal size for an sblock.
38 */ 36 */
39#define MAX_SBLOCK_SIZE (60 * 1024) 37#define MAX_SBLOCK_SIZE (60 * 1024)
40 38
41/**
42 * Maximum legal size for an nblock.
43 */
44#define MAX_NBLOCK_SIZE (60 * 1024)
45
46 39
47/** 40/**
48 * Return the name of the directory in which we store 41 * Return the name of the directory in which we store
@@ -233,253 +226,6 @@ END:
233} 226}
234 227
235 228
236/**
237 * Context for advertising a namespace.
238 */
239struct AdvertisementContext
240{
241 /**
242 * Function to call with the result.
243 */
244 GNUNET_FS_PublishContinuation cont;
245
246 /**
247 * Closure for cont.
248 */
249 void *cont_cls;
250
251 /**
252 * Datastore handle.
253 */
254 struct GNUNET_DATASTORE_Handle *dsh;
255
256 /**
257 * Our KSK URI.
258 */
259 struct GNUNET_FS_Uri *ksk_uri;
260
261 /**
262 * Plaintext.
263 */
264 char *pt;
265
266 /**
267 * NBlock to sign and store.
268 */
269 struct NBlock *nb;
270
271 /**
272 * The namespace.
273 */
274 struct GNUNET_FS_Namespace *ns;
275
276 /**
277 * Block options.
278 */
279 struct GNUNET_FS_BlockOptions bo;
280
281 /**
282 * Number of bytes of plaintext.
283 */
284 size_t pt_size;
285
286 /**
287 * Current keyword offset.
288 */
289 unsigned int pos;
290};
291
292
293/**
294 * Disconnect from the datastore.
295 *
296 * @param cls datastore handle
297 * @param tc scheduler context
298 */
299static void
300do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
301{
302 struct GNUNET_DATASTORE_Handle *dsh = cls;
303
304 GNUNET_DATASTORE_disconnect (dsh, GNUNET_NO);
305}
306
307
308/**
309 * Continuation called to notify client about result of the
310 * operation.
311 *
312 * @param cls closure (our struct AdvertismentContext)
313 * @param success GNUNET_SYSERR on failure
314 * @param min_expiration minimum expiration time required for content to be stored
315 * @param msg NULL on success, otherwise an error message
316 */
317static void
318advertisement_cont (void *cls, int success,
319 struct GNUNET_TIME_Absolute min_expiration,
320 const char *msg)
321{
322 struct AdvertisementContext *ac = cls;
323 const char *keyword;
324 GNUNET_HashCode key;
325 GNUNET_HashCode query;
326 struct GNUNET_CRYPTO_AesSessionKey skey;
327 struct GNUNET_CRYPTO_AesInitializationVector iv;
328 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
329
330 if (GNUNET_OK != success)
331 {
332 /* error! */
333 GNUNET_SCHEDULER_add_continuation (&do_disconnect, ac->dsh,
334 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
335 if (msg == NULL)
336 {
337 GNUNET_break (0);
338 msg = _("Unknown error");
339 }
340 if (ac->cont != NULL)
341 ac->cont (ac->cont_cls, NULL, msg);
342 GNUNET_FS_uri_destroy (ac->ksk_uri);
343 GNUNET_free (ac->pt);
344 GNUNET_free (ac->nb);
345 GNUNET_FS_namespace_delete (ac->ns, GNUNET_NO);
346 GNUNET_free (ac);
347 return;
348 }
349 if (ac->pos == ac->ksk_uri->data.ksk.keywordCount)
350 {
351 /* done! */
352 GNUNET_SCHEDULER_add_continuation (&do_disconnect, ac->dsh,
353 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
354 if (ac->cont != NULL)
355 ac->cont (ac->cont_cls, ac->ksk_uri, NULL);
356 GNUNET_FS_uri_destroy (ac->ksk_uri);
357 GNUNET_free (ac->pt);
358 GNUNET_free (ac->nb);
359 GNUNET_FS_namespace_delete (ac->ns, GNUNET_NO);
360 GNUNET_free (ac);
361 return;
362 }
363 keyword = ac->ksk_uri->data.ksk.keywords[ac->pos++];
364 /* first character of keyword indicates if it is
365 * mandatory or not -- ignore for hashing */
366 GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
367 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
368 GNUNET_CRYPTO_aes_encrypt (ac->pt, ac->pt_size, &skey, &iv, &ac->nb[1]);
369 GNUNET_break (GNUNET_OK ==
370 GNUNET_CRYPTO_rsa_sign (ac->ns->key, &ac->nb->ns_purpose,
371 &ac->nb->ns_signature));
372 pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
373 GNUNET_assert (pk != NULL);
374 GNUNET_CRYPTO_rsa_key_get_public (pk, &ac->nb->keyspace);
375 GNUNET_CRYPTO_hash (&ac->nb->keyspace,
376 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
377 &query);
378 GNUNET_break (GNUNET_OK ==
379 GNUNET_CRYPTO_rsa_sign (pk, &ac->nb->ksk_purpose,
380 &ac->nb->ksk_signature));
381 GNUNET_CRYPTO_rsa_key_free (pk);
382 GNUNET_DATASTORE_put (ac->dsh, 0 /* no reservation */ ,
383 &query, ac->pt_size + sizeof (struct NBlock), ac->nb,
384 GNUNET_BLOCK_TYPE_FS_NBLOCK, ac->bo.content_priority,
385 ac->bo.anonymity_level, ac->bo.replication_level,
386 ac->bo.expiration_time, -2, 1,
387 GNUNET_CONSTANTS_SERVICE_TIMEOUT, &advertisement_cont,
388 ac);
389}
390
391
392/**
393 * Publish an advertismement for a namespace.
394 *
395 * @param h handle to the file sharing subsystem
396 * @param ksk_uri keywords to use for advertisment
397 * @param namespace handle for the namespace that should be advertised
398 * @param meta meta-data for the namespace advertisement
399 * @param bo block options
400 * @param rootEntry name of the root of the namespace
401 * @param cont continuation
402 * @param cont_cls closure for cont
403 */
404void
405GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
406 struct GNUNET_FS_Uri *ksk_uri,
407 struct GNUNET_FS_Namespace *namespace,
408 const struct GNUNET_CONTAINER_MetaData *meta,
409 const struct GNUNET_FS_BlockOptions *bo,
410 const char *rootEntry,
411 GNUNET_FS_PublishContinuation cont,
412 void *cont_cls)
413{
414 size_t reslen;
415 size_t size;
416 ssize_t mdsize;
417 struct NBlock *nb;
418 char *mdst;
419 struct GNUNET_DATASTORE_Handle *dsh;
420 struct AdvertisementContext *ctx;
421 char *pt;
422
423 /* create advertisements */
424 mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
425 if (-1 == mdsize)
426 {
427 cont (cont_cls, NULL, _("Failed to serialize meta data"));
428 return;
429 }
430 reslen = strlen (rootEntry) + 1;
431 size = mdsize + sizeof (struct NBlock) + reslen;
432 if (size > MAX_NBLOCK_SIZE)
433 {
434 size = MAX_NBLOCK_SIZE;
435 mdsize = size - sizeof (struct NBlock) - reslen;
436 }
437
438 pt = GNUNET_malloc (mdsize + reslen);
439 memcpy (pt, rootEntry, reslen);
440 mdst = &pt[reslen];
441 mdsize =
442 GNUNET_CONTAINER_meta_data_serialize (meta, &mdst, mdsize,
443 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
444 if (mdsize == -1)
445 {
446 GNUNET_break (0);
447 GNUNET_free (pt);
448 cont (cont_cls, NULL, _("Failed to serialize meta data"));
449 return;
450 }
451 size = mdsize + sizeof (struct NBlock) + reslen;
452 nb = GNUNET_malloc (size);
453 GNUNET_CRYPTO_rsa_key_get_public (namespace->key, &nb->subspace);
454 nb->ns_purpose.size =
455 htonl (mdsize + reslen +
456 sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
457 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
458 nb->ns_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK);
459 nb->ksk_purpose.size =
460 htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
461 nb->ksk_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG);
462 dsh = GNUNET_DATASTORE_connect (h->cfg);
463 if (NULL == dsh)
464 {
465 GNUNET_free (nb);
466 GNUNET_free (pt);
467 cont (cont_cls, NULL, _("Failed to connect to datastore service"));
468 return;
469 }
470 ctx = GNUNET_malloc (sizeof (struct AdvertisementContext));
471 ctx->cont = cont;
472 ctx->cont_cls = cont_cls;
473 ctx->dsh = dsh;
474 ctx->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
475 ctx->nb = nb;
476 ctx->pt = pt;
477 ctx->pt_size = mdsize + reslen;
478 ctx->ns = namespace;
479 ctx->ns->rc++;
480 ctx->bo = *bo;
481 advertisement_cont (ctx, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
482}
483 229
484 230
485/** 231/**
@@ -557,26 +303,25 @@ GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace, int freeze)
557 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", 303 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink",
558 namespace->filename); 304 namespace->filename);
559 } 305 }
560 if (0 == namespace->rc) 306 if (0 != namespace->rc)
307 return GNUNET_OK;
308 GNUNET_CRYPTO_rsa_key_free (namespace->key);
309 GNUNET_free (namespace->filename);
310 GNUNET_free (namespace->name);
311 for (i = 0; i < namespace->update_node_count; i++)
561 { 312 {
562 GNUNET_CRYPTO_rsa_key_free (namespace->key); 313 nsn = namespace->update_nodes[i];
563 GNUNET_free (namespace->filename); 314 GNUNET_CONTAINER_meta_data_destroy (nsn->md);
564 GNUNET_free (namespace->name); 315 GNUNET_FS_uri_destroy (nsn->uri);
565 for (i = 0; i < namespace->update_node_count; i++) 316 GNUNET_free (nsn->id);
566 { 317 GNUNET_free (nsn->update);
567 nsn = namespace->update_nodes[i]; 318 GNUNET_free (nsn);
568 GNUNET_CONTAINER_meta_data_destroy (nsn->md); 319 }
569 GNUNET_FS_uri_destroy (nsn->uri); 320 GNUNET_array_grow (namespace->update_nodes, namespace->update_node_count,
570 GNUNET_free (nsn->id); 321 0);
571 GNUNET_free (nsn->update); 322 if (namespace->update_map != NULL)
572 GNUNET_free (nsn); 323 GNUNET_CONTAINER_multihashmap_destroy (namespace->update_map);
573 } 324 GNUNET_free (namespace);
574 GNUNET_array_grow (namespace->update_nodes, namespace->update_node_count,
575 0);
576 if (namespace->update_map != NULL)
577 GNUNET_CONTAINER_multihashmap_destroy (namespace->update_map);
578 GNUNET_free (namespace);
579 }
580 return GNUNET_OK; 325 return GNUNET_OK;
581} 326}
582 327
@@ -666,12 +411,10 @@ GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
666} 411}
667 412
668 413
669
670
671/** 414/**
672 * Context for the SKS publication. 415 * Context for the SKS publication.
673 */ 416 */
674struct PublishSksContext 417struct GNUNET_FS_PublishSksContext
675{ 418{
676 419
677 /** 420 /**
@@ -705,6 +448,10 @@ struct PublishSksContext
705 */ 448 */
706 void *cont_cls; 449 void *cont_cls;
707 450
451 /**
452 * Handle for our datastore request.
453 */
454 struct GNUNET_DATASTORE_QueueEntry *dqe;
708}; 455};
709 456
710 457
@@ -712,7 +459,7 @@ struct PublishSksContext
712 * Function called by the datastore API with 459 * Function called by the datastore API with
713 * the result from the PUT (SBlock) request. 460 * the result from the PUT (SBlock) request.
714 * 461 *
715 * @param cls closure of type "struct PublishSksContext*" 462 * @param cls closure of type "struct GNUNET_FS_PublishSksContext*"
716 * @param success GNUNET_OK on success 463 * @param success GNUNET_OK on success
717 * @param min_expiration minimum expiration time required for content to be stored 464 * @param min_expiration minimum expiration time required for content to be stored
718 * @param msg error message (or NULL) 465 * @param msg error message (or NULL)
@@ -722,54 +469,39 @@ sb_put_cont (void *cls, int success,
722 struct GNUNET_TIME_Absolute min_expiration, 469 struct GNUNET_TIME_Absolute min_expiration,
723 const char *msg) 470 const char *msg)
724{ 471{
725 struct PublishSksContext *psc = cls; 472 struct GNUNET_FS_PublishSksContext *psc = cls;
726 GNUNET_HashCode hc; 473 GNUNET_HashCode hc;
727 474
728 if (NULL != psc->dsh) 475 psc->dqe = NULL;
729 {
730 GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO);
731 psc->dsh = NULL;
732 }
733 if (GNUNET_OK != success) 476 if (GNUNET_OK != success)
734 { 477 {
735 if (psc->cont != NULL) 478 if (NULL != psc->cont)
736 psc->cont (psc->cont_cls, NULL, msg); 479 psc->cont (psc->cont_cls, NULL, msg);
480 GNUNET_FS_publish_sks_cancel (psc);
481 return;
737 } 482 }
738 else 483 if (NULL != psc->nsn)
739 { 484 {
740 if (psc->nsn != NULL) 485 /* FIXME: this can be done much more
486 * efficiently by simply appending to the
487 * file and overwriting the 4-byte header */
488 if (psc->namespace->update_nodes == NULL)
489 read_update_information_graph (psc->namespace);
490 GNUNET_array_append (psc->namespace->update_nodes,
491 psc->namespace->update_node_count, psc->nsn);
492 if (psc->namespace->update_map != NULL)
741 { 493 {
742 /* FIXME: this can be done much more 494 GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc);
743 * efficiently by simply appending to the 495 GNUNET_CONTAINER_multihashmap_put (psc->namespace->update_map, &hc,
744 * file and overwriting the 4-byte header */ 496 psc->nsn,
745 if (psc->namespace->update_nodes == NULL) 497 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
746 read_update_information_graph (psc->namespace);
747 GNUNET_array_append (psc->namespace->update_nodes,
748 psc->namespace->update_node_count, psc->nsn);
749 if (psc->namespace->update_map != NULL)
750 {
751 GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc);
752 GNUNET_CONTAINER_multihashmap_put (psc->namespace->update_map, &hc,
753 psc->nsn,
754 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
755 }
756 psc->nsn = NULL;
757 write_update_information_graph (psc->namespace);
758 } 498 }
759 if (psc->cont != NULL) 499 psc->nsn = NULL;
760 psc->cont (psc->cont_cls, psc->uri, NULL); 500 write_update_information_graph (psc->namespace);
761 }
762 GNUNET_FS_namespace_delete (psc->namespace, GNUNET_NO);
763 GNUNET_FS_uri_destroy (psc->uri);
764 if (psc->nsn != NULL)
765 {
766 GNUNET_CONTAINER_meta_data_destroy (psc->nsn->md);
767 GNUNET_FS_uri_destroy (psc->nsn->uri);
768 GNUNET_free (psc->nsn->id);
769 GNUNET_free (psc->nsn->update);
770 GNUNET_free (psc->nsn);
771 } 501 }
772 GNUNET_free (psc); 502 if (NULL != psc->cont)
503 psc->cont (psc->cont_cls, psc->uri, NULL);
504 GNUNET_FS_publish_sks_cancel (psc);
773} 505}
774 506
775 507
@@ -786,8 +518,9 @@ sb_put_cont (void *cls, int success,
786 * @param options publication options 518 * @param options publication options
787 * @param cont continuation 519 * @param cont continuation
788 * @param cont_cls closure for cont 520 * @param cont_cls closure for cont
521 * @return NULL on error ('cont' will still be called)
789 */ 522 */
790void 523struct GNUNET_FS_PublishSksContext *
791GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, 524GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
792 struct GNUNET_FS_Namespace *namespace, 525 struct GNUNET_FS_Namespace *namespace,
793 const char *identifier, const char *update, 526 const char *identifier, const char *update,
@@ -797,7 +530,7 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
797 enum GNUNET_FS_PublishOptions options, 530 enum GNUNET_FS_PublishOptions options,
798 GNUNET_FS_PublishContinuation cont, void *cont_cls) 531 GNUNET_FS_PublishContinuation cont, void *cont_cls)
799{ 532{
800 struct PublishSksContext *psc; 533 struct GNUNET_FS_PublishSksContext *psc;
801 struct GNUNET_CRYPTO_AesSessionKey sk; 534 struct GNUNET_CRYPTO_AesSessionKey sk;
802 struct GNUNET_CRYPTO_AesInitializationVector iv; 535 struct GNUNET_CRYPTO_AesInitializationVector iv;
803 struct GNUNET_FS_Uri *sks_uri; 536 struct GNUNET_FS_Uri *sks_uri;
@@ -851,8 +584,9 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
851 { 584 {
852 GNUNET_break (0); 585 GNUNET_break (0);
853 GNUNET_free (sb); 586 GNUNET_free (sb);
854 cont (cont_cls, NULL, _("Internal error.")); 587 if (NULL != cont)
855 return; 588 cont (cont_cls, NULL, _("Internal error."));
589 return NULL;
856 } 590 }
857 size = sizeof (struct SBlock) + mdsize + slen + nidlen; 591 size = sizeof (struct SBlock) + mdsize + slen + nidlen;
858 sb_enc = GNUNET_malloc (size); 592 sb_enc = GNUNET_malloc (size);
@@ -877,18 +611,17 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
877 GNUNET_assert (GNUNET_OK == 611 GNUNET_assert (GNUNET_OK ==
878 GNUNET_CRYPTO_rsa_sign (namespace->key, &sb_enc->purpose, 612 GNUNET_CRYPTO_rsa_sign (namespace->key, &sb_enc->purpose,
879 &sb_enc->signature)); 613 &sb_enc->signature));
880 psc = GNUNET_malloc (sizeof (struct PublishSksContext)); 614 psc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishSksContext));
881 psc->uri = sks_uri; 615 psc->uri = sks_uri;
882 psc->cont = cont; 616 psc->cont = cont;
883 psc->namespace = namespace; 617 psc->namespace = GNUNET_FS_namespace_dup (namespace);
884 namespace->rc++;
885 psc->cont_cls = cont_cls; 618 psc->cont_cls = cont_cls;
886 if (0 != (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) 619 if (0 != (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
887 { 620 {
888 GNUNET_free (sb_enc); 621 GNUNET_free (sb_enc);
889 GNUNET_free (sb); 622 GNUNET_free (sb);
890 sb_put_cont (psc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL); 623 sb_put_cont (psc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
891 return; 624 return NULL;
892 } 625 }
893 psc->dsh = GNUNET_DATASTORE_connect (h->cfg); 626 psc->dsh = GNUNET_DATASTORE_connect (h->cfg);
894 if (NULL == psc->dsh) 627 if (NULL == psc->dsh)
@@ -896,7 +629,7 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
896 GNUNET_free (sb_enc); 629 GNUNET_free (sb_enc);
897 GNUNET_free (sb); 630 GNUNET_free (sb);
898 sb_put_cont (psc, GNUNET_NO, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to connect to datastore.")); 631 sb_put_cont (psc, GNUNET_NO, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to connect to datastore."));
899 return; 632 return NULL;
900 } 633 }
901 GNUNET_CRYPTO_hash_xor (&sks_uri->data.sks.namespace, &id, &query); 634 GNUNET_CRYPTO_hash_xor (&sks_uri->data.sks.namespace, &id, &query);
902 if (NULL != update) 635 if (NULL != update)
@@ -907,13 +640,46 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
907 psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta); 640 psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta);
908 psc->nsn->uri = GNUNET_FS_uri_dup (uri); 641 psc->nsn->uri = GNUNET_FS_uri_dup (uri);
909 } 642 }
910 GNUNET_DATASTORE_put (psc->dsh, 0, &sb_enc->identifier, size, sb_enc, 643 psc->dqe = GNUNET_DATASTORE_put (psc->dsh, 0, &sb_enc->identifier, size, sb_enc,
911 GNUNET_BLOCK_TYPE_FS_SBLOCK, bo->content_priority, 644 GNUNET_BLOCK_TYPE_FS_SBLOCK, bo->content_priority,
912 bo->anonymity_level, bo->replication_level, 645 bo->anonymity_level, bo->replication_level,
913 bo->expiration_time, -2, 1, 646 bo->expiration_time, -2, 1,
914 GNUNET_CONSTANTS_SERVICE_TIMEOUT, &sb_put_cont, psc); 647 GNUNET_CONSTANTS_SERVICE_TIMEOUT, &sb_put_cont, psc);
915 GNUNET_free (sb); 648 GNUNET_free (sb);
916 GNUNET_free (sb_enc); 649 GNUNET_free (sb_enc);
650 return psc;
651}
652
653
654/**
655 * Abort the SKS publishing operation.
656 *
657 * @param sc context of the operation to abort.
658 */
659void
660GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc)
661{
662 if (NULL != psc->dqe)
663 {
664 GNUNET_DATASTORE_cancel (psc->dqe);
665 psc->dqe = NULL;
666 }
667 if (NULL != psc->dsh)
668 {
669 GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO);
670 psc->dsh = NULL;
671 }
672 GNUNET_FS_namespace_delete (psc->namespace, GNUNET_NO);
673 GNUNET_FS_uri_destroy (psc->uri);
674 if (NULL != psc->nsn)
675 {
676 GNUNET_CONTAINER_meta_data_destroy (psc->nsn->md);
677 GNUNET_FS_uri_destroy (psc->nsn->uri);
678 GNUNET_free (psc->nsn->id);
679 GNUNET_free (psc->nsn->update);
680 GNUNET_free (psc->nsn);
681 }
682 GNUNET_free (psc);
917} 683}
918 684
919 685
@@ -1081,10 +847,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1081 read_update_information_graph (namespace); 847 read_update_information_graph (namespace);
1082 if (namespace->update_nodes == NULL) 848 if (namespace->update_nodes == NULL)
1083 { 849 {
1084#if DEBUG_NAMESPACE
1085 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1086 "No updateable nodes found for ID `%s'\n", next_id); 851 "No updateable nodes found for ID `%s'\n", next_id);
1087#endif
1088 return; /* no nodes */ 852 return; /* no nodes */
1089 } 853 }
1090 if (namespace->update_map == NULL) 854 if (namespace->update_map == NULL)
@@ -1111,10 +875,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1111 &process_update_node, &pc); 875 &process_update_node, &pc);
1112 return; 876 return;
1113 } 877 }
1114#if DEBUG_NAMESPACE
1115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1116 "Calculating TREEs to find roots of update trees\n"); 879 "Calculating TREEs to find roots of update trees\n");
1117#endif
1118 /* Find heads of TREEs in update graph */ 880 /* Find heads of TREEs in update graph */
1119 nug = ++namespace->nug_gen; 881 nug = ++namespace->nug_gen;
1120 fc.tree_array = NULL; 882 fc.tree_array = NULL;
@@ -1125,10 +887,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1125 nsn = namespace->update_nodes[i]; 887 nsn = namespace->update_nodes[i];
1126 if (nsn->nug == nug) 888 if (nsn->nug == nug)
1127 { 889 {
1128#if DEBUG_NAMESPACE
1129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, 890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id,
1130 nsn->nug); 891 nsn->nug);
1131#endif
1132 continue; /* already placed in TREE */ 892 continue; /* already placed in TREE */
1133 } 893 }
1134 GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc); 894 GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc);
@@ -1156,11 +916,9 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1156 GNUNET_array_append (fc.tree_array, fc.tree_array_size, nsn); 916 GNUNET_array_append (fc.tree_array, fc.tree_array_size, nsn);
1157 nsn->tree_id = fc.id; 917 nsn->tree_id = fc.id;
1158 } 918 }
1159#if DEBUG_NAMESPACE
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1161 "Starting new TREE %u with node `%s'\n", nsn->tree_id, 920 "Starting new TREE %u with node `%s'\n", nsn->tree_id,
1162 nsn->id); 921 nsn->id);
1163#endif
1164 /* put all nodes with same identifier into this TREE */ 922 /* put all nodes with same identifier into this TREE */
1165 GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); 923 GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc);
1166 fc.id = nsn->tree_id; 924 fc.id = nsn->tree_id;
@@ -1175,28 +933,21 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1175 fc.tree_array[fc.id] = nsn; 933 fc.tree_array[fc.id] = nsn;
1176 nsn->tree_id = fc.id; 934 nsn->tree_id = fc.id;
1177 } 935 }
1178#if DEBUG_NAMESPACE
1179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, 936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id,
1180 fc.id); 937 fc.id);
1181#endif
1182 } 938 }
1183 for (i = 0; i < fc.tree_array_size; i++) 939 for (i = 0; i < fc.tree_array_size; i++)
1184 { 940 {
1185 nsn = fc.tree_array[i]; 941 nsn = fc.tree_array[i];
1186 if (NULL != nsn) 942 if (NULL != nsn)
1187 { 943 {
1188#if DEBUG_NAMESPACE
1189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Root of TREE %u is node `%s'\n", i, 944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Root of TREE %u is node `%s'\n", i,
1190 nsn->id); 945 nsn->id);
1191#endif
1192
1193 ip (ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update); 946 ip (ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update);
1194 } 947 }
1195 } 948 }
1196 GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0); 949 GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0);
1197#if DEBUG_NAMESPACE
1198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n"); 950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n");
1199#endif
1200} 951}
1201 952
1202 953
diff --git a/src/fs/fs_namespace_advertise.c b/src/fs/fs_namespace_advertise.c
new file mode 100644
index 000000000..60b4de095
--- /dev/null
+++ b/src/fs/fs_namespace_advertise.c
@@ -0,0 +1,323 @@
1/*
2 This file is part of GNUnet
3 (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Christian Grothoff (and other contributing authors)
4
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
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/fs_namespace_advertise.c
23 * @brief advertise namespaces (creating NBlocks)
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_constants.h"
28#include "gnunet_signatures.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_fs_service.h"
31#include "fs_api.h"
32
33
34/**
35 * Maximum legal size for an nblock.
36 */
37#define MAX_NBLOCK_SIZE (60 * 1024)
38
39
40/**
41 * Context for advertising a namespace.
42 */
43struct GNUNET_FS_AdvertisementContext
44{
45 /**
46 * Function to call with the result.
47 */
48 GNUNET_FS_PublishContinuation cont;
49
50 /**
51 * Closure for cont.
52 */
53 void *cont_cls;
54
55 /**
56 * Datastore handle.
57 */
58 struct GNUNET_DATASTORE_Handle *dsh;
59
60 /**
61 * Our KSK URI.
62 */
63 struct GNUNET_FS_Uri *ksk_uri;
64
65 /**
66 * Plaintext.
67 */
68 char *pt;
69
70 /**
71 * NBlock to sign and store.
72 */
73 struct NBlock *nb;
74
75 /**
76 * The namespace.
77 */
78 struct GNUNET_FS_Namespace *ns;
79
80 /**
81 * Current datastore queue entry for advertising.
82 */
83 struct GNUNET_DATASTORE_QueueEntry *dqe;
84
85 /**
86 * Block options.
87 */
88 struct GNUNET_FS_BlockOptions bo;
89
90 /**
91 * Number of bytes of plaintext.
92 */
93 size_t pt_size;
94
95 /**
96 * Current keyword offset.
97 */
98 unsigned int pos;
99};
100
101
102// FIXME: I see no good reason why this should need to be done
103// in a new task (anymore). Integrate with 'cancel' function below?
104/**
105 * Disconnect from the datastore.
106 *
107 * @param cls datastore handle
108 * @param tc scheduler context
109 */
110static void
111do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
112{
113 struct GNUNET_DATASTORE_Handle *dsh = cls;
114
115 GNUNET_DATASTORE_disconnect (dsh, GNUNET_NO);
116}
117
118
119/**
120 * Continuation called to notify client about result of the
121 * operation.
122 *
123 * @param cls closure (our struct GNUNET_FS_AdvertismentContext)
124 * @param success GNUNET_SYSERR on failure
125 * @param min_expiration minimum expiration time required for content to be stored
126 * @param msg NULL on success, otherwise an error message
127 */
128static void
129advertisement_cont (void *cls, int success,
130 struct GNUNET_TIME_Absolute min_expiration,
131 const char *msg)
132{
133 struct GNUNET_FS_AdvertisementContext *ac = cls;
134 const char *keyword;
135 GNUNET_HashCode key;
136 GNUNET_HashCode query;
137 struct GNUNET_CRYPTO_AesSessionKey skey;
138 struct GNUNET_CRYPTO_AesInitializationVector iv;
139 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
140
141 ac->dqe = NULL;
142 if (GNUNET_SYSERR == success)
143 {
144 /* error! */
145 (void) GNUNET_SCHEDULER_add_now (&do_disconnect, ac->dsh);
146 ac->dsh = NULL;
147 if (msg == NULL)
148 {
149 GNUNET_break (0);
150 msg = _("Unknown error");
151 }
152 if (ac->cont != NULL)
153 {
154 ac->cont (ac->cont_cls, NULL, msg);
155 ac->cont = NULL;
156 }
157 GNUNET_FS_namespace_advertise_cancel (ac);
158 return;
159 }
160 if (ac->pos == ac->ksk_uri->data.ksk.keywordCount)
161 {
162 /* done! */
163 (void) GNUNET_SCHEDULER_add_now (&do_disconnect, ac->dsh);
164 ac->dsh = NULL;
165 if (ac->cont != NULL)
166 {
167 ac->cont (ac->cont_cls, ac->ksk_uri, NULL);
168 ac->cont = NULL;
169 }
170 GNUNET_FS_namespace_advertise_cancel (ac);
171 return;
172 }
173 keyword = ac->ksk_uri->data.ksk.keywords[ac->pos++];
174 /* first character of keyword indicates if it is
175 * mandatory or not -- ignore for hashing */
176 GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
177 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
178 GNUNET_CRYPTO_aes_encrypt (ac->pt, ac->pt_size, &skey, &iv, &ac->nb[1]);
179 GNUNET_break (GNUNET_OK ==
180 GNUNET_CRYPTO_rsa_sign (ac->ns->key, &ac->nb->ns_purpose,
181 &ac->nb->ns_signature));
182 pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
183 GNUNET_assert (pk != NULL);
184 GNUNET_CRYPTO_rsa_key_get_public (pk, &ac->nb->keyspace);
185 GNUNET_CRYPTO_hash (&ac->nb->keyspace,
186 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
187 &query);
188 GNUNET_break (GNUNET_OK ==
189 GNUNET_CRYPTO_rsa_sign (pk, &ac->nb->ksk_purpose,
190 &ac->nb->ksk_signature));
191 GNUNET_CRYPTO_rsa_key_free (pk);
192 ac->dqe = GNUNET_DATASTORE_put (ac->dsh, 0 /* no reservation */ ,
193 &query, ac->pt_size + sizeof (struct NBlock), ac->nb,
194 GNUNET_BLOCK_TYPE_FS_NBLOCK, ac->bo.content_priority,
195 ac->bo.anonymity_level, ac->bo.replication_level,
196 ac->bo.expiration_time, -2, 1,
197 GNUNET_CONSTANTS_SERVICE_TIMEOUT, &advertisement_cont,
198 ac);
199}
200
201
202/**
203 * Publish an advertismement for a namespace.
204 *
205 * @param h handle to the file sharing subsystem
206 * @param ksk_uri keywords to use for advertisment
207 * @param namespace handle for the namespace that should be advertised
208 * @param meta meta-data for the namespace advertisement
209 * @param bo block options
210 * @param rootEntry name of the root of the namespace
211 * @param cont continuation
212 * @param cont_cls closure for cont
213 * @return NULL on error ('cont' is still called)
214 */
215struct GNUNET_FS_AdvertisementContext *
216GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
217 struct GNUNET_FS_Uri *ksk_uri,
218 struct GNUNET_FS_Namespace *namespace,
219 const struct GNUNET_CONTAINER_MetaData *meta,
220 const struct GNUNET_FS_BlockOptions *bo,
221 const char *rootEntry,
222 GNUNET_FS_PublishContinuation cont,
223 void *cont_cls)
224{
225 size_t reslen;
226 size_t size;
227 ssize_t mdsize;
228 struct NBlock *nb;
229 char *mdst;
230 struct GNUNET_DATASTORE_Handle *dsh;
231 struct GNUNET_FS_AdvertisementContext *ctx;
232 char *pt;
233
234 /* create advertisements */
235 mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
236 if (-1 == mdsize)
237 {
238 cont (cont_cls, NULL, _("Failed to serialize meta data"));
239 return NULL;
240 }
241 reslen = strlen (rootEntry) + 1;
242 size = mdsize + sizeof (struct NBlock) + reslen;
243 if (size > MAX_NBLOCK_SIZE)
244 {
245 size = MAX_NBLOCK_SIZE;
246 mdsize = size - sizeof (struct NBlock) - reslen;
247 }
248
249 pt = GNUNET_malloc (mdsize + reslen);
250 memcpy (pt, rootEntry, reslen);
251 mdst = &pt[reslen];
252 mdsize =
253 GNUNET_CONTAINER_meta_data_serialize (meta, &mdst, mdsize,
254 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
255 if (-1 == mdsize)
256 {
257 GNUNET_break (0);
258 GNUNET_free (pt);
259 cont (cont_cls, NULL, _("Failed to serialize meta data"));
260 return NULL;
261 }
262 size = mdsize + sizeof (struct NBlock) + reslen;
263 nb = GNUNET_malloc (size);
264 GNUNET_CRYPTO_rsa_key_get_public (namespace->key, &nb->subspace);
265 nb->ns_purpose.size =
266 htonl (mdsize + reslen +
267 sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
268 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
269 nb->ns_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK);
270 nb->ksk_purpose.size =
271 htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
272 nb->ksk_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG);
273 dsh = GNUNET_DATASTORE_connect (h->cfg);
274 if (NULL == dsh)
275 {
276 GNUNET_free (nb);
277 GNUNET_free (pt);
278 cont (cont_cls, NULL, _("Failed to connect to datastore service"));
279 return NULL;
280 }
281 ctx = GNUNET_malloc (sizeof (struct GNUNET_FS_AdvertisementContext));
282 ctx->cont = cont;
283 ctx->cont_cls = cont_cls;
284 ctx->dsh = dsh;
285 ctx->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
286 ctx->nb = nb;
287 ctx->pt = pt;
288 ctx->pt_size = mdsize + reslen;
289 ctx->ns = namespace;
290 ctx->ns->rc++;
291 ctx->bo = *bo;
292 advertisement_cont (ctx, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
293 return ctx;
294}
295
296
297/**
298 * Abort the namespace advertisement operation.
299 *
300 * @param pkc context of the operation to abort.
301 */
302void
303GNUNET_FS_namespace_advertise_cancel (struct GNUNET_FS_AdvertisementContext *ac)
304{
305 if (NULL != ac->dqe)
306 {
307 GNUNET_DATASTORE_cancel (ac->dqe);
308 ac->dqe = NULL;
309 }
310 if (NULL != ac->dsh)
311 {
312 GNUNET_DATASTORE_disconnect (ac->dsh, GNUNET_NO);
313 ac->dsh = NULL;
314 }
315 GNUNET_FS_uri_destroy (ac->ksk_uri);
316 GNUNET_free (ac->pt);
317 GNUNET_free (ac->nb);
318 GNUNET_FS_namespace_delete (ac->ns, GNUNET_NO);
319 GNUNET_free (ac);
320}
321
322
323/* end of fs_namespace_advertise.c */
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c
index 444128016..134dd21e4 100644
--- a/src/fs/fs_publish.c
+++ b/src/fs/fs_publish.c
@@ -34,13 +34,6 @@
34#include "fs_api.h" 34#include "fs_api.h"
35#include "fs_tree.h" 35#include "fs_tree.h"
36 36
37#define DEBUG_PUBLISH GNUNET_EXTRA_LOGGING
38
39/**
40 * Maximum legal size for a kblock.
41 */
42#define MAX_KBLOCK_SIZE (60 * 1024)
43
44 37
45/** 38/**
46 * Fill in all of the generic fields for 39 * Fill in all of the generic fields for
@@ -78,17 +71,12 @@ GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi,
78/** 71/**
79 * Cleanup the publish context, we're done with it. 72 * Cleanup the publish context, we're done with it.
80 * 73 *
81 * @param cls struct to clean up after 74 * @param pc struct to clean up
82 * @param tc scheduler context
83 */ 75 */
84static void 76static void
85publish_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 77publish_cleanup (struct GNUNET_FS_PublishContext *pc)
86{ 78{
87 struct GNUNET_FS_PublishContext *pc = cls;
88
89#if DEBUG_PUBLISH
90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n"); 79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n");
91#endif
92 if (pc->fhc != NULL) 80 if (pc->fhc != NULL)
93 { 81 {
94 GNUNET_CRYPTO_hash_file_cancel (pc->fhc); 82 GNUNET_CRYPTO_hash_file_cancel (pc->fhc);
@@ -136,15 +124,6 @@ ds_put_cont (void *cls, int success,
136 struct GNUNET_FS_ProgressInfo pi; 124 struct GNUNET_FS_ProgressInfo pi;
137 125
138 pc->qre = NULL; 126 pc->qre = NULL;
139 if (GNUNET_SYSERR == pc->in_network_wait)
140 {
141 /* we were aborted in the meantime, finish shutdown! */
142 GNUNET_SCHEDULER_add_continuation (&publish_cleanup, pc,
143 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
144 return;
145 }
146 GNUNET_assert (GNUNET_YES == pc->in_network_wait);
147 pc->in_network_wait = GNUNET_NO;
148 if (GNUNET_SYSERR == success) 127 if (GNUNET_SYSERR == success)
149 { 128 {
150 GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg); 129 GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg);
@@ -238,9 +217,7 @@ finish_release_reserve (void *cls, int success,
238 struct GNUNET_FS_PublishContext *pc = cls; 217 struct GNUNET_FS_PublishContext *pc = cls;
239 218
240 pc->qre = NULL; 219 pc->qre = NULL;
241#if DEBUG_PUBLISH
242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n"); 220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n");
243#endif
244 signal_publish_completion (pc->fi, pc); 221 signal_publish_completion (pc->fi, pc);
245 pc->all_done = GNUNET_YES; 222 pc->all_done = GNUNET_YES;
246 GNUNET_FS_publish_sync_ (pc); 223 GNUNET_FS_publish_sync_ (pc);
@@ -261,6 +238,7 @@ publish_sblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri,
261{ 238{
262 struct GNUNET_FS_PublishContext *pc = cls; 239 struct GNUNET_FS_PublishContext *pc = cls;
263 240
241 pc->sks_pc = NULL;
264 if (NULL != emsg) 242 if (NULL != emsg)
265 { 243 {
266 signal_publish_error (pc->fi, pc, emsg); 244 signal_publish_error (pc->fi, pc, emsg);
@@ -292,9 +270,9 @@ static void
292publish_sblock (struct GNUNET_FS_PublishContext *pc) 270publish_sblock (struct GNUNET_FS_PublishContext *pc)
293{ 271{
294 if (NULL != pc->namespace) 272 if (NULL != pc->namespace)
295 GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid, 273 pc->sks_pc = GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid,
296 pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo, 274 pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo,
297 pc->options, &publish_sblocks_cont, pc); 275 pc->options, &publish_sblocks_cont, pc);
298 else 276 else
299 publish_sblocks_cont (pc, NULL, NULL); 277 publish_sblocks_cont (pc, NULL, NULL);
300} 278}
@@ -316,25 +294,22 @@ publish_kblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri,
316 struct GNUNET_FS_PublishContext *pc = cls; 294 struct GNUNET_FS_PublishContext *pc = cls;
317 struct GNUNET_FS_FileInformation *p = pc->fi_pos; 295 struct GNUNET_FS_FileInformation *p = pc->fi_pos;
318 296
297 pc->ksk_pc = NULL;
319 if (NULL != emsg) 298 if (NULL != emsg)
320 { 299 {
321#if DEBUG_PUBLISH
322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n", 300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n",
323 emsg); 301 emsg);
324#endif
325 signal_publish_error (p, pc, emsg); 302 signal_publish_error (p, pc, emsg);
326 GNUNET_FS_file_information_sync_ (p); 303 GNUNET_FS_file_information_sync_ (p);
327 GNUNET_FS_publish_sync_ (pc); 304 GNUNET_FS_publish_sync_ (pc);
328 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); 305 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task);
329 pc->upload_task = 306 pc->upload_task =
330 GNUNET_SCHEDULER_add_with_priority 307 GNUNET_SCHEDULER_add_with_priority
331 (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); 308 (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc);
332 return; 309 return;
333 } 310 }
334#if DEBUG_PUBLISH
335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
336 "KSK blocks published, moving on to next file\n"); 312 "KSK blocks published, moving on to next file\n");
337#endif
338 if (NULL != p->dir) 313 if (NULL != p->dir)
339 signal_publish_completion (p, pc); 314 signal_publish_completion (p, pc);
340 /* move on to next file */ 315 /* move on to next file */
@@ -415,9 +390,7 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
415 p->te = NULL; 390 p->te = NULL;
416 if (NULL != emsg) 391 if (NULL != emsg)
417 { 392 {
418#if DEBUG_PUBLISH
419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg); 393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg);
420#endif
421 GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg); 394 GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg);
422 GNUNET_free (emsg); 395 GNUNET_free (emsg);
423 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; 396 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR;
@@ -425,9 +398,7 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
425 pi.value.publish.specifics.error.message = p->emsg; 398 pi.value.publish.specifics.error.message = p->emsg;
426 p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); 399 p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0);
427 } 400 }
428#if DEBUG_PUBLISH
429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); 401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n");
430#endif
431 /* final progress event */ 402 /* final progress event */
432 flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); 403 flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri);
433 pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; 404 pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS;
@@ -471,9 +442,7 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset,
471 p = pc->fi_pos; 442 p = pc->fi_pos;
472 if (NULL == pc->dsh) 443 if (NULL == pc->dsh)
473 { 444 {
474#if DEBUG_PUBLISH
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n"); 445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n");
476#endif
477 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); 446 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task);
478 pc->upload_task = 447 pc->upload_task =
479 GNUNET_SCHEDULER_add_with_priority 448 GNUNET_SCHEDULER_add_with_priority
@@ -481,17 +450,13 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset,
481 return; 450 return;
482 } 451 }
483 452
484 GNUNET_assert (GNUNET_NO == pc->in_network_wait);
485 pc->in_network_wait = GNUNET_YES;
486 if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) && 453 if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) &&
487 (type == GNUNET_BLOCK_TYPE_FS_DBLOCK)) 454 (type == GNUNET_BLOCK_TYPE_FS_DBLOCK))
488 { 455 {
489#if DEBUG_PUBLISH
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "Indexing block `%s' for offset %llu with index size %u\n", 457 "Indexing block `%s' for offset %llu with index size %u\n",
492 GNUNET_h2s (&chk->query), (unsigned long long) offset, 458 GNUNET_h2s (&chk->query), (unsigned long long) offset,
493 sizeof (struct OnDemandBlock)); 459 sizeof (struct OnDemandBlock));
494#endif
495 odb.offset = GNUNET_htonll (offset); 460 odb.offset = GNUNET_htonll (offset);
496 odb.file_id = p->data.file.file_id; 461 odb.file_id = p->data.file.file_id;
497 GNUNET_assert (pc->qre == NULL); 462 GNUNET_assert (pc->qre == NULL);
@@ -505,12 +470,10 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset,
505 &ds_put_cont, pc); 470 &ds_put_cont, pc);
506 return; 471 return;
507 } 472 }
508#if DEBUG_PUBLISH
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510 "Publishing block `%s' for offset %llu with size %u\n", 474 "Publishing block `%s' for offset %llu with size %u\n",
511 GNUNET_h2s (&chk->query), (unsigned long long) offset, 475 GNUNET_h2s (&chk->query), (unsigned long long) offset,
512 (unsigned int) block_size); 476 (unsigned int) block_size);
513#endif
514 GNUNET_assert (pc->qre == NULL); 477 GNUNET_assert (pc->qre == NULL);
515 pc->qre = 478 pc->qre =
516 GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid, 479 GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid,
@@ -573,9 +536,7 @@ publish_content (struct GNUNET_FS_PublishContext *pc)
573 { 536 {
574 if (p->is_directory) 537 if (p->is_directory)
575 { 538 {
576#if DEBUG_PUBLISH
577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n"); 539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n");
578#endif
579 db = GNUNET_FS_directory_builder_create (p->meta); 540 db = GNUNET_FS_directory_builder_create (p->meta);
580 dirpos = p->data.dir.entries; 541 dirpos = p->data.dir.entries;
581 while (NULL != dirpos) 542 while (NULL != dirpos)
@@ -617,18 +578,14 @@ publish_content (struct GNUNET_FS_PublishContext *pc)
617 GNUNET_FS_file_information_sync_ (p); 578 GNUNET_FS_file_information_sync_ (p);
618 } 579 }
619 size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; 580 size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size;
620#if DEBUG_PUBLISH
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n"); 581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n");
622#endif
623 p->te = 582 p->te =
624 GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader, 583 GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader,
625 &block_proc, &progress_proc, 584 &block_proc, &progress_proc,
626 &encode_cont); 585 &encode_cont);
627 586
628 } 587 }
629#if DEBUG_PUBLISH
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n"); 588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n");
631#endif
632 GNUNET_FS_tree_encoder_next (p->te); 589 GNUNET_FS_tree_encoder_next (p->te);
633} 590}
634 591
@@ -739,10 +696,8 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res)
739 publish_content (pc); 696 publish_content (pc);
740 return; 697 return;
741 } 698 }
742#if DEBUG_PUBLISH
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n", 699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n",
744 p->filename, GNUNET_h2s (res)); 700 p->filename, GNUNET_h2s (res));
745#endif
746 if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) 701 if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
747 { 702 {
748 p->data.file.file_id = *res; 703 p->data.file.file_id = *res;
@@ -779,13 +734,11 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res)
779 ism->device = GNUNET_htonll (dev); 734 ism->device = GNUNET_htonll (dev);
780 ism->inode = GNUNET_htonll (ino); 735 ism->inode = GNUNET_htonll (ino);
781 } 736 }
782#if DEBUG_PUBLISH
783 else 737 else
784 { 738 {
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786 _("Failed to get file identifiers for `%s'\n"), p->filename); 740 _("Failed to get file identifiers for `%s'\n"), p->filename);
787 } 741 }
788#endif
789 ism->file_id = *res; 742 ism->file_id = *res;
790 memcpy (&ism[1], fn, slen); 743 memcpy (&ism[1], fn, slen);
791 GNUNET_free (fn); 744 GNUNET_free (fn);
@@ -820,10 +773,8 @@ GNUNET_FS_publish_main_ (void *cls,
820 p = pc->fi_pos; 773 p = pc->fi_pos;
821 if (NULL == p) 774 if (NULL == p)
822 { 775 {
823#if DEBUG_PUBLISH
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 776 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "Publishing complete, now publishing SKS and KSK blocks.\n"); 777 "Publishing complete, now publishing SKS and KSK blocks.\n");
826#endif
827 /* upload of entire hierarchy complete, 778 /* upload of entire hierarchy complete,
828 * publish namespace entries */ 779 * publish namespace entries */
829 GNUNET_FS_publish_sync_ (pc); 780 GNUNET_FS_publish_sync_ (pc);
@@ -841,9 +792,7 @@ GNUNET_FS_publish_main_ (void *cls,
841 /* abort on error */ 792 /* abort on error */
842 if (NULL != p->emsg) 793 if (NULL != p->emsg)
843 { 794 {
844#if DEBUG_PUBLISH
845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg); 795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg);
846#endif
847 /* error with current file, abort all 796 /* error with current file, abort all
848 * related files as well! */ 797 * related files as well! */
849 while (NULL != p->dir) 798 while (NULL != p->dir)
@@ -873,10 +822,8 @@ GNUNET_FS_publish_main_ (void *cls,
873 /* handle completion */ 822 /* handle completion */
874 if (NULL != p->chk_uri) 823 if (NULL != p->chk_uri)
875 { 824 {
876#if DEBUG_PUBLISH
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878 "File upload complete, now publishing KSK blocks.\n"); 826 "File upload complete, now publishing KSK blocks.\n");
879#endif
880 if (0 == p->bo.anonymity_level) 827 if (0 == p->bo.anonymity_level)
881 { 828 {
882 /* zero anonymity, box CHK URI in LOC URI */ 829 /* zero anonymity, box CHK URI in LOC URI */
@@ -890,8 +837,8 @@ GNUNET_FS_publish_main_ (void *cls,
890 /* upload of "p" complete, publish KBlocks! */ 837 /* upload of "p" complete, publish KBlocks! */
891 if (p->keywords != NULL) 838 if (p->keywords != NULL)
892 { 839 {
893 GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo, 840 pc->ksk_pc = GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo,
894 pc->options, &publish_kblocks_cont, pc); 841 pc->options, &publish_kblocks_cont, pc);
895 } 842 }
896 else 843 else
897 { 844 {
@@ -959,9 +906,7 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi,
959 pc->skip_next_fi_callback = GNUNET_NO; 906 pc->skip_next_fi_callback = GNUNET_NO;
960 return GNUNET_OK; 907 return GNUNET_OK;
961 } 908 }
962#if DEBUG_PUBLISH
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n"); 909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n");
964#endif
965 if (*do_index) 910 if (*do_index)
966 { 911 {
967 /* space for on-demand blocks */ 912 /* space for on-demand blocks */
@@ -1043,9 +988,17 @@ fip_signal_suspend (void *cls, struct GNUNET_FS_FileInformation *fi,
1043 pc->skip_next_fi_callback = GNUNET_YES; 988 pc->skip_next_fi_callback = GNUNET_YES;
1044 GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc); 989 GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc);
1045 } 990 }
1046#if DEBUG_PUBLISH 991 if (NULL != pc->ksk_pc)
992 {
993 GNUNET_FS_publish_ksk_cancel (pc->ksk_pc);
994 pc->ksk_pc = NULL;
995 }
996 if (NULL != pc->sks_pc)
997 {
998 GNUNET_FS_publish_sks_cancel (pc->sks_pc);
999 pc->sks_pc = NULL;
1000 }
1047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n"); 1001 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n");
1048#endif
1049 GNUNET_free_non_null (fi->serialization); 1002 GNUNET_free_non_null (fi->serialization);
1050 fi->serialization = NULL; 1003 fi->serialization = NULL;
1051 off = (fi->chk_uri == NULL) ? 0 : length; 1004 off = (fi->chk_uri == NULL) ? 0 : length;
@@ -1086,7 +1039,7 @@ GNUNET_FS_publish_signal_suspend_ (void *cls)
1086 GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc); 1039 GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc);
1087 GNUNET_FS_end_top (pc->h, pc->top); 1040 GNUNET_FS_end_top (pc->h, pc->top);
1088 pc->top = NULL; 1041 pc->top = NULL;
1089 publish_cleanup (pc, NULL); 1042 publish_cleanup (pc);
1090} 1043}
1091 1044
1092 1045
@@ -1107,9 +1060,7 @@ finish_reserve (void *cls, int success,
1107 struct GNUNET_FS_PublishContext *pc = cls; 1060 struct GNUNET_FS_PublishContext *pc = cls;
1108 1061
1109 pc->qre = NULL; 1062 pc->qre = NULL;
1110#if DEBUG_PUBLISH
1111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success); 1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success);
1112#endif
1113 if ((msg != NULL) || (success <= 0)) 1064 if ((msg != NULL) || (success <= 0))
1114 { 1065 {
1115 GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"), 1066 GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"),
@@ -1267,14 +1218,17 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc)
1267 struct GNUNET_FS_ProgressInfo pi; 1218 struct GNUNET_FS_ProgressInfo pi;
1268 uint64_t off; 1219 uint64_t off;
1269 1220
1270#if DEBUG_PUBLISH
1271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n"); 1221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n");
1272#endif
1273 GNUNET_FS_end_top (pc->h, pc->top); 1222 GNUNET_FS_end_top (pc->h, pc->top);
1274 if (NULL != pc->qre) 1223 if (NULL != pc->ksk_pc)
1275 { 1224 {
1276 GNUNET_DATASTORE_cancel (pc->qre); 1225 GNUNET_FS_publish_ksk_cancel (pc->ksk_pc);
1277 pc->qre = NULL; 1226 pc->ksk_pc = NULL;
1227 }
1228 if (NULL != pc->sks_pc)
1229 {
1230 GNUNET_FS_publish_sks_cancel (pc->sks_pc);
1231 pc->sks_pc = NULL;
1278 } 1232 }
1279 if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) 1233 if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task)
1280 { 1234 {
@@ -1300,299 +1254,16 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc)
1300 GNUNET_free (pc->serialization); 1254 GNUNET_free (pc->serialization);
1301 pc->serialization = NULL; 1255 pc->serialization = NULL;
1302 } 1256 }
1303 if (GNUNET_YES == pc->in_network_wait) 1257 if (NULL != pc->qre)
1304 { 1258 {
1305 pc->in_network_wait = GNUNET_SYSERR; 1259 GNUNET_DATASTORE_cancel (pc->qre);
1306 return; 1260 pc->qre = NULL;
1307 } 1261 }
1308 pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; 1262 pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED;
1309 GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); 1263 GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off));
1310 publish_cleanup (pc, NULL); 1264 publish_cleanup (pc);
1311} 1265}
1312 1266
1313 1267
1314/**
1315 * Context for the KSK publication.
1316 */
1317struct PublishKskContext
1318{
1319
1320 /**
1321 * Keywords to use.
1322 */
1323 struct GNUNET_FS_Uri *ksk_uri;
1324
1325 /**
1326 * Global FS context.
1327 */
1328 struct GNUNET_FS_Handle *h;
1329
1330 /**
1331 * The master block that we are sending
1332 * (in plaintext), has "mdsize+slen" more
1333 * bytes than the struct would suggest.
1334 */
1335 struct KBlock *kb;
1336
1337 /**
1338 * Buffer of the same size as "kb" for
1339 * the encrypted version.
1340 */
1341 struct KBlock *cpy;
1342
1343 /**
1344 * Handle to the datastore, NULL if we are just
1345 * simulating.
1346 */
1347 struct GNUNET_DATASTORE_Handle *dsh;
1348
1349 /**
1350 * Handle to datastore PUT request.
1351 */
1352 struct GNUNET_DATASTORE_QueueEntry *qre;
1353
1354 /**
1355 * Function to call once we're done.
1356 */
1357 GNUNET_FS_PublishContinuation cont;
1358
1359 /**
1360 * Closure for cont.
1361 */
1362 void *cont_cls;
1363
1364 /**
1365 * When should the KBlocks expire?
1366 */
1367 struct GNUNET_FS_BlockOptions bo;
1368
1369 /**
1370 * Size of the serialized metadata.
1371 */
1372 ssize_t mdsize;
1373
1374 /**
1375 * Size of the (CHK) URI as a string.
1376 */
1377 size_t slen;
1378
1379 /**
1380 * Keyword that we are currently processing.
1381 */
1382 unsigned int i;
1383
1384};
1385
1386
1387/**
1388 * Continuation of "GNUNET_FS_publish_ksk" that performs
1389 * the actual publishing operation (iterating over all
1390 * of the keywords).
1391 *
1392 * @param cls closure of type "struct PublishKskContext*"
1393 * @param tc unused
1394 */
1395static void
1396publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1397
1398
1399/**
1400 * Function called by the datastore API with
1401 * the result from the PUT request.
1402 *
1403 * @param cls closure of type "struct PublishKskContext*"
1404 * @param success GNUNET_OK on success
1405 * @param min_expiration minimum expiration time required for content to be stored
1406 * @param msg error message (or NULL)
1407 */
1408static void
1409kb_put_cont (void *cls, int success,
1410 struct GNUNET_TIME_Absolute min_expiration,
1411 const char *msg)
1412{
1413 struct PublishKskContext *pkc = cls;
1414
1415 pkc->qre = NULL;
1416 if (GNUNET_OK != success)
1417 {
1418#if DEBUG_PUBLISH
1419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KB PUT operation complete\n");
1420#endif
1421 if (NULL != pkc->dsh)
1422 {
1423 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
1424 pkc->dsh = NULL;
1425 }
1426 GNUNET_free (pkc->cpy);
1427 GNUNET_free (pkc->kb);
1428 pkc->cont (pkc->cont_cls, NULL, msg);
1429 GNUNET_FS_uri_destroy (pkc->ksk_uri);
1430 GNUNET_free (pkc);
1431 return;
1432 }
1433 GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc,
1434 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1435}
1436
1437
1438/**
1439 * Continuation of "GNUNET_FS_publish_ksk" that performs the actual
1440 * publishing operation (iterating over all of the keywords).
1441 *
1442 * @param cls closure of type "struct PublishKskContext*"
1443 * @param tc unused
1444 */
1445static void
1446publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1447{
1448 struct PublishKskContext *pkc = cls;
1449 const char *keyword;
1450 GNUNET_HashCode key;
1451 GNUNET_HashCode query;
1452 struct GNUNET_CRYPTO_AesSessionKey skey;
1453 struct GNUNET_CRYPTO_AesInitializationVector iv;
1454 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
1455
1456
1457 if ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh))
1458 {
1459#if DEBUG_PUBLISH
1460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n");
1461#endif
1462 if (NULL != pkc->dsh)
1463 {
1464 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
1465 pkc->dsh = NULL;
1466 }
1467 GNUNET_free (pkc->cpy);
1468 GNUNET_free (pkc->kb);
1469 pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL);
1470 GNUNET_FS_uri_destroy (pkc->ksk_uri);
1471 GNUNET_free (pkc);
1472 return;
1473 }
1474 keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
1475#if DEBUG_PUBLISH
1476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n",
1477 keyword);
1478#endif
1479 /* first character of keyword indicates if it is
1480 * mandatory or not -- ignore for hashing */
1481 GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
1482 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
1483 GNUNET_CRYPTO_aes_encrypt (&pkc->kb[1], pkc->slen + pkc->mdsize, &skey, &iv,
1484 &pkc->cpy[1]);
1485 pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
1486 GNUNET_assert (NULL != pk);
1487 GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace);
1488 GNUNET_CRYPTO_hash (&pkc->cpy->keyspace,
1489 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1490 &query);
1491 GNUNET_assert (GNUNET_OK ==
1492 GNUNET_CRYPTO_rsa_sign (pk, &pkc->cpy->purpose,
1493 &pkc->cpy->signature));
1494 GNUNET_CRYPTO_rsa_key_free (pk);
1495 pkc->qre =
1496 GNUNET_DATASTORE_put (pkc->dsh, 0, &query,
1497 pkc->mdsize + sizeof (struct KBlock) + pkc->slen,
1498 pkc->cpy, GNUNET_BLOCK_TYPE_FS_KBLOCK,
1499 pkc->bo.content_priority, pkc->bo.anonymity_level,
1500 pkc->bo.replication_level, pkc->bo.expiration_time,
1501 -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
1502 &kb_put_cont, pkc);
1503}
1504
1505
1506/**
1507 * Publish a CHK under various keywords on GNUnet.
1508 *
1509 * @param h handle to the file sharing subsystem
1510 * @param ksk_uri keywords to use
1511 * @param meta metadata to use
1512 * @param uri URI to refer to in the KBlock
1513 * @param bo per-block options
1514 * @param options publication options
1515 * @param cont continuation
1516 * @param cont_cls closure for cont
1517 */
1518void
1519GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
1520 const struct GNUNET_FS_Uri *ksk_uri,
1521 const struct GNUNET_CONTAINER_MetaData *meta,
1522 const struct GNUNET_FS_Uri *uri,
1523 const struct GNUNET_FS_BlockOptions *bo,
1524 enum GNUNET_FS_PublishOptions options,
1525 GNUNET_FS_PublishContinuation cont, void *cont_cls)
1526{
1527 struct PublishKskContext *pkc;
1528 char *uris;
1529 size_t size;
1530 char *kbe;
1531 char *sptr;
1532
1533 GNUNET_assert (NULL != uri);
1534 pkc = GNUNET_malloc (sizeof (struct PublishKskContext));
1535 pkc->h = h;
1536 pkc->bo = *bo;
1537 pkc->cont = cont;
1538 pkc->cont_cls = cont_cls;
1539 if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
1540 {
1541 pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
1542 if (pkc->dsh == NULL)
1543 {
1544 cont (cont_cls, NULL, _("Could not connect to datastore."));
1545 GNUNET_free (pkc);
1546 return;
1547 }
1548 }
1549 if (meta == NULL)
1550 pkc->mdsize = 0;
1551 else
1552 pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
1553 GNUNET_assert (pkc->mdsize >= 0);
1554 uris = GNUNET_FS_uri_to_string (uri);
1555 pkc->slen = strlen (uris) + 1;
1556 size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen;
1557 if (size > MAX_KBLOCK_SIZE)
1558 {
1559 size = MAX_KBLOCK_SIZE;
1560 pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen;
1561 }
1562 pkc->kb = GNUNET_malloc (size);
1563 kbe = (char *) &pkc->kb[1];
1564 memcpy (kbe, uris, pkc->slen);
1565 GNUNET_free (uris);
1566 sptr = &kbe[pkc->slen];
1567 if (meta != NULL)
1568 pkc->mdsize =
1569 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
1570 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
1571 if (pkc->mdsize == -1)
1572 {
1573 GNUNET_break (0);
1574 GNUNET_free (pkc->kb);
1575 if (pkc->dsh != NULL)
1576 {
1577 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
1578 pkc->dsh = NULL;
1579 }
1580 cont (cont_cls, NULL, _("Internal error."));
1581 GNUNET_free (pkc);
1582 return;
1583 }
1584 size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize;
1585
1586 pkc->cpy = GNUNET_malloc (size);
1587 pkc->cpy->purpose.size =
1588 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1589 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
1590 pkc->mdsize + pkc->slen);
1591 pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK);
1592 pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
1593 GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc,
1594 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1595}
1596
1597 1268
1598/* end of fs_publish.c */ 1269/* end of fs_publish.c */
diff --git a/src/fs/fs_publish_ksk.c b/src/fs/fs_publish_ksk.c
new file mode 100644
index 000000000..5119de4c5
--- /dev/null
+++ b/src/fs/fs_publish_ksk.c
@@ -0,0 +1,342 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors)
4
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
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/fs_publish_ksk.c
23 * @brief publish a URI under a keyword in GNUnet
24 * @see https://gnunet.org/encoding
25 * @author Krista Bennett
26 * @author Christian Grothoff
27 */
28
29#include "platform.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_fs_service.h"
34#include "fs_api.h"
35#include "fs_tree.h"
36
37
38/**
39 * Maximum legal size for a kblock.
40 */
41#define MAX_KBLOCK_SIZE (60 * 1024)
42
43
44/**
45 * Context for the KSK publication.
46 */
47struct GNUNET_FS_PublishKskContext
48{
49
50 /**
51 * Keywords to use.
52 */
53 struct GNUNET_FS_Uri *ksk_uri;
54
55 /**
56 * Global FS context.
57 */
58 struct GNUNET_FS_Handle *h;
59
60 /**
61 * The master block that we are sending
62 * (in plaintext), has "mdsize+slen" more
63 * bytes than the struct would suggest.
64 */
65 struct KBlock *kb;
66
67 /**
68 * Buffer of the same size as "kb" for
69 * the encrypted version.
70 */
71 struct KBlock *cpy;
72
73 /**
74 * Handle to the datastore, NULL if we are just
75 * simulating.
76 */
77 struct GNUNET_DATASTORE_Handle *dsh;
78
79 /**
80 * Handle to datastore PUT request.
81 */
82 struct GNUNET_DATASTORE_QueueEntry *qre;
83
84 /**
85 * Current task.
86 */
87 GNUNET_SCHEDULER_TaskIdentifier ksk_task;
88
89 /**
90 * Function to call once we're done.
91 */
92 GNUNET_FS_PublishContinuation cont;
93
94 /**
95 * Closure for cont.
96 */
97 void *cont_cls;
98
99 /**
100 * When should the KBlocks expire?
101 */
102 struct GNUNET_FS_BlockOptions bo;
103
104 /**
105 * Size of the serialized metadata.
106 */
107 ssize_t mdsize;
108
109 /**
110 * Size of the (CHK) URI as a string.
111 */
112 size_t slen;
113
114 /**
115 * Keyword that we are currently processing.
116 */
117 unsigned int i;
118
119};
120
121
122/**
123 * Continuation of "GNUNET_FS_publish_ksk" that performs
124 * the actual publishing operation (iterating over all
125 * of the keywords).
126 *
127 * @param cls closure of type "struct PublishKskContext*"
128 * @param tc unused
129 */
130static void
131publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
132
133
134/**
135 * Function called by the datastore API with
136 * the result from the PUT request.
137 *
138 * @param cls closure of type "struct GNUNET_FS_PublishKskContext*"
139 * @param success GNUNET_OK on success
140 * @param min_expiration minimum expiration time required for content to be stored
141 * @param msg error message (or NULL)
142 */
143static void
144kb_put_cont (void *cls, int success,
145 struct GNUNET_TIME_Absolute min_expiration,
146 const char *msg)
147{
148 struct GNUNET_FS_PublishKskContext *pkc = cls;
149
150 pkc->qre = NULL;
151 if (GNUNET_OK != success)
152 {
153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154 "KBlock PUT operation failed: %s\n", msg);
155 pkc->cont (pkc->cont_cls, NULL, msg);
156 GNUNET_FS_publish_ksk_cancel (pkc);
157 return;
158 }
159 pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
160}
161
162
163/**
164 * Continuation of "GNUNET_FS_publish_ksk" that performs the actual
165 * publishing operation (iterating over all of the keywords).
166 *
167 * @param cls closure of type "struct GNUNET_FS_PublishKskContext*"
168 * @param tc unused
169 */
170static void
171publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
172{
173 struct GNUNET_FS_PublishKskContext *pkc = cls;
174 const char *keyword;
175 GNUNET_HashCode key;
176 GNUNET_HashCode query;
177 struct GNUNET_CRYPTO_AesSessionKey skey;
178 struct GNUNET_CRYPTO_AesInitializationVector iv;
179 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
180
181 pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK;
182 if ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh))
183 {
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n");
185 pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL);
186 GNUNET_FS_publish_ksk_cancel (pkc);
187 return;
188 }
189 keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n",
191 keyword);
192 /* first character of keyword indicates if it is
193 * mandatory or not -- ignore for hashing */
194 GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
195 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
196 GNUNET_CRYPTO_aes_encrypt (&pkc->kb[1], pkc->slen + pkc->mdsize, &skey, &iv,
197 &pkc->cpy[1]);
198 pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
199 GNUNET_assert (NULL != pk);
200 GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace);
201 GNUNET_CRYPTO_hash (&pkc->cpy->keyspace,
202 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
203 &query);
204 GNUNET_assert (GNUNET_OK ==
205 GNUNET_CRYPTO_rsa_sign (pk, &pkc->cpy->purpose,
206 &pkc->cpy->signature));
207 GNUNET_CRYPTO_rsa_key_free (pk);
208 pkc->qre =
209 GNUNET_DATASTORE_put (pkc->dsh, 0, &query,
210 pkc->mdsize + sizeof (struct KBlock) + pkc->slen,
211 pkc->cpy, GNUNET_BLOCK_TYPE_FS_KBLOCK,
212 pkc->bo.content_priority, pkc->bo.anonymity_level,
213 pkc->bo.replication_level, pkc->bo.expiration_time,
214 -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
215 &kb_put_cont, pkc);
216}
217
218
219/**
220 * Publish a CHK under various keywords on GNUnet.
221 *
222 * @param h handle to the file sharing subsystem
223 * @param ksk_uri keywords to use
224 * @param meta metadata to use
225 * @param uri URI to refer to in the KBlock
226 * @param bo per-block options
227 * @param options publication options
228 * @param cont continuation
229 * @param cont_cls closure for cont
230 * @return NULL on error ('cont' will still be called)
231 */
232struct GNUNET_FS_PublishKskContext *
233GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
234 const struct GNUNET_FS_Uri *ksk_uri,
235 const struct GNUNET_CONTAINER_MetaData *meta,
236 const struct GNUNET_FS_Uri *uri,
237 const struct GNUNET_FS_BlockOptions *bo,
238 enum GNUNET_FS_PublishOptions options,
239 GNUNET_FS_PublishContinuation cont, void *cont_cls)
240{
241 struct GNUNET_FS_PublishKskContext *pkc;
242 char *uris;
243 size_t size;
244 char *kbe;
245 char *sptr;
246
247 GNUNET_assert (NULL != uri);
248 pkc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishKskContext));
249 pkc->h = h;
250 pkc->bo = *bo;
251 pkc->cont = cont;
252 pkc->cont_cls = cont_cls;
253 if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
254 {
255 pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
256 if (NULL == pkc->dsh)
257 {
258 cont (cont_cls, NULL, _("Could not connect to datastore."));
259 GNUNET_free (pkc);
260 return NULL;
261 }
262 }
263 if (meta == NULL)
264 pkc->mdsize = 0;
265 else
266 pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
267 GNUNET_assert (pkc->mdsize >= 0);
268 uris = GNUNET_FS_uri_to_string (uri);
269 pkc->slen = strlen (uris) + 1;
270 size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen;
271 if (size > MAX_KBLOCK_SIZE)
272 {
273 size = MAX_KBLOCK_SIZE;
274 pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen;
275 }
276 pkc->kb = GNUNET_malloc (size);
277 kbe = (char *) &pkc->kb[1];
278 memcpy (kbe, uris, pkc->slen);
279 GNUNET_free (uris);
280 sptr = &kbe[pkc->slen];
281 if (meta != NULL)
282 pkc->mdsize =
283 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
284 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
285 if (-1 == pkc->mdsize)
286 {
287 GNUNET_break (0);
288 GNUNET_free (pkc->kb);
289 if (pkc->dsh != NULL)
290 {
291 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
292 pkc->dsh = NULL;
293 }
294 GNUNET_free (pkc);
295 cont (cont_cls, NULL, _("Internal error."));
296 return NULL;
297 }
298 size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize;
299
300 pkc->cpy = GNUNET_malloc (size);
301 pkc->cpy->purpose.size =
302 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
303 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
304 pkc->mdsize + pkc->slen);
305 pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK);
306 pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
307 pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
308 return pkc;
309}
310
311
312/**
313 * Abort the KSK publishing operation.
314 *
315 * @param pkc context of the operation to abort.
316 */
317void
318GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc)
319{
320 if (GNUNET_SCHEDULER_NO_TASK != pkc->ksk_task)
321 {
322 GNUNET_SCHEDULER_cancel (pkc->ksk_task);
323 pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK;
324 }
325 if (NULL != pkc->qre)
326 {
327 GNUNET_DATASTORE_cancel (pkc->qre);
328 pkc->qre = NULL;
329 }
330 if (NULL != pkc->dsh)
331 {
332 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
333 pkc->dsh = NULL;
334 }
335 GNUNET_free (pkc->cpy);
336 GNUNET_free (pkc->kb);
337 GNUNET_FS_uri_destroy (pkc->ksk_uri);
338 GNUNET_free (pkc);
339}
340
341
342/* end of fs_publish_ksk.c */
diff --git a/src/fs/fs_tree.c b/src/fs/fs_tree.c
index fc04446c9..2ac38ffd3 100644
--- a/src/fs/fs_tree.c
+++ b/src/fs/fs_tree.c
@@ -360,8 +360,7 @@ GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder *te)
360 if (pt_size != 360 if (pt_size !=
361 te->reader (te->cls, te->publish_offset, pt_size, iob, &te->emsg)) 361 te->reader (te->cls, te->publish_offset, pt_size, iob, &te->emsg))
362 { 362 {
363 GNUNET_SCHEDULER_add_continuation (te->cont, te->cls, 363 te->cont (te->cls, NULL);
364 GNUNET_SCHEDULER_REASON_TIMEOUT);
365 te->in_next = GNUNET_NO; 364 te->in_next = GNUNET_NO;
366 return; 365 return;
367 } 366 }
diff --git a/src/fs/gnunet-fs.c b/src/fs/gnunet-fs.c
index 8cf08ec28..0b2892371 100644
--- a/src/fs/gnunet-fs.c
+++ b/src/fs/gnunet-fs.c
@@ -47,20 +47,6 @@ static int verbose;
47 47
48 48
49/** 49/**
50 * Shutdown this process.
51 *
52 * @param cls unused
53 * @param tc unused
54 */
55static void
56do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
57{
58 GNUNET_FS_stop (fs);
59 fs = NULL;
60}
61
62
63/**
64 * Print indexed filenames to stdout. 50 * Print indexed filenames to stdout.
65 * 51 *
66 * @param cls closure 52 * @param cls closure
@@ -71,6 +57,12 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
71static int 57static int
72print_indexed (void *cls, const char *filename, const GNUNET_HashCode * file_id) 58print_indexed (void *cls, const char *filename, const GNUNET_HashCode * file_id)
73{ 59{
60 if (NULL == filename)
61 {
62 GNUNET_FS_stop (fs);
63 fs = NULL;
64 return GNUNET_OK;
65 }
74 if (verbose) 66 if (verbose)
75 FPRINTF (stdout, "%s: %s\n", GNUNET_h2s (file_id), filename); 67 FPRINTF (stdout, "%s: %s\n", GNUNET_h2s (file_id), filename);
76 else 68 else
@@ -100,7 +92,13 @@ run (void *cls, char *const *args, const char *cfgfile,
100 ret = 1; 92 ret = 1;
101 return; 93 return;
102 } 94 }
103 GNUNET_FS_get_indexed_files (fs, &print_indexed, NULL, &do_shutdown, NULL); 95 if (NULL == GNUNET_FS_get_indexed_files (fs, &print_indexed, NULL))
96 {
97 ret = 2;
98 GNUNET_FS_stop (fs);
99 fs = NULL;
100 return;
101 }
104 } 102 }
105} 103}
106 104
diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c
index 370f1062c..8f8d9147c 100644
--- a/src/fs/gnunet-publish.c
+++ b/src/fs/gnunet-publish.c
@@ -356,7 +356,7 @@ uri_ksk_continuation (void *cls, const struct GNUNET_FS_Uri *ksk_uri,
356 { 356 {
357 GNUNET_FS_publish_sks (ctx, ns, this_id, next_id, meta, uri, &bo, 357 GNUNET_FS_publish_sks (ctx, ns, this_id, next_id, meta, uri, &bo,
358 GNUNET_FS_PUBLISH_OPTION_NONE, 358 GNUNET_FS_PUBLISH_OPTION_NONE,
359 uri_sks_continuation, NULL); 359 &uri_sks_continuation, NULL);
360 GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_NO)); 360 GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_NO));
361 return; 361 return;
362 } 362 }