/*
This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
+ Copyright (C) 2013 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
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.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
* @file conversation/gnunet-service-conversation.c
#include "gnunet_applications.h"
#include "gnunet_constants.h"
#include "gnunet_signatures.h"
-#include "gnunet_mesh_service.h"
+#include "gnunet_cadet_service.h"
#include "gnunet_conversation_service.h"
#include "conversation.h"
#define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
+/**
+ * A line connects a local client with a cadet channel (or, if it is an
+ * open line, is waiting for a cadet channel).
+ */
+struct Line;
+
/**
* The possible connection status
*/
-enum LineStatus
+enum ChannelStatus
{
- /**
- * We are waiting for incoming calls.
- */
- LS_CALLEE_LISTEN,
-
/**
* Our phone is ringing, waiting for the client to pick up.
*/
- LS_CALLEE_RINGING,
+ CS_CALLEE_RINGING,
/**
* We are talking!
*/
- LS_CALLEE_CONNECTED,
+ CS_CALLEE_CONNECTED,
/**
* We're in shutdown, sending hangup messages before cleaning up.
*/
- LS_CALLEE_SHUTDOWN,
+ CS_CALLEE_SHUTDOWN,
/**
* We are waiting for the phone to be picked up.
*/
- LS_CALLER_CALLING,
+ CS_CALLER_CALLING,
/**
* We are talking!
*/
- LS_CALLER_CONNECTED,
+ CS_CALLER_CONNECTED,
/**
* We're in shutdown, sending hangup messages before cleaning up.
*/
- LS_CALLER_SHUTDOWN
+ CS_CALLER_SHUTDOWN
+
};
/**
- * A line connects a local client with a mesh tunnel (or, if it is an
- * open line, is waiting for a mesh tunnel).
+ * A `struct Channel` represents a cadet channel, which is a P2P
+ * connection to another conversation service. Multiple channels can
+ * be attached the the same `struct Line`, which represents a local
+ * client. We keep them in a linked list.
*/
-struct Line
+struct Channel
{
+
/**
- * Kept in a DLL.
+ * This is a DLL.
*/
- struct Line *next;
+ struct Channel *next;
/**
- * Kept in a DLL.
+ * This is a DLL.
*/
- struct Line *prev;
+ struct Channel *prev;
/**
- * Handle for the reliable tunnel (contol data)
+ * Line associated with the channel.
*/
- struct GNUNET_MESH_Tunnel *tunnel_reliable;
-
+ struct Line *line;
+
/**
- * Handle for unreliable tunnel (audio data)
+ * Handle for the reliable channel (contol data)
*/
- struct GNUNET_MESH_Tunnel *tunnel_unreliable;
+ struct GNUNET_CADET_Channel *channel_reliable;
/**
- * Transmit handle for pending audio messages
+ * Handle for unreliable channel (audio data)
*/
- struct GNUNET_MESH_TransmitHandle *unreliable_mth;
+ struct GNUNET_CADET_Channel *channel_unreliable;
/**
- * Message queue for control messages
+ * Transmit handle for pending audio messages
*/
- struct GNUNET_MQ_Handle *reliable_mq;
+ struct GNUNET_CADET_TransmitHandle *unreliable_mth;
/**
- * Handle to the line client.
+ * Message queue for control messages
*/
- struct GNUNET_SERVER_Client *client;
+ struct GNUNET_MQ_Handle *reliable_mq;
/**
* Target of the line, if we are the caller.
size_t audio_size;
/**
- * Our line number.
+ * Channel identifier.
*/
- uint32_t local_line;
+ uint32_t cid;
/**
* Remote line number.
/**
* Current status of this line.
- */
- enum LineStatus status;
+ */
+ enum ChannelStatus status;
+
+ /**
+ * #GNUNET_YES if the channel was suspended by the other peer.
+ */
+ int8_t suspended_remote;
+
+ /**
+ * #GNUNET_YES if the channel was suspended by the local client.
+ */
+ int8_t suspended_local;
+
+};
+
+
+/**
+ * A `struct Line` connects a local client with cadet channels.
+ */
+struct Line
+{
+ /**
+ * Kept in a DLL.
+ */
+ struct Line *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct Line *prev;
+
+ /**
+ * This is a DLL.
+ */
+ struct Channel *channel_head;
+
+ /**
+ * This is a DLL.
+ */
+ struct Channel *channel_tail;
+
+ /**
+ * Handle to the line client.
+ */
+ struct GNUNET_SERVER_Client *client;
+
+ /**
+ * Generator for channel IDs.
+ */
+ uint32_t cid_gen;
+
+ /**
+ * Our line number.
+ */
+ uint32_t local_line;
};
static struct GNUNET_SERVER_NotificationContext *nc;
/**
- * Handle for mesh
+ * Handle for cadet
*/
-static struct GNUNET_MESH_Handle *mesh;
+static struct GNUNET_CADET_Handle *cadet;
/**
* Identity of this peer.
const struct ClientPhoneRegisterMessage *msg;
struct Line *line;
- msg = (struct ClientPhoneRegisterMessage *) message;
+ msg = (const struct ClientPhoneRegisterMessage *) message;
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL != line)
{
GNUNET_CONTAINER_DLL_insert (lines_head,
lines_tail,
line);
- line->local_line = ntohl (msg->line);
+ line->local_line = ntohl (msg->line) & (~ (1 << 31));
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
{
const struct ClientPhonePickupMessage *msg;
struct GNUNET_MQ_Envelope *e;
- struct MeshPhonePickupMessage *mppm;
- const char *meta;
+ struct CadetPhonePickupMessage *mppm;
struct Line *line;
- size_t len;
+ struct Channel *ch;
- msg = (struct ClientPhonePickupMessage *) message;
- meta = (const char *) &msg[1];
- len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage);
- if ( (0 == len) ||
- ('\0' != meta[len - 1]) )
- {
- meta = NULL;
- len = 0;
- }
+ msg = (const struct ClientPhonePickupMessage *) message;
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL == line)
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- switch (line->status)
+ for (ch = line->channel_head; NULL != ch; ch = ch->next)
+ if (msg->cid == ch->cid)
+ break;
+ if (NULL == ch)
{
- case LS_CALLEE_LISTEN:
+ /* could have been destroyed asynchronously, ignore message */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Ignoring client's PICKUP message, caller has HUNG UP already\n");
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- break;
- case LS_CALLEE_RINGING:
- line->status = LS_CALLEE_CONNECTED;
+ "Channel %u not found\n",
+ msg->cid);
+ GNUNET_SERVER_receive_done (client, GNUNET_YES);
+ return;
+ }
+ switch (ch->status)
+ {
+ case CS_CALLEE_RINGING:
+ ch->status = CS_CALLEE_CONNECTED;
break;
- case LS_CALLEE_CONNECTED:
+ case CS_CALLEE_CONNECTED:
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
- case LS_CALLEE_SHUTDOWN:
+ case CS_CALLEE_SHUTDOWN:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Ignoring client's PICKUP message, line is in SHUTDOWN\n");
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
break;
- case LS_CALLER_CALLING:
- case LS_CALLER_CONNECTED:
- case LS_CALLER_SHUTDOWN:
+ case CS_CALLER_CALLING:
+ case CS_CALLER_CONNECTED:
+ case CS_CALLER_SHUTDOWN:
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- line->status = LS_CALLEE_CONNECTED;
+ GNUNET_break (CS_CALLEE_CONNECTED == ch->status);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending PICK_UP message to mesh with meta data `%s'\n",
- meta);
- e = GNUNET_MQ_msg_extra (mppm,
- len,
- GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP);
- memcpy (&mppm[1], meta, len);
- GNUNET_MQ_send (line->reliable_mq, e);
+ "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);
}
/**
- * Destroy the mesh tunnels of a line.
+ * Destroy a channel.
*
- * @param line line to shutdown tunnels of
+ * @param ch channel to destroy.
*/
static void
-destroy_line_mesh_tunnels (struct Line *line)
+destroy_line_cadet_channels (struct Channel *ch)
{
- struct GNUNET_MESH_Tunnel *t;
+ struct Line *line = ch->line;
+ struct GNUNET_CADET_Channel *t;
- if (NULL != line->reliable_mq)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Destroying cadet channels\n");
+ if (NULL != ch->reliable_mq)
{
- GNUNET_MQ_destroy (line->reliable_mq);
- line->reliable_mq = NULL;
+ GNUNET_MQ_destroy (ch->reliable_mq);
+ ch->reliable_mq = NULL;
}
- if (NULL != line->unreliable_mth)
+ if (NULL != ch->unreliable_mth)
{
- GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
- line->unreliable_mth = NULL;
+ GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
+ ch->unreliable_mth = NULL;
}
- if (NULL != (t = line->tunnel_unreliable))
+ if (NULL != (t = ch->channel_unreliable))
{
- line->tunnel_unreliable = NULL;
- GNUNET_MESH_tunnel_destroy (t);
+ ch->channel_unreliable = NULL;
+ GNUNET_CADET_channel_destroy (t);
}
- if (NULL != (t = line->tunnel_reliable))
+ if (NULL != (t = ch->channel_reliable))
{
- line->tunnel_reliable = NULL;
- GNUNET_MESH_tunnel_destroy (t);
+ ch->channel_reliable = NULL;
+ GNUNET_CADET_channel_destroy (t);
}
+ GNUNET_CONTAINER_DLL_remove (line->channel_head,
+ line->channel_tail,
+ ch);
+ GNUNET_free_non_null (ch->audio_data);
+ GNUNET_free (ch);
}
/**
* We are done signalling shutdown to the other peer. Close down
- * (or reset) the line.
+ * the channel.
*
- * @param cls the `struct Line` to reset/terminate
+ * @param cls the `struct Channel` to reset/terminate
*/
static void
mq_done_finish_caller_shutdown (void *cls)
{
- struct Line *line = cls;
+ struct Channel *ch = cls;
- switch (line->status)
+ switch (ch->status)
{
- case LS_CALLEE_LISTEN:
+ case CS_CALLEE_RINGING:
GNUNET_break (0);
break;
- case LS_CALLEE_RINGING:
+ case CS_CALLEE_CONNECTED:
GNUNET_break (0);
break;
- case LS_CALLEE_CONNECTED:
- GNUNET_break (0);
+ case CS_CALLEE_SHUTDOWN:
+ destroy_line_cadet_channels (ch);
break;
- case LS_CALLEE_SHUTDOWN:
- line->status = LS_CALLEE_LISTEN;
- destroy_line_mesh_tunnels (line);
- return;
- case LS_CALLER_CALLING:
- line->status = LS_CALLER_SHUTDOWN;
+ case CS_CALLER_CALLING:
+ GNUNET_break (0);
break;
- case LS_CALLER_CONNECTED:
- line->status = LS_CALLER_SHUTDOWN;
+ case CS_CALLER_CONNECTED:
+ GNUNET_break (0);
break;
- case LS_CALLER_SHUTDOWN:
- destroy_line_mesh_tunnels (line);
+ case CS_CALLER_SHUTDOWN:
+ destroy_line_cadet_channels (ch);
break;
- }
+ }
}
{
const struct ClientPhoneHangupMessage *msg;
struct GNUNET_MQ_Envelope *e;
- struct MeshPhoneHangupMessage *mhum;
- const char *meta;
+ struct CadetPhoneHangupMessage *mhum;
struct Line *line;
- size_t len;
+ struct Channel *ch;
- msg = (struct ClientPhoneHangupMessage *) message;
- meta = (const char *) &msg[1];
- len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage);
- if ( (0 == len) ||
- ('\0' != meta[len - 1]) )
- {
- meta = NULL;
- len = 0;
- }
+ msg = (const struct ClientPhoneHangupMessage *) message;
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL == line)
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- switch (line->status)
+ for (ch = line->channel_head; NULL != ch; ch = ch->next)
+ if (msg->cid == ch->cid)
+ break;
+ if (NULL == ch)
{
- case LS_CALLEE_LISTEN:
- GNUNET_break (0);
+ /* 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);
return;
- case LS_CALLEE_RINGING:
- line->status = LS_CALLEE_SHUTDOWN;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received HANGUP for channel %u which is in state %d\n",
+ msg->cid,
+ ch->status);
+ switch (ch->status)
+ {
+ case CS_CALLEE_RINGING:
+ ch->status = CS_CALLEE_SHUTDOWN;
break;
- case LS_CALLEE_CONNECTED:
- line->status = LS_CALLEE_SHUTDOWN;
+ case CS_CALLEE_CONNECTED:
+ ch->status = CS_CALLEE_SHUTDOWN;
break;
- case LS_CALLEE_SHUTDOWN:
- GNUNET_break (0);
+ case CS_CALLEE_SHUTDOWN:
+ /* maybe the other peer closed asynchronously... */
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
- case LS_CALLER_CALLING:
- line->status = LS_CALLER_SHUTDOWN;
+ case CS_CALLER_CALLING:
+ ch->status = CS_CALLER_SHUTDOWN;
break;
- case LS_CALLER_CONNECTED:
- line->status = LS_CALLER_SHUTDOWN;
+ case CS_CALLER_CONNECTED:
+ ch->status = CS_CALLER_SHUTDOWN;
break;
- case LS_CALLER_SHUTDOWN:
- GNUNET_break (0);
+ case CS_CALLER_SHUTDOWN:
+ /* maybe the other peer closed asynchronously... */
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending HANG_UP message via mesh with meta data `%s'\n",
- meta);
- e = GNUNET_MQ_msg_extra (mhum,
- len,
- GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP);
- memcpy (&mhum[1], meta, len);
+ "Sending HANG_UP message via cadet\n");
+ e = GNUNET_MQ_msg (mhum,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
GNUNET_MQ_notify_sent (e,
&mq_done_finish_caller_shutdown,
- line);
- GNUNET_MQ_send (line->reliable_mq, e);
+ ch);
+ GNUNET_MQ_send (ch->reliable_mq, e);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Function to handle a suspend request message from the client
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_suspend_message (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct ClientPhoneSuspendMessage *msg;
+ struct GNUNET_MQ_Envelope *e;
+ struct CadetPhoneSuspendMessage *mhum;
+ struct Line *line;
+ struct Channel *ch;
+
+ msg = (const struct ClientPhoneSuspendMessage *) 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;
+ }
+ for (ch = line->channel_head; NULL != ch; ch = ch->next)
+ if (msg->cid == ch->cid)
+ break;
+ 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);
+ return;
+ }
+ if (GNUNET_YES == ch->suspended_local)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received SUSPEND for channel %u which is in state %d\n",
+ msg->cid,
+ ch->status);
+ switch (ch->status)
+ {
+ case CS_CALLEE_RINGING:
+ GNUNET_break (0);
+ 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);
+ return;
+ case CS_CALLER_CALLING:
+ GNUNET_break (0);
+ 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);
+ 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);
}
/**
- * Function to handle call request the client
+ * Function to handle a resume request message from the client
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_resume_message (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct ClientPhoneResumeMessage *msg;
+ struct GNUNET_MQ_Envelope *e;
+ struct CadetPhoneResumeMessage *mhum;
+ struct Line *line;
+ struct Channel *ch;
+
+ msg = (const struct ClientPhoneResumeMessage *) 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;
+ }
+ for (ch = line->channel_head; NULL != ch; ch = ch->next)
+ if (msg->cid == ch->cid)
+ break;
+ 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);
+ return;
+ }
+ if (GNUNET_YES != ch->suspended_local)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received RESUME for channel %u which is in state %d\n",
+ msg->cid,
+ ch->status);
+ switch (ch->status)
+ {
+ case CS_CALLEE_RINGING:
+ GNUNET_break (0);
+ 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);
+ return;
+ case CS_CALLER_CALLING:
+ GNUNET_break (0);
+ 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);
+ 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);
+}
+
+
+/**
+ * Function to handle call request from the client
*
* @param cls closure, NULL
* @param client the client from which the message is
{
const struct ClientCallMessage *msg;
struct Line *line;
+ struct Channel *ch;
struct GNUNET_MQ_Envelope *e;
- struct MeshPhoneRingMessage *ring;
+ struct CadetPhoneRingMessage *ring;
- msg = (struct ClientCallMessage *) message;
+ msg = (const struct ClientCallMessage *) message;
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL != line)
{
}
line = GNUNET_new (struct Line);
line->client = client;
+ line->local_line = (local_line_cnt++) | (1 << 31);
GNUNET_SERVER_client_set_user_context (client, line);
GNUNET_SERVER_notification_context_add (nc, client);
- line->target = msg->target;
GNUNET_CONTAINER_DLL_insert (lines_head,
lines_tail,
line);
- line->remote_line = ntohl (msg->line);
- line->status = LS_CALLER_CALLING;
- line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh,
- line,
+ 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,
GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
- GNUNET_NO,
- GNUNET_YES);
- line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
- line->local_line = local_line_cnt++;
- e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
+ 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_EccPublicSignKey));
- GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id,
- &ring->caller_id);
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id,
+ &ring->caller_id);
ring->remote_line = msg->line;
- ring->source_line = line->local_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));
- GNUNET_CRYPTO_ecc_sign (&msg->caller_id,
- &ring->purpose,
- &ring->signature);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id,
+ &ring->purpose,
+ &ring->signature));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending RING message via mesh\n");
- GNUNET_MQ_send (line->reliable_mq, e);
+ "Sending RING message via cadet\n");
+ GNUNET_MQ_send (ch->reliable_mq, e);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
/**
- * Transmit audio data via unreliable mesh channel.
+ * Transmit audio data via unreliable cadet channel.
*
- * @param cls the `struct Line` we are transmitting for
+ * @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
size_t size,
void *buf)
{
- struct Line *line = cls;
- struct MeshAudioMessage *mam = buf;
-
- line->unreliable_mth = NULL;
+ struct Channel *ch = cls;
+ struct CadetAudioMessage *mam = buf;
+
+ ch->unreliable_mth = NULL;
if ( (NULL == buf) ||
- (size < sizeof (struct MeshAudioMessage) + line->audio_size) )
+ (size < sizeof (struct CadetAudioMessage) + ch->audio_size) )
{
/* eh, other error handling? */
return 0;
}
- mam->header.size = htons (sizeof (struct MeshAudioMessage) + line->audio_size);
- mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO);
- mam->remote_line = htonl (line->remote_line);
- memcpy (&mam[1], line->audio_data, line->audio_size);
- GNUNET_free (line->audio_data);
- line->audio_data = NULL;
+ 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);
+ 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 via mesh\n",
- line->audio_size);
- return sizeof (struct MeshAudioMessage) + line->audio_size;
+ "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;
}
{
const struct ClientAudioMessage *msg;
struct Line *line;
+ struct Channel *ch;
size_t size;
size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
- msg = (struct ClientAudioMessage *) message;
+ msg = (const struct ClientAudioMessage *) message;
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL == line)
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- switch (line->status)
+ for (ch = line->channel_head; NULL != ch; ch = ch->next)
+ if (msg->cid == ch->cid)
+ break;
+ if (NULL == ch)
{
- case LS_CALLEE_LISTEN:
- /* could be OK if the line just was closed by the other side */
+ /* could have been destroyed asynchronously, ignore message */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Audio data dropped, channel is down\n");
+ "Channel %u not found\n",
+ msg->cid);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
- break;
- case LS_CALLEE_RINGING:
- case LS_CALLER_CALLING:
+ return;
+ }
+
+ switch (ch->status)
+ {
+ case CS_CALLEE_RINGING:
+ case CS_CALLER_CALLING:
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
- case LS_CALLEE_CONNECTED:
- case LS_CALLER_CONNECTED:
+ case CS_CALLEE_CONNECTED:
+ case CS_CALLER_CONNECTED:
/* common case, handled below */
break;
- case LS_CALLEE_SHUTDOWN:
- case LS_CALLER_SHUTDOWN:
+ case CS_CALLEE_SHUTDOWN:
+ case CS_CALLER_SHUTDOWN:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Mesh audio channel in shutdown; audio data dropped\n");
+ "Cadet audio channel in shutdown; audio data dropped\n");
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- if (NULL == line->tunnel_unreliable)
+ 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,
- _("Mesh audio channel not ready; audio data dropped\n"));
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ _("Cadet audio channel not ready; audio data dropped\n"));
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- if (NULL != line->unreliable_mth)
+ if (NULL != ch->unreliable_mth)
{
/* 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) line->audio_size);
- GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
- line->unreliable_mth = NULL;
- GNUNET_free (line->audio_data);
- line->audio_data = NULL;
+ (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;
}
- line->audio_size = size;
- line->audio_data = GNUNET_malloc (line->audio_size);
- memcpy (line->audio_data,
+ ch->audio_size = size;
+ ch->audio_data = GNUNET_malloc (ch->audio_size);
+ memcpy (ch->audio_data,
&msg[1],
size);
- line->unreliable_mth = GNUNET_MESH_notify_transmit_ready (line->tunnel_unreliable,
- GNUNET_NO,
- GNUNET_TIME_UNIT_FOREVER_REL,
- sizeof (struct MeshAudioMessage)
- + line->audio_size,
- &transmit_line_audio,
- line);
+ 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 tunnel.
+ * We are done signalling shutdown to the other peer.
+ * Destroy the channel.
*
- * @param cls the `struct GNUNET_MESH_tunnel` to destroy
+ * @param cls the `struct GNUNET_CADET_channel` to destroy
*/
static void
-mq_done_destroy_tunnel (void *cls)
+mq_done_destroy_channel (void *cls)
{
- struct GNUNET_MESH_Tunnel *tunnel = cls;
-
- GNUNET_MESH_tunnel_destroy (tunnel);
+ struct GNUNET_CADET_Channel *channel = cls;
+
+ GNUNET_CADET_channel_destroy (channel);
}
/**
- * Function to handle a ring message incoming over mesh
+ * Function to handle a ring message incoming over cadet
*
* @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
+ * @param channel the channel over which the message arrived
+ * @param channel_ctx the channel context, can be NULL
+ * or point to the `struct Channel`
* @param message the incoming message
* @return #GNUNET_OK
*/
static int
-handle_mesh_ring_message (void *cls,
- struct GNUNET_MESH_Tunnel *tunnel,
- void **tunnel_ctx,
+handle_cadet_ring_message (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ void **channel_ctx,
const struct GNUNET_MessageHeader *message)
{
- const struct MeshPhoneRingMessage *msg;
+ const struct CadetPhoneRingMessage *msg;
struct Line *line;
+ struct Channel *ch;
struct GNUNET_MQ_Envelope *e;
- struct MeshPhoneBusyMessage *busy;
+ struct CadetPhoneHangupMessage *hang_up;
struct ClientPhoneRingMessage cring;
-
- msg = (const struct MeshPhoneRingMessage *) message;
+ struct GNUNET_MQ_Handle *reliable_mq;
+
+ 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_EccPublicSignKey))) ||
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) ||
(GNUNET_OK !=
- GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
+ GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
&msg->purpose,
&msg->signature,
&msg->caller_id)) )
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- for (line = lines_head; NULL != line; line = line->next)
- if ( (line->local_line == ntohl (msg->remote_line)) &&
- (LS_CALLEE_LISTEN == line->status) )
+ 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 (NULL == line)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("No available phone for incoming call on line %u, sending BUSY signal\n"),
+ _("No available phone for incoming call on line %u, sending HANG_UP signal\n"),
ntohl (msg->remote_line));
- e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY);
+ e = GNUNET_MQ_msg (hang_up,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
GNUNET_MQ_notify_sent (e,
- &mq_done_destroy_tunnel,
- tunnel);
- GNUNET_MQ_send (line->reliable_mq, e);
- GNUNET_MESH_receive_done (tunnel); /* needed? */
+ &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;
}
- line->status = LS_CALLEE_RINGING;
- line->remote_line = ntohl (msg->source_line);
- line->tunnel_reliable = tunnel;
- line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
- *tunnel_ctx = line;
+ ch = GNUNET_new (struct Channel);
+ ch->line = line;
+ GNUNET_CONTAINER_DLL_insert (line->channel_head,
+ line->channel_tail,
+ ch);
+ 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.reserved = htonl (0);
+ cring.cid = ch->cid;
cring.caller_id = msg->caller_id;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending RING message to client\n");
+ "Sending RING message to client. CID %u:(%u, %u)\n",
+ ch->cid, ch->remote_line, line->local_line);
GNUNET_SERVER_notification_context_unicast (nc,
line->client,
&cring.header,
GNUNET_NO);
- GNUNET_MESH_receive_done (tunnel);
return GNUNET_OK;
}
/**
- * Function to handle a hangup message incoming over mesh
+ * Function to handle a hangup message incoming over cadet
*
* @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
+ * @param channel the channel over which the message arrived
+ * @param channel_ctx the channel context, can be NULL
+ * or point to the `struct Channel`
* @param message the incoming message
* @return #GNUNET_OK
*/
static int
-handle_mesh_hangup_message (void *cls,
- struct GNUNET_MESH_Tunnel *tunnel,
- void **tunnel_ctx,
+handle_cadet_hangup_message (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ void **channel_ctx,
const struct GNUNET_MessageHeader *message)
{
- struct Line *line = *tunnel_ctx;
- const struct MeshPhoneHangupMessage *msg;
- const char *reason;
- size_t len = ntohs (message->size) - sizeof (struct MeshPhoneHangupMessage);
- char buf[len + sizeof (struct ClientPhoneHangupMessage)];
- struct ClientPhoneHangupMessage *hup;
-
- msg = (const struct MeshPhoneHangupMessage *) message;
- len = ntohs (msg->header.size) - sizeof (struct MeshPhoneHangupMessage);
- reason = (const char *) &msg[1];
- if ( (0 == len) ||
- ('\0' != reason[len - 1]) )
- {
- reason = NULL;
- len = 0;
- }
- if (NULL == line)
+ struct Channel *ch = *channel_ctx;
+ struct Line *line;
+ struct ClientPhoneHangupMessage hup;
+ enum ChannelStatus status;
+
+ if (NULL == ch)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "HANGUP message received for non-existing line, dropping tunnel.\n");
+ "HANGUP message received for non-existing line, dropping channel.\n");
return GNUNET_SYSERR;
}
- *tunnel_ctx = NULL;
- switch (line->status)
+ line = ch->line;
+ *channel_ctx = NULL;
+ 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 LS_CALLEE_LISTEN:
- GNUNET_break (0);
- return GNUNET_SYSERR;
- case LS_CALLEE_RINGING:
- line->status = LS_CALLEE_LISTEN;
- destroy_line_mesh_tunnels (line);
- break;
- case LS_CALLEE_CONNECTED:
- line->status = LS_CALLEE_LISTEN;
- destroy_line_mesh_tunnels (line);
+ case CS_CALLEE_RINGING:
+ case CS_CALLEE_CONNECTED:
break;
- case LS_CALLEE_SHUTDOWN:
- line->status = LS_CALLEE_LISTEN;
- destroy_line_mesh_tunnels (line);
+ case CS_CALLEE_SHUTDOWN:
return GNUNET_OK;
- case LS_CALLER_CALLING:
- line->status = LS_CALLER_SHUTDOWN;
- mq_done_finish_caller_shutdown (line);
- break;
- case LS_CALLER_CONNECTED:
- line->status = LS_CALLER_SHUTDOWN;
- mq_done_finish_caller_shutdown (line);
+ case CS_CALLER_CALLING:
+ case CS_CALLER_CONNECTED:
break;
- case LS_CALLER_SHUTDOWN:
- mq_done_finish_caller_shutdown (line);
+ case CS_CALLER_SHUTDOWN:
return GNUNET_OK;
}
- hup = (struct ClientPhoneHangupMessage *) buf;
- hup->header.size = sizeof (buf);
- hup->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
- memcpy (&hup[1], reason, len);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending HANG UP message to client with reason `%s'\n",
- reason);
+ "Sending HANG UP message to client\n");
GNUNET_SERVER_notification_context_unicast (nc,
line->client,
- &hup->header,
+ &hup.header,
GNUNET_NO);
- GNUNET_MESH_receive_done (tunnel);
return GNUNET_OK;
}
/**
- * Function to handle a pickup message incoming over mesh
+ * Function to handle a pickup message incoming over cadet
*
* @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
+ * @param channel the channel over which the message arrived
+ * @param channel_ctx the channel context, can be NULL
+ * or point to the `struct Channel`
* @param message the incoming message
- * @return #GNUNET_OK
+ * @return #GNUNET_OK if message was OK,
+ * #GNUNET_SYSERR if message violated the protocol
*/
static int
-handle_mesh_pickup_message (void *cls,
- struct GNUNET_MESH_Tunnel *tunnel,
- void **tunnel_ctx,
+handle_cadet_pickup_message (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ void **channel_ctx,
const struct GNUNET_MessageHeader *message)
{
- const struct MeshPhonePickupMessage *msg;
- struct Line *line = *tunnel_ctx;
- const char *metadata;
- size_t len = ntohs (message->size) - sizeof (struct MeshPhonePickupMessage);
- char buf[len + sizeof (struct ClientPhonePickupMessage)];
- struct ClientPhonePickupMessage *pick;
-
- msg = (const struct MeshPhonePickupMessage *) message;
- len = ntohs (msg->header.size) - sizeof (struct MeshPhonePickupMessage);
- metadata = (const char *) &msg[1];
- if ( (0 == len) ||
- ('\0' != metadata[len - 1]) )
- {
- metadata = NULL;
- len = 0;
- }
- if (NULL == line)
+ struct Channel *ch = *channel_ctx;
+ struct Line *line;
+ struct ClientPhonePickupMessage pick;
+
+ if (NULL == ch)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "PICKUP message received for non-existing line, dropping tunnel.\n");
+ "PICKUP message received for non-existing channel, dropping channel.\n");
return GNUNET_SYSERR;
}
- GNUNET_MESH_receive_done (tunnel);
- switch (line->status)
+ line = ch->line;
+ GNUNET_CADET_receive_done (channel);
+ switch (ch->status)
{
- case LS_CALLEE_LISTEN:
- GNUNET_break (0);
- return GNUNET_SYSERR;
- case LS_CALLEE_RINGING:
- case LS_CALLEE_CONNECTED:
+ case CS_CALLEE_RINGING:
+ case CS_CALLEE_CONNECTED:
GNUNET_break_op (0);
- destroy_line_mesh_tunnels (line);
- line->status = LS_CALLEE_LISTEN;
+ destroy_line_cadet_channels (ch);
return GNUNET_SYSERR;
- case LS_CALLEE_SHUTDOWN:
+ case CS_CALLEE_SHUTDOWN:
GNUNET_break_op (0);
- line->status = LS_CALLEE_LISTEN;
- destroy_line_mesh_tunnels (line);
- break;
- case LS_CALLER_CALLING:
- line->status = LS_CALLER_CONNECTED;
+ destroy_line_cadet_channels (ch);
+ return GNUNET_SYSERR;
+ case CS_CALLER_CALLING:
+ ch->status = CS_CALLER_CONNECTED;
break;
- case LS_CALLER_CONNECTED:
+ case CS_CALLER_CONNECTED:
GNUNET_break_op (0);
return GNUNET_OK;
- case LS_CALLER_SHUTDOWN:
+ case CS_CALLER_SHUTDOWN:
GNUNET_break_op (0);
- mq_done_finish_caller_shutdown (line);
+ mq_done_finish_caller_shutdown (ch);
return GNUNET_SYSERR;
}
- pick = (struct ClientPhonePickupMessage *) buf;
- pick->header.size = sizeof (buf);
- pick->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP);
- memcpy (&pick[1], metadata, len);
+ 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 with metadata `%s'\n",
- metadata);
+ "Sending PICKED UP message to client\n");
GNUNET_SERVER_notification_context_unicast (nc,
line->client,
- &pick->header,
+ &pick.header,
GNUNET_NO);
- line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
- line,
- &line->target,
+ ch->channel_unreliable = GNUNET_CADET_channel_create (cadet,
+ ch,
+ &ch->target,
GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
- GNUNET_YES,
- GNUNET_NO);
- if (NULL == line->tunnel_unreliable)
+ GNUNET_CADET_OPTION_DEFAULT);
+ if (NULL == ch->channel_unreliable)
{
GNUNET_break (0);
- }
+ }
return GNUNET_OK;
}
/**
- * Function to handle a busy message incoming over mesh
+ * Function to handle a suspend message incoming over cadet
*
* @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
+ * @param channel the channel over which the message arrived
+ * @param channel_ctx the channel context, can be NULL
+ * or point to the `struct Channel`
* @param message the incoming message
* @return #GNUNET_OK
*/
static int
-handle_mesh_busy_message (void *cls,
- struct GNUNET_MESH_Tunnel *tunnel,
- void **tunnel_ctx,
- const struct GNUNET_MessageHeader *message)
+handle_cadet_suspend_message (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ void **channel_ctx,
+ const struct GNUNET_MessageHeader *message)
{
- struct Line *line = *tunnel_ctx;
- struct ClientPhoneBusyMessage busy;
+ struct Channel *ch = *channel_ctx;
+ struct Line *line;
+ struct ClientPhoneSuspendMessage suspend;
- if (NULL == line)
+ if (NULL == ch)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "HANGUP message received for non-existing line, dropping tunnel.\n");
+ "SUSPEND message received for non-existing line, dropping channel.\n");
return GNUNET_SYSERR;
}
- busy.header.size = sizeof (busy);
- busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY);
- GNUNET_MESH_receive_done (tunnel);
- *tunnel_ctx = NULL;
- switch (line->status)
+ line = ch->line;
+ 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);
+ switch (ch->status)
{
- case LS_CALLEE_LISTEN:
- GNUNET_break (0);
- return GNUNET_SYSERR;
- case LS_CALLEE_RINGING:
+ case CS_CALLEE_RINGING:
GNUNET_break_op (0);
break;
- case LS_CALLEE_CONNECTED:
- GNUNET_break_op (0);
+ case CS_CALLEE_CONNECTED:
+ ch->suspended_remote = GNUNET_YES;
break;
- case LS_CALLEE_SHUTDOWN:
+ case CS_CALLEE_SHUTDOWN:
+ return GNUNET_OK;
+ case CS_CALLER_CALLING:
GNUNET_break_op (0);
break;
- case LS_CALLER_CALLING:
+ case CS_CALLER_CONNECTED:
+ ch->suspended_remote = GNUNET_YES;
+ break;
+ case CS_CALLER_SHUTDOWN:
+ return GNUNET_OK;
+ }
+ GNUNET_SERVER_notification_context_unicast (nc,
+ line->client,
+ &suspend.header,
+ GNUNET_NO);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function to handle a resume message incoming over cadet
+ *
+ * @param cls closure, NULL
+ * @param channel the channel over which the message arrived
+ * @param channel_ctx the channel context, can be NULL
+ * or point to the `struct Channel`
+ * @param message the incoming message
+ * @return #GNUNET_OK
+ */
+static int
+handle_cadet_resume_message (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ void **channel_ctx,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct Channel *ch = *channel_ctx;
+ struct Line *line;
+ struct ClientPhoneResumeMessage resume;
+
+ if (NULL == ch)
+ {
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending BUSY message to client\n");
- GNUNET_SERVER_notification_context_unicast (nc,
- line->client,
- &busy.header,
- GNUNET_NO);
- line->status = LS_CALLER_SHUTDOWN;
- mq_done_finish_caller_shutdown (line);
+ "RESUME message received for non-existing line, dropping channel.\n");
+ return GNUNET_SYSERR;
+ }
+ line = ch->line;
+ resume.header.size = htons (sizeof (resume));
+ resume.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
+ resume.cid = ch->cid;
+ GNUNET_CADET_receive_done (channel);
+ if (GNUNET_YES != ch->suspended_remote)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "RESUME message received for non-suspended channel, dropping channel.\n");
+ return GNUNET_SYSERR;
+ }
+ switch (ch->status)
+ {
+ case CS_CALLEE_RINGING:
+ GNUNET_break (0);
break;
- case LS_CALLER_CONNECTED:
- GNUNET_break_op (0);
- line->status = LS_CALLER_SHUTDOWN;
- mq_done_finish_caller_shutdown (line);
+ case CS_CALLEE_CONNECTED:
+ ch->suspended_remote = GNUNET_NO;
break;
- case LS_CALLER_SHUTDOWN:
- GNUNET_break_op (0);
- mq_done_finish_caller_shutdown (line);
+ case CS_CALLEE_SHUTDOWN:
+ return GNUNET_OK;
+ case CS_CALLER_CALLING:
+ GNUNET_break (0);
break;
+ case CS_CALLER_CONNECTED:
+ ch->suspended_remote = GNUNET_NO;
+ break;
+ case CS_CALLER_SHUTDOWN:
+ return GNUNET_OK;
}
+ GNUNET_SERVER_notification_context_unicast (nc,
+ line->client,
+ &resume.header,
+ GNUNET_NO);
return GNUNET_OK;
}
/**
- * Function to handle an audio message incoming over mesh
+ * Function to handle an audio message incoming over cadet
*
* @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
+ * @param channel the channel over which the message arrived
+ * @param channel_ctx the channel context, can be NULL
+ * or point to the `struct Channel`
* @param message the incoming message
* @return #GNUNET_OK
*/
static int
-handle_mesh_audio_message (void *cls,
- struct GNUNET_MESH_Tunnel *tunnel,
- void **tunnel_ctx,
+handle_cadet_audio_message (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ void **channel_ctx,
const struct GNUNET_MessageHeader *message)
{
- const struct MeshAudioMessage *msg;
- struct Line *line = *tunnel_ctx;
+ const struct CadetAudioMessage *msg;
+ struct Channel *ch = *channel_ctx;
+ struct Line *line;
struct GNUNET_PeerIdentity sender;
- size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage);
+ size_t msize = ntohs (message->size) - sizeof (struct CadetAudioMessage);
char buf[msize + sizeof (struct ClientAudioMessage)];
struct ClientAudioMessage *cam;
- const union GNUNET_MESH_TunnelInfo *info;
-
- msg = (const struct MeshAudioMessage *) message;
- if (NULL == line)
+ const union GNUNET_CADET_ChannelInfo *info;
+
+ msg = (const struct CadetAudioMessage *) message;
+ if (NULL == ch)
{
- info = GNUNET_MESH_tunnel_get_info (tunnel,
- GNUNET_MESH_OPTION_PEER);
+ info = GNUNET_CADET_channel_get_info (channel,
+ GNUNET_CADET_OPTION_PEER);
if (NULL == info)
{
GNUNET_break (0);
- return GNUNET_OK;
+ return GNUNET_SYSERR;
}
sender = info->peer;
for (line = lines_head; NULL != line; line = line->next)
- if ( (line->local_line == ntohl (msg->remote_line)) &&
- (LS_CALLEE_CONNECTED == line->status) &&
- (0 == memcmp (&line->target,
- &sender,
- sizeof (struct GNUNET_PeerIdentity))) &&
- (NULL == line->tunnel_unreliable) )
+ 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 AUDIO data for non-existing line %u, dropping.\n",
+ "Received %u bytes of AUDIO data for non-existing line %u, dropping.\n",
+ (unsigned int) msize,
ntohl (msg->remote_line));
return GNUNET_SYSERR;
- }
- line->tunnel_unreliable = tunnel;
- *tunnel_ctx = line;
+ }
+ 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_CADET_receive_done (channel);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Forwarding %u bytes of AUDIO data to client\n",
- msize);
+ "Forwarding %u bytes of AUDIO data to client CID %u:(%u:%u)\n",
+ (unsigned int) msize,
+ ch->cid,
+ ch->remote_line,
+ ch->line->local_line);
cam = (struct ClientAudioMessage *) buf;
cam->header.size = htons (sizeof (buf));
cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
+ cam->cid = ch->cid;
memcpy (&cam[1], &msg[1], msize);
GNUNET_SERVER_notification_context_unicast (nc,
- line->client,
+ ch->line->client,
&cam->header,
GNUNET_YES);
- GNUNET_MESH_receive_done (tunnel);
return GNUNET_OK;
}
/**
- * Method called whenever another peer has added us to a tunnel
+ * Method called whenever another peer has added us to a channel
* the other peer initiated.
*
* @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
+ * @param channel new handle to the channel
+ * @param initiator peer that started the channel
* @param port port
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
+ * @param options channel option flags
+ * @return initial channel context for the channel;
+ * (can be NULL -- that's not an error)
*/
static void *
-inbound_tunnel (void *cls,
- struct GNUNET_MESH_Tunnel *tunnel,
- const struct GNUNET_PeerIdentity *initiator,
- uint32_t port)
+inbound_channel (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ const struct GNUNET_PeerIdentity *initiator,
+ uint32_t port, enum GNUNET_CADET_ChannelOption options)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Received incoming tunnel on port %u\n"),
+ _("Received incoming Cadet channel on port %u\n"),
(unsigned int) port);
return NULL;
}
/**
- * Function called whenever an inbound tunnel is destroyed. Should clean up
+ * Function called whenever an inbound channel is destroyed. Should clean up
* any associated state.
*
- * @param cls closure (set from #GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- * with the tunnel is stored
+ * @param cls closure (set from #GNUNET_CADET_connect)
+ * @param channel connection to the other end (henceforth invalid)
+ * @param channel_ctx place where local state associated
+ * with the channel is stored;
+ * may point to the `struct Channel`
*/
static void
inbound_end (void *cls,
- const struct GNUNET_MESH_Tunnel *tunnel,
- void *tunnel_ctx)
+ const struct GNUNET_CADET_Channel *channel,
+ void *channel_ctx)
{
- struct Line *line = tunnel_ctx;
+ struct Channel *ch = channel_ctx;
+ struct Line *line;
struct ClientPhoneHangupMessage hup;
- if (NULL == line)
+ if (NULL == ch)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cadet channel destroyed, but channel is unknown to us\n");
return;
- if (line->tunnel_unreliable == tunnel)
+ }
+ line = ch->line;
+ if (ch->channel_unreliable == channel)
{
- if (NULL != line->unreliable_mth)
+ if (NULL != ch->unreliable_mth)
{
- GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
- line->unreliable_mth = NULL;
+ GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
+ ch->unreliable_mth = NULL;
}
- line->tunnel_unreliable = NULL;
+ ch->channel_unreliable = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Unreliable channel destroyed\n");
return;
}
- if (line->tunnel_reliable != tunnel)
+ if (ch->channel_reliable != channel)
+ {
+ /* recursive call, I'm the one destroying 'ch' right now */
return;
- line->tunnel_reliable = NULL;
+ }
+ ch->channel_reliable = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Mesh tunnel destroyed by mesh\n");
- hup.header.size = sizeof (hup);
+ "Cadet 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);
- switch (line->status)
+ hup.cid = ch->cid;
+ switch (ch->status)
{
- case LS_CALLEE_LISTEN:
- GNUNET_break (0);
- break;
- case LS_CALLEE_RINGING:
- case LS_CALLEE_CONNECTED:
+ case CS_CALLEE_RINGING:
+ case CS_CALLEE_CONNECTED:
GNUNET_SERVER_notification_context_unicast (nc,
line->client,
&hup.header,
GNUNET_NO);
- line->status = LS_CALLEE_LISTEN;
break;
- case LS_CALLEE_SHUTDOWN:
- line->status = LS_CALLEE_LISTEN;
+ case CS_CALLEE_SHUTDOWN:
break;
- case LS_CALLER_CALLING:
- case LS_CALLER_CONNECTED:
+ case CS_CALLER_CALLING:
+ case CS_CALLER_CONNECTED:
GNUNET_SERVER_notification_context_unicast (nc,
line->client,
&hup.header,
GNUNET_NO);
break;
- case LS_CALLER_SHUTDOWN:
+ case CS_CALLER_SHUTDOWN:
break;
}
- destroy_line_mesh_tunnels (line);
+ destroy_line_cadet_channels (ch);
}
* @param client identification of the client
*/
static void
-handle_client_disconnect (void *cls,
+handle_client_disconnect (void *cls,
struct GNUNET_SERVER_Client *client)
{
struct Line *line;
GNUNET_CONTAINER_DLL_remove (lines_head,
lines_tail,
line);
- destroy_line_mesh_tunnels (line);
- GNUNET_free_non_null (line->audio_data);
+ while (NULL != line->channel_head)
+ destroy_line_cadet_channels (line->channel_head);
GNUNET_free (line);
}
/**
* Shutdown nicely
- *
+ *
* @param cls closure, NULL
- * @param tc the task context
*/
static void
-do_shutdown (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_shutdown (void *cls)
{
- if (NULL != mesh)
+ struct Line *line;
+ struct Channel *ch;
+
+ while (NULL != (line = lines_head))
+ {
+ 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);
+ }
+ if (NULL != cadet)
{
- GNUNET_MESH_disconnect (mesh);
- mesh = NULL;
+ GNUNET_CADET_disconnect (cadet);
+ cadet = NULL;
}
if (NULL != nc)
{
* @param c configuration
*/
static void
-run (void *cls,
+run (void *cls,
struct GNUNET_SERVER_Handle *server,
const struct GNUNET_CONFIGURATION_Handle *c)
{
sizeof (struct ClientPhoneRegisterMessage)},
{&handle_client_pickup_message, NULL,
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
- 0},
+ sizeof (struct ClientPhonePickupMessage) },
+ {&handle_client_suspend_message, NULL,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND,
+ sizeof (struct ClientPhoneSuspendMessage) },
+ {&handle_client_resume_message, NULL,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME,
+ sizeof (struct ClientPhoneResumeMessage) },
{&handle_client_hangup_message, NULL,
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
- 0},
+ sizeof (struct ClientPhoneHangupMessage) },
{&handle_client_call_message, NULL,
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
- 0},
+ sizeof (struct ClientCallMessage) },
{&handle_client_audio_message, NULL,
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
0},
{NULL, NULL, 0, 0}
};
- static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
- {&handle_mesh_ring_message,
- GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
- sizeof (struct MeshPhoneRingMessage)},
- {&handle_mesh_hangup_message,
- GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
- 0},
- {&handle_mesh_pickup_message,
- GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
- 0},
- {&handle_mesh_busy_message,
- GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
- sizeof (struct MeshPhoneBusyMessage)},
- {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
+ static struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
+ {&handle_cadet_ring_message,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING,
+ sizeof (struct CadetPhoneRingMessage)},
+ {&handle_cadet_hangup_message,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP,
+ sizeof (struct CadetPhoneHangupMessage)},
+ {&handle_cadet_pickup_message,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP,
+ sizeof (struct CadetPhonePickupMessage)},
+ {&handle_cadet_suspend_message,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND,
+ sizeof (struct CadetPhoneSuspendMessage)},
+ {&handle_cadet_resume_message,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME,
+ sizeof (struct CadetPhoneResumeMessage)},
+ {&handle_cadet_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO,
0},
{NULL, 0, 0}
};
- static uint32_t ports[] = {
+ static uint32_t ports[] = {
GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
- 0
+ 0
};
cfg = c;
GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_get_host_identity (cfg,
+ GNUNET_CRYPTO_get_peer_identity (cfg,
&my_identity));
- mesh = GNUNET_MESH_connect (cfg,
+ cadet = GNUNET_CADET_connect (cfg,
NULL,
- &inbound_tunnel,
- &inbound_end,
- mesh_handlers,
+ &inbound_channel,
+ &inbound_end,
+ cadet_handlers,
ports);
- if (NULL == mesh)
+ if (NULL == cadet)
{
GNUNET_break (0);
GNUNET_SCHEDULER_shutdown ();
}
nc = GNUNET_SERVER_notification_context_create (server, 16);
GNUNET_SERVER_add_handlers (server, server_handlers);
- GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &do_shutdown,
- NULL);
+ GNUNET_SERVER_disconnect_notify (server,
+ &handle_client_disconnect,
+ NULL);
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+ NULL);
}
* @return 0 ok, 1 on error
*/
int
-main (int argc,
+main (int argc,
char *const *argv)
{
return (GNUNET_OK ==
GNUNET_SERVICE_run (argc, argv,
- "conversation",
+ "conversation",
GNUNET_SERVICE_OPTION_NONE,
&run, NULL)) ? 0 : 1;
}