misc fixes in new CADET API, porting gnunet-cadet to new API
authorChristian Grothoff <christian@grothoff.org>
Fri, 17 Feb 2017 19:22:54 +0000 (20:22 +0100)
committerChristian Grothoff <christian@grothoff.org>
Fri, 17 Feb 2017 19:22:54 +0000 (20:22 +0100)
src/cadet/Makefile.am
src/cadet/cadet_api_new.c
src/cadet/gnunet-cadet.c
src/include/gnunet_cadet_service.h

index 9b593b48690490e5d411940dbe004ce7785b6f90..1a51453c9c4794c255cb804f5e288d2e81f5dcd6 100644 (file)
@@ -58,7 +58,7 @@ libgnunetcadetnew_la_LDFLAGS = \
 gnunet_cadet_SOURCES = \
   gnunet-cadet.c
 gnunet_cadet_LDADD = \
-  libgnunetcadet.la \
+  libgnunetcadetnew.la \
   $(top_builddir)/src/util/libgnunetutil.la
 
 gnunet_service_cadet_new_SOURCES = \
@@ -175,7 +175,7 @@ test_cadet_local_LDADD = $(ld_cadet_test_lib)
 test_cadet_local_mq_SOURCES = \
   test_cadet_local_mq.c
 test_cadet_local_mq_LDADD = \
-  libgnunetcadet.la \
+  libgnunetcadetnew.la \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la
 
index e9ab3ea5798f955485f362bd64abef698d2d0a63..8d778e10e46d76106e727d5639736bc7ba8a571d 100644 (file)
@@ -146,7 +146,7 @@ struct GNUNET_CADET_Channel
   void *ctx;
 
   /**
-   * Message Queue for the channel.
+   * Message Queue for the channel (which we are implementing).
    */
   struct GNUNET_MQ_Handle *mq;
 
@@ -156,7 +156,9 @@ struct GNUNET_CADET_Channel
   struct GNUNET_SCHEDULER_Task *mq_cont;
 
   /**
-   * Pending envelope in case we don't have an ACK from the service.
+   * Pending envelope with a message to be transmitted to the
+   * service as soon as we are allowed to.  Should only be
+   * non-NULL if @e allow_send is 0.
    */
   struct GNUNET_MQ_Envelope *pending_env;
 
@@ -181,7 +183,7 @@ struct GNUNET_CADET_Channel
   enum GNUNET_CADET_ChannelOption options;
 
   /**
-   * Are we allowed to send to the service?
+   * How many messages are we allowed to send to the service right now?
    */
   unsigned int allow_send;
 
@@ -193,6 +195,12 @@ struct GNUNET_CADET_Channel
  */
 struct GNUNET_CADET_Port
 {
+
+  /**
+   * Port "number"
+   */
+  struct GNUNET_HashCode id;
+
   /**
    * Handle to the CADET session this port belongs to.
    */
@@ -208,11 +216,6 @@ struct GNUNET_CADET_Port
    */
   void *cls;
 
-  /**
-   * Port "number"
-   */
-  struct GNUNET_HashCode id;
-
   /**
    * Handler for incoming channels on this port
    */
@@ -229,7 +232,7 @@ struct GNUNET_CADET_Port
   GNUNET_CADET_WindowSizeEventHandler window_changes;
 
   /**
-   * Handler called when an incoming channel is destroyed..
+   * Handler called when an incoming channel is destroyed.
    */
   GNUNET_CADET_DisconnectEventHandler disconnects;
 
@@ -327,7 +330,7 @@ destroy_channel (struct GNUNET_CADET_Channel *ch)
   struct GNUNET_CADET_Handle *h = ch->cadet;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " destroy_channel %X of %p\n",
+       "Destroying channel %X of %p\n",
        ch->ccn,
        h);
   GNUNET_assert (GNUNET_YES ==
@@ -343,6 +346,7 @@ destroy_channel (struct GNUNET_CADET_Channel *ch)
   if (NULL != ch->disconnects)
     ch->disconnects (ch->ctx,
                      ch);
+  GNUNET_MQ_destroy (ch->mq);
   GNUNET_free (ch);
 }
 
@@ -373,6 +377,28 @@ reconnect_cbk (void *cls)
 }
 
 
+/**
+ * Function called during #reconnect() to destroy
+ * all channels that are still open.
+ *
+ * @param cls the `struct GNUNET_CADET_Handle`
+ * @param cid chanenl ID
+ * @param value a `struct GNUNET_CADET_Channel` to destroy
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+destroy_channel_on_reconnect_cb (void *cls,
+                                 uint32_t cid,
+                                 void *value)
+{
+  /* struct GNUNET_CADET_Handle *handle = cls; */
+  struct GNUNET_CADET_Channel *ch = value;
+
+  destroy_channel (ch);
+  return GNUNET_OK;
+}
+
+
 /**
  * Reconnect to the service, retransmit all infomation to try to restore the
  * original state.
@@ -384,12 +410,17 @@ reconnect_cbk (void *cls)
 static void
 schedule_reconnect (struct GNUNET_CADET_Handle *h)
 {
-  if (NULL == h->reconnect_task)
-  {
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-    h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
-  }
+  if (NULL != h->reconnect_task)
+    return;
+  GNUNET_CONTAINER_multihashmap32_iterate (h->channels,
+                                           &destroy_channel_on_reconnect_cb,
+                                           h);
+  h->reconnect_task
+    = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
+                                    &reconnect_cbk,
+                                    h);
+  h->reconnect_time
+    = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
 }
 
 
@@ -402,7 +433,8 @@ static void
 notify_window_size (struct GNUNET_CADET_Channel *ch)
 {
   if (NULL != ch->window_changes)
-    ch->window_changes (ch->ctx, ch,
+    ch->window_changes (ch->ctx,
+                        ch, /* FIXME: remove 'ch'? */
                         ch->allow_send);
 }
 
