-fix the fix
[oweals/gnunet.git] / src / util / test_server.c
index 95206c0f137e68cea52e04943e2cfda977053ba4..189c13e18e95c9eb7576e025d3f1ac37cbc01f84 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2009, 2010, 2014 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
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 /**
  * @file util/test_server.c
  * @brief tests for server.c
  */
 #include "platform.h"
 */
 /**
  * @file util/test_server.c
  * @brief tests for server.c
  */
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_scheduler_lib.h"
-#include "gnunet_server_lib.h"
-#include "gnunet_time_lib.h"
-
-#define VERBOSE GNUNET_NO
+#include "gnunet_util_lib.h"
 
 
+/**
+ * TCP port to use for the server.
+ */
 #define PORT 12435
 
 #define PORT 12435
 
+/**
+ * Timeout to use for operations.
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
+
+/**
+ * Test message type.
+ */
 #define MY_TYPE 128
 #define MY_TYPE 128
+
+/**
+ * Test message type.
+ */
 #define MY_TYPE2 129
 
 #define MY_TYPE2 129
 
+/**
+ * Handle for the server.
+ */
 static struct GNUNET_SERVER_Handle *server;
 
 static struct GNUNET_SERVER_Handle *server;
 
-static struct GNUNET_SCHEDULER_Handle *sched;
-
-static void
-recv_fin_cb (void *cls,
-             struct GNUNET_SERVER_Client *client,
-             const struct GNUNET_MessageHeader *message)
-{
-  int *ok = cls;
-  GNUNET_assert (2 == *ok);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  *ok = 3;
-}
-
-struct SignalTimeoutContext
-{
-  GNUNET_CONNECTION_Receiver cb;
-  void *cb_cls;
-};
-
-
-static void
-signal_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct SignalTimeoutContext *stctx = cls;
+/**
+ * Handle for the client.
+ */
+static struct GNUNET_CLIENT_Connection *cc;
 
 
-  stctx->cb (stctx->cb_cls, NULL, 0, NULL, 0, 0);
-  GNUNET_free (stctx);
-}
+/**
+ * Handle of the server for the client.
+ */
+static struct GNUNET_SERVER_Client *argclient;
 
 
+/**
+ * Our configuration.
+ */
+static struct GNUNET_CONFIGURATION_Handle *cfg;
 
 
-static GNUNET_SCHEDULER_TaskIdentifier ti;
+/**
+ * Number indiciating in which phase of the test we are.
+ */
+static int ok;
 
 
 
 
+/**
+ * Final task invoked to clean up.
+ *
+ * @param cls NULL
+ */
 static void
 static void
