-document test
[oweals/gnunet.git] / src / conversation / test_conversation_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 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 conversation/test_conversation_api.c
22  * @brief testcase for conversation_api.c
23  *
24  * This test performs the operations of a call to a phone
25  * where the phone user picks up and then the call is
26  * terminated by the party that initiated the call.  The
27  * actual transmission of voice data is not tested.
28  */
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_testing_lib.h"
32 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_conversation_service.h"
34 #include "gnunet_identity_service.h"
35 #include "gnunet_namestore_service.h"
36
37 static int ok = 1;
38
39 static const struct GNUNET_CONFIGURATION_Handle *cfg;
40
41 static struct GNUNET_IDENTITY_Handle *id;
42
43 static struct GNUNET_IDENTITY_Operation *op;
44
45 static struct GNUNET_CONVERSATION_Phone *phone;
46
47 static struct GNUNET_NAMESTORE_Handle *ns;
48
49 static struct GNUNET_CONVERSATION_Call *call;
50
51 static struct GNUNET_NAMESTORE_QueueEntry *qe;
52
53 static struct GNUNET_CONVERSATION_Caller *active_caller;
54
55 static char *gns_name;
56
57 static char *gns_caller_id;
58
59
60 static int
61 enable_speaker (void *cls)
62 {
63   const char *origin = cls;
64
65   fprintf (stderr,
66            "Speaker %s enabled\n",
67            origin);
68   return GNUNET_OK;
69 }
70
71
72 static void
73 disable_speaker (void *cls)
74 {
75   const char *origin = cls;
76
77   fprintf (stderr,
78            "Speaker %s disabled\n",
79            origin);
80 }
81
82
83 static void
84 play (void *cls,
85       size_t data_size,
86       const void *data)
87 {
88   const char *origin = cls;
89
90   fprintf (stderr,
91            "Speaker %s plays %u bytes\n",
92            origin,
93            (unsigned int) data_size);
94 }
95
96
97 static void
98 destroy_speaker (void *cls)
99 {
100   const char *origin = cls;
101
102   fprintf (stderr, "Speaker %s destroyed\n", origin);
103 }
104
105
106 static struct GNUNET_SPEAKER_Handle caller_speaker = {
107   &enable_speaker,
108   &play,
109   &disable_speaker,
110   &destroy_speaker,
111   "caller"
112 };
113
114
115 static struct GNUNET_SPEAKER_Handle phone_speaker = {
116   &enable_speaker,
117   &play,
118   &disable_speaker,
119   &destroy_speaker,
120   "caller"
121 };
122
123
124 static int
125 enable_mic (void *cls,
126             GNUNET_MICROPHONE_RecordedDataCallback rdc,
127             void *rdc_cls)
128 {
129   const char *origin = cls;
130
131   fprintf (stderr,
132            "Mic %s enabled\n",
133            origin);
134   return GNUNET_OK;
135 }
136
137
138 static void
139 disable_mic (void *cls)
140 {
141   const char *origin = cls;
142
143   fprintf (stderr,
144            "Mic %s disabled\n",
145            origin);
146 }
147
148
149 static void
150 destroy_mic (void *cls)
151 {
152   const char *origin = cls;
153
154   fprintf (stderr,
155            "Mic %s destroyed\n",
156            origin);
157 }
158
159
160 static struct GNUNET_MICROPHONE_Handle caller_mic = {
161   &enable_mic,
162   &disable_mic,
163   &destroy_mic,
164   "caller"
165 };
166
167
168 static struct GNUNET_MICROPHONE_Handle phone_mic = {
169   &enable_mic,
170   &disable_mic,
171   &destroy_mic,
172   "caller"
173 };
174
175
176 /**
177  * Signature of the main function of a task.
178  *
179  * @param cls closure
180  * @param tc context information (why was this task triggered now)
181  */
182 static void
183 end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
184 {
185   GNUNET_SCHEDULER_shutdown ();
186   if (NULL != op)
187   {
188     GNUNET_IDENTITY_cancel (op);
189     op = NULL;
190   }
191   if (NULL != call)
192   {
193     GNUNET_CONVERSATION_call_stop (call);
194     call = NULL;
195   }
196   if (NULL != phone)
197   {
198     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n");
199     GNUNET_CONVERSATION_phone_destroy (phone);
200     phone = NULL;
201   }
202   if (NULL != id)
203   {
204     GNUNET_IDENTITY_disconnect (id);
205     id = NULL;
206   }
207   if (NULL != qe)
208   {
209     GNUNET_NAMESTORE_cancel (qe);
210     qe = NULL;
211   }
212   if (NULL != ns)
213   {
214     GNUNET_NAMESTORE_disconnect (ns);
215     ns = NULL;
216   }
217 }
218
219
220 static void
221 caller_event_handler (void *cls,
222                       enum GNUNET_CONVERSATION_CallerEventCode code)
223 {
224   switch (code)
225   {
226   case GNUNET_CONVERSATION_EC_CALLER_SUSPEND:
227   case GNUNET_CONVERSATION_EC_CALLER_RESUME:
228     fprintf (stderr, "Unexpected caller code: %d\n", code);
229     break;
230   }
231 }
232
233
234 static void
235 phone_event_handler (void *cls,
236                      enum GNUNET_CONVERSATION_PhoneEventCode code,
237                      struct GNUNET_CONVERSATION_Caller *caller,
238                      const char *caller_id)
239 {
240   static enum GNUNET_CONVERSATION_PhoneEventCode expect
241     = GNUNET_CONVERSATION_EC_PHONE_RING;
242
243   GNUNET_break (0 == strcmp (caller_id,
244                              gns_caller_id));
245   GNUNET_break (code == expect);
246   switch (code)
247   {
248   case GNUNET_CONVERSATION_EC_PHONE_RING:
249     active_caller = caller;
250     GNUNET_CONVERSATION_caller_pick_up (caller,
251                                         &caller_event_handler,
252                                         NULL,
253                                         &phone_speaker,
254                                         &phone_mic);
255     expect = GNUNET_CONVERSATION_EC_PHONE_HUNG_UP;
256     break;
257   case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP:
258     GNUNET_break (caller == active_caller);
259     active_caller = NULL;
260     ok = 0;
261     GNUNET_SCHEDULER_shutdown ();
262     break;
263   default:
264     fprintf (stderr, "Unexpected phone code: %d\n", code);
265     break;
266   }
267 }
268
269
270 static void
271 call_event_handler (void *cls,
272                     enum GNUNET_CONVERSATION_CallEventCode code)
273 {
274   static enum GNUNET_CONVERSATION_CallEventCode expect
275     = GNUNET_CONVERSATION_EC_CALL_RINGING;
276
277   GNUNET_break (code == expect);
278   switch (code)
279   {
280   case GNUNET_CONVERSATION_EC_CALL_RINGING:
281     expect = GNUNET_CONVERSATION_EC_CALL_PICKED_UP;
282     break;
283   case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
284     expect = -1;
285     GNUNET_CONVERSATION_call_stop (call);
286     call = NULL;
287     break;
288   case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
289   case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
290   case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
291   case GNUNET_CONVERSATION_EC_CALL_RESUMED:
292     fprintf (stderr, "Unexpected call code: %d\n", code);
293     break;
294   }
295 }
296
297
298 static void
299 caller_ego_create_cont (void *cls,
300                         const char *emsg)
301 {
302   op = NULL;
303   GNUNET_assert (NULL == emsg);
304 }
305
306
307 static void
308 namestore_put_cont (void *cls,
309                     int32_t success,
310                     const char *emsg)
311 {
312   qe = NULL;
313   GNUNET_assert (GNUNET_YES == success);
314   GNUNET_assert (NULL == emsg);
315   GNUNET_assert (NULL == op);
316   op = GNUNET_IDENTITY_create (id, "caller-ego", &caller_ego_create_cont, NULL);
317 }
318
319
320 static void
321 identity_cb (void *cls,
322              struct GNUNET_IDENTITY_Ego *ego,
323              void **ctx,
324              const char *name)
325 {
326   struct GNUNET_GNSRECORD_Data rd;
327   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
328
329   if (NULL == name)
330     return;
331   if (NULL == ego)
332     return;
333   if (0 == strcmp (name, "phone-ego"))
334   {
335     GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
336     GNUNET_asprintf (&gns_name,
337                      "phone.%s",
338                      GNUNET_GNSRECORD_pkey_to_zkey (&pub));
339     phone = GNUNET_CONVERSATION_phone_create (cfg,
340                                               ego,
341                                               &phone_event_handler,
342                                               NULL);
343     GNUNET_assert (NULL != phone);
344     memset (&rd, 0, sizeof (rd));
345     GNUNET_CONVERSATION_phone_get_record (phone,
346                                           &rd);
347     GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE);
348     rd.expiration_time = UINT64_MAX;
349     qe = GNUNET_NAMESTORE_records_store (ns,
350                                          GNUNET_IDENTITY_ego_get_private_key (ego),
351                                          "phone" /* GNS label */,
352                                          1,
353                                          &rd,
354                                          &namestore_put_cont,
355                                          NULL);
356     return;
357   }
358   if (0 == strcmp (name, "caller-ego"))
359   {
360     GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
361     GNUNET_asprintf (&gns_caller_id,
362                      "%s",
363                      GNUNET_GNSRECORD_pkey_to_zkey (&pub));
364     call = GNUNET_CONVERSATION_call_start (cfg,
365                                            ego,
366                                            gns_name,
367                                            &caller_speaker,
368                                            &caller_mic,
369                                            &call_event_handler,
370                                            NULL);
371     return;
372   }
373 }
374
375
376 static void
377 phone_ego_create_cont (void *cls,
378                        const char *emsg)
379 {
380   op = NULL;
381   GNUNET_assert (NULL == emsg);
382 }
383
384
385 static void
386 run (void *cls,
387      const struct GNUNET_CONFIGURATION_Handle *c,
388      struct GNUNET_TESTING_Peer *peer)
389 {
390   cfg = c;
391   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
392                                 (GNUNET_TIME_UNIT_MINUTES, 1), &end_test,
393                                 NULL);
394   id = GNUNET_IDENTITY_connect (cfg,
395                                 &identity_cb,
396                                 NULL);
397   op = GNUNET_IDENTITY_create (id, "phone-ego", &phone_ego_create_cont, NULL);
398   ns = GNUNET_NAMESTORE_connect (cfg);
399 }
400
401
402 int
403 main (int argc, char *argv[])
404 {
405   if (0 != GNUNET_TESTING_peer_run ("test_conversation_api",
406                                     "test_conversation.conf",
407                                     &run, NULL))
408     return 1;
409   return ok;
410 }
411
412 /* end of test_conversation_api.c */