@@ -418,9 +450,46 @@ cadet_mq_send_continue (void *cls)
   struct GNUNET_CADET_Channel *ch = cls;
 
   ch->mq_cont = NULL;
+  GNUNET_assert (NULL == ch->pending_env);
   GNUNET_MQ_impl_send_continue (ch->mq);
 }
 
+
+/**
+ * Transmit the next message from our queue.
+ *
+ * @param cls Closure (channel whose mq to activate).
+ */
+static void
+cadet_mq_send_now (void *cls)
+{
+  struct GNUNET_CADET_Channel *ch = cls;
+  struct GNUNET_MQ_Envelope *env = ch->pending_env;
+
+  ch->mq_cont = NULL;
+  if (0 == ch->allow_send)
+  {
+    /* how did we get here? */
+    GNUNET_break (0);
+    return;
+  }
+  if (NULL == env)
+  {
+    /* how did we get here? */
+    GNUNET_break (0);
+    return;
+  }
+  ch->allow_send--;
+  GNUNET_MQ_impl_send_in_flight (ch->mq);
+  ch->pending_env = NULL;
+  GNUNET_MQ_notify_sent (env,
+                         &cadet_mq_send_continue,
+                         ch);
+  GNUNET_MQ_send (ch->cadet->mq,
+                  env);
+}
+
+
 /**
  * Implement sending functionality of a message queue for
  * us sending messages to a peer.
@@ -444,7 +513,6 @@ cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_CADET_LocalData *cadet_msg;
 
-
   if (NULL == h->mq)
   {
     /* We're currently reconnecting, pretend this worked */
@@ -460,26 +528,16 @@ cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
     GNUNET_MQ_impl_send_continue (mq);
     return;
   }
-
   env = GNUNET_MQ_msg_nested_mh (cadet_msg,
                                  GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
                                  msg);
   cadet_msg->ccn = ch->ccn;
-
+  GNUNET_assert (NULL == ch->pending_env);
+  ch->pending_env = env;
   if (0 < ch->allow_send)
-  {
-    /* Service has allowed this message, just send it and continue accepting */
-    GNUNET_MQ_send (h->mq, env);
-    ch->allow_send--;
-    ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue, ch);
-    // notify_window_size (ch); /* FIXME add "verbose" setting? */
-  }
-  else
-  {
-    /* Service has NOT allowed this message, queue it and wait for an ACK */
-    GNUNET_assert (NULL == ch->pending_env);
-    ch->pending_env = env;
-  }
+    ch->mq_cont
+      = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now,
+                                  ch);
 }
 
 
@@ -515,12 +573,16 @@ cadet_mq_error_handler (void *cls,
 {
   struct GNUNET_CADET_Channel *ch = cls;
 
-  GNUNET_break_op (0);
-  if (GNUNET_MQ_ERROR_NO_MATCH)
+  GNUNET_break (0);
+  if (GNUNET_MQ_ERROR_NO_MATCH == error)
   {
     /* Got a message we did not understand, still try to continue! */
     GNUNET_CADET_receive_done (ch);
   }
+  else
+  {
+    schedule_reconnect (ch->cadet);
+  }
 }
 
 
@@ -537,11 +599,9 @@ cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
 {
   struct GNUNET_CADET_Channel *ch = impl_state;
 
-  LOG (GNUNET_ERROR_TYPE_WARNING,
-       "Cannot cancel mq message on channel %X of %p\n",
-       ch->ccn.channel_of_client,
-       ch->cadet);
-  GNUNET_break (0);
+  GNUNET_assert (NULL != ch->pending_env);
+  GNUNET_MQ_discard (ch->pending_env);
+  ch->pending_env = NULL;
 }
 
 
@@ -568,7 +628,8 @@ handle_channel_created (void *cls,
     GNUNET_break (0);
     return;
   }
-  port = find_port (h, port_number);
+  port = find_port (h,
+                    port_number);
   if (NULL == port)
   {
     /* We could have closed the port but the service didn't know about it yet
@@ -666,7 +727,7 @@ check_local_data (void *cls,
   size = ntohs (message->header.size);
   if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size)
   {
-    GNUNET_break_op (0);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
 
@@ -674,7 +735,7 @@ check_local_data (void *cls,
                      message->ccn);
   if (NULL == ch)
   {
-    GNUNET_break_op (0);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
 
@@ -702,7 +763,7 @@ handle_local_data (void *cls,
                      message->ccn);
   if (NULL == ch)
   {
-    GNUNET_break_op (0);
+    GNUNET_break (0);
     reconnect (h);
     return;
   }
@@ -752,19 +813,16 @@ handle_local_ack (void *cls,
          ntohl (ch->ccn.channel_of_client),
          ch->allow_send);
     notify_window_size (ch);
+    return;
   }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Got an ACK on mq channel %X, sending pending message!\n",
-         ntohl (ch->ccn.channel_of_client));
-    GNUNET_MQ_send (h->mq,
-                    ch->pending_env);
-    ch->allow_send--;
-    ch->pending_env = NULL;
-    ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue,
-                                            ch);
-  }
+  if (NULL != ch->mq_cont)
+    return; /* already working on it! */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got an ACK on mq channel %X, sending pending message!\n",
+       ntohl (ch->ccn.channel_of_client));
+  ch->mq_cont
+    = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now,
+                                ch);
 }
 
 
@@ -782,48 +840,15 @@ handle_mq_error (void *cls,
 {
   struct GNUNET_CADET_Handle *h = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "MQ ERROR: %u\n",
+              error);
   GNUNET_MQ_destroy (h->mq);
   h->mq = NULL;
   reconnect (h);
 }
 
 
