ffb90d678c5ce659a43806d85833191e8d9a9f72
[oweals/gnunet.git] / src / fs / test_fs_download.c
1 /*
2      This file is part of GNUnet.
3      (C) 2004, 2005, 2006, 2008, 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/test_fs_download.c
23  * @brief simple testcase for download
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_arm_service.h"
30 #include "gnunet_fs_service.h"
31
32 #define DEBUG_VERBOSE 42 
33 //GNUNET_NO
34
35 #define START_ARM GNUNET_YES
36
37 #define FILESIZE (1024 * 1024 * 2)
38
39 /**
40  * How long until we give up on transmitting the message?
41  */
42 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
43
44 /**
45  * How long should our test-content live?
46  */ 
47 #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
48
49 struct PeerContext
50 {
51   struct GNUNET_CONFIGURATION_Handle *cfg;
52   struct GNUNET_PeerIdentity id;   
53 #if START_ARM
54   pid_t arm_pid;
55 #endif
56 };
57
58 static struct PeerContext p1;
59
60
61 static struct GNUNET_SCHEDULER_Handle *sched;
62
63 static struct GNUNET_FS_Handle *fs;
64
65 static struct GNUNET_FS_DownloadContext *download;
66
67 static struct GNUNET_FS_PublishContext *publish;
68
69 static char *fn;
70
71
72 static void
73 abort_download_task (void *cls,
74                      const struct GNUNET_SCHEDULER_TaskContext *tc)
75 {
76   GNUNET_FS_download_stop (download, GNUNET_YES);
77   download = NULL;
78 }
79
80
81 static void
82 abort_publish_task (void *cls,
83                      const struct GNUNET_SCHEDULER_TaskContext *tc)
84 {
85   GNUNET_FS_publish_stop (publish);
86   publish = NULL;
87 }
88
89
90 static void *
91 progress_cb (void *cls, 
92              const struct GNUNET_FS_ProgressInfo *event)
93 {
94
95   switch (event->status)
96     {
97     case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
98 #if DEBUG_VERBOSE
99       printf ("Publish is progressing (%llu/%llu)...\n",
100               (unsigned long long) event->value.publish.completed,
101               (unsigned long long) event->value.publish.size);
102 #endif
103       break;
104     case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
105 #if DEBUG_VERBOSE
106       printf ("Publish complete.\n");
107 #endif
108       GNUNET_FS_publish_stop (publish);
109       publish = NULL;
110       fn = GNUNET_DISK_mktemp ("gnunet-download-test-dstXXXXXX");
111       download = GNUNET_FS_download_start (fs,
112                                            event->value.publish.specifics.completed.chk_uri,
113                                            NULL,
114                                            fn,
115                                            0,
116                                            FILESIZE,
117                                            1,
118                                            GNUNET_FS_DOWNLOAD_OPTION_NONE,
119                                            NULL);
120       GNUNET_assert (download != NULL);
121       break;
122     case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
123 #if DEBUG_VERBOSE
124       printf ("Download complete.\n");
125 #endif
126       GNUNET_FS_download_stop (download, GNUNET_YES);
127       download = NULL;
128       break;
129     case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
130 #if DEBUG_VERBOSE
131       printf ("Download is progressing (%llu/%llu)...\n",
132               (unsigned long long) event->value.download.completed,
133               (unsigned long long) event->value.download.size);
134 #endif
135       break;
136     case GNUNET_FS_STATUS_PUBLISH_ERROR:
137       fprintf (stderr,
138                "Error publishing file: %s\n",
139                event->value.publish.specifics.error.message);
140       GNUNET_break (0);
141       GNUNET_SCHEDULER_add_continuation (sched,
142                                          GNUNET_NO,
143                                          &abort_publish_task,
144                                          NULL,
145                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
146       break;
147     case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
148       fprintf (stderr,
149                "Error downloading file: %s\n",
150                event->value.download.specifics.error.message);
151       GNUNET_SCHEDULER_add_continuation (sched,
152                                          GNUNET_NO,
153                                          &abort_download_task,
154                                          NULL,
155                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
156       break;
157     case GNUNET_FS_STATUS_PUBLISH_START:
158       /* FIXME: add checks here... */
159       break;
160     case GNUNET_FS_STATUS_PUBLISH_STOPPED:
161       /* FIXME: add checks here... */
162       break;
163     case GNUNET_FS_STATUS_DOWNLOAD_START:
164       /* FIXME: add checks here... */
165       break;
166     case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
167       /* FIXME: add checks here... */
168       GNUNET_FS_stop (fs);
169       fs = NULL;
170       break;
171     default:
172       printf ("Unexpected event: %d\n", 
173               event->status);
174       break;
175     }
176   return NULL;
177 }
178
179
180 static void
181 setup_peer (struct PeerContext *p, const char *cfgname)
182 {
183   p->cfg = GNUNET_CONFIGURATION_create ();
184 #if START_ARM
185   p->arm_pid = GNUNET_OS_start_process ("gnunet-service-arm",
186                                         "gnunet-service-arm",
187 #if VERBOSE
188                                         "-L", "DEBUG",
189 #endif
190                                         "-c", cfgname, NULL);
191   sleep (1);                    /* allow ARM to start */
192 #endif
193   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
194   GNUNET_ARM_start_services (p->cfg, sched, "core", NULL);
195 }
196
197
198 static void
199 stop_arm (struct PeerContext *p)
200 {
201 #if START_ARM
202   if (0 != PLIBC_KILL (p->arm_pid, SIGTERM))
203     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
204   if (GNUNET_OS_process_wait(p->arm_pid) != GNUNET_OK)
205     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
206   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
207               "ARM process %u stopped\n", p->arm_pid);
208 #endif
209   GNUNET_CONFIGURATION_destroy (p->cfg);
210 }
211
212
213 static void
214 run (void *cls,
215      struct GNUNET_SCHEDULER_Handle *s,
216      char *const *args,
217      const char *cfgfile,
218      const struct GNUNET_CONFIGURATION_Handle *cfg)
219 {
220   const char *keywords[] = {
221     "down_foo",
222     "down_bar",
223   };
224   char *buf;
225   struct GNUNET_CONTAINER_MetaData *meta;
226   struct GNUNET_FS_Uri *kuri;
227   struct GNUNET_FS_FileInformation *fi;
228   size_t i;
229
230   sched = s;
231   setup_peer (&p1, "test_fs_download_data.conf");
232   fs = GNUNET_FS_start (sched,
233                         cfg,
234                         "test-fs-download",
235                         &progress_cb,
236                         NULL,
237                         GNUNET_FS_FLAGS_NONE,
238                         GNUNET_FS_OPTIONS_END);
239   GNUNET_assert (NULL != fs); 
240   buf = GNUNET_malloc (FILESIZE);
241   for (i = 0; i < FILESIZE; i++)
242     buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256);
243   meta = GNUNET_CONTAINER_meta_data_create ();
244   kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords);
245   fi = GNUNET_FS_file_information_create_from_data ("file-to-publish",
246                                                     FILESIZE,
247                                                     buf,
248                                                     kuri,
249                                                     meta,
250                                                     GNUNET_NO,
251                                                     1,
252                                                     42,
253                                                     GNUNET_TIME_relative_to_absolute (LIFETIME)); 
254   GNUNET_FS_uri_destroy (kuri);
255   GNUNET_CONTAINER_meta_data_destroy (meta);
256   GNUNET_assert (NULL != fi);
257   publish = GNUNET_FS_publish_start (fs,
258                                     "publish-context",
259                                     fi,
260                                     NULL, NULL, NULL,
261                                     GNUNET_FS_PUBLISH_OPTION_NONE);
262   GNUNET_assert (publish != NULL);
263 }
264
265
266 int
267 main (int argc, char *argv[])
268 {
269   char *const argvx[] = { 
270     "test-fs-download",
271     "-c",
272     "test_fs_download_data.conf",
273 #if VERBOSE
274     "-L", "DEBUG",
275 #endif
276     NULL
277   };
278   struct GNUNET_GETOPT_CommandLineOption options[] = {
279     GNUNET_GETOPT_OPTION_END
280   };
281
282   GNUNET_log_setup ("test_fs_download", 
283 #if VERBOSE
284                     "DEBUG",
285 #else
286                     "WARNING",
287 #endif
288                     NULL);
289   GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1,
290                       argvx, "test-fs-download",
291                       "nohelp", options, &run, NULL);
292   stop_arm (&p1);
293   return 0;
294 }
295
296 /* end of test_fs_download.c */