-my_receive (void *cls,
-            size_t max,
-            struct GNUNET_TIME_Relative timeout,
-            GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
+finish_up (void *cls)
 {
 {
-  int *ok = cls;
-  struct GNUNET_MessageHeader msg;
-  struct SignalTimeoutContext *stctx;
-  GNUNET_SCHEDULER_TaskIdentifier ret;
-
-  ret = GNUNET_SCHEDULER_NO_TASK;
-  switch (*ok)
-    {
-    case 1:
-      *ok = 2;                  /* report success */
-      msg.type = htons (MY_TYPE2);
-      msg.size = htons (sizeof (struct GNUNET_MessageHeader));
-      receiver (receiver_cls, &msg, sizeof (struct GNUNET_MessageHeader),
-                NULL, 0, 0);
-      break;
-    case 3:
-      /* called after first receive instantly
-         produced a reply;
-         schedule receiver call with timeout
-         after timeout expires! */
-      *ok = 4;
-      stctx = GNUNET_malloc (sizeof (struct SignalTimeoutContext));
-      stctx->cb = receiver;
-      stctx->cb_cls = receiver_cls;
-      ret = GNUNET_SCHEDULER_add_delayed (sched,
-                                          timeout, &signal_timeout, stctx);
-      break;
-    default:
-      GNUNET_assert (0);
-    }
-  ti = ret;
+  GNUNET_assert (7 == ok);
+  ok = 0;
+  GNUNET_SERVER_destroy (server);
+  GNUNET_CLIENT_disconnect (cc);
+  GNUNET_CONFIGURATION_destroy (cfg);
 }
 
 
 }
 
 
+/**
+ * The server has received the second message, initiate clean up.
+ *
+ * @param cls NULL
+ * @param client client we got the message from
+ * @param message the message
+ */
 static void
 static void
-my_cancel (void *cls)
+recv_fin_cb (void *cls,
+             struct GNUNET_SERVER_Client *client,
+             const struct GNUNET_MessageHeader *message)
 {
 {
-  GNUNET_SCHEDULER_cancel (sched, ti);
+  GNUNET_assert (6 == ok);
+  ok = 7;
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SCHEDULER_add_now (&finish_up, NULL);
 }
 
 }
 
-static void *
-my_transmit_ready_cb (void *cls,
-                      size_t size,
-                      struct GNUNET_TIME_Relative timeout,
-                      GNUNET_CONNECTION_TransmitReadyNotify notify,
-                      void *notify_cls)
+
+/**
+ * The client connected to the server and is now allowed
+ * to send a second message.  We send one.
+ *
+ * @param cls NULL
+ * @param size number of bytes that can be transmitted
+ * @param buf where to copy the message
+ * @return number of bytes copied to @a buf
+ */
+static size_t
+transmit_second_message (void *cls,
+                         size_t size,
+                         void *buf)
 {
 {
-  static int non_null_addr;
-  int *ok = cls;
-  char buf[size];
   struct GNUNET_MessageHeader msg;
 
   struct GNUNET_MessageHeader msg;
 
-  GNUNET_assert (4 == *ok);
-  GNUNET_assert (size == sizeof (struct GNUNET_MessageHeader));
-  notify (notify_cls, size, buf);
-  msg.type = htons (MY_TYPE);
+  GNUNET_assert (5 == ok);
+  ok = 6;
+  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
+  msg.type = htons (MY_TYPE2);
   msg.size = htons (sizeof (struct GNUNET_MessageHeader));
   msg.size = htons (sizeof (struct GNUNET_MessageHeader));
-  GNUNET_assert (0 == memcmp (&msg, buf, size));
-  *ok = 5;                      /* report success */
-  return &non_null_addr;
+  memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader));
+  return sizeof (struct GNUNET_MessageHeader);
 }
 
 
 }
 
 
+/**
+ * We have received the reply from the server, check that we are at
+ * the right stage and queue the next message to the server.  Cleans
+ * up #argclient.
+ *
+ * @param cls NULL
+ * @param msg message we got from the server
+ */
 static void
 static void
-my_transmit_ready_cancel_cb (void *cls, void *ctx)
+first_reply_handler (void *cls,
+                     const struct GNUNET_MessageHeader *msg)
 {
 {
-  GNUNET_assert (0);
-}
-
-
-static int
-my_check (void *cls)
-{
-  return GNUNET_YES;
+  GNUNET_assert (4 == ok);
+  ok = 5;
+  GNUNET_assert (NULL !=
+                 GNUNET_CLIENT_notify_transmit_ready (cc,
+                                                      sizeof (struct GNUNET_MessageHeader),
+                                                      TIMEOUT,
+                                                      GNUNET_YES,
+                                                      &transmit_second_message,
+                                                      NULL));
 }
 
 
 }
 
 
-static void my_destroy (void *cls);
-
-
-struct CopyContext
-{
-  struct GNUNET_SERVER_Client *client;
-  struct GNUNET_MessageHeader *cpy;
-};
-
+/**
+ * Send a reply of type #MY_TYPE from the server to the client.
+ * Checks that we are in the right phase and transmits the
+ * reply.  Cleans up #argclient state.
+ *
+ * @param cls NULL
+ * @param size number of bytes we are allowed to send
+ * @param buf where to copy the reply
+ * @return number of bytes written to @a buf
+ */
 static size_t
 static size_t
-copy_msg (void *cls, size_t size, void *buf)
+reply_msg (void *cls,
+           size_t size,
+           void *buf)
 {
 {
-  struct CopyContext *ctx = cls;
-  struct GNUNET_MessageHeader *cpy = ctx->cpy;
-  GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (cpy->size));
-  GNUNET_assert (size >= ntohs (cpy->size));
-  memcpy (buf, cpy, ntohs (cpy->size));
-  GNUNET_free (cpy);
-  GNUNET_free (ctx);
+  struct GNUNET_MessageHeader msg;
+
+  GNUNET_assert (3 == ok);
+  ok = 4;
+  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
+  msg.type = htons (MY_TYPE);
+  msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+  memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader));
+  GNUNET_assert (NULL != argclient);
+  GNUNET_SERVER_receive_done (argclient, GNUNET_OK);
+  GNUNET_SERVER_client_drop (argclient);
+  argclient = NULL;
   return sizeof (struct GNUNET_MessageHeader);
 }
 
 
   return sizeof (struct GNUNET_MessageHeader);
 }
 
 
