123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- /*
- This file is part of GNUnet.
- (C) 2013, 2014 Christian Grothoff (and other contributing authors)
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
- /**
- * @file conversation/test_conversation_api.c
- * @brief testcase for conversation_api.c
- *
- * This test performs the operations of a call to a phone
- * where the phone user picks up and then the call is
- * terminated by the party that initiated the call.
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "gnunet_testing_lib.h"
- #include "gnunet_gnsrecord_lib.h"
- #include "gnunet_conversation_service.h"
- #include "gnunet_identity_service.h"
- #include "gnunet_namestore_service.h"
- #define FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
- #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 25)
- static int ok = 1;
- static const struct GNUNET_CONFIGURATION_Handle *cfg;
- static struct GNUNET_IDENTITY_Handle *id;
- static struct GNUNET_IDENTITY_Operation *op;
- static struct GNUNET_CONVERSATION_Phone *phone;
- static struct GNUNET_NAMESTORE_Handle *ns;
- static struct GNUNET_CONVERSATION_Call *call;
- static struct GNUNET_NAMESTORE_QueueEntry *qe;
- static struct GNUNET_CONVERSATION_Caller *active_caller;
- static char *gns_name;
- static char *gns_caller_id;
- static GNUNET_MICROPHONE_RecordedDataCallback phone_rdc;
- static void *phone_rdc_cls;
- static GNUNET_MICROPHONE_RecordedDataCallback call_rdc;
- static void *call_rdc_cls;
- static GNUNET_SCHEDULER_TaskIdentifier phone_task;
- static GNUNET_SCHEDULER_TaskIdentifier call_task;
- static void
- phone_send (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
- {
- static unsigned int i;
- char buf[32];
- GNUNET_assert (NULL != phone_rdc);
- GNUNET_snprintf (buf, sizeof (buf), "phone-%u", i++);
- phone_rdc (phone_rdc_cls, strlen (buf) + 1, buf);
- phone_task = GNUNET_SCHEDULER_add_delayed (FREQ,
- &phone_send, NULL);
- }
- static void
- call_send (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
- {
- static unsigned int i;
- char buf[32];
- GNUNET_assert (NULL != call_rdc);
- GNUNET_snprintf (buf, sizeof (buf), "call-%u", i++);
- call_rdc (call_rdc_cls, strlen (buf) + 1, buf);
- call_task = GNUNET_SCHEDULER_add_delayed (FREQ,
- &call_send, NULL);
- }
- static int
- enable_speaker (void *cls)
- {
- const char *origin = cls;
- fprintf (stderr,
- "Speaker %s enabled\n",
- origin);
- return GNUNET_OK;
- }
- static void
- disable_speaker (void *cls)
- {
- const char *origin = cls;
- fprintf (stderr,
- "Speaker %s disabled\n",
- origin);
- }
- static void
- play (void *cls,
- size_t data_size,
- const void *data)
- {
- const char *origin = cls;
- static unsigned int phone_i = 1;
- static unsigned int call_i;
- char buf[32];
- if (0 == strcmp (origin, "phone"))
- GNUNET_snprintf (buf, sizeof (buf), "call-%u", call_i++);
- else
- GNUNET_snprintf (buf, sizeof (buf), "phone-%u", phone_i++);
- if ( (data_size != strlen (buf) + 1) ||
- (0 != strncmp (buf, data, data_size)) )
- {
- fprintf (stderr,
- "Expected %s, received %.*s\n",
- buf,
- (int) data_size,
- (const char *) data);
- }
- else
- {
- fprintf (stderr, ".");
- }
- if ( (20 < call_i) &&
- (20 < phone_i) &&
- (NULL != call) )
- {
- /* time to hang up ... */
- GNUNET_CONVERSATION_call_stop (call);
- call = NULL;
- }
- }
- static void
- destroy_speaker (void *cls)
- {
- const char *origin = cls;
- fprintf (stderr, "Speaker %s destroyed\n", origin);
- }
- static struct GNUNET_SPEAKER_Handle call_speaker = {
- &enable_speaker,
- &play,
- &disable_speaker,
- &destroy_speaker,
- "caller"
- };
- static struct GNUNET_SPEAKER_Handle phone_speaker = {
- &enable_speaker,
- &play,
- &disable_speaker,
- &destroy_speaker,
- "phone"
- };
- static int
- enable_mic (void *cls,
- GNUNET_MICROPHONE_RecordedDataCallback rdc,
- void *rdc_cls)
- {
- const char *origin = cls;
- fprintf (stderr,
- "Mic %s enabled\n",
- origin);
- if (0 == strcmp (origin, "phone"))
- {
- phone_rdc = rdc;
- phone_rdc_cls = rdc_cls;
- phone_task = GNUNET_SCHEDULER_add_now (&phone_send, NULL);
- }
- else
- {
- call_rdc = rdc;
- call_rdc_cls = rdc_cls;
- call_task = GNUNET_SCHEDULER_add_now (&call_send, NULL);
- }
- return GNUNET_OK;
- }
- static void
- disable_mic (void *cls)
- {
- const char *origin = cls;
- fprintf (stderr,
- "Mic %s disabled\n",
- origin);
- if (0 == strcmp (origin, "phone"))
- {
- phone_rdc = NULL;
- phone_rdc_cls = NULL;
- GNUNET_SCHEDULER_cancel (phone_task);
- phone_task = GNUNET_SCHEDULER_NO_TASK;
- }
- else
- {
- call_rdc = NULL;
- call_rdc_cls = NULL;
- GNUNET_SCHEDULER_cancel (call_task);
- call_task = GNUNET_SCHEDULER_NO_TASK;
- }
- }
- static void
- destroy_mic (void *cls)
- {
- const char *origin = cls;
- fprintf (stderr,
- "Mic %s destroyed\n",
- origin);
- }
- static struct GNUNET_MICROPHONE_Handle call_mic = {
- &enable_mic,
- &disable_mic,
- &destroy_mic,
- "caller"
- };
- static struct GNUNET_MICROPHONE_Handle phone_mic = {
- &enable_mic,
- &disable_mic,
- &destroy_mic,
- "phone"
- };
- /**
- * Signature of the main function of a task.
- *
- * @param cls closure
- * @param tc context information (why was this task triggered now)
- */
- static void
- end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
- {
- GNUNET_SCHEDULER_shutdown ();
- if (NULL != op)
- {
- GNUNET_IDENTITY_cancel (op);
- op = NULL;
- }
- if (NULL != call)
- {
- GNUNET_CONVERSATION_call_stop (call);
- call = NULL;
- }
- if (NULL != phone)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n");
- GNUNET_CONVERSATION_phone_destroy (phone);
- phone = NULL;
- }
- if (NULL != id)
- {
- GNUNET_IDENTITY_disconnect (id);
- id = NULL;
- }
- if (NULL != qe)
- {
- GNUNET_NAMESTORE_cancel (qe);
- qe = NULL;
- }
- if (NULL != ns)
- {
- GNUNET_NAMESTORE_disconnect (ns);
- ns = NULL;
- }
- }
- static void
- caller_event_handler (void *cls,
- enum GNUNET_CONVERSATION_CallerEventCode code)
- {
- switch (code)
- {
- case GNUNET_CONVERSATION_EC_CALLER_SUSPEND:
- case GNUNET_CONVERSATION_EC_CALLER_RESUME:
- fprintf (stderr, "Unexpected caller code: %d\n", code);
- break;
- }
- }
- static void
- phone_event_handler (void *cls,
- enum GNUNET_CONVERSATION_PhoneEventCode code,
- struct GNUNET_CONVERSATION_Caller *caller,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *caller_id)
- {
- static enum GNUNET_CONVERSATION_PhoneEventCode expect
- = GNUNET_CONVERSATION_EC_PHONE_RING;
- GNUNET_break (code == expect);
- switch (code)
- {
- case GNUNET_CONVERSATION_EC_PHONE_RING:
- active_caller = caller;
- GNUNET_CONVERSATION_caller_pick_up (caller,
- &caller_event_handler,
- NULL,
- &phone_speaker,
- &phone_mic);
- expect = GNUNET_CONVERSATION_EC_PHONE_HUNG_UP;
- break;
- case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP:
- GNUNET_break (caller == active_caller);
- active_caller = NULL;
- ok = 0;
- GNUNET_SCHEDULER_shutdown ();
- break;
- default:
- fprintf (stderr, "Unexpected phone code: %d\n", code);
- break;
- }
- }
- static void
- call_event_handler (void *cls,
- enum GNUNET_CONVERSATION_CallEventCode code)
- {
- static enum GNUNET_CONVERSATION_CallEventCode expect
- = GNUNET_CONVERSATION_EC_CALL_RINGING;
- GNUNET_break (code == expect);
- switch (code)
- {
- case GNUNET_CONVERSATION_EC_CALL_RINGING:
- expect = GNUNET_CONVERSATION_EC_CALL_PICKED_UP;
- break;
- case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
- expect = -1;
- break;
- case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
- case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
- call = NULL;
- fprintf (stderr, "Unexpected call code: %d\n", code);
- break;
- case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
- case GNUNET_CONVERSATION_EC_CALL_RESUMED:
- case GNUNET_CONVERSATION_EC_CALL_ERROR:
- fprintf (stderr, "Unexpected call code: %d\n", code);
- break;
- }
- }
- static void
- caller_ego_create_cont (void *cls,
- const char *emsg)
- {
- op = NULL;
- GNUNET_assert (NULL == emsg);
- }
- static void
- namestore_put_cont (void *cls,
- int32_t success,
- const char *emsg)
- {
- qe = NULL;
- GNUNET_assert (GNUNET_YES == success);
- GNUNET_assert (NULL == emsg);
- GNUNET_assert (NULL == op);
- op = GNUNET_IDENTITY_create (id, "caller-ego", &caller_ego_create_cont, NULL);
- }
- static void
- identity_cb (void *cls,
- struct GNUNET_IDENTITY_Ego *ego,
- void **ctx,
- const char *name)
- {
- struct GNUNET_GNSRECORD_Data rd;
- struct GNUNET_CRYPTO_EcdsaPublicKey pub;
- if (NULL == name)
- return;
- if (NULL == ego)
- return;
- if (0 == strcmp (name, "phone-ego"))
- {
- GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
- GNUNET_asprintf (&gns_name,
- "phone.%s",
- GNUNET_GNSRECORD_pkey_to_zkey (&pub));
- phone = GNUNET_CONVERSATION_phone_create (cfg,
- ego,
- &phone_event_handler,
- NULL);
- GNUNET_assert (NULL != phone);
- memset (&rd, 0, sizeof (rd));
- GNUNET_CONVERSATION_phone_get_record (phone,
- &rd);
- GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE);
- rd.expiration_time = UINT64_MAX;
- qe = GNUNET_NAMESTORE_records_store (ns,
- GNUNET_IDENTITY_ego_get_private_key (ego),
- "phone" /* GNS label */,
- 1,
- &rd,
- &namestore_put_cont,
- NULL);
- return;
- }
- if (0 == strcmp (name, "caller-ego"))
- {
- GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
- GNUNET_asprintf (&gns_caller_id,
- "%s",
- GNUNET_GNSRECORD_pkey_to_zkey (&pub));
- call = GNUNET_CONVERSATION_call_start (cfg,
- ego,
- ego,
- gns_name,
- &call_speaker,
- &call_mic,
- &call_event_handler,
- NULL);
- return;
- }
- }
- static void
- phone_ego_create_cont (void *cls,
- const char *emsg)
- {
- op = NULL;
- GNUNET_assert (NULL == emsg);
- }
- static void
- run (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *c,
- struct GNUNET_TESTING_Peer *peer)
- {
- cfg = c;
- GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test,
- NULL);
- id = GNUNET_IDENTITY_connect (cfg,
- &identity_cb,
- NULL);
- op = GNUNET_IDENTITY_create (id, "phone-ego", &phone_ego_create_cont, NULL);
- ns = GNUNET_NAMESTORE_connect (cfg);
- }
- int
- main (int argc, char *argv[])
- {
- if (0 != GNUNET_TESTING_peer_run ("test_conversation_api",
- "test_conversation.conf",
- &run, NULL))
- return 1;
- return ok;
- }
- /* end of test_conversation_api.c */
|