[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r6348 - in GNUnet/src: applications applications/dht/module
From: |
gnunet |
Subject: |
[GNUnet-SVN] r6348 - in GNUnet/src: applications applications/dht/module applications/dht/tools applications/fs/collection applications/fs/fsui applications/fs/gap applications/rpc include util/containers |
Date: |
Sun, 17 Feb 2008 00:50:48 -0700 (MST) |
Author: grothoff
Date: 2008-02-17 00:50:48 -0700 (Sun, 17 Feb 2008)
New Revision: 6348
Removed:
GNUnet/src/include/gnunet_blockstore.h
GNUnet/src/util/containers/vector.c
GNUnet/src/util/containers/vectortest.c
Modified:
GNUnet/src/applications/Makefile.am
GNUnet/src/applications/dht/module/cs.c
GNUnet/src/applications/dht/module/routing.c
GNUnet/src/applications/dht/module/service.c
GNUnet/src/applications/dht/tools/dht-query.c
GNUnet/src/applications/dht/tools/dht_api.c
GNUnet/src/applications/fs/collection/collection.c
GNUnet/src/applications/fs/fsui/deserialize.c
GNUnet/src/applications/fs/fsui/fsui.h
GNUnet/src/applications/fs/fsui/serialize.c
GNUnet/src/applications/fs/gap/fs_dht.c
GNUnet/src/applications/rpc/parameters.c
GNUnet/src/applications/rpc/parameterstest.c
GNUnet/src/applications/rpc/rpc.c
GNUnet/src/include/Makefile.am
GNUnet/src/include/gnunet_dht_lib.h
GNUnet/src/include/gnunet_dht_service.h
GNUnet/src/include/gnunet_dstore_service.h
GNUnet/src/include/gnunet_rpc_lib.h
GNUnet/src/include/gnunet_rpc_service.h
GNUnet/src/include/gnunet_util_containers.h
GNUnet/src/util/containers/Makefile.am
Log:
RPC code clean up
Modified: GNUnet/src/applications/Makefile.am
===================================================================
--- GNUnet/src/applications/Makefile.am 2008-02-17 04:58:52 UTC (rev 6347)
+++ GNUnet/src/applications/Makefile.am 2008-02-17 07:50:48 UTC (rev 6348)
@@ -18,7 +18,6 @@
identity \
bootstrap_http \
datastore \
- rpc \
fragmentation \
getoption \
$(HOSTLIST_DIR) \
Modified: GNUnet/src/applications/dht/module/cs.c
===================================================================
--- GNUnet/src/applications/dht/module/cs.c 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/applications/dht/module/cs.c 2008-02-17 07:50:48 UTC (rev
6348)
@@ -29,7 +29,6 @@
#include "platform.h"
#include "gnunet_core.h"
#include "gnunet_protocols.h"
-#include "gnunet_rpc_service.h"
#include "dht.h"
#include "gnunet_dht_service.h"
@@ -100,18 +99,17 @@
}
static int
-get_result (const GNUNET_HashCode * key, const GNUNET_DataContainer * value,
+get_result (const GNUNET_HashCode * key,
+ unsigned int type,
+ unsigned int size,
+ const char * value,
void *cls)
{
struct DHT_CLIENT_GET_RECORD *record = cls;
CS_dht_request_put_MESSAGE *msg;
size_t n;
- GNUNET_GE_ASSERT (NULL,
- ntohl (value->size) >= sizeof (GNUNET_DataContainer));
- n =
- sizeof (CS_dht_request_put_MESSAGE) + ntohl (value->size) -
- sizeof (GNUNET_DataContainer);
+ n = sizeof (CS_dht_request_put_MESSAGE) + size;
if (n > GNUNET_MAX_BUFFER_SIZE)
{
GNUNET_GE_BREAK (NULL, 0);
@@ -121,8 +119,7 @@
msg->header.size = htons (n);
msg->header.type = htons (GNUNET_CS_PROTO_DHT_REQUEST_PUT);
msg->key = *key;
- memcpy (&msg[1], &value[1],
- ntohl (value->size) - sizeof (GNUNET_DataContainer));
+ memcpy (&msg[1], value, size);
#if DEBUG_CS
GNUNET_GE_LOG (coreAPI->ectx,
GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
@@ -130,8 +127,8 @@
__FUNCTION__,
__FILE__,
__LINE__,
- ntohl (value->size) - sizeof (GNUNET_DataContainer),
- &value[1]);
+ size,
+ value);
#endif
if (GNUNET_OK !=
coreAPI->cs_send_to_client (record->client, &msg->header, GNUNET_YES))
Modified: GNUnet/src/applications/dht/module/routing.c
===================================================================
--- GNUnet/src/applications/dht/module/routing.c 2008-02-17 04:58:52 UTC
(rev 6347)
+++ GNUnet/src/applications/dht/module/routing.c 2008-02-17 07:50:48 UTC
(rev 6348)
@@ -247,7 +247,7 @@
* Given a result, lookup in the routing table
* where to send it next.
*/
-static void
+static int
routeResult (const GNUNET_HashCode * key,
unsigned int type,
unsigned int size, const char *data, void *cls)
@@ -387,6 +387,7 @@
#endif
if (cls == NULL)
GNUNET_free (result);
+ return GNUNET_OK;
}
/**
Modified: GNUnet/src/applications/dht/module/service.c
===================================================================
--- GNUnet/src/applications/dht/module/service.c 2008-02-17 04:58:52 UTC
(rev 6347)
+++ GNUnet/src/applications/dht/module/service.c 2008-02-17 07:50:48 UTC
(rev 6348)
@@ -48,8 +48,8 @@
/**
* Function to call for each result.
*/
- GNUNET_DataProcessor callback;
-
+ GNUNET_ResultProcessor callback;
+
/**
* Extra argument to callback.
*/
@@ -62,21 +62,6 @@
};
-static void
-client_result_converter (const GNUNET_HashCode * key,
- unsigned int type,
- unsigned int size, const char *data, void *cls)
-{
- struct GNUNET_DHT_GetHandle *get = cls;
- GNUNET_DataContainer *dc;
-
- dc = GNUNET_malloc (sizeof (GNUNET_DataContainer) + size);
- dc->size = ntohl (sizeof (GNUNET_DataContainer) + size);
- memcpy (&dc[1], data, size);
- get->callback (key, dc, get->cls);
- GNUNET_free (dc);
-}
-
/**
* Perform an asynchronous GET operation on the DHT identified by
* 'table' using 'key' as the key. The peer does not have to be part
@@ -96,7 +81,7 @@
static struct GNUNET_DHT_GetHandle *
dht_get_async_start (unsigned int type,
const GNUNET_HashCode * key,
- GNUNET_DataProcessor callback, void *cls)
+ GNUNET_ResultProcessor callback, void *cls)
{
struct GNUNET_DHT_GetHandle *ret;
@@ -106,7 +91,7 @@
ret->cls = cls;
ret->type = type;
if (GNUNET_OK !=
- GNUNET_DHT_get_start (key, type, &client_result_converter, ret))
+ GNUNET_DHT_get_start (key, type, callback, cls))
{
GNUNET_free (ret);
return NULL;
@@ -120,8 +105,7 @@
static int
dht_get_async_stop (struct GNUNET_DHT_GetHandle *record)
{
- GNUNET_DHT_get_stop (&record->key, record->type, &client_result_converter,
- record);
+ GNUNET_DHT_get_stop (&record->key, record->type, record->callback,
record->cls);
GNUNET_free (record);
return GNUNET_OK;
}
Modified: GNUnet/src/applications/dht/tools/dht-query.c
===================================================================
--- GNUnet/src/applications/dht/tools/dht-query.c 2008-02-17 04:58:52 UTC
(rev 6347)
+++ GNUnet/src/applications/dht/tools/dht-query.c 2008-02-17 07:50:48 UTC
(rev 6348)
@@ -62,14 +62,16 @@
static int
printCallback (const GNUNET_HashCode * hash,
- const GNUNET_DataContainer * data, void *cls)
+ unsigned int type,
+ unsigned int size,
+ const char * data, void *cls)
{
char *key = cls;
printf ("%s(%s): '%.*s'\n",
"get",
key,
- (int) (ntohl (data->size) - sizeof (GNUNET_DataContainer)),
- (char *) &data[1]);
+ size,
+ data);
return GNUNET_OK;
}
@@ -99,13 +101,9 @@
do_put (struct GNUNET_ClientServerConnection *sock,
const char *key, const char *value)
{
- GNUNET_DataContainer *dc;
GNUNET_HashCode hc;
GNUNET_hash (key, strlen (key), &hc);
- dc = GNUNET_malloc (sizeof (GNUNET_DataContainer) + strlen (value));
- dc->size = htonl (strlen (value) + sizeof (GNUNET_DataContainer));
- memcpy (&dc[1], value, strlen (value));
#if DEBUG_DHT_QUERY
GNUNET_GE_LOG (ectx,
GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
@@ -115,7 +113,8 @@
timeout = 30 * GNUNET_CRON_MINUTES;
if (GNUNET_OK ==
GNUNET_DHT_put (cfg, ectx, &hc, GNUNET_ECRS_BLOCKTYPE_DHT_STRING2STRING,
- dc))
+ strlen(value),
+ value))
{
printf (_("'%s(%s,%s)' succeeded\n"), "put", key, value);
}
@@ -123,7 +122,6 @@
{
printf (_("'%s(%s,%s)' failed.\n"), "put", key, value);
}
- GNUNET_free (dc);
}
int
Modified: GNUnet/src/applications/dht/tools/dht_api.c
===================================================================
--- GNUnet/src/applications/dht/tools/dht_api.c 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/applications/dht/tools/dht_api.c 2008-02-17 07:50:48 UTC (rev
6348)
@@ -46,7 +46,7 @@
/**
* Callback to call for each result.
*/
- GNUNET_DataProcessor processor;
+ GNUNET_ResultProcessor processor;
/**
* Extra argument for processor.
@@ -81,7 +81,6 @@
GetInfo *info = cls;
GNUNET_MessageHeader *reply;
CS_dht_request_put_MESSAGE *put;
- GNUNET_DataContainer *cont;
unsigned int size;
while (info->aborted == GNUNET_NO)
@@ -100,15 +99,13 @@
}
size = ntohs (reply->size) - sizeof (CS_dht_request_put_MESSAGE);
put = (CS_dht_request_put_MESSAGE *) reply;
- if (info->processor != NULL)
- {
- cont = GNUNET_malloc (sizeof (GNUNET_DataContainer) + size);
- cont->size = htonl (sizeof (GNUNET_DataContainer) + size);
- memcpy (&cont[1], &put[1], size);
- if (GNUNET_OK != info->processor (&put->key, cont, info->closure))
- info->aborted = GNUNET_YES;
- GNUNET_free (cont);
- }
+ if ( (info->processor != NULL) &&
+ (GNUNET_OK != info->processor (&put->key,
+ 0 /* unknown! */,
+ size,
+ (const char*) &put[1],
+ info->closure)) )
+ info->aborted = GNUNET_YES;
info->total++;
GNUNET_free (reply);
}
@@ -142,7 +139,7 @@
struct GNUNET_GE_Context *ectx,
unsigned int type,
const GNUNET_HashCode * key,
- GNUNET_CronTime timeout, GNUNET_DataProcessor processor,
+ GNUNET_CronTime timeout, GNUNET_ResultProcessor processor,
void *closure)
{
struct GNUNET_ClientServerConnection *sock;
@@ -206,7 +203,9 @@
GNUNET_DHT_put (struct GNUNET_GC_Configuration *cfg,
struct GNUNET_GE_Context *ectx,
const GNUNET_HashCode * key,
- unsigned int type, const GNUNET_DataContainer * value)
+ unsigned int type,
+ unsigned int size,
+ const char * value)
{
struct GNUNET_ClientServerConnection *sock;
CS_dht_request_put_MESSAGE *req;
@@ -216,24 +215,19 @@
GNUNET_GE_LOG (ectx,
GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
"DHT_LIB_put called with value '%.*s'\n",
- ntohl (value->size), &value[1]);
+ size, value);
#endif
sock = GNUNET_client_connection_create (ectx, cfg);
if (sock == NULL)
return GNUNET_SYSERR;
- GNUNET_GE_ASSERT (NULL,
- ntohl (value->size) >= sizeof (GNUNET_DataContainer));
req =
- GNUNET_malloc (sizeof (CS_dht_request_put_MESSAGE) + ntohl (value->size) -
- sizeof (GNUNET_DataContainer));
+ GNUNET_malloc (sizeof (CS_dht_request_put_MESSAGE) + size);
req->header.size =
- htons (sizeof (CS_dht_request_put_MESSAGE) + ntohl (value->size) -
- sizeof (GNUNET_DataContainer));
+ htons (sizeof (CS_dht_request_put_MESSAGE) + size);
req->header.type = htons (GNUNET_CS_PROTO_DHT_REQUEST_PUT);
req->key = *key;
req->type = htonl (type);
- memcpy (&req[1], &value[1],
- ntohl (value->size) - sizeof (GNUNET_DataContainer));
+ memcpy (&req[1], value, size);
ret = GNUNET_client_connection_write (sock, &req->header);
GNUNET_client_connection_destroy (sock);
GNUNET_free (req);
Modified: GNUnet/src/applications/fs/collection/collection.c
===================================================================
--- GNUnet/src/applications/fs/collection/collection.c 2008-02-17 04:58:52 UTC
(rev 6347)
+++ GNUnet/src/applications/fs/collection/collection.c 2008-02-17 07:50:48 UTC
(rev 6348)
@@ -36,7 +36,6 @@
*/
#include "platform.h"
-#include "gnunet_blockstore.h"
#include "gnunet_directories.h"
#include "gnunet_collection_lib.h"
#include "gnunet_util.h"
Modified: GNUnet/src/applications/fs/fsui/deserialize.c
===================================================================
--- GNUnet/src/applications/fs/fsui/deserialize.c 2008-02-17 04:58:52 UTC
(rev 6347)
+++ GNUnet/src/applications/fs/fsui/deserialize.c 2008-02-17 07:50:48 UTC
(rev 6348)
@@ -362,12 +362,13 @@
GNUNET_GE_BREAK (NULL, 0);
return GNUNET_SYSERR;
}
+ ctx->collectionDataSize = big;
ctx->collectionData = GNUNET_malloc (big);
- if (big - sizeof (unsigned int) !=
- READ (fd, &ctx->collectionData[1], big - sizeof (unsigned int)))
+ if (big != READ (fd, ctx->collectionData, big))
{
GNUNET_free (ctx->collectionData);
ctx->collectionData = NULL;
+ ctx->collectionDataSize = 0;
GNUNET_GE_BREAK (NULL, 0);
return GNUNET_SYSERR;
}
Modified: GNUnet/src/applications/fs/fsui/fsui.h
===================================================================
--- GNUnet/src/applications/fs/fsui/fsui.h 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/applications/fs/fsui/fsui.h 2008-02-17 07:50:48 UTC (rev
6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other
contributing authors)
+ (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 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
@@ -29,7 +29,6 @@
#include "gnunet_util.h"
#include "gnunet_util_cron.h"
#include "gnunet_ecrs_lib.h"
-#include "gnunet_blockstore.h"
/**
* Track record for a given result.
@@ -408,7 +407,9 @@
/**
* Collection related data.
*/
- GNUNET_DataContainer *collectionData;
+ char * collectionData;
+
+ unsigned int collectionDataSize;
/**
* List of active searches.
Modified: GNUnet/src/applications/fs/fsui/serialize.c
===================================================================
--- GNUnet/src/applications/fs/fsui/serialize.c 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/applications/fs/fsui/serialize.c 2008-02-17 07:50:48 UTC (rev
6348)
@@ -174,13 +174,14 @@
writeCollection (int fd, struct GNUNET_FSUI_Context *ctx)
{
if ((ctx->collectionData == NULL) ||
- (ctx->collectionData->size > 16 * 1024 * 1024))
+ (ctx->collectionDataSize > 16 * 1024 * 1024))
{
WRITEINT (fd, 0);
return;
}
/* serialize collection data */
- WRITE (fd, ctx->collectionData, ntohl (ctx->collectionData->size));
+ WRITEINT(fd, ctx->collectionDataSize);
+ WRITE (fd, ctx->collectionData, ctx->collectionDataSize);
}
static void
Modified: GNUnet/src/applications/fs/gap/fs_dht.c
===================================================================
--- GNUnet/src/applications/fs/gap/fs_dht.c 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/applications/fs/gap/fs_dht.c 2008-02-17 07:50:48 UTC (rev
6348)
@@ -130,20 +130,15 @@
*/
static int
response_callback (const GNUNET_HashCode * key,
- const GNUNET_DataContainer * value, void *cls)
+ unsigned int type,
+ unsigned int size,
+ const char * value, void *cls)
{
struct ActiveRequestRecords *record = cls;
- unsigned int size;
const DBlock *dblock;
GNUNET_HashCode hc;
- size = ntohl (value->size);
- if (size < 4)
- {
- GNUNET_GE_BREAK_OP (NULL, 0);
- return GNUNET_OK;
- }
- dblock = (const DBlock *) &value[1];
+ dblock = (const DBlock *) value;
if ((GNUNET_SYSERR ==
GNUNET_EC_file_block_check_and_get_query (size,
dblock,
Modified: GNUnet/src/applications/rpc/parameters.c
===================================================================
--- GNUnet/src/applications/rpc/parameters.c 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/applications/rpc/parameters.c 2008-02-17 07:50:48 UTC (rev
6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 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
@@ -30,25 +30,35 @@
#include "platform.h"
/**
- * A parameter to/from an RPC call. These (and nothing else) are stored in
- * the GNUNET_Vector of the GNUNET_RPC_CallParameters structure.
+ * A linked list of parameters to/from an RPC call.
*/
-typedef struct
+struct Parameter
{
+ struct Parameter * next;
+ char * name;
+ void * data;
unsigned int dataLength;
- char *name;
- void *data;
-} Parameter;
+};
+struct GNUNET_RPC_CallParameters
+{
+ struct Parameter * list;
+};
+
+
/**
* Allocate a new, empty RPC parameter structure.
*
* @return An empty GNUNET_RPC_CallParameters structure
*/
-GNUNET_RPC_CallParameters *
+struct GNUNET_RPC_CallParameters *
GNUNET_RPC_parameters_create ()
{
- return GNUNET_vector_create (4);
+ struct GNUNET_RPC_CallParameters * ret;
+
+ ret = GNUNET_malloc(sizeof(struct GNUNET_RPC_CallParameters));
+ ret->list = NULL;
+ return ret;
}
/**
@@ -59,18 +69,19 @@
* @param param The RPC parameter structure to be freed
*/
void
-GNUNET_RPC_parameters_destroy (GNUNET_RPC_CallParameters * param)
+GNUNET_RPC_parameters_destroy (struct GNUNET_RPC_CallParameters * param)
{
if (param == NULL)
return;
- while (GNUNET_vector_get_size (param) > 0)
+ while (param->list != NULL)
{
- Parameter *p = GNUNET_vector_delete_last (param);
+ struct Parameter *p = param->list;
+ param->list = p->next;
GNUNET_free (p->name);
GNUNET_free (p->data);
GNUNET_free (p);
}
- GNUNET_vector_destroy (param);
+ GNUNET_free(param);
}
/**
@@ -78,43 +89,40 @@
* GNUNET_RPC_parameters_get_serialized_size(param) bytes of memory.
*/
void
-GNUNET_RPC_parameters_serialize (GNUNET_RPC_CallParameters * param,
+GNUNET_RPC_parameters_serialize (const struct GNUNET_RPC_CallParameters *
param,
char *target)
{
- int i;
- const char *paramName;
+ const struct Parameter *pos;
unsigned int dataLength;
- void *paramValue;
- size_t pos;
+ size_t off;
if (param == NULL)
return;
if (target == NULL)
return;
- pos = 0;
+ off = 0;
dataLength = 0;
- for (i = 0; i < GNUNET_RPC_parameters_count (param); i++)
+ pos = param->list;
+ while (pos != NULL)
{
- paramName = GNUNET_RPC_parameters_get_name (param, i);
- paramValue = NULL;
- GNUNET_RPC_parameters_get_value_by_index (param, i, &dataLength,
- ¶mValue);
- memcpy (&target[pos], paramName, strlen (paramName) + 1);
- pos += strlen (paramName) + 1;
- *(unsigned int *) &target[pos] = htonl (dataLength);
- pos += sizeof (unsigned int);
- memcpy (&target[pos], paramValue, dataLength);
- pos += dataLength;
+ memcpy (&target[off], pos->name, strlen (pos->name) + 1);
+ off += strlen (pos->name) + 1;
+ dataLength = htonl(pos->dataLength);
+ memcpy(&target[off], &dataLength, sizeof(unsigned int));
+ off += sizeof (unsigned int);
+ memcpy (&target[off], pos->data, pos->dataLength);
+ off += pos->dataLength;
+ pos = pos->next;
}
}
/**
* Deserialize parameters from buffer.
*/
-GNUNET_RPC_CallParameters *
-GNUNET_RPC_parameters_deserialize (char *buffer, size_t size)
+struct GNUNET_RPC_CallParameters *
+GNUNET_RPC_parameters_deserialize (const char *buffer, size_t size)
{
- GNUNET_RPC_CallParameters *ret;
+ struct GNUNET_RPC_CallParameters *ret;
size_t pos;
size_t xpos;
unsigned int dataLength;
@@ -134,15 +142,19 @@
GNUNET_RPC_parameters_destroy (ret);
return NULL;
}
- dataLength = ntohl (*(unsigned int *) &buffer[pos]);
+ memcpy(&dataLength,
+ &buffer[pos],
+ sizeof(unsigned int));
+ dataLength = ntohl(dataLength);
pos += sizeof (unsigned int);
if ((pos + dataLength < pos) || (pos + dataLength > size))
{
GNUNET_RPC_parameters_destroy (ret);
return NULL;
}
-
- GNUNET_RPC_parameters_add (ret, &buffer[xpos], dataLength,
+ GNUNET_RPC_parameters_add (ret,
+ &buffer[xpos],
+ dataLength,
&buffer[pos]);
pos += dataLength;
}
@@ -153,36 +165,26 @@
* How many bytes are required to serialize the param array?
*/
size_t
-GNUNET_RPC_parameters_get_serialized_size (GNUNET_RPC_CallParameters * param)
+GNUNET_RPC_parameters_get_serialized_size (const struct
GNUNET_RPC_CallParameters * param)
{
- int i;
- const char *paramName;
- unsigned int dataLength;
- void *paramValue;
- size_t pos;
+ const struct Parameter *pos;
+ size_t off;
if (param == NULL)
return 0;
- pos = 0;
- dataLength = 0;
- for (i = 0; i < GNUNET_RPC_parameters_count (param); i++)
+ off = 0;
+ pos = param->list;
+ while (pos != NULL) {
{
- paramName = GNUNET_RPC_parameters_get_name (param, i);
- paramValue = NULL;
- GNUNET_RPC_parameters_get_value_by_index (param, i, &dataLength,
- ¶mValue);
- if (pos + strlen (paramName) + 1 + sizeof (unsigned int) < pos)
- return 0;
- pos += strlen (paramName) + 1;
- pos += sizeof (unsigned int);
- if (pos + dataLength < pos)
- return 0;
- pos += dataLength;
+ off += strlen (pos->name) + 1;
+ off += sizeof (unsigned int);
+ off += pos->dataLength;
+ pos = pos->next;
}
- return pos;
+ }
+ return off;
}
-
/**
* Return the number of parameters in an RPC parameter structure.
*
@@ -190,11 +192,19 @@
* @return The number of parameters
*/
unsigned int
-GNUNET_RPC_parameters_count (GNUNET_RPC_CallParameters * param)
+GNUNET_RPC_parameters_count (const struct GNUNET_RPC_CallParameters * param)
{
- if (param == NULL)
- return 0;
- return GNUNET_vector_get_size (param);
+ const struct Parameter *pos;
+ unsigned int s;
+
+ s = 0;
+ pos = param->list;
+ while (pos != NULL)
+ {
+ s++;
+ pos = pos->next;
+ }
+ return s;
}
@@ -211,89 +221,42 @@
*/
void
-GNUNET_RPC_parameters_add (GNUNET_RPC_CallParameters * param,
+GNUNET_RPC_parameters_add (struct GNUNET_RPC_CallParameters * param,
const char *name, unsigned int dataLength,
const void *data)
{
- Parameter *new;
+ struct Parameter *p;
+ struct Parameter *pos;
if (param == NULL)
return;
- new = GNUNET_malloc (sizeof (Parameter));
- new->name = GNUNET_strdup (name);
- new->dataLength = dataLength;
+ p = GNUNET_malloc (sizeof (struct Parameter));
+ p->name = GNUNET_strdup (name);
+ p->dataLength = dataLength;
if (dataLength == 0)
{
- new->data = NULL;
+ p->data = NULL;
}
else
{
- new->data = GNUNET_malloc (dataLength);
- memcpy (new->data, data, dataLength);
+ p->data = GNUNET_malloc (dataLength);
+ memcpy (p->data, data, dataLength);
}
- GNUNET_vector_insert_last (param, new);
-}
-
-
-/**
- * Add a new parameter to the RPC parameter structure. The parameter name and
- * value are copied to memory private to the RPC parameter collection. The
- * pointers returned by other functions point to this private memory and should
- * not be freed by the user of the abstraction.
- *
- * @param param Target RPC parameter structure
- * @param name Name of the parameter
- * @param dataLength Length of the value of the parameter
- * @param data Value of the parameter
- */
-void
-GNUNET_RPC_parameters_add_data_container (GNUNET_RPC_CallParameters * param,
- const char *name,
- const GNUNET_DataContainer * data)
-{
- Parameter *new;
-
- if (param == NULL)
- return;
- new = GNUNET_malloc (sizeof (Parameter));
- new->name = GNUNET_strdup (name);
- new->dataLength = ntohl (data->size) - sizeof (GNUNET_DataContainer);
- if (new->dataLength == 0)
+ p->next = NULL;
+ if (param->list == NULL)
{
- new->data = NULL;
+ param->list = p;
}
else
{
- new->data = GNUNET_malloc (new->dataLength);
- memcpy (new->data, &data[1], new->dataLength);
+ pos = param->list;
+ while (pos->next != NULL)
+ pos = pos->next;
+ pos->next = p;
}
- GNUNET_vector_insert_last (param, new);
}
/**
- * Return the name of the given parameter in the RPC parameter structure, the
- * first parameter being parameter number zero.
- *
- * @param param Target RPC parameter structure
- * @return Name of the parameter
- */
-const char *
-GNUNET_RPC_parameters_get_name (GNUNET_RPC_CallParameters * param,
- unsigned int i)
-{
- Parameter *p;
-
- if (param == NULL)
- return NULL;
- p = GNUNET_vector_get (param, i);
- if (p)
- return p->name;
- else
- return NULL;
-}
-
-
-/**
* Return the value of the named parameter in the RPC parameter structure.
*
* @param param Target RPC parameter structure
@@ -301,16 +264,16 @@
* @return GNUNET_SYSERR on error
*/
int
-GNUNET_RPC_parameters_get_value_by_name (GNUNET_RPC_CallParameters * param,
+GNUNET_RPC_parameters_get_value_by_name (const struct
GNUNET_RPC_CallParameters * param,
const char *name,
unsigned int *dataLength,
- void **value)
+ void const * *value)
{
- Parameter *p;
+ const struct Parameter *p;
if (param == NULL)
return GNUNET_SYSERR;
- p = GNUNET_vector_get_first (param);
+ p = param->list;
while (p != NULL)
{
if (!strcmp (p->name, name))
@@ -319,61 +282,34 @@
*dataLength = p->dataLength;
return GNUNET_OK;
}
- p = GNUNET_vector_get_next (param);
+ p = p->next;
}
-
return GNUNET_SYSERR;
}
/**
- * Return the value of the named parameter in the RPC parameter structure.
- *
- * @param param Target RPC parameter structure
- * @param value set to the value of the named parameter
- * @return GNUNET_SYSERR on error
- */
-GNUNET_DataContainer *
-GNUNET_RPC_parameters_get_data_container_by_name (GNUNET_RPC_CallParameters *
- param, const char *name)
-{
- Parameter *p;
- GNUNET_DataContainer *ret;
-
- if (param == NULL)
- return NULL;
- p = GNUNET_vector_get_first (param);
- while (p != NULL)
- {
- if (!strcmp (p->name, name))
- {
- ret = GNUNET_malloc (sizeof (GNUNET_DataContainer) + p->dataLength);
- ret->size = htonl (sizeof (GNUNET_DataContainer) + p->dataLength);
- memcpy (&ret[1], p->data, p->dataLength);
- return ret;
- }
- p = GNUNET_vector_get_next (param);
- }
-
- return NULL;
-}
-
-/**
* Return the value of the given parameter in the RPC parameter structure.
*
* @param param Target RPC parameter structure
* @param value set to the value of the parameter
*/
int
-GNUNET_RPC_parameters_get_value_by_index (GNUNET_RPC_CallParameters * param,
+GNUNET_RPC_parameters_get_value_by_index (const struct
GNUNET_RPC_CallParameters * param,
unsigned int i,
unsigned int *dataLength,
- void **value)
+ void const **value)
{
- Parameter *p;
+ struct Parameter *p;
if (param == NULL)
return GNUNET_SYSERR;
- p = GNUNET_vector_get (param, i);
+ p = param->list;
+ while ( (i > 0) &&
+ (p != NULL) )
+ {
+ i--;
+ p = p->next;
+ }
if (p != NULL)
{
*dataLength = p->dataLength;
@@ -383,30 +319,4 @@
return GNUNET_SYSERR;
}
-/**
- * Return the value of the given parameter in the RPC parameter structure.
- *
- * @param param Target RPC parameter structure
- * @param value set to the value of the parameter
- */
-GNUNET_DataContainer *
-GNUNET_RPC_parameters_get_data_container_by_index (GNUNET_RPC_CallParameters *
- param, unsigned int i)
-{
- Parameter *p;
- GNUNET_DataContainer *ret;
-
- if (param == NULL)
- return NULL;
- p = GNUNET_vector_get (param, i);
- if (p != NULL)
- {
- ret = GNUNET_malloc (sizeof (GNUNET_DataContainer) + p->dataLength);
- ret->size = htonl (sizeof (GNUNET_DataContainer) + p->dataLength);
- memcpy (&ret[1], p->data, p->dataLength);
- return ret;
- }
- return NULL;
-}
-
/* end of parameters.c */
Modified: GNUnet/src/applications/rpc/parameterstest.c
===================================================================
--- GNUnet/src/applications/rpc/parameterstest.c 2008-02-17 04:58:52 UTC
(rev 6347)
+++ GNUnet/src/applications/rpc/parameterstest.c 2008-02-17 07:50:48 UTC
(rev 6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 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
@@ -29,8 +29,9 @@
int
main (int argc, char *argv[])
{
- GNUNET_RPC_CallParameters *p;
- void *buf;
+ struct GNUNET_RPC_CallParameters *p;
+ const void *buf;
+ void *wbuf;
size_t size;
unsigned int len;
@@ -50,17 +51,12 @@
GNUNET_RPC_parameters_add (p, "bar", 4, "foo");
if (GNUNET_RPC_parameters_count (p) != 2)
return 1;
- if (0 != strcmp (GNUNET_RPC_parameters_get_name (p, 0), "foo"))
- return 1;
- if (0 != strcmp (GNUNET_RPC_parameters_get_name (p, 1), "bar"))
- return 1;
-
size = GNUNET_RPC_parameters_get_serialized_size (p);
- buf = GNUNET_malloc (size);
- GNUNET_RPC_parameters_serialize (p, buf);
+ wbuf = GNUNET_malloc (size);
+ GNUNET_RPC_parameters_serialize (p, wbuf);
GNUNET_RPC_parameters_destroy (p);
- p = GNUNET_RPC_parameters_deserialize (buf, size);
- GNUNET_free (buf);
+ p = GNUNET_RPC_parameters_deserialize (wbuf, size);
+ GNUNET_free (wbuf);
if (p == NULL)
return 1;
buf = NULL;
Modified: GNUnet/src/applications/rpc/rpc.c
===================================================================
--- GNUnet/src/applications/rpc/rpc.c 2008-02-17 04:58:52 UTC (rev 6347)
+++ GNUnet/src/applications/rpc/rpc.c 2008-02-17 07:50:48 UTC (rev 6348)
@@ -1,5 +1,6 @@
/*
This file is part of GNUnet
+ (C) 2003, 2005, 2008 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
@@ -18,8 +19,8 @@
*/
/**
- * @file module/dht_rpc.c
- * @brief Implementation of RPC's
+ * @file rpc/module/rpc.c
+ * @brief Implementation of RPCs
* @author Antti Salonen, Christian Grothoff
*/
@@ -30,566 +31,186 @@
#include "gnunet_rpc_lib.h"
/**
- * Flag that determines if the RPC test will be build as
- * an application module.
+ * Maximum number of concurrent RPCs that we support per peer.
*/
-#define PROVIDE_RPC_TEST GNUNET_YES
+#define RPC_MAX_REQUESTS_PER_PEER 16
/**
- * Print messages helpful for debugging the RPC code.
+ * Maximum number of retries done for sending of responses.
*/
-#define DEBUG_RPC GNUNET_NO
+#define RPC_MAX_REPLY_ATTEMPTS 3
/**
- * Print messages helpful for debugging RPC clients.
+ * Granularity for the RPC cron job.
*/
-#define DEBUG_RPC_CLIENT GNUNET_NO
+#define RPC_CRON_FREQUENCY (500 * GNUNET_CRON_MILLISECONDS)
/**
- * Minimum delay between retry attempts for RPC messages.
- */
-#define MIN_RPC_FREQUENCY (50 * GNUNET_CRON_MILLISECONDS)
-
-/**
* Initial minimum delay between retry attempts for RPC messages
* (before we figure out how fast the connection really is).
*/
-#define INITIAL_RPC_FREQUENCY (15 * GNUNET_CRON_SECONDS)
+#define RPC_INITIAL_ROUND_TRIP_TIME (15 * GNUNET_CRON_SECONDS)
/**
* After what time do we time-out every request (if it is not
* repeated)?
*/
-#define MAX_RPC_TIMEOUT (2 * GNUNET_CRON_MINUTES)
+#define RPC_INTERNAL_PROCESSING_TIMEOUT (2 * GNUNET_CRON_MINUTES)
-#if DEBUG_RPC_CLIENT
-#define RPC_STATUS(a,b,c) GNUNET_GE_LOG(ectx, GNUNET_GE_DEBUG |
GNUNET_GE_REQUEST | GNUNET_GE_USER, "RPC: `%s' (%p) %s at %s\n", a, c, b,
__FUNCTION__);
-#else
-#define RPC_STATUS(a,b,c)
-#endif
-
-
/**
- * Access to GNUnet core API.
+ * @brief Request to execute an function call on the remote peer. The
+ * message is of variable size to pass arguments. Requests and reply
+ * messages use the same struct, the only difference is in the value
+ * of the header.type field.
*/
-static GNUNET_CoreAPIForPlugins *coreAPI = NULL;
-
-/**
- * A mutex for synchronous access to all module-wide data structures. This
- * lock must be held by the thread that accesses any module-wide accessable
- * data structures.
- */
-static struct GNUNET_Mutex *rpcLock;
-
-static struct GNUNET_GE_Context *ectx;
-
-/* *************** RPC registration ****************** */
-
-/**
- * An RPC registered by the local node.
- */
typedef struct
{
- char *name;
+ GNUNET_MessageHeader header;
+
/**
- * Callback for a synchronous RPC. NULL for async RPCs.
+ * Timestamp (of the sender of this message).
*/
- GNUNET_RPC_SynchronousFunction callback;
+ GNUNET_Int32Time timestamp;
+
+ /**
+ * Sequence number (of the initiator).
+ */
+ unsigned int sequenceNumber;
+
+ /**
+ * How important is this message?
+ */
+ unsigned int importance;
/**
- * Callback for an asynchronous RPC. NULL for sync RPCs.
+ * Number of arguments or return values. Must be 0
+ * if this message communicates an error.
*/
- GNUNET_RPC_AsynchronousFunction async_callback;
-} RegisteredRPC;
+ unsigned int argumentCount;
-/**
- * A set of RegisteredRPC structures, one for each RPC registered by the
- * local node.
- */
-static struct GNUNET_Vector *list_of_callbacks;
+ /**
+ * For the request, this is the length of the
+ * name of the function. For a response,
+ * this is the status.
+ */
+ unsigned int functionNameLength;
+} P2P_rpc_MESSAGE;
-
/**
- * Registers an RPC callback under the given name.
- * @param name the name of the callback, must not be NULL
- * @param callback the function to call
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- * (typically if a callback of that name is already in use).
+ * An ACK message. An ACK acknowledges the receiving a reply to an
+ * RPC call (three-way handshake). Without an ACK, the receiver of an
+ * RPC request is supposed to repeatedly send the RPC reply (until it
+ * times out).
*/
-static int
-RPC_register (const char *name, GNUNET_RPC_SynchronousFunction callback)
+typedef struct
{
- RegisteredRPC *rrpc;
+ GNUNET_MessageHeader header;
+ /**
+ * The number of the original request for which this is the
+ * ACK.
+ */
+ unsigned int sequenceNumber;
+} RPC_ACK_Message;
- GNUNET_GE_ASSERT (ectx, name != NULL);
- GNUNET_GE_ASSERT (ectx, callback != NULL);
- GNUNET_mutex_lock (rpcLock);
- rrpc = GNUNET_vector_get_first (list_of_callbacks);
- while (rrpc != NULL)
- {
- if (0 == strcmp (rrpc->name, name))
- {
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("%s::%s - RPC %s:%p could not be registered:"
- " another callback is already using this name
(%p)\n"),
- __FILE__, __FUNCTION__, name, callback,
- rrpc->callback);
- return GNUNET_SYSERR;
- }
- rrpc = GNUNET_vector_get_next (list_of_callbacks);
- }
- rrpc = GNUNET_malloc (sizeof (RegisteredRPC));
- rrpc->name = GNUNET_strdup (name);
- rrpc->callback = callback;
- rrpc->async_callback = NULL;
- GNUNET_vector_insert_last (list_of_callbacks, rrpc);
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "%s::%s - Registered RPC %d: %s\n",
- __FILE__, __FUNCTION__,
- GNUNET_vector_get_size (list_of_callbacks), name);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_OK;
-}
-
/**
- * Registers an async RPC callback under the given name.
- * @param name the name of the callback, must not be NULL
- * @param callback the function to call
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- * (typically if a callback of that name is already in use).
+ * These structures are allocated while a peer
+ * is handling an RPC request.
*/
-static int
-RPC_register_async (const char *name,
- GNUNET_RPC_AsynchronousFunction callback)
+struct GNUNET_RPC_CallHandle
{
- RegisteredRPC *rrpc;
+ struct GNUNET_RPC_CallHandle * next;
- GNUNET_GE_ASSERT (ectx, name != NULL);
- GNUNET_GE_ASSERT (ectx, callback != NULL);
- GNUNET_mutex_lock (rpcLock);
- rrpc = GNUNET_vector_get_first (list_of_callbacks);
- while (rrpc != NULL)
- {
- if (0 == strcmp (rrpc->name, name))
- {
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("%s::%s - RPC %s:%p could not be registered:"
- " another callback is already using this name
(%p)\n"),
- __FILE__, __FUNCTION__, name, callback,
- rrpc->callback);
- return GNUNET_SYSERR;
- }
- rrpc = GNUNET_vector_get_next (list_of_callbacks);
- }
- rrpc = GNUNET_malloc (sizeof (RegisteredRPC));
- rrpc->name = GNUNET_strdup (name);
- rrpc->callback = NULL;
- rrpc->async_callback = callback;
- GNUNET_vector_insert_last (list_of_callbacks, rrpc);
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "%s::%s - Registered asynchronous RPC %d: %s\n",
- __FILE__, __FUNCTION__,
- GNUNET_vector_get_size (list_of_callbacks), name);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_OK;
-}
+ struct GNUNET_RPC_CallHandle * prev;
+ /**
+ * The message we are transmitting. NULL
+ * if our local RPC invocation has not
+ * yet completed. NON-NULL if we are
+ * waiting for the ACK.
+ */
+ P2P_rpc_MESSAGE *msg;
-/**
- * Unregisters an RPC callback of the given name.
- * @param name the name of the callback, must not be NULL
- * @param callback the function to unregister, NULL for any function
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- * (typically if a callback of that name does not exist or is
- * bound to a different function).
- */
-static int
-RPC_unregister (const char *name, GNUNET_RPC_SynchronousFunction callback)
-{
- RegisteredRPC *rrpc;
+ /**
+ * Name of the local RPC function that we
+ * have been calling.
+ */
+ char * function_name;
- GNUNET_GE_ASSERT (ectx, name != NULL);
- GNUNET_mutex_lock (rpcLock);
- rrpc = GNUNET_vector_get_first (list_of_callbacks);
- while (rrpc != NULL)
- {
- if (0 == strcmp (rrpc->name, name))
- {
- if ((rrpc->callback != callback) && (callback != NULL))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK |
- GNUNET_GE_USER,
- _("%s::%s - RPC %s:%p could not be unregistered:"
- " another callback registered under that name:
%p\n"),
- __FILE__, __FUNCTION__, name, callback,
- rrpc->callback);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_SYSERR;
- }
- GNUNET_vector_delete (list_of_callbacks, rrpc);
- GNUNET_free (rrpc->name);
- GNUNET_free (rrpc);
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "%s::%s - Unregistered RPC %s\n", __FILE__,
- __FUNCTION__, name);
- return GNUNET_OK;
- }
- rrpc = GNUNET_vector_get_next (list_of_callbacks);
- }
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _
- ("%s::%s - RPC %s:%p could not be unregistered: not found\n"),
- __FILE__, __FUNCTION__, name, callback);
- return GNUNET_SYSERR;
-}
+ /**
+ * For which peer is this response?
+ */
+ GNUNET_PeerIdentity initiator;
-/**
- * Unregisters an asynchronous RPC callback of the given name.
- * @param name the name of the callback, must not be NULL
- * @param callback the function to unregister, NULL for any function
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- * (typically if a callback of that name does not exist or is
- * bound to a different function).
- */
-static int
-RPC_unregister_async (const char *name,
- GNUNET_RPC_AsynchronousFunction callback)
-{
- RegisteredRPC *rrpc;
-
- GNUNET_GE_ASSERT (ectx, name != NULL);
- GNUNET_mutex_lock (rpcLock);
- rrpc = GNUNET_vector_get_first (list_of_callbacks);
- while (rrpc != NULL)
- {
- if (0 == strcmp (rrpc->name, name))
- {
- if ((rrpc->async_callback != callback) && (callback != NULL))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK |
- GNUNET_GE_USER,
- _("%s::%s - RPC %s:%p could not be unregistered:"
- " another callback registered under that name:
%p\n"),
- __FILE__, __FUNCTION__, name, callback,
- rrpc->callback);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_SYSERR;
- }
- GNUNET_vector_delete (list_of_callbacks, rrpc);
- GNUNET_free (rrpc->name);
- GNUNET_free (rrpc);
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "%s::%s - Unregistered asynchronous RPC %s\n",
- __FILE__, __FUNCTION__, name);
- return GNUNET_OK;
- }
- rrpc = GNUNET_vector_get_next (list_of_callbacks);
- }
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _
- ("%s::%s - async RPC %s:%p could not be unregistered: not
found\n"),
- __FILE__, __FUNCTION__, name, callback);
- return GNUNET_SYSERR;
-}
-
-
-/* ******** tracking per peer stats to estimate turnaround ***** */
-
-/**
- * What is the time-interval for which we keep activity stats?
- */
-#define PEER_TRACKING_TIME_INTERVAL (30 * GNUNET_CRON_SECONDS)
-
-/**
- * Of how many messages do we keep track per peer (for statistics).
- */
-#define MTRACK_COUNT 64
-
-/**
- * A per-peer structure to store TCP-like data.
- */
-typedef struct
-{
- GNUNET_PeerIdentity identity;
-
/**
- * What is the expected response time for this peer? (0 for unknown)
+ * Time where this record times out (timeout value for original
+ * request, fixed timeout for reply if no further requests are
+ * received; once we send the ACK the record of the sender is
+ * discarded; we always send additional ACKs even if we don't have a
+ * matching record anymore).
*/
- GNUNET_CronTime averageResponseTime;
+ GNUNET_CronTime expirationTime;
/**
- * In which of the last 32 time intervals did we send a message?
- * (highest bit corresponds to last time interval; if zero,
- * the record is to be freed).
+ * Frequency at which we currently repeat the message. Initially
+ * set to the round-trip estimate, with exponential back-off.
*/
- unsigned int agedActivitySend;
+ GNUNET_CronTime repetitionFrequency;
/**
- * In which of the last 32 time intervals did we receive a message?
- * (highest bit corresponds to last time interval; if zero,
- * the record is to be freed).
+ * Last time the message was sent.
*/
- unsigned int agedActivityRecv;
+ GNUNET_CronTime lastAttempt;
/**
- * What were the last times when requests were send to the peer?
- * 0 for no request send *or* last request was repeated.
+ * Number of times we have attempted to transmit.
*/
- GNUNET_CronTime lastRequestTimes[MTRACK_COUNT];
+ unsigned int attempts;
/**
- * Message ID of the last requests.
+ * Error code for the response.
*/
- unsigned int lastRequestId[MTRACK_COUNT];
+ unsigned int errorCode;
/**
- * Index to the smallest value in lastRequestTimes.
+ * The sequence number of this RPC.
*/
- unsigned int oldestRTIndex;
+ unsigned int sequenceNumber;
-} PeerInfo;
+ /**
+ * How important is this RPC?
+ */
+ unsigned int importance;
+};
/**
- * A set of Peer structures, one for each GNUnet peer (as identified by
- * GNUNET_PeerIdentity) known to the RPC module. Peers are added as either
RPC's
- * are made to them from the local node, or an RPC call is received from them.
+ * These structures are allocated while a peer
+ * is waiting for a remote RPC to return a result.
*/
-static struct GNUNET_Vector *peerInformation;
-
-static PeerInfo *
-getPeerInfo (const GNUNET_PeerIdentity * id)
+struct GNUNET_RPC_RequestHandle
{
- PeerInfo *pi;
+ struct GNUNET_RPC_RequestHandle * next;
- pi = (PeerInfo *) GNUNET_vector_get_first (peerInformation);
- while (pi != NULL)
- {
- if (0 == memcmp (id, &pi->identity, sizeof (GNUNET_PeerIdentity)))
- return pi;
- pi = (PeerInfo *) GNUNET_vector_get_next (peerInformation);
- }
- return NULL;
-}
+ struct GNUNET_RPC_RequestHandle * prev;
-/**
- * What is the expected response time for this peer?
- * @return 0 for unknown
- */
-static GNUNET_CronTime
-getExpectedResponseTime (const GNUNET_PeerIdentity * peer)
-{
- GNUNET_CronTime result;
- PeerInfo *pi;
-
- GNUNET_mutex_lock (rpcLock);
- pi = getPeerInfo (peer);
- if (pi == NULL)
- result = 0;
- else
- result = pi->averageResponseTime;
- GNUNET_mutex_unlock (rpcLock);
- return result;
-}
-
-/**
- * Cron-job used to age the peer statistics.
- */
-static void
-agePeerStats (void *unused)
-{
- PeerInfo *pi;
-
- GNUNET_mutex_lock (rpcLock);
- pi = GNUNET_vector_get_first (peerInformation);
- while (pi != NULL)
- {
- pi->agedActivitySend = pi->agedActivitySend / 2;
- pi->agedActivityRecv = pi->agedActivityRecv / 2;
- if ((pi->agedActivitySend == 0) && (pi->agedActivityRecv == 0))
- {
- GNUNET_vector_delete (peerInformation, pi);
- GNUNET_free (pi);
- }
-
- pi = GNUNET_vector_get_next (peerInformation);
- }
- GNUNET_mutex_unlock (rpcLock);
-}
-
-/**
- * Ensure replies and requests have different IDs when dealing
- * with the same peer.
- */
-#define MINGLE(a,b) (((b) == GNUNET_P2P_PROTO_RPC_RES) ? (a) : (a) ^
0x12345678)
-
-/**
- * Notification: we sent a message to the peer.
- * @param messageID pseudo-unique ID of the request
- */
-static void
-notifyPeerRequest (GNUNET_PeerIdentity * peer, unsigned int messageID)
-{
- int i;
- PeerInfo *pi;
-
- GNUNET_mutex_lock (rpcLock);
- pi = getPeerInfo (peer);
- if (pi != NULL)
- {
- for (i = 0; i < MTRACK_COUNT; i++)
- {
- if (pi->lastRequestId[i] == messageID)
- {
- pi->lastRequestTimes[i] = 0; /* re-send! */
- GNUNET_mutex_unlock (rpcLock);
- return;
- }
- }
- pi->agedActivitySend |= 0x80000000;
- pi->lastRequestTimes[pi->oldestRTIndex] = GNUNET_get_time ();
- pi->lastRequestId[pi->oldestRTIndex] = messageID;
- pi->oldestRTIndex = (pi->oldestRTIndex + 1) % MTRACK_COUNT;
- GNUNET_mutex_unlock (rpcLock);
- return;
- }
- pi = GNUNET_malloc (sizeof (PeerInfo));
- memset (pi, 0, sizeof (PeerInfo));
- pi->identity = *peer;
- pi->agedActivitySend = 0x80000000;
- pi->lastRequestTimes[0] = GNUNET_get_time ();
- pi->lastRequestId[0] = messageID;
- pi->oldestRTIndex = 1;
- GNUNET_vector_insert_last (peerInformation, pi);
- GNUNET_mutex_unlock (rpcLock);
-}
-
-/**
- * Notification: we received a (valid) response from the peer.
- * @param messageID the ID of the message that a reply was received
- * for
- */
-static void
-notifyPeerReply (const GNUNET_PeerIdentity * peer, unsigned int messageID)
-{
- int i;
- PeerInfo *pi;
-
- GNUNET_mutex_lock (rpcLock);
- pi = GNUNET_vector_get_first (peerInformation);
- while (pi != NULL)
- {
- if (0 == memcmp (peer, &pi->identity, sizeof (GNUNET_PeerIdentity)))
- {
- for (i = 0; i < MTRACK_COUNT; i++)
- {
- if (pi->lastRequestId[i] == messageID)
- {
- if (pi->lastRequestTimes[i] != 0)
- { /* resend */
- pi->averageResponseTime
- = (pi->averageResponseTime * (MTRACK_COUNT - 1) +
- GNUNET_get_time () -
- pi->lastRequestTimes[i]) / MTRACK_COUNT;
- pi->agedActivityRecv |= 0x80000000;
- pi->lastRequestTimes[i] = 0;
- }
- GNUNET_mutex_unlock (rpcLock);
- return;
- }
- }
- break;
- }
- pi = GNUNET_vector_get_next (peerInformation);
- }
- GNUNET_mutex_unlock (rpcLock);
-}
-
-/* ***************** RPC datastructures ****************** */
-
-
-/**
- * @brief Request to execute an function call on the remote peer. The
- * message is of variable size to pass arguments. Requests and reply
- * messages use the same struct, the only difference is in the value
- * of the header.type field. For the reply, the
- * functionNameLength indicates the status (0 for GNUNET_OK, otherwise an
- * error code). argumentCount must be 0 for errors and otherwise
- * indicate the number of return values.
- */
-typedef struct
-{
- GNUNET_MessageHeader header;
- GNUNET_Int32Time timestamp;
- unsigned int sequenceNumber;
- unsigned int importance;
- unsigned short argumentCount;
- unsigned short functionNameLength;
-} P2P_rpc_MESSAGE;
-
-/**
- * An ACK message. An ACK acknowledges the receiving a reply to an
- * RPC call (three-way handshake). Without an ACK, the receiver of an
- * RPC request is supposed to repeatedly send the RPC reply (until it
- * times out).
- */
-typedef struct
-{
- GNUNET_MessageHeader header;
/**
- * The number of the original request for which this is the
- * ACK.
+ * The message we are transmitting.
*/
- unsigned int sequenceNumber;
-} RPC_ACK_Message;
+ P2P_rpc_MESSAGE *msg;
-/**
- * GNUNET_RSA_Signature of a function called on completion of
- * the RPC.
- * @param context closure
- * @param sequenceNumber ID of the callback
- * @param errorCode 0 on success
- * @param result the return values, NULL on error
- */
-typedef void (*RPCFinishedCallback) (void *context,
- unsigned int sequenceNumber,
- unsigned short errorCode,
- GNUNET_RPC_CallParameters * result);
-
-/**
- * A per-RPC structure.
- */
-typedef struct GNUNET_RPC_CallHandle
-{
/**
- * The sequence number of this RPC.
+ * Function to call once we get a reply.
*/
- unsigned int sequenceNumber;
+ GNUNET_RPC_AsynchronousCompletionCallback callback;
+ void * cls;
+
/**
- * For which peer is this message?
+ * To which peer are we sending the request?
*/
GNUNET_PeerIdentity receiver;
/**
- * The message we are transmitting (either the request or the
- * reply).
- */
- P2P_rpc_MESSAGE *msg;
-
- /**
* Time where this record times out (timeout value for original
* request, fixed timeout for reply if no further requests are
* received; once we send the ACK the record of the sender is
@@ -608,41 +229,68 @@
* Last time the message was sent.
*/
GNUNET_CronTime lastAttempt;
-
+
/**
+ * The sequence number of this RPC.
+ */
+ unsigned int sequenceNumber;
+
+ /**
* Number of times we have attempted to transmit.
*/
unsigned int attempts;
+ /**
+ * How important is this RPC?
+ */
+ unsigned int importance;
+
/**
- * If this was a request initiated by this node we'll have to pass
- * the result back to the original caller. This gives the method
- * and some context args that needs to be invoked.
+ * Error code for the response.
*/
- RPCFinishedCallback finishedCallback;
+ unsigned int errorCode;
+};
+/**
+ * List of RPC handlers registered by the local node.
+ */
+struct RegisteredRPC
+{
+ struct RegisteredRPC * next;
+
/**
- * Arguments to the callback.
+ * Name of the RPC.
*/
- void *rpcCallbackArgs;
+ char *name;
- /**
- * How important is this RPC?
- */
- unsigned int importance;
-} CallInstance;
+ /**
+ * Callback for an asynchronous RPC.
+ */
+ GNUNET_RPC_AsynchronousFunction async_callback;
+ /**
+ * Extra argument to async_callback.
+ */
+ void * cls;
+};
+
/**
+ * A set of RegisteredRPC structures, one for each RPC registered by the
+ * local node.
+ */
+static struct RegisteredRPC *list_of_callbacks;
+
+/**
* A set of GNUNET_RPC_CallHandle structures for active incoming rpc calls.
* (requests without a reply).
*/
-static struct GNUNET_Vector *incomingCalls;
+static struct GNUNET_RPC_CallHandle *incomingCalls;
/**
- * A set of GNUNET_RPC_CallHandle structures for active outgoing rpc calls.
- * (reply messages without an ACK).
+ * Linked list active outgoing rpc calls.
+ * (waiting for function and reply messages without an ACK).
*/
-static struct GNUNET_Vector *outgoingCalls;
+static struct GNUNET_RPC_RequestHandle *outgoingCalls;
/**
* A counter whose value is used for identifying the RPC's originating
@@ -650,133 +298,120 @@
* RPC and thus its value also tells the number of RPC's originated from the
* local node (modulo integer overflow).
*/
-static unsigned int rpcIdentifier = 0;
+static unsigned int rpcIdentifier;
/**
- * Cron-job that processes the RPC queues. Created for
- * each GNUNET_RPC_CallHandle. Not renewed if the call times out,
- * deleted if the appropriate response is received.
+ * Access to GNUnet core API.
*/
-static void
-retryRPCJob (void *ctx)
+static GNUNET_CoreAPIForPlugins *coreAPI;
+
+/**
+ * A mutex for synchronous access to all module-wide data structures. This
+ * lock must be held by the thread that accesses any module-wide accessable
+ * data structures.
+ */
+static struct GNUNET_Mutex *lock;
+
+/**
+ * Registers an async RPC callback under the given name.
+ * @param name the name of the callback, must not be NULL
+ * @param callback the function to call
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ * (typically if a callback of that name is already in use).
+ */
+static int
+RPC_register (const char *name,
+ GNUNET_RPC_AsynchronousFunction callback,
+ void * cls)
{
- CallInstance *call = ctx;
- GNUNET_CronTime now;
+ struct RegisteredRPC *rrpc;
- now = GNUNET_get_time ();
- GNUNET_GE_ASSERT (ectx,
- (GNUNET_get_time () + 1 * GNUNET_CRON_MINUTES >
- call->expirationTime)
- || (call->expirationTime - GNUNET_get_time () <
- 1 * GNUNET_CRON_HOURS));
- GNUNET_mutex_lock (rpcLock);
- if (now > call->expirationTime)
+ GNUNET_GE_ASSERT (coreAPI->ectx, name != NULL);
+ GNUNET_GE_ASSERT (coreAPI->ectx, callback != NULL);
+ GNUNET_mutex_lock (lock);
+ rrpc = list_of_callbacks;
+ while (rrpc != NULL)
{
-#if DEBUG_RPC
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Completed RPC %p (timeout).\n", call);
-#endif
- if (call->finishedCallback != NULL)
+ if (0 == strcmp (rrpc->name, name))
{
- call->finishedCallback (call->rpcCallbackArgs,
- call->sequenceNumber,
- GNUNET_RPC_ERROR_TIMEOUT, NULL);
- GNUNET_vector_delete (outgoingCalls, call);
+ GNUNET_mutex_unlock (lock);
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("%s::%s - RPC %s:%p could not be registered:"
+ " another callback is already using this name
(%p)\n"),
+ __FILE__, __FUNCTION__, name, callback,
+ rrpc->async_callback);
+ return GNUNET_SYSERR;
}
- else
- {
- GNUNET_vector_delete (incomingCalls, call);
- }
- GNUNET_free (call->msg);
- GNUNET_free (call);
+ rrpc = rrpc->next;
}
- else
- {
- if ((coreAPI != NULL)
- && (call->expirationTime - now > 50 * GNUNET_CRON_MILLISECONDS))
- {
- unsigned int maxdelay;
-
- if (call->repetitionFrequency == 0)
- {
- call->repetitionFrequency
- = getExpectedResponseTime (&call->receiver) * 2;
- if (call->repetitionFrequency == 0)
- call->repetitionFrequency = INITIAL_RPC_FREQUENCY;
- if (call->repetitionFrequency < MIN_RPC_FREQUENCY)
- call->repetitionFrequency = MIN_RPC_FREQUENCY;
- }
- else
- call->repetitionFrequency = 2 * call->repetitionFrequency;
- maxdelay = (now - call->expirationTime) / 2;
- if (maxdelay > call->repetitionFrequency / 2)
- maxdelay = call->repetitionFrequency / 2;
- notifyPeerRequest (&call->receiver,
- MINGLE (call->sequenceNumber,
- ntohs (call->msg->header.type)));
-#if DEBUG_RPC
- if (ntohs (call->msg->header.type) == GNUNET_P2P_PROTO_RPC_REQ)
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
- GNUNET_GE_USER,
- "Sending RPC request %p: '%.*s' (expires in
%llums, last attempt %llums ago; attempt %u).\n",
- call, ntohs (call->msg->functionNameLength),
- &call->msg[1], call->expirationTime - now,
- now - call->lastAttempt, call->attempts);
- }
- else
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
- GNUNET_GE_USER,
- "Sending RPC reply %p (expires in %llums, last
attempt %llums ago, attempt %u).\n",
- call, call->expirationTime - now,
- now - call->lastAttempt, call->attempts);
- }
-#endif
- call->lastAttempt = now;
- call->attempts++;
- coreAPI->unicast (&call->receiver,
- &call->msg->header,
- ntohl (call->msg->importance), maxdelay);
- }
- GNUNET_GE_ASSERT (ectx,
- (GNUNET_get_time () + 1 * GNUNET_CRON_MINUTES >
- call->expirationTime)
- || (call->expirationTime - GNUNET_get_time () <
- 1 * GNUNET_CRON_HOURS));
- GNUNET_cron_add_job (coreAPI->cron, &retryRPCJob,
- call->repetitionFrequency, 0, call);
- }
- GNUNET_mutex_unlock (rpcLock);
+ rrpc = GNUNET_malloc(sizeof(struct RegisteredRPC));
+ rrpc->name = GNUNET_strdup (name);
+ rrpc->async_callback = callback;
+ rrpc->cls = cls;
+ rrpc->next = list_of_callbacks;
+ list_of_callbacks = rrpc;
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_OK;
}
/**
- * Send an ACK message.
+ * Unregisters an asynchronous RPC callback of the given name.
+ * @param name the name of the callback, must not be NULL
+ * @param callback the function to unregister, NULL for any function
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ * (typically if a callback of that name does not exist or is
+ * bound to a different function).
*/
-static void
-sendAck (const GNUNET_PeerIdentity * receiver,
- unsigned int sequenceNumber,
- unsigned int importance, unsigned int maxDelay)
+static int
+RPC_unregister (const char *name,
+ GNUNET_RPC_AsynchronousFunction callback,
+ void * cls)
{
- RPC_ACK_Message msg;
+ struct RegisteredRPC *pos;
+ struct RegisteredRPC *prev;
- msg.header.size = htons (sizeof (RPC_ACK_Message));
- msg.header.type = htons (GNUNET_P2P_PROTO_RPC_ACK);
- msg.sequenceNumber = htonl (sequenceNumber);
- coreAPI->unicast (receiver, &msg.header, importance, maxDelay);
+ GNUNET_GE_ASSERT (NULL, NULL == incomingCalls);
+ GNUNET_GE_ASSERT (coreAPI->ectx, name != NULL);
+ GNUNET_mutex_lock (lock);
+ prev = NULL;
+ pos = list_of_callbacks;
+ while (pos != NULL)
+ {
+ if ( (0 == strcmp (pos->name, name)) &&
+ (pos->async_callback == callback) &&
+ (pos->cls == cls) )
+ {
+ if (prev == NULL)
+ list_of_callbacks = pos->next;
+ else
+ prev->next = pos->next;
+ GNUNET_free(pos->name);
+ GNUNET_free(pos);
+ }
+ prev = pos;
+ pos = pos->next;
+ }
+ GNUNET_mutex_unlock (lock);
+ GNUNET_GE_LOG (coreAPI->ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK |
GNUNET_GE_USER,
+ _
+ ("%s::%s - async RPC %s:%p could not be unregistered: not
found\n"),
+ __FILE__, __FUNCTION__, name, callback);
+ return GNUNET_SYSERR;
}
+/**
+ * Get the name of the RPC function.
+ */
static char *
-getFunctionName (P2P_rpc_MESSAGE * req)
+RPC_get_function_name (const P2P_rpc_MESSAGE * req)
{
char *ret;
- unsigned short slen;
+ unsigned int slen;
- slen = ntohs (req->functionNameLength);
- if (ntohs (req->header.size) < sizeof (P2P_rpc_MESSAGE) + slen)
+ slen = ntohl (req->functionNameLength);
+ if ( (ntohs (req->header.size) < sizeof (P2P_rpc_MESSAGE) + slen) ||
+ (sizeof(P2P_rpc_MESSAGE) + slen < sizeof(P2P_rpc_MESSAGE) ) )
return NULL; /* invalid! */
ret = GNUNET_malloc (slen + 1);
memcpy (ret, &req[1], slen);
@@ -784,17 +419,22 @@
return ret;
}
-static GNUNET_RPC_CallParameters *
-deserializeArguments (P2P_rpc_MESSAGE * req)
+/**
+ * Get the arguments (or return value) from
+ * the request.
+ */
+static struct GNUNET_RPC_CallParameters *
+RPC_deserialize_arguments (const P2P_rpc_MESSAGE * req)
{
- unsigned short slen;
- GNUNET_RPC_CallParameters *ret;
+ unsigned int slen;
+ struct GNUNET_RPC_CallParameters *ret;
if (ntohs (req->header.type) == GNUNET_P2P_PROTO_RPC_REQ)
- slen = ntohs (req->functionNameLength);
+ slen = ntohl (req->functionNameLength);
else
slen = 0;
- if (ntohs (req->header.size) < sizeof (P2P_rpc_MESSAGE) + slen)
+ if ( (ntohs (req->header.size) < sizeof (P2P_rpc_MESSAGE) + slen) ||
+ (sizeof(P2P_rpc_MESSAGE) + slen < sizeof(P2P_rpc_MESSAGE) ) )
return NULL; /* invalid! */
ret =
GNUNET_RPC_parameters_deserialize (&((char *) &req[1])[slen],
@@ -809,8 +449,25 @@
}
/**
+ * Send an ACK message.
+ */
+static void
+RPC_send_ack (const GNUNET_PeerIdentity * receiver,
+ unsigned int sequenceNumber,
+ unsigned int importance, unsigned int maxDelay)
+{
+ RPC_ACK_Message msg;
+
+ msg.header.size = htons (sizeof (RPC_ACK_Message));
+ msg.header.type = htons (GNUNET_P2P_PROTO_RPC_ACK);
+ msg.sequenceNumber = htonl (sequenceNumber);
+ coreAPI->unicast (receiver, &msg.header, importance, maxDelay);
+}
+
+/**
* Build an RPC message serializing the name and values
* properly.
+ *
* @param errorCode the status code for the message, if non-NULL
* values will be NULL
* @param name the name of the target method, NULL for a reply.
@@ -819,88 +476,77 @@
* @return the RPC message to transmit, caller must free
*/
static P2P_rpc_MESSAGE *
-buildMessage (unsigned short errorCode,
- const char *name,
- unsigned int sequenceNumber,
- unsigned int importance, GNUNET_RPC_CallParameters * values)
+RPC_build_message (unsigned short errorCode,
+ const char *name,
+ unsigned int sequenceNumber,
+ unsigned int importance,
+ const struct GNUNET_RPC_CallParameters * values)
{
P2P_rpc_MESSAGE *ret;
size_t size = sizeof (P2P_rpc_MESSAGE);
int slen;
if (name != NULL)
- {
- slen = strlen (name);
- size += slen;
- }
+ slen = strlen (name);
else
- slen = 0;
+ slen = 0;
+ size += slen;
if (values != NULL)
size += GNUNET_RPC_parameters_get_serialized_size (values);
if (size >= GNUNET_MAX_BUFFER_SIZE)
return NULL; /* message to big! */
ret = GNUNET_malloc (size);
ret->header.size = htons (size);
+ ret->header.type = htons ((name == NULL) ? GNUNET_P2P_PROTO_RPC_RES :
GNUNET_P2P_PROTO_RPC_REQ);
ret->timestamp = htonl (GNUNET_get_time_int32 (NULL));
ret->sequenceNumber = htonl (sequenceNumber);
ret->importance = htonl (importance);
if (name == NULL)
- ret->functionNameLength = htons (errorCode);
+ ret->functionNameLength = htonl (errorCode);
else
- ret->functionNameLength = htons (slen);
- ret->argumentCount = htons (GNUNET_RPC_parameters_count (values));
+ ret->functionNameLength = htonl (slen);
+ ret->argumentCount = htonl (GNUNET_RPC_parameters_count (values));
if (name != NULL)
- {
- memcpy (&ret[1], name, slen);
- }
+ memcpy (&ret[1], name, slen);
GNUNET_RPC_parameters_serialize (values, &((char *) &ret[1])[slen]);
-
- if (name == NULL)
- ret->header.type = htons (GNUNET_P2P_PROTO_RPC_RES);
- else
- ret->header.type = htons (GNUNET_P2P_PROTO_RPC_REQ);
-
return ret;
}
+
/* ***************** RPC P2P message handlers **************** */
-
/**
- * GNUNET_RSA_Signature of the callback function for the ASYNC_RPC to
- * be called upon completion of the ASYNC function. Initiates
- * sending back the reply. Also called in the synchronous RPC
- * case o complete the reply (since it's the same code).
+ * Function called to communicate the return value of
+ * an RPC to the peer that initiated it.
*/
static void
-async_rpc_complete_callback (GNUNET_RPC_CallParameters * results,
- int errorCode, CallInstance * calls)
+RPC_complete (const struct GNUNET_RPC_CallParameters * results,
+ int errorCode,
+ struct GNUNET_RPC_CallHandle * call)
{
- GNUNET_mutex_lock (rpcLock);
- /* build reply message */
- calls->msg = buildMessage (errorCode,
- NULL,
- calls->sequenceNumber,
- calls->importance, results);
- if (calls->msg == NULL)
- calls->msg = buildMessage (GNUNET_RPC_ERROR_RETURN_VALUE_TOO_LARGE,
- NULL,
- calls->sequenceNumber,
- calls->importance, results);
- GNUNET_vector_insert_last (incomingCalls, calls);
-
- GNUNET_GE_ASSERT (ectx,
- (GNUNET_get_time () + 1 * GNUNET_CRON_MINUTES >
- calls->expirationTime)
- || (calls->expirationTime - GNUNET_get_time () <
- 1 * GNUNET_CRON_HOURS));
- /* for right now: schedule cron job to send reply! */
- GNUNET_cron_add_job (coreAPI->cron, &retryRPCJob, 0, 0, calls);
- GNUNET_mutex_unlock (rpcLock);
+ GNUNET_mutex_lock (lock);
+ GNUNET_GE_ASSERT(NULL, call->msg == NULL);
+ call->msg = RPC_build_message (errorCode,
+ NULL,
+ call->sequenceNumber,
+ call->importance, results);
+ if (call->msg == NULL)
+ call->msg = RPC_build_message (GNUNET_RPC_ERROR_RETURN_VALUE_TOO_LARGE,
+ NULL,
+ call->sequenceNumber,
+ call->importance, results);
+ call->lastAttempt = GNUNET_get_time();
+ call->repetitionFrequency = RPC_INITIAL_ROUND_TRIP_TIME;
+ call->attempts = 1;
+ call->errorCode = errorCode;
+ coreAPI->unicast(&call->initiator,
+ &call->msg->header,
+ call->importance,
+ RPC_INITIAL_ROUND_TRIP_TIME / 2);
+ GNUNET_mutex_unlock (lock);
}
-
/**
* Handle request for remote function call. Checks if message
* has been seen before, if not performs the call and sends
@@ -910,233 +556,169 @@
handleRPCMessageReq (const GNUNET_PeerIdentity * sender,
const GNUNET_MessageHeader * message)
{
- P2P_rpc_MESSAGE *req;
- CallInstance *calls;
+ const P2P_rpc_MESSAGE * req;
+ struct GNUNET_RPC_CallHandle * pos;
+ struct GNUNET_RPC_CallParameters *argumentValues;
+ const struct RegisteredRPC *rpc;
unsigned int sq;
- unsigned short errorCode;
+ unsigned int total;
char *functionName;
- GNUNET_RPC_CallParameters *argumentValues;
- GNUNET_RPC_CallParameters *returnValues;
- RegisteredRPC *rpc;
- unsigned int minSQ;
- if ((ntohs (message->type) != GNUNET_P2P_PROTO_RPC_REQ) ||
- (ntohs (message->size) < sizeof (P2P_rpc_MESSAGE)))
+ if (ntohs (message->size) < sizeof (P2P_rpc_MESSAGE))
{
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_REQUEST | GNUNET_GE_ADMIN,
- _("Invalid message of type %u received. Dropping.\n"),
- ntohs (message->type));
+ GNUNET_GE_BREAK_OP(NULL, 0);
return GNUNET_SYSERR;
}
- req = (P2P_rpc_MESSAGE *) message;
- sq = ntohl (req->sequenceNumber);
-#if DEBUG_RPC
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Received RPC request with id %u.\n", sq);
-#endif
- GNUNET_mutex_lock (rpcLock);
-
- /* check if message is already in incomingCalls,
- if so, update expiration, otherwise deserialize,
- perform call, add reply and create cron job */
-
- calls = GNUNET_vector_get_first (incomingCalls);
- if (calls == NULL)
- minSQ = 0;
- else
- minSQ = 0xFFFFFFFF;
- while (calls != NULL)
+ req = (const P2P_rpc_MESSAGE *) message;
+ functionName = RPC_get_function_name (req);
+ if (functionName == NULL)
{
- if (calls->sequenceNumber < minSQ)
- minSQ = calls->sequenceNumber;
- if ((calls->sequenceNumber == sq) &&
- (0 ==
- memcmp (&calls->receiver, sender, sizeof (GNUNET_PeerIdentity))))
- break;
- calls = GNUNET_vector_get_next (incomingCalls);
+ GNUNET_GE_BREAK_OP(NULL, 0);
+ return GNUNET_SYSERR;
}
- if (calls != NULL)
+ argumentValues = RPC_deserialize_arguments (req);
+ if (argumentValues == NULL)
{
- PeerInfo *pi = getPeerInfo (sender);
-
- if (pi != NULL)
- {
- if (pi->averageResponseTime < MAX_RPC_TIMEOUT / 2)
- pi->averageResponseTime *= 2;
- }
- RPC_STATUS ("", "received duplicate request", calls);
- calls->expirationTime = GNUNET_get_time () + MAX_RPC_TIMEOUT;
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Dropping RPC request %u, duplicate.\n", sq);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_OK; /* seen before */
+ GNUNET_free (functionName);
+ GNUNET_GE_BREAK_OP(NULL, 0);
+ return GNUNET_SYSERR; /* message malformed */
}
- if (minSQ > sq)
+ sq = ntohl (req->sequenceNumber);
+
+ /* check if message is already in incomingCalls! */
+ GNUNET_mutex_lock (lock);
+ pos = incomingCalls;
+ total = 0;
+ while ( (pos != NULL) &&
+ ( (pos->sequenceNumber != sq) ||
+ (0 != memcmp(&pos->initiator,
+ sender,
+ sizeof(GNUNET_PeerIdentity)))) )
{
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Dropping RPC request %u, sequence number too old
(current minimum is %u).\n",
- sq, minSQ);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_OK; /* seen before */
+ if (0 == memcmp(&pos->initiator,
+ sender,
+ sizeof(GNUNET_PeerIdentity)))
+ total++;
+ pos = pos->next;
}
-
- /* deserialize */
- functionName = getFunctionName (req);
- argumentValues = deserializeArguments (req);
- if ((functionName == NULL) || (argumentValues == NULL))
+ if ( (pos != NULL) ||
+ (total > RPC_MAX_REQUESTS_PER_PEER) )
{
- GNUNET_free_non_null (functionName);
- if (argumentValues != NULL)
- GNUNET_RPC_parameters_destroy (argumentValues);
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("Dropping RPC request %u: message malformed.\n"));
- return GNUNET_SYSERR; /* message malformed */
+ /* already pending or too many pending */
+ GNUNET_free (functionName);
+ GNUNET_RPC_parameters_destroy(argumentValues);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
}
/* find matching RPC function */
- rpc = (RegisteredRPC *) GNUNET_vector_get_first (list_of_callbacks);
+ rpc = list_of_callbacks;
while (rpc != NULL)
{
if (0 == strcmp (functionName, rpc->name))
break;
- rpc = (RegisteredRPC *) GNUNET_vector_get_next (list_of_callbacks);
+ rpc = rpc->next;
}
- calls = GNUNET_malloc (sizeof (CallInstance));
- RPC_STATUS (functionName, "received request", calls);
- GNUNET_free (functionName);
- calls->sequenceNumber = sq;
- calls->receiver = *sender;
- calls->expirationTime = GNUNET_get_time () + MAX_RPC_TIMEOUT;
- calls->lastAttempt = 0;
- calls->attempts = 0;
- calls->finishedCallback = NULL;
- calls->rpcCallbackArgs = NULL;
- calls->importance = ntohl (req->importance);
-
- /* if possible, perform RPC call */
+ /* create call handle */
+ pos = GNUNET_malloc (sizeof (struct GNUNET_RPC_CallHandle));
+ memset(pos, 0, sizeof (struct GNUNET_RPC_CallHandle));
+ pos->function_name = functionName;
+ pos->sequenceNumber = sq;
+ pos->initiator = *sender;
+ pos->expirationTime = GNUNET_get_time () + RPC_INTERNAL_PROCESSING_TIMEOUT;
+ pos->importance = ntohl (req->importance);
+ pos->next = incomingCalls;
+ if (incomingCalls != NULL)
+ incomingCalls->prev = pos;
+ incomingCalls = pos;
if (rpc == NULL)
- {
- GNUNET_RPC_parameters_destroy (argumentValues);
- returnValues = NULL;
- errorCode = GNUNET_RPC_ERROR_UNKNOWN_FUNCTION;
- }
+ RPC_complete(NULL,
+ GNUNET_RPC_ERROR_UNKNOWN_FUNCTION,
+ pos);
else
- {
- if (rpc->callback == NULL)
- {
- /* asynchronous RPC */
- rpc->async_callback (sender,
- argumentValues,
- &async_rpc_complete_callback, calls);
- GNUNET_mutex_unlock (rpcLock);
- return GNUNET_OK;
- }
- returnValues = GNUNET_RPC_parameters_create ();
- rpc->callback (sender, argumentValues, returnValues);
- GNUNET_RPC_parameters_destroy (argumentValues);
- errorCode = GNUNET_RPC_ERROR_OK;
- }
- GNUNET_mutex_unlock (rpcLock);
- async_rpc_complete_callback (returnValues, errorCode, calls);
+ rpc->async_callback (rpc->cls,
+ sender,
+ argumentValues,
+ pos);
+ GNUNET_RPC_parameters_destroy (argumentValues);
+ GNUNET_mutex_unlock (lock);
return GNUNET_OK;
}
/**
* Handle reply for request for remote function call. Checks
- * if we are waiting for a reply, if so triggers the reply.
+ * if we are waiting for a reply, if so triggers the callback.
* Also always sends an ACK.
*/
static int
handleRPCMessageRes (const GNUNET_PeerIdentity * sender,
const GNUNET_MessageHeader * message)
{
- P2P_rpc_MESSAGE *res;
- CallInstance *call;
+ const P2P_rpc_MESSAGE *res;
+ struct GNUNET_RPC_RequestHandle * pos;
+ struct GNUNET_RPC_CallParameters *reply;
+ unsigned int error;
- if ((ntohs (message->type) != GNUNET_P2P_PROTO_RPC_RES) ||
- (ntohs (message->size) < sizeof (P2P_rpc_MESSAGE)))
+ if (ntohs (message->size) < sizeof (P2P_rpc_MESSAGE))
{
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("Invalid message of type %u received. Dropping.\n"),
- ntohs (message->type));
+ GNUNET_GE_BREAK_OP(NULL, 0);
return GNUNET_SYSERR;
}
- res = (P2P_rpc_MESSAGE *) message;
-#if DEBUG_RPC
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Received RPC reply with id %u.\n",
- ntohl (res->sequenceNumber));
-#endif
-
- GNUNET_cron_suspend_jobs (coreAPI->cron, GNUNET_NO);
- GNUNET_mutex_lock (rpcLock);
-
+ res = (const P2P_rpc_MESSAGE *) message;
+ RPC_send_ack(sender,
+ ntohl(res->sequenceNumber),
+ ntohl(res->importance),
+ 0);
/* Locate the GNUNET_RPC_CallHandle structure. */
- call = GNUNET_vector_get_first (outgoingCalls);
- while (call != NULL)
+ GNUNET_mutex_lock (lock);
+ pos = outgoingCalls;
+ while (pos != NULL)
{
- if ((0 == memcmp (&call->receiver,
+ if ((0 == memcmp (&pos->receiver,
sender,
sizeof (GNUNET_PeerIdentity))) &&
- (call->sequenceNumber == ntohl (res->sequenceNumber)))
+ (pos->sequenceNumber == ntohl (res->sequenceNumber)))
break;
- call = GNUNET_vector_get_next (outgoingCalls);
+ pos = pos->next;
}
- if (NULL != call)
+ if (pos == NULL)
{
- GNUNET_RPC_CallParameters *reply;
- unsigned short error;
+ /* duplicate reply */
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_OK;
+ }
+ /* remove pos from linked list */
+ GNUNET_mutex_unlock (lock);
- RPC_STATUS ("", "received reply", call);
+ /* call callback */
+ reply = NULL;
+ error = ntohl (res->functionNameLength);
+ if (error == GNUNET_RPC_ERROR_OK)
+ reply = GNUNET_RPC_parameters_deserialize ((char *) &res[1],
+ ntohs (message->size) -
+ sizeof
+ (P2P_rpc_MESSAGE));
+ if (ntohl (res->argumentCount) !=
+ GNUNET_RPC_parameters_count (reply))
+ {
+ GNUNET_RPC_parameters_destroy (reply);
reply = NULL;
- error = ntohs (res->functionNameLength);
-
- if (error == GNUNET_RPC_ERROR_OK)
- {
- reply = GNUNET_RPC_parameters_deserialize ((char *) &res[1],
- ntohs (message->size) -
- sizeof
- (P2P_rpc_MESSAGE));
- if (ntohs (res->argumentCount) !=
- GNUNET_RPC_parameters_count (reply))
- {
- GNUNET_RPC_parameters_destroy (reply);
- reply = NULL;
- error = GNUNET_RPC_ERROR_REPLY_MALFORMED;
- }
- }
- if (call->finishedCallback != NULL)
- {
- call->finishedCallback (call->rpcCallbackArgs,
- call->sequenceNumber, error, reply);
- call->finishedCallback = NULL;
- }
- GNUNET_vector_delete (outgoingCalls, call);
- notifyPeerReply (sender,
- MINGLE (call->sequenceNumber,
- GNUNET_P2P_PROTO_RPC_REQ));
- GNUNET_cron_del_job (coreAPI->cron, &retryRPCJob, 0, call);
- GNUNET_free (call->msg);
- GNUNET_free (call);
- if (reply != NULL)
- GNUNET_RPC_parameters_destroy (reply);
+ error = GNUNET_RPC_ERROR_REPLY_MALFORMED;
}
- sendAck (sender, ntohl (res->sequenceNumber), 0, /* not important, ACK
should be tiny enough to go through anyway */
- 0 /* right away */ );
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_cron_resume_jobs (coreAPI->cron, GNUNET_NO);
+ if (pos->callback != NULL)
+ {
+ pos->callback(sender,
+ reply,
+ error,
+ pos->cls);
+ pos->callback = NULL;
+ pos->errorCode = error;
+ }
+ if (reply != NULL)
+ GNUNET_RPC_parameters_destroy (reply);
return GNUNET_OK;
}
-
/**
* Handle a peer-to-peer message of type GNUNET_P2P_PROTO_RPC_ACK.
*/
@@ -1144,180 +726,49 @@
handleRPCMessageAck (const GNUNET_PeerIdentity * sender,
const GNUNET_MessageHeader * message)
{
- RPC_ACK_Message *ack;
- CallInstance *call;
+ const RPC_ACK_Message *ack;
+ struct GNUNET_RPC_CallHandle *pos;
- if ((ntohs (message->type) != GNUNET_P2P_PROTO_RPC_ACK) ||
- (ntohs (message->size) != sizeof (RPC_ACK_Message)))
+ if (ntohs (message->size) != sizeof (RPC_ACK_Message))
{
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_REQUEST | GNUNET_GE_ADMIN,
- _("Invalid message of type %u received. Dropping.\n"),
- ntohs (message->type));
+ GNUNET_GE_BREAK_OP(NULL, 0);
return GNUNET_SYSERR;
}
+ ack = (const RPC_ACK_Message *) message;
+ GNUNET_mutex_lock (lock);
- ack = (RPC_ACK_Message *) message;
-#if DEBUG_RPC
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Received RPC ACK with id %u.\n",
- ntohl (ack->sequenceNumber));
-#endif
- GNUNET_cron_suspend_jobs (coreAPI->cron, GNUNET_NO);
- GNUNET_mutex_lock (rpcLock);
-
/* Locate the GNUNET_RPC_CallHandle structure. */
- call = (CallInstance *) GNUNET_vector_get_first (incomingCalls);
- while (call != NULL)
+ pos = incomingCalls;
+ while (pos != NULL)
{
- if ((0 == memcmp (&call->receiver,
+ if ((0 == memcmp (&pos->initiator,
sender,
sizeof (GNUNET_PeerIdentity))) &&
- (call->sequenceNumber == ntohl (ack->sequenceNumber)))
+ (pos->sequenceNumber == ntohl (ack->sequenceNumber)))
break;
- call = (CallInstance *) GNUNET_vector_get_next (incomingCalls);
+ pos = pos->next;
}
-
- /* check if we're waiting for an ACK, if so remove job */
- if (NULL != call)
+ if (pos == NULL)
{
- RPC_STATUS ("", "acknowledged reply", call);
- notifyPeerReply (sender,
- MINGLE (ntohl (ack->sequenceNumber),
- GNUNET_P2P_PROTO_RPC_RES));
- GNUNET_cron_del_job (coreAPI->cron, &retryRPCJob, 0, call);
- GNUNET_vector_delete (incomingCalls, call);
- GNUNET_free (call->msg);
- GNUNET_free (call);
+ /* duplicate ACK, ignore */
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_OK;
}
+ /* remove from list */
+ if (pos->prev == NULL)
+ incomingCalls = pos->next;
else
- {
- PeerInfo *pi = getPeerInfo (sender);
- if (pi != NULL)
- {
- if (pi->averageResponseTime < MAX_RPC_TIMEOUT / 2)
- pi->averageResponseTime *= 2;
- }
-#if DEBUG_RPC
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "ACK is a duplicate (or invalid).\n");
-#endif
- }
-
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_cron_resume_jobs (coreAPI->cron, GNUNET_NO);
+ pos->prev->next = pos->next;
+ if (pos->next != NULL)
+ pos->next->prev = pos->prev;
+ GNUNET_free (pos->msg);
+ GNUNET_free (pos->function_name);
+ GNUNET_free (pos);
+ GNUNET_mutex_unlock (lock);
return GNUNET_OK;
}
-/* ********************* RPC service functions ******************** */
-
-typedef struct
-{
- struct GNUNET_Semaphore *sem;
- GNUNET_RPC_CallParameters *result;
- unsigned short ec;
-} RPC_EXEC_CLS;
-
/**
- * Callback function invoked whenever the RPC is complete
- * (timeout, error or success).
- */
-static void
-RPC_execute_callback (RPC_EXEC_CLS * context,
- unsigned int sq, unsigned short ec,
- GNUNET_RPC_CallParameters * res)
-{
- int i;
- unsigned int dl;
- void *data;
-
- for (i = GNUNET_RPC_parameters_count (res) - 1; i >= 0; i--)
- {
- data = NULL;
- GNUNET_RPC_parameters_get_value_by_index (res, i, &dl, &data);
- GNUNET_RPC_parameters_add (context->result,
- GNUNET_RPC_parameters_get_name (res, i), dl,
- data);
- }
- context->ec = ec;
- GNUNET_semaphore_up (context->sem);
-}
-
-/**
- * Executes a blocking RPC on a node, which may be the local node. The
- * function performs the following steps:
- *
- * - Constructs a request packet from the request parameters
- * - Waits on a signaling semaphore until the result is ready or timeout
- * - passes the results back to the caller
- *
- * @return the error code of the operation (0 for success).
- */
-static int
-RPC_execute (const GNUNET_PeerIdentity * receiver,
- const char *name,
- GNUNET_RPC_CallParameters * requestParam,
- GNUNET_RPC_CallParameters * returnParam, unsigned int importance,
- GNUNET_CronTime timeout)
-{
- RPC_EXEC_CLS cls;
- CallInstance *call;
-
- GNUNET_mutex_lock (rpcLock);
- cls.sem = GNUNET_semaphore_create (0);
- cls.result = returnParam;
- call = GNUNET_malloc (sizeof (CallInstance));
- RPC_STATUS (name, "started synchronously", call);
- call->lastAttempt = 0;
- call->attempts = 0;
- call->repetitionFrequency = getExpectedResponseTime (receiver);
- call->expirationTime = GNUNET_get_time () + timeout;
- call->receiver = *receiver;
- call->sequenceNumber = rpcIdentifier++;
- call->msg = buildMessage (GNUNET_RPC_ERROR_OK,
- name,
- call->sequenceNumber, importance, requestParam);
- call->finishedCallback = (RPCFinishedCallback) & RPC_execute_callback;
- call->rpcCallbackArgs = &cls;
- GNUNET_vector_insert_last (outgoingCalls, call);
- GNUNET_GE_ASSERT (ectx,
- (GNUNET_get_time () + 1 * GNUNET_CRON_MINUTES >
- call->expirationTime)
- || (call->expirationTime - GNUNET_get_time () <
- 1 * GNUNET_CRON_HOURS));
- GNUNET_cron_add_job (coreAPI->cron, &retryRPCJob, 0, 0, call);
- GNUNET_mutex_unlock (rpcLock);
- GNUNET_semaphore_down (cls.sem, GNUNET_YES);
- GNUNET_semaphore_destroy (cls.sem);
- RPC_STATUS (name, "completed synchronously", call);
- return cls.ec;
-}
-
-typedef struct GNUNET_RPC_RequestHandle
-{
- GNUNET_PeerIdentity peer;
- CallInstance *call;
- GNUNET_RPC_AsynchronousCompletionCallback callback;
- void *closure;
- unsigned short errorCode;
-} RPC_Record;
-
-static void
-RPC_async_callback (RPC_Record * rec,
- unsigned int sequenceNumber,
- unsigned short errorCode,
- GNUNET_RPC_CallParameters * result)
-{
- if ((errorCode == GNUNET_RPC_ERROR_OK) && (rec->callback != NULL))
- {
- rec->callback (&rec->peer, result, rec->closure);
- rec->callback = NULL; /* never call callback twice */
- }
- rec->errorCode = errorCode;
-}
-
-/**
* Start an asynchronous RPC.
*
* @param timeout when should we stop trying the RPC
@@ -1327,52 +778,42 @@
* @return value required to stop the RPC (and the RPC must
* be explicitly stopped to free resources!)
*/
-static RPC_Record *
+static struct GNUNET_RPC_RequestHandle *
RPC_start (const GNUNET_PeerIdentity * receiver,
const char *name,
- GNUNET_RPC_CallParameters * request_param,
+ const struct GNUNET_RPC_CallParameters * request_param,
unsigned int importance,
GNUNET_CronTime timeout,
GNUNET_RPC_AsynchronousCompletionCallback callback, void *closure)
{
- RPC_Record *ret;
+ struct GNUNET_RPC_RequestHandle *ret;
if (timeout > 1 * GNUNET_CRON_HOURS)
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("`%s' called with timeout above 1 hour (bug?)\n"),
- __FUNCTION__);
- timeout = 1 * GNUNET_CRON_HOURS;
- }
- ret = GNUNET_malloc (sizeof (RPC_Record));
- RPC_STATUS (name, "started asynchronously", ret);
- ret->peer = *receiver;
+ timeout = 1 * GNUNET_CRON_HOURS;
+ ret = GNUNET_malloc (sizeof (struct GNUNET_RPC_RequestHandle));
+ memset(ret, 0, sizeof (struct GNUNET_RPC_RequestHandle));
+ ret->receiver = *receiver;
ret->callback = callback;
- ret->closure = closure;
- ret->errorCode = GNUNET_RPC_ERROR_TIMEOUT;
- GNUNET_mutex_lock (rpcLock);
- ret->call = GNUNET_malloc (sizeof (CallInstance));
- ret->call->lastAttempt = 0;
- ret->call->attempts = 0;
- ret->call->repetitionFrequency = getExpectedResponseTime (receiver);
- ret->call->expirationTime = GNUNET_get_time () + timeout;
- ret->call->receiver = *receiver;
- ret->call->sequenceNumber = rpcIdentifier++;
- ret->call->msg = buildMessage (GNUNET_RPC_ERROR_OK,
- name,
- ret->call->sequenceNumber,
- importance, request_param);
- ret->call->finishedCallback = (RPCFinishedCallback) & RPC_async_callback;
- ret->call->rpcCallbackArgs = ret;
- GNUNET_vector_insert_last (outgoingCalls, ret->call);
- GNUNET_GE_ASSERT (ectx,
- (GNUNET_get_time () + 1 * GNUNET_CRON_MINUTES >
- ret->call->expirationTime)
- || (ret->call->expirationTime - GNUNET_get_time () <
- 1 * GNUNET_CRON_HOURS));
- GNUNET_cron_add_job (coreAPI->cron, &retryRPCJob, 0, 0, ret->call);
- GNUNET_mutex_unlock (rpcLock);
+ ret->cls = closure;
+ ret->expirationTime = GNUNET_get_time () + timeout;
+ ret->lastAttempt = 0;
+ ret->attempts = 0;
+ ret->sequenceNumber = rpcIdentifier++;
+ ret->msg = RPC_build_message (GNUNET_RPC_ERROR_OK,
+ name,
+ ret->sequenceNumber,
+ importance, request_param);
+ ret->repetitionFrequency = RPC_INITIAL_ROUND_TRIP_TIME;
+ GNUNET_mutex_lock (lock);
+ ret->next = outgoingCalls;
+ outgoingCalls = ret;
+ if (ret->next != NULL)
+ ret->next->prev = ret;
+ GNUNET_mutex_unlock (lock);
+ coreAPI->unicast(receiver,
+ &ret->msg->header,
+ importance,
+ RPC_INITIAL_ROUND_TRIP_TIME / 2);
return ret;
}
@@ -1384,27 +825,109 @@
* another RPC_ERROR code if it was aborted
*/
static int
-RPC_stop (RPC_Record * record)
+RPC_stop (struct GNUNET_RPC_RequestHandle * record)
{
int ret;
- RPC_STATUS ("", "stopped", record);
- GNUNET_cron_suspend_jobs (coreAPI->cron, GNUNET_YES);
- GNUNET_cron_del_job (coreAPI->cron, &retryRPCJob, 0, record->call);
- GNUNET_cron_resume_jobs (coreAPI->cron, GNUNET_YES);
- GNUNET_mutex_lock (rpcLock);
- if (NULL != GNUNET_vector_delete (outgoingCalls, record->call))
- {
- GNUNET_free (record->call->msg);
- GNUNET_free (record->call);
- }
- GNUNET_mutex_unlock (rpcLock);
- ret = record->errorCode;
+ GNUNET_mutex_lock (lock);
+ if (record->prev == NULL)
+ outgoingCalls = record->next;
+ else
+ record->prev->next = record->next;
+ if (record->next != NULL)
+ record->next->prev = record->prev;
+ GNUNET_free (record->msg);
+ GNUNET_mutex_unlock (lock);
+ ret = (record->callback == NULL) ? record->errorCode :
GNUNET_RPC_ERROR_ABORTED;
GNUNET_free (record);
-
return ret;
}
+
+/**
+ * Cron-job that processes the RPC queues. This job is responsible
+ * for retransmission of requests and un-ACKed responses. It is also
+ * there to trigger timeouts.
+ */
+static void
+RPC_retry_job (void * unused)
+{
+ GNUNET_CronTime now;
+ struct GNUNET_RPC_CallHandle * ipos;
+ struct GNUNET_RPC_RequestHandle * opos;
+
+ GNUNET_mutex_lock (lock);
+ now = GNUNET_get_time ();
+ ipos = incomingCalls;
+ while (ipos != NULL)
+ {
+ if ( (ipos->expirationTime < now) ||
+ (ipos->attempts >= RPC_MAX_REPLY_ATTEMPTS) )
+ {
+ GNUNET_free_non_null(ipos->msg);
+ GNUNET_free(ipos->function_name);
+ if (ipos->prev == NULL)
+ incomingCalls = ipos->next;
+ else
+ ipos->prev->next = ipos->next;
+ if (ipos->next != NULL)
+ ipos->next = ipos->prev;
+ GNUNET_free(ipos);
+ ipos = incomingCalls;
+ continue;
+ }
+ if ( (ipos->msg != NULL) &&
+ (ipos->lastAttempt + ipos->repetitionFrequency < now) )
+ {
+ ipos->lastAttempt = now;
+ ipos->attempts++;
+ ipos->repetitionFrequency *= 2;
+ coreAPI->unicast(&ipos->initiator,
+ &ipos->msg->header,
+ ipos->repetitionFrequency / 2,
+ ipos->importance);
+ }
+ ipos = ipos->next;
+ }
+ opos = outgoingCalls;
+ while (opos != NULL)
+ {
+ if (opos->expirationTime < now)
+ {
+ if (opos->callback != NULL)
+ {
+ opos->callback(&opos->receiver,
+ NULL,
+ GNUNET_RPC_ERROR_TIMEOUT,
+ opos->cls);
+ opos->callback = NULL;
+ }
+ GNUNET_free_non_null(opos->msg);
+ if (opos->prev == NULL)
+ outgoingCalls = opos->next;
+ else
+ opos->prev->next = opos->next;
+ if (opos->next != NULL)
+ opos->next = opos->prev;
+ GNUNET_free(opos);
+ opos = outgoingCalls;
+ continue;
+ }
+ if (opos->lastAttempt + opos->repetitionFrequency < now)
+ {
+ opos->lastAttempt = now;
+ opos->attempts++;
+ opos->repetitionFrequency *= 2;
+ coreAPI->unicast(&opos->receiver,
+ &opos->msg->header,
+ opos->repetitionFrequency / 2,
+ opos->importance);
+ }
+ opos = opos->next;
+ }
+ GNUNET_mutex_unlock (lock);
+}
+
/* ******************* Exported functions ******************* */
/**
@@ -1413,63 +936,18 @@
void
release_module_rpc ()
{
- CallInstance *call;
-
- GNUNET_cron_del_job (coreAPI->cron,
- &agePeerStats, PEER_TRACKING_TIME_INTERVAL, NULL);
coreAPI->unregisterHandler (GNUNET_P2P_PROTO_RPC_REQ, &handleRPCMessageReq);
coreAPI->unregisterHandler (GNUNET_P2P_PROTO_RPC_RES, &handleRPCMessageRes);
coreAPI->unregisterHandler (GNUNET_P2P_PROTO_RPC_ACK, &handleRPCMessageAck);
- if (NULL != peerInformation)
- {
- while (GNUNET_vector_get_size (peerInformation) > 0)
- GNUNET_free (GNUNET_vector_delete_last (peerInformation));
- GNUNET_vector_destroy (peerInformation);
- peerInformation = NULL;
- }
- if (NULL != incomingCalls)
- {
- while (GNUNET_vector_get_size (incomingCalls) > 0)
- {
- call = (CallInstance *) GNUNET_vector_delete_last (incomingCalls);
- GNUNET_cron_del_job (coreAPI->cron, &retryRPCJob, 0, call);
- GNUNET_free (call->msg);
- GNUNET_free (call);
- }
- GNUNET_vector_destroy (incomingCalls);
- incomingCalls = NULL;
- }
- if (NULL != outgoingCalls)
- {
- while (GNUNET_vector_get_size (outgoingCalls) > 0)
- {
- call = (CallInstance *) GNUNET_vector_delete_last (outgoingCalls);
- GNUNET_cron_del_job (coreAPI->cron, &retryRPCJob, 0, call);
- GNUNET_free (call->msg);
- GNUNET_free (call);
- }
- GNUNET_vector_destroy (outgoingCalls);
- outgoingCalls = NULL;
- }
- if (NULL != list_of_callbacks)
- {
- while (GNUNET_vector_get_size (list_of_callbacks) > 0)
- {
- RegisteredRPC *rpc;
- rpc =
- (RegisteredRPC *) GNUNET_vector_delete_last (list_of_callbacks);
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("RPC not unregistered: %s:%p\n"), rpc->name,
- rpc->callback);
- GNUNET_free (rpc->name);
- GNUNET_free (rpc);
- }
- GNUNET_vector_destroy (list_of_callbacks);
- list_of_callbacks = NULL;
- }
+ GNUNET_GE_ASSERT(NULL, NULL == incomingCalls);
+ GNUNET_GE_ASSERT(NULL, NULL == outgoingCalls);
+ GNUNET_GE_ASSERT(NULL, NULL == list_of_callbacks);
+ GNUNET_cron_del_job(coreAPI->cron,
+ &RPC_retry_job,
+ RPC_CRON_FREQUENCY,
+ NULL);
coreAPI = NULL;
- rpcLock = NULL;
+ lock = NULL;
}
/**
@@ -1481,14 +959,9 @@
static GNUNET_RPC_ServiceAPI rpcAPI;
int rvalue;
- ectx = capi->ectx;
- rpcLock = capi->connection_get_lock ();
+ lock = capi->connection_get_lock ();
coreAPI = capi;
- peerInformation = GNUNET_vector_create (16);
- incomingCalls = GNUNET_vector_create (16);
- outgoingCalls = GNUNET_vector_create (16);
- list_of_callbacks = GNUNET_vector_create (16);
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ GNUNET_GE_LOG (coreAPI->ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
GNUNET_GE_USER,
_("`%s' registering handlers %d %d %d\n"),
"rpc", GNUNET_P2P_PROTO_RPC_REQ, GNUNET_P2P_PROTO_RPC_RES,
GNUNET_P2P_PROTO_RPC_ACK);
@@ -1505,170 +978,22 @@
if (rvalue == GNUNET_SYSERR)
{
release_module_rpc ();
- GNUNET_GE_LOG (ectx,
+ GNUNET_GE_LOG (coreAPI->ectx,
GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
_("Failed to initialize `%s' service.\n"), "rpc");
return NULL;
}
- else
- {
- rpcAPI.RPC_execute = &RPC_execute;
- rpcAPI.RPC_register = &RPC_register;
- rpcAPI.RPC_unregister = &RPC_unregister;
- rpcAPI.RPC_register_async = &RPC_register_async;
- rpcAPI.RPC_unregister_async = &RPC_unregister_async;
- rpcAPI.RPC_start = &RPC_start;
- rpcAPI.RPC_stop = &RPC_stop;
- GNUNET_cron_add_job (coreAPI->cron,
- &agePeerStats,
- PEER_TRACKING_TIME_INTERVAL,
- PEER_TRACKING_TIME_INTERVAL, NULL);
- return &rpcAPI;
- }
+ GNUNET_cron_add_job(coreAPI->cron,
+ &RPC_retry_job,
+ RPC_CRON_FREQUENCY,
+ RPC_CRON_FREQUENCY,
+ NULL);
+ rpcAPI.RPC_register = &RPC_register;
+ rpcAPI.RPC_unregister = &RPC_unregister;
+ rpcAPI.RPC_complete = &RPC_complete;
+ rpcAPI.RPC_start = &RPC_start;
+ rpcAPI.RPC_stop = &RPC_stop;
+ return &rpcAPI;
}
-#if PROVIDE_RPC_TEST
-
-static void
-testCallback (const GNUNET_PeerIdentity * sender,
- GNUNET_RPC_CallParameters * arguments,
- GNUNET_RPC_CallParameters * results)
-{
- unsigned int dl;
- char *data;
-
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "RPC callback invoked!\n");
- if ((GNUNET_OK ==
- GNUNET_RPC_parameters_get_value_by_name (arguments, "command", &dl,
- (void **) &data))
- && (strncmp ("Hello", data, dl) == 0))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "RPC callback received Hello command!\n");
- GNUNET_RPC_parameters_add (results, "response",
- strlen ("Hello RPC World") + 1,
- "Hello RPC World");
- }
-}
-
-static void
-async_RPC_Complete_callback (GNUNET_RPC_CallParameters * results,
- struct GNUNET_Semaphore *GNUNET_RSA_sign)
-{
- unsigned int dl;
- char *reply;
-
- GNUNET_semaphore_down (GNUNET_RSA_sign, GNUNET_YES);
- if ((GNUNET_OK != GNUNET_RPC_parameters_get_value_by_name (results,
- "response",
- &dl,
- (void **)
- &reply))
- || (strncmp ("Hello RPC World", reply, dl) != 0))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("RPC async reply invalid.\n"));
- }
- else
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "RPC async reply received.\n");
-}
-
-int
-initialize_module_rpc (GNUNET_CoreAPIForPlugins * capi)
-{
- GNUNET_RPC_ServiceAPI *rpcAPI;
- int ret;
- GNUNET_RPC_CallParameters *args;
- GNUNET_RPC_CallParameters *rets;
- unsigned int dl;
- char *reply;
- int code;
- struct GNUNET_RPC_RequestHandle *record;
- struct GNUNET_Semaphore *GNUNET_RSA_sign;
-
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "RPC testcase starting\n");
- rpcAPI = capi->request_service ("rpc");
- if (rpcAPI == NULL)
- {
- GNUNET_GE_BREAK (ectx, 0);
- return GNUNET_SYSERR;
- }
- ret = GNUNET_OK;
-
- if (GNUNET_OK != rpcAPI->RPC_register ("testFunction", &testCallback))
- {
- GNUNET_GE_BREAK (ectx, 0);
- ret = GNUNET_SYSERR;
- }
-
- args = GNUNET_RPC_parameters_create ();
- GNUNET_RPC_parameters_add (args, "command", strlen ("Hello") + 1, "Hello");
- GNUNET_RSA_sign = GNUNET_semaphore_create (0);
- record = rpcAPI->RPC_start (coreAPI->myIdentity,
- "testFunction",
- args,
- 0,
- 5 * GNUNET_CRON_SECONDS,
- (GNUNET_RPC_AsynchronousCompletionCallback) &
- async_RPC_Complete_callback, GNUNET_RSA_sign);
- GNUNET_semaphore_up (GNUNET_RSA_sign); /* allow callback now - forces
async! */
- rets = GNUNET_RPC_parameters_create ();
- code = rpcAPI->RPC_execute (coreAPI->myIdentity,
- "testFunction", args, rets, 0,
- 5 * GNUNET_CRON_SECONDS);
- if (code != GNUNET_RPC_ERROR_OK)
- {
- GNUNET_GE_BREAK (ectx, 0);
- ret = GNUNET_SYSERR;
- }
- GNUNET_RPC_parameters_destroy (args);
- if ((GNUNET_OK != GNUNET_RPC_parameters_get_value_by_name (rets,
- "response",
- &dl,
- (void **)
- &reply))
- || (strncmp ("Hello RPC World", reply, dl) != 0))
- {
- GNUNET_GE_BREAK (ectx, 0);
- ret = GNUNET_SYSERR;
- }
- GNUNET_RPC_parameters_destroy (rets);
- GNUNET_thread_sleep (1 * GNUNET_CRON_SECONDS);
- if (GNUNET_RPC_ERROR_OK != rpcAPI->RPC_stop (record))
- GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _("async RPC reply not received.\n"));
-
- if (GNUNET_OK != rpcAPI->RPC_unregister ("testFunction", &testCallback))
- {
- GNUNET_GE_BREAK (ectx, 0);
- ret = GNUNET_SYSERR;
- }
- if (GNUNET_OK != capi->release_service (rpcAPI))
- {
- GNUNET_GE_BREAK (ectx, 0);
- ret = GNUNET_SYSERR;
- }
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "RPC testcase completed with status %s\n",
- ret == GNUNET_OK ? "SUCCESS" : "FAILURE");
- return ret;
-}
-
-/**
- * Does nothing (but must be present for clean unload of the
- * testcase!).
- */
-int
-done_module_rpc ()
-{
- return GNUNET_OK;
-}
-
-#endif
-
/* end of rpc.c */
Modified: GNUnet/src/include/Makefile.am
===================================================================
--- GNUnet/src/include/Makefile.am 2008-02-17 04:58:52 UTC (rev 6347)
+++ GNUnet/src/include/Makefile.am 2008-02-17 07:50:48 UTC (rev 6348)
@@ -13,7 +13,6 @@
gnunetincludedir = $(includedir)/GNUnet
gnunetinclude_HEADERS = \
- gnunet_blockstore.h \
gnunet_bootstrap_service.h \
gnunet_collection_lib.h \
gnunet_core.h \
Deleted: GNUnet/src/include/gnunet_blockstore.h
===================================================================
--- GNUnet/src/include/gnunet_blockstore.h 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/include/gnunet_blockstore.h 2008-02-17 07:50:48 UTC (rev
6348)
@@ -1,155 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2004, 2005, 2006 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
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- 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.
- */
-
-/**
- * @file include/gnunet_blockstore.h
- * @brief common API for DHT and GAP service to obtain local data (from FS)
- * @author Christian Grothoff
- */
-
-#ifndef GNUNET_BLOCKSTORE_H
-#define GNUNET_BLOCKSTORE_H
-
-#include "gnunet_util.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-/**
- * Data stored in the blockstore.
- */
-typedef struct
-{
- /**
- * Size of the data container (in NBO). This field
- * is followed by size-sizeof(unsigned int) bytes
- * of data.
- */
- unsigned int size;
-} GNUNET_DataContainer;
-
-/**
- * Callback function type for items in the GAP datastore.
- *
- * @param key the current key
- * @param value the current value
- * @param cls argument passed for context (closure)
- * @return GNUNET_OK to continue with iteration, GNUNET_SYSERR to abort
- */
-typedef int (*GNUNET_DataProcessor) (const GNUNET_HashCode * key,
- const GNUNET_DataContainer * value,
- void *cls);
-
-/**
- * GAP and DHT clients must implement this interface to tell
- * the routing code how to get to local data.
- *
- * The use of key in this API maybe confusing. The specific content
- * of keys is not specified, the routing code only transmits the
- * number of keys and the type. Only the first key is used for
- * routing, the other parts are just passed along and untouched by the
- * routing code. The type is typically used to tell what they refer
- * to. The assumption is that they (including the type) can be
- * reproduced from the GNUNET_DataContainer and thus the Iterator
- * methods do not communicate those values.
- *
- * The put method is (ab)used to check an item that is merely routed
- * for its integrity.
- */
-typedef struct
-{
-
- /**
- * First argument to be passed to all functions in this struct.
- */
- void *closure;
-
- /**
- * Do a quick test if we MAY have the content.
- */
- int (*fast_get) (const GNUNET_HashCode * key);
-
- /**
- * Lookup an item in the datastore.
- *
- * @param type kind of item to look up
- * @param prio how important is this lookup
- * @param keyCount number of keys given
- * @param keys to look up
- * @param resultCallback function to call for each result that was found
- * @param resCallbackClosure extra argument to resultCallback
- * @return number of results, GNUNET_SYSERR on error
- */
- int (*get) (void *closure,
- unsigned int type,
- unsigned int prio,
- unsigned int keyCount,
- const GNUNET_HashCode * keys,
- GNUNET_DataProcessor resultCallback, void *resCallbackClosure);
-
- /**
- * Store an item in the datastore.
- *
- * @param key the key of the item, NULL if not known
- * (client should try to figure it out)
- * @param value the value to store
- * @return GNUNET_OK if the value could be stored,
- * GNUNET_NO if the value verifies but is not stored,
- * GNUNET_SYSERR if the value is malformed
- */
- int (*put) (void *closure,
- const GNUNET_HashCode * key,
- const GNUNET_DataContainer * value, unsigned int prio);
-
- /**
- * Remove an item from the datastore.
- *
- * @param key the key of the item
- * @param value the value to remove, NULL for all values of the key
- * @return GNUNET_OK if the value could be removed, GNUNET_SYSERR if not
(i.e. not present)
- */
- int (*del) (void *closure,
- const GNUNET_HashCode * key,
- const GNUNET_DataContainer * value);
-
- /**
- * Iterate over all keys in the local datastore
- *
- * @param processor function to call on each item
- * @param cls argument to processor
- * @return number of results, GNUNET_SYSERR on error
- */
- int (*iterate) (void *closure, GNUNET_DataProcessor processor, void *cls);
-
-} GNUNET_Blockstore;
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif
Modified: GNUnet/src/include/gnunet_dht_lib.h
===================================================================
--- GNUnet/src/include/gnunet_dht_lib.h 2008-02-17 04:58:52 UTC (rev 6347)
+++ GNUnet/src/include/gnunet_dht_lib.h 2008-02-17 07:50:48 UTC (rev 6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 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
@@ -27,7 +27,6 @@
#ifndef GNUNET_DHT_LIB_H
#define GNUNET_DHT_LIB_H
-#include "gnunet_blockstore.h"
#include "gnunet_dht_service.h"
#ifdef __cplusplus
@@ -55,7 +54,7 @@
unsigned int type,
const GNUNET_HashCode * key,
GNUNET_CronTime timeout,
- GNUNET_DataProcessor resultCallback,
+ GNUNET_ResultProcessor resultCallback,
void *resCallbackClosure);
/**
@@ -68,7 +67,9 @@
int GNUNET_DHT_put (struct GNUNET_GC_Configuration *cfg,
struct GNUNET_GE_Context *ectx,
const GNUNET_HashCode * key,
- unsigned int type, const GNUNET_DataContainer * value);
+ unsigned int type,
+ unsigned int size,
+ const char * value);
#if 0 /* keep Emacsens' auto-indent happy */
{
Modified: GNUnet/src/include/gnunet_dht_service.h
===================================================================
--- GNUnet/src/include/gnunet_dht_service.h 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/include/gnunet_dht_service.h 2008-02-17 07:50:48 UTC (rev
6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 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
@@ -32,7 +32,7 @@
#define GNUNET_DHT_SERVICE_H
#include "gnunet_core.h"
-#include "gnunet_blockstore.h"
+#include "gnunet_dstore_service.h"
#ifdef __cplusplus
extern "C"
@@ -61,7 +61,7 @@
*/
struct GNUNET_DHT_GetHandle *(*get_start) (unsigned int type,
const GNUNET_HashCode * key,
- GNUNET_DataProcessor callback,
+ GNUNET_ResultProcessor callback,
void *cls);
/**
Modified: GNUnet/src/include/gnunet_dstore_service.h
===================================================================
--- GNUnet/src/include/gnunet_dstore_service.h 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/include/gnunet_dstore_service.h 2008-02-17 07:50:48 UTC (rev
6348)
@@ -42,10 +42,10 @@
#endif
#endif
-typedef void (*GNUNET_ResultProcessor) (const GNUNET_HashCode * key,
- unsigned int type,
- unsigned int size,
- const char *data, void *cls);
+typedef int (*GNUNET_ResultProcessor) (const GNUNET_HashCode * key,
+ unsigned int type,
+ unsigned int size,
+ const char *data, void *cls);
/**
* @brief Definition of the SQ-Store API.
Modified: GNUnet/src/include/gnunet_rpc_lib.h
===================================================================
--- GNUnet/src/include/gnunet_rpc_lib.h 2008-02-17 04:58:52 UTC (rev 6347)
+++ GNUnet/src/include/gnunet_rpc_lib.h 2008-02-17 07:50:48 UTC (rev 6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 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
@@ -29,7 +29,6 @@
#include "gnunet_core.h"
#include "gnunet_util.h"
-#include "gnunet_blockstore.h"
#ifdef __cplusplus
extern "C"
@@ -42,89 +41,55 @@
/**
* Type of RPC arguments.
*/
-#define GNUNET_RPC_CallParameters struct GNUNET_Vector
+struct GNUNET_RPC_CallParameters;
/**
* RPC argument handling helper functions.
*/
-GNUNET_RPC_CallParameters *GNUNET_RPC_parameters_create (void);
+struct GNUNET_RPC_CallParameters *GNUNET_RPC_parameters_create (void);
-void GNUNET_RPC_parameters_destroy (GNUNET_RPC_CallParameters * param);
+void GNUNET_RPC_parameters_destroy (struct GNUNET_RPC_CallParameters * param);
-unsigned int GNUNET_RPC_parameters_count (GNUNET_RPC_CallParameters * param);
+unsigned int GNUNET_RPC_parameters_count (const struct
GNUNET_RPC_CallParameters * param);
-void GNUNET_RPC_parameters_add (GNUNET_RPC_CallParameters * param,
+void GNUNET_RPC_parameters_add (struct GNUNET_RPC_CallParameters * param,
const char *name,
unsigned int dataLength, const void *data);
-void GNUNET_RPC_parameters_add_data_container (GNUNET_RPC_CallParameters *
- param, const char *name,
- const GNUNET_DataContainer *
- data);
-
-const char *GNUNET_RPC_parameters_get_name (GNUNET_RPC_CallParameters * param,
- unsigned int i);
-
-unsigned int GNUNET_RPC_get_index_by_name (GNUNET_RPC_CallParameters * param,
- const char *name);
-
/**
* @return GNUNET_OK on success, GNUNET_SYSERR on error
*/
-int GNUNET_RPC_parameters_get_value_by_name (GNUNET_RPC_CallParameters *
+int GNUNET_RPC_parameters_get_value_by_name (const struct
GNUNET_RPC_CallParameters *
param, const char *name,
unsigned int *dataLength,
- void **data);
+ void const ** data);
/**
* @return GNUNET_OK on success, GNUNET_SYSERR on error
*/
-int GNUNET_RPC_parameters_get_value_by_index (GNUNET_RPC_CallParameters *
+int GNUNET_RPC_parameters_get_value_by_index (const struct
GNUNET_RPC_CallParameters *
param, unsigned int i,
unsigned int *dataLength,
- void **data);
+ void const ** data);
/**
- * Return the value of the given parameter in the RPC parameter structure.
+ * Serialize the param array.
*
- * @param param Target RPC parameter structure
- * @param value set to the value of the parameter
+ * @param target must point to at least
GNUNET_RPC_parameters_get_serialized_size(param) bytes of memory.
*/
-GNUNET_DataContainer
- * GNUNET_RPC_parameters_get_data_container_by_index
- (GNUNET_RPC_CallParameters * param, unsigned int i);
-
-/**
- * Return the value of the named parameter in the RPC parameter
- * structure.
- *
- * @param param Target RPC parameter structure
- * @param value set to the value of the named parameter
- * @return GNUNET_SYSERR on error
- */
-GNUNET_DataContainer
- *
-GNUNET_RPC_parameters_get_data_container_by_name (GNUNET_RPC_CallParameters *
- param, const char *name);
-
-/**
- * Serialize the param array. target must point to at least
- * GNUNET_RPC_parameters_get_serialized_size(param) bytes of memory.
- */
-void GNUNET_RPC_parameters_serialize (GNUNET_RPC_CallParameters * param,
+void GNUNET_RPC_parameters_serialize (const struct GNUNET_RPC_CallParameters *
param,
char *target);
/**
* Deserialize parameters from buffer.
*/
-GNUNET_RPC_CallParameters *GNUNET_RPC_parameters_deserialize (char *buffer,
- size_t size);
+struct GNUNET_RPC_CallParameters *GNUNET_RPC_parameters_deserialize (const
char *buffer,
+ size_t
size);
/**
* How many bytes are required to serialize the param array?
*/
-size_t GNUNET_RPC_parameters_get_serialized_size (GNUNET_RPC_CallParameters *
- param);
+size_t GNUNET_RPC_parameters_get_serialized_size (const struct
GNUNET_RPC_CallParameters * param);
#if 0 /* keep Emacsens' auto-indent happy */
Modified: GNUnet/src/include/gnunet_rpc_service.h
===================================================================
--- GNUnet/src/include/gnunet_rpc_service.h 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/include/gnunet_rpc_service.h 2008-02-17 07:50:48 UTC (rev
6348)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 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
@@ -28,8 +28,6 @@
#define GNUNET_RPC_SERVICE_H
#include "gnunet_core.h"
-#include "gnunet_util_containers.h"
-#include "gnunet_blockstore.h"
#include "gnunet_rpc_lib.h"
#ifdef __cplusplus
@@ -73,14 +71,9 @@
#define GNUNET_RPC_ERROR_REPLY_MALFORMED 5
/**
- * Prototype for synchronous RPC functions.
+ * RPC_stop was called before a response was received
*/
-typedef void (*GNUNET_RPC_SynchronousFunction) (const GNUNET_PeerIdentity *
- caller,
- GNUNET_RPC_CallParameters *
- arguments,
- GNUNET_RPC_CallParameters *
- results);
+#define GNUNET_RPC_ERROR_ABORTED 6
/**
* Opaque RPC internal per-RPC data.
@@ -88,35 +81,34 @@
struct GNUNET_RPC_CallHandle;
/**
- * GNUNET_RSA_Signature of the callback function for the ASYNC_RPC to
- * be called upon completion of the ASYNC function.
- */
-typedef void (*GNUNET_RPC_CompleteCallback) (GNUNET_RPC_CallParameters *
- results, int errorCode,
- struct GNUNET_RPC_CallHandle *
- context);
-
-/**
* Prototype for asynchronous RPC functions.
+ *
+ * @param caller who called the function?
+ * @param arguments arguments to the call
+ * @param context argument to pass to rpc->RPC_complete when the function is
done
*/
-typedef void (*GNUNET_RPC_AsynchronousFunction) (const GNUNET_PeerIdentity *
+typedef void (*GNUNET_RPC_AsynchronousFunction) (void * cls,
+ const GNUNET_PeerIdentity *
caller,
- GNUNET_RPC_CallParameters *
+ const struct
GNUNET_RPC_CallParameters *
arguments,
- GNUNET_RPC_CompleteCallback
- callback,
struct GNUNET_RPC_CallHandle
* context);
/**
* Function to call once an asynchronous RPC completes.
+ * A function of this type is called if we receive return
+ * values from an RPC.
+ * @param responder who responded
+ * @param results return values
+ * @param closure client-specific context
*/
-typedef void (*GNUNET_RPC_AsynchronousCompletionCallback) (const
- GNUNET_PeerIdentity
+typedef void (*GNUNET_RPC_AsynchronousCompletionCallback) (const
GNUNET_PeerIdentity
* responder,
-
GNUNET_RPC_CallParameters
+ const struct
GNUNET_RPC_CallParameters
* results,
+ unsigned int
errorCode,
void *closure);
struct GNUNET_RPC_RequestHandle;
@@ -128,37 +120,19 @@
{
/**
- * Perform a synchronous RPC.
- */
- int (*RPC_execute) (const GNUNET_PeerIdentity * receiver,
- const char *name,
- GNUNET_RPC_CallParameters * request_param,
- GNUNET_RPC_CallParameters * return_param,
- unsigned int importance, GNUNET_CronTime timeout);
-
- /**
- * Register a synchronous RPC function.
- */
- int (*RPC_register) (const char *name, GNUNET_RPC_SynchronousFunction func);
-
- /**
- * Unregister a synchronous RPC function.
- */
- int (*RPC_unregister) (const char *name,
- GNUNET_RPC_SynchronousFunction func);
-
- /**
* Register an asynchronous RPC function.
*/
- int (*RPC_register_async) (const char *name,
- GNUNET_RPC_AsynchronousFunction func);
+ int (*RPC_register) (const char *name,
+ GNUNET_RPC_AsynchronousFunction func,
+ void * cls);
/**
* Unregister an asynchronous RPC function.
*/
- int (*RPC_unregister_async) (const char *name,
- GNUNET_RPC_AsynchronousFunction func);
+ int (*RPC_unregister) (const char *name,
+ GNUNET_RPC_AsynchronousFunction func,
+ void * cls);
/**
* Start an asynchronous RPC.
@@ -172,7 +146,7 @@
*/
struct GNUNET_RPC_RequestHandle *(*RPC_start) (const GNUNET_PeerIdentity *
receiver, const char *name,
- GNUNET_RPC_CallParameters *
+ const struct
GNUNET_RPC_CallParameters *
request_param,
unsigned int importance,
GNUNET_CronTime timeout,
@@ -180,13 +154,28 @@
callback, void *closure);
/**
- * Stop an asynchronous RPC.
+ * Stop an asynchronous RPC. After calling this function,
+ * the AsynchronousCompletionCallback of the corresponding
+ * RPC_start request will no longer be called. RPC_stop
+ * must be called either to abort the RPC early or to
+ * clean up the RPC's state after successful completion.
+ * There must be one and only one call to RPC_stop for
+ * each call to RPC_start.
*
* @param record the return value from RPC_start
* @return GNUNET_RPC_ERROR_OK if the RPC was successful
*/
int (*RPC_stop) (struct GNUNET_RPC_RequestHandle * record);
+ /**
+ * Tell RPC the result of an RPC call. This function must
+ * be called once and only once for each AsynchronousFunction
+ * that is called from the RPC module.
+ */
+ void (*RPC_complete) (const struct GNUNET_RPC_CallParameters *
+ results, int errorCode,
+ struct GNUNET_RPC_CallHandle *
+ context);
} GNUNET_RPC_ServiceAPI;
Modified: GNUnet/src/include/gnunet_util_containers.h
===================================================================
--- GNUnet/src/include/gnunet_util_containers.h 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/include/gnunet_util_containers.h 2008-02-17 07:50:48 UTC (rev
6348)
@@ -59,11 +59,6 @@
typedef int (*GNUNET_HashCodeIterator) (GNUNET_HashCode * next, void *arg);
/**
- * @brief a GNUNET_Vector (ordered variable size set of elements), opaque
- */
-struct GNUNET_Vector;
-
-/**
* Load a bloom-filter from a file.
* @param filename the name of the file (or the prefix)
* @param size the size of the bloom-filter (number of
@@ -173,129 +168,6 @@
void *iterator_arg,
unsigned int size, unsigned int k);
-/**
- * A debug function that dumps the vector to stderr.
- */
-void GNUNET_vector_dump (struct GNUNET_Vector *v);
-
-/**
- * @param vss Size of the VectorSegment data area. The "correct" value for this
- * is a bit of a gamble, as it depends on both the operations you
- * perform on the vectors and how much data is stored in them. In
- * general, the more data you store the bigger the segments should be,
- * or otherwise the increased length of the linked list will become a
- * bottleneck for operations that are performed on arbitrary indexes.
- */
-struct GNUNET_Vector *GNUNET_vector_create (unsigned int vss);
-
-/**
- * Free vector structure including its data segments, but _not_ including the
- * stored void pointers. It is the user's responsibility to empty the vector
- * when necessary to avoid memory leakage.
- */
-void GNUNET_vector_destroy (struct GNUNET_Vector *v);
-
-size_t GNUNET_vector_get_size (struct GNUNET_Vector *v);
-
-/**
- * Insert a new element in the vector at given index.
- * @return GNUNET_OK on success, GNUNET_SYSERR if the index is out of bounds.
- */
-int GNUNET_vector_insert_at (struct GNUNET_Vector *v, void *object,
- unsigned int index);
-
-/**
- * Insert a new element at the end of the vector.
- */
-void GNUNET_vector_insert_last (struct GNUNET_Vector *v, void *object);
-
-/**
- * Return the element at given index in the vector or NULL if the index is out
- * of bounds. The iterator is set to point to the returned element.
- */
-void *GNUNET_vector_get (struct GNUNET_Vector *v, unsigned int index);
-
-/**
- * Return the first element in the vector, whose index is 0, or NULL if the
- * vector is empty. The iterator of the vector is set to point to the first
- * element.
- */
-void *GNUNET_vector_get_first (struct GNUNET_Vector *v);
-
-/**
- * Return the last element in the vector or NULL if the vector is empty. The
- * iterator of the vector is set to point to the last element.
- */
-void *GNUNET_vector_get_last (struct GNUNET_Vector *v);
-
-/**
- * Return the next element in the vector, as called after vector_get_at() or
- * vector_get_first(). The return value is NULL if there are no more elements
- * in the vector or if the iterator has not been set.
- */
-void *GNUNET_vector_get_next (struct GNUNET_Vector *v);
-
-/**
- * Return the previous element in the vector, as called after vector_get_at()
- * or vector_get_last(). The return value is NULL if there are no more
- * elements in the vector or if the iterator has not been set.
- */
-void *GNUNET_vector_get_prev (struct GNUNET_Vector *v);
-
-/**
- * Delete and return the element at given index. NULL is returned if index is
- * out of bounds.
- */
-void *GNUNET_vector_delete_at (struct GNUNET_Vector *v, unsigned int index);
-
-/**
- * Delete and return the last element in the vector, or NULL if the vector
- * is empty.
- */
-void *GNUNET_vector_delete_last (struct GNUNET_Vector *v);
-
-/**
- * Delete and return given object from the vector, or return NULL if the object
- * is not found.
- */
-void *GNUNET_vector_delete (struct GNUNET_Vector *v, void *object);
-
-/**
- * Set the given index in the vector. The old value of the index is
- * returned, or NULL if the index is out of bounds.
- */
-void *GNUNET_vector_update_at (struct GNUNET_Vector *v, void *object,
- unsigned int index);
-
-/**
- * Set the index occupied by the given object to point to the new object.
- * The old object is returned, or NULL if it's not found.
- */
-void *GNUNET_vector_update (struct GNUNET_Vector *v, void *object,
- void *old_object);
-
-/**
- * Swaps the contents of index1 and index2. Return value is GNUNET_OK
- * on success, GNUNET_SYSERR if either index is out of bounds.
- */
-int GNUNET_vector_swap_elements (struct GNUNET_Vector *v, unsigned int index1,
- unsigned int index2);
-
-/**
- * Return the index of given element or -1 if the element is not found.
- */
-unsigned int GNUNET_vector_index_of (struct GNUNET_Vector *v, void *object);
-
-/**
- * Return the data stored in the vector as a single dynamically
- * allocated array of (void *), which must be GNUNET_freeed by the caller.
- * Use the functions get_{at,first,last,next,previous} instead, unless
- * you really need to access everything in the vector as fast as
- * possible.
- */
-void **GNUNET_vector_to_array (struct GNUNET_Vector *v);
-
-
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: GNUnet/src/util/containers/Makefile.am
===================================================================
--- GNUnet/src/util/containers/Makefile.am 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/util/containers/Makefile.am 2008-02-17 07:50:48 UTC (rev
6348)
@@ -5,12 +5,10 @@
noinst_LTLIBRARIES = libcontainers.la
libcontainers_la_SOURCES = \
- bloomfilter.c \
- vector.c
+ bloomfilter.c
check_PROGRAMS = \
- bloomtest \
- vectortest
+ bloomtest
TESTS = $(check_PROGRAMS)
@@ -18,9 +16,3 @@
bloomtest.c
bloomtest_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la
-
-vectortest_SOURCES = \
- vectortest.c
-vectortest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
Deleted: GNUnet/src/util/containers/vector.c
===================================================================
--- GNUnet/src/util/containers/vector.c 2008-02-17 04:58:52 UTC (rev 6347)
+++ GNUnet/src/util/containers/vector.c 2008-02-17 07:50:48 UTC (rev 6348)
@@ -1,689 +0,0 @@
-/*
- This file is part of GNUnet
-
- 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
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- 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.
-*/
-
-/**
- * @file util/containers/vector.c
- * @brief Implementation of a dynamic array
- * @author Antti Salonen, Christian Grothoff
- * @version vector.c,v 1.3 2004/05/02 20:22:52 aksalone Exp
- *
- * An implementation of a dynamic array of objects. Like an array, the
- * vector's elements are indexed, but it is also possible to
- * dynamically resize the vector by inserting and removing elements at
- * any location. The vector is implemented as a double-linked list of
- * arrays, each with a static maximum length. When one array fills up,
- * it's splitted into two half-full arrays, and so forth. With
- * functions {insert,get,remove}_last the vector can also be used as a
- * fairly efficient stack. The functions
- * get_{at,first,last,next,previous} allow traversing the vector in an
- * efficient manner, each function call taking more or less constant
- * time. Vector_get_next and Vector_get_first may only be called after
- * a call to one of vector_get_{first,last,at}, which set the vector's
- * iterator. All functions that modify the vector's contents unset the
- * iterator.
- */
-
-#include "platform.h"
-#include "gnunet_util.h"
-#include "gnunet_util_containers.h"
-
-typedef struct GNUNET_Vector
-{
- unsigned int VECTOR_SEGMENT_SIZE;
- struct vector_segment_t *segmentsHead;
- struct vector_segment_t *segmentsTail;
- struct vector_segment_t *iteratorSegment;
- unsigned int iteratorIndex;
- size_t size;
-} Vector;
-
-
-typedef struct vector_segment_t
-{
- void **data; /* always of size VECTOR_SEGMENT_SIZE */
- struct vector_segment_t *next;
- struct vector_segment_t *previous;
- size_t size;
-} VectorSegment;
-
-/**
- * A debug function that traverses the linked list and prints the
- * sizes of the segments. This currently isn't used.
- */
-void
-GNUNET_vector_dump (Vector * v)
-{
- VectorSegment *vs;
- int n;
- unsigned int sum = 0;
-
- for (vs = v->segmentsHead; vs; vs = vs->next)
- {
- fprintf (stderr,
- "Segment-size: %3llu / %llu [%llu...%llu]: ",
- (unsigned long long) vs->size,
- (unsigned long long) v->VECTOR_SEGMENT_SIZE,
- (unsigned long long) sum,
- (unsigned long long) (sum + vs->size - 1));
- for (n = 0; n < vs->size; n++)
- {
- fprintf (stderr, "%p, ", vs->data[n]);
- }
- fprintf (stderr, "\n");
- sum += vs->size;
- }
- fprintf (stderr, "Vector size: %u\n", sum);
-}
-
-/**
- * Remove and return the element at given index in the segment's array. The
- * trailing pointers in the array, if any, are moved backwards to fill the gap.
- */
-static void *
-vectorSegmentRemoveAtIndex (VectorSegment * vs, int index)
-{
- void *rvalue = vs->data[index];
-
- while (index < vs->size)
- {
- vs->data[index] = vs->data[index + 1];
- index++;
- }
- return rvalue;
-}
-
-
-/**
- * Split the full segment vs into two half-full segments.
- */
-static void
-vectorSegmentSplit (Vector * v, VectorSegment * vs)
-{
- VectorSegment *oldNext;
- int moveCount;
-
- oldNext = vs->next;
- vs->next = GNUNET_malloc (sizeof (VectorSegment));
- vs->next->data = GNUNET_malloc (v->VECTOR_SEGMENT_SIZE * sizeof (void *));
- vs->next->previous = vs;
- vs->next->next = oldNext;
- if (NULL != oldNext)
- oldNext->previous = vs->next;
- else
- v->segmentsTail = vs->next;
- moveCount = vs->size / 2;
- memcpy (vs->next->data,
- vs->data + (vs->size - moveCount), moveCount * sizeof (void *));
- vs->next->size = moveCount;
- vs->size -= moveCount;
-}
-
-/**
- * Joins the given segment with the following segment. The first segment _must_
- * be empty enough to store the data of both segments.
- */
-static void
-vectorSegmentJoin (Vector * v, VectorSegment * vs)
-{
- VectorSegment *oldNext = vs->next->next;
-
- memcpy (vs->data + vs->size,
- vs->next->data, vs->next->size * sizeof (void *));
- vs->size += vs->next->size;
- GNUNET_free (vs->next->data);
- GNUNET_free (vs->next);
- vs->next = oldNext;
- if (oldNext != NULL)
- vs->next->previous = vs;
- else
- v->segmentsTail = vs;
-}
-
-/**
- * Free an empty segment, _unless_ it is the only segment.
- */
-static void
-vectorSegmentRemove (Vector * v, VectorSegment * vs)
-{
- if ((vs->previous == NULL) && (vs->next == NULL))
- return;
- if (vs->previous != NULL)
- vs->previous->next = vs->next;
- else
- v->segmentsHead = vs->next;
- if (vs->next != NULL)
- vs->next->previous = vs->previous;
- else
- v->segmentsTail = vs->previous;
- GNUNET_free (vs->data);
- GNUNET_free (vs);
-}
-
-
-/**
- * Search for given index in the vector v. When the index is found, its
- * segment and relative index are written to parameters vs and segment_index.
- * If possible, an unused index at the end of a segment is returned, as this
- * is also a requirement for adding data in an empty vector.
- */
-static int
-vectorFindNewIndex (Vector * v, unsigned int index, VectorSegment ** vs)
-{
- VectorSegment *segment;
- int segmentStartIndex;
-
- if (index > v->size)
- {
- *vs = NULL;
- return -1;
- }
- if (index <= v->size / 2)
- { /* empty vector included */
- segment = v->segmentsHead;
- segmentStartIndex = 0;
- while (index > segmentStartIndex + segment->size)
- {
- segmentStartIndex += segment->size;
- segment = segment->next;
- }
- }
- else
- { /* reverse */
- segment = v->segmentsTail;
- segmentStartIndex = v->size - segment->size;
- while (index <= segmentStartIndex)
- {
- segment = segment->previous;
- segmentStartIndex -= segment->size;
- }
- }
- *vs = segment;
- return index - segmentStartIndex;
-}
-
-
-/**
- * Find the segment and segmentIndex of the element
- * with the given index.
- */
-static int
-vectorFindIndex (Vector * v, unsigned int index, VectorSegment ** vs)
-{
- VectorSegment *segment;
- int segmentStartIndex;
-
- if (index >= v->size)
- {
- *vs = NULL;
- return -1;
- }
- if (index < v->size / 2)
- {
- segment = v->segmentsHead;
- segmentStartIndex = 0;
- while (index >= segmentStartIndex + segment->size)
- {
- segmentStartIndex += segment->size;
- segment = segment->next;
- }
- }
- else
- {
- segment = v->segmentsTail;
- segmentStartIndex = v->size - segment->size;
- while (index < segmentStartIndex)
- {
- segment = segment->previous;
- segmentStartIndex -= segment->size;
- }
- }
- *vs = segment;
- return index - segmentStartIndex;
-}
-
-
-/*
- * Traverse the vector looking for a given object. When found, set the pointer
- * pointed to by vs to point to the object's segment and the integer pointed
- * to by segmentIndex to the object's index in the segment. If the object is
- * not found, *vs is set to NULL.
- */
-static void
-vectorFindObject (Vector * v,
- void *object, VectorSegment ** vs, int *segmentIndex)
-{
- VectorSegment *segment;
- int i;
-
- segment = v->segmentsHead;
- while (NULL != segment)
- {
- for (i = 0; i < segment->size; i++)
- {
- if (segment->data[i] == object)
- {
- *vs = segment;
- *segmentIndex = i;
- return;
- }
- }
- segment = segment->next;
- }
- *vs = NULL;
-}
-
-
-/**
- * Allocate a new vector structure with a single empty data segment.
- */
-Vector *
-GNUNET_vector_create (unsigned int vss)
-{
- Vector *rvalue;
-
- if (vss < 2)
- return NULL; /* invalid! */
- rvalue = GNUNET_malloc (sizeof (Vector));
- rvalue->VECTOR_SEGMENT_SIZE = vss;
- rvalue->size = 0;
- rvalue->segmentsHead = GNUNET_malloc (sizeof (VectorSegment));
- rvalue->segmentsHead->data = GNUNET_malloc (sizeof (void *) * vss);
- rvalue->segmentsTail = rvalue->segmentsHead;
- rvalue->segmentsHead->next = NULL;
- rvalue->segmentsHead->previous = NULL;
- rvalue->segmentsHead->size = 0;
- rvalue->iteratorSegment = NULL;
- rvalue->iteratorIndex = 0;
- return rvalue;
-}
-
-/**
- * Free vector structure including its data segments, but _not_ including the
- * stored void pointers. It is the user's responsibility to empty the vector
- * when necessary to avoid memory leakage.
- */
-void
-GNUNET_vector_destroy (Vector * v)
-{
- VectorSegment *vs;
- VectorSegment *vsNext;
-
- vs = v->segmentsHead;
- while (vs != NULL)
- {
- vsNext = vs->next;
- GNUNET_free (vs->data);
- GNUNET_free (vs);
- vs = vsNext;
- }
- GNUNET_free (v);
-}
-
-/**
- * Return the size of the vector.
- */
-size_t
-GNUNET_vector_get_size (Vector * v)
-{
- return v->size;
-}
-
-/**
- * Insert a new element in the vector at given index. The return value is
- * GNUNET_OK on success, GNUNET_SYSERR if the index is out of bounds.
- */
-int
-GNUNET_vector_insert_at (Vector * v, void *object, unsigned int index)
-{
- VectorSegment *segment;
- int segmentIndex;
- int i;
-
- if (index > v->size)
- return GNUNET_SYSERR;
- v->iteratorSegment = NULL;
- segmentIndex = vectorFindNewIndex (v, index, &segment);
- if (segmentIndex == -1)
- return GNUNET_SYSERR;
- for (i = segment->size; i > segmentIndex; i--)
- segment->data[i] = segment->data[i - 1];
- segment->data[segmentIndex] = object;
- v->size++;
- segment->size++;
- if (segment->size == v->VECTOR_SEGMENT_SIZE)
- vectorSegmentSplit (v, segment);
- return GNUNET_OK;
-}
-
-/**
- * Insert a new element at the end of the vector.
- */
-void
-GNUNET_vector_insert_last (Vector * v, void *object)
-{
- v->iteratorSegment = NULL;
- v->segmentsTail->data[v->segmentsTail->size++] = object;
- if (v->segmentsTail->size == v->VECTOR_SEGMENT_SIZE)
- vectorSegmentSplit (v, v->segmentsTail);
- v->size++;
-}
-
-/**
- * Return the element at given index in the vector or NULL if the index is out
- * of bounds. The iterator is set to point to the returned element.
- */
-void *
-GNUNET_vector_get (Vector * v, unsigned int index)
-{
- int ret;
- if (index >= v->size)
- return NULL;
- ret = vectorFindIndex (v, index, &v->iteratorSegment);
- if (ret == -1)
- return NULL;
- v->iteratorIndex = ret;
- return v->iteratorSegment->data[ret];
-}
-
-/**
- * Return the first element in the vector, whose index is 0, or NULL if the
- * vector is empty. The iterator of the vector is set to point to the first
- * element.
- */
-void *
-GNUNET_vector_get_first (Vector * v)
-{
- if (v->size == 0)
- return NULL;
- v->iteratorSegment = v->segmentsHead;
- v->iteratorIndex = 0;
- return v->iteratorSegment->data[0];
-}
-
-/**
- * Return the last element in the vector or NULL if the vector is
- * empty. The iterator of the vector is set to the last element.
- */
-void *
-GNUNET_vector_get_last (Vector * v)
-{
- if (v->size == 0)
- return NULL;
- v->iteratorSegment = v->segmentsTail;
- v->iteratorIndex = v->segmentsTail->size - 1;
- return v->segmentsTail->data[v->iteratorIndex];
-}
-
-/**
- * Return the next element in the vector, as called after vector_get_at() or
- * vector_get_first(). The return value is NULL if there are no more elements
- * in the vector or if the iterator has not been set.
- */
-void *
-GNUNET_vector_get_next (Vector * v)
-{
- if (v->iteratorSegment == NULL)
- return NULL;
- if (++v->iteratorIndex >= v->iteratorSegment->size)
- {
- if (v->iteratorSegment == v->segmentsTail)
- {
- v->iteratorSegment = NULL;
- return NULL;
- }
- else
- {
- v->iteratorSegment = v->iteratorSegment->next;
- v->iteratorIndex = 0;
- }
- }
- return v->iteratorSegment->data[v->iteratorIndex];
-}
-
-/**
- * Return the previous element in the vector, as called after vector_get_at()
- * or vector_get_last(). The return value is NULL if there are no more
- * elements in the vector or if the iterator has not been set.
- */
-void *
-GNUNET_vector_get_prev (Vector * v)
-{
- if (v->iteratorSegment == NULL)
- return NULL;
- if (--v->iteratorIndex == -1)
- {
- if (v->iteratorSegment == v->segmentsHead)
- {
- v->iteratorSegment = 0;
- return NULL;
- }
- else
- {
- v->iteratorSegment = v->iteratorSegment->previous;
- v->iteratorIndex = v->iteratorSegment->size - 1;
- }
- }
- return v->iteratorSegment->data[v->iteratorIndex];
-}
-
-/**
- * Delete and return the element at given index. NULL is returned if index is
- * out of bounds.
- */
-void *
-GNUNET_vector_delete_at (Vector * v, unsigned int index)
-{
- VectorSegment *segment;
- int segmentIndex;
- void *rvalue;
-
- if (index >= v->size)
- return NULL;
- v->iteratorSegment = NULL;
- segmentIndex = vectorFindIndex (v, index, &segment);
- if (segmentIndex == -1)
- return NULL;
- rvalue = vectorSegmentRemoveAtIndex (segment, segmentIndex);
- /* If the segment ends empty remove it, otherwise
- try to join it with its neighbors. */
- if (--segment->size == 0)
- vectorSegmentRemove (v, segment);
- else if (segment->next &&
- segment->size + segment->next->size < v->VECTOR_SEGMENT_SIZE)
- vectorSegmentJoin (v, segment);
- else if (segment->previous &&
- segment->size + segment->previous->size < v->VECTOR_SEGMENT_SIZE)
- vectorSegmentJoin (v, segment->previous);
- v->size--;
- return rvalue;
-}
-
-/**
- * Delete and return the last element in the vector, or NULL if the vector
- * is empty.
- */
-void *
-GNUNET_vector_delete_last (Vector * v)
-{
- void *rvalue;
-
- if (v->size == 0)
- return NULL;
- v->iteratorSegment = NULL;
- rvalue = v->segmentsTail->data[v->segmentsTail->size - 1];
- /* If the segment ends empty remove it, otherwise join it if necessary. */
- if (--v->segmentsTail->size == 0)
- vectorSegmentRemove (v, v->segmentsTail);
- else if ((v->segmentsTail->previous != NULL) &&
- (v->segmentsTail->size + v->segmentsTail->previous->size
- < v->VECTOR_SEGMENT_SIZE))
- vectorSegmentJoin (v, v->segmentsTail->previous);
- v->size--;
- return rvalue;
-}
-
-/**
- * Delete and return given object from the vector, or return NULL if the object
- * is not found.
- */
-void *
-GNUNET_vector_delete (Vector * v, void *object)
-{
- VectorSegment *segment;
- int segmentIndex;
- void *rvalue;
-
- v->iteratorSegment = NULL;
- vectorFindObject (v, object, &segment, &segmentIndex);
- if (segment == NULL)
- return NULL;
- rvalue = vectorSegmentRemoveAtIndex (segment, segmentIndex);
- /* If the segment ends empty remove it, otherwise join it if necessary. */
- if (--segment->size == 0)
- vectorSegmentRemove (v, segment);
- else if ((segment->next != NULL) &&
- (segment->size + segment->next->size < v->VECTOR_SEGMENT_SIZE))
- vectorSegmentJoin (v, segment);
- else if ((segment->previous != NULL) &&
- (segment->size + segment->previous->size < v->VECTOR_SEGMENT_SIZE))
- vectorSegmentJoin (v, segment->previous);
- v->size--;
- return rvalue;
-}
-
-/**
- * Set the given index in the vector. The old value of the index is
- * returned, or NULL if the index is out of bounds.
- */
-void *
-GNUNET_vector_update_at (Vector * v, void *object, unsigned int index)
-{
- VectorSegment *segment;
- int segmentIndex;
- void *rvalue;
-
- if (index >= v->size)
- return NULL;
- v->iteratorSegment = NULL;
- segmentIndex = vectorFindIndex (v, index, &segment);
- if (segmentIndex == -1)
- return NULL;
- rvalue = segment->data[segmentIndex];
- segment->data[segmentIndex] = object;
- return rvalue;
-}
-
-
-/**
- * Set the index occupied by the given object to point to the new object.
- * The old object is returned, or NULL if it's not found.
- */
-void *
-GNUNET_vector_update (Vector * v, void *object, void *oldObject)
-{
- VectorSegment *segment;
- int segmentIndex;
- void *rvalue;
-
- v->iteratorSegment = NULL;
- vectorFindObject (v, oldObject, &segment, &segmentIndex);
- if (segment == NULL)
- return NULL;
- rvalue = segment->data[segmentIndex];
- segment->data[segmentIndex] = object;
- return rvalue;
-}
-
-
-/**
- * Swaps the contents of index1 and index2. Return value is GNUNET_OK
- * on success, GNUNET_SYSERR if either index is out of bounds.
- */
-int
-GNUNET_vector_swap_elements (Vector * v, unsigned int index1,
- unsigned int index2)
-{
- VectorSegment *segment1;
- VectorSegment *segment2;
- int segmentIndex1;
- int segmentIndex2;
- void *temp;
-
- if ((index1 >= v->size) || (index2 >= v->size))
- return GNUNET_SYSERR;
- v->iteratorSegment = NULL;
- segmentIndex1 = vectorFindIndex (v, index1, &segment1);
- segmentIndex2 = vectorFindIndex (v, index2, &segment2);
- if ((segmentIndex1 == -1) || (segmentIndex2 == -1))
- return GNUNET_SYSERR;
- temp = segment1->data[segmentIndex1];
- segment1->data[segmentIndex1] = segment2->data[segmentIndex2];
- segment2->data[segmentIndex2] = temp;
- return GNUNET_OK;
-}
-
-/**
- * Return the index of given element or -1 if the element is not found.
- */
-unsigned int
-GNUNET_vector_index_of (Vector * v, void *object)
-{
- VectorSegment *segment;
- unsigned int i;
- unsigned int segmentStartIndex;
-
- segmentStartIndex = 0;
- segment = v->segmentsHead;
- while (NULL != segment)
- {
- for (i = 0; i < segment->size; i++)
- if (segment->data[i] == object)
- return segmentStartIndex + i;
- segmentStartIndex += segment->size;
- segment = segment->next;
- }
- return (unsigned int) -1;
-}
-
-
-/*
- * Return the data stored in the vector as a single dynamically allocated
- * array of (void *), which must be free(3)d by the user. Use the functions
- * get_{at,first,last,next,previous} instead, unless you really need to access
- * everything in the vector as fast as possible.
- */
-void **
-GNUNET_vector_to_array (Vector * v)
-{
- void **rvalue;
- VectorSegment *vs;
- size_t i = 0;
-
- rvalue = GNUNET_malloc_large (v->size * sizeof (void *));
- for (vs = v->segmentsHead; vs; vs = vs->next)
- {
- memcpy (rvalue + i, vs->data, vs->size * sizeof (void *));
- i += vs->size;
- }
- return rvalue;
-}
-
-
-
-/* end of vector.c */
Deleted: GNUnet/src/util/containers/vectortest.c
===================================================================
--- GNUnet/src/util/containers/vectortest.c 2008-02-17 04:58:52 UTC (rev
6347)
+++ GNUnet/src/util/containers/vectortest.c 2008-02-17 07:50:48 UTC (rev
6348)
@@ -1,277 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2005, 2006 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
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- 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.
-*/
-
-/**
- * This is a testcase for the vector, waiting to be extended.
- */
-
-#include "gnunet_util.h"
-#include "gnunet_util_containers.h"
-#include "platform.h"
-
-#define DUMP(v) fprintf(stderr, "At %d: \n", __LINE__); GNUNET_vector_dump(v);
GNUNET_vector_destroy(v);
-
-static int
-test (int size)
-{
- struct GNUNET_Vector *v;
-
- v = GNUNET_vector_create (size);
- if (0 != GNUNET_vector_get_size (v))
- {
- DUMP (v);
- return 1;
- }
- if (GNUNET_OK != GNUNET_vector_insert_at (v, "first", 0))
- {
- DUMP (v);
- return 1;
- }
- if (GNUNET_OK == GNUNET_vector_insert_at (v, "not", 2))
- {
- DUMP (v);
- return 1;
- }
- if (GNUNET_OK != GNUNET_vector_insert_at (v, "zero", 0))
- {
- DUMP (v);
- return 1;
- }
- if (GNUNET_OK != GNUNET_vector_insert_at (v, "second", 2))
- {
- DUMP (v);
- return 1;
- }
- GNUNET_vector_insert_last (v, "third");
- if (4 != GNUNET_vector_get_size (v))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_get (v, 1), "first"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_get (v, 3), "third"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_get (v, 0), "zero"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_get_first (v), "zero"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_get_last (v), "third"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_delete_at (v, 1), "first"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_get (v, 1), "second"))
- {
- DUMP (v);
- return 1;
- }
- if (NULL != GNUNET_vector_delete_at (v, 3))
- {
- DUMP (v);
- return 1;
- }
- if (3 != GNUNET_vector_get_size (v))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_delete_at (v, 1), "second"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_delete (v, "third"), "third"))
- {
- DUMP (v);
- return 1;
- }
- if (NULL != GNUNET_vector_delete (v, "third"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != strcmp (GNUNET_vector_delete_last (v), "zero"))
- {
- DUMP (v);
- return 1;
- }
- if (0 != GNUNET_vector_get_size (v))
- {
- DUMP (v);
- return 1;
- }
- if (NULL != GNUNET_vector_delete_last (v))
- {
- DUMP (v);
- return 1;
- }
- if (0 != GNUNET_vector_get_size (v))
- {
- DUMP (v);
- return 1;
- }
- GNUNET_vector_destroy (v);
- return 0;
-}
-
-static int
-test2 (int size)
-{
- long i;
- struct GNUNET_Vector *v;
-
- v = GNUNET_vector_create (size);
-
- for (i = 0; i < 500; i++)
- if (GNUNET_OK != GNUNET_vector_insert_at (v, (void *) i, 0))
- {
- DUMP (v);
- return 1;
- }
- if (500 != GNUNET_vector_get_size (v))
- {
- DUMP (v);
- return 1;
- }
- for (i = 0; i < 500; i++)
- if (499 - i != (long) GNUNET_vector_get (v, i))
- {
- DUMP (v);
- return 1;
- }
- if (499 != (long) GNUNET_vector_get_first (v))
- {
- DUMP (v);
- return 1;
- }
- for (i = 498; i >= 0; i--)
- if (i != (long) GNUNET_vector_get_next (v))
- {
- DUMP (v);
- return 1;
- }
-
- if (499 != (long) GNUNET_vector_get_first (v))
- {
- DUMP (v);
- return 1;
- }
- for (i = 498; i >= 250; i--)
- if (i != (long) GNUNET_vector_get_next (v))
- {
- DUMP (v);
- return 1;
- }
- for (i = 251; i < 499; i++)
- if (i != (long) GNUNET_vector_get_prev (v))
- {
- DUMP (v);
- return 1;
- }
-
- GNUNET_vector_destroy (v);
- return 0;
-}
-
-
-int
-main (int argc, char *argv[])
-{
- if (NULL != GNUNET_vector_create (0))
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (NULL != GNUNET_vector_create (1))
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test (2) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test (3) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test (4) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test (128) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test (65536) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test (2 * 65536) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
-
- if (test2 (2) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test2 (3) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test2 (4) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- if (test2 (128) != 0)
- {
- printf ("At %d\n", __LINE__);
- return 1;
- }
- return 0;
-}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r6348 - in GNUnet/src: applications applications/dht/module applications/dht/tools applications/fs/collection applications/fs/fsui applications/fs/gap applications/rpc include util/containers,
gnunet <=