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