aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_publish_ksk.c
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/fs_publish_ksk.c
parent6d0a62078edfa5c0001acb93d517c674c5124f4e (diff)
downloadgnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.tar.gz
gnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.zip
make all (?) asynchronously operating FS operations actually cancel-able
Diffstat (limited to 'src/fs/fs_publish_ksk.c')
-rw-r--r--src/fs/fs_publish_ksk.c342
1 files changed, 342 insertions, 0 deletions
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 */