aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/test_conversation_api_twocalls.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-12-07 21:02:15 +0000
committerChristian Grothoff <christian@grothoff.org>2013-12-07 21:02:15 +0000
commitd66ade0522e3a00c9f8e2b84632f80e93d49e753 (patch)
treee189bc2f78f0061e81e1d9a84ac303a16050af72 /src/conversation/test_conversation_api_twocalls.c
parent4d14f67cd579bf4831293b75b4f24a135cff05b3 (diff)
downloadgnunet-d66ade0522e3a00c9f8e2b84632f80e93d49e753.tar.gz
gnunet-d66ade0522e3a00c9f8e2b84632f80e93d49e753.zip
-test two incoming calls at the same time, plus suspend/resume
Diffstat (limited to 'src/conversation/test_conversation_api_twocalls.c')
-rw-r--r--src/conversation/test_conversation_api_twocalls.c548
1 files changed, 548 insertions, 0 deletions
diff --git a/src/conversation/test_conversation_api_twocalls.c b/src/conversation/test_conversation_api_twocalls.c
new file mode 100644
index 000000000..71b8f758c
--- /dev/null
+++ b/src/conversation/test_conversation_api_twocalls.c
@@ -0,0 +1,548 @@
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_twocalls.c
22 * @brief testcase for conversation_api.c
23 *
24 * This test performs the operations of TWO calls made to a phone
25 * where the phone user picks up one, suspends it, picks up the
26 * second one; eventually, the initiator hangs up, the callee
27 * resumes the first call, and then the initiator hangs up the
28 * second call.
29 */
30#include "platform.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_testing_lib.h"
33#include "gnunet_gnsrecord_lib.h"
34#include "gnunet_conversation_service.h"
35#include "gnunet_identity_service.h"
36#include "gnunet_namestore_service.h"
37
38#define FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
39
40#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 25)
41
42static int ok = 1;
43
44static const struct GNUNET_CONFIGURATION_Handle *cfg;
45
46static struct GNUNET_IDENTITY_Handle *id;
47
48static struct GNUNET_IDENTITY_Operation *op;
49
50static struct GNUNET_CONVERSATION_Phone *phone;
51
52static struct GNUNET_NAMESTORE_Handle *ns;
53
54static struct GNUNET_CONVERSATION_Call *call1;
55
56static struct GNUNET_CONVERSATION_Call *call2;
57
58static struct GNUNET_NAMESTORE_QueueEntry *qe;
59
60static struct GNUNET_CONVERSATION_Caller *active_caller1;
61
62static struct GNUNET_CONVERSATION_Caller *active_caller2;
63
64static char *gns_name;
65
66static char *gns_caller_id;
67
68static GNUNET_MICROPHONE_RecordedDataCallback phone_rdc;
69
70static void *phone_rdc_cls;
71
72static GNUNET_MICROPHONE_RecordedDataCallback call_rdc;
73
74static void *call_rdc_cls;
75
76static GNUNET_SCHEDULER_TaskIdentifier phone_task;
77
78static GNUNET_SCHEDULER_TaskIdentifier call_task;
79
80
81static void
82phone_send (void *cls,
83 const struct GNUNET_SCHEDULER_TaskContext *tc)
84{
85 char buf[32];
86
87 GNUNET_assert (NULL != phone_rdc);
88 GNUNET_snprintf (buf, sizeof (buf), "phone");
89 phone_rdc (phone_rdc_cls, strlen (buf) + 1, buf);
90 phone_task = GNUNET_SCHEDULER_add_delayed (FREQ,
91 &phone_send, NULL);
92}
93
94
95static void
96call_send (void *cls,
97 const struct GNUNET_SCHEDULER_TaskContext *tc)
98{
99 char buf[32];
100
101 GNUNET_assert (NULL != call_rdc);
102 GNUNET_snprintf (buf, sizeof (buf), "call");
103 call_rdc (call_rdc_cls, strlen (buf) + 1, buf);
104 call_task = GNUNET_SCHEDULER_add_delayed (FREQ,
105 &call_send, NULL);
106}
107
108
109static int
110enable_speaker (void *cls)
111{
112 const char *origin = cls;
113
114 fprintf (stderr,
115 "Speaker %s enabled\n",
116 origin);
117 return GNUNET_OK;
118}
119
120
121static void
122disable_speaker (void *cls)
123{
124 const char *origin = cls;
125
126 fprintf (stderr,
127 "Speaker %s disabled\n",
128 origin);
129}
130
131
132static void
133play (void *cls,
134 size_t data_size,
135 const void *data)
136{
137 static unsigned int phone_i;
138 static unsigned int call_i;
139
140 if (0 == strncmp ("call", data, data_size))
141 call_i++;
142 else if (0 == strncmp ("phone", data, data_size))
143 phone_i++;
144 else
145 {
146 fprintf (stderr,
147 "Received unexpected data %.*s\n",
148 (int) data_size,
149 (const char *) data);
150 }
151
152 if ( (20 < call_i) &&
153 (20 < phone_i) &&
154 (NULL != call2) )
155 {
156 /* time to hang up ... */
157 GNUNET_CONVERSATION_call_stop (call2);
158 call2 = NULL;
159 /* reset counters */
160 call_i = 0;
161 phone_i = 0;
162 }
163 if ( (20 < call_i) &&
164 (20 < phone_i) &&
165 (NULL != call1) )
166 {
167 /* time to hang up ... */
168 GNUNET_CONVERSATION_call_stop (call1);
169 call1 = NULL;
170 }
171}
172
173
174static void
175destroy_speaker (void *cls)
176{
177 const char *origin = cls;
178
179 fprintf (stderr, "Speaker %s destroyed\n", origin);
180}
181
182
183static struct GNUNET_SPEAKER_Handle call_speaker = {
184 &enable_speaker,
185 &play,
186 &disable_speaker,
187 &destroy_speaker,
188 "caller"
189};
190
191
192static struct GNUNET_SPEAKER_Handle phone_speaker = {
193 &enable_speaker,
194 &play,
195 &disable_speaker,
196 &destroy_speaker,
197 "phone"
198};
199
200
201static int
202enable_mic (void *cls,
203 GNUNET_MICROPHONE_RecordedDataCallback rdc,
204 void *rdc_cls)
205{
206 const char *origin = cls;
207
208 fprintf (stderr,
209 "Mic %s enabled\n",
210 origin);
211 if (0 == strcmp (origin, "phone"))
212 {
213 phone_rdc = rdc;
214 phone_rdc_cls = rdc_cls;
215 GNUNET_break (GNUNET_SCHEDULER_NO_TASK == phone_task);
216 phone_task = GNUNET_SCHEDULER_add_now (&phone_send, NULL);
217 }
218 else
219 {
220 call_rdc = rdc;
221 call_rdc_cls = rdc_cls;
222 GNUNET_break (GNUNET_SCHEDULER_NO_TASK == call_task);
223 call_task = GNUNET_SCHEDULER_add_now (&call_send, NULL);
224 }
225 return GNUNET_OK;
226}
227
228
229static void
230disable_mic (void *cls)
231{
232 const char *origin = cls;
233
234 fprintf (stderr,
235 "Mic %s disabled\n",
236 origin);
237 if (0 == strcmp (origin, "phone"))
238 {
239 phone_rdc = NULL;
240 phone_rdc_cls = NULL;
241 GNUNET_SCHEDULER_cancel (phone_task);
242 phone_task = GNUNET_SCHEDULER_NO_TASK;
243 }
244 else
245 {
246 call_rdc = NULL;
247 call_rdc_cls = NULL;
248 GNUNET_SCHEDULER_cancel (call_task);
249 call_task = GNUNET_SCHEDULER_NO_TASK;
250 }
251}
252
253
254static void
255destroy_mic (void *cls)
256{
257 const char *origin = cls;
258
259 fprintf (stderr,
260 "Mic %s destroyed\n",
261 origin);
262}
263
264
265static struct GNUNET_MICROPHONE_Handle call_mic = {
266 &enable_mic,
267 &disable_mic,
268 &destroy_mic,
269 "caller"
270};
271
272
273static struct GNUNET_MICROPHONE_Handle phone_mic = {
274 &enable_mic,
275 &disable_mic,
276 &destroy_mic,
277 "phone"
278};
279
280
281/**
282 * Signature of the main function of a task.
283 *
284 * @param cls closure
285 * @param tc context information (why was this task triggered now)
286 */
287static void
288end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
289{
290 GNUNET_SCHEDULER_shutdown ();
291 if (NULL != op)
292 {
293 GNUNET_IDENTITY_cancel (op);
294 op = NULL;
295 }
296 if (NULL != call1)
297 {
298 GNUNET_CONVERSATION_call_stop (call1);
299 call1 = NULL;
300 }
301 if (NULL != call2)
302 {
303 GNUNET_CONVERSATION_call_stop (call2);
304 call2 = NULL;
305 }
306 if (NULL != phone)
307 {
308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n");
309 GNUNET_CONVERSATION_phone_destroy (phone);
310 phone = NULL;
311 }
312 if (NULL != id)
313 {
314 GNUNET_IDENTITY_disconnect (id);
315 id = NULL;
316 }
317 if (NULL != qe)
318 {
319 GNUNET_NAMESTORE_cancel (qe);
320 qe = NULL;
321 }
322 if (NULL != ns)
323 {
324 GNUNET_NAMESTORE_disconnect (ns);
325 ns = NULL;
326 }
327}
328
329
330static void
331caller_event_handler (void *cls,
332 enum GNUNET_CONVERSATION_CallerEventCode code)
333{
334 switch (code)
335 {
336 case GNUNET_CONVERSATION_EC_CALLER_SUSPEND:
337 case GNUNET_CONVERSATION_EC_CALLER_RESUME:
338 fprintf (stderr, "Unexpected caller code: %d\n", code);
339 break;
340 }
341}
342
343
344static void
345phone_event_handler (void *cls,
346 enum GNUNET_CONVERSATION_PhoneEventCode code,
347 struct GNUNET_CONVERSATION_Caller *caller,
348 const char *caller_id)
349{
350 const char *cid;
351
352 GNUNET_break (0 == strcmp (caller_id,
353 gns_caller_id));
354 switch (code)
355 {
356 case GNUNET_CONVERSATION_EC_PHONE_RING:
357 if (NULL == active_caller1)
358 {
359 active_caller1 = caller;
360 cid = "caller1";
361 GNUNET_CONVERSATION_caller_pick_up (caller,
362 &caller_event_handler,
363 (void *) cid,
364 &phone_speaker,
365 &phone_mic);
366 }
367 else
368 {
369 GNUNET_CONVERSATION_caller_suspend (active_caller1);
370 active_caller2 = caller;
371 cid = "caller2";
372 GNUNET_CONVERSATION_caller_pick_up (caller,
373 &caller_event_handler,
374 (void *) cid,
375 &phone_speaker,
376 &phone_mic);
377 }
378 break;
379 case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP:
380 if (caller == active_caller2)
381 {
382 active_caller2 = NULL;
383 GNUNET_CONVERSATION_caller_resume (active_caller1,
384 &phone_speaker,
385 &phone_mic);
386 }
387 else if (caller == active_caller1)
388 {
389 active_caller1 = NULL;
390 GNUNET_break (NULL == active_caller2);
391 ok = 0;
392 GNUNET_SCHEDULER_shutdown ();
393 }
394 break;
395 default:
396 fprintf (stderr, "Unexpected phone code: %d\n", code);
397 break;
398 }
399}
400
401
402static void
403call_event_handler (void *cls,
404 enum GNUNET_CONVERSATION_CallEventCode code)
405{
406 const char *cid = cls;
407
408 switch (code)
409 {
410 case GNUNET_CONVERSATION_EC_CALL_RINGING:
411 break;
412 case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
413 break;
414 case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
415 case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
416 if (0 == strcmp (cid, "call1"))
417 call1 = NULL;
418 else
419 call2 = NULL;
420 break;
421 case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
422 case GNUNET_CONVERSATION_EC_CALL_RESUMED:
423 break;
424 }
425}
426
427
428static void
429caller_ego_create_cont (void *cls,
430 const char *emsg)
431{
432 op = NULL;
433 GNUNET_assert (NULL == emsg);
434}
435
436
437static void
438namestore_put_cont (void *cls,
439 int32_t success,
440 const char *emsg)
441{
442 qe = NULL;
443 GNUNET_assert (GNUNET_YES == success);
444 GNUNET_assert (NULL == emsg);
445 GNUNET_assert (NULL == op);
446 op = GNUNET_IDENTITY_create (id, "caller-ego", &caller_ego_create_cont, NULL);
447}
448
449
450static void
451identity_cb (void *cls,
452 struct GNUNET_IDENTITY_Ego *ego,
453 void **ctx,
454 const char *name)
455{
456 struct GNUNET_GNSRECORD_Data rd;
457 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
458
459 if (NULL == name)
460 return;
461 if (NULL == ego)
462 return;
463 if (0 == strcmp (name, "phone-ego"))
464 {
465 GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
466 GNUNET_asprintf (&gns_name,
467 "phone.%s",
468 GNUNET_GNSRECORD_pkey_to_zkey (&pub));
469 phone = GNUNET_CONVERSATION_phone_create (cfg,
470 ego,
471 &phone_event_handler,
472 NULL);
473 GNUNET_assert (NULL != phone);
474 memset (&rd, 0, sizeof (rd));
475 GNUNET_CONVERSATION_phone_get_record (phone,
476 &rd);
477 GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE);
478 rd.expiration_time = UINT64_MAX;
479 qe = GNUNET_NAMESTORE_records_store (ns,
480 GNUNET_IDENTITY_ego_get_private_key (ego),
481 "phone" /* GNS label */,
482 1,
483 &rd,
484 &namestore_put_cont,
485 NULL);
486 return;
487 }
488 if (0 == strcmp (name, "caller-ego"))
489 {
490 GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
491 GNUNET_asprintf (&gns_caller_id,
492 "%s",
493 GNUNET_GNSRECORD_pkey_to_zkey (&pub));
494 call1 = GNUNET_CONVERSATION_call_start (cfg,
495 ego,
496 gns_name,
497 &call_speaker,
498 &call_mic,
499 &call_event_handler,
500 (void *) "call1");
501 call2 = GNUNET_CONVERSATION_call_start (cfg,
502 ego,
503 gns_name,
504 &call_speaker,
505 &call_mic,
506 &call_event_handler,
507 (void *) "call2");
508 return;
509 }
510}
511
512
513static void
514phone_ego_create_cont (void *cls,
515 const char *emsg)
516{
517 op = NULL;
518 GNUNET_assert (NULL == emsg);
519}
520
521
522static void
523run (void *cls,
524 const struct GNUNET_CONFIGURATION_Handle *c,
525 struct GNUNET_TESTING_Peer *peer)
526{
527 cfg = c;
528 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test,
529 NULL);
530 id = GNUNET_IDENTITY_connect (cfg,
531 &identity_cb,
532 NULL);
533 op = GNUNET_IDENTITY_create (id, "phone-ego", &phone_ego_create_cont, NULL);
534 ns = GNUNET_NAMESTORE_connect (cfg);
535}
536
537
538int
539main (int argc, char *argv[])
540{
541 if (0 != GNUNET_TESTING_peer_run ("test_conversation_api_twocalls",
542 "test_conversation.conf",
543 &run, NULL))
544 return 1;
545 return ok;
546}
547
548/* end of test_conversation_api_twocalls.c */