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