-/**
- * Check that message received from CADET service is well-formed.
- *
- * @param cls the `struct GNUNET_CADET_Handle`
- * @param message the message we got
- * @return #GNUNET_OK if the message is well-formed,
- *         #GNUNET_SYSERR otherwise
- */
-static int
-check_get_peers (void *cls,
-                 const struct GNUNET_CADET_LocalInfoPeer *message)
-{
-  struct GNUNET_CADET_Handle *h = cls;
-  uint16_t size;
-
-  if (NULL == h->info_cb.peers_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "  no handler for peesr monitor message!\n");
-    return GNUNET_SYSERR;
-  }
-
-  size = ntohs (message->header.size);
-  if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size)
-  {
-    h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0);
-    h->info_cb.peers_cb = NULL;
-    h->info_cls = NULL;
-    return GNUNET_SYSERR;
-  }
-
-  return GNUNET_OK;
-}
-
-
 /**
  * Process a local reply about info on all tunnels, pass info to the user.
  *
@@ -835,9 +860,13 @@ handle_get_peers (void *cls,
                   const struct GNUNET_CADET_LocalInfoPeer *msg)
 {
   struct GNUNET_CADET_Handle *h = cls;
-  h->info_cb.peers_cb (h->info_cls, &msg->destination,
+
+  if (NULL == h->info_cb.peers_cb)
+    return;
+  h->info_cb.peers_cb (h->info_cls,
+                       &msg->destination,
                        (int) ntohs (msg->tunnel),
-                       (unsigned int ) ntohs (msg->paths),
+                       (unsigned int) ntohs (msg->paths),
                        0);
 }
 
@@ -854,62 +883,39 @@ static int
 check_get_peer (void *cls,
                 const struct GNUNET_CADET_LocalInfoPeer *message)
 {
-  struct GNUNET_CADET_Handle *h = cls;
-  const size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer);
-  struct GNUNET_PeerIdentity *paths_array;
+  size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer);
+  const struct GNUNET_PeerIdentity *paths_array;
   size_t esize;
   unsigned int epaths;
   unsigned int paths;
   unsigned int peers;
 
-  if (NULL == h->info_cb.peer_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "  no handler for peer monitor message!\n");
-    goto clean_cls;
-  }
-
-  /* Verify message sanity */
   esize = ntohs (message->header.size);
   if (esize < msize)
   {
-    GNUNET_break_op (0);
-    h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
-    goto clean_cls;
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
   }
   if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity)))
   {
-    GNUNET_break_op (0);
-    h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
-    goto clean_cls;
-
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
   }
   peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity);
-  epaths = (unsigned int) ntohs (message->paths);
-  paths_array = (struct GNUNET_PeerIdentity *) &message[1];
+  epaths = ntohs (message->paths);
+  paths_array = (const struct GNUNET_PeerIdentity *) &message[1];
   paths = 0;
-  for (int i = 0; i < peers; i++)
-  {
-    if (0 == memcmp (&paths_array[i], &message->destination,
+  for (unsigned int i = 0; i < peers; i++)
+    if (0 == memcmp (&paths_array[i],
+                     &message->destination,
                      sizeof (struct GNUNET_PeerIdentity)))
-    {
       paths++;
-    }
-  }
   if (paths != epaths)
   {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "p:%u, e: %u\n", paths, epaths);
-    h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
-    goto clean_cls;
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
   }
-
   return GNUNET_OK;
-
-clean_cls:
-  h->info_cb.peer_cb = NULL;
-  h->info_cls = NULL;
-  return GNUNET_SYSERR;
 }
 
 
@@ -924,22 +930,26 @@ handle_get_peer (void *cls,
                  const struct GNUNET_CADET_LocalInfoPeer *message)
 {
   struct GNUNET_CADET_Handle *h = cls;
-  struct GNUNET_PeerIdentity *paths_array;
+  const struct GNUNET_PeerIdentity *paths_array;
   unsigned int paths;
   unsigned int path_length;
   int neighbor;
   unsigned int peers;
 
-  paths = (unsigned int) ntohs (message->paths);
-  paths_array = (struct GNUNET_PeerIdentity *) &message[1];
+  if (NULL == h->info_cb.peer_cb)
+    return;
+  paths = ntohs (message->paths);
+  paths_array = (const struct GNUNET_PeerIdentity *) &message[1];
   peers = (ntohs (message->header.size) - sizeof (*message))
           / sizeof (struct GNUNET_PeerIdentity);
   path_length = 0;
   neighbor = GNUNET_NO;
 
-  for (int i = 0; i < peers; i++)
+  for (unsigned int i = 0; i < peers; i++)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&paths_array[i]));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                " %s\n",
+                GNUNET_i2s (&paths_array[i]));
     path_length++;
     if (0 == memcmp (&paths_array[i], &message->destination,
                      sizeof (struct GNUNET_PeerIdentity)))
@@ -951,7 +961,7 @@ handle_get_peer (void *cls,
   }
 
   /* Call Callback with tunnel info. */
-  paths_array = (struct GNUNET_PeerIdentity *) &message[1];
+  paths_array = (const struct GNUNET_PeerIdentity *) &message[1];
   h->info_cb.peer_cb (h->info_cls,
                       &message->destination,
                       (int) ntohs (message->tunnel),
@@ -961,40 +971,6 @@ handle_get_peer (void *cls,
 }
 
 
-/**
- * Check that message received from CADET service is well-formed.
- *
- * @param cls the `struct GNUNET_CADET_Handle`
- * @param msg the message we got
- * @return #GNUNET_OK if the message is well-formed,
- *         #GNUNET_SYSERR otherwise
- */
-static int
-check_get_tunnels (void *cls,
-                   const struct GNUNET_CADET_LocalInfoTunnel *msg)
-{
-  struct GNUNET_CADET_Handle *h = cls;
-  uint16_t size;
-
-  if (NULL == h->info_cb.tunnels_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "  no handler for tunnels monitor message!\n");
-    return GNUNET_SYSERR;
-  }
-
-  size = ntohs (msg->header.size);
-  if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size)
-  {
-    h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0);
-    h->info_cb.tunnels_cb = NULL;
-    h->info_cls = NULL;
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
 /**
  * Process a local reply about info on all tunnels, pass info to the user.
  *
@@ -1007,6 +983,8 @@ handle_get_tunnels (void *cls,
 {
   struct GNUNET_CADET_Handle *h = cls;
 
+  if (NULL == h->info_cb.tunnels_cb)
+    return;
   h->info_cb.tunnels_cb (h->info_cls,
                          &msg->destination,
                          ntohl (msg->channels),
@@ -1029,28 +1007,18 @@ static int
 check_get_tunnel (void *cls,
                   const struct GNUNET_CADET_LocalInfoTunnel *msg)
 {
-  struct GNUNET_CADET_Handle *h = cls;
   unsigned int ch_n;
   unsigned int c_n;
   size_t esize;
   size_t msize;
 
-  if (NULL == h->info_cb.tunnel_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "  no handler for tunnel monitor message!\n");
-    goto clean_cls;
-  }
-
   /* Verify message sanity */
   msize = ntohs (msg->header.size);
   esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
   if (esize > msize)
   {
-    GNUNET_break_op (0);
-    h->info_cb.tunnel_cb (h->info_cls,
-                          NULL, 0, 0, NULL, NULL, 0, 0);
-    goto clean_cls;
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
   }
   ch_n = ntohl (msg->channels);
   c_n = ntohl (msg->connections);
