error handling
[oweals/gnunet.git] / src / fs / fs_list_indexed.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2003, 2004, 2006, 2009 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_list_indexed.c
23  * @author Christian Grothoff
24  * @brief provide a list of all indexed files
25  */
26
27 #include "platform.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_fs_service.h"
30 #include "gnunet_protocols.h"
31 #include "fs_api.h"
32
33
34 /**
35  * Context for #GNUNET_FS_get_indexed_files().
36  */
37 struct GNUNET_FS_GetIndexedContext
38 {
39   /**
40    * Connection to the FS service.
41    */
42   struct GNUNET_MQ_Handle *mq;
43
44   /**
45    * Function to call for each indexed file.
46    */
47   GNUNET_FS_IndexedFileProcessor iterator;
48
49   /**
50    * Closure for @e iterator.
51    */
52   void *iterator_cls;
53
54   /**
55    * Continuation to trigger at the end.
56    */
57   GNUNET_SCHEDULER_TaskCallback cont;
58
59   /**
60    * Closure for @e cont.
61    */
62   void *cont_cls;
63 };
64
65
66 /**
67  * Function called on each response from the FS
68  * service with information about indexed files.
69  *
70  * @param cls closure (of type `struct GNUNET_FS_GetIndexedContext *`)
71  * @param msg message with indexing information
72  */
73 static void
74 handle_index_info_end (void *cls,
75                        const struct GNUNET_MessageHeader *msg)
76 {
77   struct GNUNET_FS_GetIndexedContext *gic = cls;
78
79   (void) gic->iterator (gic->iterator_cls,
80                         NULL,
81                         NULL);
82   GNUNET_FS_get_indexed_files_cancel (gic);
83 }
84
85
86 /**
87  * Check validity of response from the FS
88  * service with information about indexed files.
89  *
90  * @param cls closure (of type `struct GNUNET_FS_GetIndexedContext *`)
91  * @param iim message with indexing information
92  */
93 static int
94 check_index_info (void *cls,
95                   const struct IndexInfoMessage *iim)
96 {
97   uint16_t msize = ntohs (iim->header.size) - sizeof(*iim);
98   const char *filename;
99
100   filename = (const char *) &iim[1];
101   if (filename[msize - 1] != '\0')
102   {
103     GNUNET_break (0);
104     return GNUNET_SYSERR;
105   }
106   return GNUNET_OK;
107 }
108
109
110 /**
111  * Function called on each response from the FS
112  * service with information about indexed files.
113  *
114  * @param cls closure (of type `struct GNUNET_FS_GetIndexedContext *`)
115  * @param iim message with indexing information
116  */
117 static void
118 handle_index_info (void *cls,
119                    const struct IndexInfoMessage *iim)
120 {
121   struct GNUNET_FS_GetIndexedContext *gic = cls;
122   const char *filename;
123
124   filename = (const char *) &iim[1];
125   if (GNUNET_OK !=
126       gic->iterator (gic->iterator_cls,
127                      filename,
128                      &iim->file_id))
129   {
130     GNUNET_FS_get_indexed_files_cancel (gic);
131     return;
132   }
133 }
134
135
136 /**
137  * Generic error handler, called with the appropriate error code and
138  * the same closure specified at the creation of the message queue.
139  * Not every message queue implementation supports an error handler.
140  *
141  * @param cls closure with the `struct GNUNET_FS_GetIndexedContent *`
142  * @param error error code
143  */
144 static void
145 mq_error_handler (void *cls,
146                   enum GNUNET_MQ_Error error)
147 {
148   struct GNUNET_FS_GetIndexedContext *gic = cls;
149
150   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
151               _ ("Failed to receive response from `%s' service.\n"),
152               "fs");
153   (void) gic->iterator (gic->iterator_cls, NULL, NULL);
154   GNUNET_FS_get_indexed_files_cancel (gic);
155 }
156
157
158 /**
159  * Iterate over all indexed files.
160  *
161  * @param h handle to the file sharing subsystem
162  * @param iterator function to call on each indexed file
163  * @param iterator_cls closure for iterator
164  * @return NULL on error ('iter' is not called)
165  */
166 struct GNUNET_FS_GetIndexedContext *
167 GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
168                              GNUNET_FS_IndexedFileProcessor iterator,
169                              void *iterator_cls)
170 {
171   struct GNUNET_FS_GetIndexedContext *gic
172     = GNUNET_new (struct GNUNET_FS_GetIndexedContext);
173   struct GNUNET_MQ_MessageHandler handlers[] = {
174     GNUNET_MQ_hd_fixed_size (index_info_end,
175                              GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END,
176                              struct GNUNET_MessageHeader,
177                              gic),
178     GNUNET_MQ_hd_var_size (index_info,
179                            GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY,
180                            struct IndexInfoMessage,
181                            gic),
182     GNUNET_MQ_handler_end ()
183   };
184   struct GNUNET_MQ_Envelope *env;
185   struct GNUNET_MessageHeader *msg;
186
187   gic->mq = GNUNET_CLIENT_connect (h->cfg,
188                                    "fs",
189                                    handlers,
190                                    &mq_error_handler,
191                                    h);
192   if (NULL == gic->mq)
193   {
194     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
195                 _ ("Failed to not connect to `%s' service.\n"),
196                 "fs");
197     GNUNET_free (gic);
198     return NULL;
199   }
200   gic->iterator = iterator;
201   gic->iterator_cls = iterator_cls;
202   env = GNUNET_MQ_msg (msg,
203                        GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET);
204   GNUNET_MQ_send (gic->mq,
205                   env);
206   return gic;
207 }
208
209
210 /**
211  * Cancel iteration over all indexed files.
212  *
213  * @param gic operation to cancel
214  */
215 void
216 GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic)
217 {
218   GNUNET_MQ_destroy (gic->mq);
219   GNUNET_free (gic);
220 }
221
222
223 /* end of fs_list_indexed.c */