-fix
[oweals/gnunet.git] / src / mesh / test_mesh_local_1.c
1 /*
2      This file is part of GNUnet.
3      (C) 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 /**
22  * @file mesh/test_mesh_local_1.c
23  * @brief test mesh local: test of tunnels with just one peer
24  * @author Bartlomiej Polot
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dht_service.h"
30 #include "gnunet_testing_lib-new.h"
31 #include "gnunet_mesh_service.h"
32
33
34 static struct GNUNET_MESH_Handle *mesh_peer_1;
35
36 static struct GNUNET_MESH_Handle *mesh_peer_2;
37
38 static struct GNUNET_MESH_Tunnel *t;
39
40 static unsigned int one = 1;
41
42 static unsigned int two = 2;
43
44 static int result = GNUNET_OK;
45
46 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
47
48 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
49
50
51 /**
52  * Shutdown nicely
53  */
54 static void
55 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
56 {
57   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n");
58   if (0 != abort_task)
59   {
60     GNUNET_SCHEDULER_cancel (abort_task);
61   }
62   if (NULL != t)
63   {
64     GNUNET_MESH_tunnel_destroy(t);
65   }
66   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n");
67   if (NULL != mesh_peer_1)
68   {
69     GNUNET_MESH_disconnect (mesh_peer_1);
70   }
71   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n");
72   if (NULL != mesh_peer_2)
73   {
74     GNUNET_MESH_disconnect (mesh_peer_2);
75   }
76 }
77
78
79 /**
80  * Something went wrong and timed out. Kill everything and set error flag
81  */
82 static void
83 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
84 {
85   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
86   result = GNUNET_SYSERR;
87   abort_task = 0;
88   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
89   {
90     GNUNET_SCHEDULER_cancel (shutdown_task);
91     shutdown_task = GNUNET_SCHEDULER_NO_TASK;
92   }
93   do_shutdown (cls, tc);
94 }
95
96
97 /**
98  * Function is called whenever a message is received.
99  *
100  * @param cls closure (set from GNUNET_MESH_connect)
101  * @param tunnel connection to the other end
102  * @param tunnel_ctx place to store local state associated with the tunnel
103  * @param sender who sent the message
104  * @param message the actual message
105  * @param atsi performance data for the connection
106  * @return GNUNET_OK to keep the connection open,
107  *         GNUNET_SYSERR to close it (signal serious error)
108  */
109 static int
110 data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
111                const struct GNUNET_PeerIdentity *sender,
112                const struct GNUNET_MessageHeader *message,
113                const struct GNUNET_ATS_Information *atsi)
114 {
115   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n");
116   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
117     GNUNET_SCHEDULER_cancel (shutdown_task);
118   shutdown_task =
119     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
120                                   (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown,
121                                   NULL);
122   return GNUNET_OK;
123 }
124
125
126 /**
127  * Method called whenever another peer has added us to a tunnel
128  * the other peer initiated.
129  *
130  * @param cls closure
131  * @param tunnel new handle to the tunnel
132  * @param initiator peer that started the tunnel
133  * @param atsi performance information for the tunnel
134  * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
135  */
136 static void *
137 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
138                 const struct GNUNET_PeerIdentity *initiator,
139                 const struct GNUNET_ATS_Information *atsi)
140 {
141   unsigned int id = *(unsigned int *) cls;
142
143   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n");
144   if (id != 1)
145   {
146     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
147                 "test: received incoming tunnel on peer 2\n");
148     result = GNUNET_SYSERR;
149   }
150   return NULL;
151 }
152
153
154 /**
155  * Function called whenever an inbound tunnel is destroyed.  Should clean up
156  * any associated state.
157  *
158  * @param cls closure (set from GNUNET_MESH_connect)
159  * @param tunnel connection to the other end (henceforth invalid)
160  * @param tunnel_ctx place where local state associated
161  *                   with the tunnel is stored
162  */
163 static void
164 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
165              void *tunnel_ctx)
166 {
167   unsigned int id = *(unsigned int *) cls;
168
169   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n");
170   if (id != 1)
171   {
172     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
173                 "test: received closing tunnel on peer 2\n");
174     result = GNUNET_SYSERR;
175   }
176 }
177
178
179 /**
180  * Method called whenever a peer has connected to the tunnel.
181  *
182  * @param cls closure
183  * @param peer peer identity the tunnel stopped working with
184  */
185 static void
186 peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer,
187                const struct GNUNET_ATS_Information *atsi)
188 {
189   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n");
190   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
191     GNUNET_SCHEDULER_cancel(shutdown_task);
192   shutdown_task =  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
193                                                  &do_shutdown, NULL);
194 }
195
196
197 /**
198  * Method called whenever a peer has connected to the tunnel.
199  *
200  * @param cls closure
201  * @param peer peer identity the tunnel was created to, NULL on timeout
202  * @param atsi performance data for the connection
203  */
204 static void
205 peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
206 {
207   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n");
208 }
209
210
211 /**
212  * Handler array for traffic received on peer1
213  */
214 static struct GNUNET_MESH_MessageHandler handlers1[] = {
215   {&data_callback, 1, 0},
216   {NULL, 0, 0}
217 };
218
219
220 /**
221  * Handler array for traffic received on peer2 (none expected)
222  */
223 static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} };
224
225
226 /**
227  * Start looking for a peer by type
228  */
229 static void
230 do_find (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
231 {
232   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CONNECT BY TYPE\n");
233   GNUNET_MESH_peer_request_connect_by_type (t, 1);
234 }
235
236
237 /**
238  * Initialize framework and start test
239  */
240 static void
241 run (void *cls, 
242      const struct GNUNET_CONFIGURATION_Handle *cfg,
243      struct GNUNET_TESTING_Peer *peer)
244 {
245   static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 };
246   static const GNUNET_MESH_ApplicationType app2[] = { 0 };
247
248   abort_task =
249       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
250                                     (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
251                                     NULL);
252   mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
253                                      (void *) &one,     /* cls */
254                                      &inbound_tunnel,   /* inbound new hndlr */
255                                      &inbound_end,      /* inbound end hndlr */
256                                      handlers1, /* traffic handlers */
257                                      app1);     /* apps offered */
258
259   mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
260                                      (void *) &two,     /* cls */
261                                      &inbound_tunnel,   /* inbound new hndlr */
262                                      &inbound_end,      /* inbound end hndlr */
263                                      handlers2, /* traffic handlers */
264                                      app2);     /* apps offered */
265   if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
266   {
267     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n");
268     result = GNUNET_SYSERR;
269     return;
270   }
271   else
272   {
273     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
274   }
275   t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected,
276                                  &peer_disconnected, (void *) &two);
277   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_find, NULL);
278 }
279
280
281 /**
282  * Main
283  */
284 int
285 main (int argc, char *argv[])
286 {
287   if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-1",
288                                     "test_mesh.conf",
289                                     &run, NULL))
290     return 1;
291   return (result == GNUNET_OK) ? 0 : 1;
292 }
293
294 /* end of test_mesh_local_1.c */