[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r11876 - gnunet/src/util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r11876 - gnunet/src/util |
Date: |
Tue, 22 Jun 2010 18:30:43 +0200 |
Author: grothoff
Date: 2010-06-22 18:30:43 +0200 (Tue, 22 Jun 2010)
New Revision: 11876
Modified:
gnunet/src/util/Makefile.am
gnunet/src/util/server.c
gnunet/src/util/server_mst.c
gnunet/src/util/test_server.c
gnunet/src/util/test_server_disconnect.c
Log:
cleaning up server.c code and fixing mst bugs
Modified: gnunet/src/util/Makefile.am
===================================================================
--- gnunet/src/util/Makefile.am 2010-06-22 16:30:23 UTC (rev 11875)
+++ gnunet/src/util/Makefile.am 2010-06-22 16:30:43 UTC (rev 11876)
@@ -143,6 +143,7 @@
perf_crypto_hash \
test_os_start_process
+
TESTS = $(check_PROGRAMS)
@@ -156,7 +157,7 @@
test_os_start_process.c
test_os_start_process_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la
-
+
test_client_SOURCES = \
test_client.c
test_client_LDADD = \
Modified: gnunet/src/util/server.c
===================================================================
--- gnunet/src/util/server.c 2010-06-22 16:30:23 UTC (rev 11875)
+++ gnunet/src/util/server.c 2010-06-22 16:30:43 UTC (rev 11876)
@@ -22,9 +22,6 @@
* @file util/server.c
* @brief library for building GNUnet network servers
* @author Christian Grothoff
- *
- * TODO:
- * - fix inefficient memmove in message processing
*/
#include "platform.h"
@@ -36,7 +33,7 @@
#include "gnunet_disk_lib.h"
#include "gnunet_protocols.h"
-#define DEBUG_SERVER GNUNET_NO
+#define DEBUG_SERVER GNUNET_YES
/**
* List of arrays of message handlers.
@@ -157,15 +154,14 @@
{
/**
- * Size of the buffer for incoming data. Should be
- * first so we get nice alignment.
+ * This is a linked list.
*/
- char incoming_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
+ struct GNUNET_SERVER_Client *next;
/**
- * This is a linked list.
+ * Processing of incoming data.
*/
- struct GNUNET_SERVER_Client *next;
+ struct GNUNET_SERVER_MessageStreamTokenizer *mst;
/**
* Server that this client belongs to.
@@ -175,67 +171,20 @@
/**
* Client closure for callbacks.
*/
- void *client_closure;
+ struct GNUNET_CONNECTION_Handle *connection;
/**
- * Callback to receive from client.
- */
- GNUNET_SERVER_ReceiveCallback receive;
-
- /**
- * Callback to cancel receive from client.
- */
- GNUNET_SERVER_ReceiveCancelCallback receive_cancel;
-
- /**
- * Callback to ask about transmit-ready notification.
- */
- GNUNET_SERVER_TransmitReadyCallback notify_transmit_ready;
-
- /**
- * Callback to ask about transmit-ready notification.
- */
- GNUNET_SERVER_TransmitReadyCancelCallback notify_transmit_ready_cancel;
-
- /**
- * Callback to check if client is still valid.
- */
- GNUNET_SERVER_CheckCallback check;
-
- /**
- * Callback to destroy client.
- */
- GNUNET_SERVER_DestroyCallback destroy;
-
- /**
- * Side-buffer for incoming data used when processing
- * is suspended.
- */
- char *side_buf;
-
- /**
* ID of task used to restart processing.
*/
GNUNET_SCHEDULER_TaskIdentifier restart_task;
/**
- * Number of bytes in the side buffer.
- */
- size_t side_buf_size;
-
- /**
* Last activity on this socket (used to time it out
* if reference_count == 0).
*/
struct GNUNET_TIME_Absolute last_activity;
/**
- * How many bytes in the "incoming_buffer" are currently
- * valid? (starting at offset 0).
- */
- size_t receive_pos;
-
- /**
* Number of external entities with a reference to
* this client object.
*/
@@ -266,7 +215,8 @@
int shutdown_now;
/**
- * Are we currently trying to receive?
+ * Are we currently trying to receive? (YES if we are, NO if we are not,
+ * SYSERR if data is already available in MST).
*/
int receive_pending;
@@ -660,7 +610,8 @@
if (found == GNUNET_NO)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- _("Received message of unknown type %d\n"), type);
+ "Received message of unknown type %d\n",
+ type);
if (server->require_found == GNUNET_YES)
return GNUNET_SYSERR;
}
@@ -669,64 +620,84 @@
/**
- * Go over the contents of the client buffer; as long as full messages
- * are available, pass them on for processing. Update the buffer
- * accordingly. Handles fatal errors by shutting down the connection.
+ * We are receiving an incoming message. Process it.
*
- * @param client identifies which client receive buffer to process
+ * @param cls our closure (handle for the client)
+ * @param buf buffer with data received from network
+ * @param available number of bytes available in buf
+ * @param addr address of the sender
+ * @param addrlen length of addr
+ * @param errCode code indicating errors receiving, 0 for success
*/
static void
-process_client_buffer (struct GNUNET_SERVER_Client *client)
-{
- struct GNUNET_SERVER_Handle *server;
- const struct GNUNET_MessageHeader *hdr;
- size_t msize;
+process_incoming (void *cls,
+ const void *buf,
+ size_t available,
+ const struct sockaddr *addr,
+ socklen_t addrlen, int errCode);
- client->in_process_client_buffer = GNUNET_YES;
- server = client->server;
+
+/**
+ * Process messages from the client's message tokenizer until either
+ * the tokenizer is empty (and then schedule receiving more), or
+ * until some handler is not immediately done (then wait for
restart_processing)
+ * or shutdown.
+ *
+ * @param client the client to process, RC must have already been increased
+ * using GNUNET_SERVER_client_keep and will be decreased by one in this
+ * function
+ * @param ret GNUNET_NO to start processing from the buffer,
+ * GNUNET_OK if the mst buffer is drained and we should instantly
go back to receiving
+ * GNUNET_SYSERR if we should instantly abort due to error in a
previous step
+ */
+static void
+process_mst (struct GNUNET_SERVER_Client *client,
+ int ret)
+{
+ while ( (ret != GNUNET_SYSERR) &&
+ (client->server != NULL) &&
+ (GNUNET_YES != client->shutdown_now) &&
+ (0 == client->suspended) )
+ {
+ if (ret == GNUNET_OK)
+ {
+ client->receive_pending = GNUNET_YES;
#if DEBUG_SERVER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Private buffer contains %u bytes; client is %s and we are %s\n",
- client->receive_pos,
- client->suspended ? "suspended" : "up",
- client->shutdown_now ? "in shutdown" : "running");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server re-enters receive loop.\n");
#endif
- while ( (client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
- (0 == client->suspended) &&
- (GNUNET_YES != client->shutdown_now) )
- {
- hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
- msize = ntohs (hdr->size);
- if (msize > client->receive_pos)
- {
+ GNUNET_CONNECTION_receive (client->connection,
+ GNUNET_SERVER_MAX_MESSAGE_SIZE,
+ client->server->idle_timeout,
+ &process_incoming, client);
+ break;
+ }
#if DEBUG_SERVER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Total message size is %u, we only have %u bytes; need
more data\n",
- msize, client->receive_pos);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server processes additional
messages instantly.\n");
#endif
- break;
- }
+ ret = GNUNET_SERVER_mst_receive (client->mst, NULL, 0, GNUNET_NO,
GNUNET_YES);
+ }
#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server leaves instant processing loop: ret = %d, server = %p,
shutdown = %d, suspended = %u\n",
+ ret,
+ client->server,
+ client->shutdown_now,
+ client->suspended);
+#endif
+
+ if (ret == GNUNET_NO)
+ {
+#if DEBUG_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Passing %u bytes to callback for processing\n", msize);
+ "Server has more data pending but is suspended.\n");
#endif
- if ( (msize < sizeof (struct GNUNET_MessageHeader)) ||
- (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)) )
- {
- client->in_process_client_buffer = GNUNET_NO;
- GNUNET_SERVER_client_disconnect (client);
- return;
- }
- /* FIXME: this is highly inefficient; we should
- try to avoid this if the new base address is
- already nicely aligned. See old handler code... */
- memmove (client->incoming_buffer,
- &client->incoming_buffer[msize], client->receive_pos - msize);
- client->receive_pos -= msize;
+ client->receive_pending = GNUNET_SYSERR; /* data pending */
}
- client->in_process_client_buffer = GNUNET_NO;
- if (GNUNET_YES == client->shutdown_now)
+ if ( (ret == GNUNET_SYSERR) ||
+ (GNUNET_YES == client->shutdown_now) )
GNUNET_SERVER_client_disconnect (client);
+ GNUNET_SERVER_client_drop (client);
}
@@ -744,20 +715,21 @@
process_incoming (void *cls,
const void *buf,
size_t available,
- const struct sockaddr *addr, socklen_t addrlen, int errCode)
+ const struct sockaddr *addr,
+ socklen_t addrlen, int errCode)
{
struct GNUNET_SERVER_Client *client = cls;
struct GNUNET_SERVER_Handle *server = client->server;
- const char *cbuf = buf;
- size_t maxcpy;
+ int ret;
+ GNUNET_assert (client->receive_pending == GNUNET_YES);
client->receive_pending = GNUNET_NO;
if ((buf == NULL) ||
(available == 0) ||
(errCode != 0) ||
(server == NULL) ||
(client->shutdown_now == GNUNET_YES) ||
- (GNUNET_YES != client->check (client->client_closure)))
+ (GNUNET_YES != GNUNET_CONNECTION_check (client->connection)))
{
/* other side closed connection, error connecting, etc. */
GNUNET_SERVER_client_disconnect (client);
@@ -766,61 +738,13 @@
#if DEBUG_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Server receives %u bytes from `%s'.\n",
- available, GNUNET_a2s (addr, addrlen));
+ (unsigned int) available,
+ GNUNET_a2s (addr, addrlen));
#endif
GNUNET_SERVER_client_keep (client);
client->last_activity = GNUNET_TIME_absolute_get ();
- /* process data (if available) */
- while (available > 0)
- {
- maxcpy = available;
- if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
- maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
-#if DEBUG_SERVER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Can copy %u bytes to private buffer\n", maxcpy);
-#endif
- memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
- client->receive_pos += maxcpy;
- cbuf += maxcpy;
- available -= maxcpy;
- if (0 < client->suspended)
- {
- if (available > 0)
- {
-#if DEBUG_SERVER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Client has suspended processing; copying %u bytes
to side buffer to be used later.\n",
- available);
-#endif
- GNUNET_assert (client->side_buf_size == 0);
- GNUNET_assert (client->side_buf == NULL);
- client->side_buf_size = available;
- client->side_buf = GNUNET_malloc (available);
- memcpy (client->side_buf, cbuf, available);
- available = 0;
- }
- break; /* do not run next client iteration! */
- }
-#if DEBUG_SERVER
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Now processing messages in private buffer\n");
-#endif
- process_client_buffer (client);
- }
- GNUNET_assert (available == 0);
- if ((client->suspended == 0) &&
- (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
- {
- /* Finally, keep receiving! */
- client->receive_pending = GNUNET_YES;
- client->receive (client->client_closure,
- GNUNET_SERVER_MAX_MESSAGE_SIZE,
- server->idle_timeout, &process_incoming, client);
- }
- if (GNUNET_YES == client->shutdown_now)
- GNUNET_SERVER_client_disconnect (client);
- GNUNET_SERVER_client_drop (client);
+ ret = GNUNET_SERVER_mst_receive (client->mst, buf, available, GNUNET_NO,
GNUNET_YES);
+ process_mst (client, ret);
}
@@ -832,7 +756,8 @@
* @param tc scheduler context (unused)
*/
static void
-restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+restart_processing (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct GNUNET_SERVER_Client *client = cls;
struct GNUNET_SERVER_Handle *server = client->server;
@@ -843,125 +768,60 @@
{
GNUNET_SERVER_client_disconnect (client);
return;
- }
- GNUNET_SERVER_client_keep (client);
- process_client_buffer (client);
- if (0 == client->suspended)
+ }
+ if (client->receive_pending == GNUNET_NO)
{
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server begins to read again from client.\n");
+#endif
client->receive_pending = GNUNET_YES;
- client->receive (client->client_closure,
- GNUNET_SERVER_MAX_MESSAGE_SIZE,
- client->server->idle_timeout, &process_incoming, client);
+ GNUNET_CONNECTION_receive (client->connection,
+ GNUNET_SERVER_MAX_MESSAGE_SIZE,
+ client->server->idle_timeout,
&process_incoming, client);
+ return;
}
- GNUNET_SERVER_client_drop (client);
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server continues processing messages still in the buffer.\n");
+#endif
+ GNUNET_SERVER_client_keep (client);
+ client->receive_pending = GNUNET_NO;
+ process_mst (client, GNUNET_NO);
}
/**
- * Add a client to the set of our clients and
- * start receiving.
- */
-static void
-add_client (struct GNUNET_SERVER_Handle *server,
- struct GNUNET_SERVER_Client *client)
-{
- client->server = server;
- client->last_activity = GNUNET_TIME_absolute_get ();
- client->next = server->clients;
- server->clients = client;
- client->receive_pending = GNUNET_YES;
- client->receive (client->client_closure,
- GNUNET_SERVER_MAX_MESSAGE_SIZE,
- server->idle_timeout, &process_incoming, client);
-}
-
-
-/**
- * Create a request for receiving data from a socket.
+ * This function is called whenever our inbound message tokenizer has
+ * received a complete message.
*
- * @param cls identifies the socket to receive from
- * @param max how much data to read at most
- * @param timeout when should this operation time out
- * @param receiver function to call for processing
- * @param receiver_cls closure for receiver
+ * @param cls closure (struct GNUNET_SERVER_Handle)
+ * @param client identification of the client (struct GNUNET_SERVER_Client*)
+ * @param message the actual message
*/
static void
-sock_receive (void *cls,
- size_t max,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
+client_message_tokenizer_callback (void *cls,
+ void *client,
+ const struct GNUNET_MessageHeader *message)
{
- GNUNET_CONNECTION_receive (cls, max, timeout, receiver, receiver_cls);
-}
+ struct GNUNET_SERVER_Handle *server = cls;
+ struct GNUNET_SERVER_Client *sender = client;
+ int ret;
-
-/**
- * Wrapper to cancel receiving from a socket.
- *
- * @param cls handle to the GNUNET_CONNECTION_Handle to cancel
- */
-static void
-sock_receive_cancel (void *cls)
-{
- GNUNET_CONNECTION_receive_cancel (cls);
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Tokenizer gives server message of type %u from client\n",
+ ntohs (message->type));
+#endif
+ sender->in_process_client_buffer = GNUNET_YES;
+ ret = GNUNET_SERVER_inject (server, sender, message);
+ sender->in_process_client_buffer = GNUNET_NO;
+ if (GNUNET_OK != ret)
+ GNUNET_SERVER_client_disconnect (sender);
}
/**
- * FIXME: document.
- */
-static void *
-sock_notify_transmit_ready (void *cls,
- size_t size,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_CONNECTION_TransmitReadyNotify notify,
- void *notify_cls)
-{
- return GNUNET_CONNECTION_notify_transmit_ready (cls, size, timeout, notify,
- notify_cls);
-}
-
-
-/**
- * FIXME: document.
- */
-static void
-sock_notify_transmit_ready_cancel (void *cls, void *h)
-{
- GNUNET_CONNECTION_notify_transmit_ready_cancel (h);
-}
-
-
-/**
- * Check if socket is still valid (no fatal errors have happened so far).
- *
- * @param cls the socket
- * @return GNUNET_YES if valid, GNUNET_NO otherwise
- */
-static int
-sock_check (void *cls)
-{
- return GNUNET_CONNECTION_check (cls);
-}
-
-
-/**
- * Destroy this socket (free resources).
- *
- * @param cls the socket
- * @param persist set the socket to be persisted
- */
-static void
-sock_destroy (void *cls, int persist)
-{
- struct GNUNET_CONNECTION_Handle *sock = cls;
- if (persist == GNUNET_YES)
- GNUNET_CONNECTION_persist_ (sock);
- GNUNET_CONNECTION_destroy (sock, GNUNET_NO);
-}
-
-
-/**
* Add a TCP socket-based connection to the set of handles managed by
* this server. Use this function for outgoing (P2P) connections that
* we initiated (and where this server should process incoming
@@ -982,70 +842,25 @@
struct GNUNET_SERVER_Client *client;
client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
- client->client_closure = connection;
- client->receive = &sock_receive;
- client->receive_cancel = &sock_receive_cancel;
- client->notify_transmit_ready = &sock_notify_transmit_ready;
- client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
- client->check = &sock_check;
- client->destroy = &sock_destroy;
+ client->connection = connection;
+ client->mst = GNUNET_SERVER_mst_create (GNUNET_SERVER_MAX_MESSAGE_SIZE,
+ client,
+ &client_message_tokenizer_callback,
+ server);
client->reference_count = 1;
- add_client (server, client);
+ client->server = server;
+ client->last_activity = GNUNET_TIME_absolute_get ();
+ client->next = server->clients;
+ server->clients = client;
+ client->receive_pending = GNUNET_YES;
+ GNUNET_CONNECTION_receive (client->connection,
+ GNUNET_SERVER_MAX_MESSAGE_SIZE,
+ server->idle_timeout, &process_incoming, client);
return client;
}
/**
- * Add an arbitrary connection to the set of handles managed by this
- * server. This can be used if a sending and receiving does not
- * really go over the network (internal transmission) or for servers
- * using UDP.
- *
- * @param server the server to use
- * @param chandle opaque handle for the connection
- * @param creceive receive function for the connection
- * @param ccancel cancel receive function for the connection
- * @param cnotify transmit notification function for the connection
- * @param cnotify_cancel transmit notification cancellation function for the
connection
- * @param ccheck function to test if the connection is still up
- * @param cdestroy function to close and free the connection
- * @return the client handle (client should call
- * "client_drop" on the return value eventually)
- */
-struct GNUNET_SERVER_Client *
-GNUNET_SERVER_connect_callback (struct
- GNUNET_SERVER_Handle
- *server,
- void *chandle,
- GNUNET_SERVER_ReceiveCallback
- creceive,
- GNUNET_SERVER_ReceiveCancelCallback
- ccancel,
- GNUNET_SERVER_TransmitReadyCallback
- cnotify,
- GNUNET_SERVER_TransmitReadyCancelCallback
- cnotify_cancel,
- GNUNET_SERVER_CheckCallback
- ccheck,
- GNUNET_SERVER_DestroyCallback cdestroy)
-{
- struct GNUNET_SERVER_Client *client;
-
- client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
- client->client_closure = chandle;
- client->receive = creceive;
- client->receive_cancel = ccancel;
- client->notify_transmit_ready = cnotify;
- client->notify_transmit_ready_cancel = cnotify_cancel;
- client->check = ccheck;
- client->destroy = cdestroy;
- client->reference_count = 1;
- add_client (server, client);
- return client;
-}
-
-
-/**
* Notify the server that the given client handle should
* be kept (keeps the connection up if possible, increments
* the internal reference counter).
@@ -1090,9 +905,7 @@
GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
void **addr, size_t * addrlen)
{
- if (client->receive != &sock_receive)
- return GNUNET_SYSERR; /* not a network client */
- return GNUNET_CONNECTION_get_address (client->client_closure,
+ return GNUNET_CONNECTION_get_address (client->connection,
addr, addrlen);
}
@@ -1177,6 +990,10 @@
struct NotifyList *n;
unsigned int rc;
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client is being disconnected from the server.\n");
+#endif
if (client->restart_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (client->server->sched,
@@ -1185,7 +1002,7 @@
}
if (GNUNET_YES == client->receive_pending)
{
- client->receive_cancel (client->client_closure);
+ GNUNET_CONNECTION_receive_cancel (client->connection);
client->receive_pending = GNUNET_NO;
}
@@ -1236,7 +1053,11 @@
#endif
return;
}
- client->destroy (client->client_closure, client->persist);
+
+ if (client->persist == GNUNET_YES)
+ GNUNET_CONNECTION_persist_ (client->connection);
+ GNUNET_CONNECTION_destroy (client->connection, GNUNET_NO);
+ GNUNET_SERVER_mst_destroy (client->mst);
GNUNET_free (client);
}
@@ -1263,9 +1084,9 @@
GNUNET_CONNECTION_TransmitReadyNotify
callback, void *callback_cls)
{
- return client->notify_transmit_ready (client->client_closure,
- size,
- timeout, callback, callback_cls);
+ return GNUNET_CONNECTION_notify_transmit_ready (client->connection,
+ size,
+ timeout, callback,
callback_cls);
}
/**
@@ -1295,30 +1116,33 @@
void
GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
{
- char *sb;
-
if (client == NULL)
return;
GNUNET_assert (client->suspended > 0);
client->suspended--;
if (success != GNUNET_OK)
{
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GNUNET_SERVER_receive_done called with failure
indication\n");
+#endif
GNUNET_SERVER_client_disconnect (client);
return;
}
if (client->suspended > 0)
- return;
+ {
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GNUNET_SERVER_receive_done called, but more clients
pending\n");
+#endif
+ return;
+ }
if (client->in_process_client_buffer == GNUNET_YES)
- return;
- if (client->side_buf_size > 0)
{
- /* resume processing from side-buf */
- sb = client->side_buf;
- client->side_buf = NULL;
- /* this will also resume the receive job */
- process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
- /* finally, free the side-buf */
- GNUNET_free (sb);
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GNUNET_SERVER_receive_done called while still in processing
loop\n");
+#endif
return;
}
if (client->server == NULL)
@@ -1326,6 +1150,11 @@
GNUNET_SERVER_client_disconnect (client);
return;
}
+#if DEBUG_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GNUNET_SERVER_receive_done causes restart in reading from the
socket\n");
+#endif
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->restart_task);
client->restart_task = GNUNET_SCHEDULER_add_now (client->server->sched,
&restart_processing,
client);
Modified: gnunet/src/util/server_mst.c
===================================================================
--- gnunet/src/util/server_mst.c 2010-06-22 16:30:23 UTC (rev 11875)
+++ gnunet/src/util/server_mst.c 2010-06-22 16:30:43 UTC (rev 11876)
@@ -31,6 +31,8 @@
#include "gnunet_server_lib.h"
#include "gnunet_time_lib.h"
+#define DEBUG_SERVER_MST GNUNET_NO
+
#if HAVE_UNALIGNED_64_ACCESS
#define ALIGN_FACTOR 4
#else
@@ -140,9 +142,15 @@
unsigned long offset;
int ret;
+#if DEBUG_SERVER_MST
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server-mst receives %u bytes with %u bytes already in private
buffer\n",
+ (unsigned int) size,
+ (unsigned int) (mst->pos - mst->off));
+#endif
ret = GNUNET_OK;
ibuf = (char*) &mst->hdr;
- if (mst->pos > 0)
+ while (mst->pos > 0)
{
do_align:
if ( (mst->maxbuf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
@@ -231,6 +239,11 @@
}
while (size > 0)
{
+#if DEBUG_SERVER_MST
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server-mst has %u bytes left in inbound buffer\n",
+ (unsigned int) size);
+#endif
if (size < sizeof (struct GNUNET_MessageHeader))
break;
offset = (unsigned long) buf;
@@ -271,6 +284,11 @@
}
if (purge)
mst->off = 0;
+#if DEBUG_SERVER_MST
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Server-mst leaves %u bytes in private buffer\n",
+ (unsigned int) (mst->pos - mst->off));
+#endif
return ret;
}
Modified: gnunet/src/util/test_server.c
===================================================================
--- gnunet/src/util/test_server.c 2010-06-22 16:30:23 UTC (rev 11875)
+++ gnunet/src/util/test_server.c 2010-06-22 16:30:43 UTC (rev 11876)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
+ (C) 2009, 2010 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -23,6 +23,7 @@
*/
#include "platform.h"
#include "gnunet_common.h"
+#include "gnunet_client_lib.h"
#include "gnunet_scheduler_lib.h"
#include "gnunet_server_lib.h"
#include "gnunet_time_lib.h"
@@ -31,181 +32,94 @@
#define PORT 12435
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
250)
+
#define MY_TYPE 128
#define MY_TYPE2 129
static struct GNUNET_SERVER_Handle *server;
-static struct GNUNET_SCHEDULER_Handle *sched;
+static struct GNUNET_CLIENT_Connection *cc;
-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;
-}
+static struct GNUNET_SERVER_Client *argclient;
-struct SignalTimeoutContext
-{
- GNUNET_CONNECTION_Receiver cb;
- void *cb_cls;
-};
+static struct GNUNET_CONFIGURATION_Handle *cfg;
+static struct GNUNET_SCHEDULER_Handle *sched;
-static void
-signal_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct SignalTimeoutContext *stctx = cls;
+static int ok;
- stctx->cb (stctx->cb_cls, NULL, 0, NULL, 0, 0);
- GNUNET_free (stctx);
-}
-
-static GNUNET_SCHEDULER_TaskIdentifier ti;
-
-
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,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- 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 (ok == 6);
+ ok = 0;
+ GNUNET_SERVER_destroy (server);
+ GNUNET_CLIENT_disconnect (cc, GNUNET_NO);
+ GNUNET_CONFIGURATION_destroy (cfg);
}
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 (ok == 5);
+ ok = 6;
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ GNUNET_SCHEDULER_add_now (sched,
+ &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)
-{
- 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);
- msg.size = htons (sizeof (struct GNUNET_MessageHeader));
- GNUNET_assert (0 == memcmp (&msg, buf, size));
- *ok = 5; /* report success */
- return &non_null_addr;
-}
-
-
static void
-my_transmit_ready_cancel_cb (void *cls, void *ctx)
+first_reply_handler (void *cls,
+ const struct GNUNET_MessageHeader *msg)
{
- GNUNET_assert (0);
+ GNUNET_assert (ok == 4);
+ ok = 5;
+ GNUNET_SERVER_receive_done (argclient, GNUNET_OK);
+ GNUNET_SERVER_client_drop (argclient);
+ argclient = NULL;
}
-static int
-my_check (void *cls)
-{
- return GNUNET_YES;
-}
-
-
-static void my_destroy (void *cls, int persist);
-
-
-struct CopyContext
-{
- struct GNUNET_SERVER_Client *client;
- struct GNUNET_MessageHeader *cpy;
-};
-
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 (ok == 3);
+ 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));
return sizeof (struct GNUNET_MessageHeader);
}
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 (ok == 2);
+ 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));
}
@@ -216,22 +130,50 @@
};
-static void
-my_destroy (void *cls, int persist)
+static size_t
+transmit_second_message (void *cls,
+ size_t size,
+ void *buf)
{
- int *ok = cls;
- GNUNET_assert (5 == *ok);
- *ok = 0; /* report success */
- /* this will cause us to terminate */
- GNUNET_SERVER_destroy (server);
+ struct GNUNET_MessageHeader msg;
+
+ GNUNET_assert (size > sizeof (struct GNUNET_MessageHeader));
+ msg.type = htons (MY_TYPE2);
+ msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+ memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader));
+ return sizeof (struct GNUNET_MessageHeader);
}
+static size_t
+transmit_initial_message (void *cls,
+ size_t size,
+ void *buf)
+{
+ struct GNUNET_MessageHeader msg;
+
+ GNUNET_assert (ok == 1);
+ 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_assert (NULL !=
+ GNUNET_CLIENT_notify_transmit_ready (cc,
+ sizeof (struct
GNUNET_MessageHeader),
+ TIMEOUT,
+ GNUNET_YES,
+ &transmit_second_message,
+ NULL));
+ GNUNET_CLIENT_receive (cc, &first_reply_handler, NULL, TIMEOUT);
+ return sizeof (struct GNUNET_MessageHeader);
+}
+
+
static void
task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct sockaddr_in sa;
- struct GNUNET_MessageHeader msg;
struct sockaddr * sap[2];
socklen_t slens[2];
@@ -252,17 +194,25 @@
sap,
slens,
1024,
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 250),
+ 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 (tc->sched,
+ "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));
}
@@ -273,8 +223,6 @@
static int
check ()
{
- int ok;
-
ok = 1;
GNUNET_SCHEDULER_run (&task, &ok);
return ok;
Modified: gnunet/src/util/test_server_disconnect.c
===================================================================
--- gnunet/src/util/test_server_disconnect.c 2010-06-22 16:30:23 UTC (rev
11875)
+++ gnunet/src/util/test_server_disconnect.c 2010-06-22 16:30:43 UTC (rev
11876)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
+ (C) 2009, 2010 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -19,150 +19,84 @@
*/
/**
* @file util/test_server_disconnect.c
- * @brief tests for server.c and client.c,
- * specifically client_disconnect
+ * @brief tests for server.c, specifically GNUNET_SERVER_client_disconnect
*/
#include "platform.h"
#include "gnunet_common.h"
-#include "gnunet_scheduler_lib.h"
#include "gnunet_client_lib.h"
+#include "gnunet_scheduler_lib.h"
#include "gnunet_server_lib.h"
#include "gnunet_time_lib.h"
#define VERBOSE GNUNET_NO
-#define PORT 22335
+#define PORT 12435
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
250)
+
#define MY_TYPE 128
-
static struct GNUNET_SERVER_Handle *server;
-static struct GNUNET_CLIENT_Connection *client;
+static struct GNUNET_CLIENT_Connection *cc;
-static struct GNUNET_SCHEDULER_Handle *sched;
-
static struct GNUNET_CONFIGURATION_Handle *cfg;
+static struct GNUNET_SCHEDULER_Handle *sched;
+
static int ok;
-static void
-send_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct GNUNET_SERVER_Client *argclient = cls;
- GNUNET_assert (ok == 3);
- ok++;
- GNUNET_SERVER_receive_done (argclient, GNUNET_OK);
-}
static void
-server_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+finish_up (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct GNUNET_SERVER_Client *argclient = cls;
GNUNET_assert (ok == 5);
- ok++;
- GNUNET_SERVER_client_disconnect (argclient);
-}
-
-
-static void
-recv_cb (void *cls,
- struct GNUNET_SERVER_Client *argclient,
- const struct GNUNET_MessageHeader *message)
-{
- void *addr;
- size_t addrlen;
- struct sockaddr_in sa;
- struct sockaddr_in *have;
-
- GNUNET_assert (GNUNET_OK ==
- GNUNET_SERVER_client_get_address (argclient,
- &addr, &addrlen));
-
- GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
- have = addr;
- 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 = have->sin_port;
- sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- GNUNET_assert (0 == memcmp (&sa, addr, addrlen));
- GNUNET_free (addr);
- switch (ok)
- {
- case 2:
- ok++;
- GNUNET_SCHEDULER_add_delayed (sched,
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 50),
- &send_done, argclient);
- break;
- case 4:
- ok++;
- GNUNET_SCHEDULER_add_delayed (sched,
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 50),
- &server_disconnect, argclient);
- GNUNET_SERVER_receive_done (argclient, GNUNET_OK);
- break;
- default:
- GNUNET_assert (0);
- }
-
-}
-
-static void
-disconnect_notify (void *cls, const struct GNUNET_MessageHeader *msg)
-{
- GNUNET_assert (msg == NULL);
- GNUNET_assert (ok == 7);
ok = 0;
- GNUNET_CLIENT_disconnect (client, GNUNET_YES);
- client = NULL;
GNUNET_SERVER_destroy (server);
- server = NULL;
+ GNUNET_CLIENT_disconnect (cc, GNUNET_NO);
GNUNET_CONFIGURATION_destroy (cfg);
- cfg = NULL;
}
-/**
- * Functions with this signature are called whenever a client
- * is disconnected on the network level.
- *
- * @param cls closure
- * @param client identification of the client
- */
static void
notify_disconnect (void *cls, struct GNUNET_SERVER_Client *clientarg)
{
if (clientarg == NULL)
return;
- GNUNET_assert (ok == 6);
- ok++;
- GNUNET_CLIENT_receive (client,
- &disconnect_notify,
- NULL, GNUNET_TIME_UNIT_FOREVER_REL);
+ GNUNET_assert (ok == 4);
+ ok = 5;
+ GNUNET_SCHEDULER_add_now (sched,
+ &finish_up,
+ NULL);
}
-static size_t
-notify_ready (void *cls, size_t size, void *buf)
+static void
+server_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct GNUNET_MessageHeader *msg;
+ struct GNUNET_SERVER_Client *argclient = cls;
+ GNUNET_assert (ok == 3);
+ ok = 4;
+ GNUNET_SERVER_client_disconnect (argclient);
+ GNUNET_SERVER_client_drop (argclient);
+}
- GNUNET_assert (size >= 256);
- GNUNET_assert (1 == ok);
- ok++;
- msg = buf;
- msg->type = htons (MY_TYPE);
- msg->size = htons (sizeof (struct GNUNET_MessageHeader));
- msg++;
- msg->type = htons (MY_TYPE);
- msg->size = htons (sizeof (struct GNUNET_MessageHeader));
- return 2 * sizeof (struct GNUNET_MessageHeader);
+
+static void
+recv_cb (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ GNUNET_assert (ok == 2);
+ ok = 3;
+ GNUNET_SERVER_client_keep (client);
+ GNUNET_SCHEDULER_add_now (sched,
+ &server_disconnect, client);
+ GNUNET_assert (sizeof (struct GNUNET_MessageHeader) ==
+ ntohs (message->size));
+ GNUNET_assert (MY_TYPE == ntohs (message->type));
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
@@ -172,6 +106,23 @@
};
+static size_t
+transmit_initial_message (void *cls,
+ size_t size,
+ void *buf)
+{
+ struct GNUNET_MessageHeader msg;
+
+ GNUNET_assert (ok == 1);
+ 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));
+ return sizeof (struct GNUNET_MessageHeader);
+}
+
+
static void
task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
@@ -196,26 +147,26 @@
sap,
slens,
1024,
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 250),
+ TIMEOUT,
GNUNET_NO);
GNUNET_assert (server != NULL);
- handlers[0].callback_cls = cls;
GNUNET_SERVER_add_handlers (server, handlers);
- GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, cls);
+ GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, NULL);
cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_CONFIGURATION_set_value_number (cfg, "test", "PORT", PORT);
- GNUNET_CONFIGURATION_set_value_string (cfg, "test", "HOSTNAME",
- "localhost");
- GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
- "localhost");
- client = GNUNET_CLIENT_connect (tc->sched, "test", cfg);
- GNUNET_assert (client != NULL);
- GNUNET_CLIENT_notify_transmit_ready (client,
- 256,
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 250),
- GNUNET_NO, ¬ify_ready, NULL);
+ 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 (tc->sched,
+ "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));
}
@@ -226,9 +177,8 @@
static int
check ()
{
-
ok = 1;
- GNUNET_SCHEDULER_run (&task, NULL);
+ GNUNET_SCHEDULER_run (&task, &ok);
return ok;
}
@@ -238,13 +188,7 @@
{
int ret = 0;
- GNUNET_log_setup ("test_server_disconnect",
-#if VERBOSE
- "DEBUG",
-#else
- "WARNING",
-#endif
- NULL);
+ GNUNET_log_setup ("test_server_disconnect", "WARNING", NULL);
ret += check ();
return ret;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r11876 - gnunet/src/util,
gnunet <=