glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / fs / fs_publish_ksk.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 2012, 2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14 */
15
16 /**
17  * @file fs/fs_publish_ksk.c
18  * @brief publish a URI under a keyword in GNUnet
19  * @see https://gnunet.org/encoding and #2564
20  * @author Krista Bennett
21  * @author Christian Grothoff
22  */
23
24 #include "platform.h"
25 #include "gnunet_constants.h"
26 #include "gnunet_signatures.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_fs_service.h"
29 #include "fs_api.h"
30 #include "fs_tree.h"
31 #include "fs_publish_ublock.h"
32
33 /**
34  * Context for the KSK publication.
35  */
36 struct GNUNET_FS_PublishKskContext
37 {
38
39   /**
40    * Keywords to use.
41    */
42   struct GNUNET_FS_Uri *ksk_uri;
43
44   /**
45    * URI to publish.
46    */
47   struct GNUNET_FS_Uri *uri;
48
49   /**
50    * Metadata to use.
51    */
52   struct GNUNET_CONTAINER_MetaData *meta;
53
54   /**
55    * Global FS context.
56    */
57   struct GNUNET_FS_Handle *h;
58
59   /**
60    * UBlock publishing operation that is active.
61    */
62   struct GNUNET_FS_PublishUblockContext *uc;
63
64   /**
65    * Handle to the datastore, NULL if we are just simulating.
66    */
67   struct GNUNET_DATASTORE_Handle *dsh;
68
69   /**
70    * Current task.
71    */
72   struct GNUNET_SCHEDULER_Task * ksk_task;
73
74   /**
75    * Function to call once we're done.
76    */
77   GNUNET_FS_PublishContinuation cont;
78
79   /**
80    * Closure for cont.
81    */
82   void *cont_cls;
83
84   /**
85    * When should the KBlocks expire?
86    */
87   struct GNUNET_FS_BlockOptions bo;
88
89   /**
90    * Options to use.
91    */
92   enum GNUNET_FS_PublishOptions options;
93
94   /**
95    * Keyword that we are currently processing.
96    */
97   unsigned int i;
98
99 };
100
101
102 /**
103  * Continuation of #GNUNET_FS_publish_ksk() that performs
104  * the actual publishing operation (iterating over all
105  * of the keywords).
106  *
107  * @param cls closure of type `struct PublishKskContext *`
108  */
109 static void
110 publish_ksk_cont (void *cls);
111
112
113 /**
114  * Function called by the datastore API with
115  * the result from the PUT request.
116  *
117  * @param cls closure of type `struct GNUNET_FS_PublishKskContext *`
118  * @param msg error message (or NULL)
119  */
120 static void
121 kb_put_cont (void *cls,
122              const char *msg)
123 {
124   struct GNUNET_FS_PublishKskContext *pkc = cls;
125
126   pkc->uc = NULL;
127   if (NULL != msg)
128   {
129     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130                 "KBlock PUT operation failed: %s\n", msg);
131     pkc->cont (pkc->cont_cls, NULL, msg);
132     GNUNET_FS_publish_ksk_cancel (pkc);
133     return;
134   }
135   pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
136 }
137
138
139 /**
140  * Continuation of #GNUNET_FS_publish_ksk() that performs the actual
141  * publishing operation (iterating over all of the keywords).
142  *
143  * @param cls closure of type `struct GNUNET_FS_PublishKskContext *`
144  */
145 static void
146 publish_ksk_cont (void *cls)
147 {
148   struct GNUNET_FS_PublishKskContext *pkc = cls;
149   const char *keyword;
150
151   pkc->ksk_task = NULL;
152   if ( (pkc->i == pkc->ksk_uri->data.ksk.keywordCount) ||
153        (NULL == pkc->dsh) )
154   {
155     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
156                 "KSK PUT operation complete\n");
157     pkc->cont (pkc->cont_cls, pkc->ksk_uri,
158                NULL);
159     GNUNET_FS_publish_ksk_cancel (pkc);
160     return;
161   }
162   keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
163   pkc->uc = GNUNET_FS_publish_ublock_ (pkc->h,
164                                        pkc->dsh,
165                                        keyword + 1 /* skip '+' */,
166                                        NULL,
167                                        GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
168                                        pkc->meta,
169                                        pkc->uri,
170                                        &pkc->bo,
171                                        pkc->options,
172                                        &kb_put_cont, pkc);
173 }
174
175
176 /**
177  * Publish a CHK under various keywords on GNUnet.
178  *
179  * @param h handle to the file sharing subsystem
180  * @param ksk_uri keywords to use
181  * @param meta metadata to use
182  * @param uri URI to refer to in the KBlock
183  * @param bo per-block options
184  * @param options publication options
185  * @param cont continuation
186  * @param cont_cls closure for cont
187  * @return NULL on error ('cont' will still be called)
188  */
189 struct GNUNET_FS_PublishKskContext *
190 GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
191                        const struct GNUNET_FS_Uri *ksk_uri,
192                        const struct GNUNET_CONTAINER_MetaData *meta,
193                        const struct GNUNET_FS_Uri *uri,
194                        const struct GNUNET_FS_BlockOptions *bo,
195                        enum GNUNET_FS_PublishOptions options,
196                        GNUNET_FS_PublishContinuation cont, void *cont_cls)
197 {
198   struct GNUNET_FS_PublishKskContext *pkc;
199
200   GNUNET_assert (NULL != uri);
201   pkc = GNUNET_new (struct GNUNET_FS_PublishKskContext);
202   pkc->h = h;
203   pkc->bo = *bo;
204   pkc->options = options;
205   pkc->cont = cont;
206   pkc->cont_cls = cont_cls;
207   pkc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
208   if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
209   {
210     pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
211     if (NULL == pkc->dsh)
212     {
213       cont (cont_cls,
214             NULL,
215             _("Could not connect to datastore."));
216       GNUNET_free (pkc);
217       return NULL;
218     }
219   }
220   pkc->uri = GNUNET_FS_uri_dup (uri);
221   pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
222   pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
223   return pkc;
224 }
225
226
227 /**
228  * Abort the KSK publishing operation.
229  *
230  * @param pkc context of the operation to abort.
231  */
232 void
233 GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc)
234 {
235   if (NULL != pkc->ksk_task)
236   {
237     GNUNET_SCHEDULER_cancel (pkc->ksk_task);
238     pkc->ksk_task = NULL;
239   }
240   if (NULL != pkc->uc)
241   {
242     GNUNET_FS_publish_ublock_cancel_ (pkc->uc);
243     pkc->uc = NULL;
244   }
245   if (NULL != pkc->dsh)
246   {
247     GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
248     pkc->dsh = NULL;
249   }
250   GNUNET_CONTAINER_meta_data_destroy (pkc->meta);
251   GNUNET_FS_uri_destroy (pkc->ksk_uri);
252   GNUNET_FS_uri_destroy (pkc->uri);
253   GNUNET_free (pkc);
254 }
255
256
257 /* end of fs_publish_ksk.c */