@@ -1065,17 +1033,9 @@ check_get_tunnel (void *cls,
                 (unsigned int) esize,
                 ch_n,
                 c_n);
-    h->info_cb.tunnel_cb (h->info_cls,
-                          NULL, 0, 0, NULL, NULL, 0, 0);
-    goto clean_cls;
+    return GNUNET_SYSERR;
   }
-
   return GNUNET_OK;
-
-clean_cls:
-  h->info_cb.tunnel_cb = NULL;
-  h->info_cls = NULL;
-  return GNUNET_SYSERR;
 }
 
 
@@ -1095,6 +1055,9 @@ handle_get_tunnel (void *cls,
   const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
   const struct GNUNET_CADET_ChannelTunnelNumber *chns;
 
+  if (NULL == h->info_cb.tunnel_cb)
+    return;
+
   ch_n = ntohl (msg->channels);
   c_n = ntohl (msg->connections);
 
@@ -1112,28 +1075,6 @@ handle_get_tunnel (void *cls,
 }
 
 
-/**
- * Function called during #reconnect() to destroy
- * all channels that are still open.
- *
- * @param cls the `struct GNUNET_CADET_Handle`
- * @param cid chanenl ID
- * @param value a `struct GNUNET_CADET_Channel` to destroy
- * @return #GNUNET_OK (continue to iterate)
- */
-static int
-destroy_channel_on_reconnect_cb (void *cls,
-                                 uint32_t cid,
-                                 void *value)
-{
-  /* struct GNUNET_CADET_Handle *handle = cls; */
-  struct GNUNET_CADET_Channel *ch = value;
-
-  destroy_channel (ch);
-  return GNUNET_OK;
-}
-
-
 /**
  * Reconnect to the service, retransmit all infomation to try to restore the
  * original state.
@@ -1160,18 +1101,18 @@ reconnect (struct GNUNET_CADET_Handle *h)
                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
                              struct GNUNET_CADET_LocalAck,
                              h),
-    GNUNET_MQ_hd_var_size (get_peers,
-                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
-                           struct GNUNET_CADET_LocalInfoPeer,
-                           h),
+    GNUNET_MQ_hd_fixed_size (get_peers,
+                             GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
+                             struct GNUNET_CADET_LocalInfoPeer,
+                             h),
     GNUNET_MQ_hd_var_size (get_peer,
                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
                            struct GNUNET_CADET_LocalInfoPeer,
                            h),
-    GNUNET_MQ_hd_var_size (get_tunnels,
-                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
-                           struct GNUNET_CADET_LocalInfoTunnel,
-                           h),
+    GNUNET_MQ_hd_fixed_size (get_tunnels,
+                             GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
+                             struct GNUNET_CADET_LocalInfoTunnel,
+                             h),
     GNUNET_MQ_hd_var_size (get_tunnel,
                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
                            struct GNUNET_CADET_LocalInfoTunnel,
@@ -1179,14 +1120,6 @@ reconnect (struct GNUNET_CADET_Handle *h)
     GNUNET_MQ_handler_end ()
   };
 
-  GNUNET_CONTAINER_multihashmap32_iterate (h->channels,
-                                           &destroy_channel_on_reconnect_cb,
-                                           h);
-  if (NULL != h->mq)
-  {
-    GNUNET_MQ_destroy (h->mq);
-    h->mq = NULL;
-  }
   h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "cadet",
                                  handlers,
@@ -1309,6 +1242,7 @@ GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
                  GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports,
                                                        &p->id,
                                                        p));
+  GNUNET_free (p->handlers);
   GNUNET_free (p);
 }
 
@@ -1329,11 +1263,14 @@ GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
   struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
   struct GNUNET_MQ_Envelope *env;
 
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
-  msg->ccn = channel->ccn;
-  GNUNET_MQ_send (h->mq,
-                  env);
+  if (NULL != h->mq)
+  {
+    env = GNUNET_MQ_msg (msg,
+                         GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
+    msg->ccn = channel->ccn;
+    GNUNET_MQ_send (h->mq,
+                    env);
+  }
   destroy_channel (channel);
 }
 
index f9f156f5828530ec82d0ba5e430179237b22c2f9..d4286a1b00eb6dc4079e8e0deef66317d05b9261 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2012 GNUnet e.V.
+     Copyright (C) 2012, 2017 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
@@ -22,6 +22,7 @@
  * @file cadet/gnunet-cadet.c
  * @brief Print information about cadet tunnels and peers.
  * @author Bartlomiej Polot
+ * @author Christian Grothoff
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "cadet.h"
 
 
-/**
- * Option -m.
- */
-static int monitor_mode;
-
 /**
  * Option -P.
  */
@@ -99,11 +95,6 @@ static char *target_id;
  */
 static char *target_port = "default";
 
-/**
- * Data pending in netcat mode.
- */
-static size_t data_size;
-
 /**
  * Cadet handle.
  */
@@ -114,11 +105,6 @@ static struct GNUNET_CADET_Handle *mh;
  */
 static struct GNUNET_CADET_Channel *ch;
 
-/**
- * Transmit handle.
- */
-static struct GNUNET_CADET_TransmitHandle *th;
-
 /**
  * HashCode of the given port string
  */
@@ -129,11 +115,6 @@ static struct GNUNET_HashCode porthash;
  */
 struct GNUNET_CADET_Port *lp;
 
-/**
- * Shutdown task handle.
- */
-static struct GNUNET_SCHEDULER_Task *sd;
-
 /**
  * Task for reading from stdin.
  */
@@ -145,6 +126,9 @@ static struct GNUNET_SCHEDULER_Task *rd_task;
 static struct GNUNET_SCHEDULER_Task *job;
 
 
+/**
+ * Wait for input on STDIO and send it out over the #ch.
+ */
 static void
 listen_stdio (void);
 
@@ -214,22 +198,11 @@ shutdown_task (void *cls)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Shutdown\n");
-  if (NULL != th)
-  {
-    GNUNET_CADET_notify_transmit_ready_cancel (th);
-    th = NULL;
-  }
   if (NULL != ch)
   {
     GNUNET_CADET_channel_destroy (ch);
     ch = NULL;
   }
-  else if (NULL != target_id) {
-    // FIXME: would be nicer to have proper NACK support from cadet_api
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-               "Connection refused to %s\n",
-               target_id);
-  }
   if (NULL != mh)
   {
     GNUNET_CADET_disconnect (mh);
@@ -254,42 +227,38 @@ shutdown_task (void *cls)
 
 
 /**
- * Function called to notify a client about the connection
- * begin ready to queue more data.  "buf" will be
- * NULL and "size" zero if the connection was closed for
- * writing in the meantime.
- *
- * FIXME
+ * Task run in stdio mode, after some data is available at stdin.
  *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * @param cls Closure (unused).
  */
-static size_t
-data_ready (void *cls, size_t size, void *buf)
+static void
+read_stdio (void *cls)
 {
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_MessageHeader *msg;
-  size_t total_size;
+  char buf[60000];
+  ssize_t data_size;
 
-  th = NULL;
-
-  if (NULL == buf || 0 == size)
+  rd_task = NULL;
+  data_size = read (0,
+                    buf,
+                    60000);
+  if (data_size < 1)
   {
     GNUNET_SCHEDULER_shutdown();
-    return 0;
+    return;
   }
-
-  total_size = data_size + sizeof (struct GNUNET_MessageHeader);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "sending %u bytes\n",
+              "Read %u bytes from stdio\n",
               (unsigned int) data_size);
-  GNUNET_assert (size >= total_size);
-
-  msg = buf;
-  msg->size = htons (total_size);
-  msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_CLI);
-  GNUNET_memcpy (&msg[1], cls, data_size);
+  env = GNUNET_MQ_msg_extra (msg,
+                             data_size,
+                             GNUNET_MESSAGE_TYPE_CADET_CLI);
+  GNUNET_memcpy (&msg[1],
+                 buf,
+                 data_size);
+  GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
+                  env);
   if (GNUNET_NO == echo)
   {
     listen_stdio ();
@@ -298,54 +267,27 @@ data_ready (void *cls, size_t size, void *buf)
   {
     echo_time = GNUNET_TIME_absolute_get ();
   }
-
-  return total_size;
-}
-
-
-/**
- * Task run in stdio mode, after some data is available at stdin.
- *
- * @param cls Closure (unused).
- */
-static void
-read_stdio (void *cls)
-{
-  static char buf[60000];
-
-  rd_task = NULL;
-  data_size = read (0, buf, 60000);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "stdio read %u bytes\n",
-              (unsigned int) data_size);
-  if (data_size < 1)
-  {
-    GNUNET_SCHEDULER_shutdown();
-    return;
-  }
-  GNUNET_assert (NULL == th);
-  th = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           sizeof (struct GNUNET_MessageHeader)
-                                           + data_size,
-                                           &data_ready, buf);
 }
 
 
 /**
- * Start listening to stdin
+ * Wait for input on STDIO and send it out over the #ch.
  */
 static void
