allow client's payload to include more than one message
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new.c
index 6ba0df69e4d6bb9d96c3bd5c356c63730c78cfcb..78d4206f007b78ec9a7e9ec7c12731bf7932bba4 100644 (file)
@@ -292,7 +292,7 @@ GSC_bind (struct CadetClient *c,
                                                       ch,
                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Accepting incoming channel %s from %s on open port %s (%u)\n",
+       "Accepting incoming %s from %s on open port %s (%u)\n",
        GCCH_2s (ch),
        GCP_2s (dest),
        GNUNET_h2s (port),
@@ -310,6 +310,51 @@ GSC_bind (struct CadetClient *c,
 }
 
 
+/**
+ * Callback invoked on all peers to destroy all tunnels
+ * that may still exist.
+ *
+ * @param cls NULL
+ * @param pid identify of a peer
+ * @param value a `struct CadetPeer` that may still have a tunnel
+ * @return #GNUNET_OK (iterate over all entries)
+ */
+static int
+destroy_tunnels_now (void *cls,
+                     const struct GNUNET_PeerIdentity *pid,
+                     void *value)
+{
+  struct CadetPeer *cp = value;
+  struct CadetTunnel *t = GCP_get_tunnel (cp,
+                                          GNUNET_NO);
+
+  if (NULL != t)
+    GCT_destroy_tunnel_now (t);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Callback invoked on all peers to destroy all tunnels
+ * that may still exist.
+ *
+ * @param cls NULL
+ * @param pid identify of a peer
+ * @param value a `struct CadetPeer` that may still have a tunnel
+ * @return #GNUNET_OK (iterate over all entries)
+ */
+static int
+destroy_paths_now (void *cls,
+                   const struct GNUNET_PeerIdentity *pid,
+                   void *value)
+{
+  struct CadetPeer *cp = value;
+
+  GCP_drop_owned_paths (cp);
+  return GNUNET_OK;
+}
+
+
 /**
  * Task run during shutdown.
  *
@@ -338,7 +383,13 @@ shutdown_task (void *cls)
     GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
     loose_channels = NULL;
   }
-  /* All channels, connections and CORE must be down before this point. */
+  /* Destroy tunnels.  Note that all channels must be destroyed first! */
+  GCP_iterate_all (&destroy_tunnels_now,
+                   NULL);
+  /* All tunnels, channels, connections and CORE must be down before this point. */
+  GCP_iterate_all (&destroy_paths_now,
+                   NULL);
+  /* All paths, tunnels, channels, connections and CORE must be down before this point. */
   GCP_destroy_all_peers ();
   if (NULL != peers)
   {
@@ -405,7 +456,7 @@ handle_port_open (void *cls,
   struct CadetClient *c = cls;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Open port %s requested by client %s\n",
+       "Open port %s requested by %s\n",
        GNUNET_h2s (&pmsg->port),
        GSC_2s (c));
   if (NULL == c->ports)
@@ -449,7 +500,7 @@ handle_port_close (void *cls,
   struct CadetClient *c = cls;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Closing port %s as requested by client %s\n",
+       "Closing port %s as requested by %s\n",
        GNUNET_h2s (&pmsg->port),
        GSC_2s (c));
   if (GNUNET_YES !=
@@ -498,6 +549,11 @@ handle_channel_create (void *cls,
     GNUNET_SERVICE_client_drop (c->client);
     return;
   }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "New channel to %s at port %s requested by %s\n",
+       GNUNET_i2s (&tcm->peer),
+       GNUNET_h2s (&tcm->port),
+       GSC_2s (c));
 
   /* Create channel */
   ch = GCCH_channel_local_new (c,
@@ -518,12 +574,6 @@ handle_channel_create (void *cls,
                                                       ch,
                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "New channel %s to %s at port %s requested by client %s\n",
-       GCCH_2s (ch),
-       GNUNET_i2s (&tcm->peer),
-       GNUNET_h2s (&tcm->port),
-       GSC_2s (c));
   GNUNET_SERVICE_client_continue (c->client);
 }
 
@@ -551,7 +601,7 @@ handle_channel_destroy (void *cls,
     return;
   }
   LOG (GNUNET_ERROR_TYPE_INFO,
-       "Client %s is destroying channel %s\n",
+       "%s is destroying %s\n",
        GSC_2s(c),
        GCCH_2s (ch));
   GNUNET_assert (GNUNET_YES ==
@@ -574,9 +624,10 @@ static int
 check_data (void *cls,
             const struct GNUNET_CADET_LocalData *msg)
 {
-  const struct GNUNET_MessageHeader *payload;
   size_t payload_size;
   size_t payload_claimed_size;
+  const char *buf;
+  struct GNUNET_MessageHeader pa;
 
   /* Sanity check for message size */
   payload_size = ntohs (msg->header.size) - sizeof (*msg);
@@ -586,11 +637,24 @@ check_data (void *cls,
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  payload = (struct GNUNET_MessageHeader *) &msg[1];
-  payload_claimed_size = ntohs (payload->size);
-  if (payload_size != payload_claimed_size)
+  buf = (const char *) &msg[1];
+  do {
+    /* need to memcpy() for alignment */
+    GNUNET_memcpy (&pa,
+                   buf,
+                   sizeof (pa));
+    payload_claimed_size = ntohs (pa.size);
+    if (payload_size < payload_claimed_size)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    payload_size -= payload_claimed_size;
+    buf += payload_claimed_size;
+  } while (payload_size >= sizeof (struct GNUNET_MessageHeader));
+  if (0 != payload_size)
   {
-    GNUNET_break (0);
+    GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   return GNUNET_OK;
@@ -610,7 +674,8 @@ handle_data (void *cls,
 {
   struct CadetClient *c = cls;
   struct CadetChannel *ch;
-  const struct GNUNET_MessageHeader *payload;
+  size_t payload_size;
+  const char *buf;
 
   ch = lookup_channel (c,
                        msg->ccn);
@@ -621,16 +686,17 @@ handle_data (void *cls,
     GNUNET_SERVICE_client_drop (c->client);
     return;
   }
-
-  payload = (const struct GNUNET_MessageHeader *) &msg[1];
+  payload_size = ntohs (msg->header.size) - sizeof (*msg);
+  buf = (const char *) &msg[1];
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received %u bytes payload from client %s for channel %s\n",
-       ntohs (payload->size),
+       "Received %u bytes payload from %s for %s\n",
+       (unsigned int) payload_size,
        GSC_2s (c),
        GCCH_2s (ch));
   if (GNUNET_OK !=
       GCCH_handle_local_data (ch,
-                              payload))
+                              buf,
+                              payload_size))
   {
     GNUNET_SERVICE_client_drop (c->client);
     return;
@@ -662,7 +728,7 @@ handle_ack (void *cls,
     return;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Got a local ACK from client %s for channel %s\n",
+       "Got a local ACK from %s for %s\n",
        GSC_2s(c),
        GCCH_2s (ch));
   GCCH_handle_local_ack (ch);
@@ -1065,12 +1131,39 @@ client_connect_cb (void *cls,
                             +1,
                             GNUNET_NO);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Client %s connected\n",
+       "%s connected\n",
        GSC_2s (c));
   return c;
 }
 
 
+/**
+ * A channel was destroyed by the other peer. Tell our client.
+ *
+ * @param c client that lost a channel
+ * @param ccn channel identification number for the client
+ * @param ch the channel object
+ */
+void
+GSC_handle_remote_channel_destroy (struct CadetClient *c,
+                                   struct GNUNET_CADET_ClientChannelNumber ccn,
+                                   struct CadetChannel *ch)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
+
+  env = GNUNET_MQ_msg (tdm,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
+  tdm->ccn = ccn;
+  GSC_send_to_client (c,
+                      env);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
+                                                         ntohl (ccn.channel_of_client),
+                                                         ch));
+}
+
+
 /**
  * Iterator for deleting each channel whose client endpoint disconnected.
  *
@@ -1087,14 +1180,14 @@ channel_destroy_iterator (void *cls,
   struct CadetClient *c = cls;
   struct CadetChannel *ch = value;
 
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Destroying %s, due to %s disconnecting.\n",
+       GCCH_2s (ch),
+       GSC_2s (c));
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multihashmap32_remove (c->channels,
                                                          key,
                                                          ch));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Destroying channel %s, due to client %s disconnecting.\n",
-       GCCH_2s (ch),
-       GSC_2s (c));
   if (key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
     GCCH_channel_local_destroy (ch);
   else
@@ -1119,7 +1212,7 @@ client_release_ports (void *cls,
   struct CadetClient *c = value;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Closing port %s due to client %s disconnect.\n",
+       "Closing port %s due to %s disconnect.\n",
        GNUNET_h2s (key),
        GSC_2s (c));
   GNUNET_assert (GNUNET_YES ==
@@ -1150,7 +1243,7 @@ client_disconnect_cb (void *cls,
 
   GNUNET_assert (c->client == client);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Client %s is disconnecting.\n",
+       "%s is disconnecting.\n",
        GSC_2s (c));
   if (NULL != c->channels)
   {