- adding GNUNET_ATS_address_add functionality .. no changes to scheduling API yet
[oweals/gnunet.git] / src / ats / test_ats_api_reset_backoff.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010,2011 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file ats/test_ats_api_reset_backoff.c
22  * @brief test case for block reset api
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_ats_service.h"
28 #include "ats.h"
29
30 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
31 #define ATS_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 90)
32
33 static GNUNET_SCHEDULER_TaskIdentifier die_task;
34
35 static GNUNET_SCHEDULER_TaskIdentifier suggest_timeout_task;
36
37 static struct GNUNET_ATS_SchedulingHandle *ats;
38
39 struct GNUNET_OS_Process *arm_proc;
40
41 static int ret;
42
43 struct Address
44 {
45   char *plugin;
46   size_t plugin_len;
47
48   void *addr;
49   size_t addr_len;
50
51   struct GNUNET_ATS_Information *ats;
52   int ats_count;
53
54   void *session;
55 };
56
57 struct PeerContext
58 {
59   struct GNUNET_PeerIdentity id;
60
61   struct Address *addr;
62 };
63
64 struct GNUNET_HELLO_Address hello_addr;
65 struct Address address;
66 struct PeerContext peer;
67 struct GNUNET_ATS_Information atsi[2];
68
69 static void
70 stop_arm ()
71 {
72   if (0 != GNUNET_OS_process_kill (arm_proc, SIGTERM))
73     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
74   GNUNET_OS_process_wait (arm_proc);
75   GNUNET_OS_process_destroy (arm_proc);
76   arm_proc = NULL;
77 }
78
79
80 static void
81 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
82 {
83   die_task = GNUNET_SCHEDULER_NO_TASK;
84
85   if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK)
86   {
87     GNUNET_SCHEDULER_cancel (suggest_timeout_task);
88     suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
89   }
90
91   if (ats != NULL)
92   {
93     GNUNET_ATS_scheduling_done (ats);
94     ats = NULL;
95   }
96
97   ret = GNUNET_SYSERR;
98
99   stop_arm ();
100 }
101
102
103 static void
104 end ()
105 {
106   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n");
107   if (die_task != GNUNET_SCHEDULER_NO_TASK)
108   {
109     GNUNET_SCHEDULER_cancel (die_task);
110     die_task = GNUNET_SCHEDULER_NO_TASK;
111   }
112
113   if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK)
114   {
115     GNUNET_SCHEDULER_cancel (suggest_timeout_task);
116     suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
117   }
118
119   GNUNET_ATS_scheduling_done (ats);
120
121   ret = 0;
122
123   stop_arm ();
124 }
125
126
127 static void
128 suggest_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
129 {
130   suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
131
132   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting address for peer timed out\n");
133
134   if (die_task != GNUNET_SCHEDULER_NO_TASK)
135   {
136     GNUNET_SCHEDULER_cancel (die_task);
137     die_task = GNUNET_SCHEDULER_NO_TASK;
138   }
139
140   die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
141 }
142
143 static void
144 address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *a,
145                     struct Session *session,
146                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
147                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
148                     const struct GNUNET_ATS_Information *atsi,
149                     uint32_t ats_count)
150 {
151   static int suggestions;
152   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS suggests address `%s'\n",
153               GNUNET_i2s (&a->peer));
154
155   if (0 != memcmp (&a->peer, &peer.id,
156                          sizeof (struct GNUNET_PeerIdentity)))
157   {
158    GNUNET_break (0);
159    if (die_task != GNUNET_SCHEDULER_NO_TASK)
160    {
161      GNUNET_SCHEDULER_cancel (die_task);
162      die_task = GNUNET_SCHEDULER_NO_TASK;
163    }
164    GNUNET_SCHEDULER_add_now (&end_badly, NULL);
165    return;
166   }
167
168   if (0 != strcmp (a->transport_name, address.plugin))
169   {
170    GNUNET_break (0);
171    if (die_task != GNUNET_SCHEDULER_NO_TASK)
172    {
173      GNUNET_SCHEDULER_cancel (die_task);
174      die_task = GNUNET_SCHEDULER_NO_TASK;
175    }
176    GNUNET_SCHEDULER_add_now (&end_badly, NULL);
177    return;
178   }
179
180   if (a->address_length != address.addr_len)
181   {
182    GNUNET_break (0);
183    if (die_task != GNUNET_SCHEDULER_NO_TASK)
184    {
185      GNUNET_SCHEDULER_cancel (die_task);
186      die_task = GNUNET_SCHEDULER_NO_TASK;
187    }
188    GNUNET_SCHEDULER_add_now (&end_badly, NULL);
189    return;
190   }
191
192   if (0 != memcmp (a->address, address.addr,
193       a->address_length))
194   {
195    GNUNET_break (0);
196    if (die_task != GNUNET_SCHEDULER_NO_TASK)
197    {
198      GNUNET_SCHEDULER_cancel (die_task);
199      die_task = GNUNET_SCHEDULER_NO_TASK;
200    }
201    GNUNET_SCHEDULER_add_now (&end_badly, NULL);
202    return;
203   }
204
205   if (session != address.session)
206   {
207    GNUNET_break (0);
208    if (die_task != GNUNET_SCHEDULER_NO_TASK)
209    {
210      GNUNET_SCHEDULER_cancel (die_task);
211      die_task = GNUNET_SCHEDULER_NO_TASK;
212    }
213    GNUNET_SCHEDULER_add_now (&end_badly, NULL);
214    return;
215   }
216
217   suggestions ++;
218
219   if (2 == suggestions)
220   {
221     GNUNET_SCHEDULER_add_now(&end, NULL);
222     return;
223   }
224
225   if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK)
226   {
227     GNUNET_SCHEDULER_cancel (suggest_timeout_task);
228     suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
229   }
230   suggest_timeout_task = GNUNET_SCHEDULER_add_delayed(ATS_TIMEOUT, &suggest_timeout, NULL);
231 }
232
233 void
234 start_arm (const char *cfgname)
235 {
236   arm_proc =
237     GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm",
238                                "gnunet-service-arm",
239                                "-c", cfgname, NULL);
240 }
241
242 static void
243 check (void *cls, char *const *args, const char *cfgfile,
244        const struct GNUNET_CONFIGURATION_Handle *cfg)
245 {
246   ret = GNUNET_SYSERR;
247
248   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
249   start_arm (cfgfile);
250
251   ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
252
253   if (ats == NULL)
254   {
255     ret = GNUNET_SYSERR;
256     end ();
257     return;
258   }
259
260   /* set up peer */
261   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
262                                     &peer.id.hashPubKey);
263   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s (&peer.id));
264
265   address.plugin = "test";
266   address.session = NULL;
267   address.addr = GNUNET_strdup ("test");
268   address.addr_len = 4;
269
270   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding address\n");
271
272   hello_addr.peer = peer.id;
273   hello_addr.transport_name = address.plugin;
274   hello_addr.address = address.addr;
275   hello_addr.address_length = address.addr_len;
276   GNUNET_ATS_address_update (ats, &hello_addr, address.session, NULL, 0);
277
278   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting address for peer `%s'\n",
279               GNUNET_i2s (&peer.id));
280   /* Increase block timout far beyond ATS_TIMEOUT */
281   GNUNET_ATS_suggest_address (ats, &peer.id);
282
283   GNUNET_ATS_reset_backoff(ats, &peer.id);
284   GNUNET_ATS_suggest_address (ats, &peer.id);
285 }
286
287 int
288 main (int argc, char *argv[])
289 {
290   static char *const argv2[] = { "test_ats_api_scheduling",
291     "-c",
292     "test_ats_api.conf",
293     "-L", "WARNING",
294     NULL
295   };
296
297   static struct GNUNET_GETOPT_CommandLineOption options[] = {
298     GNUNET_GETOPT_OPTION_END
299   };
300
301   GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
302                       "test_ats_api_scheduling", "nohelp", options, &check,
303                       NULL);
304
305
306   return ret;
307 }
308 /* end of file test_ats_api_reset_backoff.c */