-preparations for replacement of try_connect call
[oweals/gnunet.git] / src / fs / fs_publish_ksk.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 2012, 2013 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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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 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  * @param tc unused
114  */
115 static void
116 publish_ksk_cont (void *cls,
117                   const struct GNUNET_SCHEDULER_TaskContext *tc);
118
119
120 /**
121  * Function called by the datastore API with
122  * the result from the PUT request.
123  *
124  * @param cls closure of type `struct GNUNET_FS_PublishKskContext *`
125  * @param msg error message (or NULL)
126  */
127 static void
128 kb_put_cont (void *cls,
129              const char *msg)
130 {
131   struct GNUNET_FS_PublishKskContext *pkc = cls;
132
133   pkc->uc = NULL;
134   if (NULL != msg)
135   {
136     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
137                 "KBlock PUT operation failed: %s\n", msg);
138     pkc->cont (pkc->cont_cls, NULL, msg);
139     GNUNET_FS_publish_ksk_cancel (pkc);
140     return;
141   }
142   pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
143 }
144
145
146 /**
147  * Continuation of #GNUNET_FS_publish_ksk() that performs the actual
148  * publishing operation (iterating over all of the keywords).
149  *
150  * @param cls closure of type `struct GNUNET_FS_PublishKskContext *`
151  * @param tc unused
152  */
153 static void
154 publish_ksk_cont (void *cls,
155                   const struct GNUNET_SCHEDULER_TaskContext *tc)
156 {
157   struct GNUNET_FS_PublishKskContext *pkc = cls;
158   const char *keyword;
159
160   pkc->ksk_task = NULL;
161   if ( (pkc->i == pkc->ksk_uri->data.ksk.keywordCount) ||
162        (NULL == pkc->dsh) )
163   {
164     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
165                 "KSK PUT operation complete\n");
166     pkc->cont (pkc->cont_cls, pkc->ksk_uri,
167                NULL);
168     GNUNET_FS_publish_ksk_cancel (pkc);
169     return;
170   }
171   keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
172   pkc->uc = GNUNET_FS_publish_ublock_ (pkc->h,
173                                        pkc->dsh,
174                                        keyword + 1 /* skip '+' */,
175                                        NULL,
176                                        GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
177                                        pkc->meta,
178                                        pkc->uri,
179                                        &pkc->bo,
180                                        pkc->options,
181                                        &kb_put_cont, pkc);
182 }
183
184
185 /**
186  * Publish a CHK under various keywords on GNUnet.
187  *
188  * @param h handle to the file sharing subsystem
189  * @param ksk_uri keywords to use
190  * @param meta metadata to use
191  * @param uri URI to refer to in the KBlock
192  * @param bo per-block options
193  * @param options publication options
194  * @param cont continuation
195  * @param cont_cls closure for cont
196  * @return NULL on error ('cont' will still be called)
197  */
198 struct GNUNET_FS_PublishKskContext *
199 GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
200                        const struct GNUNET_FS_Uri *ksk_uri,
201                        const struct GNUNET_CONTAINER_MetaData *meta,
202                        const struct GNUNET_FS_Uri *uri,
203                        const struct GNUNET_FS_BlockOptions *bo,
204                        enum GNUNET_FS_PublishOptions options,
205                        GNUNET_FS_PublishContinuation cont, void *cont_cls)
206 {
207   struct GNUNET_FS_PublishKskContext *pkc;
208
209   GNUNET_assert (NULL != uri);
210   pkc = GNUNET_new (struct GNUNET_FS_PublishKskContext);
211   pkc->h = h;
212   pkc->bo = *bo;
213   pkc->options = options;
214   pkc->cont = cont;
215   pkc->cont_cls = cont_cls;
216   pkc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
217   if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
218   {
219     pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
220     if (NULL == pkc->dsh)
221     {
222       cont (cont_cls,
223             NULL,
224             _("Could not connect to datastore."));
225       GNUNET_free (pkc);
226       return NULL;
227     }
228   }
229   pkc->uri = GNUNET_FS_uri_dup (uri);
230   pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
231   pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
232   return pkc;
233 }
234
235
236 /**
237  * Abort the KSK publishing operation.
238  *
239  * @param pkc context of the operation to abort.
240  */
241 void
242 GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc)
243 {
244   if (NULL != pkc->ksk_task)
245   {
246     GNUNET_SCHEDULER_cancel (pkc->ksk_task);
247     pkc->ksk_task = NULL;
248   }
249   if (NULL != pkc->uc)
250   {
251     GNUNET_FS_publish_ublock_cancel_ (pkc->uc);
252     pkc->uc = NULL;
253   }
254   if (NULL != pkc->dsh)
255   {
256     GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
257     pkc->dsh = NULL;
258   }
259   GNUNET_CONTAINER_meta_data_destroy (pkc->meta);
260   GNUNET_FS_uri_destroy (pkc->ksk_uri);
261   GNUNET_FS_uri_destroy (pkc->uri);
262   GNUNET_free (pkc);
263 }
264
265
266 /* end of fs_publish_ksk.c */