730720d403b7cf80547396e70ab2f5f952bad76f
[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 at level %u off %llu)...\n",
100               (unsigned long long) event->value.publish.completed,
101               (unsigned long long) event->value.publish.size,
102               event->value.publish.specifics.progress.depth,
103               (unsigned long long) event->value.publish.specifics.progress.offset);
104 #endif
105       break;
106     case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
107 #if DEBUG_VERBOSE
108       printf ("Publish complete.\n");
109 #endif
110       GNUNET_SCHEDULER_add_continuation (sched,
111                                          GNUNET_NO,
112                                          &abort_publish_task,
113                                          NULL,
114                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
115       fn = GNUNET_DISK_mktemp ("gnunet-download-test-dstXXXXXX");
116       download = GNUNET_FS_download_start (fs,
117                                            event->value.publish.specifics.completed.chk_uri,
118                                            NULL,
119                                            fn,
120                                            0,
121                                            FILESIZE,
122                                            1,
123                                            GNUNET_FS_DOWNLOAD_OPTION_NONE,
124                                            NULL);
125       GNUNET_assert (download != NULL);
126       break;
127     case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
128 #if DEBUG_VERBOSE
129       printf ("Download complete.\n");
130 #endif
131       GNUNET_SCHEDULER_add_continuation (sched,
132                                          GNUNET_NO,
133                                          &abort_download_task,
134                                          NULL,
135                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
136       break;
137     case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
138 #if DEBUG_VERBOSE
139       printf ("Download is progressing (%llu/%llu at level %u off %llu)...\n",
140               (unsigned long long) event->value.download.completed,
141               (unsigned long long) event->value.download.size,
142               event->value.download.specifics.progress.depth,
143               (unsigned long long) event->value.download.specifics.progress.offset);
144 #endif
145       break;
146     case GNUNET_FS_STATUS_PUBLISH_ERROR:
147       fprintf (stderr,
148                "Error publishing file: %s\n",
149                event->value.publish.specifics.error.message);
150       GNUNET_break (0);
151       GNUNET_SCHEDULER_add_continuation (sched,
152                                          GNUNET_NO,
153                                          &abort_publish_task,
154                                          NULL,
155                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
156       break;
157     case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
158       fprintf (stderr,
159                "Error downloading file: %s\n",
160                event->value.download.specifics.error.message);
161       GNUNET_SCHEDULER_add_continuation (sched,
162                                          GNUNET_NO,
163                                          &abort_download_task,
164                                          NULL,
165                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
166       break;
167     case GNUNET_FS_STATUS_PUBLISH_START:
168       /* FIXME: add checks here... */
169       break;
170     case GNUNET_FS_STATUS_PUBLISH_STOPPED:
171       /* FIXME: add checks here... */
172       break;
173     case GNUNET_FS_STATUS_DOWNLOAD_START:
174       /* FIXME: add checks here... */
175       break;
176     case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
177       /* FIXME: add checks here... */
178       GNUNET_FS_stop (fs);
179       fs = NULL;
180       break;
181     default:
182       printf ("Unexpected event: %d\n", 
183               event->status);
184       break;
185     }
186   return NULL;
187 }
188
189
190 static void
191 setup_peer (struct PeerContext *p, const char *cfgname)
192 {
193   p->cfg = GNUNET_CONFIGURATION_create ();
194 #if START_ARM
195   p->arm_pid = GNUNET_OS_start_process ("gnunet-service-arm",
196                                         "gnunet-service-arm",
197 #if VERBOSE
198                                         "-L", "DEBUG",
199 #endif
200                                         "-c", cfgname, NULL);
201   sleep (1);                    /* allow ARM to start */
202 #endif
203   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
204   GNUNET_ARM_start_services (p->cfg, sched, "core", NULL);
205 }
206
207
208 static void
209 stop_arm (struct PeerContext *p)
210 {
211 #if START_ARM
212   if (0 != PLIBC_KILL (p->arm_pid, SIGTERM))
213     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
214   if (GNUNET_OS_process_wait(p->arm_pid) != GNUNET_OK)
215     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
216   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
217               "ARM process %u stopped\n", p->arm_pid);
218 #endif
219   GNUNET_CONFIGURATION_destroy (p->cfg);
220 }
221
222
223 static void
224 run (void *cls,
225      struct GNUNET_SCHEDULER_Handle *s,
226      char *const *args,
227      const char *cfgfile,
228      const struct GNUNET_CONFIGURATION_Handle *cfg)
229 {
230   const char *keywords[] = {
231     "down_foo",
232     "down_bar",
233   };
234   char *buf;
235   struct GNUNET_CONTAINER_MetaData *meta;
236   struct GNUNET_FS_Uri *kuri;
237   struct GNUNET_FS_FileInformation *fi;
238   size_t i;
239
240   sched = s;
241   setup_peer (&p1, "test_fs_download_data.conf");
242   fs = GNUNET_FS_start (sched,
243                         cfg,
244                         "test-fs-download",
245                         &progress_cb,
246                         NULL,
247                         GNUNET_FS_FLAGS_NONE,
248                         GNUNET_FS_OPTIONS_END);
249   GNUNET_assert (NULL != fs); 
250   buf = GNUNET_malloc (FILESIZE);
251   for (i = 0; i < FILESIZE; i++)
252     buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256);
253   meta = GNUNET_CONTAINER_meta_data_create ();
254   kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords);
255   fi = GNUNET_FS_file_information_create_from_data ("file-to-publish",
256                                                     FILESIZE,
257                                                     buf,
258                                                     kuri,
259                                                     meta,
260                                                     GNUNET_NO,
261                                                     1,
262                                                     42,
263                                                     GNUNET_TIME_relative_to_absolute (LIFETIME)); 
264   GNUNET_FS_uri_destroy (kuri);
265   GNUNET_CONTAINER_meta_data_destroy (meta);
266   GNUNET_assert (NULL != fi);
267   publish = GNUNET_FS_publish_start (fs,
268                                     "publish-context",
269                                     fi,
270                                     NULL, NULL, NULL,
271                                     GNUNET_FS_PUBLISH_OPTION_NONE);
272   GNUNET_assert (publish != NULL);
273 }
274
275
276 int
277 main (int argc, char *argv[])
278 {
279   char *const argvx[] = { 
280     "test-fs-download",
281     "-c",
282     "test_fs_download_data.conf",
283 #if VERBOSE
284     "-L", "DEBUG",
285 #endif
286     NULL
287   };
288   struct GNUNET_GETOPT_CommandLineOption options[] = {
289     GNUNET_GETOPT_OPTION_END
290   };
291
292   GNUNET_log_setup ("test_fs_download", 
293 #if VERBOSE
294                     "DEBUG",
295 #else
296                     "WARNING",
297 #endif
298                     NULL);
299   GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1,
300                       argvx, "test-fs-download",
301                       "nohelp", options, &run, NULL);
302   stop_arm (&p1);
303   return 0;
304 }
305
306 /* end of test_fs_download.c */