Use more-or-equal (some machines are fast enough)
[oweals/gnunet.git] / src / conversation / gnunet-service-conversation.c
index 36e8d5060f173dae7f47b0f107a80bdf8b068b1a..c50c688c21a98de047cc587e0f0584a99061fcf4 100644 (file)
@@ -325,6 +325,7 @@ 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);
     return;
   }
   switch (ch->status)
@@ -339,7 +340,6 @@ handle_client_pickup_message (void *cls,
   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 CS_CALLER_CALLING:
   case CS_CALLER_CONNECTED:
@@ -369,6 +369,8 @@ destroy_line_mesh_channels (struct Channel *ch)
   struct Line *line = ch->line;
   struct GNUNET_MESH_Channel *t;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Destroying mesh channels\n");
   if (NULL != ch->reliable_mq)
   {
     GNUNET_MQ_destroy (ch->reliable_mq);
@@ -467,6 +469,7 @@ 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);
     return;
   }
 
@@ -480,6 +483,7 @@ handle_client_hangup_message (void *cls,
     break;
   case CS_CALLEE_SHUTDOWN:
     /* maybe the other peer closed asynchronously... */
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   case CS_CALLER_CALLING:
     ch->status = CS_CALLER_SHUTDOWN;
@@ -489,6 +493,7 @@ handle_client_hangup_message (void *cls,
     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,
@@ -538,6 +543,7 @@ 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);
     return;
   }
   if (GNUNET_YES == ch->suspended_local)
@@ -557,6 +563,7 @@ handle_client_suspend_message (void *cls,
     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);
@@ -567,6 +574,7 @@ handle_client_suspend_message (void *cls,
     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,
@@ -613,6 +621,7 @@ 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);
     return;
   }
   if (GNUNET_YES != ch->suspended_local)
@@ -632,6 +641,7 @@ handle_client_resume_message (void *cls,
     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);
@@ -642,6 +652,7 @@ handle_client_resume_message (void *cls,
     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,
@@ -699,8 +710,7 @@ handle_client_call_message (void *cls,
                                                      ch,
                                                      &msg->target,
                                                      GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
-                                                     GNUNET_NO,
-                                                     GNUNET_YES);
+                                                     GNUNET_MESH_OPTION_RELIABLE);
   ch->reliable_mq = GNUNET_MESH_mq_create (ch->channel_reliable);
   e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
   ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
@@ -711,7 +721,7 @@ handle_client_call_message (void *cls,
   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));
@@ -751,12 +761,13 @@ transmit_line_audio (void *cls,
   mam->header.size = htons (sizeof (struct MeshAudioMessage) + ch->audio_size);
   mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_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",
-              ch->audio_size);
+              "Sending %u bytes of audio data from line %u to remote line %u via mesh\n",
+              ch->audio_size, ch->line->local_line, ch->remote_line);
   return sizeof (struct MeshAudioMessage) + ch->audio_size;
 }
 
@@ -796,6 +807,7 @@ handle_client_audio_message (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Channel %u not found\n",
                 msg->cid);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
 
