*/
LS_CALLEE_CONNECTED,
+ /**
+ * We're in shutdown, sending hangup messages before cleaning up.
+ */
+ LS_CALLEE_SHUTDOWN,
+
/**
* We are waiting for the phone to be picked up.
*/
*/
struct GNUNET_PeerIdentity target;
+ /**
+ * Temporary buffer for audio data.
+ */
+ void *audio_data;
+
+ /**
+ * Number of bytes in @e audio_data.
+ */
+ size_t audio_size;
+
/**
* Our line number.
*/
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL != line)
{
+ GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
const struct GNUNET_MessageHeader *message)
{
const struct ClientPhonePickupMessage *msg;
+ struct GNUNET_MQ_Envelope *e;
+ struct MeshPhonePickupMessage *mppm;
+ const char *meta;
+ struct Line *line;
+ size_t len;
msg = (struct ClientPhonePickupMessage *) message;
- GNUNET_break (0); // FIXME
+ meta = (const char *) &msg[1];
+ len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage);
+ if ( (0 == len) ||
+ ('\0' != meta[len - 1]) )
+ {
+ meta = NULL;
+ len = 0;
+ }
+ line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+ if (NULL == line)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ 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;
+ break;
+ case LS_CALLEE_CONNECTED:
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ case LS_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:
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ line->status = LS_CALLEE_CONNECTED;
+ 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);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+/**
+ * Destroy the mesh tunnels of a line.
+ *
+ * @param line line to shutdown tunnels of
+ */
+static void
+destroy_line_mesh_tunnels (struct Line *line)
+{
+ if (NULL != line->reliable_mq)
+ {
+ GNUNET_MQ_destroy (line->reliable_mq);
+ line->reliable_mq = NULL;
+ }
+ if (NULL != line->unreliable_mth)
+ {
+ GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
+ line->unreliable_mth = NULL;
+ }
+ if (NULL != line->tunnel_unreliable)
+ {
+ GNUNET_MESH_tunnel_destroy (line->tunnel_unreliable);
+ line->tunnel_unreliable = NULL;
+ }
+ if (NULL != line->tunnel_reliable)
+ {
+ GNUNET_MESH_tunnel_destroy (line->tunnel_reliable);
+ line->tunnel_reliable = NULL;
+ }
+}
+
+
+/**
+ * We are done signalling shutdown to the other peer. Close down
+ * (or reset) the line.
+ *
+ * @param cls the `struct Line` to reset/terminate
+ */
+static void
+mq_done_finish_caller_shutdown (void *cls)
+{
+ struct Line *line = cls;
+
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ GNUNET_break (0);
+ break;
+ case LS_CALLEE_RINGING:
+ GNUNET_break (0);
+ break;
+ case LS_CALLEE_CONNECTED:
+ GNUNET_break (0);
+ 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;
+ break;
+ case LS_CALLER_CONNECTED:
+ line->status = LS_CALLER_SHUTDOWN;
+ break;
+ case LS_CALLER_SHUTDOWN:
+ destroy_line_mesh_tunnels (line);
+ GNUNET_CONTAINER_DLL_remove (lines_head,
+ lines_tail,
+ line);
+ GNUNET_free_non_null (line->audio_data);
+ GNUNET_free (line);
+ break;
+ }
+}
+
+
/**
* Function to handle a hangup request message from the client
*
const struct GNUNET_MessageHeader *message)
{
const struct ClientPhoneHangupMessage *msg;
+ struct GNUNET_MQ_Envelope *e;
+ struct MeshPhoneHangupMessage *mhum;
+ const char *meta;
+ struct Line *line;
+ size_t len;
msg = (struct ClientPhoneHangupMessage *) message;
- GNUNET_break (0); // FIXME
+ meta = (const char *) &msg[1];
+ len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage);
+ if ( (0 == len) ||
+ ('\0' != meta[len - 1]) )
+ {
+ meta = NULL;
+ len = 0;
+ }
+ line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+ if (NULL == line)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ case LS_CALLEE_RINGING:
+ line->status = LS_CALLEE_SHUTDOWN;
+ break;
+ case LS_CALLEE_CONNECTED:
+ line->status = LS_CALLEE_SHUTDOWN;
+ break;
+ case LS_CALLEE_SHUTDOWN:
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ case LS_CALLER_CALLING:
+ line->status = LS_CALLER_SHUTDOWN;
+ break;
+ case LS_CALLER_CONNECTED:
+ line->status = LS_CALLER_SHUTDOWN;
+ break;
+ case LS_CALLER_SHUTDOWN:
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+ e = GNUNET_MQ_msg_extra (mhum,
+ len,
+ GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP);
+ memcpy (&mhum[1], meta, len);
+ GNUNET_MQ_notify_sent (e,
+ &mq_done_finish_caller_shutdown,
+ line);
+ GNUNET_MQ_send (line->reliable_mq, e);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
line = GNUNET_SERVER_client_get_user_context (client, struct Line);
if (NULL != line)
{
+ GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
}
+/**
+ * Transmit audio data via unreliable mesh channel.
+ *
+ * @param cls the `struct Line` 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 @buf
+ */
+static size_t
+transmit_line_audio (void *cls,
+ size_t size,
+ void *buf)
+{
+ struct Line *line = cls;
+ struct MeshAudioMessage *mam = buf;
+
+ line->unreliable_mth = NULL;
+ if ( (NULL == buf) ||
+ (size < sizeof (struct MeshAudioMessage) + line->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;
+ return sizeof (struct MeshAudioMessage) + line->audio_size;
+}
+
+
/**
* Function to handle audio data from the client
*
const struct GNUNET_MessageHeader *message)
{
const struct ClientAudioMessage *msg;
+ struct Line *line;
+ size_t size;
+ size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
msg = (struct ClientAudioMessage *) message;
- GNUNET_break (0); // FIXME
+ line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+ if (NULL == line)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ case LS_CALLEE_RINGING:
+ case LS_CALLER_CALLING:
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ case LS_CALLEE_CONNECTED:
+ case LS_CALLER_CONNECTED:
+ /* common case, handled below */
+ break;
+ case LS_CALLEE_SHUTDOWN:
+ case LS_CALLER_SHUTDOWN:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Mesh audio channel in shutdown; audio data dropped\n");
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+ if (NULL == line->tunnel_unreliable)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Mesh audio channel not ready; audio data dropped\n"));
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+ if (NULL != line->unreliable_mth)
+ {
+ /* NOTE: we may want to not do this and instead combine the data */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Dropping previous audio data segment with %u bytes\n",
+ line->audio_size);
+ GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
+ GNUNET_free (line->audio_data);
+ }
+ line->audio_size = size;
+ line->audio_data = GNUNET_malloc (line->audio_size);
+ memcpy (line->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);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+/**
+ * We are done signalling shutdown to the other peer.
+ * Destroy the tunnel.
+ *
+ * @param cls the `struct GNUNET_MESH_tunnel` to destroy
+ */
+static void
+mq_done_destroy_tunnel (void *cls)
+{
+ struct GNUNET_MESH_Tunnel *tunnel = cls;
+
+ GNUNET_MESH_tunnel_destroy (tunnel);
+}
+
+
/**
* Function to handle a ring message incoming over mesh
*
_("No available phone for incoming call on line %u, sending BUSY signal\n"),
ntohl (msg->remote_line));
e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY);
+ GNUNET_MQ_notify_sent (e,
+ &mq_done_destroy_tunnel,
+ tunnel);
GNUNET_MQ_send (line->reliable_mq, e);
+ GNUNET_MESH_receive_done (tunnel); /* needed? */
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;
cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
cring.header.size = htons (sizeof (cring));
cring.reserved = htonl (0);
line->client,
&cring.header,
GNUNET_NO);
+ GNUNET_MESH_receive_done (tunnel);
return GNUNET_OK;
}
void **tunnel_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;
- GNUNET_break (0); // FIXME
+ 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)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "HANGUP message received for non-existing line, dropping tunnel.\n");
+ return GNUNET_SYSERR;
+ }
+ *tunnel_ctx = NULL;
+ switch (line->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);
+ break;
+ case LS_CALLEE_SHUTDOWN:
+ line->status = LS_CALLEE_LISTEN;
+ destroy_line_mesh_tunnels (line);
+ 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);
+ break;
+ case LS_CALLER_SHUTDOWN:
+ mq_done_finish_caller_shutdown (line);
+ 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_SERVER_notification_context_unicast (nc,
+ line->client,
+ &hup->header,
+ GNUNET_NO);
+ GNUNET_MESH_receive_done (tunnel);
return GNUNET_OK;
}
{
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;
- GNUNET_break (0); // FIXME
-
-
+ 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)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "PICKUP message received for non-existing line, dropping tunnel.\n");
+ return GNUNET_SYSERR;
+ }
+ GNUNET_MESH_receive_done (tunnel);
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ case LS_CALLEE_RINGING:
+ case LS_CALLEE_CONNECTED:
+ GNUNET_break_op (0);
+ destroy_line_mesh_tunnels (line);
+ line->status = LS_CALLEE_LISTEN;
+ return GNUNET_SYSERR;
+ case LS_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;
+ break;
+ case LS_CALLER_CONNECTED:
+ GNUNET_break_op (0);
+ return GNUNET_OK;
+ case LS_CALLER_SHUTDOWN:
+ GNUNET_break_op (0);
+ mq_done_finish_caller_shutdown (line);
+ return GNUNET_SYSERR;
+ }
+ pick = (struct ClientPhonePickupMessage *) buf;
+ pick->header.size = sizeof (buf);
+ pick->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
+ memcpy (&pick[1], metadata, len);
+ GNUNET_SERVER_notification_context_unicast (nc,
+ line->client,
+ &pick->header,
+ GNUNET_NO);
line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
line,
&line->target,
GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
GNUNET_YES,
GNUNET_NO);
-
-
return GNUNET_OK;
}
void **tunnel_ctx,
const struct GNUNET_MessageHeader *message)
{
- const struct MeshPhoneBusyMessage *msg;
-
- msg = (const struct MeshPhoneBusyMessage *) message;
- GNUNET_break (0); // FIXME
+ struct Line *line = *tunnel_ctx;
+ struct ClientPhoneBusyMessage busy;
+
+ if (NULL == line)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "HANGUP message received for non-existing line, dropping tunnel.\n");
+ return GNUNET_SYSERR;
+ }
+ busy.header.size = sizeof (busy);
+ busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY);
+ GNUNET_SERVER_notification_context_unicast (nc,
+ line->client,
+ &busy.header,
+ GNUNET_NO);
+ GNUNET_MESH_receive_done (tunnel);
+ *tunnel_ctx = NULL;
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ case LS_CALLEE_RINGING:
+ GNUNET_break_op (0);
+ break;
+ case LS_CALLEE_CONNECTED:
+ GNUNET_break_op (0);
+ break;
+ case LS_CALLEE_SHUTDOWN:
+ GNUNET_break_op (0);
+ break;
+ 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);
+ break;
+ case LS_CALLER_SHUTDOWN:
+ mq_done_finish_caller_shutdown (line);
+ break;
+ }
return GNUNET_OK;
}
const struct GNUNET_MessageHeader *message)
{
const struct MeshAudioMessage *msg;
+ struct Line *line = *tunnel_ctx;
+ struct GNUNET_PeerIdentity sender;
+ size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage);
+ char buf[msize + sizeof (struct ClientAudioMessage)];
+ struct ClientAudioMessage *cam;
msg = (const struct MeshAudioMessage *) message;
- GNUNET_break (0); // FIXME
+ if (NULL == line)
+ {
+ sender = *GNUNET_MESH_tunnel_get_info (tunnel,
+ GNUNET_MESH_OPTION_PEER)->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) )
+ break;
+ if (NULL == line)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received AUDIO data for non-existing line %u, dropping.\n",
+ ntohl (msg->remote_line));
+ return GNUNET_SYSERR;
+ }
+ line->tunnel_unreliable = tunnel;
+ *tunnel_ctx = line;
+ }
+ cam = (struct ClientAudioMessage *) buf;
+ cam->header.size = htons (sizeof (buf));
+ cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
+ memcpy (&cam[1], &msg[1], msize);
+ GNUNET_SERVER_notification_context_unicast (nc,
+ line->client,
+ &cam->header,
+ GNUNET_YES);
+ GNUNET_MESH_receive_done (tunnel);
return GNUNET_OK;
}
const struct GNUNET_PeerIdentity *initiator,
uint32_t port)
{
-
- GNUNET_break (0); // FIXME
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Received incoming tunnel on port %d\n"), port);
+ _("Received incoming tunnel on port %d\n"),
+ port);
return NULL;
}
const struct GNUNET_MESH_Tunnel *tunnel,
void *tunnel_ctx)
{
- GNUNET_break (0); // FIXME
+ struct Line *line = tunnel_ctx;
+ struct ClientPhoneHangupMessage hup;
+
+ if (NULL == line)
+ return;
+ if (line->tunnel_unreliable == tunnel)
+ {
+ line->tunnel_unreliable = NULL;
+ return;
+ }
+ hup.header.size = sizeof (hup);
+ hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
+ switch (line->status)
+ {
+ case LS_CALLEE_LISTEN:
+ GNUNET_break (0);
+ return;
+ case LS_CALLEE_RINGING:
+ case LS_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;
+ destroy_line_mesh_tunnels (line);
+ break;
+ case LS_CALLER_CALLING:
+ case LS_CALLER_CONNECTED:
+ GNUNET_SERVER_notification_context_unicast (nc,
+ line->client,
+ &hup.header,
+ GNUNET_NO);
+ destroy_line_mesh_tunnels (line);
+ GNUNET_CONTAINER_DLL_remove (lines_head,
+ lines_tail,
+ line);
+ GNUNET_free_non_null (line->audio_data);
+ GNUNET_free (line);
+ break;
+ case LS_CALLER_SHUTDOWN:
+ destroy_line_mesh_tunnels (line);
+ GNUNET_CONTAINER_DLL_remove (lines_head,
+ lines_tail,
+ line);
+ GNUNET_free (line);
+ break;
+ }
}
do_shutdown (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- GNUNET_break (0); // FIXME
if (NULL != mesh)
{
GNUNET_MESH_disconnect (mesh);