X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Ftest_server.c;h=189c13e18e95c9eb7576e025d3f1ac37cbc01f84;hb=4707789ebfb4cef9672db31e3ceb8f98381901d0;hp=95206c0f137e68cea52e04943e2cfda977053ba4;hpb=cf45b8dff29c366d51aa2e6ea6a64b99b514b9c9;p=oweals%2Fgnunet.git diff --git a/src/util/test_server.c b/src/util/test_server.c index 95206c0f1..189c13e18 100644 --- a/src/util/test_server.c +++ b/src/util/test_server.c @@ -1,10 +1,10 @@ /* 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 - 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 @@ -14,201 +14,239 @@ 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" -#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 +/** + * Timeout to use for operations. + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) + +/** + * Test message type. + */ #define MY_TYPE 128 + +/** + * Test message type. + */ #define MY_TYPE2 129 +/** + * Handle for the 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 -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 -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; - 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)); - 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 -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 -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); } +/** + * 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, - struct GNUNET_SERVER_Client *argclient, + struct GNUNET_SERVER_Client *client, 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)); - 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_TIME_UNIT_SECONDS, - ©_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)}, @@ -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 -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 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); - 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); - handlers[0].callback_cls = cls; - handlers[1].callback_cls = cls; 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; } - -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 */