-listen_stdio (void)
+listen_stdio ()
 {
   struct GNUNET_NETWORK_FDSet *rs;
 
+  /* FIXME: why use 'rs' here, seems overly complicated... */
   rs = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_set_native (rs, 0);
+  GNUNET_NETWORK_fdset_set_native (rs,
+                                   0); /* STDIN */
   rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                                        GNUNET_TIME_UNIT_FOREVER_REL,
-                                        rs, NULL,
-                                        &read_stdio, NULL);
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         rs,
+                                         NULL,
+                                         &read_stdio,
+                                         NULL);
   GNUNET_NETWORK_fdset_destroy (rs);
 }
 
@@ -356,32 +298,17 @@ listen_stdio (void)
  *
  * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
  *
- * @param cls closure (set from #GNUNET_CADET_connect)
+ * @param cls closure
  * @param channel connection to the other end (henceforth invalid)
- * @param channel_ctx place where local state associated
- *                   with the channel is stored
  */
 static void
 channel_ended (void *cls,
-               const struct GNUNET_CADET_Channel *channel,
-               void *channel_ctx)
+               const struct GNUNET_CADET_Channel *channel)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n");
-  if (channel != ch)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ended: %p, expected: %p\n", channel, ch);
-  }
-  else
-  {
-    ch = NULL;
-  }
-  if (NULL != th)
-  {
-    GNUNET_CADET_notify_transmit_ready_cancel (th);
-    th = NULL;
-  }
-
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Channel ended!\n");
+  GNUNET_assert (channel == ch);
+  ch = NULL;
   GNUNET_SCHEDULER_shutdown ();
 }
 