@@ -817,6 +829,12 @@ handle_client_audio_message (void *cls,
     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,
@@ -933,13 +951,15 @@ handle_mesh_ring_message (void *cls,
   ch->channel_reliable = channel;
   ch->reliable_mq = GNUNET_MESH_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\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,
@@ -968,6 +988,7 @@ handle_mesh_hangup_message (void *cls,
   struct Channel *ch = *channel_ctx;
   struct Line *line;
   struct ClientPhoneHangupMessage hup;
+  enum ChannelStatus status;
 
   if (NULL == ch)
   {
@@ -977,11 +998,13 @@ handle_mesh_hangup_message (void *cls,
   }
   line = ch->line;
   *channel_ctx = NULL;
-  hup.header.size = sizeof (hup);
+  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_MESH_receive_done (channel);
   destroy_line_mesh_channels (ch);
-  switch (ch->status)
+  switch (status)
   {
   case CS_CALLEE_RINGING:
   case CS_CALLEE_CONNECTED:
@@ -1000,7 +1023,6 @@ handle_mesh_hangup_message (void *cls,
                                               line->client,
                                               &hup.header,
                                               GNUNET_NO);
-  GNUNET_MESH_receive_done (channel);
   return GNUNET_OK;
 }
 
@@ -1055,7 +1077,7 @@ handle_mesh_pickup_message (void *cls,
     mq_done_finish_caller_shutdown (ch);
     return GNUNET_SYSERR;
   }
-  pick.header.size = sizeof (pick);
+  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,
@@ -1068,8 +1090,7 @@ handle_mesh_pickup_message (void *cls,
                                                        ch,
                                                        &ch->target,
                                                        GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
-                                                       GNUNET_YES,
-                                                       GNUNET_NO);
+                                                       GNUNET_MESH_OPTION_DEFAULT);
   if (NULL == ch->channel_unreliable)
   {
     GNUNET_break (0);
@@ -1105,10 +1126,13 @@ handle_mesh_suspend_message (void *cls,
     return GNUNET_SYSERR;
   }
   line = ch->line;
-  suspend.header.size = sizeof (suspend);
+  suspend.header.size = htons (sizeof (suspend));
   suspend.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
   suspend.cid = ch->cid;
   GNUNET_MESH_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 CS_CALLEE_RINGING:
@@ -1163,7 +1187,7 @@ handle_mesh_resume_message (void *cls,
     return GNUNET_SYSERR;
   }
   line = ch->line;
-  resume.header.size = sizeof (resume);
+  resume.header.size = htons (sizeof (resume));
   resume.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
   resume.cid = ch->cid;
   GNUNET_MESH_receive_done (channel);
@@ -1235,7 +1259,7 @@ handle_mesh_audio_message (void *cls,
       GNUNET_break (0);
       return GNUNET_OK;
     }
-    sender = *(info->peer);
+    sender = info->peer;
     for (line = lines_head; NULL != line; line = line->next)
       if (line->local_line == ntohl (msg->remote_line))
       {
@@ -1245,30 +1269,47 @@ handle_mesh_audio_message (void *cls,
                (0 == memcmp (&ch->target,
                              &sender,
                              sizeof (struct GNUNET_PeerIdentity))) &&
-               (NULL == ch->channel_unreliable) )
+               (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",
+                  msize, ntohl (msg->remote_line));
+      return GNUNET_SYSERR;
+    }
     if (NULL == ch)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received AUDIO data for non-existing line %u, dropping.\n",
-                  ntohl (msg->remote_line));
+                  "Received %u bytes of AUDIO data for unknown sender.\n",
+                  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",
+                  msize, ch->cid, ch->remote_line, line->local_line);
+      return GNUNET_OK;
+    }
     ch->channel_unreliable = channel;
     *channel_ctx = ch;
   }
+  GNUNET_break (ch->line->local_line == ntohl (msg->remote_line));
   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",
+              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 (channel);
@@ -1284,6 +1325,7 @@ handle_mesh_audio_message (void *cls,
  * @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)
  */
@@ -1291,7 +1333,7 @@ static void *
 inbound_channel (void *cls,
                 struct GNUNET_MESH_Channel *channel,
                const struct GNUNET_PeerIdentity *initiator,
-                uint32_t port)
+                uint32_t port, enum GNUNET_MESH_ChannelOption options)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              _("Received incoming channel on port %u\n"),
@@ -1320,7 +1362,11 @@ inbound_end (void *cls,
   struct ClientPhoneHangupMessage hup;
 
   if (NULL == ch)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Mesh channel destroyed, but channel is unknown to us\n");
     return;
+  }
   line = ch->line;
   if (ch->channel_unreliable == channel)
   {
@@ -1330,16 +1376,21 @@ inbound_end (void *cls,
       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 */
     return;
+  }
   ch->channel_reliable = NULL;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Mesh channel destroyed by mesh in state %d\n",
               ch->status);
-  hup.header.size = sizeof (hup);
+  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)
@@ -1406,6 +1457,19 @@ static void
 do_shutdown (void *cls,
              const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct Line *line;
+  struct Channel *ch;
+
+  while (NULL != (line = lines_head))
+  {
+    while (NULL != (ch = line->channel_head))
+      destroy_line_mesh_channels (ch);
+    GNUNET_CONTAINER_DLL_remove (lines_head,
+                                 lines_tail,
+                                 line);
+    GNUNET_SERVER_client_set_user_context (line->client, (void *) NULL);
+    GNUNET_free (line);
+  }
   if (NULL != mesh)
   {
     GNUNET_MESH_disconnect (mesh);