From 9c37ec935877bc6196febec8f6b2f0ad036189b9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 11 Aug 2016 18:04:19 +0000 Subject: -converting API to use new CADET ports --- src/conversation/conversation.h | 92 ++- src/conversation/conversation_api.c | 97 ++- src/conversation/conversation_api_call.c | 30 +- src/conversation/gnunet-conversation.c | 17 +- src/conversation/gnunet-service-conversation.c | 859 ++++++++++------------- src/conversation/plugin_gnsrecord_conversation.c | 46 +- src/conversation/test_conversation.conf | 3 +- src/conversation/test_conversation_api.c | 4 +- src/conversation/test_conversation_api_reject.c | 6 +- 9 files changed, 557 insertions(+), 597 deletions(-) diff --git a/src/conversation/conversation.h b/src/conversation/conversation.h index bbe587b50..1ca816f0e 100644 --- a/src/conversation/conversation.h +++ b/src/conversation/conversation.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2013 GNUnet e.V. + Copyright (C) 2013-2016 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -75,9 +75,14 @@ struct ClientPhoneRegisterMessage struct GNUNET_MessageHeader header; /** - * Phone line to register. + * Always zero. */ - uint32_t line GNUNET_PACKED; + uint32_t reserved GNUNET_PACKED; + + /** + * Phone line / CADET port to register. + */ + struct GNUNET_HashCode line_port; }; @@ -92,8 +97,8 @@ struct ClientPhoneRingMessage struct GNUNET_MessageHeader header; /** - * CID, internal caller ID to identify which active call we are - * talking about. + * CID, internal caller ID number used in the future to identify + * which active call we are talking about. */ uint32_t cid GNUNET_PACKED; @@ -183,7 +188,7 @@ struct ClientPhoneHangupMessage /** - * Message Client <->Service to transmit the audio. + * Message Client <-> Service to transmit the audio. */ struct ClientAudioMessage { @@ -214,15 +219,20 @@ struct ClientCallMessage struct GNUNET_MessageHeader header; /** - * Which phone line to call at the peer? + * Always zero. */ - uint32_t line GNUNET_PACKED; + uint32_t reserved GNUNET_PACKED; /** * Which peer is hosting the line? */ struct GNUNET_PeerIdentity target; + /** + * Which phone line to call at the peer? + */ + struct GNUNET_HashCode line_port; + /** * Identity of the caller. */ @@ -241,58 +251,74 @@ struct ClientPhonePickedupMessage */ struct GNUNET_MessageHeader header; + /** + * Call ID of the corresponding + * #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL + */ + uint32_t cid GNUNET_PACKED; + }; /** - * Cadet message for phone is ringing. + * Information signed in a `struct CadetPhoneRingMessage` + * whereby the caller self-identifies to the receiver. */ -struct CadetPhoneRingMessage +struct CadetPhoneRingInfoPS { /** - * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING + * Purpose for the signature, must be + * #GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING. */ - struct GNUNET_MessageHeader header; + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * Desired target line. + * Which port did the call go to? */ - uint32_t remote_line GNUNET_PACKED; + struct GNUNET_HashCode line_port; /** - * Purpose for the signature. + * Which peer is the call for? */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct GNUNET_PeerIdentity target_peer; /** - * Who is calling us? (also who is signing). + * When does the signature expire? */ - struct GNUNET_CRYPTO_EcdsaPublicKey caller_id; + struct GNUNET_TIME_AbsoluteNBO expiration_time; +}; + +/** + * Cadet message to make a phone ring. Sent to the port + * of the respective phone. + */ +struct CadetPhoneRingMessage +{ /** - * Who are we calling? + * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING */ - struct GNUNET_PeerIdentity target; + struct GNUNET_MessageHeader header; /** - * From where are we calling? + * Always zero. */ - struct GNUNET_PeerIdentity source; + uint32_t reserved GNUNET_PACKED; /** - * When does the signature expire? + * Who is calling us? (also who is signing). */ - struct GNUNET_TIME_AbsoluteNBO expiration_time; + struct GNUNET_CRYPTO_EcdsaPublicKey caller_id; /** - * Signature on the above. + * When does the signature expire? */ - struct GNUNET_CRYPTO_EcdsaSignature signature; + struct GNUNET_TIME_AbsoluteNBO expiration_time; /** - * Source line for audio data in the other direction. + * Signature over a `struct CadetPhoneRingInfoPS` */ - uint32_t source_line GNUNET_PACKED; + struct GNUNET_CRYPTO_EcdsaSignature signature; }; @@ -359,16 +385,6 @@ struct CadetAudioMessage */ struct GNUNET_MessageHeader header; - /** - * Target line on the receiving end. - */ - uint32_t remote_line GNUNET_PACKED; - - /** - * The source line sending this data - */ - uint32_t source_line GNUNET_PACKED; - /* followed by audio data */ }; diff --git a/src/conversation/conversation_api.c b/src/conversation/conversation_api.c index 3c0a68f4f..5dd9cf79e 100644 --- a/src/conversation/conversation_api.c +++ b/src/conversation/conversation_api.c @@ -238,8 +238,11 @@ transmit_phone_audio (void *cls, data_size, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); am->cid = caller->cid; - GNUNET_memcpy (&am[1], data, data_size); - GNUNET_MQ_send (phone->mq, e); + GNUNET_memcpy (&am[1], + data, + data_size); + GNUNET_MQ_send (phone->mq, + e); } @@ -279,6 +282,26 @@ handle_phone_ring (void *cls, } +/** + * Find the record of the caller matching the @a cid + * + * @param phone phone to search + * @param cid caller ID to search for (in NBO) + * @return NULL if @a cid was not found + */ +static struct GNUNET_CONVERSATION_Caller * +find_caller (struct GNUNET_CONVERSATION_Phone *phone, + uint32_t cid) +{ + struct GNUNET_CONVERSATION_Caller *caller; + + for (caller = phone->caller_head;NULL != caller;caller = caller->next) + if (cid == caller->cid) + return caller; + return NULL; +} + + /** * We received a `struct ClientPhoneHangupMessage`. * @@ -292,9 +315,8 @@ handle_phone_hangup (void *cls, struct GNUNET_CONVERSATION_Phone *phone = cls; struct GNUNET_CONVERSATION_Caller *caller; - for (caller = phone->caller_head; NULL != caller; caller = caller->next) - if (hang->cid == caller->cid) - break; + caller = find_caller (phone, + hang->cid); if (NULL == caller) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -351,9 +373,8 @@ handle_phone_suspend (void *cls, struct GNUNET_CONVERSATION_Phone *phone = cls; struct GNUNET_CONVERSATION_Caller *caller; - for (caller = phone->caller_head; NULL != caller; caller = caller->next) - if (suspend->cid == caller->cid) - break; + caller = find_caller (phone, + suspend->cid); if (NULL == caller) return; switch (caller->state) @@ -394,9 +415,8 @@ handle_phone_resume (void *cls, struct GNUNET_CONVERSATION_Phone *phone = cls; struct GNUNET_CONVERSATION_Caller *caller; - for (caller = phone->caller_head; NULL != caller; caller = caller->next) - if (resume->cid == caller->cid) - break; + caller = find_caller (phone, + resume->cid); if (NULL == caller) return; switch (caller->state) @@ -455,9 +475,8 @@ handle_phone_audio (void *cls, struct GNUNET_CONVERSATION_Phone *phone = cls; struct GNUNET_CONVERSATION_Caller *caller; - for (caller = phone->caller_head; NULL != caller; caller = caller->next) - if (am->cid == caller->cid) - break; + caller = find_caller (phone, + am->cid); if (NULL == caller) return; switch (caller->state) @@ -572,9 +591,11 @@ reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone) phone); if (NULL == phone->mq) return; - e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER); - reg->line = phone->my_record.line; - GNUNET_MQ_send (phone->mq, e); + e = GNUNET_MQ_msg (reg, + GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER); + reg->line_port = phone->my_record.line_port; + GNUNET_MQ_send (phone->mq, + e); phone->state = PS_READY; } @@ -596,10 +617,11 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg, void *event_handler_cls) { struct GNUNET_CONVERSATION_Phone *phone; - unsigned long long line; + char *line; + struct GNUNET_HashCode line_port; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, + GNUNET_CONFIGURATION_get_value_string (cfg, "CONVERSATION", "LINE", &line)) @@ -609,14 +631,9 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg, "LINE"); return NULL; } - if (line >= HIGH_BIT) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "CONVERSATION", - "LINE", - _("number too large")); - return NULL; - } + GNUNET_CRYPTO_hash (line, + strlen (line), + &line_port); phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone); if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, @@ -631,8 +648,9 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg, phone->event_handler = event_handler; phone->event_handler_cls = event_handler_cls; phone->ns = GNUNET_NAMESTORE_connect (cfg); - phone->my_record.line = htonl ((uint32_t) line); - phone->my_record.version = htonl (0); + phone->my_record.version = htonl (1); + phone->my_record.reserved = htonl (0); + phone->my_record.line_port = line_port; reconnect_phone (phone); if ( (NULL == phone->mq) || (NULL == phone->ns) ) @@ -689,9 +707,11 @@ GNUNET_CONVERSATION_caller_pick_up (struct GNUNET_CONVERSATION_Caller *caller, GNUNET_assert (CS_RINGING == caller->state); caller->speaker = speaker; caller->mic = mic; - e = GNUNET_MQ_msg (pick, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP); + e = GNUNET_MQ_msg (pick, + GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP); pick->cid = caller->cid; - GNUNET_MQ_send (phone->mq, e); + GNUNET_MQ_send (phone->mq, + e); caller->state = CS_ACTIVE; caller->event_handler = event_handler; caller->event_handler_cls = event_handler_cls; @@ -730,7 +750,8 @@ GNUNET_CONVERSATION_caller_hang_up (struct GNUNET_CONVERSATION_Caller *caller) e = GNUNET_MQ_msg (hang, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); hang->cid = caller->cid; - GNUNET_MQ_send (phone->mq, e); + GNUNET_MQ_send (phone->mq, + e); GNUNET_free (caller); } @@ -781,9 +802,11 @@ GNUNET_CONVERSATION_caller_suspend (struct GNUNET_CONVERSATION_Caller *caller) } caller->speaker = NULL; caller->mic = NULL; - e = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); + e = GNUNET_MQ_msg (suspend, + GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); suspend->cid = caller->cid; - GNUNET_MQ_send (phone->mq, e); + GNUNET_MQ_send (phone->mq, + e); if (CS_ACTIVE == caller->state) caller->state = CS_CALLEE_SUSPENDED; else @@ -811,9 +834,11 @@ GNUNET_CONVERSATION_caller_resume (struct GNUNET_CONVERSATION_Caller *caller, (CS_BOTH_SUSPENDED == caller->state) ); caller->speaker = speaker; caller->mic = mic; - e = GNUNET_MQ_msg (resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME); + e = GNUNET_MQ_msg (resume, + GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME); resume->cid = caller->cid; - GNUNET_MQ_send (phone->mq, e); + GNUNET_MQ_send (phone->mq, + e); if (CS_CALLEE_SUSPENDED == caller->state) { caller->state = CS_ACTIVE; diff --git a/src/conversation/conversation_api_call.c b/src/conversation/conversation_api_call.c index cd1bf8f86..af05f3ea6 100644 --- a/src/conversation/conversation_api_call.c +++ b/src/conversation/conversation_api_call.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - Copyright (C) 2013 GNUnet e.V. + Copyright (C) 2013, 2016 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -177,8 +177,11 @@ transmit_call_audio (void *cls, e = GNUNET_MQ_msg_extra (am, data_size, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); - GNUNET_memcpy (&am[1], data, data_size); - GNUNET_MQ_send (call->mq, e); + GNUNET_memcpy (&am[1], + data, + data_size); + GNUNET_MQ_send (call->mq, + e); } @@ -345,7 +348,8 @@ handle_call_hangup (void *cls, eh = call->event_handler; eh_cls = call->event_handler_cls; GNUNET_CONVERSATION_call_stop (call); - eh (eh_cls, GNUNET_CONVERSATION_EC_CALL_HUNG_UP); + eh (eh_cls, + GNUNET_CONVERSATION_EC_CALL_HUNG_UP); return; case CS_SHUTDOWN: GNUNET_CONVERSATION_call_stop (call); @@ -443,13 +447,15 @@ handle_gns_response (void *cls, continue; } GNUNET_memcpy (&call->phone_record, - rd[i].data, - rd[i].data_size); - e = GNUNET_MQ_msg (ccm, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL); - ccm->line = call->phone_record.line; + rd[i].data, + rd[i].data_size); + e = GNUNET_MQ_msg (ccm, + GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL); + ccm->line_port = call->phone_record.line_port; ccm->target = call->phone_record.peer; ccm->caller_id = *GNUNET_IDENTITY_ego_get_private_key (call->caller_id); - GNUNET_MQ_send (call->mq, e); + GNUNET_MQ_send (call->mq, + e); call->state = CS_RINGING; call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_RINGING); @@ -663,8 +669,10 @@ GNUNET_CONVERSATION_call_suspend (struct GNUNET_CONVERSATION_Call *call) } call->speaker = NULL; call->mic = NULL; - e = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); - GNUNET_MQ_send (call->mq, e); + e = GNUNET_MQ_msg (suspend, + GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); + GNUNET_MQ_send (call->mq, + e); if (CS_SUSPENDED_CALLER == call->state) call->state = CS_SUSPENDED_BOTH; else diff --git a/src/conversation/gnunet-conversation.c b/src/conversation/gnunet-conversation.c index d899ee5ca..925db4665 100644 --- a/src/conversation/gnunet-conversation.c +++ b/src/conversation/gnunet-conversation.c @@ -166,9 +166,9 @@ static struct CallList *cl_head; static struct CallList *cl_tail; /** - * Desired phone line. + * Desired phone line (string to be converted to a hash). */ -static unsigned int line; +static char *line; /** * Task which handles the commands @@ -357,7 +357,8 @@ start_phone () GNUNET_assert (NULL == phone); phone = GNUNET_CONVERSATION_phone_create (cfg, my_caller_id, - &phone_event_handler, NULL); + &phone_event_handler, + NULL); /* FIXME: get record and print full GNS record info later here... */ if (NULL == phone) { @@ -375,8 +376,8 @@ start_phone () rd.data, rd.data_size); FPRINTF (stdout, - _("Phone active on line %u. Type `/help' for a list of available commands\n"), - (unsigned int) line); + _("Phone active at `%s'. Type `/help' for a list of available commands\n"), + address); phone_state = PS_LISTEN; } } @@ -687,7 +688,7 @@ do_status (const char *args) break; case PS_LISTEN: FPRINTF (stdout, - _("We are listening for incoming calls for ego `%s' on line %u.\n"), + _("We are listening for incoming calls for ego `%s' on line `%s'.\n"), ego_name, line); break; @@ -1187,7 +1188,7 @@ identity_cb (void *cls, return; } my_caller_id = ego; - GNUNET_CONFIGURATION_set_value_number (cfg, + GNUNET_CONFIGURATION_set_value_string (cfg, "CONVERSATION", "LINE", line); @@ -1270,7 +1271,7 @@ main (int argc, char *const *argv) 1, &GNUNET_GETOPT_set_string, &ego_name}, {'p', "phone", "LINE", gettext_noop ("sets the LINE to use for the phone"), - 1, &GNUNET_GETOPT_set_uint, &line}, + 1, &GNUNET_GETOPT_set_string, &line}, GNUNET_GETOPT_OPTION_END }; int ret; diff --git a/src/conversation/gnunet-service-conversation.c b/src/conversation/gnunet-service-conversation.c index b547d814c..baf35c9a2 100644 --- a/src/conversation/gnunet-service-conversation.c +++ b/src/conversation/gnunet-service-conversation.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2013 GNUnet e.V. + Copyright (C) 2013, 2016 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -54,6 +54,11 @@ struct Line; */ enum ChannelStatus { + /** + * We just got the connection, but no introduction yet. + */ + CS_CALLEE_INIT, + /** * Our phone is ringing, waiting for the client to pick up. */ @@ -112,50 +117,25 @@ struct Channel struct Line *line; /** - * Handle for the reliable channel (contol data) - */ - struct GNUNET_CADET_Channel *channel_reliable; - - /** - * Handle for unreliable channel (audio data) - */ - struct GNUNET_CADET_Channel *channel_unreliable; - - /** - * Transmit handle for pending audio messages + * Handle for the channel. */ - struct GNUNET_CADET_TransmitHandle *unreliable_mth; + struct GNUNET_CADET_Channel *channel; /** * Message queue for control messages */ - struct GNUNET_MQ_Handle *reliable_mq; + struct GNUNET_MQ_Handle *mq; /** - * Target of the line, if we are the caller. + * Temporary buffer for audio data in the @e mq. */ - struct GNUNET_PeerIdentity target; + struct GNUNET_MQ_Envelope *env; /** - * Temporary buffer for audio data. - */ - void *audio_data; - - /** - * Number of bytes in @e audio_data. - */ - size_t audio_size; - - /** - * Channel identifier. + * Channel identifier we use for this call with the client. */ uint32_t cid; - /** - * Remote line number. - */ - uint32_t remote_line; - /** * Current status of this line. */ @@ -179,16 +159,6 @@ struct Channel */ struct Line { - /** - * Kept in a DLL. - */ - struct Line *next; - - /** - * Kept in a DLL. - */ - struct Line *prev; - /** * This is a DLL. */ @@ -205,14 +175,20 @@ struct Line struct GNUNET_SERVER_Client *client; /** - * Generator for channel IDs. + * Our open port. */ - uint32_t cid_gen; + struct GNUNET_CADET_Port *port; /** - * Our line number. + * Port number we are listening on (to verify signatures). + * Only valid if @e port is non-NULL. */ - uint32_t local_line; + struct GNUNET_HashCode line_port; + + /** + * Generator for channel IDs. + */ + uint32_t cid_gen; }; @@ -237,56 +213,25 @@ static struct GNUNET_CADET_Handle *cadet; */ static struct GNUNET_PeerIdentity my_identity; -/** - * Head of DLL of active lines. - */ -static struct Line *lines_head; - -/** - * Tail of DLL of active lines. - */ -static struct Line *lines_tail; - -/** - * Counter for generating local line numbers. - * FIXME: randomize generation in the future - * to eliminate information leakage. - */ -static uint32_t local_line_cnt; - /** - * Function to register a phone. + * Given a @a cid, find the corresponding channel given + * a @a line. * - * @param cls closure, NULL - * @param client the client from which the message is - * @param message the message from the client + * @param line a line to search + * @param cid what to search for + * @return NULL for not found */ -static void -handle_client_register_message (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static struct Channel * +find_channel_by_line (struct Line *line, + uint32_t cid) { - const struct ClientPhoneRegisterMessage *msg; - struct Line *line; + struct Channel *ch; - msg = (const struct ClientPhoneRegisterMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); - if (NULL != line) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - line = GNUNET_new (struct Line); - line->client = client; - GNUNET_SERVER_notification_context_add (nc, client); - GNUNET_SERVER_client_set_user_context (client, line); - GNUNET_CONTAINER_DLL_insert (lines_head, - lines_tail, - line); - line->local_line = ntohl (msg->line) & (~ HIGH_BIT); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + for (ch = line->channel_head; NULL != ch; ch = ch->next) + if (cid == ch->cid) + return ch; + return NULL; } @@ -309,7 +254,8 @@ handle_client_pickup_message (void *cls, struct Channel *ch; msg = (const struct ClientPhonePickupMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL == line) { GNUNET_break (0); @@ -325,17 +271,24 @@ handle_client_pickup_message (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); - GNUNET_SERVER_receive_done (client, GNUNET_YES); + GNUNET_SERVER_receive_done (client, + GNUNET_YES); return; } switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); + return; case CS_CALLEE_RINGING: ch->status = CS_CALLEE_CONNECTED; break; case CS_CALLEE_CONNECTED: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; case CS_CALLEE_SHUTDOWN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -353,8 +306,9 @@ handle_client_pickup_message (void *cls, "Sending PICK_UP message to cadet\n"); e = GNUNET_MQ_msg (mppm, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP); - GNUNET_MQ_send (ch->reliable_mq, e); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (ch->mq, e); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); } @@ -366,36 +320,15 @@ handle_client_pickup_message (void *cls, static void destroy_line_cadet_channels (struct Channel *ch) { - struct Line *line = ch->line; - struct GNUNET_CADET_Channel *t; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying cadet channels\n"); - if (NULL != ch->reliable_mq) - { - GNUNET_MQ_destroy (ch->reliable_mq); - ch->reliable_mq = NULL; - } - if (NULL != ch->unreliable_mth) - { - GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth); - ch->unreliable_mth = NULL; - } - if (NULL != (t = ch->channel_unreliable)) - { - ch->channel_unreliable = NULL; - GNUNET_CADET_channel_destroy (t); - } - if (NULL != (t = ch->channel_reliable)) + if (NULL != ch->mq) { - ch->channel_reliable = NULL; - GNUNET_CADET_channel_destroy (t); + GNUNET_MQ_destroy (ch->mq); + ch->mq = NULL; } - GNUNET_CONTAINER_DLL_remove (line->channel_head, - line->channel_tail, - ch); - GNUNET_free_non_null (ch->audio_data); - GNUNET_free (ch); + if (NULL != ch->channel) + GNUNET_CADET_channel_destroy (ch->channel); } @@ -412,6 +345,9 @@ mq_done_finish_caller_shutdown (void *cls) switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break (0); + break; case CS_CALLEE_RINGING: GNUNET_break (0); break; @@ -453,11 +389,13 @@ handle_client_hangup_message (void *cls, struct Channel *ch; msg = (const struct ClientPhoneHangupMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL == line) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) @@ -469,7 +407,8 @@ handle_client_hangup_message (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -478,6 +417,11 @@ handle_client_hangup_message (void *cls, ch->status); switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); + return; case CS_CALLEE_RINGING: ch->status = CS_CALLEE_SHUTDOWN; break; @@ -486,7 +430,8 @@ handle_client_hangup_message (void *cls, break; case CS_CALLEE_SHUTDOWN: /* maybe the other peer closed asynchronously... */ - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; case CS_CALLER_CALLING: ch->status = CS_CALLER_SHUTDOWN; @@ -506,8 +451,10 @@ handle_client_hangup_message (void *cls, GNUNET_MQ_notify_sent (e, &mq_done_finish_caller_shutdown, ch); - GNUNET_MQ_send (ch->reliable_mq, e); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (ch->mq, + e); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); } @@ -530,11 +477,13 @@ handle_client_suspend_message (void *cls, struct Channel *ch; msg = (const struct ClientPhoneSuspendMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL == line) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) @@ -546,13 +495,15 @@ handle_client_suspend_message (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; } if (GNUNET_YES == ch->suspended_local) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -561,35 +512,46 @@ handle_client_suspend_message (void *cls, ch->status); switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); + return; case CS_CALLEE_RINGING: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; case CS_CALLEE_CONNECTED: ch->suspended_local = GNUNET_YES; break; case CS_CALLEE_SHUTDOWN: /* maybe the other peer closed asynchronously... */ - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; case CS_CALLER_CALLING: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; case CS_CALLER_CONNECTED: ch->suspended_local = GNUNET_YES; break; case CS_CALLER_SHUTDOWN: /* maybe the other peer closed asynchronously... */ - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUSPEND message via cadet\n"); e = GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND); - GNUNET_MQ_send (ch->reliable_mq, e); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (ch->mq, + e); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); } @@ -612,11 +574,13 @@ handle_client_resume_message (void *cls, struct Channel *ch; msg = (const struct ClientPhoneResumeMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL == line) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) @@ -628,7 +592,8 @@ handle_client_resume_message (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; } if (GNUNET_YES != ch->suspended_local) @@ -643,35 +608,46 @@ handle_client_resume_message (void *cls, ch->status); switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); + return; case CS_CALLEE_RINGING: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; case CS_CALLEE_CONNECTED: ch->suspended_local = GNUNET_NO; break; case CS_CALLEE_SHUTDOWN: /* maybe the other peer closed asynchronously... */ - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; case CS_CALLER_CALLING: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; case CS_CALLER_CONNECTED: ch->suspended_local = GNUNET_NO; break; case CS_CALLER_SHUTDOWN: /* maybe the other peer closed asynchronously... */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RESUME message via cadet\n"); e = GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME); - GNUNET_MQ_send (ch->reliable_mq, e); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (ch->mq, + e); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); } @@ -692,9 +668,11 @@ handle_client_call_message (void *cls, struct Channel *ch; struct GNUNET_MQ_Envelope *e; struct CadetPhoneRingMessage *ring; + struct CadetPhoneRingInfoPS rs; msg = (const struct ClientCallMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL != line) { GNUNET_break (0); @@ -703,86 +681,59 @@ handle_client_call_message (void *cls, } line = GNUNET_new (struct Line); line->client = client; - line->local_line = (local_line_cnt++) | HIGH_BIT; - GNUNET_SERVER_client_set_user_context (client, line); - GNUNET_SERVER_notification_context_add (nc, client); - GNUNET_CONTAINER_DLL_insert (lines_head, - lines_tail, - line); + line->line_port = msg->line_port; + GNUNET_SERVER_client_set_user_context (client, + line); + GNUNET_SERVER_notification_context_add (nc, + client); + rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); + rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS)); + rs.line_port = line->line_port; + rs.target_peer = msg->target; + rs.expiration_time + = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT)); + ch = GNUNET_new (struct Channel); ch->line = line; GNUNET_CONTAINER_DLL_insert (line->channel_head, line->channel_tail, ch); - ch->target = msg->target; - ch->remote_line = ntohl (msg->line); ch->status = CS_CALLER_CALLING; - ch->channel_reliable = GNUNET_CADET_channel_create (cadet, - ch, - &msg->target, - GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL), - GNUNET_CADET_OPTION_RELIABLE); - ch->reliable_mq = GNUNET_CADET_mq_create (ch->channel_reliable); - e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING); - ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); - ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 + - sizeof (struct GNUNET_TIME_AbsoluteNBO) + - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + ch->channel = GNUNET_CADET_channel_create (cadet, + ch, + &msg->target, + &msg->line_port, + GNUNET_CADET_OPTION_RELIABLE); + ch->mq = GNUNET_CADET_mq_create (ch->channel); + e = GNUNET_MQ_msg (ring, + GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING); GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id, &ring->caller_id); - ring->remote_line = msg->line; - ring->source_line = htonl (line->local_line); - ring->target = msg->target; - ring->source = my_identity; - ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT)); + ring->expiration_time = rs.expiration_time; GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id, - &ring->purpose, + &rs.purpose, &ring->signature)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending RING message via cadet\n"); - GNUNET_MQ_send (ch->reliable_mq, e); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + "Sending RING message via CADET\n"); + GNUNET_MQ_send (ch->mq, + e); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); } /** - * Transmit audio data via unreliable cadet channel. + * Transmission of audio data via cadet channel finished. * * @param cls the `struct Channel` we are transmitting for - * @param size number of bytes available in @a buf - * @param buf where to copy the data - * @return number of bytes copied to @a buf */ -static size_t -transmit_line_audio (void *cls, - size_t size, - void *buf) +static void +channel_audio_sent_notify (void *cls) { struct Channel *ch = cls; - struct CadetAudioMessage *mam = buf; - - ch->unreliable_mth = NULL; - if ( (NULL == buf) || - (size < sizeof (struct CadetAudioMessage) + ch->audio_size) ) - { - /* eh, other error handling? */ - return 0; - } - mam->header.size = htons (sizeof (struct CadetAudioMessage) + ch->audio_size); - mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO); - mam->remote_line = htonl (ch->remote_line); - mam->source_line = htonl (ch->line->local_line); - GNUNET_memcpy (&mam[1], ch->audio_data, ch->audio_size); - GNUNET_free (ch->audio_data); - ch->audio_data = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending %u bytes of audio data from line %u to remote line %u via cadet\n", - (unsigned int) ch->audio_size, - ch->line->local_line, - ch->remote_line); - return sizeof (struct CadetAudioMessage) + ch->audio_size; + + ch->env = NULL; } @@ -799,38 +750,43 @@ handle_client_audio_message (void *cls, const struct GNUNET_MessageHeader *message) { const struct ClientAudioMessage *msg; + struct ClientAudioMessage *mam; struct Line *line; struct Channel *ch; size_t size; size = ntohs (message->size) - sizeof (struct ClientAudioMessage); msg = (const struct ClientAudioMessage *) message; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL == line) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } - for (ch = line->channel_head; NULL != ch; ch = ch->next) - if (msg->cid == ch->cid) - break; + ch = find_channel_by_line (line, + msg->cid); if (NULL == ch) { /* could have been destroyed asynchronously, ignore message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; } switch (ch->status) { + case CS_CALLEE_INIT: case CS_CALLEE_RINGING: case CS_CALLER_CALLING: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; case CS_CALLEE_CONNECTED: case CS_CALLER_CONNECTED: @@ -840,61 +796,41 @@ handle_client_audio_message (void *cls, case CS_CALLER_SHUTDOWN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Cadet audio channel in shutdown; audio data dropped\n"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); return; } if (GNUNET_YES == ch->suspended_local) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "This channel is suspended locally\n"); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - if (NULL == ch->channel_unreliable) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, - _("Cadet audio channel not ready; audio data dropped\n")); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "This channel is suspended locally\n"); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); return; } - if (NULL != ch->unreliable_mth) + if (NULL != ch->env) { /* NOTE: we may want to not do this and instead combine the data */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Bandwidth insufficient; dropping previous audio data segment with %u bytes\n", - (unsigned int) ch->audio_size); - GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth); - ch->unreliable_mth = NULL; - GNUNET_free (ch->audio_data); - ch->audio_data = NULL; + "Bandwidth insufficient; dropping previous audio data segment\n"); + GNUNET_MQ_send_cancel (ch->env); + ch->env = NULL; } - ch->audio_size = size; - ch->audio_data = GNUNET_malloc (ch->audio_size); - GNUNET_memcpy (ch->audio_data, - &msg[1], - size); - ch->unreliable_mth = GNUNET_CADET_notify_transmit_ready (ch->channel_unreliable, - GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - sizeof (struct CadetAudioMessage) - + ch->audio_size, - &transmit_line_audio, - ch); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - -/** - * We are done signalling shutdown to the other peer. - * Destroy the channel. - * - * @param cls the `struct GNUNET_CADET_channel` to destroy - */ -static void -mq_done_destroy_channel (void *cls) -{ - struct GNUNET_CADET_Channel *channel = cls; - - GNUNET_CADET_channel_destroy (channel); + ch->env = GNUNET_MQ_msg_extra (mam, + size, + GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO); + GNUNET_memcpy (&mam[1], + &msg[1], + size); + /* FIXME: set options for unreliable transmission */ + GNUNET_MQ_notify_sent (ch->env, + &channel_audio_sent_notify, + ch); + GNUNET_MQ_send (ch->mq, + ch->env); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); } @@ -910,70 +846,55 @@ mq_done_destroy_channel (void *cls) */ static int handle_cadet_ring_message (void *cls, - struct GNUNET_CADET_Channel *channel, - void **channel_ctx, - const struct GNUNET_MessageHeader *message) + struct GNUNET_CADET_Channel *channel, + void **channel_ctx, + const struct GNUNET_MessageHeader *message) { + struct Channel *ch = *channel_ctx; + struct Line *line = ch->line; const struct CadetPhoneRingMessage *msg; - struct Line *line; - struct Channel *ch; - struct GNUNET_MQ_Envelope *e; - struct CadetPhoneHangupMessage *hang_up; struct ClientPhoneRingMessage cring; - struct GNUNET_MQ_Handle *reliable_mq; + struct CadetPhoneRingInfoPS rs; msg = (const struct CadetPhoneRingMessage *) message; - if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 + - sizeof (struct GNUNET_TIME_AbsoluteNBO) + - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) || - (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING, - &msg->purpose, + rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); + rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS)); + rs.line_port = line->line_port; + rs.target_peer = my_identity; + rs.expiration_time = msg->expiration_time; + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING, + &rs.purpose, &msg->signature, - &msg->caller_id)) ) + &msg->caller_id)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - GNUNET_CADET_receive_done (channel); /* needed? */ - for (line = lines_head; NULL != line; line = line->next) - if (line->local_line == ntohl (msg->remote_line)) - break; - if (NULL == line) + if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (msg->expiration_time)).rel_value_us) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("No available phone for incoming call on line %u, sending HANG_UP signal\n"), - ntohl (msg->remote_line)); - e = GNUNET_MQ_msg (hang_up, - GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP); - GNUNET_MQ_notify_sent (e, - &mq_done_destroy_channel, - channel); - reliable_mq = GNUNET_CADET_mq_create (channel); - GNUNET_MQ_send (reliable_mq, e); - /* FIXME: do we need to clean up reliable_mq somehow/somewhere? */ - return GNUNET_OK; + /* ancient call, replay? */ + GNUNET_break_op (0); + /* Note that our reliance on time here is awkward; better would be + to use a more complex challenge-response protocol against + replay attacks. Left for future work ;-). */ + return GNUNET_SYSERR; } - ch = GNUNET_new (struct Channel); - ch->line = line; - GNUNET_CONTAINER_DLL_insert (line->channel_head, - line->channel_tail, - ch); + if (CS_CALLEE_INIT != ch->status) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + GNUNET_CADET_receive_done (channel); ch->status = CS_CALLEE_RINGING; - ch->remote_line = ntohl (msg->source_line); - ch->channel_reliable = channel; - ch->reliable_mq = GNUNET_CADET_mq_create (ch->channel_reliable); - ch->cid = line->cid_gen++; - ch->target = msg->source; - *channel_ctx = ch; cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING); cring.header.size = htons (sizeof (cring)); cring.cid = ch->cid; cring.caller_id = msg->caller_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending RING message to client. CID %u:(%u, %u)\n", - ch->cid, ch->remote_line, line->local_line); + "Sending RING message to client. CID is %u\n", + (unsigned int) ch->cid); GNUNET_SERVER_notification_context_unicast (nc, line->client, &cring.header, @@ -994,31 +915,26 @@ handle_cadet_ring_message (void *cls, */ static int handle_cadet_hangup_message (void *cls, - struct GNUNET_CADET_Channel *channel, - void **channel_ctx, - const struct GNUNET_MessageHeader *message) + struct GNUNET_CADET_Channel *channel, + void **channel_ctx, + const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; - struct Line *line; + struct Line *line = ch->line; struct ClientPhoneHangupMessage hup; enum ChannelStatus status; - if (NULL == ch) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "HANGUP message received for non-existing line, dropping channel.\n"); - return GNUNET_SYSERR; - } - line = ch->line; - *channel_ctx = NULL; + GNUNET_CADET_receive_done (channel); hup.header.size = htons (sizeof (hup)); hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); hup.cid = ch->cid; status = ch->status; - GNUNET_CADET_receive_done (channel); destroy_line_cadet_channels (ch); switch (status) { + case CS_CALLEE_INIT: + GNUNET_break_op (0); + return GNUNET_OK; case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: break; @@ -1053,24 +969,18 @@ handle_cadet_hangup_message (void *cls, */ static int handle_cadet_pickup_message (void *cls, - struct GNUNET_CADET_Channel *channel, - void **channel_ctx, - const struct GNUNET_MessageHeader *message) + struct GNUNET_CADET_Channel *channel, + void **channel_ctx, + const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; - struct Line *line; + struct Line *line = ch->line; struct ClientPhonePickedupMessage pick; - if (NULL == ch) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "PICKUP message received for non-existing channel, dropping channel.\n"); - return GNUNET_SYSERR; - } - line = ch->line; GNUNET_CADET_receive_done (channel); switch (ch->status) { + case CS_CALLEE_INIT: case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: GNUNET_break_op (0); @@ -1093,21 +1003,13 @@ handle_cadet_pickup_message (void *cls, } pick.header.size = htons (sizeof (pick)); pick.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP); + pick.cid = ch->cid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending PICKED UP message to client\n"); GNUNET_SERVER_notification_context_unicast (nc, line->client, &pick.header, GNUNET_NO); - ch->channel_unreliable = GNUNET_CADET_channel_create (cadet, - ch, - &ch->target, - GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO), - GNUNET_CADET_OPTION_DEFAULT); - if (NULL == ch->channel_unreliable) - { - GNUNET_break (0); - } return GNUNET_OK; } @@ -1124,30 +1026,26 @@ handle_cadet_pickup_message (void *cls, */ static int handle_cadet_suspend_message (void *cls, - struct GNUNET_CADET_Channel *channel, - void **channel_ctx, - const struct GNUNET_MessageHeader *message) + struct GNUNET_CADET_Channel *channel, + void **channel_ctx, + const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; - struct Line *line; + struct Line *line = ch->line; struct ClientPhoneSuspendMessage suspend; - if (NULL == ch) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "SUSPEND message received for non-existing line, dropping channel.\n"); - return GNUNET_SYSERR; - } - line = ch->line; + GNUNET_CADET_receive_done (channel); suspend.header.size = htons (sizeof (suspend)); suspend.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); suspend.cid = ch->cid; - GNUNET_CADET_receive_done (channel); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Suspending channel CID: %u(%u:%u)\n", - ch->cid, ch->remote_line, line->local_line); + "Suspending channel CID: %u\n", + ch->cid); switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break_op (0); + break; case CS_CALLEE_RINGING: GNUNET_break_op (0); break; @@ -1212,6 +1110,9 @@ handle_cadet_resume_message (void *cls, } switch (ch->status) { + case CS_CALLEE_INIT: + GNUNET_break (0); + break; case CS_CALLEE_RINGING: GNUNET_break (0); break; @@ -1249,86 +1150,38 @@ handle_cadet_resume_message (void *cls, */ static int handle_cadet_audio_message (void *cls, - struct GNUNET_CADET_Channel *channel, - void **channel_ctx, - const struct GNUNET_MessageHeader *message) + struct GNUNET_CADET_Channel *channel, + void **channel_ctx, + const struct GNUNET_MessageHeader *message) { - const struct CadetAudioMessage *msg; struct Channel *ch = *channel_ctx; - struct Line *line; - struct GNUNET_PeerIdentity sender; + const struct CadetAudioMessage *msg; size_t msize = ntohs (message->size) - sizeof (struct CadetAudioMessage); - char buf[msize + sizeof (struct ClientAudioMessage)]; + char buf[msize + sizeof (struct ClientAudioMessage)] GNUNET_ALIGN; struct ClientAudioMessage *cam; - const union GNUNET_CADET_ChannelInfo *info; msg = (const struct CadetAudioMessage *) message; - if (NULL == ch) + GNUNET_CADET_receive_done (channel); + if ( (GNUNET_YES == ch->suspended_local) || + (GNUNET_YES == ch->suspended_remote) ) { - info = GNUNET_CADET_channel_get_info (channel, - GNUNET_CADET_OPTION_PEER); - if (NULL == info) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - sender = info->peer; - for (line = lines_head; NULL != line; line = line->next) - if (line->local_line == ntohl (msg->remote_line)) - { - for (ch = line->channel_head; NULL != ch; ch = ch->next) - { - if ( (CS_CALLEE_CONNECTED == ch->status) && - (0 == memcmp (&ch->target, - &sender, - sizeof (struct GNUNET_PeerIdentity))) && - (NULL == ch->channel_unreliable) && - (ch->remote_line == ntohl (msg->source_line)) ) - break; - } - break; - } - if (NULL == line) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received %u bytes of AUDIO data for non-existing line %u, dropping.\n", - (unsigned int) msize, - ntohl (msg->remote_line)); - return GNUNET_SYSERR; - } - if (NULL == ch) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received %u bytes of AUDIO data for unknown sender.\n", - (unsigned int) msize); - return GNUNET_SYSERR; - } - if ((GNUNET_YES == ch->suspended_local) || (GNUNET_YES == ch->suspended_remote)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received %u bytes of AUDIO data on suspended channel CID %u:(%u:%u); dropping\n", - (unsigned int) msize, - ch->cid, - ch->remote_line, - line->local_line); - GNUNET_CADET_receive_done (channel); - return GNUNET_OK; - } - ch->channel_unreliable = channel; - *channel_ctx = ch; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received %u bytes of AUDIO data on suspended channel CID %u; dropping\n", + (unsigned int) msize, + ch->cid); + return GNUNET_OK; } - GNUNET_CADET_receive_done (channel); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Forwarding %u bytes of AUDIO data to client CID %u:(%u:%u)\n", + "Forwarding %u bytes of AUDIO data to client CID %u\n", (unsigned int) msize, - ch->cid, - ch->remote_line, - ch->line->local_line); + ch->cid); cam = (struct ClientAudioMessage *) buf; cam->header.size = htons (sizeof (buf)); cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); cam->cid = ch->cid; - GNUNET_memcpy (&cam[1], &msg[1], msize); + GNUNET_memcpy (&cam[1], + &msg[1], + msize); GNUNET_SERVER_notification_context_unicast (nc, ch->line->client, &cam->header, @@ -1341,13 +1194,12 @@ handle_cadet_audio_message (void *cls, * Method called whenever another peer has added us to a channel * the other peer initiated. * - * @param cls closure + * @param cls the `struct Line` receiving a connection * @param channel new handle to the channel * @param initiator peer that started the channel * @param port port * @param options channel option flags - * @return initial channel context for the channel; - * (can be NULL -- that's not an error) + * @return initial channel context for the channel */ static void * inbound_channel (void *cls, @@ -1356,10 +1208,22 @@ inbound_channel (void *cls, const struct GNUNET_HashCode *port, enum GNUNET_CADET_ChannelOption options) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Received incoming Cadet channel on port %s\n"), - GNUNET_h2s (port)); - return NULL; + struct Line *line = cls; + struct Channel *ch; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received incoming cadet channel on line %p\n", + line); + ch = GNUNET_new (struct Channel); + ch->status = CS_CALLEE_INIT; + ch->line = line; + ch->channel = channel; + ch->mq = GNUNET_CADET_mq_create (ch->channel); + ch->cid = line->cid_gen++; + GNUNET_CONTAINER_DLL_insert (line->channel_head, + line->channel_tail, + ch); + return ch; } @@ -1379,63 +1243,53 @@ inbound_end (void *cls, void *channel_ctx) { struct Channel *ch = channel_ctx; - struct Line *line; + struct Line *line = ch->line; struct ClientPhoneHangupMessage hup; if (NULL == ch) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cadet channel destroyed, but channel is unknown to us\n"); - return; - } - line = ch->line; - if (ch->channel_unreliable == channel) - { - if (NULL != ch->unreliable_mth) - { - GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth); - ch->unreliable_mth = NULL; - } - ch->channel_unreliable = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Unreliable channel destroyed\n"); - return; - } - if (ch->channel_reliable != channel) - { - /* recursive call, I'm the one destroying 'ch' right now */ + GNUNET_break (0); return; } - ch->channel_reliable = NULL; - + GNUNET_assert (channel == ch->channel); + ch->channel = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cadet channel destroyed by Cadet in state %d\n", + "Channel destroyed by CADET in state %d\n", ch->status); hup.header.size = htons (sizeof (hup)); hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); hup.cid = ch->cid; switch (ch->status) { + case CS_CALLEE_INIT: + break; case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: - GNUNET_SERVER_notification_context_unicast (nc, - line->client, - &hup.header, - GNUNET_NO); + if (NULL != line) + GNUNET_SERVER_notification_context_unicast (nc, + line->client, + &hup.header, + GNUNET_NO); break; case CS_CALLEE_SHUTDOWN: break; case CS_CALLER_CALLING: case CS_CALLER_CONNECTED: - GNUNET_SERVER_notification_context_unicast (nc, - line->client, - &hup.header, - GNUNET_NO); + if (NULL != line) + GNUNET_SERVER_notification_context_unicast (nc, + line->client, + &hup.header, + GNUNET_NO); break; case CS_CALLER_SHUTDOWN: break; } destroy_line_cadet_channels (ch); + if (NULL != line) + GNUNET_CONTAINER_DLL_remove (line->channel_head, + line->channel_tail, + ch); + GNUNET_free (ch); } @@ -1450,45 +1304,83 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct Line *line; + struct Channel *ch; + struct Channel *chn; if (NULL == client) return; - line = GNUNET_SERVER_client_get_user_context (client, struct Line); + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); if (NULL == line) return; - GNUNET_SERVER_client_set_user_context (client, NULL); + GNUNET_SERVER_client_set_user_context (client, + NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, closing line\n"); - GNUNET_CONTAINER_DLL_remove (lines_head, - lines_tail, - line); - while (NULL != line->channel_head) - destroy_line_cadet_channels (line->channel_head); + if (NULL != line->port) + { + GNUNET_CADET_close_port (line->port); + line->port = NULL; + } + for (ch = line->channel_head; NULL != ch; ch = chn) + { + chn = ch->next; + ch->line = NULL; + destroy_line_cadet_channels (ch); + } GNUNET_free (line); } /** - * Shutdown nicely + * Function to register a phone. * * @param cls closure, NULL + * @param client the client from which the message is + * @param message the message from the client */ static void -do_shutdown (void *cls) +handle_client_register_message (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { + const struct ClientPhoneRegisterMessage *msg; struct Line *line; - struct Channel *ch; - while (NULL != (line = lines_head)) + msg = (const struct ClientPhoneRegisterMessage *) message; + line = GNUNET_SERVER_client_get_user_context (client, + struct Line); + if (NULL != line) { - while (NULL != (ch = line->channel_head)) - destroy_line_cadet_channels (ch); - GNUNET_CONTAINER_DLL_remove (lines_head, - lines_tail, - line); - GNUNET_SERVER_client_set_user_context (line->client, NULL); - GNUNET_free (line); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); + return; } + line = GNUNET_new (struct Line); + line->client = client; + GNUNET_SERVER_notification_context_add (nc, + client); + GNUNET_SERVER_client_set_user_context (client, + line); + line->line_port = msg->line_port; + line->port = GNUNET_CADET_open_port (cadet, + &msg->line_port, + &inbound_channel, + line); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); +} + + +/** + * Shutdown nicely + * + * @param cls closure, NULL + */ +static void +do_shutdown (void *cls) +{ if (NULL != cadet) { GNUNET_CADET_disconnect (cadet); @@ -1564,26 +1456,19 @@ run (void *cls, GNUNET_CRYPTO_get_peer_identity (cfg, &my_identity)); cadet = GNUNET_CADET_connect (cfg, - NULL, - &inbound_end, - cadet_handlers); - + NULL, + &inbound_end, + cadet_handlers); if (NULL == cadet) { GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } - - GNUNET_CADET_open_port (cadet, - GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL), - &inbound_channel, NULL); - GNUNET_CADET_open_port (cadet, - GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO), - &inbound_channel, NULL); - - nc = GNUNET_SERVER_notification_context_create (server, 16); - GNUNET_SERVER_add_handlers (server, server_handlers); + nc = GNUNET_SERVER_notification_context_create (server, + 16); + GNUNET_SERVER_add_handlers (server, + server_handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); diff --git a/src/conversation/plugin_gnsrecord_conversation.c b/src/conversation/plugin_gnsrecord_conversation.c index f68377a64..ecdcb2057 100644 --- a/src/conversation/plugin_gnsrecord_conversation.c +++ b/src/conversation/plugin_gnsrecord_conversation.c @@ -49,6 +49,8 @@ conversation_value_to_string (void *cls, const void *data, size_t data_size) { + char *s; + switch (type) { case GNUNET_GNSRECORD_TYPE_PHONE: @@ -63,10 +65,14 @@ conversation_value_to_string (void *cls, if (0 != ntohl (pr->version)) return NULL; pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key); + s = GNUNET_STRINGS_data_to_string_alloc (&pr->line_port, + sizeof (struct GNUNET_HashCode)); + GNUNET_asprintf (&ret, - "%u-%s", - ntohl (pr->line), + "%s-%s", + s, pkey); + GNUNET_free (s); GNUNET_free (pkey); return ret; } @@ -89,10 +95,10 @@ conversation_value_to_string (void *cls, */ static int conversation_string_to_value (void *cls, - uint32_t type, - const char *s, - void **data, - size_t *data_size) + uint32_t type, + const char *s, + void **data, + size_t *data_size) { if (NULL == s) return GNUNET_SYSERR; @@ -101,16 +107,16 @@ conversation_string_to_value (void *cls, case GNUNET_GNSRECORD_TYPE_PHONE: { struct GNUNET_CONVERSATION_PhoneRecord *pr; - unsigned int line; + char line_port[128]; const char *dash; struct GNUNET_PeerIdentity peer; if ( (NULL == (dash = strchr (s, '-'))) || - (1 != sscanf (s, "%u-", &line)) || + (1 != sscanf (s, "%128s-", line_port)) || (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1, - strlen (dash + 1), - &peer.public_key)) ) + strlen (dash + 1), + &peer.public_key)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PHONE record `%s'\n"), @@ -118,8 +124,20 @@ conversation_string_to_value (void *cls, return GNUNET_SYSERR; } pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord); - pr->version = htonl (0); - pr->line = htonl ((uint32_t) line); + pr->version = htonl (1); + pr->reserved = htonl (0); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (line_port, + strlen (line_port), + &pr->line_port, + sizeof (struct GNUNET_HashCode))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to parse PHONE record `%s'\n"), + s); + GNUNET_free (pr); + return GNUNET_SYSERR; + } pr->peer = peer; *data = pr; *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord); @@ -153,7 +171,7 @@ static struct { */ static uint32_t conversation_typename_to_number (void *cls, - const char *gns_typename) + const char *gns_typename) { unsigned int i; @@ -174,7 +192,7 @@ conversation_typename_to_number (void *cls, */ static const char * conversation_number_to_typename (void *cls, - uint32_t type) + uint32_t type) { unsigned int i; diff --git a/src/conversation/test_conversation.conf b/src/conversation/test_conversation.conf index 421a62682..46ea95d52 100644 --- a/src/conversation/test_conversation.conf +++ b/src/conversation/test_conversation.conf @@ -1,6 +1,7 @@ +@INLINE@ ../../contrib/no_forcestart.conf + [conversation] LINE=1 [nse] WORKBITS = 0 - diff --git a/src/conversation/test_conversation_api.c b/src/conversation/test_conversation_api.c index fd9327805..0bf173d2b 100644 --- a/src/conversation/test_conversation_api.c +++ b/src/conversation/test_conversation_api.c @@ -317,7 +317,9 @@ caller_event_handler (void *cls, { case GNUNET_CONVERSATION_EC_CALLER_SUSPEND: case GNUNET_CONVERSATION_EC_CALLER_RESUME: - fprintf (stderr, "Unexpected caller code: %d\n", code); + fprintf (stderr, + "Unexpected caller code: %d\n", + code); break; } } diff --git a/src/conversation/test_conversation_api_reject.c b/src/conversation/test_conversation_api_reject.c index 5f1f836f7..9257764cf 100644 --- a/src/conversation/test_conversation_api_reject.c +++ b/src/conversation/test_conversation_api_reject.c @@ -147,7 +147,8 @@ end_test (void *cls) } if (NULL != phone) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting from PHONE service.\n"); GNUNET_CONVERSATION_phone_destroy (phone); phone = NULL; } @@ -214,8 +215,11 @@ call_event_handler (void *cls, case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL: case GNUNET_CONVERSATION_EC_CALL_SUSPENDED: case GNUNET_CONVERSATION_EC_CALL_RESUMED: + fprintf (stderr, "Unexpected call code: %d\n", code); + break; case GNUNET_CONVERSATION_EC_CALL_ERROR: fprintf (stderr, "Unexpected call code: %d\n", code); + call = NULL; break; } } -- cgit v1.2.3