@@ -398,65 +325,27 @@ channel_ended (void *cls,
  * @param cls closure
  * @param channel new handle to the channel
  * @param initiator peer that started the channel
- * @param port Port this channel is for.
- * @param options CadetOption flag field, with all active option bits set to 1.
- *
- * @return initial channel context for the channel
- *         (can be NULL -- that's not an error)
+ * @return initial channel context for the channel, we use @a channel
  */
 static void *
 channel_incoming (void *cls,
                   struct GNUNET_CADET_Channel *channel,
-                  const struct GNUNET_PeerIdentity *initiator,
-                  const struct GNUNET_HashCode *port,
-                  enum GNUNET_CADET_ChannelOption options)
+                  const struct GNUNET_PeerIdentity *initiator)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-              "Connected from %s\n",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Incomming connection from %s\n",
               GNUNET_i2s_full (initiator));
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming channel %p on port %s\n",
-              channel, GNUNET_h2s (port));
-  if (NULL != ch)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "A channel already exists (%p)\n", ch);
-    /*
-     * From now on multiple channels will be sending data to us
-     * making the service of this command unpredictable in its
-     * current implementation. So for now let's just bail out.
-     */
-    GNUNET_SCHEDULER_shutdown();
-    return NULL;
-  }
-  if (NULL == listen_port)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Not listening to channels\n");
-    return NULL;
-  }
-  // Closing the listen port currently breaks open connections.
-  // Is this an intentional departure from POSIX socket behavior?
-  //
-  if (NULL != lp) {
-    /* Now that we have our circuit up and running, let's not
-     * get confused by further incoming connect requests.
-     * You need to start another 'gnunet-cadet -o' process
-     * to receive those.
-     */
-    GNUNET_CADET_close_port (lp);
-    lp = NULL;
-  }
+  GNUNET_assert (NULL == ch);
+  GNUNET_assert (NULL != lp);
+  GNUNET_CADET_close_port (lp);
+  lp = NULL;
   ch = channel;
   if (GNUNET_NO == echo)
-  {
     listen_stdio ();
-    return NULL;
-  }
-  data_size = 0;
-  return NULL;
+  return channel;
 }
 
+
 /**
  * @brief Send an echo request to the remote peer.
  *
@@ -465,14 +354,16 @@ channel_incoming (void *cls,
 static void
 send_echo (void *cls)
 {
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *msg;
+
   echo_task = NULL;
   if (NULL == ch)
     return;
-  GNUNET_assert (NULL == th);
-  th = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           sizeof (struct GNUNET_MessageHeader),
-                                           &data_ready, NULL);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_CLI);
+  GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
+                  env);
 }
 
 
@@ -485,44 +376,27 @@ static void
 request_dump (void *cls)
 {
   GNUNET_CADET_request_dump (mh);
-  GNUNET_SCHEDULER_cancel (sd);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                               &shutdown_task, NULL);
+  GNUNET_SCHEDULER_shutdown ();
 }
 
 
 /**
- * Call CADET's monitor API, get info of one connection.
+ * Function called whenever a message is received.
  *
- * @param cls Closure (unused).
+ * Each time the function must call #GNUNET_CADET_receive_done on the channel
+ * in order to receive the next message. This doesn't need to be immediate:
+ * can be delayed if some processing is done on the message.
+ *
+ * @param cls should match #ch
+ * @param message The actual message.
+ * @return #GNUNET_OK to keep the channel open,
+ *         #GNUNET_SYSERR to close it (signal serious error).
  */
-static void
-create_channel (void *cls)
+static int
+check_data (void *cls,
+            const struct GNUNET_MessageHeader *message)
 {
-  struct GNUNET_PeerIdentity pid;
-  enum GNUNET_CADET_ChannelOption opt;
-
-  GNUNET_assert (NULL == ch);
-
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
-                                                  strlen (target_id),
-                                                  &pid.public_key))
-  {
-    FPRINTF (stderr,
-             _("Invalid target `%s'\n"),
-             target_id);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id);
-  opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
-  GNUNET_CRYPTO_hash (target_port, strlen(target_port), &porthash);
-  ch = GNUNET_CADET_channel_create (mh, NULL, &pid, &porthash, opt);
-  if (GNUNET_NO == echo)
-    listen_stdio ();
-  else
-    echo_task = GNUNET_SCHEDULER_add_now (&send_echo, NULL);
+  return GNUNET_OK; /* all is well-formed */
 }
 
 
@@ -533,42 +407,36 @@ create_channel (void *cls)
  * in order to receive the next message. This doesn't need to be immediate:
  * can be delayed if some processing is done on the message.
  *
- * @param cls Closure (set from #GNUNET_CADET_connect).
- * @param channel Connection to the other end.
- * @param channel_ctx Place to store local state associated with the channel.
+ * @param cls NULL
  * @param message The actual message.
- * @return #GNUNET_OK to keep the channel open,
- *         #GNUNET_SYSERR to close it (signal serious error).
  */
-static int
-data_callback (void *cls,
-               struct GNUNET_CADET_Channel *channel,
-               void **channel_ctx,
-               const struct GNUNET_MessageHeader *message)
+static void
+handle_data (void *cls,
+             const struct GNUNET_MessageHeader *message)
 {
+  size_t payload_size = ntohs (message->size) - sizeof (*message);
   uint16_t len;
   ssize_t done;
   uint16_t off;
   const char *buf;
-  GNUNET_break (ch == channel);
-  GNUNET_CADET_receive_done (channel);
 
+  GNUNET_CADET_receive_done (ch);
   if (GNUNET_YES == echo)
   {
     if (NULL != listen_port)
     {
-      /* Just listening to echo incoming messages*/
-      if (NULL != th)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Last echo reply not yet sent, dropping current reply.\n");
-        return GNUNET_OK;
-      }
-      th = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
-                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                               sizeof (struct GNUNET_MessageHeader),
-                                               &data_ready, NULL);
-      return GNUNET_OK;
+      struct GNUNET_MQ_Envelope *env;
+      struct GNUNET_MessageHeader *msg;
+
+      env = GNUNET_MQ_msg_extra (msg,
+                                 payload_size,
+                                 GNUNET_MESSAGE_TYPE_CADET_CLI);
+      GNUNET_memcpy (&msg[1],
+                     &message[1],
+                     payload_size);
+      GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
+                      env);
+      return;
     }
     else
     {
@@ -576,30 +444,37 @@ data_callback (void *cls,
 
       latency = GNUNET_TIME_absolute_get_duration (echo_time);
       echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
-      FPRINTF (stdout, "time: %s\n",
-               GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
+      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                  "time: %s\n",
+                  GNUNET_STRINGS_relative_time_to_string (latency,
+                                                          GNUNET_NO));
       echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                &send_echo, NULL);
+                                                &send_echo,
+                                                NULL);
     }
   }
 
   len = ntohs (message->size) - sizeof (*message);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got %u bytes\n",
