Use more-or-equal (some machines are fast enough)
[oweals/gnunet.git] / src / conversation / gnunet-service-conversation.c
index 6e79ad3dddbdaf53709a4002fc7a30503109b8b9..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:
@@ -469,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;
   }
 
@@ -482,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;
@@ -491,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,
@@ -540,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)
@@ -559,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);
@@ -569,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,
@@ -615,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)
@@ -634,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);
@@ -644,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,
@@ -701,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);
@@ -713,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));
@@ -753,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;
 }
 
@@ -798,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;
   }
 
@@ -819,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,
@@ -935,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,
@@ -1072,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);
@@ -1113,6 +1130,9 @@ handle_mesh_suspend_message (void *cls,
   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:
@@ -1239,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))
       {
@@ -1249,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);
@@ -1288,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)
  */
@@ -1295,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"),