+/**
+ * Function called whenever the server receives a message of
+ * type #MY_TYPE.  Checks that we are at the stage where
+ * we expect the first message, then sends a reply.  Stores
+ * the handle to the client in #argclient.
+ *
+ * @param cls NULL
+ * @param client client that sent the message
+ * @param message the message we received
+ */
 static void
 recv_cb (void *cls,
 static void
 recv_cb (void *cls,
-         struct GNUNET_SERVER_Client *argclient,
+         struct GNUNET_SERVER_Client *client,
          const struct GNUNET_MessageHeader *message)
 {
          const struct GNUNET_MessageHeader *message)
 {
-  struct GNUNET_SERVER_Client *client;
-  struct CopyContext *cc;
-  struct GNUNET_MessageHeader *cpy;
-
-  GNUNET_assert (argclient == NULL);
-  GNUNET_assert (sizeof (struct GNUNET_MessageHeader) ==
-                 ntohs (message->size));
+  GNUNET_assert (2 == ok);
+  ok = 3;
+  argclient = client;
+  GNUNET_SERVER_client_keep (argclient);
+  GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size));
   GNUNET_assert (MY_TYPE == ntohs (message->type));
   GNUNET_assert (MY_TYPE == ntohs (message->type));
-  client = GNUNET_SERVER_connect_callback (server,
-                                           cls,
-                                           &my_receive,
-                                           &my_cancel,
-                                           &my_transmit_ready_cb,
-                                           &my_transmit_ready_cancel_cb,
-                                           &my_check, &my_destroy);
-  cc = GNUNET_malloc (sizeof (struct CopyContext));
-  cc->client = client;
-  cpy = GNUNET_malloc (ntohs (message->size));
-  memcpy (cpy, message, ntohs (message->size));
-  cc->cpy = cpy;
   GNUNET_assert (NULL !=
                  GNUNET_SERVER_notify_transmit_ready (client,
                                                       ntohs (message->size),
   GNUNET_assert (NULL !=
                  GNUNET_SERVER_notify_transmit_ready (client,
                                                       ntohs (message->size),
-                                                      GNUNET_TIME_UNIT_SECONDS,
-                                                      &copy_msg, cc));
-  GNUNET_SERVER_client_drop (client);
+                                                      TIMEOUT, &reply_msg,
+                                                      NULL));
 }
 
 
 }
 
 
+/**
+ * The client connected to the server and is now allowed
+ * to send a first message.  We transmit a simple message,
+ * ask for a second transmission and get ready to receive
+ * a response.
+ *
+ * @param cls NULL
+ * @param size number of bytes that can be transmitted
+ * @param buf where to copy the message
+ * @return number of bytes copied to @a buf
+ */
+static size_t
+transmit_initial_message (void *cls,
+                          size_t size,
+                          void *buf)
+{
+  struct GNUNET_MessageHeader msg;
+
+  GNUNET_assert (1 == ok);
+  ok = 2;
+  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
+  msg.type = htons (MY_TYPE);
+  msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+  memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader));
+  GNUNET_CLIENT_receive (cc, &first_reply_handler, NULL, TIMEOUT);
+  return sizeof (struct GNUNET_MessageHeader);
+}
+
+
+/**
+ * Message handlers for the server.
+ */
 static struct GNUNET_SERVER_MessageHandler handlers[] = {
   {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)},
   {&recv_fin_cb, NULL, MY_TYPE2, sizeof (struct GNUNET_MessageHeader)},
 static struct GNUNET_SERVER_MessageHandler handlers[] = {
   {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)},
   {&recv_fin_cb, NULL, MY_TYPE2, sizeof (struct GNUNET_MessageHeader)},
@@ -216,74 +254,76 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = {
 };
 
 
 };
 
 
+/**
+ * First task run by the scheduler.  Initializes the server and
+ * a client and asks for a transmission from the client to the
+ * server.
+ *
+ * @param cls NULL
+ */
 static void
 static void