+              len);
   buf = (const char *) &message[1];
   off = 0;
   while (off < len)
   {
-    done = write (1, &buf[off], len - off);
+    done = write (1,
+                  &buf[off],
+                  len - off);
     if (done <= 0)
     {
       if (-1 == done)
         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
                              "write");
-      return GNUNET_SYSERR;
+      GNUNET_SCHEDULER_shutdown ();
+      return;
     }
     off += done;
   }
-  return GNUNET_OK;
 }
 
 
@@ -625,16 +500,17 @@ peers_callback (void *cls,
 {
   if (NULL == peer)
   {
-    if (GNUNET_YES != monitor_mode)
-    {
-      GNUNET_SCHEDULER_shutdown();
-    }
+    GNUNET_SCHEDULER_shutdown();
     return;
   }
-  FPRINTF (stdout, "%s tunnel: %c, paths: %u\n",
-           GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths);
+  FPRINTF (stdout,
+           "%s tunnel: %c, paths: %u\n",
+           GNUNET_i2s_full (peer),
+           tunnel ? 'Y' : 'N',
+           n_paths);
 }
 
+
 /**
  * Method called to retrieve information about a specific peer
  * known to the service.
@@ -654,19 +530,26 @@ peer_callback (void *cls,
                int tunnel,
                int neighbor,
                unsigned int n_paths,
-               struct GNUNET_PeerIdentity *paths)
+               const struct GNUNET_PeerIdentity *paths)
 {
   unsigned int i;
-  struct GNUNET_PeerIdentity *p;
+  const struct GNUNET_PeerIdentity *p;
 
-  FPRINTF (stdout, "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n",
+  FPRINTF (stdout,
+           "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n",
            GNUNET_i2s_full (peer),
-           tunnel ? "Y" : "N", neighbor ? "Y" : "N", n_paths);
+           tunnel ? "Y" : "N",
+           neighbor ? "Y" : "N",
+           n_paths);
   p = paths;
   for (i = 0; i < n_paths && NULL != p;)
   {
-    FPRINTF (stdout, "%s ", GNUNET_i2s (p));
-    if (0 == memcmp (p, peer, sizeof (*p)))
+    FPRINTF (stdout,
+             "%s ",
+             GNUNET_i2s (p));
+    if (0 == memcmp (p,
+                     peer,
+                     sizeof (*p)))
     {
       FPRINTF (stdout, "\n");
       i++;
@@ -698,16 +581,16 @@ tunnels_callback (void *cls,
 {
   if (NULL == peer)
   {
-    if (GNUNET_YES != monitor_mode)
-    {
-      GNUNET_SCHEDULER_shutdown();
-    }
+    GNUNET_SCHEDULER_shutdown();
     return;
   }
-  FPRINTF (stdout, "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
+  FPRINTF (stdout,
+           "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
            GNUNET_i2s_full (peer),
-           enc_2s (estate), conn_2s (cstate),
-           channels, connections);
+           enc_2s (estate),
+           conn_2s (cstate),
+           channels,
+           connections);
 }
 
 
@@ -748,11 +631,7 @@ tunnel_callback (void *cls,
     FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate));
     FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate));
   }
-  if (GNUNET_YES != monitor_mode)
-  {
-    GNUNET_SCHEDULER_shutdown ();
-  }
-  return;
+  GNUNET_SCHEDULER_shutdown ();
 }
 
 
@@ -876,18 +755,21 @@ run (void *cls,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  static const struct GNUNET_CADET_MessageHandler handlers[] = {
-    {&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0},
-    {NULL, 0, 0} /* FIXME add option to monitor msg types */
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_var_size (data,
+                           GNUNET_MESSAGE_TYPE_CADET_CLI,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+    GNUNET_MQ_handler_end ()
   };
 
   /* FIXME add option to monitor apps */
 
   target_id = args[0];
-  if (target_id && args[1]) target_port = args[1];
+  if (target_id && args[1])
+    target_port = args[1];
 
   if ( (0 != (request_peers | request_tunnels)
-        || 0 != monitor_mode
         || NULL != tunnel_id
         || NULL != conn_id
         || NULL != channel_id)
@@ -903,66 +785,128 @@ run (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "requesting debug dump\n");
-    GNUNET_SCHEDULER_add_now (&request_dump, NULL);
-  }
-  else if (NULL != target_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating channel to %s\n",
-                target_id);
-    GNUNET_SCHEDULER_add_now (&create_channel, NULL);
+    job = GNUNET_SCHEDULER_add_now (&request_dump,
+                                    NULL);
   }
   else if (NULL != peer_id)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n");
-    job = GNUNET_SCHEDULER_add_now (&show_peer, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Show peer\n");
+    job = GNUNET_SCHEDULER_add_now (&show_peer,
+                                    NULL);
   }
   else if (NULL != tunnel_id)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n");
