types
[oweals/gnunet.git] / src / fs / fs_list_indexed.c
1 /*
2      This file is part of GNUnet.
3      (C) 2003, 2004, 2006, 2009 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 2, 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
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.h"
32
33
34 /**
35  * Context for "GNUNET_FS_get_indexed_files".
36  */
37 struct GetIndexedContext
38 {
39   /**
40    * Handle to global FS context.
41    */
42   struct GNUNET_FS_Handle *h;
43
44   /**
45    * Connection to the FS service.
46    */
47   struct GNUNET_CLIENT_Connection *client;
48
49   /**
50    * Function to call for each indexed file.
51    */
52   GNUNET_FS_IndexedFileProcessor iterator;
53
54   /**
55    * Closure for iterator.
56    */
57   void *iterator_cls;
58
59   /**
60    * Continuation to trigger at the end.
61    */
62   GNUNET_SCHEDULER_Task cont;
63
64   /**
65    * Closure for cont.
66    */
67   void *cont_cls;
68 };
69
70
71 /**
72  * Function called on each response from the FS
73  * service with information about indexed files.
74  *
75  * @param cls closure (of type "struct GetIndexedContext*")
76  * @param msg message with indexing information
77  */
78 static void
79 handle_index_info (void *cls,
80                    const struct GNUNET_MessageHeader *msg)
81 {
82   struct GetIndexedContext *gic = cls;
83   const struct IndexInfoMessage *iim;
84   uint16_t msize;
85   const char *filename;
86
87   if (NULL == msg)
88     {
89       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
90                   _("Failed to receive response for `%s' request from `%s' service.\n"),
91                   "GET_INDEXED",
92                   "fs");
93       GNUNET_SCHEDULER_add_continuation (gic->h->sched,
94                                          GNUNET_NO,
95                                          gic->cont,
96                                          gic->cont_cls,
97                                          GNUNET_SCHEDULER_REASON_TIMEOUT);
98       GNUNET_CLIENT_disconnect (gic->client);
99       GNUNET_free (gic);
100       return;
101     }
102   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END)
103     {
104       /* normal end-of-list */
105       GNUNET_SCHEDULER_add_continuation (gic->h->sched,
106                                          GNUNET_NO,
107                                          gic->cont,
108                                          gic->cont_cls,
109                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
110       GNUNET_CLIENT_disconnect (gic->client);
111       GNUNET_free (gic);
112       return;
113     }
114   msize = ntohs (msg->size);
115   iim = (const struct IndexInfoMessage*) msg;
116   filename = (const char*) &iim[1];
117   if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY) ||
118        (msize <= sizeof (struct IndexInfoMessage)) ||
119        (filename[msize-sizeof (struct IndexInfoMessage) -1] != '\0') )
120     {
121       /* bogus reply */
122       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
123                   _("Failed to receive valid response for `%s' request from `%s' service.\n"),
124                   "GET_INDEXED",
125                   "fs");
126       GNUNET_SCHEDULER_add_continuation (gic->h->sched,
127                                          GNUNET_NO,
128                                          gic->cont,
129                                          gic->cont_cls,
130                                          GNUNET_SCHEDULER_REASON_TIMEOUT);
131       GNUNET_CLIENT_disconnect (gic->client);
132       GNUNET_free (gic);
133       return;
134     }
135   if (GNUNET_OK !=
136       gic->iterator (gic->iterator_cls,
137                      filename,
138                      &iim->file_id))
139     {
140       GNUNET_SCHEDULER_add_continuation (gic->h->sched,
141                                          GNUNET_NO,
142                                          gic->cont,
143                                          gic->cont_cls,
144                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
145       GNUNET_CLIENT_disconnect (gic->client);
146       GNUNET_free (gic);
147       return;
148     }
149   /* get more */
150   GNUNET_CLIENT_receive (gic->client,
151                          &handle_index_info,
152                          gic,
153                          GNUNET_CONSTANTS_SERVICE_TIMEOUT);  
154 }
155
156
157 /**
158  * Transmit the request to get a list of all 
159  * indexed files to the "FS" service.
160  *
161  * @param cls closure (of type "struct GetIndexedContext*")
162  * @param size number of bytes availabe in buf
163  * @param buf where to write the message, NULL on error
164  * @return number of bytes written to buf
165  */
166 static size_t
167 transmit_get_indexed (void *cls,
168                       size_t size,
169                       void *buf)
170 {
171   struct GetIndexedContext *gic = cls;
172   struct GNUNET_MessageHeader *hdr;
173
174   if (NULL == buf)
175     {
176       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
177                   _("Failed to transmit `%s' request to `%s' service.\n"),
178                   "GET_INDEXED",
179                   "fs");
180       GNUNET_SCHEDULER_add_continuation (gic->h->sched,
181                                          GNUNET_NO,
182                                          gic->cont,
183                                          gic->cont_cls,
184                                          GNUNET_SCHEDULER_REASON_TIMEOUT);
185       GNUNET_CLIENT_disconnect (gic->client);
186       GNUNET_free (gic);
187       return 0;
188     }
189   GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
190   hdr = buf;
191   hdr->size = htons (sizeof (struct GNUNET_MessageHeader));
192   hdr->type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET);
193   GNUNET_CLIENT_receive (gic->client,
194                          &handle_index_info,
195                          gic,
196                          GNUNET_CONSTANTS_SERVICE_TIMEOUT);
197   return sizeof (struct GNUNET_MessageHeader);
198 }
199
200
201 /**
202  * Iterate over all indexed files.
203  *
204  * @param h handle to the file sharing subsystem
205  * @param iterator function to call on each indexed file
206  * @param iterator_cls closure for iterator
207  * @param cont continuation to call when done;
208  *             reason should be "TIMEOUT" (on
209  *             error) or  "PREREQ_DONE" (on success)
210  * @param cont_cls closure for cont
211  */
212 void 
213 GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
214                              GNUNET_FS_IndexedFileProcessor iterator,
215                              void *iterator_cls,
216                              GNUNET_SCHEDULER_Task cont,
217                              void *cont_cls)
218 {
219   struct GNUNET_CLIENT_Connection *client;
220   struct GetIndexedContext *gic;
221
222   client = GNUNET_CLIENT_connect (h->sched,
223                                   "fs",
224                                   h->cfg);
225   if (NULL == client)
226     {
227       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
228                   _("Failed to not connect to `%s' service.\n"),
229                   "fs");
230       GNUNET_SCHEDULER_add_continuation (h->sched,
231                                          GNUNET_NO,
232                                          cont,
233                                          cont_cls,
234                                          GNUNET_SCHEDULER_REASON_TIMEOUT);
235       return;
236     }
237
238   gic = GNUNET_malloc (sizeof (struct GetIndexedContext));
239   gic->h = h;
240   gic->client = client;
241   gic->iterator = iterator;
242   gic->iterator_cls = iterator_cls;
243   gic->cont = cont;
244   gic->cont_cls = cont_cls;
245   GNUNET_CLIENT_notify_transmit_ready (client,
246                                        sizeof (struct GNUNET_MessageHeader),
247                                        GNUNET_CONSTANTS_SERVICE_TIMEOUT,
248                                        &transmit_get_indexed,
249                                        gic);
250 }
251
252 /* end of fs_list_indexed.c */