-my_destroy (void *cls)
-{
-  int *ok = cls;
-  GNUNET_assert (5 == *ok);
-  *ok = 0;                      /* report success */
-  /* this will cause us to terminate */
-  GNUNET_SERVER_destroy (server);
-}
-
-
-static void
-task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+task (void *cls)
 {
   struct sockaddr_in sa;
 {
   struct sockaddr_in sa;
-  struct GNUNET_MessageHeader msg;
+  struct sockaddr *sap[2];
+  socklen_t slens[2];
 
 
-  sched = tc->sched;
+  sap[0] = (struct sockaddr *) &sa;
+  slens[0] = sizeof (sa);
+  sap[1] = NULL;
+  slens[1] = 0;
   memset (&sa, 0, sizeof (sa));
 #if HAVE_SOCKADDR_IN_SIN_LEN
   sa.sin_len = sizeof (sa);
 #endif
   sa.sin_family = AF_INET;
   sa.sin_port = htons (PORT);
   memset (&sa, 0, sizeof (sa));
 #if HAVE_SOCKADDR_IN_SIN_LEN
   sa.sin_len = sizeof (sa);
 #endif
   sa.sin_family = AF_INET;
   sa.sin_port = htons (PORT);
-  server = GNUNET_SERVER_create (tc->sched,
-                                 NULL,
-                                 NULL,
-                                 (const struct sockaddr *) &sa,
-                                 sizeof (sa),
-                                 1024,
-                                 GNUNET_TIME_relative_multiply
-                                 (GNUNET_TIME_UNIT_MILLISECONDS, 250),
-                                 GNUNET_NO);
+  server = GNUNET_SERVER_create (NULL, NULL,
+                                 sap, slens,
+                                 TIMEOUT, GNUNET_NO);
   GNUNET_assert (server != NULL);
   GNUNET_assert (server != NULL);
-  handlers[0].callback_cls = cls;
-  handlers[1].callback_cls = cls;
   GNUNET_SERVER_add_handlers (server, handlers);
   GNUNET_SERVER_add_handlers (server, handlers);
-  msg.type = htons (MY_TYPE);
-  msg.size = htons (sizeof (struct GNUNET_MessageHeader));
-  GNUNET_SERVER_inject (server, NULL, &msg);
-  memset (&msg, 0, sizeof (struct GNUNET_MessageHeader));
+  cfg = GNUNET_CONFIGURATION_create ();
+  GNUNET_CONFIGURATION_set_value_number (cfg,
+                                         "test-server",
+                                         "PORT",
+                                         PORT);
+  GNUNET_CONFIGURATION_set_value_string (cfg,
+                                         "test-server",
+                                         "HOSTNAME",
+                                         "localhost");
+  GNUNET_CONFIGURATION_set_value_string (cfg,
+                                         "resolver",
+                                         "HOSTNAME",
+                                         "localhost");
+  cc = GNUNET_CLIENT_connect ("test-server", cfg);
+  GNUNET_assert (cc != NULL);
+  GNUNET_assert (NULL !=
+                 GNUNET_CLIENT_notify_transmit_ready (cc,
+                                                      sizeof (struct
+                                                              GNUNET_MessageHeader),
+                                                      TIMEOUT, GNUNET_YES,
+                                                      &transmit_initial_message,
+                                                      NULL));
 }
 
 
 /**
 }
 
 
 /**
- * Main method, starts scheduler with task1,
- * checks that "ok" is correct at the end.
+ * Runs the test.
+ *
+ * @param argc length of @a argv
+ * @param argv command line arguments (ignored)
+ * @return 0 on success, otherwise phase of failure
  */
  */
-static int
-check ()
+int
+main (int argc, char *argv[])
 {
 {
-  int ok;
-
+  GNUNET_log_setup ("test_server",
+                    "WARNING",
+                    NULL);
   ok = 1;
   GNUNET_SCHEDULER_run (&task, &ok);
   return ok;
 }
 
   ok = 1;
   GNUNET_SCHEDULER_run (&task, &ok);
   return ok;
 }
 
-
-int
-main (int argc, char *argv[])
-{
-  int ret = 0;
-
-  GNUNET_log_setup ("test_server", "WARNING", NULL);
-  ret += check ();
-
-  return ret;
-}
-
 /* end of test_server.c */
 /* end of test_server.c */