-    job = GNUNET_SCHEDULER_add_now (&show_tunnel, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Show tunnel\n");
+    job = GNUNET_SCHEDULER_add_now (&show_tunnel,
+                                    NULL);
   }
   else if (NULL != channel_id)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n");
-    job = GNUNET_SCHEDULER_add_now (&show_channel, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Show channel\n");
+    job = GNUNET_SCHEDULER_add_now (&show_channel,
+                                    NULL);
   }
   else if (NULL != conn_id)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n");
-    job = GNUNET_SCHEDULER_add_now (&show_connection, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Show connection\n");
+    job = GNUNET_SCHEDULER_add_now (&show_connection,
+                                    NULL);
   }
   else if (GNUNET_YES == request_peers)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n");
-    job = GNUNET_SCHEDULER_add_now (&get_peers, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Show all peers\n");
+    job = GNUNET_SCHEDULER_add_now (&get_peers,
+                                    NULL);
   }
   else if (GNUNET_YES == request_tunnels)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n");
-    job = GNUNET_SCHEDULER_add_now (&get_tunnels, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Show all tunnels\n");
+    job = GNUNET_SCHEDULER_add_now (&get_tunnels,
+                                    NULL);
   }
-  else if (NULL == listen_port)
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting to CADET service\n");
+  mh = GNUNET_CADET_connecT (cfg);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                 NULL);
+  if (NULL == mh)
   {
-    FPRINTF (stderr, "No action requested\n");
+    GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET service\n");
-  mh = GNUNET_CADET_connect (cfg,
-                            NULL, /* cls */
-                            &channel_ended, /* cleaner */
-                            handlers);
-  if (NULL == mh)
-    GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
-  else
-    sd = GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
-
   if (NULL != listen_port)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening CADET listen port\n");
-    GNUNET_CRYPTO_hash (listen_port, strlen(listen_port), &porthash);
-    lp = GNUNET_CADET_open_port (mh, &porthash, &channel_incoming, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Opening CADET listen port\n");
+    GNUNET_CRYPTO_hash (listen_port,
+                        strlen (listen_port),
+                        &porthash);
+    lp = GNUNET_CADET_open_porT (mh,
+                                 &porthash,
+                                 &channel_incoming,
+                                 NULL,
+                                 NULL /* window changes */,
+                                 &channel_ended,
+                                 handlers);
+  }
+  if (NULL != target_id)
+  {
+    struct GNUNET_PeerIdentity pid;
+    enum GNUNET_CADET_ChannelOption opt;
+
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
+                                                    strlen (target_id),
+                                                    &pid.public_key))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                  _("Invalid target `%s'\n"),
+                  target_id);
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Connecting to `%s:%s'\n",
+                target_id,
+                target_port);
+    opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
+    GNUNET_CRYPTO_hash (target_port,
+                        strlen(target_port),
+                        &porthash);
+    ch = GNUNET_CADET_channel_creatE (mh,
+                                      NULL,
+                                      &pid,
+                                      &porthash,
+                                      opt,
+                                      NULL /* window changes */,
+                                      &channel_ended,
+                                      handlers);
+    if (GNUNET_YES == echo)
+    {
+      echo_task = GNUNET_SCHEDULER_add_now (&send_echo,
+                                            NULL);
+    }
+    else
+    {
+      listen_stdio ();
+    }
+  }
+
+  if ( (NULL == lp) &&
+       (NULL == job) &&
+       (NULL == ch) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("No action requested\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
   }
 }
 
@@ -975,14 +919,12 @@ run (void *cls,
  * @return 0 ok, 1 on error
  */
 int
-main (int argc, char *const *argv)
+main (int argc,
+      char *const *argv)
 {
   int res;
   const char helpstr[] = "Create channels and retreive info about cadets status.";
   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-//     {'a', "channel", "TUNNEL_ID:CHANNEL_ID",
-//      gettext_noop ("provide information about a particular channel"),
-//      GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id},
     {'C', "connection", "CONNECTION_ID",
      gettext_noop ("provide information about a particular connection"),
      GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id},
@@ -992,10 +934,7 @@ main (int argc, char *const *argv)
     {'d', "dump", NULL,
      gettext_noop ("dump debug information to STDERR"),
      GNUNET_NO, &GNUNET_GETOPT_set_one, &dump},
-//     {'m', "monitor", NULL,
-//      gettext_noop ("provide information about all events (continuously)"),
-//      GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_mode},
-    {'o', "open-port", NULL,
+    {'o', "open-port", "PORT",
      gettext_noop ("port to listen to"),
      GNUNET_YES, &GNUNET_GETOPT_set_string, &listen_port},
     {'p', "peer", "PEER_ID",
@@ -1014,12 +953,13 @@ main (int argc, char *const *argv)
     GNUNET_GETOPT_OPTION_END
   };
 
-  monitor_mode = GNUNET_NO;
-
-  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                    &argc, &argv))
     return 2;
 
-  res = GNUNET_PROGRAM_run (argc, argv, "gnunet-cadet (OPTIONS | TARGET PORT)",
+  res = GNUNET_PROGRAM_run (argc, argv,
+                            "gnunet-cadet (OPTIONS | TARGET PORT)",
                             gettext_noop (helpstr),
                             options, &run, NULL);
 
@@ -1027,8 +967,7 @@ main (int argc, char *const *argv)
 
   if (GNUNET_OK == res)
     return 0;
-  else
-    return 1;
+  return 1;
 }
 
 /* end of gnunet-cadet.c */
index 6f71424fbcc41a3d0c8722f9ef98dadec4d7eecd..4d13606ef3628c811959d6a6dc39180704d73fd5 100644 (file)
@@ -456,7 +456,7 @@ typedef void
                         int tunnel,
                         int neighbor,
                         unsigned int n_paths,
-                        struct GNUNET_PeerIdentity *paths);
+                        const struct GNUNET_PeerIdentity *paths);
 
 
 /**