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