[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r8841 - in gnunet: . src/fs src/include
From: |
gnunet |
Subject: |
[GNUnet-SVN] r8841 - in gnunet: . src/fs src/include |
Date: |
Sat, 22 Aug 2009 11:57:31 -0600 |
Author: grothoff
Date: 2009-08-22 11:57:31 -0600 (Sat, 22 Aug 2009)
New Revision: 8841
Added:
gnunet/src/fs/fs.c
gnunet/src/fs/fs_download.c
gnunet/src/fs/fs_file_information.c
gnunet/src/fs/fs_namespace.c
gnunet/src/fs/fs_publish.c
gnunet/src/fs/fs_search.c
gnunet/src/fs/fs_test.c
gnunet/src/fs/fs_unindex.c
gnunet/src/fs/test_fs_collection_data.conf
gnunet/src/fs/test_fs_download.c
gnunet/src/fs/test_fs_download_recursive.c
gnunet/src/fs/test_fs_search_persistence.c
gnunet/src/fs/test_fs_search_ranking.c
gnunet/src/fs/test_fs_start_stop.c
gnunet/src/fs/test_namespace.c
Modified:
gnunet/TODO
gnunet/src/fs/Makefile.am
gnunet/src/fs/fs.h
gnunet/src/fs/fs_directory.c
gnunet/src/fs/fs_uri.c
gnunet/src/fs/test_fs_collection.c
gnunet/src/fs/test_fs_directory.c
gnunet/src/fs/test_fs_getopt.c
gnunet/src/fs/test_fs_uri.c
gnunet/src/include/gnunet_fs_service.h
Log:
stuff
Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/TODO 2009-08-22 17:57:31 UTC (rev 8841)
@@ -39,8 +39,8 @@
- review FS API [Nils, Amatus, CG]
- design network structs (CS)
- implement FS library
- + URI API
- + getopt API
+ + URI API -- DONE (but do more testing)
+ + getopt API -- DONE (but do more testing)
+ persistence mechanism
+ sharing API
~ file-information
Modified: gnunet/src/fs/Makefile.am
===================================================================
--- gnunet/src/fs/Makefile.am 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/Makefile.am 2009-08-22 17:57:31 UTC (rev 8841)
@@ -13,9 +13,13 @@
lib_LTLIBRARIES = libgnunetfs.la
libgnunetfs_la_SOURCES = \
+ fs.c \
fs_collection.c \
fs_directory.c \
+ fs_file_information.c \
fs_getopt.c \
+ fs_publish.c \
+ fs_namespace.c \
fs_uri.c
libgnunetfs_la_LIBADD = \
@@ -31,8 +35,8 @@
# gnunet-directory
# gnunet-download
# gnunet-pseudonym
+# gnunet-publish
# gnunet-search
-# gnunet-share
# gnunet-unindex
#gnunet_directory_SOURCES =
@@ -76,4 +80,5 @@
$(top_builddir)/src/util/libgnunetutil.la
EXTRA_DIST = \
+ test_fs_collection_data.conf \
test_fs_uri_data.conf
Added: gnunet/src/fs/fs.c
===================================================================
--- gnunet/src/fs/fs.c (rev 0)
+++ gnunet/src/fs/fs.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,65 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 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 fs/fs.c
+ * @brief main FS functions
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_fs_service.h"
+#include "fs.h"
+
+
+
+/**
+ * Setup a connection to the file-sharing service.
+ *
+ * @param sched scheduler to use
+ * @param cfg configuration to use
+ * @param client_name unique identifier for this client
+ * @param upcb function to call to notify about FS actions
+ * @param upcb_cls closure for upcb
+ */
+struct GNUNET_FS_Handle *
+GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *client_name,
+ GNUNET_FS_ProgressCallback upcb,
+ void *upcb_cls)
+{
+ return NULL;
+}
+
+
+/**
+ * Close our connection with the file-sharing service.
+ * The callback given to GNUNET_FS_start will no longer be
+ * called after this function returns.
+ *
+ * @param h handle that was returned from GNUNET_FS_start
+ */
+void
+GNUNET_FS_stop (struct GNUNET_FS_Handle *h)
+{
+}
+
+/* end of fs.c */
Modified: gnunet/src/fs/fs.h
===================================================================
--- gnunet/src/fs/fs.h 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/fs.h 2009-08-22 17:57:31 UTC (rev 8841)
@@ -129,4 +129,16 @@
};
+
+/**
+ * Information for a file or directory that is
+ * about to be published.
+ */
+struct GNUNET_FS_FileInformation
+{
+
+
+};
+
+
#endif
Modified: gnunet/src/fs/fs_directory.c
===================================================================
--- gnunet/src/fs/fs_directory.c 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/fs_directory.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -231,6 +231,13 @@
}
}
+
+void
+GNUNET_FS_directory_create ()
+{
+}
+
+
#if 0
Added: gnunet/src/fs/fs_download.c
===================================================================
--- gnunet/src/fs/fs_download.c (rev 0)
+++ gnunet/src/fs/fs_download.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,923 @@
+/*
+ This file is part of GNUnet.
+ (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
+ 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 applications/fs/ecrs/download.c
+ * @brief DOWNLOAD helper methods (which do the real work).
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_protocols.h"
+#include "gnunet_ecrs_lib.h"
+#include "gnunet_fs_lib.h"
+#include "gnunet_identity_lib.h"
+#include "ecrs_core.h"
+#include "ecrs.h"
+#include "fs.h"
+#include "tree.h"
+
+#define DEBUG_DOWNLOAD GNUNET_NO
+
+/**
+ * Node-specific data (not shared, keep small!). 152 bytes.
+ * Nodes are kept in a doubly-linked list.
+ */
+struct Node
+{
+ /**
+ * Pointer to shared data between all nodes (request manager,
+ * progress data, etc.).
+ */
+ struct GNUNET_ECRS_DownloadContext *ctx;
+
+ /**
+ * Previous entry in DLL.
+ */
+ struct Node *prev;
+
+ /**
+ * Next entry in DLL.
+ */
+ struct Node *next;
+
+ /**
+ * What is the GNUNET_EC_ContentHashKey for this block?
+ */
+ GNUNET_EC_ContentHashKey chk;
+
+ /**
+ * At what offset (on the respective level!) is this
+ * block?
+ */
+ unsigned long long offset;
+
+ /**
+ * 0 for dblocks, >0 for iblocks.
+ */
+ unsigned int level;
+
+};
+
+/**
+ * @brief structure that keeps track of currently pending requests for
+ * a download
+ *
+ * Handle to the state of a request manager. Here we keep track of
+ * which queries went out with which priorities and which nodes in
+ * the merkle-tree are waiting for the replies.
+ */
+struct GNUNET_ECRS_DownloadContext
+{
+
+ /**
+ * Total number of bytes in the file.
+ */
+ unsigned long long total;
+
+ /**
+ * Number of bytes already obtained
+ */
+ unsigned long long completed;
+
+ /**
+ * Starting-offset in file (for partial download)
+ */
+ unsigned long long offset;
+
+ /**
+ * Length of the download (starting at offset).
+ */
+ unsigned long long length;
+
+ /**
+ * Time download was started.
+ */
+ GNUNET_CronTime startTime;
+
+ /**
+ * Doubly linked list of all pending requests (head)
+ */
+ struct Node *head;
+
+ /**
+ * Doubly linked list of all pending requests (tail)
+ */
+ struct Node *tail;
+
+ /**
+ * FSLIB context for issuing requests.
+ */
+ struct GNUNET_FS_SearchContext *sctx;
+
+ /**
+ * Context for error reporting.
+ */
+ struct GNUNET_GE_Context *ectx;
+
+ /**
+ * Configuration information.
+ */
+ struct GNUNET_GC_Configuration *cfg;
+
+ /**
+ * The file handle.
+ */
+ int handle;
+
+ /**
+ * Do we exclusively own this sctx?
+ */
+ int my_sctx;
+
+ /**
+ * The base-filename
+ */
+ char *filename;
+
+ /**
+ * Main thread running the operation.
+ */
+ struct GNUNET_ThreadHandle *main;
+
+ /**
+ * Function to call when we make progress.
+ */
+ GNUNET_ECRS_DownloadProgressCallback dpcb;
+
+ /**
+ * Extra argument to dpcb.
+ */
+ void *dpcbClosure;
+
+ /**
+ * Identity of the peer having the content, or all-zeros
+ * if we don't know of such a peer.
+ */
+ GNUNET_PeerIdentity target;
+
+ /**
+ * Abort? Flag that can be set at any time
+ * to abort the RM as soon as possible. Set
+ * to GNUNET_YES during orderly shutdown,
+ * set to GNUNET_SYSERR on error.
+ */
+ int abortFlag;
+
+ /**
+ * Do we have a specific peer from which we download
+ * from?
+ */
+ int have_target;
+
+ /**
+ * Desired anonymity level for the download.
+ */
+ unsigned int anonymityLevel;
+
+ /**
+ * The depth of the file-tree.
+ */
+ unsigned int treedepth;
+
+};
+
+static int
+content_receive_callback (const GNUNET_HashCode * query,
+ const GNUNET_DatastoreValue * reply, void *cls,
+ unsigned long long uid);
+
+
+/**
+ * Close the files and free the associated resources.
+ *
+ * @param self reference to the download context
+ */
+static void
+free_request_manager (struct GNUNET_ECRS_DownloadContext *rm)
+{
+ struct Node *pos;
+
+ if (rm->abortFlag == GNUNET_NO)
+ rm->abortFlag = GNUNET_YES;
+ if (rm->my_sctx == GNUNET_YES)
+ GNUNET_FS_destroy_search_context (rm->sctx);
+ else
+ GNUNET_FS_suspend_search_context (rm->sctx);
+ while (rm->head != NULL)
+ {
+ pos = rm->head;
+ GNUNET_DLL_remove (rm->head, rm->tail, pos);
+ if (rm->my_sctx != GNUNET_YES)
+ GNUNET_FS_stop_search (rm->sctx, &content_receive_callback, pos);
+ GNUNET_free (pos);
+ }
+ if (rm->my_sctx != GNUNET_YES)
+ GNUNET_FS_resume_search_context (rm->sctx);
+ GNUNET_GE_ASSERT (NULL, rm->tail == NULL);
+ if (rm->handle >= 0)
+ CLOSE (rm->handle);
+ if (rm->main != NULL)
+ GNUNET_thread_release_self (rm->main);
+ GNUNET_free_non_null (rm->filename);
+ rm->sctx = NULL;
+ GNUNET_free (rm);
+}
+
+/**
+ * Read method.
+ *
+ * @param self reference to the download context
+ * @param level level in the tree to read/write at
+ * @param pos position where to read or write
+ * @param buf where to read from or write to
+ * @param len how many bytes to read or write
+ * @return number of bytes read, GNUNET_SYSERR on error
+ */
+static int
+read_from_files (struct GNUNET_ECRS_DownloadContext *self,
+ unsigned int level,
+ unsigned long long pos, void *buf, unsigned int len)
+{
+ if ((level > 0) || (self->handle == -1))
+ return GNUNET_SYSERR;
+ LSEEK (self->handle, pos, SEEK_SET);
+ return READ (self->handle, buf, len);
+}
+
+/**
+ * Write method.
+ *
+ * @param self reference to the download context
+ * @param level level in the tree to write to
+ * @param pos position where to write
+ * @param buf where to write to
+ * @param len how many bytes to write
+ * @return number of bytes written, GNUNET_SYSERR on error
+ */
+static int
+write_to_files (struct GNUNET_ECRS_DownloadContext *self,
+ unsigned int level,
+ unsigned long long pos, void *buf, unsigned int len)
+{
+ int ret;
+
+ if (level > 0)
+ return len; /* lie -- no more temps */
+ if (self->handle == -1)
+ return len;
+ LSEEK (self->handle, pos, SEEK_SET);
+ ret = WRITE (self->handle, buf, len);
+ if (ret != len)
+ GNUNET_GE_LOG_STRERROR_FILE (self->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK |
+ GNUNET_GE_USER, "write", self->filename);
+ return ret;
+}
+
+/**
+ * Queue a request for execution.
+ *
+ * @param rm the request manager struct from createRequestManager
+ * @param node the node to call once a reply is received
+ */
+static void
+add_request (struct Node *node)
+{
+ struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
+
+ GNUNET_DLL_insert (rm->head, rm->tail, node);
+ GNUNET_FS_start_search (rm->sctx,
+ rm->have_target == GNUNET_NO ? NULL : &rm->target,
+ GNUNET_ECRS_BLOCKTYPE_DATA, 1,
+ &node->chk.query,
+ rm->anonymityLevel,
+ &content_receive_callback, node);
+}
+
+static void
+signal_abort (struct GNUNET_ECRS_DownloadContext *rm, const char *msg)
+{
+ rm->abortFlag = GNUNET_SYSERR;
+ if ((rm->head != NULL) && (rm->dpcb != NULL))
+ rm->dpcb (rm->length + 1, 0, 0, 0, msg, 0, rm->dpcbClosure);
+ GNUNET_thread_stop_sleep (rm->main);
+}
+
+/**
+ * Dequeue a request.
+ *
+ * @param self the request manager struct from createRequestManager
+ * @param node the block for which the request is canceled
+ */
+static void
+delete_node (struct Node *node)
+{
+ struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
+
+ GNUNET_DLL_remove (rm->head, rm->tail, node);
+ GNUNET_free (node);
+ if (rm->head == NULL)
+ GNUNET_thread_stop_sleep (rm->main);
+}
+
+/**
+ * Compute how many bytes of data are stored in
+ * this node.
+ */
+static unsigned int
+get_node_size (const struct Node *node)
+{
+ unsigned int i;
+ unsigned int ret;
+ unsigned long long rsize;
+ unsigned long long spos;
+ unsigned long long epos;
+
+ GNUNET_GE_ASSERT (node->ctx->ectx, node->offset < node->ctx->total);
+ if (node->level == 0)
+ {
+ ret = GNUNET_ECRS_DBLOCK_SIZE;
+ if (node->offset + (unsigned long long) ret > node->ctx->total)
+ ret = (unsigned int) (node->ctx->total - node->offset);
+#if DEBUG_DOWNLOAD
+ GNUNET_GE_LOG (node->ctx->rm->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Node at offset %llu and level %d has size %u\n",
+ node->offset, node->level, ret);
+#endif
+ return ret;
+ }
+ rsize = GNUNET_ECRS_DBLOCK_SIZE;
+ for (i = 0; i < node->level - 1; i++)
+ rsize *= GNUNET_ECRS_CHK_PER_INODE;
+ spos = rsize * (node->offset / sizeof (GNUNET_EC_ContentHashKey));
+ epos = spos + rsize * GNUNET_ECRS_CHK_PER_INODE;
+ if (epos > node->ctx->total)
+ epos = node->ctx->total;
+ ret = (epos - spos) / rsize;
+ if (ret * rsize < epos - spos)
+ ret++; /* need to round up! */
+#if DEBUG_DOWNLOAD
+ GNUNET_GE_LOG (node->ctx->rm->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Node at offset %llu and level %d has size %u\n",
+ node->offset, node->level,
+ ret * sizeof (GNUNET_EC_ContentHashKey));
+#endif
+ return ret * sizeof (GNUNET_EC_ContentHashKey);
+}
+
+/**
+ * Notify client about progress.
+ */
+static void
+notify_client_about_progress (const struct Node *node,
+ const char *data, unsigned int size)
+{
+ struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
+ GNUNET_CronTime eta;
+
+ if ((rm->abortFlag != GNUNET_NO) || (node->level != 0))
+ return;
+ rm->completed += size;
+ eta = GNUNET_get_time ();
+ if (rm->completed > 0)
+ eta = (GNUNET_CronTime) (rm->startTime +
+ (((double) (eta - rm->startTime) /
+ (double) rm->completed)) *
+ (double) rm->length);
+ if (rm->dpcb != NULL)
+ rm->dpcb (rm->length,
+ rm->completed, eta, node->offset, data, size, rm->dpcbClosure);
+}
+
+
+/**
+ * DOWNLOAD children of this GNUNET_EC_IBlock.
+ *
+ * @param node the node for which the children should be downloaded
+ * @param data data for the node
+ * @param size size of data
+ */
+static void iblock_download_children (const struct Node *node,
+ const char *data, unsigned int size);
+
+/**
+ * Check if self block is already present on the drive. If the block
+ * is a dblock and present, the ProgressModel is notified. If the
+ * block is present and it is an iblock, downloading the children is
+ * triggered.
+ *
+ * Also checks if the block is within the range of blocks
+ * that we are supposed to download. If not, the method
+ * returns as if the block is present but does NOT signal
+ * progress.
+ *
+ * @param node that is checked for presence
+ * @return GNUNET_YES if present, GNUNET_NO if not.
+ */
+static int
+check_node_present (const struct Node *node)
+{
+ int res;
+ int ret;
+ char *data;
+ unsigned int size;
+ GNUNET_HashCode hc;
+
+ size = get_node_size (node);
+ /* first check if node is within range.
+ For now, keeping it simple, we only do
+ this for level-0 nodes */
+ if ((node->level == 0) &&
+ ((node->offset + size < node->ctx->offset) ||
+ (node->offset >= node->ctx->offset + node->ctx->length)))
+ return GNUNET_YES;
+ data = GNUNET_malloc (size);
+ ret = GNUNET_NO;
+ res = read_from_files (node->ctx, node->level, node->offset, data, size);
+ if (res == size)
+ {
+ GNUNET_hash (data, size, &hc);
+ if (0 == memcmp (&hc, &node->chk.key, sizeof (GNUNET_HashCode)))
+ {
+ notify_client_about_progress (node, data, size);
+ if (node->level > 0)
+ iblock_download_children (node, data, size);
+ ret = GNUNET_YES;
+ }
+ }
+ GNUNET_free (data);
+ return ret;
+}
+
+/**
+ * DOWNLOAD children of this GNUNET_EC_IBlock.
+ *
+ * @param node the node that should be downloaded
+ */
+static void
+iblock_download_children (const struct Node *node,
+ const char *data, unsigned int size)
+{
+ struct GNUNET_GE_Context *ectx = node->ctx->ectx;
+ int i;
+ struct Node *child;
+ unsigned int childcount;
+ const GNUNET_EC_ContentHashKey *chks;
+ unsigned int levelSize;
+ unsigned long long baseOffset;
+
+ GNUNET_GE_ASSERT (ectx, node->level > 0);
+ childcount = size / sizeof (GNUNET_EC_ContentHashKey);
+ if (size != childcount * sizeof (GNUNET_EC_ContentHashKey))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ return;
+ }
+ if (node->level == 1)
+ {
+ levelSize = GNUNET_ECRS_DBLOCK_SIZE;
+ baseOffset =
+ node->offset / sizeof (GNUNET_EC_ContentHashKey) *
+ GNUNET_ECRS_DBLOCK_SIZE;
+ }
+ else
+ {
+ levelSize =
+ sizeof (GNUNET_EC_ContentHashKey) * GNUNET_ECRS_CHK_PER_INODE;
+ baseOffset = node->offset * GNUNET_ECRS_CHK_PER_INODE;
+ }
+ chks = (const GNUNET_EC_ContentHashKey *) data;
+ for (i = 0; i < childcount; i++)
+ {
+ child = GNUNET_malloc (sizeof (struct Node));
+ child->ctx = node->ctx;
+ child->chk = chks[i];
+ child->offset = baseOffset + i * levelSize;
+ GNUNET_GE_ASSERT (ectx, child->offset < node->ctx->total);
+ child->level = node->level - 1;
+ GNUNET_GE_ASSERT (ectx, (child->level != 0) ||
+ ((child->offset % GNUNET_ECRS_DBLOCK_SIZE) == 0));
+ if (GNUNET_NO == check_node_present (child))
+ add_request (child);
+ else
+ GNUNET_free (child); /* done already! */
+ }
+}
+
+
+/**
+ * Decrypts a given data block
+ *
+ * @param data represents the data block
+ * @param hashcode represents the key concatenated with the initial
+ * value used in the alg
+ * @param result where to store the result (encrypted block)
+ * @returns GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+static int
+decrypt_content (const char *data,
+ unsigned int size, const GNUNET_HashCode * hashcode,
+ char *result)
+{
+ GNUNET_AES_InitializationVector iv;
+ GNUNET_AES_SessionKey skey;
+
+ /* get key and init value from the GNUNET_HashCode */
+ GNUNET_hash_to_AES_key (hashcode, &skey, &iv);
+ return GNUNET_AES_decrypt (&skey, data, size, &iv, result);
+}
+
+/**
+ * We received a GNUNET_EC_ContentHashKey reply for a block. Decrypt. Note
+ * that the caller (fslib) has already aquired the
+ * RM lock (we sometimes aquire it again in callees,
+ * mostly because our callees could be also be theoretically
+ * called from elsewhere).
+ *
+ * @param cls the node for which the reply is given, freed in
+ * the function!
+ * @param query the query for which reply is the answer
+ * @param reply the reply
+ * @return GNUNET_OK if the reply was valid, GNUNET_SYSERR on error
+ */
+static int
+content_receive_callback (const GNUNET_HashCode * query,
+ const GNUNET_DatastoreValue * reply, void *cls,
+ unsigned long long uid)
+{
+ struct Node *node = cls;
+ struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
+ struct GNUNET_GE_Context *ectx = rm->ectx;
+ GNUNET_HashCode hc;
+ unsigned int size;
+ char *data;
+
+ if (rm->abortFlag != GNUNET_NO)
+ return GNUNET_SYSERR;
+ GNUNET_GE_ASSERT (ectx,
+ 0 == memcmp (query, &node->chk.query,
+ sizeof (GNUNET_HashCode)));
+ size = ntohl (reply->size) - sizeof (GNUNET_DatastoreValue);
+ if ((size <= sizeof (GNUNET_EC_DBlock)) ||
+ (size - sizeof (GNUNET_EC_DBlock) != get_node_size (node)))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ return GNUNET_SYSERR; /* invalid size! */
+ }
+ size -= sizeof (GNUNET_EC_DBlock);
+ data = GNUNET_malloc (size);
+ if (GNUNET_SYSERR ==
+ decrypt_content ((const char *)
+ &((const GNUNET_EC_DBlock *) &reply[1])[1], size,
+ &node->chk.key, data))
+ GNUNET_GE_ASSERT (ectx, 0);
+ GNUNET_hash (data, size, &hc);
+ if (0 != memcmp (&hc, &node->chk.key, sizeof (GNUNET_HashCode)))
+ {
+ GNUNET_free (data);
+ GNUNET_GE_BREAK (ectx, 0);
+ signal_abort (rm,
+ _("Decrypted content does not match key. "
+ "This is either a bug or a maliciously inserted "
+ "file. Download aborted.\n"));
+ return GNUNET_SYSERR;
+ }
+ if (size != write_to_files (rm, node->level, node->offset, data, size))
+ {
+ GNUNET_GE_LOG_STRERROR (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
+ GNUNET_GE_USER | GNUNET_GE_BULK, "WRITE");
+ signal_abort (rm, _("IO error."));
+ return GNUNET_SYSERR;
+ }
+ notify_client_about_progress (node, data, size);
+ if (node->level > 0)
+ iblock_download_children (node, data, size);
+ GNUNET_free (data);
+ /* request satisfied, stop requesting! */
+ delete_node (node);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Helper function to sanitize filename
+ * and create necessary directories.
+ */
+static char *
+get_real_download_filename (struct GNUNET_GE_Context *ectx,
+ const char *filename)
+{
+ struct stat buf;
+ char *realFN;
+ char *path;
+ char *pos;
+
+ if ((filename[strlen (filename) - 1] == '/') ||
+ (filename[strlen (filename) - 1] == '\\'))
+ {
+ realFN =
+ GNUNET_malloc (strlen (filename) + strlen (GNUNET_DIRECTORY_EXT));
+ strcpy (realFN, filename);
+ realFN[strlen (filename) - 1] = '\0';
+ strcat (realFN, GNUNET_DIRECTORY_EXT);
+ }
+ else
+ {
+ realFN = GNUNET_strdup (filename);
+ }
+ path = GNUNET_malloc (strlen (realFN) * strlen (GNUNET_DIRECTORY_EXT) + 1);
+ strcpy (path, realFN);
+ pos = path;
+ while (*pos != '\0')
+ {
+ if (*pos == DIR_SEPARATOR)
+ {
+ *pos = '\0';
+ if ((0 == STAT (path, &buf)) && (!S_ISDIR (buf.st_mode)))
+ {
+ *pos = DIR_SEPARATOR;
+ memmove (pos + strlen (GNUNET_DIRECTORY_EXT),
+ pos, strlen (pos));
+ memcpy (pos,
+ GNUNET_DIRECTORY_EXT, strlen (GNUNET_DIRECTORY_EXT));
+ pos += strlen (GNUNET_DIRECTORY_EXT);
+ }
+ else
+ {
+ *pos = DIR_SEPARATOR;
+ }
+ }
+ pos++;
+ }
+ GNUNET_free (realFN);
+ return path;
+}
+
+/* ***************** main method **************** */
+
+
+/**
+ * Download parts of a file. Note that this will store
+ * the blocks at the respective offset in the given file.
+ * Also, the download is still using the blocking of the
+ * underlying ECRS encoding. As a result, the download
+ * may *write* outside of the given boundaries (if offset
+ * and length do not match the 32k ECRS block boundaries).
+ * <p>
+ *
+ * This function should be used to focus a download towards a
+ * particular portion of the file (optimization), not to strictly
+ * limit the download to exactly those bytes.
+ *
+ * @param uri the URI of the file (determines what to download)
+ * @param filename where to store the file
+ * @param no_temporaries set to GNUNET_YES to disallow generation of temporary
files
+ * @param start starting offset
+ * @param length length of the download (starting at offset)
+ */
+struct GNUNET_ECRS_DownloadContext *
+GNUNET_ECRS_file_download_partial_start (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ struct GNUNET_FS_SearchContext *sc,
+ const struct GNUNET_ECRS_URI *uri,
+ const char *filename,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int anonymityLevel,
+ int no_temporaries,
+ GNUNET_ECRS_DownloadProgressCallback
+ dpcb, void *dpcbClosure)
+{
+ struct GNUNET_ECRS_DownloadContext *rm;
+ struct stat buf;
+ struct Node *top;
+ int ret;
+
+ if ((!GNUNET_ECRS_uri_test_chk (uri)) && (!GNUNET_ECRS_uri_test_loc (uri)))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ return NULL;
+ }
+ rm = GNUNET_malloc (sizeof (struct GNUNET_ECRS_DownloadContext));
+ memset (rm, 0, sizeof (struct GNUNET_ECRS_DownloadContext));
+ if (sc == NULL)
+ {
+ rm->sctx = GNUNET_FS_create_search_context (ectx, cfg);
+ if (rm->sctx == NULL)
+ {
+ GNUNET_free (rm);
+ return NULL;
+ }
+ rm->my_sctx = GNUNET_YES;
+ }
+ else
+ {
+ rm->sctx = sc;
+ rm->my_sctx = GNUNET_NO;
+ }
+ rm->ectx = ectx;
+ rm->cfg = cfg;
+ rm->startTime = GNUNET_get_time ();
+ rm->anonymityLevel = anonymityLevel;
+ rm->offset = offset;
+ rm->length = length;
+ rm->dpcb = dpcb;
+ rm->dpcbClosure = dpcbClosure;
+ rm->main = GNUNET_thread_get_self ();
+ rm->total = GNUNET_ntohll (uri->data.fi.file_length);
+ rm->filename =
+ filename != NULL ? get_real_download_filename (ectx, filename) : NULL;
+
+ if ((rm->filename != NULL) &&
+ (GNUNET_SYSERR ==
+ GNUNET_disk_directory_create_for_file (ectx, rm->filename)))
+ {
+ free_request_manager (rm);
+ return NULL;
+ }
+ if (0 == rm->total)
+ {
+ if (rm->filename != NULL)
+ {
+ ret = GNUNET_disk_file_open (ectx,
+ rm->filename,
+ O_CREAT | O_WRONLY | O_TRUNC,
+ S_IRUSR | S_IWUSR);
+ if (ret == -1)
+ {
+ free_request_manager (rm);
+ return NULL;
+ }
+ CLOSE (ret);
+ }
+ dpcb (0, 0, rm->startTime, 0, NULL, 0, dpcbClosure);
+ free_request_manager (rm);
+ return NULL;
+ }
+ rm->treedepth = GNUNET_ECRS_compute_depth (rm->total);
+ if ((NULL != rm->filename) &&
+ ((0 == STAT (rm->filename, &buf))
+ && ((size_t) buf.st_size > rm->total)))
+ {
+ /* if exists and oversized, truncate */
+ if (truncate (rm->filename, rm->total) != 0)
+ {
+ GNUNET_GE_LOG_STRERROR_FILE (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
+ GNUNET_GE_BULK, "truncate",
+ rm->filename);
+ free_request_manager (rm);
+ return NULL;
+ }
+ }
+ if (rm->filename != NULL)
+ {
+ rm->handle = GNUNET_disk_file_open (ectx,
+ rm->filename,
+ O_CREAT | O_RDWR,
+ S_IRUSR | S_IWUSR);
+ if (rm->handle < 0)
+ {
+ free_request_manager (rm);
+ return NULL;
+ }
+ }
+ else
+ rm->handle = -1;
+ if (GNUNET_ECRS_uri_test_loc (uri))
+ {
+ GNUNET_hash (&uri->data.loc.peer, sizeof (GNUNET_RSA_PublicKey),
+ &rm->target.hashPubKey);
+ rm->have_target = GNUNET_YES;
+ }
+ top = GNUNET_malloc (sizeof (struct Node));
+ memset (top, 0, sizeof (struct Node));
+ top->ctx = rm;
+ top->chk = uri->data.fi.chk;
+ top->offset = 0;
+ top->level = rm->treedepth;
+ if (GNUNET_NO == check_node_present (top))
+ add_request (top);
+ else
+ GNUNET_free (top);
+ return rm;
+}
+
+int
+GNUNET_ECRS_file_download_partial_stop (struct GNUNET_ECRS_DownloadContext
+ *rm)
+{
+ int ret;
+
+ ret = rm->abortFlag;
+ free_request_manager (rm);
+ if (ret == GNUNET_NO)
+ ret = GNUNET_OK; /* normal termination */
+ return ret;
+}
+
+/**
+ * Download parts of a file. Note that this will store
+ * the blocks at the respective offset in the given file.
+ * Also, the download is still using the blocking of the
+ * underlying ECRS encoding. As a result, the download
+ * may *write* outside of the given boundaries (if offset
+ * and length do not match the 32k ECRS block boundaries).
+ * <p>
+ *
+ * This function should be used to focus a download towards a
+ * particular portion of the file (optimization), not to strictly
+ * limit the download to exactly those bytes.
+ *
+ * @param uri the URI of the file (determines what to download)
+ * @param filename where to store the file
+ * @param no_temporaries set to GNUNET_YES to disallow generation of temporary
files
+ * @param start starting offset
+ * @param length length of the download (starting at offset)
+ */
+int
+GNUNET_ECRS_file_download_partial (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const struct GNUNET_ECRS_URI *uri,
+ const char *filename,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int anonymityLevel,
+ int no_temporaries,
+ GNUNET_ECRS_DownloadProgressCallback dpcb,
+ void *dpcbClosure,
+ GNUNET_ECRS_TestTerminate tt,
+ void *ttClosure)
+{
+ struct GNUNET_ECRS_DownloadContext *rm;
+ int ret;
+
+ if (length == 0)
+ return GNUNET_OK;
+ rm = GNUNET_ECRS_file_download_partial_start (ectx,
+ cfg,
+ NULL,
+ uri,
+ filename,
+ offset,
+ length,
+ anonymityLevel,
+ no_temporaries,
+ dpcb, dpcbClosure);
+ if (rm == NULL)
+ return GNUNET_SYSERR;
+ while ((GNUNET_OK == tt (ttClosure)) &&
+ (GNUNET_YES != GNUNET_shutdown_test ()) &&
+ (rm->abortFlag == GNUNET_NO) && (rm->head != NULL))
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
+ ret = GNUNET_ECRS_file_download_partial_stop (rm);
+ return ret;
+}
+
+/**
+ * Download a file (simplified API).
+ *
+ * @param uri the URI of the file (determines what to download)
+ * @param filename where to store the file
+ */
+int
+GNUNET_ECRS_file_download (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const struct GNUNET_ECRS_URI *uri,
+ const char *filename,
+ unsigned int anonymityLevel,
+ GNUNET_ECRS_DownloadProgressCallback dpcb,
+ void *dpcbClosure, GNUNET_ECRS_TestTerminate tt,
+ void *ttClosure)
+{
+ return GNUNET_ECRS_file_download_partial (ectx,
+ cfg,
+ uri,
+ filename,
+ 0,
+ GNUNET_ECRS_uri_get_file_size
+ (uri), anonymityLevel, GNUNET_NO,
+ dpcb, dpcbClosure, tt, ttClosure);
+}
+
+/* end of download.c */
Added: gnunet/src/fs/fs_file_information.c
===================================================================
--- gnunet/src/fs/fs_file_information.c (rev 0)
+++ gnunet/src/fs/fs_file_information.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,269 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 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 fs/fs_file_information.c
+ * @brief Manage information for publishing directory hierarchies
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_fs_service.h"
+#include "fs.h"
+
+
+/**
+ * Create an entry for a file in a publish-structure.
+ *
+ * @param filename name of the file or directory to publish
+ * @param meta metadata for the file
+ * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
+ * GNUNET_SYSERR for simulation
+ * @param anonymity what is the desired anonymity level for sharing?
+ * @param priority what is the priority for OUR node to
+ * keep this file available? Use 0 for maximum anonymity and
+ * minimum reliability...
+ * @param expirationTime when should this content expire?
+ * @return publish structure entry for the file
+ */
+struct GNUNET_FS_FileInformation *
+GNUNET_FS_file_information_create_from_file (void *client_info,
+ const char *filename,
+ const struct
GNUNET_CONTAINER_MetaData *meta,
+ int do_index,
+ unsigned int anonymity,
+ unsigned int priority,
+ struct GNUNET_TIME_Absolute
expirationTime)
+{
+ return NULL;
+}
+
+/**
+ * Create an entry for a file in a publish-structure.
+ *
+ * @param length length of the file
+ * @param data data for the file (should not be used afterwards by
+ * the caller; caller will "free")
+ * @param meta metadata for the file
+ * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
+ * GNUNET_SYSERR for simulation
+ * @param anonymity what is the desired anonymity level for sharing?
+ * @param priority what is the priority for OUR node to
+ * keep this file available? Use 0 for maximum anonymity and
+ * minimum reliability...
+ * @param expirationTime when should this content expire?
+ * @return publish structure entry for the file
+ */
+struct GNUNET_FS_FileInformation *
+GNUNET_FS_file_information_create_from_data (void *client_info,
+ uint64_t length,
+ void *data,
+ const struct
GNUNET_CONTAINER_MetaData *meta,
+ int do_index,
+ unsigned int anonymity,
+ unsigned int priority,
+ struct GNUNET_TIME_Absolute
expirationTime)
+{
+ return NULL;
+}
+
+
+/**
+ * Create an entry for a file in a publish-structure.
+ *
+ * @param length length of the file
+ * @param reader function that can be used to obtain the data for the file
+ * @param reader_cls closure for "reader"
+ * @param keywords under which keywords should this file be available
+ * directly; can be NULL
+ * @param meta metadata for the file
+ * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
+ * GNUNET_SYSERR for simulation
+ * @param anonymity what is the desired anonymity level for sharing?
+ * @param priority what is the priority for OUR node to
+ * keep this file available? Use 0 for maximum anonymity and
+ * minimum reliability...
+ * @param expirationTime when should this content expire?
+ * @return publish structure entry for the file
+ */
+struct GNUNET_FS_FileInformation *
+GNUNET_FS_file_information_create_from_reader (void *client_info,
+ uint64_t length,
+ GNUNET_FS_DataReader reader,
+ void *reader_cls,
+ const struct GNUNET_FS_Uri
*keywords,
+ const struct
GNUNET_CONTAINER_MetaData *meta,
+ int do_index,
+ unsigned int anonymity,
+ unsigned int priority,
+ struct GNUNET_TIME_Absolute
expirationTime)
+{
+ return NULL;
+}
+
+
+
+/**
+ * Simple, useful default implementation of a directory scanner
+ * (GNUNET_FS_DirectoryScanner). This implementation expects to get a
+ * UNIX filename, will publish all files in the directory except hidden
+ * files (those starting with a "."). Metadata will be extracted
+ * using GNU libextractor; the specific list of plugins should be
+ * specified in "cls", passing NULL will disable (!) metadata
+ * extraction. Keywords will be derived from the metadata and be
+ * subject to default canonicalization. This is strictly a
+ * convenience function.
+ *
+ * @param cls must be of type "struct EXTRACTOR_Extractor*"
+ * @param dirname name of the directory to scan
+ * @param proc function called on each entry
+ * @param proc_cls closure for proc
+ * @param emsg where to store an error message (on errors)
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_FS_directory_scanner_default (void *cls,
+ const char *dirname,
+ GNUNET_FS_FileProcessor proc,
+ void *proc_cls)
+{
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Create a publish-structure from an existing file hierarchy, inferring
+ * and organizing keywords and metadata as much as possible. This
+ * function primarily performs the recursive build and re-organizes
+ * keywords and metadata; for automatically getting metadata
+ * extraction, scanning of directories and creation of the respective
+ * GNUNET_FS_FileInformation entries the default scanner should be
+ * passed (GNUNET_FS_directory_scanner_default). This is strictly a
+ * convenience function.
+ *
+ * @param filename name of the top-level file or directory
+ * @param scanner function used to get a list of files in a directory
+ * @param scanner_cls closure for scanner
+ * @param anonymity what is the desired anonymity level for sharing?
+ * @param priority what is the priority for OUR node to
+ * keep this file available? Use 0 for maximum anonymity and
+ * minimum reliability...
+ * @param expirationTime when should this content expire?
+ * @return publish structure entry for the directory, NULL on error
+ */
+struct GNUNET_FS_FileInformation *
+GNUNET_FS_file_information_create_from_directory (void *client_info,
+ GNUNET_FS_DirectoryScanner
scanner,
+ void *scanner_cls,
+ unsigned int anonymity,
+ unsigned int priority,
+ struct GNUNET_TIME_Absolute
expirationTime)
+{
+ return NULL;
+}
+
+
+/**
+ * Create an entry for an empty directory in a publish-structure.
+ * This function should be used by applications for which the
+ * use of "GNUNET_FS_file_information_create_from_directory"
+ * is not appropriate.
+ *
+ * @param meta metadata for the directory
+ * @param keywords under which keywords should this directory be available
+ * directly; can be NULL
+ * @param anonymity what is the desired anonymity level for sharing?
+ * @param priority what is the priority for OUR node to
+ * keep this file available? Use 0 for maximum anonymity and
+ * minimum reliability...
+ * @param expirationTime when should this content expire?
+ * @return publish structure entry for the directory , NULL on error
+ */
+struct GNUNET_FS_FileInformation *
+GNUNET_FS_file_information_create_empty_directory (void *client_info,
+ const struct
GNUNET_CONTAINER_MetaData *meta,
+ const struct GNUNET_FS_Uri
*keywords,
+ unsigned int anonymity,
+ unsigned int priority,
+ struct GNUNET_TIME_Absolute
expirationTime)
+{
+ return NULL;
+}
+
+
+/**
+ * Add an entry to a directory in a publish-structure. Clients
+ * should never modify publish structures that were passed to
+ * "GNUNET_FS_publish_start" already.
+ *
+ * @param dir the directory
+ * @param end the entry to add; the entry must not have been
+ * added to any other directory at this point and
+ * must not include "dir" in its structure
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir,
+ struct GNUNET_FS_FileInformation *end)
+{
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Inspect a file or directory in a publish-structure. Clients
+ * should never modify publish structures that were passed to
+ * "GNUNET_FS_publish_start" already. When called on a directory,
+ * this function will FIRST call "proc" with information about
+ * the directory itself and then for each of the files in the
+ * directory (but not for files in subdirectories). When called
+ * on a file, "proc" will be called exactly once (with information
+ * about the specific file).
+ *
+ * @param dir the directory
+ * @param proc function to call on each entry
+ * @param proc_cls closure for proc
+ */
+void
+GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir,
+ GNUNET_FS_FileInformationProcessor proc,
+ void *proc_cls)
+{
+}
+
+
+/**
+ * Destroy publish-structure. Clients should never destroy publish
+ * structures that were passed to "GNUNET_FS_publish_start" already.
+ *
+ * @param fi structure to destroy
+ * @param cleaner function to call on each entry in the structure
+ * (useful to clean up client_info); can be NULL; return
+ * values are ignored
+ * @param cleaner_cls closure for cleaner
+ */
+void
+GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi,
+ GNUNET_FS_FileInformationProcessor cleaner,
+ void *cleaner_cls)
+{
+}
+
+
+/* end of fs_file_information.c */
Added: gnunet/src/fs/fs_namespace.c
===================================================================
--- gnunet/src/fs/fs_namespace.c (rev 0)
+++ gnunet/src/fs/fs_namespace.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,729 @@
+/*
+ This file is part of GNUnet
+ (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 fs/fs_namespace.c
+ * @brief create and destroy namespaces
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_fs_service.h"
+
+
+/**
+ * Publish an advertismement for a namespace.
+ *
+ * @param h handle to the file sharing subsystem
+ * @param namespace handle for the namespace that should be advertised
+ * @param meta meta-data for the namespace advertisement
+ * @param anonymity for the namespace advertismement
+ * @param priority for the namespace advertisement
+ * @param expiration for the namespace advertisement
+ * @param advertisementURI the keyword (!) URI to advertise the
+ * namespace under (we will create a GNUNET_EC_KNBlock)
+ * @param rootEntry name of the root entry in the namespace (for
+ * the namespace advertisement)
+ *
+ * @return uri of the advertisement
+ */
+struct GNUNET_FS_Uri *
+GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
+ struct GNUNET_FS_Namespace *namespace,
+ const struct GNUNET_MetaData *meta,
+ unsigned int anonymity,
+ unsigned int priority,
+ struct GNUNET_TIME_Absolute expiration,
+ const struct GNUNET_FS_Uri *advertisementURI,
+ const char *rootEntry)
+{
+ return NULL;
+}
+
+
+/**
+ * Create a namespace with the given name; if one already
+ * exists, return a handle to the existing namespace.
+ *
+ * @param h handle to the file sharing subsystem
+ * @param name name to use for the namespace
+ * @return handle to the namespace, NULL on error
+ */
+struct GNUNET_FS_Namespace *
+GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h,
+ const char *name)
+{
+ return NULL;
+}
+
+
+/**
+ * Delete a namespace handle. Can be used for a clean shutdown (free
+ * memory) or also to freeze the namespace to prevent further
+ * insertions by anyone.
+ *
+ * @param namespace handle to the namespace that should be deleted / freed
+ * @param freeze prevents future insertions; creating a namespace
+ * with the same name again will create a fresh namespace instead
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace,
+ int freeze)
+{
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Build a list of all available local (!) namespaces The returned
+ * names are only the nicknames since we only iterate over the local
+ * namespaces.
+ *
+ * @param h handle to the file sharing subsystem
+ * @param cb function to call on each known namespace
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
+ GNUNET_FS_NamespaceInfoProcessor cb,
+ void *cb_cls)
+{
+}
+
+/* end of fs_namespace.c */
+
+#if 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 applications/fs/ecrs/namespace.c
+ * @brief creation, deletion and advertising of namespaces
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_directories.h"
+#include "gnunet_protocols.h"
+#include "gnunet_ecrs_lib.h"
+#include "gnunet_fs_lib.h"
+#include "ecrs_core.h"
+#include "ecrs.h"
+
+#define PSEUDODIR "data/namespace/keys/"
+#define INITVALUE "GNUnet!!"
+#define MAX_SBLOCK_SIZE 32000
+
+static char *
+getPseudonymFileName (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const GNUNET_HashCode * pid)
+{
+ char *gnHome;
+ char *fileName;
+ GNUNET_EncName enc;
+
+ GNUNET_GC_get_configuration_value_filename (cfg,
+ "GNUNET",
+ "GNUNET_HOME",
+ GNUNET_DEFAULT_HOME_DIRECTORY,
+ &fileName);
+ gnHome = GNUNET_expand_file_name (ectx, fileName);
+ GNUNET_free (fileName);
+ fileName =
+ GNUNET_malloc (strlen (gnHome) + strlen (PSEUDODIR) +
+ sizeof (GNUNET_EncName) + 2);
+ strcpy (fileName, gnHome);
+ GNUNET_free (gnHome);
+ strcat (fileName, DIR_SEPARATOR_STR);
+ strcat (fileName, PSEUDODIR);
+ GNUNET_disk_directory_create (ectx, fileName);
+ if (pid != NULL)
+ {
+ GNUNET_hash_to_enc (pid, &enc);
+ strcat (fileName, (char *) &enc);
+ }
+ return fileName;
+}
+
+
+/**
+ * Check if the given namespace exists (locally).
+ *
+ * @return GNUNET_OK if the namespace exists, GNUNET_SYSERR if not
+ */
+int
+GNUNET_ECRS_namespace_test_exists (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const GNUNET_HashCode * pid)
+{
+ char *fileName;
+ int ret;
+
+ fileName = getPseudonymFileName (ectx, cfg, pid);
+ ret = GNUNET_disk_file_test (ectx, fileName);
+ GNUNET_free (fileName);
+ return ret;
+}
+
+/**
+ * Delete a local namespace.
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_ECRS_namespace_delete (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const GNUNET_HashCode * pid)
+{
+ char *fileName;
+
+ fileName = getPseudonymFileName (ectx, cfg, pid);
+ if (GNUNET_YES != GNUNET_disk_file_test (ectx, fileName))
+ {
+ GNUNET_free (fileName);
+ return GNUNET_SYSERR; /* no such namespace */
+ }
+ if (0 != UNLINK (fileName))
+ {
+ GNUNET_GE_LOG_STRERROR_FILE (ectx,
+ GNUNET_GE_WARNING | GNUNET_GE_USER |
+ GNUNET_GE_BULK, "unlink", fileName);
+ GNUNET_free (fileName);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (fileName);
+ return GNUNET_OK;
+}
+
+/**
+ * Write the private key of the namespace to a file.
+ */
+static int
+write_namespace_key (struct GNUNET_GC_Configuration *cfg,
+ const struct GNUNET_RSA_PrivateKey *key)
+{
+ GNUNET_RSA_PrivateKeyEncoded *namespace_priv_key_encoded;
+ char *fileName;
+ GNUNET_RSA_PublicKey pubk;
+ GNUNET_HashCode pid;
+
+ GNUNET_RSA_get_public_key (key, &pubk);
+ GNUNET_hash (&pubk, sizeof (GNUNET_RSA_PublicKey), &pid);
+ fileName = getPseudonymFileName (NULL, cfg, &pid);
+ if (GNUNET_YES == GNUNET_disk_file_test (NULL, fileName))
+ {
+ GNUNET_GE_BREAK (NULL, 0); /* hash collision!? */
+ GNUNET_free (fileName);
+ return GNUNET_SYSERR;
+ }
+ namespace_priv_key_encoded = GNUNET_RSA_encode_key (key);
+ GNUNET_disk_file_write (NULL, fileName,
+ (const char *) namespace_priv_key_encoded,
+ ntohs (namespace_priv_key_encoded->len), "600");
+ GNUNET_free (fileName);
+ GNUNET_free (namespace_priv_key_encoded);
+ return GNUNET_OK;
+}
+
+/**
+ * Create a new namespace (and publish an advertismement).
+ * This publishes both an GNUNET_EC_NBlock in the namespace itself
+ * as well as KNBlocks under all keywords specified in
+ * the advertisementURI.
+ *
+ * @param anonymity_level for the namespace advertismement
+ * @param priority for the namespace advertisement
+ * @param expiration for the namespace advertisement
+ * @param advertisementURI the keyword (!) URI to advertise the
+ * namespace under (GNUNET_EC_KNBlock)
+ * @param meta meta-data for the namespace advertisement
+ * (will be used to derive a name)
+ * @param rootEntry name of the root entry in the namespace (for
+ * the namespace advertisement)
+ * @param rootURI set to the URI of the namespace, NULL if
+ * no advertisement was created
+ *
+ * @return URI on success, NULL on error
+ */
+struct GNUNET_ECRS_URI *
+GNUNET_ECRS_namespace_create (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const struct GNUNET_MetaData *meta,
+ unsigned int anonymityLevel,
+ unsigned int priority,
+ GNUNET_CronTime expiration,
+ const struct GNUNET_ECRS_URI *advertisementURI,
+ const char *rootEntry)
+{
+ struct GNUNET_ECRS_URI *rootURI;
+ struct GNUNET_RSA_PrivateKey *namespace_priv_key;
+ GNUNET_HashCode hc;
+ struct GNUNET_ClientServerConnection *sock;
+ GNUNET_DatastoreValue *value;
+ GNUNET_DatastoreValue *knvalue;
+ unsigned int size;
+ unsigned int mdsize;
+ struct GNUNET_RSA_PrivateKey *pk;
+ GNUNET_EC_SBlock *sb;
+ GNUNET_EC_KSBlock *ksb;
+ char **keywords;
+ const char *keyword;
+ unsigned int keywordCount;
+ int i;
+ char *cpy;
+ char *rtgt;
+
+ if ((advertisementURI != NULL)
+ && (!GNUNET_ECRS_uri_test_ksk (advertisementURI)))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ return NULL;
+ }
+ namespace_priv_key = GNUNET_RSA_create_key ();
+ if (GNUNET_OK != write_namespace_key (cfg, namespace_priv_key))
+ {
+ GNUNET_RSA_free_key (namespace_priv_key);
+ return NULL;
+ }
+
+ /* create advertisements */
+ mdsize = GNUNET_meta_data_get_serialized_size (meta, GNUNET_SERIALIZE_PART);
+ size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
+ if (size > MAX_SBLOCK_SIZE)
+ {
+ size = MAX_SBLOCK_SIZE;
+ mdsize = size - sizeof (GNUNET_EC_SBlock) - strlen (rootEntry) - 2;
+ }
+ value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
+ memset (value, 0, sizeof (GNUNET_DatastoreValue) + size);
+ sb = (GNUNET_EC_SBlock *) & value[1];
+ sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
+ GNUNET_RSA_get_public_key (namespace_priv_key, &sb->subspace);
+ rtgt = (char *) &sb[1];
+ memcpy (rtgt, rootEntry, strlen (rootEntry) + 1);
+ mdsize = GNUNET_meta_data_serialize (ectx,
+ meta,
+ &rtgt[strlen (rootEntry) + 2],
+ mdsize, GNUNET_SERIALIZE_PART);
+ if (mdsize == -1)
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ GNUNET_RSA_free_key (namespace_priv_key);
+ GNUNET_free (value);
+ return NULL;
+ }
+ size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
+ GNUNET_GE_ASSERT (ectx,
+ GNUNET_OK == GNUNET_RSA_sign (namespace_priv_key,
+ size
+ -
+ sizeof
+ (GNUNET_RSA_Signature) -
+ sizeof
+ (GNUNET_RSA_PublicKey) -
+ sizeof (unsigned int),
+ &sb->identifier,
+ &sb->signature));
+ value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
+ value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
+ value->priority = htonl (priority);
+ value->anonymity_level = htonl (anonymityLevel);
+ value->expiration_time = GNUNET_htonll (expiration);
+ sock = GNUNET_client_connection_create (ectx, cfg);
+ if (sock == NULL)
+ {
+ GNUNET_free (value);
+ GNUNET_RSA_free_key (namespace_priv_key);
+ return NULL;
+ }
+ if (GNUNET_OK != GNUNET_FS_insert (sock, value))
+ {
+ GNUNET_free (value);
+ GNUNET_client_connection_destroy (sock);
+ GNUNET_RSA_free_key (namespace_priv_key);
+ return NULL;
+ }
+
+
+ /* publish KNBlocks */
+ size += sizeof (GNUNET_EC_KSBlock) - sizeof (GNUNET_EC_SBlock);
+ knvalue = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
+ *knvalue = *value;
+ knvalue->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
+ knvalue->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
+ ksb = (GNUNET_EC_KSBlock *) & knvalue[1];
+ ksb->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
+ memcpy (&ksb->sblock,
+ sb, sizeof (GNUNET_EC_SBlock) + mdsize + strlen (rootEntry) + 2);
+
+ if (advertisementURI != NULL)
+ {
+ keywords = advertisementURI->data.ksk.keywords;
+ keywordCount = advertisementURI->data.ksk.keywordCount;
+ cpy =
+ GNUNET_malloc (size - sizeof (GNUNET_EC_KBlock) -
+ sizeof (unsigned int));
+ memcpy (cpy,
+ &ksb->sblock,
+ size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
+ for (i = 0; i < keywordCount; i++)
+ {
+ keyword = keywords[i];
+ /* first character of keyword indicates
+ mandatory or not -- ignore for hashing! */
+ GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc);
+ pk = GNUNET_RSA_create_key_from_hash (&hc);
+ GNUNET_RSA_get_public_key (pk, &ksb->kblock.keyspace);
+ GNUNET_GE_ASSERT (ectx,
+ size - sizeof (GNUNET_EC_KBlock) -
+ sizeof (unsigned int) ==
+ sizeof (GNUNET_EC_SBlock) + mdsize +
+ strlen (rootEntry) + 2);
+ GNUNET_ECRS_encryptInPlace (&hc, &ksb->sblock,
+ size - sizeof (GNUNET_EC_KBlock) -
+ sizeof (unsigned int));
+
+ GNUNET_GE_ASSERT (ectx,
+ GNUNET_OK == GNUNET_RSA_sign (pk,
+ size -
+ sizeof
+ (GNUNET_EC_KBlock) -
+ sizeof (unsigned
+ int),
+ &ksb->sblock,
+ &ksb->
+ kblock.signature));
+ /* extra check: verify sig */
+ GNUNET_RSA_free_key (pk);
+ if (GNUNET_OK != GNUNET_FS_insert (sock, knvalue))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ GNUNET_free (cpy);
+ GNUNET_free (knvalue);
+ GNUNET_free (value);
+ GNUNET_client_connection_destroy (sock);
+ GNUNET_RSA_free_key (namespace_priv_key);
+ return NULL;
+ }
+ /* restore nblock to avoid re-encryption! */
+ memcpy (&ksb->sblock,
+ cpy,
+ size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
+ }
+ GNUNET_free (cpy);
+ }
+ rootURI = GNUNET_malloc (sizeof (URI));
+ rootURI->type = sks;
+ GNUNET_hash (&sb->subspace,
+ sizeof (GNUNET_RSA_PublicKey), &rootURI->data.sks.namespace);
+ rootURI->data.sks.identifier = GNUNET_strdup (rootEntry);
+ GNUNET_free (knvalue);
+ GNUNET_free (value);
+ GNUNET_client_connection_destroy (sock);
+ GNUNET_RSA_free_key (namespace_priv_key);
+
+ return rootURI;
+}
+
+static struct GNUNET_RSA_PrivateKey *
+read_namespace_key (struct GNUNET_GC_Configuration *cfg,
+ const GNUNET_HashCode * pid)
+{
+ char *fileName;
+ GNUNET_RSA_PrivateKeyEncoded *hke;
+ struct GNUNET_RSA_PrivateKey *hk;
+ char *dst;
+ unsigned long long len;
+
+ fileName = getPseudonymFileName (NULL, cfg, pid);
+ if (GNUNET_OK != GNUNET_disk_file_size (NULL, fileName, &len, GNUNET_YES))
+ {
+ GNUNET_free (fileName);
+ return NULL;
+ }
+ if (len < 2)
+ {
+ GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("File `%s' does not contain a pseudonym.\n"),
+ fileName);
+ GNUNET_free (fileName);
+ return NULL;
+ }
+ dst = GNUNET_malloc (len);
+ len = GNUNET_disk_file_read (NULL, fileName, len, dst);
+ hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
+ if (ntohs (hke->len) != len)
+ {
+ GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Format of pseudonym `%s' is invalid.\n"), fileName);
+ GNUNET_free (fileName);
+ GNUNET_free (hke);
+ return NULL;
+ }
+ GNUNET_free (fileName);
+ hk = GNUNET_RSA_decode_key (hke);
+ GNUNET_free (hke);
+ return hk;
+}
+
+
+/**
+ * Add an entry into a namespace.
+ *
+ * @param dstU to which URI should the namespace entry refer?
+ * @param md what meta-data should be associated with the
+ * entry?
+ * @param thisId name of this entry in the namespace (keyword/identifier)
+ * @param nextId name of the update for this entry (to be published in
+ * the future; maybe NULL)
+ * @param pid unique identifier of the namespace/pseudonym
+ * @return URI on success, NULL on error
+ */
+struct GNUNET_ECRS_URI *
+GNUNET_ECRS_namespace_add_content (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const GNUNET_HashCode * pid,
+ unsigned int anonymityLevel,
+ unsigned int priority,
+ GNUNET_CronTime expiration,
+ const char *thisId,
+ const char *nextId,
+ const struct GNUNET_ECRS_URI *dstU,
+ const struct GNUNET_MetaData *md)
+{
+ struct GNUNET_ECRS_URI *uri;
+ struct GNUNET_ClientServerConnection *sock;
+ GNUNET_DatastoreValue *value;
+ unsigned int size;
+ unsigned int mdsize;
+ struct GNUNET_RSA_PrivateKey *hk;
+ GNUNET_EC_SBlock *sb;
+ char *dstURI;
+ char *destPos;
+ GNUNET_HashCode hc; /* hash of thisId = key */
+ GNUNET_HashCode hc2; /* hash of hc = identifier */
+ int ret;
+ unsigned int nidlen;
+
+ hk = read_namespace_key (cfg, pid);
+ if (hk == NULL)
+ return NULL;
+
+ /* THEN: construct GNUNET_EC_SBlock */
+ dstURI = GNUNET_ECRS_uri_to_string (dstU);
+ mdsize = GNUNET_meta_data_get_serialized_size (md, GNUNET_SERIALIZE_PART);
+ if (nextId == NULL)
+ nextId = "";
+ nidlen = strlen (nextId) + 1;
+ size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen;
+ if (size > MAX_SBLOCK_SIZE)
+ {
+ size = MAX_SBLOCK_SIZE;
+ mdsize =
+ size - (sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen);
+ }
+ value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
+ sb = (GNUNET_EC_SBlock *) & value[1];
+ sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
+ destPos = (char *) &sb[1];
+ memcpy (destPos, nextId, nidlen);
+ destPos += nidlen;
+ memcpy (destPos, dstURI, strlen (dstURI) + 1);
+ destPos += strlen (dstURI) + 1;
+ mdsize = GNUNET_meta_data_serialize (ectx,
+ md,
+ destPos,
+ mdsize, GNUNET_SERIALIZE_PART);
+ if (mdsize == -1)
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ GNUNET_free (dstURI);
+ GNUNET_RSA_free_key (hk);
+ GNUNET_free (value);
+ return NULL;
+ }
+ size = sizeof (GNUNET_EC_SBlock) + mdsize + strlen (dstURI) + 1 + nidlen;
+ value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
+ value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
+ value->priority = htonl (priority);
+ value->anonymity_level = htonl (anonymityLevel);
+ value->expiration_time = GNUNET_htonll (expiration);
+ GNUNET_hash (thisId, strlen (thisId), &hc);
+ GNUNET_hash (&hc, sizeof (GNUNET_HashCode), &hc2);
+ uri = GNUNET_malloc (sizeof (URI));
+ uri->type = sks;
+ GNUNET_RSA_get_public_key (hk, &sb->subspace);
+ GNUNET_hash (&sb->subspace,
+ sizeof (GNUNET_RSA_PublicKey), &uri->data.sks.namespace);
+ GNUNET_GE_BREAK (ectx, 0 == memcmp (&uri->data.sks.namespace,
+ pid, sizeof (GNUNET_HashCode)));
+ uri->data.sks.identifier = GNUNET_strdup (thisId);
+ GNUNET_hash_xor (&hc2, &uri->data.sks.namespace, &sb->identifier);
+ GNUNET_ECRS_encryptInPlace (&hc, &sb[1], size - sizeof (GNUNET_EC_SBlock));
+ GNUNET_GE_ASSERT (ectx,
+ GNUNET_OK == GNUNET_RSA_sign (hk,
+ size
+ -
+ sizeof
+ (GNUNET_RSA_Signature) -
+ sizeof
+ (GNUNET_RSA_PublicKey) -
+ sizeof (unsigned int),
+ &sb->identifier,
+ &sb->signature));
+ GNUNET_RSA_free_key (hk);
+ sock = GNUNET_client_connection_create (ectx, cfg);
+ ret = GNUNET_FS_insert (sock, value);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_free (uri);
+ uri = NULL;
+ }
+ GNUNET_client_connection_destroy (sock);
+ GNUNET_free (value);
+ GNUNET_free (dstURI);
+
+ return uri;
+}
+
+struct lNCLS
+{
+ struct GNUNET_GE_Context *ectx;
+ struct GNUNET_GC_Configuration *cfg;
+ GNUNET_ECRS_NamespaceInfoProcessor cb;
+ void *cls;
+ int cnt;
+};
+
+static int
+processFile_ (void *cls, const char *fileName)
+{
+ struct lNCLS *c = cls;
+ struct GNUNET_RSA_PrivateKey *hk;
+ GNUNET_RSA_PrivateKeyEncoded *hke;
+ char *dst;
+ unsigned long long len;
+ GNUNET_HashCode namespace;
+ GNUNET_RSA_PublicKey pk;
+ const char *name;
+
+ if (GNUNET_OK !=
+ GNUNET_disk_file_size (c->ectx, fileName, &len, GNUNET_YES))
+ return GNUNET_OK;
+ if (len < 2)
+ {
+ GNUNET_GE_LOG (c->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Format of file `%s' is invalid, trying to remove.\n"),
+ fileName);
+ UNLINK (fileName);
+ return GNUNET_OK;
+ }
+ dst = GNUNET_malloc (len);
+ len = GNUNET_disk_file_read (c->ectx, fileName, len, dst);
+ hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
+ if (ntohs (hke->len) != len)
+ {
+ GNUNET_GE_LOG (c->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Format of file `%s' is invalid, trying to remove.\n"),
+ fileName);
+ UNLINK (fileName);
+ GNUNET_free (hke);
+ return GNUNET_OK;
+ }
+ hk = GNUNET_RSA_decode_key (hke);
+ GNUNET_free (hke);
+ if (hk == NULL)
+ {
+ GNUNET_GE_LOG (c->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Format of file `%s' is invalid, trying to remove.\n"),
+ fileName);
+ UNLINK (fileName);
+ GNUNET_GE_BREAK (c->ectx, 0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_RSA_get_public_key (hk, &pk);
+ GNUNET_RSA_free_key (hk);
+ GNUNET_hash (&pk, sizeof (GNUNET_RSA_PublicKey), &namespace);
+ if (NULL != c->cb)
+ {
+ name = fileName;
+ while (NULL != strstr (name, DIR_SEPARATOR_STR))
+ name = 1 + strstr (name, DIR_SEPARATOR_STR);
+ if (GNUNET_OK == c->cb (&namespace, name, c->cls))
+ c->cnt++;
+ else
+ c->cnt = GNUNET_SYSERR;
+ }
+ else
+ c->cnt++;
+ return GNUNET_OK;
+}
+
+/**
+ * Build a list of all available namespaces
+ *
+ * @param list where to store the names (is allocated, caller frees)
+ * @return GNUNET_SYSERR on error, otherwise the number of pseudonyms in list
+ */
+int
+GNUNET_ECRS_get_namespaces (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ GNUNET_ECRS_NamespaceInfoProcessor cb, void *cls)
+{
+ char *dirName;
+ struct lNCLS myCLS;
+
+ myCLS.cls = cls;
+ myCLS.cb = cb;
+ myCLS.cnt = 0;
+ myCLS.ectx = ectx;
+ myCLS.cfg = cfg;
+ dirName = getPseudonymFileName (ectx, cfg, NULL);
+ GNUNET_disk_directory_scan (ectx, dirName, &processFile_, &myCLS);
+ GNUNET_free (dirName);
+ return myCLS.cnt;
+}
+
+
+
+/* end of namespace.c */
+#endif
Added: gnunet/src/fs/fs_publish.c
===================================================================
--- gnunet/src/fs/fs_publish.c (rev 0)
+++ gnunet/src/fs/fs_publish.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,459 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 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 fs/fs_publish.c
+ * @brief publish a file or directory in GNUnet
+ * @see http://gnunet.org/encoding.php3
+ * @author Krista Bennett
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_fs_service.h"
+#include "fs.h"
+
+#define DEBUG_PUBLISH GNUNET_YES
+
+
+
+#if 0
+
+/**
+ * Append the given key and query to the iblock[level]. If
+ * iblock[level] is already full, compute its chk and push it to
+ * level+1 and clear the level. iblocks is guaranteed to be big
+ * enough.
+ */
+static int
+pushBlock (struct GNUNET_ClientServerConnection *sock,
+ const GNUNET_EC_ContentHashKey * chk,
+ unsigned int level,
+ GNUNET_DatastoreValue ** iblocks,
+ unsigned int prio, GNUNET_CronTime expirationTime)
+{
+ unsigned int size;
+ unsigned int present;
+ GNUNET_DatastoreValue *value;
+ GNUNET_EC_DBlock *db;
+ GNUNET_EC_ContentHashKey ichk;
+
+ size = ntohl (iblocks[level]->size);
+ GNUNET_GE_ASSERT (NULL, size > sizeof (GNUNET_DatastoreValue));
+ size -= sizeof (GNUNET_DatastoreValue);
+ GNUNET_GE_ASSERT (NULL,
+ size - sizeof (GNUNET_EC_DBlock) <=
+ GNUNET_ECRS_IBLOCK_SIZE);
+ present =
+ (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);
+ db = (GNUNET_EC_DBlock *) & iblocks[level][1];
+ if (present == GNUNET_ECRS_CHK_PER_INODE)
+ {
+ GNUNET_EC_file_block_get_key (db, size, &ichk.key);
+ GNUNET_EC_file_block_get_query (db, size, &ichk.query);
+ if (GNUNET_OK != pushBlock (sock,
+ &ichk, level + 1, iblocks, prio,
+ expirationTime))
+ return GNUNET_SYSERR;
+ GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);
+ if (value == NULL)
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ return GNUNET_SYSERR;
+ }
+ value->priority = htonl (prio);
+ value->expiration_time = GNUNET_htonll (expirationTime);
+ if (GNUNET_OK != GNUNET_FS_insert (sock, value))
+ {
+ GNUNET_free (value);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (value);
+ size = sizeof (GNUNET_EC_DBlock); /* type */
+ }
+ /* append GNUNET_EC_ContentHashKey */
+ memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));
+ size += sizeof (GNUNET_EC_ContentHashKey) + sizeof (GNUNET_DatastoreValue);
+ GNUNET_GE_ASSERT (NULL, size < GNUNET_MAX_BUFFER_SIZE);
+ iblocks[level]->size = htonl (size);
+
+ return GNUNET_OK;
+}
+
+/**
+ * Index or insert a file.
+ *
+ * @param priority what is the priority for OUR node to
+ * keep this file available? Use 0 for maximum anonymity and
+ * minimum reliability...
+ * @param doIndex GNUNET_YES for index, GNUNET_NO for insertion,
+ * GNUNET_SYSERR for simulation
+ * @param uri set to the URI of the uploaded file
+ * @return GNUNET_SYSERR if the upload failed (i.e. not enough space
+ * or gnunetd not running)
+ */
+int
+GNUNET_ECRS_file_upload (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const char *filename,
+ int doIndex,
+ unsigned int anonymityLevel,
+ unsigned int priority,
+ GNUNET_CronTime expirationTime,
+ GNUNET_ECRS_UploadProgressCallback upcb,
+ void *upcbClosure,
+ GNUNET_ECRS_TestTerminate tt,
+ void *ttClosure, struct GNUNET_ECRS_URI **uri)
+{
+ unsigned long long filesize;
+ unsigned long long pos;
+ unsigned int treedepth;
+ int fd;
+ int i;
+ int ret;
+ unsigned int size;
+ GNUNET_DatastoreValue **iblocks;
+ GNUNET_DatastoreValue *dblock;
+ GNUNET_EC_DBlock *db;
+ GNUNET_DatastoreValue *value;
+ struct GNUNET_ClientServerConnection *sock;
+ GNUNET_HashCode fileId;
+ GNUNET_EC_ContentHashKey mchk;
+ GNUNET_CronTime eta;
+ GNUNET_CronTime start;
+ GNUNET_CronTime now;
+ GNUNET_EC_FileIdentifier fid;
+#if DEBUG_UPLOAD
+ GNUNET_EncName enc;
+#endif
+
+ GNUNET_GE_ASSERT (ectx, cfg != NULL);
+ start = GNUNET_get_time ();
+ memset (&mchk, 0, sizeof (GNUNET_EC_ContentHashKey));
+ if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))
+ {
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' is not a file.\n"), filename);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))
+ {
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Cannot get size of file `%s'"), filename);
+
+ return GNUNET_SYSERR;
+ }
+ sock = GNUNET_client_connection_create (ectx, cfg);
+ if (sock == NULL)
+ {
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Failed to connect to gnunetd."));
+ return GNUNET_SYSERR;
+ }
+ eta = 0;
+ if (upcb != NULL)
+ upcb (filesize, 0, eta, upcbClosure);
+ if (doIndex == GNUNET_YES)
+ {
+ if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))
+ {
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Cannot hash `%s'.\n"), filename);
+
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_YES == GNUNET_FS_test_indexed (sock, &fileId))
+ {
+ /* file already indexed; simulate only to get the URI! */
+ doIndex = GNUNET_SYSERR;
+ }
+ }
+ if (doIndex == GNUNET_YES)
+ {
+ now = GNUNET_get_time ();
+ eta = now + 2 * (now - start);
+ /* very rough estimate: GNUNET_hash reads once through the file,
+ we'll do that once more and write it. But of course
+ the second read may be cached, and we have the encryption,
+ so a factor of two is really, really just a rough estimate */
+ start = now;
+ /* reset the counter since the formula later does not
+ take the time for GNUNET_hash_file into account */
+
+ switch (GNUNET_FS_prepare_to_index (sock, &fileId, filename))
+ {
+ case GNUNET_SYSERR:
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Initialization for indexing file `%s' failed.\n"),
+ filename);
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+ case GNUNET_NO:
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _
+ ("Indexing file `%s' failed. Suggestion: try to
insert the file.\n"),
+ filename);
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+ default:
+ break;
+ }
+ }
+ treedepth = GNUNET_ECRS_compute_depth (filesize);
+ fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);
+ if (fd == -1)
+ {
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("Cannot open file `%s': `%s'"), filename,
+ STRERROR (errno));
+
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+ }
+
+ dblock =
+ GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
+ sizeof (GNUNET_EC_DBlock));
+ dblock->size =
+ htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
+ sizeof (GNUNET_EC_DBlock));
+ dblock->anonymity_level = htonl (anonymityLevel);
+ dblock->priority = htonl (priority);
+ dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ dblock->expiration_time = GNUNET_htonll (expirationTime);
+ db = (GNUNET_EC_DBlock *) & dblock[1];
+ db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ iblocks =
+ GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));
+ for (i = 0; i <= treedepth; i++)
+ {
+ iblocks[i] =
+ GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
+ GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));
+ iblocks[i]->size =
+ htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));
+ iblocks[i]->anonymity_level = htonl (anonymityLevel);
+ iblocks[i]->priority = htonl (priority);
+ iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ iblocks[i]->expiration_time = GNUNET_htonll (expirationTime);
+ ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =
+ htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ }
+
+ pos = 0;
+ while (pos < filesize)
+ {
+ if (upcb != NULL)
+ upcb (filesize, pos, eta, upcbClosure);
+ if (tt != NULL)
+ if (GNUNET_OK != tt (ttClosure))
+ goto FAILURE;
+ size = GNUNET_ECRS_DBLOCK_SIZE;
+ if (size > filesize - pos)
+ {
+ size = filesize - pos;
+ memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);
+ }
+ GNUNET_GE_ASSERT (ectx,
+ sizeof (GNUNET_DatastoreValue) + size +
+ sizeof (GNUNET_EC_DBlock) < GNUNET_MAX_BUFFER_SIZE);
+ dblock->size =
+ htonl (sizeof (GNUNET_DatastoreValue) + size +
+ sizeof (GNUNET_EC_DBlock));
+ if (size != READ (fd, &db[1], size))
+ {
+ GNUNET_GE_LOG_STRERROR_FILE (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK |
+ GNUNET_GE_ADMIN | GNUNET_GE_USER,
+ "READ", filename);
+ goto FAILURE;
+ }
+ if (tt != NULL)
+ if (GNUNET_OK != tt (ttClosure))
+ goto FAILURE;
+ GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),
+ &mchk.key);
+ GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),
+ &mchk.query);
+#if DEBUG_UPLOAD
+ GNUNET_hash_to_enc (&mchk.query, &enc);
+ fprintf (stderr,
+ "Query for current block of size %u is `%s'\n", size,
+ (const char *) &enc);
+#endif
+ if (doIndex == GNUNET_YES)
+ {
+ if (GNUNET_SYSERR == GNUNET_FS_index (sock, &fileId, dblock, pos))
+ {
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK |
+ GNUNET_GE_USER,
+ _
+ ("Indexing data of file `%s' failed at position
%llu.\n"),
+ filename, pos);
+ goto FAILURE;
+ }
+ }
+ else
+ {
+ value = NULL;
+ if (GNUNET_OK !=
+ GNUNET_EC_file_block_encode (db,
+ size + sizeof (GNUNET_EC_DBlock),
+ &mchk.query, &value))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ GNUNET_GE_ASSERT (ectx, value != NULL);
+ *value = *dblock; /* copy options! */
+ if ((doIndex == GNUNET_NO) &&
+ (GNUNET_OK != (ret = GNUNET_FS_insert (sock, value))))
+ {
+ GNUNET_GE_BREAK (ectx, ret == GNUNET_NO);
+ GNUNET_free (value);
+ goto FAILURE;
+ }
+ GNUNET_free (value);
+ }
+ pos += size;
+ now = GNUNET_get_time ();
+ if (pos > 0)
+ {
+ eta = (GNUNET_CronTime) (start +
+ (((double) (now - start) / (double) pos))
+ * (double) filesize);
+ }
+ if (GNUNET_OK != pushBlock (sock, &mchk, 0, /* dblocks are on
level 0 */
+ iblocks, priority, expirationTime))
+ goto FAILURE;
+ }
+ if (tt != NULL)
+ if (GNUNET_OK != tt (ttClosure))
+ goto FAILURE;
+#if DEBUG_UPLOAD
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Tree depth is %u, walking up tree.\n", treedepth);
+#endif
+ for (i = 0; i < treedepth; i++)
+ {
+ size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);
+ GNUNET_GE_ASSERT (ectx, size < GNUNET_MAX_BUFFER_SIZE);
+ if (size == sizeof (GNUNET_EC_DBlock))
+ {
+#if DEBUG_UPLOAD
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Level %u is empty\n", i);
+#endif
+ continue;
+ }
+ db = (GNUNET_EC_DBlock *) & iblocks[i][1];
+ GNUNET_EC_file_block_get_key (db, size, &mchk.key);
+#if DEBUG_UPLOAD
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Computing query for %u bytes content.\n", size);
+#endif
+ GNUNET_EC_file_block_get_query (db, size, &mchk.query);
+#if DEBUG_UPLOAD
+ IF_GELOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ GNUNET_hash_to_enc (&mchk.query, &enc));
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Query for current block at level %u is `%s'.\n", i,
+ &enc);
+#endif
+ if (GNUNET_OK != pushBlock (sock,
+ &mchk, i + 1, iblocks, priority,
+ expirationTime))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ GNUNET_EC_file_block_encode (db, size, &mchk.query, &value);
+ if (value == NULL)
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ value->expiration_time = GNUNET_htonll (expirationTime);
+ value->priority = htonl (priority);
+ if ((doIndex != GNUNET_SYSERR) &&
+ (GNUNET_SYSERR == GNUNET_FS_insert (sock, value)))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ GNUNET_free (value);
+ goto FAILURE;
+ }
+ GNUNET_free (value);
+ GNUNET_free (iblocks[i]);
+ iblocks[i] = NULL;
+ }
+#if DEBUG_UPLOAD
+ IF_GELOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ GNUNET_hash_to_enc (&mchk.query, &enc));
+ GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Query for top block is %s\n", &enc);
+#endif
+ /* build URI */
+ fid.file_length = GNUNET_htonll (filesize);
+ db = (GNUNET_EC_DBlock *) & iblocks[treedepth][1];
+
+ fid.chk = *(GNUNET_EC_ContentHashKey *) & (db[1]);
+ *uri = GNUNET_malloc (sizeof (URI));
+ (*uri)->type = chk;
+ (*uri)->data.fi = fid;
+
+ /* free resources */
+ GNUNET_free_non_null (iblocks[treedepth]);
+ GNUNET_free (iblocks);
+ GNUNET_free (dblock);
+ if (upcb != NULL)
+ upcb (filesize, filesize, eta, upcbClosure);
+ CLOSE (fd);
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_OK;
+FAILURE:
+ for (i = 0; i <= treedepth; i++)
+ GNUNET_free_non_null (iblocks[i]);
+ GNUNET_free (iblocks);
+ GNUNET_free (dblock);
+ CLOSE (fd);
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+}
+
+#endif
+
+/* end of fs_publish.c */
Added: gnunet/src/fs/fs_search.c
===================================================================
--- gnunet/src/fs/fs_search.c (rev 0)
+++ gnunet/src/fs/fs_search.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,572 @@
+/*
+ This file is part of GNUnet.
+ (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
+ 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 applications/fs/ecrs/search.c
+ * @brief Helper functions for searching.
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_protocols.h"
+#include "gnunet_fs_lib.h"
+#include "gnunet_ecrs_lib.h"
+#include "ecrs_core.h"
+#include "ecrs.h"
+
+#define DEBUG_SEARCH GNUNET_NO
+
+/**
+ * Context for an individual search. Followed
+ * by keyCount keys of type GNUNET_HashCode.
+ */
+struct PendingSearch
+{
+ struct PendingSearch *next;
+
+ struct GNUNET_ECRS_SearchContext *context;
+
+ /**
+ * The key (for decryption)
+ */
+ GNUNET_HashCode decryptKey;
+
+ unsigned int keyCount;
+
+ /**
+ * What type of query is it?
+ */
+ unsigned int type;
+
+};
+
+/**
+ * Context for search operation.
+ */
+struct GNUNET_ECRS_SearchContext
+{
+ /**
+ * Time when the cron-job was first started.
+ */
+ GNUNET_CronTime start;
+
+ /**
+ * What is the global timeout?
+ */
+ GNUNET_CronTime timeout;
+
+ /**
+ * Search context
+ */
+ struct GNUNET_FS_SearchContext *sctx;
+
+ /**
+ * Active searches.
+ */
+ struct PendingSearch *queries;
+
+ GNUNET_ECRS_SearchResultProcessor spcb;
+
+ void *spcbClosure;
+
+ struct GNUNET_GE_Context *ectx;
+
+ struct GNUNET_GC_Configuration *cfg;
+
+ int aborted;
+
+ int my_sctx;
+
+ unsigned int anonymityLevel;
+
+};
+
+static int
+receive_response_callback (const GNUNET_HashCode * key,
+ const GNUNET_DatastoreValue * value,
+ void *cls, unsigned long long uid);
+
+/**
+ * Add a query to the SQC.
+ */
+static void
+add_search (unsigned int type,
+ unsigned int keyCount,
+ const GNUNET_HashCode * keys,
+ const GNUNET_HashCode * dkey,
+ struct GNUNET_ECRS_SearchContext *sqc)
+{
+ struct PendingSearch *ps;
+
+ ps =
+ GNUNET_malloc (sizeof (struct PendingSearch) +
+ sizeof (GNUNET_HashCode) * keyCount);
+ ps->type = type;
+ ps->keyCount = keyCount;
+ memcpy (&ps[1], keys, sizeof (GNUNET_HashCode) * keyCount);
+ ps->decryptKey = *dkey;
+ ps->context = sqc;
+ ps->next = sqc->queries;
+ sqc->queries = ps;
+ GNUNET_FS_start_search (sqc->sctx,
+ NULL,
+ type,
+ keyCount,
+ keys,
+ sqc->anonymityLevel,
+ &receive_response_callback, ps);
+}
+
+/**
+ * Add the query that corresponds to the given URI
+ * to the SQC.
+ */
+static void
+add_search_for_uri (const struct GNUNET_ECRS_URI *uri,
+ struct GNUNET_ECRS_SearchContext *sqc)
+{
+ struct GNUNET_GE_Context *ectx = sqc->ectx;
+
+ switch (uri->type)
+ {
+ case chk:
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("CHK URI not allowed for search.\n"));
+ break;
+ case sks:
+ {
+ GNUNET_HashCode keys[2];
+ GNUNET_HashCode hk; /* hk = GNUNET_hash(identifier) */
+ GNUNET_HashCode hk2; /* hk2 = GNUNET_hash(hk) */
+
+ GNUNET_hash (uri->data.sks.identifier,
+ strlen (uri->data.sks.identifier), &hk);
+ GNUNET_hash (&hk, sizeof (GNUNET_HashCode), &hk2);
+ /* compute routing key keys[0] = H(key) ^ namespace */
+ GNUNET_hash_xor (&hk2, &uri->data.sks.namespace, &keys[0]);
+ keys[1] = uri->data.sks.namespace;
+ add_search (GNUNET_ECRS_BLOCKTYPE_SIGNED, 2, &keys[0], &hk, sqc);
+ break;
+ }
+ case ksk:
+ {
+ GNUNET_HashCode hc;
+ GNUNET_HashCode query;
+ struct GNUNET_RSA_PrivateKey *pk;
+ GNUNET_RSA_PublicKey pub;
+ int i;
+ const char *keyword;
+
+#if DEBUG_SEARCH
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Computing queries (this may take a while).\n");
+#endif
+ for (i = 0; i < uri->data.ksk.keywordCount; i++)
+ {
+ keyword = uri->data.ksk.keywords[i];
+ /* first character of the keyword is
+ "+" or " " to indicate mandatory or
+ not -- ignore for hashing! */
+ GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc);
+ pk = GNUNET_RSA_create_key_from_hash (&hc);
+ GNUNET_RSA_get_public_key (pk, &pub);
+ GNUNET_hash (&pub, sizeof (GNUNET_RSA_PublicKey), &query);
+ add_search (GNUNET_ECRS_BLOCKTYPE_ANY, /*
GNUNET_ECRS_BLOCKTYPE_KEYWORD, GNUNET_ECRS_BLOCKTYPE_NAMESPACE or
GNUNET_ECRS_BLOCKTYPE_KEYWORD_FOR_NAMESPACE ok */
+ 1, &query, &hc, sqc);
+ GNUNET_RSA_free_key (pk);
+ }
+#if DEBUG_SEARCH
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Queries ready.\n");
+#endif
+ break;
+ }
+ case loc:
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("LOC URI not allowed for search.\n"));
+ break;
+ default:
+ GNUNET_GE_BREAK (ectx, 0);
+ /* unknown URI type */
+ break;
+ }
+}
+
+/**
+ * We found an GNUNET_EC_SBlock. Decode the meta-data and call
+ * the callback of the SQC with the root-URI for the namespace,
+ * together with the namespace advertisement. Also, if this is
+ * a result with updates, automatically start the search for
+ * updates.
+ */
+static int
+process_sblock_result (const GNUNET_EC_SBlock * sb,
+ const GNUNET_HashCode * key,
+ unsigned int size,
+ struct GNUNET_ECRS_SearchContext *sqc)
+{
+ static GNUNET_HashCode allZeros;
+ struct GNUNET_GE_Context *ectx = sqc->ectx;
+ GNUNET_ECRS_FileInfo fi;
+ URI updateURI;
+ int ret;
+ const char *id;
+ const char *uris;
+ unsigned int len;
+ unsigned int off;
+ int isRoot;
+
+ len = size - sizeof (GNUNET_EC_SBlock);
+ off = GNUNET_string_buffer_tokenize ((const char *) &sb[1],
+ len, 2, &id, &uris);
+ if (off == 0)
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
+ return GNUNET_SYSERR;
+ }
+ fi.meta = GNUNET_meta_data_deserialize (ectx, &id[off], len - off);
+ if (fi.meta == NULL)
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
+ return GNUNET_SYSERR;
+ }
+ isRoot = 0 == memcmp (&sb->identifier, &allZeros, sizeof (GNUNET_HashCode));
+ fi.uri = GNUNET_ECRS_string_to_uri (ectx, uris);
+ if ((isRoot) && (fi.uri == NULL))
+ {
+ fi.uri = GNUNET_malloc (sizeof (URI));
+ fi.uri->type = sks;
+ GNUNET_hash (&sb->subspace,
+ sizeof (GNUNET_RSA_PublicKey),
+ &fi.uri->data.sks.namespace);
+ fi.uri->data.sks.identifier = GNUNET_strdup (id);
+ }
+ if (fi.uri == NULL)
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
+ GNUNET_meta_data_destroy (fi.meta);
+ return GNUNET_SYSERR;
+ }
+ if (sqc->spcb != NULL)
+ {
+ ret = sqc->spcb (&fi, key, isRoot, sqc->spcbClosure);
+ if (ret == GNUNET_SYSERR)
+ sqc->aborted = GNUNET_YES;
+ }
+ else
+ ret = GNUNET_OK;
+ if ((strlen (id) > 0) && (strlen (uris) > 0))
+ {
+ updateURI.type = sks;
+ GNUNET_hash (&sb->subspace,
+ sizeof (GNUNET_RSA_PublicKey),
+ &updateURI.data.sks.namespace);
+ updateURI.data.sks.identifier = GNUNET_strdup (id);
+ add_search_for_uri (&updateURI, sqc);
+ GNUNET_free (updateURI.data.sks.identifier);
+ }
+ GNUNET_meta_data_destroy (fi.meta);
+ GNUNET_ECRS_uri_destroy (fi.uri);
+ return ret;
+}
+
+/**
+ * Process replies received in response to our
+ * queries. Verifies, decrypts and passes valid
+ * replies to the callback.
+ *
+ * @return GNUNET_SYSERR if the entry is malformed
+ */
+static int
+receive_response_callback (const GNUNET_HashCode * key,
+ const GNUNET_DatastoreValue * value,
+ void *cls, unsigned long long uid)
+{
+ struct PendingSearch *ps = cls;
+ struct GNUNET_ECRS_SearchContext *sqc = ps->context;
+ struct GNUNET_GE_Context *ectx = sqc->ectx;
+ unsigned int type;
+ GNUNET_ECRS_FileInfo fi;
+ unsigned int size;
+ int ret;
+ GNUNET_HashCode query;
+ GNUNET_CronTime expiration;
+
+ expiration = GNUNET_ntohll (value->expiration_time);
+ if (expiration < GNUNET_get_time ())
+ return GNUNET_OK; /* expired, ignore! */
+ type = ntohl (value->type);
+ size = ntohl (value->size) - sizeof (GNUNET_DatastoreValue);
+#if DEBUG_SEARCH
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "Search received reply of type %u and size %u.\n", type,
+ size);
+#endif
+ if (GNUNET_OK !=
+ GNUNET_EC_file_block_check_and_get_query (size,
+ (const GNUNET_EC_DBlock *)
+ &value[1], GNUNET_YES,
+ &query))
+ {
+ GNUNET_GE_BREAK_OP (NULL, 0);
+ return GNUNET_SYSERR;
+ }
+ if (!((0 == memcmp (&query,
+ (GNUNET_HashCode *) & ps[1], sizeof (GNUNET_HashCode)))
+ && ((ps->type == type) || (ps->type == GNUNET_ECRS_BLOCKTYPE_ANY))
+ && (GNUNET_YES ==
+ GNUNET_EC_is_block_applicable_for_query (type, size,
+ (const GNUNET_EC_DBlock
+ *) &value[1], &query,
+ ps->keyCount,
+ (GNUNET_HashCode *) &
+ ps[1]))))
+ {
+ return GNUNET_OK; /* not a match */
+ }
+
+ switch (type)
+ {
+ case GNUNET_ECRS_BLOCKTYPE_KEYWORD:
+ {
+ GNUNET_EC_KBlock *kb;
+ const char *dstURI;
+#if DEBUG_SEARCH
+ GNUNET_EncName enc;
+#endif
+ int j;
+
+ if (size < sizeof (GNUNET_EC_KBlock))
+ {
+ GNUNET_GE_BREAK_OP (NULL, 0);
+ return GNUNET_SYSERR;
+ }
+ kb = GNUNET_malloc (size);
+ memcpy (kb, &value[1], size);
+#if DEBUG_SEARCH
+ IF_GELOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
+ GNUNET_GE_USER, GNUNET_hash_to_enc (&ps->decryptKey, &enc));
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
+ GNUNET_GE_USER,
+ "Decrypting KBlock with key %s.\n", &enc);
+#endif
+ GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
+ &kb[1], size - sizeof (GNUNET_EC_KBlock));
+ j = sizeof (GNUNET_EC_KBlock);
+ while ((j < size) && (((const char *) kb)[j] != '\0'))
+ j++;
+ if (j == size)
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* kblock malformed */
+ GNUNET_free (kb);
+ return GNUNET_SYSERR;
+ }
+ dstURI = (const char *) &kb[1];
+ j++;
+ fi.meta = GNUNET_meta_data_deserialize (ectx,
+ &((const char *)
+ kb)[j], size - j);
+ if (fi.meta == NULL)
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* kblock malformed */
+ GNUNET_free (kb);
+ return GNUNET_SYSERR;
+ }
+ fi.uri = GNUNET_ECRS_string_to_uri (ectx, dstURI);
+ if (fi.uri == NULL)
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* kblock malformed */
+ GNUNET_meta_data_destroy (fi.meta);
+ GNUNET_free (kb);
+ return GNUNET_SYSERR;
+ }
+ if (sqc->spcb != NULL)
+ {
+ ret = sqc->spcb (&fi,
+ &ps->decryptKey, GNUNET_NO, sqc->spcbClosure);
+ if (ret == GNUNET_SYSERR)
+ sqc->aborted = GNUNET_YES;
+ }
+ else
+ ret = GNUNET_OK;
+ GNUNET_ECRS_uri_destroy (fi.uri);
+ GNUNET_meta_data_destroy (fi.meta);
+ GNUNET_free (kb);
+ return ret;
+ }
+ case GNUNET_ECRS_BLOCKTYPE_SIGNED:
+ {
+ GNUNET_EC_SBlock *sb;
+ int ret;
+
+ if (size < sizeof (GNUNET_EC_SBlock))
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
+ return GNUNET_SYSERR;
+ }
+ sb = GNUNET_malloc (size);
+ memcpy (sb, &value[1], size);
+ GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
+ &sb[1], size - sizeof (GNUNET_EC_SBlock));
+ ret = process_sblock_result (sb, &ps->decryptKey, size, sqc);
+ GNUNET_free (sb);
+ return ret;
+ }
+ case GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED:
+ {
+ GNUNET_EC_KSBlock *kb;
+ int ret;
+
+ if (size < sizeof (GNUNET_EC_KSBlock))
+ {
+ GNUNET_GE_BREAK_OP (ectx, 0); /* ksblock malformed */
+ return GNUNET_SYSERR;
+ }
+ kb = GNUNET_malloc (size);
+ memcpy (kb, &value[1], size);
+ GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
+ &kb->sblock,
+ size - sizeof (GNUNET_EC_KBlock) -
+ sizeof (unsigned int));
+ ret =
+ process_sblock_result (&kb->sblock, &ps->decryptKey,
+ size - sizeof (GNUNET_EC_KSBlock) +
+ sizeof (GNUNET_EC_SBlock), sqc);
+ GNUNET_free (kb);
+ return ret;
+ }
+ default:
+ GNUNET_GE_BREAK_OP (ectx, 0);
+ break;
+ } /* end switch */
+ return GNUNET_OK;
+}
+
+/**
+ * Start search for content.
+ *
+ * @param uri specifies the search parameters
+ * @param uri set to the URI of the uploaded file
+ */
+struct GNUNET_ECRS_SearchContext *
+GNUNET_ECRS_search_start (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ struct GNUNET_FS_SearchContext *sc,
+ const struct GNUNET_ECRS_URI *uri,
+ unsigned int anonymityLevel,
+ GNUNET_ECRS_SearchResultProcessor spcb,
+ void *spcbClosure)
+{
+ struct GNUNET_ECRS_SearchContext *ctx;
+
+ if (GNUNET_YES == GNUNET_ECRS_uri_test_ksk (uri))
+ {
+ if (1 != GNUNET_ECRS_uri_get_keyword_count_from_ksk (uri))
+ return NULL;
+ }
+ else
+ {
+ if (GNUNET_YES != GNUNET_ECRS_uri_test_sks (uri))
+ return NULL;
+ }
+ ctx = GNUNET_malloc (sizeof (struct GNUNET_ECRS_SearchContext));
+ ctx->start = GNUNET_get_time ();
+ ctx->anonymityLevel = anonymityLevel;
+ ctx->ectx = ectx;
+ ctx->cfg = cfg;
+ ctx->queries = NULL;
+ ctx->spcb = spcb;
+ ctx->spcbClosure = spcbClosure;
+ ctx->aborted = GNUNET_NO;
+ ctx->sctx = sc == NULL ? GNUNET_FS_create_search_context (ectx, cfg) : sc;
+ if (ctx->sctx == NULL)
+ {
+ GNUNET_free (ctx);
+ return NULL;
+ }
+ ctx->my_sctx = (sc == NULL);
+ add_search_for_uri (uri, ctx);
+ return ctx;
+}
+
+/**
+ * Stop search for content.
+ *
+ * @param uri specifies the search parameters
+ * @param uri set to the URI of the uploaded file
+ */
+void
+GNUNET_ECRS_search_stop (struct GNUNET_ECRS_SearchContext *ctx)
+{
+ struct PendingSearch *pos;
+
+ while (ctx->queries != NULL)
+ {
+ pos = ctx->queries;
+ ctx->queries = pos->next;
+ if (!ctx->my_sctx)
+ GNUNET_FS_stop_search (ctx->sctx, &receive_response_callback, pos);
+ GNUNET_free (pos);
+ }
+ if (ctx->my_sctx)
+ GNUNET_FS_destroy_search_context (ctx->sctx);
+ GNUNET_free (ctx);
+}
+
+/**
+ * Search for content.
+ *
+ * @param timeout how long to wait (relative)
+ * @param uri specifies the search parameters
+ * @param uri set to the URI of the uploaded file
+ */
+int
+GNUNET_ECRS_search (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const struct GNUNET_ECRS_URI *uri,
+ unsigned int anonymityLevel,
+ GNUNET_ECRS_SearchResultProcessor spcb,
+ void *spcbClosure, GNUNET_ECRS_TestTerminate tt,
+ void *ttClosure)
+{
+ struct GNUNET_ECRS_SearchContext *ctx;
+
+ ctx =
+ GNUNET_ECRS_search_start (ectx, cfg, NULL,
+ uri, anonymityLevel, spcb, spcbClosure);
+ if (ctx == NULL)
+ return GNUNET_SYSERR;
+ while (((NULL == tt) || (GNUNET_OK == tt (ttClosure)))
+ && (GNUNET_NO == GNUNET_shutdown_test ())
+ && (ctx->aborted == GNUNET_NO))
+ GNUNET_thread_sleep (100 * GNUNET_CRON_MILLISECONDS);
+ GNUNET_ECRS_search_stop (ctx);
+ return GNUNET_OK;
+}
+
+
+/* end of search.c */
Added: gnunet/src/fs/fs_test.c
===================================================================
--- gnunet/src/fs/fs_test.c (rev 0)
+++ gnunet/src/fs/fs_test.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,259 @@
+/*
+ This file is part of GNUnet.
+ (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
+ 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 applications/fs/fsui/basic_fsui_test.c
+ * @brief testcase for fsui (upload-search-download-unindex)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define DEBUG_VERBOSE GNUNET_NO
+
+#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(NULL, 0); goto
FAILURE; }
+
+static char *
+makeName (unsigned int i)
+{
+ char *fn;
+
+ fn =
+ GNUNET_malloc (strlen ("/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST") +
+ 14);
+ GNUNET_snprintf (fn,
+ strlen ("/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST") +
+ 14, "/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST%u", i);
+ GNUNET_disk_directory_create_for_file (NULL, fn);
+ return fn;
+}
+
+static volatile enum GNUNET_FSUI_EventType lastEvent;
+
+static struct GNUNET_MetaData *search_meta;
+
+static struct GNUNET_ECRS_URI *search_uri;
+
+static struct GNUNET_FSUI_Context *ctx;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event * event)
+{
+ static char unused;
+
+ switch (event->type)
+ {
+ case GNUNET_FSUI_search_resumed:
+ case GNUNET_FSUI_download_resumed:
+ case GNUNET_FSUI_upload_resumed:
+ case GNUNET_FSUI_unindex_resumed:
+ return &unused;
+ case GNUNET_FSUI_search_result:
+#if DEBUG_VERBOSE
+ printf ("Received search result\n");
+#endif
+ search_uri =
+ GNUNET_ECRS_uri_duplicate (event->data.SearchResult.fi.uri);
+ search_meta =
+ GNUNET_meta_data_duplicate (event->data.SearchResult.fi.meta);
+ break;
+ case GNUNET_FSUI_upload_completed:
+#if DEBUG_VERBOSE
+ printf ("Upload complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_download_completed:
+#if DEBUG_VERBOSE
+ printf ("Download complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_completed:
+#if DEBUG_VERBOSE
+ printf ("Unindex complete.\n");
+#endif
+ break;
+ default:
+ break;
+ }
+ lastEvent = event->type;
+ return NULL;
+}
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+ pid_t daemon;
+#endif
+ int ok;
+ struct GNUNET_ECRS_URI *uri;
+ char *filename = NULL;
+ char *keywords[] = {
+ "fsui_foo",
+ "fsui_bar",
+ };
+ char keyword[40];
+ char *fn;
+ int prog;
+ struct GNUNET_MetaData *meta;
+ struct GNUNET_ECRS_URI *kuri;
+ struct GNUNET_GC_Configuration *cfg;
+ struct GNUNET_FSUI_UploadList *upload = NULL;
+ struct GNUNET_FSUI_SearchList *search = NULL;
+ struct GNUNET_FSUI_UnindexList *unindex = NULL;
+ struct GNUNET_FSUI_DownloadList *download = NULL;
+
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+#if START_DAEMON
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ CHECK (GNUNET_OK ==
+ GNUNET_wait_for_daemon_running (NULL, cfg,
+ 60 * GNUNET_CRON_SECONDS));
+#endif
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to
start */
+ ok = GNUNET_YES;
+
+ /* ACTUAL TEST CODE */
+ ctx = GNUNET_FSUI_start (NULL, cfg, "basic_fsui_test", 32, /* thread pool
size */
+ GNUNET_NO, /* no resume */
+ &eventCallback, NULL);
+ CHECK (ctx != NULL);
+ filename = makeName (42);
+ GNUNET_disk_file_write (NULL,
+ filename,
+ "foo bar test!", strlen ("foo bar test!"), "600");
+ meta = GNUNET_meta_data_create ();
+ kuri =
+ GNUNET_ECRS_keyword_command_line_to_uri (NULL, 2,
+ (const char **) keywords);
+ /* upload */
+ upload = GNUNET_FSUI_upload_start (ctx, filename,
(GNUNET_FSUI_DirectoryScanCallback) & GNUNET_disk_directory_scan, NULL, 0, /*
anonymity */
+ 0, /* priority */
+ GNUNET_YES,
+ GNUNET_NO,
+ GNUNET_NO,
+ GNUNET_get_time () +
+ 5 * GNUNET_CRON_HOURS, meta, kuri, kuri);
+ CHECK (upload != NULL);
+ GNUNET_ECRS_uri_destroy (kuri);
+ GNUNET_meta_data_destroy (meta);
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_upload_completed)
+ {
+ prog++;
+ CHECK (prog <
+ 10000) GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+
+ /* search */
+ GNUNET_snprintf (keyword, 40, "+%s +%s", keywords[0], keywords[1]);
+ uri = GNUNET_ECRS_keyword_string_to_uri (NULL, keyword);
+ search = GNUNET_FSUI_search_start (ctx, 0, uri);
+ GNUNET_ECRS_uri_destroy (uri);
+ CHECK (search != NULL);
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_search_result)
+ {
+ prog++;
+ CHECK (prog < 10000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_search_abort (search);
+ GNUNET_FSUI_search_stop (search);
+
+ /* download */
+ fn = makeName (43);
+ download = GNUNET_FSUI_download_start (ctx,
+ 0,
+ GNUNET_NO,
+ search_uri,
+ search_meta, fn, NULL, NULL);
+ GNUNET_free (fn);
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_download_completed)
+ {
+ prog++;
+ CHECK (prog < 10000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_download_stop (download);
+ download = NULL;
+ GNUNET_ECRS_uri_destroy (search_uri);
+ GNUNET_meta_data_destroy (search_meta);
+ /* unindex */
+ unindex = GNUNET_FSUI_unindex_start (ctx, filename);
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_unindex_completed)
+ {
+ prog++;
+ CHECK (prog < 10000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ if (lastEvent != GNUNET_FSUI_unindex_completed)
+ GNUNET_FSUI_unindex_abort (unindex);
+ GNUNET_FSUI_unindex_stop (unindex);
+
+
+ /* END OF TEST CODE */
+FAILURE:
+ if (ctx != NULL)
+ GNUNET_FSUI_stop (ctx);
+ if (filename != NULL)
+ {
+ UNLINK (filename);
+ GNUNET_free (filename);
+ }
+ if (download != NULL)
+ {
+ GNUNET_FSUI_download_abort (download);
+ GNUNET_FSUI_download_stop (download);
+ }
+ filename = makeName (43);
+ /* TODO: verify file 'filename(42)' == file 'filename(43)' */
+ UNLINK (filename);
+ GNUNET_free (filename);
+
+#if START_DAEMON
+ GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+#endif
+ GNUNET_GC_free (cfg);
+
+ return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+/* end of basic_fsui_test.c */
Added: gnunet/src/fs/fs_unindex.c
===================================================================
--- gnunet/src/fs/fs_unindex.c (rev 0)
+++ gnunet/src/fs/fs_unindex.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,394 @@
+/*
+ This file is part of GNUnet.
+ (C) 2003, 2004, 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 applications/fs/ecrs/unindex.c
+ * @author Krista Bennett
+ * @author Christian Grothoff
+ *
+ * Unindex file.
+ *
+ * TODO:
+ * - code cleanup (share more with upload.c)
+ */
+
+#include "platform.h"
+#include "gnunet_protocols.h"
+#include "gnunet_ecrs_lib.h"
+#include "gnunet_fs_lib.h"
+#include "gnunet_getoption_lib.h"
+#include "ecrs_core.h"
+#include "ecrs.h"
+#include "fs.h"
+#include "tree.h"
+
+#define STRICT_CHECKS GNUNET_NO
+
+/**
+ * Append the given key and query to the iblock[level].
+ * If iblock[level] is already full, compute its chk
+ * and push it to level+1. iblocks is guaranteed to
+ * be big enough.
+ *
+ * This function matches exactly upload.c::pushBlock,
+ * except in the call to 'GNUNET_FS_delete'. TODO: refactor
+ * to avoid code duplication (move to block.c, pass
+ * GNUNET_FS_delete as argument!).
+ */
+static int
+pushBlock (struct GNUNET_ClientServerConnection *sock,
+ const GNUNET_EC_ContentHashKey * chk, unsigned int level,
+ GNUNET_DatastoreValue ** iblocks)
+{
+ unsigned int size;
+ unsigned int present;
+ GNUNET_DatastoreValue *value;
+ GNUNET_EC_DBlock *db;
+ GNUNET_EC_ContentHashKey ichk;
+
+ size = ntohl (iblocks[level]->size) - sizeof (GNUNET_DatastoreValue);
+ present =
+ (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);
+ db = (GNUNET_EC_DBlock *) & iblocks[level][1];
+ if (present == GNUNET_ECRS_CHK_PER_INODE)
+ {
+ GNUNET_EC_file_block_get_key (db, size, &ichk.key);
+ GNUNET_EC_file_block_get_query (db, size, &ichk.query);
+ if (GNUNET_OK != pushBlock (sock, &ichk, level + 1, iblocks))
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);
+#if STRICT_CHECKS
+ if (GNUNET_SYSERR == GNUNET_FS_delete (sock, value))
+ {
+ GNUNET_free (value);
+ GNUNET_GE_BREAK (NULL, 0);
+ return GNUNET_SYSERR;
+ }
+#else
+ GNUNET_FS_delete (sock, value);
+#endif
+ GNUNET_free (value);
+ size = sizeof (GNUNET_EC_DBlock);
+ }
+ /* append GNUNET_EC_ContentHashKey */
+ memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));
+ iblocks[level]->size = htonl (size +
+ sizeof (GNUNET_EC_ContentHashKey) +
+ sizeof (GNUNET_DatastoreValue));
+ return GNUNET_OK;
+}
+
+
+
+/**
+ * Undo sym-linking operation:
+ * a) check if we have a symlink
+ * b) delete symbolic link
+ */
+static int
+undoSymlinking (struct GNUNET_GE_Context *ectx,
+ const char *fn,
+ const GNUNET_HashCode * fileId,
+ struct GNUNET_ClientServerConnection *sock)
+{
+ GNUNET_EncName enc;
+ char *serverDir;
+ char *serverFN;
+ struct stat buf;
+
+#ifndef S_ISLNK
+ if (1)
+ return GNUNET_OK; /* symlinks do not exist? */
+#endif
+ if (0 != LSTAT (fn, &buf))
+ {
+ GNUNET_GE_LOG_STRERROR_FILE (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK |
+ GNUNET_GE_USER | GNUNET_GE_ADMIN, "stat",
+ fn);
+ return GNUNET_SYSERR;
+ }
+#ifdef S_ISLNK
+ if (!S_ISLNK (buf.st_mode))
+ return GNUNET_OK;
+#endif
+ serverDir =
+ GNUNET_get_daemon_configuration_value (sock, "FS", "INDEX-DIRECTORY");
+ if (serverDir == NULL)
+ return GNUNET_OK;
+ serverFN = GNUNET_malloc (strlen (serverDir) + 2 + sizeof (GNUNET_EncName));
+ strcpy (serverFN, serverDir);
+ GNUNET_free (serverDir);
+ if (serverFN[strlen (serverFN) - 1] != DIR_SEPARATOR)
+ strcat (serverFN, DIR_SEPARATOR_STR);
+ GNUNET_hash_to_enc (fileId, &enc);
+ strcat (serverFN, (char *) &enc);
+
+ if (0 != UNLINK (serverFN))
+ {
+ GNUNET_GE_LOG_STRERROR_FILE (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK |
+ GNUNET_GE_USER | GNUNET_GE_ADMIN, "unlink",
+ serverFN);
+ GNUNET_free (serverFN);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (serverFN);
+ return GNUNET_OK;
+}
+
+
+
+/**
+ * Unindex a file.
+ *
+ * @return GNUNET_SYSERR if the unindexing failed (i.e. not indexed)
+ */
+int
+GNUNET_ECRS_file_unindex (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ const char *filename,
+ GNUNET_ECRS_UploadProgressCallback upcb,
+ void *upcbClosure, GNUNET_ECRS_TestTerminate tt,
+ void *ttClosure)
+{
+ unsigned long long filesize;
+ unsigned long long pos;
+ unsigned int treedepth;
+ int fd;
+ int i;
+ unsigned int size;
+ GNUNET_DatastoreValue **iblocks;
+ GNUNET_DatastoreValue *dblock;
+ GNUNET_EC_DBlock *db;
+ GNUNET_DatastoreValue *value;
+ struct GNUNET_ClientServerConnection *sock;
+ GNUNET_HashCode fileId;
+ GNUNET_EC_ContentHashKey chk;
+ GNUNET_CronTime eta;
+ GNUNET_CronTime start;
+ GNUNET_CronTime now;
+ int wasIndexed;
+
+ start = GNUNET_get_time ();
+ if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))
+ return GNUNET_SYSERR;
+ sock = GNUNET_client_connection_create (ectx, cfg);
+ if (sock == NULL)
+ return GNUNET_SYSERR;
+ eta = 0;
+ if (upcb != NULL)
+ upcb (filesize, 0, eta, upcbClosure);
+ if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))
+ {
+ GNUNET_client_connection_destroy (sock);
+ GNUNET_GE_BREAK (ectx, 0);
+ return GNUNET_SYSERR;
+ }
+ now = GNUNET_get_time ();
+ eta = now + 2 * (now - start);
+ /* very rough estimate: GNUNET_hash reads once through the file,
+ we'll do that once more and write it. But of course
+ the second read may be cached, and we have the encryption,
+ so a factor of two is really, really just a rough estimate */
+ start = now;
+ /* reset the counter since the formula later does not
+ take the time for GNUNET_hash_file into account */
+ treedepth = GNUNET_ECRS_compute_depth (filesize);
+
+ /* Test if file is indexed! */
+ wasIndexed = GNUNET_FS_test_indexed (sock, &fileId);
+
+ fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);
+ if (fd == -1)
+ {
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+ }
+ dblock =
+ GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
+ sizeof (GNUNET_EC_DBlock));
+ dblock->size =
+ htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
+ sizeof (GNUNET_EC_DBlock));
+ dblock->anonymity_level = htonl (0);
+ dblock->priority = htonl (0);
+ dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ dblock->expiration_time = GNUNET_htonll (0);
+ db = (GNUNET_EC_DBlock *) & dblock[1];
+ db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ iblocks =
+ GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));
+ for (i = 0; i <= treedepth; i++)
+ {
+ iblocks[i] =
+ GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
+ GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));
+ iblocks[i]->size =
+ htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));
+ iblocks[i]->anonymity_level = htonl (0);
+ iblocks[i]->priority = htonl (0);
+ iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ iblocks[i]->expiration_time = GNUNET_htonll (0);
+ ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =
+ htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ }
+
+ pos = 0;
+ while (pos < filesize)
+ {
+ if (upcb != NULL)
+ upcb (filesize, pos, eta, upcbClosure);
+ if (tt != NULL)
+ if (GNUNET_OK != tt (ttClosure))
+ goto FAILURE;
+ size = GNUNET_ECRS_DBLOCK_SIZE;
+ if (size > filesize - pos)
+ {
+ size = filesize - pos;
+ memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);
+ }
+ dblock->size =
+ htonl (sizeof (GNUNET_DatastoreValue) + size +
+ sizeof (GNUNET_EC_DBlock));
+ if (size != READ (fd, &db[1], size))
+ {
+ GNUNET_GE_LOG_STRERROR_FILE (ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_USER |
+ GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ "READ", filename);
+ goto FAILURE;
+ }
+ if (tt != NULL)
+ if (GNUNET_OK != tt (ttClosure))
+ goto FAILURE;
+ GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),
+ &chk.key);
+ GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),
+ &chk.query);
+ if (GNUNET_OK != pushBlock (sock, &chk, 0, /* dblocks are on
level 0 */
+ iblocks))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ if (!wasIndexed)
+ {
+ if (GNUNET_OK ==
+ GNUNET_EC_file_block_encode (db, size, &chk.query, &value))
+ {
+ *value = *dblock; /* copy options! */
+#if STRICT_CHECKS
+ if (GNUNET_OK != GNUNET_FS_delete (sock, value))
+ {
+ GNUNET_free (value);
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+#else
+ GNUNET_FS_delete (sock, value);
+#endif
+ GNUNET_free (value);
+ }
+ else
+ {
+ goto FAILURE;
+ }
+ }
+ pos += size;
+ now = GNUNET_get_time ();
+ eta = (GNUNET_CronTime) (start +
+ (((double) (now - start) / (double) pos))
+ * (double) filesize);
+ }
+ if (tt != NULL)
+ if (GNUNET_OK != tt (ttClosure))
+ goto FAILURE;
+ for (i = 0; i < treedepth; i++)
+ {
+ size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);
+ db = (GNUNET_EC_DBlock *) & iblocks[i][1];
+ GNUNET_EC_file_block_get_key (db, size, &chk.key);
+ GNUNET_EC_file_block_get_query (db, size, &chk.query);
+ if (GNUNET_OK != pushBlock (sock, &chk, i + 1, iblocks))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ GNUNET_EC_file_block_encode (db, size, &chk.query, &value);
+#if STRICT_CHECKS
+ if (GNUNET_OK != GNUNET_FS_delete (sock, value))
+ {
+ GNUNET_free (value);
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+#else
+ GNUNET_FS_delete (sock, value);
+#endif
+ GNUNET_free (value);
+ GNUNET_free (iblocks[i]);
+ iblocks[i] = NULL;
+ }
+
+ if (wasIndexed)
+ {
+ if (GNUNET_OK == undoSymlinking (ectx, filename, &fileId, sock))
+ {
+ if (GNUNET_OK !=
+ GNUNET_FS_unindex (sock, GNUNET_ECRS_DBLOCK_SIZE, &fileId))
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ }
+ else
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ goto FAILURE;
+ }
+ }
+ GNUNET_free (iblocks[treedepth]);
+ /* free resources */
+ GNUNET_free (iblocks);
+ GNUNET_free (dblock);
+ CLOSE (fd);
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_OK;
+FAILURE:
+ for (i = 0; i <= treedepth; i++)
+ GNUNET_free_non_null (iblocks[i]);
+ GNUNET_free (iblocks);
+ GNUNET_free (dblock);
+ CLOSE (fd);
+ GNUNET_client_connection_destroy (sock);
+ return GNUNET_SYSERR;
+}
+
+/* end of unindex.c */
Modified: gnunet/src/fs/fs_uri.c
===================================================================
--- gnunet/src/fs/fs_uri.c 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/fs_uri.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -26,10 +26,10 @@
* GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER".
* The specific structure of "IDENTIFIER" depends on the module and
* maybe differenciated into additional subcategories if applicable.
- * This module only deals with ecrs identifiers (MODULE = "ecrs").
+ * This module only deals with fs identifiers (MODULE = "fs").
* <p>
*
- * This module only parses URIs for the AFS module. The ECRS URIs fall
+ * This module only parses URIs for the AFS module. The FS URIs fall
* into four categories, "chk", "sks", "ksk" and "loc". The first three
* categories were named in analogy (!) to Freenet, but they do NOT
* work in exactly the same way. They are very similar from the user's
@@ -40,7 +40,7 @@
* <ul><li>
*
* First, there are URIs that identify a file. They have the format
- * "gnunet://ecrs/chk/HEX1.HEX2.SIZE". These URIs can be used to
+ * "gnunet://fs/chk/HEX1.HEX2.SIZE". These URIs can be used to
* download the file. The description, filename, mime-type and other
* meta-data is NOT part of the file-URI since a URI uniquely
* identifies a resource (and the contents of the file would be the
@@ -49,7 +49,7 @@
* </li><li>
*
* The second category identifies entries in a namespace. The format
- * is "gnunet://ecrs/sks/NAMESPACE/IDENTIFIER" where the namespace
+ * is "gnunet://fs/sks/NAMESPACE/IDENTIFIER" where the namespace
* should be given in HEX. Applications may allow using a nickname
* for the namespace if the nickname is not ambiguous. The identifier
* can be either an ASCII sequence or a HEX-encoding. If the
@@ -59,7 +59,7 @@
* </li> <li>
*
* The third category identifies ordinary searches. The format is
- * "gnunet://ecrs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax
+ * "gnunet://fs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax
* it is possible to encode searches with the boolean "AND" operator.
* "+" is used since it indicates a commutative 'and' operation and
* is unlikely to be used in a keyword by itself.
@@ -67,7 +67,7 @@
* </li><li>
*
* The last category identifies a datum on a specific machine. The
- * format is "gnunet://ecrs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is
+ * format is "gnunet://fs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is
* the BinName of the public key of the peer storing the datum. The
* signature (SIG) certifies that this peer has this content.
* HEX1, HEX2 and SIZE correspond to a 'chk' URI.
@@ -211,6 +211,7 @@
if (1 != sscanf (&out[rpos + 1], "%2X", &hx))
{
GNUNET_free (out);
+ *emsg = GNUNET_strdup (_("`%' must be followed by HEX number"));
return NULL;
}
rpos += 3;
@@ -265,11 +266,14 @@
pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX);
if ( (slen <= pos) ||
(0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX,
- pos) ) ||
- (s[slen - 1] == '+') ||
+ pos) ) )
+ return NULL; /* not KSK URI */
+ if ( (s[slen - 1] == '+') ||
(s[pos] == '+') )
- return NULL; /* no keywords / malformed */
-
+ {
+ *emsg = GNUNET_strdup (_("Malformed KSK URI (must not begin or end with
`+')"));
+ return NULL;
+ }
max = 1;
saw_quote = 0;
for (i = pos; i < slen; i++)
@@ -284,11 +288,17 @@
{
max++;
if (s[i - 1] == '+')
- return NULL; /* "++" not allowed */
+ {
+ *emsg = GNUNET_strdup (_("`++' not allowed in KSK URI"));
+ return NULL;
+ }
}
}
if (saw_quote == 1)
- return NULL; /* quotes not balanced */
+ {
+ *emsg = GNUNET_strdup (_("Quotes not balanced in KSK URI"));
+ return NULL;
+ }
iret = max;
dup = GNUNET_strdup (s);
keywords = GNUNET_malloc (max * sizeof (char *));
@@ -304,7 +314,7 @@
{
keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg);
if (NULL == keywords[max])
- goto CLEANUP;
+ goto CLEANUP;
dup[i] = '\0';
}
}
@@ -349,14 +359,21 @@
pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX);
if ( (slen <= pos) ||
(0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX,
- pos) ) ||
- (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
+ pos) ) )
+ return NULL; /* not an SKS URI */
+ if ( (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
(s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/') )
- return NULL;
+ {
+ *emsg = GNUNET_strdup (_("Malformed SKS URI"));
+ return NULL;
+ }
memcpy (enc, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace))
- return NULL;
+ {
+ *emsg = GNUNET_strdup (_("Malformed SKS URI"));
+ return NULL;
+ }
identifier = GNUNET_strdup (&s[pos + sizeof (struct
GNUNET_CRYPTO_HashAsciiEncoded)]);
ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
ret->type = sks;
@@ -389,11 +406,14 @@
pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX);
if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
(0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX,
- pos) ) ||
- (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
+ pos) ) )
+ return NULL; /* not a CHK URI */
+ if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
(s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] !=
'.') )
- return NULL;
-
+ {
+ *emsg = GNUNET_strdup (_("Malformed CHK URI"));
+ return NULL;
+ }
memcpy (h1,
&s[pos],
sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
@@ -410,9 +430,11 @@
(1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) *
2],
"%llu",
&fi.file_length)))
- return NULL;
+ {
+ *emsg = GNUNET_strdup (_("Malformed CHK URI"));
+ return NULL;
+ }
fi.file_length = GNUNET_htonll (fi.file_length);
-
ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
ret->type = chk;
ret->data.chk = fi;
@@ -527,18 +549,20 @@
struct LocUriAssembly ass;
int ret;
size_t slen;
- char *addr;
GNUNET_assert (s != NULL);
slen = strlen (s);
pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX);
if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
(0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX,
- pos) ) ||
- (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
+ pos) ) )
+ return NULL; /* not an SKS URI */
+ if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
(s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] !=
'.') )
- return NULL;
-
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed"));
+ return NULL;
+ }
memcpy (h1,
&s[pos],
sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
@@ -555,32 +579,54 @@
(1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) *
2],
"%llu",
&ass.fi.file_length)) )
- return NULL;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed"));
+ return NULL;
+ }
ass.fi.file_length = GNUNET_htonll (ass.fi.file_length);
npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2;
while ((s[npos] != '\0') && (s[npos] != '.'))
npos++;
if (s[npos] == '\0')
- goto ERR;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed"));
+ goto ERR;
+ }
+ npos++;
ret = enc2bin (&s[npos],
&ass.peer,
sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
if (ret == -1)
- goto ERR;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode public
key)"));
+ goto ERR;
+ }
npos += ret;
if (s[npos++] != '.')
- goto ERR;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed (could not find
signature)"));
+ goto ERR;
+ }
ret = enc2bin (&s[npos],
&sig,
sizeof (struct GNUNET_CRYPTO_RsaSignature));
if (ret == -1)
- goto ERR;
- npos += ret;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode
signature)"));
+ goto ERR;
+ }
+ npos += ret;
if (s[npos++] != '.')
- goto ERR;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed"));
+ goto ERR;
+ }
if (1 != SSCANF (&s[npos], "%llu", &exptime))
- goto ERR;
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed (could not parse expiration
time)"));
+ goto ERR;
+ }
ass.purpose.size = htonl(sizeof(struct LocUriAssembly));
ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_NAMESPACE_PLACEMENT);
et.value = exptime;
@@ -590,8 +636,10 @@
&ass.purpose,
&sig,
&ass.peer))
- goto ERR;
-
+ {
+ *emsg = GNUNET_strdup (_("SKS URI malformed (signature failed
validation)"));
+ goto ERR;
+ }
uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
uri->type = loc;
uri->data.loc.fi = ass.fi;
@@ -601,7 +649,6 @@
return uri;
ERR:
- GNUNET_free_non_null (addr);
return NULL;
}
@@ -618,12 +665,20 @@
char **emsg)
{
struct GNUNET_FS_Uri *ret;
+ char *msg;
+ if (NULL == emsg)
+ emsg = &msg;
+ *emsg = NULL;
if ( (NULL != (ret = uri_chk_parse (uri, emsg))) ||
(NULL != (ret = uri_ksk_parse (uri, emsg))) ||
(NULL != (ret = uri_sks_parse (uri, emsg))) ||
(NULL != (ret = uri_loc_parse (uri, emsg))) )
return ret;
+ if (NULL == *emsg)
+ *emsg = GNUNET_strdup (_("Unrecognized URI type"));
+ if (emsg == &msg)
+ GNUNET_free (msg);
return NULL;
}
Modified: gnunet/src/fs/test_fs_collection.c
===================================================================
--- gnunet/src/fs/test_fs_collection.c 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/test_fs_collection.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -28,75 +28,87 @@
#include "gnunet_util_lib.h"
#include "gnunet_fs_service.h"
-#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_break(0); goto FAILURE; }
+static struct GNUNET_CONFIGURATION_Handle *cfg;
-int
-main (int argc, char *argv[])
+static void* progress_cb (void *cls,
+ const struct GNUNET_FS_ProgressInfo *info)
{
- struct GNUNET_CONFIGURATION_Handle *cfg;
- int ok;
- struct GNUNET_ClientServerConnection *sock;
- struct GNUNET_CONTAINER_MetaData *meta;
- struct GNUNET_CONTAINER_MetaData *have;
+ GNUNET_break (0);
+ return NULL;
+}
+
+
+static void
+task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_FS_Namespace *have;
+ struct GNUNET_FS_Namespace *ns;
char *emsg;
struct GNUNET_FS_Uri *uri;
+ struct GNUNET_FS_Handle *fsh;
struct GNUNET_CONTAINER_MetaData *md;
- struct GNUNET_FS_Handle *fsh;
- GNUNET_CRYPTO_random_disable_entropy_gathering ();
- cfg = GNUNET_CONFIGURATION_create ();
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (cfg, "check.conf"))
- {
- GNUNET_CONFIGURATION_destroy (cfg);
- return -1;
- }
- sock = NULL;
- meta = NULL;
- ok = GNUNET_YES;
- meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (meta, EXTRACTOR_MIMETYPE, "test/foo");
-
-
- fsh = GNUNET_FS_start (sched,
+ fsh = GNUNET_FS_start (tc->sched,
cfg,
"test-fs-collection",
&progress_cb,
NULL);
-
- /* ACTUAL TEST CODE */
+ GNUNET_assert (NULL != fsh);
GNUNET_FS_collection_stop (fsh);
- CHECK (NULL == GNUNET_FS_collection_get (fsh));
- CHECK (GNUNET_OK == GNUNET_FS_collection_start (fsh,
- namespace));
+ GNUNET_assert (NULL == GNUNET_FS_collection_get (fsh));
+ ns = GNUNET_FS_namespace_create (fsh, "test-namespace");
+ GNUNET_assert (NULL != ns);
+ GNUNET_assert (GNUNET_OK == GNUNET_FS_collection_start (fsh,
+ ns));
+ GNUNET_FS_namespace_delete (ns, GNUNET_NO);
have = GNUNET_FS_collection_get (fsh);
- CHECK (NULL != have);
- CHECK (GNUNET_CONTAINER_meta_data_test_equal (have, meta));
- GNUNET_CONTAINER_meta_data_destroy (have);
- md = meta;
+ GNUNET_assert (NULL != have);
+ GNUNET_FS_namespace_delete (have, GNUNET_NO);
uri =
- GNUNET_FS_uri_parse
("gnunet://ecrs/chk/0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
&emsg);
+ GNUNET_FS_uri_parse
("gnunet://fs/chk/0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
&emsg);
+ GNUNET_assert (NULL != uri);
+ md = GNUNET_CONTAINER_meta_data_create ();
GNUNET_FS_collection_add (fsh, uri, md);
+ GNUNET_CONTAINER_meta_data_destroy (md);
GNUNET_FS_uri_destroy (uri);
GNUNET_FS_stop (fsh);
- fsh = GNUNET_FS_start (sched, cfg,
+ fsh = GNUNET_FS_start (tc->sched,
+ cfg,
"test-fs-collection",
&progress_cb,
NULL);
have = GNUNET_FS_collection_get (fsh);
- CHECK (NULL != have);
- CHECK (GNUNET_CONTAINER_meta_data_test_equal (have, meta));
- GNUNET_CONTAINER_meta_data_destroy (have);
+ GNUNET_assert (NULL != have);
+ GNUNET_FS_namespace_delete (have, GNUNET_NO);
GNUNET_FS_collection_publish (fsh);
GNUNET_FS_collection_stop (fsh);
- CHECK (NULL == GNUNET_FS_collection_get (fsh));
+ GNUNET_assert (NULL == GNUNET_FS_collection_get (fsh));
GNUNET_FS_stop (fsh);
+}
- /* END OF TEST CODE */
-FAILURE:
- if (meta != NULL)
- GNUNET_CONTAINER_meta_data_destroy (meta);
+
+int
+main (int argc, char *argv[])
+{
+ int ok;
+
+ GNUNET_log_setup ("test_fs_collection",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ GNUNET_CRYPTO_random_disable_entropy_gathering ();
+ cfg = GNUNET_CONFIGURATION_create ();
+ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (cfg,
"test_fs_collection_data.conf"))
+ {
+ GNUNET_CONFIGURATION_destroy (cfg);
+ return -1;
+ }
+ ok = GNUNET_YES;
+ GNUNET_SCHEDULER_run (&task, &ok);
GNUNET_CONFIGURATION_destroy (cfg);
-
return (ok == GNUNET_YES) ? 0 : 1;
}
Added: gnunet/src/fs/test_fs_collection_data.conf
===================================================================
--- gnunet/src/fs/test_fs_collection_data.conf (rev 0)
+++ gnunet/src/fs/test_fs_collection_data.conf 2009-08-22 17:57:31 UTC (rev
8841)
@@ -0,0 +1,9 @@
+[PATHS]
+SERVICEHOME = /tmp/gnunet-test-fs-uri/
+DEFAULTCONFIG = /etc/gnunetd.conf
+
+[gnunetd]
+HOSTKEY = $SERVICEHOME/.hostkey
+
+[TESTING]
+WEAKRANDOM = YES
Modified: gnunet/src/fs/test_fs_directory.c
===================================================================
--- gnunet/src/fs/test_fs_directory.c 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/test_fs_directory.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -152,6 +152,13 @@
int failureCount = 0;
int i;
+ GNUNET_log_setup ("test_fs_directory",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
for (i = 17; i < 2000; i *= 2)
{
fprintf (stderr, ".");
Added: gnunet/src/fs/test_fs_download.c
===================================================================
--- gnunet/src/fs/test_fs_download.c (rev 0)
+++ gnunet/src/fs/test_fs_download.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,324 @@
+/*
+ This file is part of GNUnet.
+ (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
+ 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 applications/fs/fsui/download_persistence_test.c
+ * @brief testcase for fsui download persistence (upload-download)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define DEBUG_VERBOSE GNUNET_NO
+
+#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto
FAILURE; }
+
+static volatile int suspendRestart = 0;
+
+static struct GNUNET_GE_Context *ectx;
+
+static char *
+makeName (unsigned int i)
+{
+ char *fn;
+
+ fn =
+ GNUNET_malloc (strlen
+ ("/tmp/gnunet-fsui-download_persistence_test/FSUITEST") +
+ 14);
+ GNUNET_snprintf (fn,
+ strlen
+ ("/tmp/gnunet-fsui-download_persistence_test/FSUITEST") +
+ 14,
+ "/tmp/gnunet-fsui-download_persistence_test/FSUITEST%u",
+ i);
+ GNUNET_disk_directory_create_for_file (NULL, fn);
+ return fn;
+}
+
+static volatile enum GNUNET_FSUI_EventType lastEvent;
+static volatile enum GNUNET_FSUI_EventType waitForEvent;
+static volatile int download_done;
+static struct GNUNET_FSUI_Context *ctx;
+static struct GNUNET_ECRS_URI *upURI;
+static struct GNUNET_FSUI_DownloadList *download;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event * event)
+{
+ switch (event->type)
+ {
+ case GNUNET_FSUI_download_suspended:
+ download = NULL;
+ break;
+ case GNUNET_FSUI_download_resumed:
+#if DEBUG_VERBOSE
+ printf ("Download resuming\n");
+#endif
+ download = event->data.DownloadResumed.dc.pos;
+ break;
+ case GNUNET_FSUI_upload_progress:
+#if DEBUG_VERBOSE > 1
+ printf ("Upload is progressing (%llu/%llu)...\n",
+ event->data.UploadProgress.completed,
+ event->data.UploadProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_upload_completed:
+ upURI = GNUNET_ECRS_uri_duplicate (event->data.UploadCompleted.uri);
+#if DEBUG_VERBOSE
+ printf ("Upload complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_download_completed:
+#if DEBUG_VERBOSE
+ printf ("Download complete.\n");
+#endif
+ download_done = 1;
+ break;
+ case GNUNET_FSUI_download_progress:
+#if DEBUG_VERBOSE > 1
+ printf ("Download is progressing (%llu/%llu)...\n",
+ event->data.DownloadProgress.completed,
+ event->data.DownloadProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_unindex_progress:
+#if DEBUG_VERBOSE > 1
+ printf ("Unindex is progressing (%llu/%llu)...\n",
+ event->data.UnindexProgress.completed,
+ event->data.UnindexProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_unindex_completed:
+#if DEBUG_VERBOSE
+ printf ("Unindex complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_error:
+ case GNUNET_FSUI_upload_error:
+ case GNUNET_FSUI_download_error:
+ fprintf (stderr, "Received ERROR: %d\n", event->type);
+ GNUNET_GE_BREAK (ectx, 0);
+ break;
+ case GNUNET_FSUI_download_aborted:
+#if DEBUG_VERBOSE
+ printf ("Received download aborted event.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_suspended:
+ case GNUNET_FSUI_upload_suspended:
+#if DEBUG_VERBOSE
+ fprintf (stderr, "Received SUSPENDING: %d\n", event->type);
+#endif
+ break;
+ case GNUNET_FSUI_upload_started:
+ case GNUNET_FSUI_upload_stopped:
+ case GNUNET_FSUI_download_started:
+ case GNUNET_FSUI_download_stopped:
+ case GNUNET_FSUI_unindex_started:
+ case GNUNET_FSUI_unindex_stopped:
+ break;
+ default:
+ printf ("Unexpected event: %d\n", event->type);
+ break;
+ }
+ if (lastEvent == waitForEvent)
+ return NULL; /* ignore all other events */
+ lastEvent = event->type;
+ return NULL;
+}
+
+#define FILESIZE (1024 * 1024 * 2)
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+ pid_t daemon;
+#endif
+ int ok;
+ int i;
+ char *fn = NULL;
+ char *keywords[] = {
+ "down_foo",
+ "down_bar",
+ };
+ int prog;
+ char *buf;
+ struct GNUNET_MetaData *meta = NULL;
+ struct GNUNET_ECRS_URI *kuri = NULL;
+ struct GNUNET_GC_Configuration *cfg;
+ struct GNUNET_FSUI_UnindexList *unindex = NULL;
+ struct GNUNET_FSUI_UploadList *upload = NULL;
+
+ ok = GNUNET_YES;
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+#if START_DAEMON
+ GNUNET_disk_directory_remove (NULL,
+ "/tmp/gnunet-fsui-download_persistence_test/");
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ CHECK (GNUNET_OK ==
+ GNUNET_wait_for_daemon_running (NULL, cfg,
+ 30 * GNUNET_CRON_SECONDS));
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to
start */
+ /* ACTUAL TEST CODE */
+#endif
+ ctx = GNUNET_FSUI_start (NULL,
+ cfg, "fsuidownload_persistence_test", 32,
+ GNUNET_YES, &eventCallback, NULL);
+ CHECK (ctx != NULL);
+
+ /* upload */
+ fn = makeName (42);
+ buf = GNUNET_malloc (FILESIZE);
+ for (i = 0; i < FILESIZE; i++)
+ buf[i] = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 256);
+ GNUNET_disk_file_write (ectx, fn, buf, FILESIZE, "600");
+ GNUNET_free (buf);
+ meta = GNUNET_meta_data_create ();
+ kuri =
+ GNUNET_ECRS_keyword_command_line_to_uri (ectx, 2,
+ (const char **) keywords);
+ waitForEvent = GNUNET_FSUI_upload_completed;
+ upload = GNUNET_FSUI_upload_start (ctx,
+ fn,
+ (GNUNET_FSUI_DirectoryScanCallback) &
+ GNUNET_disk_directory_scan, NULL, 0, 0,
+ GNUNET_YES, GNUNET_NO, GNUNET_NO,
+ GNUNET_get_time () +
+ 5 * GNUNET_CRON_HOURS, meta, kuri, kuri);
+ CHECK (upload != NULL);
+ GNUNET_ECRS_uri_destroy (kuri);
+ kuri = NULL;
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_upload_completed)
+ {
+ prog++;
+ CHECK (prog < 5000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_upload_stop (upload);
+
+ /* download */
+ waitForEvent = GNUNET_FSUI_download_completed;
+ GNUNET_free (fn);
+ fn = makeName (43);
+ download_done = 0;
+ download = GNUNET_FSUI_download_start (ctx,
+ 0,
+ GNUNET_NO,
+ upURI, meta, fn, NULL, NULL);
+ CHECK (download != NULL);
+ GNUNET_free (fn);
+ suspendRestart = 4;
+ prog = 0;
+ while (download_done == 0)
+ {
+ prog++;
+ CHECK (prog < 1000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if ((suspendRestart > 0)
+ && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 4) == 0))
+ {
+#if 1
+#if DEBUG_VERBOSE
+ printf ("Testing FSUI suspend-resume\n");
+#endif
+ GNUNET_FSUI_stop (ctx); /* download possibly incomplete
+ at this point, thus testing resume
*/
+ ctx = GNUNET_FSUI_start (NULL,
+ cfg,
+ "fsuidownload_persistence_test",
+ 32, GNUNET_YES, &eventCallback, NULL);
+#if DEBUG_VERBOSE
+ printf ("Resumed...\n");
+#endif
+#endif
+ suspendRestart--;
+ }
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_download_stop (download);
+ download = NULL;
+
+ /* unindex */
+ waitForEvent = GNUNET_FSUI_unindex_completed;
+ fn = makeName (42);
+ unindex = GNUNET_FSUI_unindex_start (ctx, fn);
+ CHECK (unindex != NULL);
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_unindex_completed)
+ {
+ prog++;
+ CHECK (prog < 5000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ CHECK (lastEvent != GNUNET_FSUI_unindex_error);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ CHECK (lastEvent == GNUNET_FSUI_unindex_completed);
+ /* END OF TEST CODE */
+FAILURE:
+ if (meta != NULL)
+ GNUNET_meta_data_destroy (meta);
+ if (ctx != NULL)
+ {
+ if (unindex != NULL)
+ GNUNET_FSUI_unindex_stop (unindex);
+ if (download != NULL)
+ GNUNET_FSUI_download_stop (download);
+ GNUNET_FSUI_stop (ctx);
+ }
+ if (fn != NULL)
+ {
+ UNLINK (fn);
+ GNUNET_free (fn);
+ }
+ if (kuri != NULL)
+ GNUNET_ECRS_uri_destroy (kuri);
+ fn = makeName (43);
+ /* TODO: verify file 'fn(42)' == file 'fn(43)' */
+ UNLINK (fn);
+ GNUNET_free (fn);
+ if (upURI != NULL)
+ GNUNET_ECRS_uri_destroy (upURI);
+
+#if START_DAEMON
+ GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+#endif
+ GNUNET_GC_free (cfg);
+ return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+/* end of download_persistence_test.c */
Added: gnunet/src/fs/test_fs_download_recursive.c
===================================================================
--- gnunet/src/fs/test_fs_download_recursive.c (rev 0)
+++ gnunet/src/fs/test_fs_download_recursive.c 2009-08-22 17:57:31 UTC (rev
8841)
@@ -0,0 +1,380 @@
+/*
+ This file is part of GNUnet.
+ (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
+ 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 applications/fs/fsui/recursive_download_test.c
+ * @brief testcase for fsui recursive upload-download
+ * @author Christian Grothoff
+ * @author Heikki Lindholm
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define DEBUG_VERBOSE GNUNET_NO
+
+#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto
FAILURE; }
+
+#define FILESIZE (1024 * 1024 * 2)
+/* depth-first directory tree d=dir f=file .=end of level*/
+#define DIRECTORY_TREE_SPEC "dddf.f.d"
+
+static struct GNUNET_GE_Context *ectx;
+
+volatile int download_done;
+
+static char *
+makeName (unsigned int i)
+{
+ char *fn;
+
+ fn =
+ GNUNET_malloc (strlen
+ ("/tmp/gnunet-fsui-recursive_download_test/FSUITEST") +
+ 15);
+ GNUNET_snprintf (fn,
+ strlen
+ ("/tmp/gnunet-fsui-recursive_download_test/FSUITEST") + 15,
+ "/tmp/gnunet-fsui-recursive_download_test/FSUITEST%u/", i);
+ return fn;
+}
+
+static int
+makeHierarchyHelper (const char *current, const char *tree, int index,
+ int check)
+{
+ unsigned int fi, i;
+ int done;
+ char *s, *buf;
+
+ fi = 0;
+ done = 0;
+ while (!done && tree[index] != '\0')
+ {
+ s = GNUNET_malloc (strlen (current) + strlen (DIR_SEPARATOR_STR) + 14);
+ GNUNET_snprintf (s, strlen (current) + strlen (DIR_SEPARATOR_STR) + 14,
+ "%s%s%u", current, DIR_SEPARATOR_STR, fi);
+ switch (tree[index++])
+ {
+ case 'd':
+ if (check)
+ {
+ if (GNUNET_disk_directory_test (NULL, s) == GNUNET_NO)
+ {
+ index = -1;
+ done = 1;
+ }
+ }
+ else
+ {
+ GNUNET_disk_directory_create (NULL, s);
+ }
+ if (!done)
+ index = makeHierarchyHelper (s, tree, index, check);
+ break;
+ case 'f':
+ if (check)
+ {
+ /* TODO: compare file contents */
+ if (GNUNET_disk_directory_test (NULL, s) != GNUNET_NO)
+ {
+ index = -1;
+ done = 1;
+ }
+ }
+ else
+ {
+ buf = GNUNET_malloc (FILESIZE);
+ for (i = 0; i < FILESIZE; i++)
+ buf[i] = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 256);
+ GNUNET_disk_file_write (ectx, s, buf, FILESIZE, "600");
+ GNUNET_free (buf);
+ }
+ break;
+ case '.':
+ done = 1;
+ break;
+ default:
+ break;
+ }
+ GNUNET_free (s);
+ fi++;
+ }
+ return index;
+}
+
+static char *
+makeHierarchy (unsigned int i, const char *tree)
+{
+ char *fn;
+
+ fn = makeName (i);
+ makeHierarchyHelper (fn, tree, 0, 0);
+ return fn;
+}
+
+static int
+checkHierarchy (unsigned int i, const char *tree)
+{
+ char *fn;
+ int res;
+
+ fn = makeName (i);
+ if (GNUNET_disk_directory_test (NULL, fn) != GNUNET_YES)
+ {
+ GNUNET_free (fn);
+ return GNUNET_SYSERR;
+ }
+ res = ((makeHierarchyHelper (fn, tree, 0, 1) == -1) ?
+ GNUNET_SYSERR : GNUNET_OK);
+ GNUNET_free (fn);
+ return res;
+}
+
+
+static volatile enum GNUNET_FSUI_EventType lastEvent;
+static volatile enum GNUNET_FSUI_EventType waitForEvent;
+static struct GNUNET_FSUI_Context *ctx;
+static struct GNUNET_ECRS_URI *upURI;
+static struct GNUNET_FSUI_DownloadList *download;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event * event)
+{
+ switch (event->type)
+ {
+ case GNUNET_FSUI_download_suspended:
+ download = NULL;
+ break;
+ case GNUNET_FSUI_download_resumed:
+ download = event->data.DownloadResumed.dc.pos;
+ break;
+ break;
+ case GNUNET_FSUI_upload_progress:
+#if DEBUG_VERBOSE > 1
+ printf ("Upload is progressing (%llu/%llu)...\n",
+ event->data.UploadProgress.completed,
+ event->data.UploadProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_upload_completed:
+ upURI = GNUNET_ECRS_uri_duplicate (event->data.UploadCompleted.uri);
+#if DEBUG_VERBOSE
+ printf ("Upload of `%s' complete.\n",
+ event->data.UploadCompleted.filename);
+#endif
+ break;
+ case GNUNET_FSUI_download_completed:
+#if DEBUG_VERBOSE
+ printf ("Download of `%s' complete.\n",
+ event->data.DownloadCompleted.filename);
+#endif
+ if (checkHierarchy (43, DIRECTORY_TREE_SPEC) == GNUNET_OK)
+ download_done = 1;
+#if DEBUG_VERBOSE
+ else
+ printf ("Hierarchy check not successful yet...\n");
+#endif
+ break;
+ case GNUNET_FSUI_download_progress:
+#if DEBUG_VERBOSE > 1
+ printf ("Download is progressing (%llu/%llu)...\n",
+ event->data.DownloadProgress.completed,
+ event->data.DownloadProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_unindex_progress:
+#if DEBUG_VERBOSE > 1
+ printf ("Unindex is progressing (%llu/%llu)...\n",
+ event->data.UnindexProgress.completed,
+ event->data.UnindexProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_unindex_completed:
+#if DEBUG_VERBOSE
+ printf ("Unindex complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_error:
+ fprintf (stderr, "Error unindexing: %s\n",
+ event->data.UnindexError.message);
+ break;
+ case GNUNET_FSUI_upload_error:
+ fprintf (stderr, "Error uploading: %s\n",
+ event->data.UploadError.message);
+ break;
+ case GNUNET_FSUI_download_error:
+ fprintf (stderr, "Error downloading: %s\n",
+ event->data.DownloadError.message);
+ break;
+ case GNUNET_FSUI_download_aborted:
+#if DEBUG_VERBOSE
+ printf ("Received download aborted event.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_suspended:
+ case GNUNET_FSUI_upload_suspended:
+ case GNUNET_FSUI_upload_started:
+ case GNUNET_FSUI_upload_stopped:
+ case GNUNET_FSUI_download_started:
+ case GNUNET_FSUI_download_stopped:
+ case GNUNET_FSUI_unindex_started:
+ case GNUNET_FSUI_unindex_stopped:
+ break;
+ default:
+ printf ("Unexpected event: %d\n", event->type);
+ break;
+ }
+ if (lastEvent == waitForEvent)
+ return NULL; /* ignore all other events */
+ lastEvent = event->type;
+ return NULL;
+}
+
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+ pid_t daemon;
+#endif
+ int ok;
+ char *fn = NULL;
+ char *fn43 = NULL;
+ char *keywords[] = {
+ "down_foo",
+ "down_bar",
+ };
+ int prog;
+ struct GNUNET_MetaData *meta = NULL;
+ struct GNUNET_ECRS_URI *kuri = NULL;
+ struct GNUNET_GC_Configuration *cfg;
+ struct GNUNET_FSUI_UploadList *upload = NULL;
+
+ ok = GNUNET_YES;
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+ fprintf(stderr,
+ "Setup...\n");
+#if START_DAEMON
+ GNUNET_disk_directory_remove (NULL,
+ "/tmp/gnunet-fsui-recursive_download_test/");
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ CHECK (GNUNET_OK ==
+ GNUNET_wait_for_daemon_running (NULL, cfg,
+ 30 * GNUNET_CRON_SECONDS));
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to
start */
+ /* ACTUAL TEST CODE */
+#endif
+ ctx = GNUNET_FSUI_start (NULL,
+ cfg, "fsuirecursive_download_test", 32, GNUNET_YES,
+ &eventCallback, NULL);
+ CHECK (ctx != NULL);
+ fn = makeHierarchy (42, DIRECTORY_TREE_SPEC);
+ meta = GNUNET_meta_data_create ();
+ kuri =
+ GNUNET_ECRS_keyword_command_line_to_uri (ectx, 2,
+ (const char **) keywords);
+ fprintf(stderr,
+ "Uploading...\n");
+ waitForEvent = GNUNET_FSUI_upload_completed;
+ upload = GNUNET_FSUI_upload_start (ctx,
+ fn,
+ (GNUNET_FSUI_DirectoryScanCallback) &
+ GNUNET_disk_directory_scan, NULL, 0, 0,
+ GNUNET_YES, GNUNET_NO, GNUNET_NO,
+ GNUNET_get_time () +
+ 5 * GNUNET_CRON_HOURS, meta, kuri, kuri);
+ CHECK (upload != NULL);
+ GNUNET_ECRS_uri_destroy (kuri);
+ kuri = NULL;
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_upload_completed)
+ {
+ prog++;
+ CHECK (prog < 5000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_upload_stop (upload);
+ upload = NULL;
+ CHECK (upURI != NULL);
+
+ fprintf(stderr,
+ "Downloading...\n");
+ waitForEvent = GNUNET_FSUI_download_completed;
+ fn43 = makeName (43);
+ download = GNUNET_FSUI_download_start (ctx,
+ 0,
+ GNUNET_YES,
+ upURI, meta, fn43, NULL, NULL);
+ CHECK (download != NULL);
+ GNUNET_free (fn43);
+ fn43 = NULL;
+ prog = 0;
+ while (!download_done)
+ {
+ prog++;
+ CHECK (prog < 5000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+FAILURE:
+ fprintf(stderr,
+ "Cleanup...\n");
+ if (meta != NULL)
+ GNUNET_meta_data_destroy (meta);
+ if (ctx != NULL)
+ {
+ if (download != NULL)
+ GNUNET_FSUI_download_stop (download);
+ GNUNET_FSUI_stop (ctx);
+ }
+ if (fn != NULL)
+ {
+ GNUNET_disk_directory_remove (NULL, fn);
+ GNUNET_free (fn);
+ }
+ if (kuri != NULL)
+ GNUNET_ECRS_uri_destroy (kuri);
+ fn43 = makeName (43);
+ GNUNET_disk_directory_remove (NULL, fn43);
+ GNUNET_free (fn43);
+ if (upURI != NULL)
+ GNUNET_ECRS_uri_destroy (upURI);
+
+#if START_DAEMON
+ GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+#endif
+ GNUNET_GC_free (cfg);
+ return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+/* end of recursive_download_test.c */
Modified: gnunet/src/fs/test_fs_getopt.c
===================================================================
--- gnunet/src/fs/test_fs_getopt.c 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/test_fs_getopt.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -28,6 +28,13 @@
int
main (int argc, char *argv[])
{
+ GNUNET_log_setup ("test_fs_directory",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
fprintf (stderr, "WARNING: testcase not yet written.\n");
return 0; /* testcase passed */
}
Added: gnunet/src/fs/test_fs_search_persistence.c
===================================================================
--- gnunet/src/fs/test_fs_search_persistence.c (rev 0)
+++ gnunet/src/fs/test_fs_search_persistence.c 2009-08-22 17:57:31 UTC (rev
8841)
@@ -0,0 +1,213 @@
+/*
+ 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 applications/fs/fsui/search_persistence_test.c
+ * @brief testcase for fsui download persistence for search
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define DEBUG_VERBOSE GNUNET_NO
+
+#define UPLOAD_PREFIX "/tmp/gnunet-fsui-search_persistence_test"
+
+#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto
FAILURE; }
+
+static struct GNUNET_GE_Context *ectx;
+
+static struct GNUNET_FSUI_Context *ctx;
+static struct GNUNET_FSUI_SearchList *search;
+static int have_error;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event * event)
+{
+ switch (event->type)
+ {
+ case GNUNET_FSUI_search_suspended:
+ search = NULL;
+ break;
+ case GNUNET_FSUI_search_resumed:
+#if DEBUG_VERBOSE
+ printf ("Search resuming\n");
+#endif
+ search = event->data.SearchResumed.sc.pos;
+ break;
+ case GNUNET_FSUI_search_result:
+#if DEBUG_VERBOSE
+ printf ("Received search result\n");
+#endif
+ break;
+ case GNUNET_FSUI_upload_progress:
+#if DEBUG_VERBOSE
+ printf ("Upload is progressing (%llu/%llu)...\n",
+ event->data.UploadProgress.completed,
+ event->data.UploadProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_upload_completed:
+#if DEBUG_VERBOSE
+ printf ("Upload complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_progress:
+#if DEBUG_VERBOSE
+ printf ("Unindex is progressing (%llu/%llu)...\n",
+ event->data.UnindexProgress.completed,
+ event->data.UnindexProgress.total);
+#endif
+ break;
+ case GNUNET_FSUI_unindex_completed:
+#if DEBUG_VERBOSE
+ printf ("Unindex complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_error:
+ case GNUNET_FSUI_upload_error:
+ case GNUNET_FSUI_download_error:
+ fprintf (stderr, "Received ERROR: %d\n", event->type);
+ GNUNET_GE_BREAK (ectx, 0);
+ break;
+ case GNUNET_FSUI_download_aborted:
+#if DEBUG_VERBOSE
+ printf ("Received download aborted event.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_suspended:
+ case GNUNET_FSUI_upload_suspended:
+#if DEBUG_VERBOSE
+ fprintf (stderr, "Received SUSPENDING: %d\n", event->type);
+#endif
+ break;
+ case GNUNET_FSUI_upload_started:
+ case GNUNET_FSUI_upload_stopped:
+ case GNUNET_FSUI_search_started:
+ case GNUNET_FSUI_search_aborted:
+ case GNUNET_FSUI_search_stopped:
+ case GNUNET_FSUI_search_update:
+ case GNUNET_FSUI_unindex_started:
+ case GNUNET_FSUI_unindex_stopped:
+ break;
+ default:
+ printf ("Unexpected event: %d\n", event->type);
+ break;
+ }
+ return NULL;
+}
+
+#define FILESIZE (1024)
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+ pid_t daemon;
+#endif
+ int ok;
+ struct GNUNET_ECRS_URI *uri = NULL;
+ char *keywords[] = {
+ "down_foo",
+ "down_bar",
+ };
+ char keyword[40];
+ int prog;
+ struct GNUNET_GC_Configuration *cfg;
+ int suspendRestart = 0;
+
+
+ ok = GNUNET_YES;
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+#if START_DAEMON
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ CHECK (GNUNET_OK ==
+ GNUNET_wait_for_daemon_running (NULL, cfg,
+ 30 * GNUNET_CRON_SECONDS));
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to
start */
+ /* ACTUAL TEST CODE */
+#endif
+ ctx = GNUNET_FSUI_start (NULL,
+ cfg, "search_persistence_test", 32, GNUNET_YES,
+ &eventCallback, NULL);
+ CHECK (ctx != NULL);
+ GNUNET_snprintf (keyword, 40, "+%s +%s", keywords[0], keywords[1]);
+ uri = GNUNET_ECRS_keyword_string_to_uri (ectx, keyword);
+ search = GNUNET_FSUI_search_start (ctx, 0, uri);
+ CHECK (search != NULL);
+ prog = 0;
+ suspendRestart = 10;
+ while (prog < 100)
+ {
+ prog++;
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if ((suspendRestart > 0)
+ && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 10) == 0))
+ {
+#if 1
+#if DEBUG_VERBOSE
+ printf ("Testing FSUI suspend-resume\n");
+#endif
+ GNUNET_FSUI_stop (ctx); /* download possibly incomplete
+ at this point, thus testing resume
*/
+ CHECK (search == NULL);
+ ctx = GNUNET_FSUI_start (NULL,
+ cfg,
+ "search_persistence_test", 32, GNUNET_YES,
+ &eventCallback, NULL);
+#if DEBUG_VERBOSE
+ printf ("Resumed...\n");
+#endif
+#endif
+ suspendRestart--;
+ }
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_search_abort (search);
+ GNUNET_FSUI_search_stop (search);
+ search = NULL;
+ /* END OF TEST CODE */
+FAILURE:
+ if (ctx != NULL)
+ GNUNET_FSUI_stop (ctx);
+ if (uri != NULL)
+ GNUNET_ECRS_uri_destroy (uri);
+
+#if START_DAEMON
+ GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+#endif
+ GNUNET_GC_free (cfg);
+ if (have_error)
+ ok = GNUNET_NO;
+ return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+/* end of search_persistence_test.c */
Added: gnunet/src/fs/test_fs_search_ranking.c
===================================================================
--- gnunet/src/fs/test_fs_search_ranking.c (rev 0)
+++ gnunet/src/fs/test_fs_search_ranking.c 2009-08-22 17:57:31 UTC (rev
8841)
@@ -0,0 +1,250 @@
+/*
+ This file is part of GNUnet.
+ (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
+ 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 applications/fs/fsui/search_ranking_test.c
+ * @brief testcase for search ranking (availability, etc)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define CHECK_VERBOSE GNUNET_NO
+
+#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(NULL, 0); goto
FAILURE; }
+
+static char *
+makeName (unsigned int i)
+{
+ char *fn;
+
+ fn =
+ GNUNET_malloc (strlen ("/tmp/gnunet-fsui-searchranktest/FSUITEST") + 14);
+ GNUNET_snprintf (fn,
+ strlen ("/tmp/gnunet-fsui-searchranktest/FSUITEST") + 14,
+ "/tmp/gnunet-fsui-searchranktest/FSUITEST%u", i);
+ GNUNET_disk_directory_create_for_file (NULL, fn);
+ return fn;
+}
+
+static struct GNUNET_FSUI_SearchList *search;
+
+static volatile enum GNUNET_FSUI_EventType lastEvent;
+
+static volatile struct GNUNET_ECRS_URI *uri;
+
+static volatile int availability;
+
+static volatile unsigned int rank;
+
+static volatile enum GNUNET_FSUI_EventType waitForEvent;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event * event)
+{
+ static char unused;
+
+ switch (event->type)
+ {
+ case GNUNET_FSUI_search_resumed:
+ search = event->data.SearchResumed.sc.pos;
+ break;
+ case GNUNET_FSUI_search_suspended:
+ search = NULL;
+ break;
+ case GNUNET_FSUI_search_update:
+ availability = event->data.SearchUpdate.availability_rank;
+ rank = event->data.SearchUpdate.applicability_rank;
+ break;
+ case GNUNET_FSUI_search_paused:
+ case GNUNET_FSUI_search_restarted:
+ break;
+ case GNUNET_FSUI_download_resumed:
+ case GNUNET_FSUI_upload_resumed:
+ case GNUNET_FSUI_unindex_resumed:
+ return &unused;
+ case GNUNET_FSUI_search_result:
+#if CHECK_VERBOSE
+ printf ("Received search result\n");
+#endif
+ uri = GNUNET_ECRS_uri_duplicate (event->data.SearchResult.fi.uri);
+ break;
+ case GNUNET_FSUI_upload_completed:
+#if CHECK_VERBOSE
+ printf ("Upload complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_download_completed:
+#if CHECK_VERBOSE
+ printf ("Download complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_unindex_completed:
+#if CHECK_VERBOSE
+ printf ("Unindex complete.\n");
+#endif
+ break;
+ case GNUNET_FSUI_upload_error:
+ printf ("Upload error.\n");
+ break;
+ case GNUNET_FSUI_download_error:
+ printf ("Download error.\n");
+ break;
+ case GNUNET_FSUI_unindex_error:
+ printf ("Unindex error.\n");
+ break;
+ default:
+ break;
+ }
+ if (lastEvent != waitForEvent)
+ lastEvent = event->type;
+ return NULL;
+}
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+ pid_t daemon;
+#endif
+ int ok;
+ char *fn = NULL;
+ char *keywords[] = {
+ "search_foo",
+ "search_bar",
+ };
+ char keyword[40];
+ int prog;
+ struct GNUNET_MetaData *meta;
+ struct GNUNET_ECRS_URI *kuri;
+ struct GNUNET_GC_Configuration *cfg;
+ struct GNUNET_FSUI_UploadList *upload;
+ struct GNUNET_ECRS_URI *luri;
+ struct GNUNET_FSUI_Context *ctx = NULL;
+
+ ok = GNUNET_YES;
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+#if START_DAEMON
+ GNUNET_disk_directory_remove (NULL, "/tmp/gnunet-fsui-searchranktest/");
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ CHECK (GNUNET_OK ==
+ GNUNET_wait_for_daemon_running (NULL, cfg,
+ 30 * GNUNET_CRON_SECONDS));
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to
start */
+ /* ACTUAL TEST CODE */
+#endif
+ ctx = GNUNET_FSUI_start (NULL,
+ cfg, "fsuisearchranktest", 32, GNUNET_YES,
+ &eventCallback, NULL);
+ CHECK (ctx != NULL);
+ /* upload */
+ fn = makeName (42);
+ GNUNET_disk_file_write (NULL,
+ fn, "foo bar test!", strlen ("foo bar test!"),
+ "600");
+ meta = GNUNET_meta_data_create ();
+ kuri =
+ GNUNET_ECRS_keyword_command_line_to_uri (NULL, 2,
+ (const char **) keywords);
+ waitForEvent = GNUNET_FSUI_upload_completed;
+ upload =
+ GNUNET_FSUI_upload_start (ctx,
+ fn,
+ (GNUNET_FSUI_DirectoryScanCallback) &
+ GNUNET_disk_directory_scan, NULL, 0, 0,
+ GNUNET_YES, GNUNET_NO, GNUNET_NO,
+ GNUNET_get_time () + 5 * GNUNET_CRON_HOURS,
+ meta, kuri, kuri);
+ CHECK (NULL != upload);
+ GNUNET_free (fn);
+ fn = NULL;
+ GNUNET_ECRS_uri_destroy (kuri);
+ GNUNET_meta_data_destroy (meta);
+ prog = 0;
+ while (lastEvent != GNUNET_FSUI_upload_completed)
+ {
+ prog++;
+ if (prog == 10000)
+ {
+ fprintf (stderr,
+ "Upload failed to complete -- last event: %u\n",
+ lastEvent);
+ }
+ CHECK (prog < 10000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ if (GNUNET_shutdown_test () == GNUNET_YES)
+ break;
+ }
+ GNUNET_FSUI_upload_stop (upload);
+
+ /* search */
+ GNUNET_snprintf (keyword, 40, "%s %s", keywords[0], keywords[1]);
+ luri = GNUNET_ECRS_keyword_string_to_uri (NULL, keyword);
+ uri = NULL;
+ search = GNUNET_FSUI_search_start (ctx, 0, luri);
+ GNUNET_ECRS_uri_destroy (luri);
+ luri = NULL;
+ CHECK (NULL != search);
+ GNUNET_FSUI_search_pause (search);
+ GNUNET_FSUI_search_restart (search);
+ while ((uri == NULL) &&
+ (availability < 3) &&
+ (rank != 2) && (GNUNET_shutdown_test () != GNUNET_YES))
+ {
+ prog++;
+ CHECK (prog < 10000);
+ GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+ }
+ GNUNET_FSUI_search_abort (search);
+ GNUNET_FSUI_search_stop (search);
+ CHECK (uri != NULL);
+
+
+ /* END OF TEST CODE */
+FAILURE:
+ if (ctx != NULL)
+ GNUNET_FSUI_stop (ctx);
+ GNUNET_free_non_null (fn);
+ /* TODO: verify file 'fn(42)' == file 'fn(43)' */
+ fn = makeName (42);
+ UNLINK (fn);
+ GNUNET_free (fn);
+ fn = makeName (43);
+ UNLINK (fn);
+ GNUNET_free (fn);
+
+#if START_DAEMON
+ GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+#endif
+ GNUNET_GC_free (cfg);
+ return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+/* end of searchtest.c */
Added: gnunet/src/fs/test_fs_start_stop.c
===================================================================
--- gnunet/src/fs/test_fs_start_stop.c (rev 0)
+++ gnunet/src/fs/test_fs_start_stop.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,89 @@
+/*
+ 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 applications/fs/fsui/fsui_start_stop_test.c
+ * @brief testcase for fsui (start-stop only)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(NULL, 0); goto
FAILURE; }
+
+
+static struct GNUNET_FSUI_Context *ctx;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event * event)
+{
+ return NULL;
+}
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+ pid_t daemon;
+#endif
+ int ok;
+ struct GNUNET_GC_Configuration *cfg;
+
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+#if START_DAEMON
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ CHECK (GNUNET_OK ==
+ GNUNET_wait_for_daemon_running (NULL, cfg,
+ 60 * GNUNET_CRON_SECONDS));
+#endif
+ ok = GNUNET_YES;
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to
start */
+
+ /* ACTUAL TEST CODE */
+ ctx = GNUNET_FSUI_start (NULL, cfg, "fsui_start_stop_test", 32, GNUNET_YES,
/* do resume! */
+ &eventCallback, NULL);
+ CHECK (ctx != NULL);
+ GNUNET_FSUI_stop (ctx);
+ ctx =
+ GNUNET_FSUI_start (NULL, cfg, "fsui_start_stop_test", 32, GNUNET_YES,
+ &eventCallback, NULL);
+ CHECK (ctx != NULL);
+FAILURE:
+ if (ctx != NULL)
+ GNUNET_FSUI_stop (ctx);
+#if START_DAEMON
+ GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+#endif
+ GNUNET_GC_free (cfg);
+
+ return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+/* end of fsui_start_stop_test.c */
Modified: gnunet/src/fs/test_fs_uri.c
===================================================================
--- gnunet/src/fs/test_fs_uri.c 2009-08-21 08:41:21 UTC (rev 8840)
+++ gnunet/src/fs/test_fs_uri.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -38,10 +38,10 @@
struct GNUNET_FS_Uri *ret;
char *emsg;
- if (NULL != GNUNET_FS_uri_parse ("gnunet://ecrs/ksk/++", &emsg))
+ if (NULL != GNUNET_FS_uri_parse ("gnunet://fs/ksk/++", &emsg))
ABORT ();
GNUNET_free (emsg);
- ret = GNUNET_FS_uri_parse ("gnunet://ecrs/ksk/foo+bar", &emsg);
+ ret = GNUNET_FS_uri_parse ("gnunet://fs/ksk/foo+bar", &emsg);
if (ret == NULL)
ABORT ();
if (!GNUNET_FS_uri_test_ksk (ret))
@@ -58,7 +58,7 @@
}
uri = GNUNET_FS_uri_to_string (ret);
- if (0 != strcmp (uri, "gnunet://ecrs/ksk/foo+bar"))
+ if (0 != strcmp (uri, "gnunet://fs/ksk/foo+bar"))
{
GNUNET_free (uri);
GNUNET_FS_uri_destroy (ret);
@@ -80,7 +80,7 @@
struct GNUNET_CONFIGURATION_Handle *cfg;
baseURI =
- GNUNET_FS_uri_parse
("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42",
&emsg);
+ GNUNET_FS_uri_parse
("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42",
&emsg);
GNUNET_assert (baseURI != NULL);
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
@@ -97,6 +97,7 @@
{
GNUNET_break (0);
GNUNET_FS_uri_destroy (baseURI);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
if (!GNUNET_FS_uri_test_loc (uri))
@@ -104,6 +105,7 @@
GNUNET_break (0);
GNUNET_FS_uri_destroy (uri);
GNUNET_FS_uri_destroy (baseURI);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
uri2 = GNUNET_FS_uri_loc_get_uri (uri);
@@ -113,6 +115,7 @@
GNUNET_FS_uri_destroy (uri);
GNUNET_FS_uri_destroy (uri2);
GNUNET_FS_uri_destroy (baseURI);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
GNUNET_FS_uri_destroy (uri2);
@@ -128,6 +131,7 @@
{
GNUNET_break (0);
GNUNET_FS_uri_destroy (uri);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
if (GNUNET_YES != GNUNET_FS_uri_test_equal (uri, uri2))
@@ -135,10 +139,12 @@
GNUNET_break (0);
GNUNET_FS_uri_destroy (uri);
GNUNET_FS_uri_destroy (uri2);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
GNUNET_FS_uri_destroy (uri2);
GNUNET_FS_uri_destroy (uri);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 0;
}
@@ -150,15 +156,18 @@
char *emsg;
if (NULL !=
- GNUNET_FS_uri_parse
("gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK", &emsg))
+ GNUNET_FS_uri_parse ("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK",
&emsg))
ABORT ();
+ GNUNET_free (emsg);
if (NULL !=
- GNUNET_FS_uri_parse
("gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test", &emsg))
+ GNUNET_FS_uri_parse
("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test", &emsg))
ABORT ();
- if (NULL != GNUNET_FS_uri_parse ("gnunet://ecrs/sks/test", &emsg))
+ GNUNET_free (emsg);
+ if (NULL != GNUNET_FS_uri_parse ("gnunet://fs/sks/test", &emsg))
ABORT ();
+ GNUNET_free (emsg);
ret =
- GNUNET_FS_uri_parse
("gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test",
&emsg);
+ GNUNET_FS_uri_parse
("gnunet://fs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test",
&emsg);
if (ret == NULL)
ABORT ();
if (GNUNET_FS_uri_test_ksk (ret))
@@ -174,7 +183,7 @@
uri = GNUNET_FS_uri_to_string (ret);
if (0 != strcmp (uri,
-
"gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test"))
+
"gnunet://fs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test"))
{
GNUNET_FS_uri_destroy (ret);
GNUNET_free (uri);
@@ -193,19 +202,19 @@
char *emsg;
if (NULL !=
- GNUNET_FS_uri_parse
("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42",
&emsg))
+ GNUNET_FS_uri_parse
("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42",
&emsg))
ABORT ();
GNUNET_free (emsg);
if (NULL !=
- GNUNET_FS_uri_parse
("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000",
&emsg))
+ GNUNET_FS_uri_parse
("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000",
&emsg))
ABORT ();
GNUNET_free (emsg);
if (NULL !=
- GNUNET_FS_uri_parse
("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH",
&emsg))
+ GNUNET_FS_uri_parse
("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH",
&emsg))
ABORT ();
GNUNET_free (emsg);
ret =
- GNUNET_FS_uri_parse
("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42",
&emsg);
+ GNUNET_FS_uri_parse
("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42",
&emsg);
if (ret == NULL)
ABORT ();
if (GNUNET_FS_uri_test_ksk (ret))
@@ -226,7 +235,7 @@
uri = GNUNET_FS_uri_to_string (ret);
if (0 != strcmp (uri,
-
"gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"))
+
"gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"))
{
GNUNET_free (uri);
GNUNET_FS_uri_destroy (ret);
@@ -243,14 +252,23 @@
int failureCount = 0;
int i;
+ GNUNET_log_setup ("test_fs_uri",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
GNUNET_CRYPTO_random_disable_entropy_gathering ();
failureCount += testKeyword ();
failureCount += testLocation ();
for (i = 0; i < 255; i++)
{
+ /* fprintf (stderr, "."); */
failureCount += testNamespace (i);
failureCount += testFile (i);
}
+ /* fprintf (stderr, "\n"); */
if (failureCount != 0)
return 1;
return 0;
Added: gnunet/src/fs/test_namespace.c
===================================================================
--- gnunet/src/fs/test_namespace.c (rev 0)
+++ gnunet/src/fs/test_namespace.c 2009-08-22 17:57:31 UTC (rev 8841)
@@ -0,0 +1,136 @@
+/*
+ This file is part of GNUnet.
+ (C) 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
+ 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 applications/fs/ecrs/namespacetest.c
+ * @brief Test for namespace.c
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_ecrs_lib.h"
+#include "ecrs.h"
+
+#define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__);
return 1; }
+#define CHECK(c) { do { if (!(c)) ABORT(); } while(0); }
+
+#define CHECKNAME "gnunet-namespace-test"
+
+static struct GNUNET_GC_Configuration *cfg;
+
+static int match;
+
+static int
+spcb (const GNUNET_ECRS_FileInfo * fi,
+ const GNUNET_HashCode * key, int isRoot, void *closure)
+{
+ struct GNUNET_ECRS_URI *want = closure;
+
+ if (GNUNET_ECRS_uri_test_equal (want, fi->uri))
+ match = 1;
+ else
+ fprintf (stderr,
+ "Namespace search returned unexpected result: \nHAVE: %s\nWANT:
%s...\n",
+ GNUNET_ECRS_uri_to_string (fi->uri),
+ GNUNET_ECRS_uri_to_string (want));
+ return GNUNET_OK;
+}
+
+static int
+tt (void *unused)
+{
+ if (match == 1)
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+}
+
+static int
+testNamespace ()
+{
+ GNUNET_HashCode pid;
+ struct GNUNET_ECRS_URI *adv;
+ struct GNUNET_ECRS_URI *advURI;
+ struct GNUNET_ECRS_URI *rootURI;
+ struct GNUNET_MetaData *meta;
+
+ meta = GNUNET_meta_data_create ();
+ adv = GNUNET_ECRS_keyword_string_to_uri (NULL, "testNamespace");
+ rootURI =
+ GNUNET_ECRS_namespace_create (NULL,
+ cfg,
+ meta,
+ 0, 0,
+ GNUNET_get_time () +
+ 15 * GNUNET_CRON_MINUTES, adv, "root");
+ CHECK (NULL != rootURI);
+ GNUNET_ECRS_uri_get_namespace_from_sks (rootURI, &pid);
+ advURI = GNUNET_ECRS_namespace_add_content (NULL, cfg, &pid, 1, /*
anonymity */
+ 1000, /* priority */
+ 5 * GNUNET_CRON_MINUTES +
+ GNUNET_get_time (),
+ "this", "next", rootURI, meta);
+ CHECK (NULL != advURI);
+ fprintf (stderr, "Starting namespace search...\n");
+ CHECK (GNUNET_OK == GNUNET_ECRS_search (NULL,
+ cfg,
+ advURI, 1, &spcb, rootURI, &tt,
+ NULL));
+ fprintf (stderr, "Completed namespace search...\n");
+ CHECK (GNUNET_OK == GNUNET_ECRS_namespace_delete (NULL, cfg, &pid));
+ CHECK (GNUNET_SYSERR == GNUNET_ECRS_namespace_delete (NULL, cfg, &pid));
+ GNUNET_meta_data_destroy (meta);
+ GNUNET_ECRS_uri_destroy (rootURI);
+ GNUNET_ECRS_uri_destroy (advURI);
+ CHECK (match == 1);
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ pid_t daemon;
+ int failureCount = 0;
+
+ GNUNET_disable_entropy_gathering ();
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+ daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+ GNUNET_GE_ASSERT (NULL, daemon > 0);
+ if (GNUNET_OK !=
+ GNUNET_wait_for_daemon_running (NULL, cfg, 60 * GNUNET_CRON_SECONDS))
+ {
+ failureCount++;
+ }
+ else
+ {
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
+ failureCount += testNamespace ();
+ }
+ GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+
+ return (failureCount == 0) ? 0 : 1;
+}
+
+/* end of namespacetest.c */
Modified: gnunet/src/include/gnunet_fs_service.h
===================================================================
--- gnunet/src/include/gnunet_fs_service.h 2009-08-21 08:41:21 UTC (rev
8840)
+++ gnunet/src/include/gnunet_fs_service.h 2009-08-22 17:57:31 UTC (rev
8841)
@@ -441,45 +441,45 @@
enum GNUNET_FS_Status
{
/**
- * Notification that we have started to share a file structure.
+ * Notification that we have started to publish a file structure.
*/
- GNUNET_FS_STATUS_SHARE_START,
+ GNUNET_FS_STATUS_PUBLISH_START,
/**
* Notification that we have resumed sharing a file structure.
*/
- GNUNET_FS_STATUS_SHARE_RESUME,
+ GNUNET_FS_STATUS_PUBLISH_RESUME,
/**
* Notification that we have suspended sharing a file structure.
*/
- GNUNET_FS_STATUS_SHARE_SUSPEND,
+ GNUNET_FS_STATUS_PUBLISH_SUSPEND,
/**
* Notification that we are making progress sharing a file structure.
*/
- GNUNET_FS_STATUS_SHARE_PROGRESS,
+ GNUNET_FS_STATUS_PUBLISH_PROGRESS,
/**
* Notification that an error was encountered sharing a file structure.
* The application will continue to receive resume/suspend events for
- * this structure until "GNUNET_FS_share_stop" is called.
+ * this structure until "GNUNET_FS_publish_stop" is called.
*/
- GNUNET_FS_STATUS_SHARE_ERROR,
+ GNUNET_FS_STATUS_PUBLISH_ERROR,
/**
* Notification that we completed sharing a file structure.
* The application will continue to receive resume/suspend events for
- * this structure until "GNUNET_FS_share_stop" is called.
+ * this structure until "GNUNET_FS_publish_stop" is called.
*/
- GNUNET_FS_STATUS_SHARE_COMPLETED,
+ GNUNET_FS_STATUS_PUBLISH_COMPLETED,
/**
* Notification that we have stopped
* the process of uploading a file structure; no
* futher events will be generated for this action.
*/
- GNUNET_FS_STATUS_SHARE_STOPPED,
+ GNUNET_FS_STATUS_PUBLISH_STOPPED,
/**
* Notification that we have started this download.
@@ -640,7 +640,7 @@
/**
* Handle for controlling an upload.
*/
-struct GNUNET_FS_ShareContext;
+struct GNUNET_FS_PublishContext;
/**
@@ -662,7 +662,7 @@
/**
- * Handle for detail information about a file that is being shared.
+ * Handle for detail information about a file that is being publishd.
* Specifies metadata, keywords, how to get the contents of the file
* (i.e. data-buffer in memory, filename on disk) and other options.
*/
@@ -682,17 +682,17 @@
union {
/**
- * Values for all "GNUNET_FS_STATUS_SHARE_*" events.
+ * Values for all "GNUNET_FS_STATUS_PUBLISH_*" events.
*/
struct {
/**
* Context for controlling the upload.
*/
- struct GNUNET_FS_ShareContext *sc;
+ struct GNUNET_FS_PublishContext *sc;
/**
- * Information about the file that is being shared.
+ * Information about the file that is being publishd.
*/
const struct GNUNET_FS_FileInformation *fi;
@@ -747,7 +747,7 @@
/**
* These values are only valid for
- * GNUNET_FS_STATUS_SHARE_PROGRESS events.
+ * GNUNET_FS_STATUS_PUBLISH_PROGRESS events.
*/
struct {
@@ -770,7 +770,7 @@
/**
* These values are only valid for
- * GNUNET_FS_STATUS_SHARE_RESUME events.
+ * GNUNET_FS_STATUS_PUBLISH_RESUME events.
*/
struct {
@@ -783,7 +783,7 @@
/**
* These values are only valid for
- * GNUNET_FS_STATUS_SHARE_ERROR events.
+ * GNUNET_FS_STATUS_PUBLISH_ERROR events.
*/
struct {
@@ -796,7 +796,7 @@
} specifics;
- } share;
+ } publish;
/**
@@ -1348,7 +1348,7 @@
* will be passed to future callbacks in the respective
* field in the GNUNET_FS_ProgressInfo struct.
*/
-typedef int (*GNUNET_FS_ProgressCallback)
+typedef void* (*GNUNET_FS_ProgressCallback)
(void *cls,
const struct GNUNET_FS_ProgressInfo *info);
@@ -1388,10 +1388,10 @@
/**
- * Function called on entries in a GNUNET_FS_FileInformation share-structure.
+ * Function called on entries in a GNUNET_FS_FileInformation publish-structure.
*
* @param cls closure
- * @param fi the entry in the share-structure
+ * @param fi the entry in the publish-structure
* @param length length of the file or directory
* @param meta metadata for the file or directory (can be modified)
* @param uri pointer to the keywords that will be used for this entry (can be
modified)
@@ -1415,9 +1415,9 @@
/**
- * Create an entry for a file in a share-structure.
+ * Create an entry for a file in a publish-structure.
*
- * @param filename name of the file or directory to share
+ * @param filename name of the file or directory to publish
* @param meta metadata for the file
* @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
* GNUNET_SYSERR for simulation
@@ -1426,7 +1426,7 @@
* keep this file available? Use 0 for maximum anonymity and
* minimum reliability...
* @param expirationTime when should this content expire?
- * @return share structure entry for the file
+ * @return publish structure entry for the file
*/
struct GNUNET_FS_FileInformation *
GNUNET_FS_file_information_create_from_file (void *client_info,
@@ -1439,7 +1439,7 @@
/**
- * Create an entry for a file in a share-structure.
+ * Create an entry for a file in a publish-structure.
*
* @param length length of the file
* @param data data for the file (should not be used afterwards by
@@ -1452,7 +1452,7 @@
* keep this file available? Use 0 for maximum anonymity and
* minimum reliability...
* @param expirationTime when should this content expire?
- * @return share structure entry for the file
+ * @return publish structure entry for the file
*/
struct GNUNET_FS_FileInformation *
GNUNET_FS_file_information_create_from_data (void *client_info,
@@ -1489,7 +1489,7 @@
/**
- * Create an entry for a file in a share-structure.
+ * Create an entry for a file in a publish-structure.
*
* @param length length of the file
* @param reader function that can be used to obtain the data for the file
@@ -1504,7 +1504,7 @@
* keep this file available? Use 0 for maximum anonymity and
* minimum reliability...
* @param expirationTime when should this content expire?
- * @return share structure entry for the file
+ * @return publish structure entry for the file
*/
struct GNUNET_FS_FileInformation *
GNUNET_FS_file_information_create_from_reader (void *client_info,
@@ -1555,7 +1555,7 @@
/**
* Simple, useful default implementation of a directory scanner
* (GNUNET_FS_DirectoryScanner). This implementation expects to get a
- * UNIX filename, will share all files in the directory except hidden
+ * UNIX filename, will publish all files in the directory except hidden
* files (those starting with a "."). Metadata will be extracted
* using GNU libextractor; the specific list of plugins should be
* specified in "cls", passing NULL will disable (!) metadata
@@ -1578,7 +1578,7 @@
/**
- * Create a share-structure from an existing file hierarchy, inferring
+ * Create a publish-structure from an existing file hierarchy, inferring
* and organizing keywords and metadata as much as possible. This
* function primarily performs the recursive build and re-organizes
* keywords and metadata; for automatically getting metadata
@@ -1595,7 +1595,7 @@
* keep this file available? Use 0 for maximum anonymity and
* minimum reliability...
* @param expirationTime when should this content expire?
- * @return share structure entry for the directory, NULL on error
+ * @return publish structure entry for the directory, NULL on error
*/
struct GNUNET_FS_FileInformation *
GNUNET_FS_file_information_create_from_directory (void *client_info,
@@ -1607,7 +1607,7 @@
/**
- * Create an entry for an empty directory in a share-structure.
+ * Create an entry for an empty directory in a publish-structure.
* This function should be used by applications for which the
* use of "GNUNET_FS_file_information_create_from_directory"
* is not appropriate.
@@ -1620,7 +1620,7 @@
* keep this file available? Use 0 for maximum anonymity and
* minimum reliability...
* @param expirationTime when should this content expire?
- * @return share structure entry for the directory , NULL on error
+ * @return publish structure entry for the directory , NULL on error
*/
struct GNUNET_FS_FileInformation *
GNUNET_FS_file_information_create_empty_directory (void *client_info,
@@ -1632,9 +1632,9 @@
/**
- * Add an entry to a directory in a share-structure. Clients
- * should never modify share structures that were passed to
- * "GNUNET_FS_share_start" already.
+ * Add an entry to a directory in a publish-structure. Clients
+ * should never modify publish structures that were passed to
+ * "GNUNET_FS_publish_start" already.
*
* @param dir the directory
* @param end the entry to add; the entry must not have been
@@ -1648,9 +1648,9 @@
/**
- * Inspect a file or directory in a share-structure. Clients
- * should never modify share structures that were passed to
- * "GNUNET_FS_share_start" already. When called on a directory,
+ * Inspect a file or directory in a publish-structure. Clients
+ * should never modify publish structures that were passed to
+ * "GNUNET_FS_publish_start" already. When called on a directory,
* this function will FIRST call "proc" with information about
* the directory itself and then for each of the files in the
* directory (but not for files in subdirectories). When called
@@ -1668,8 +1668,8 @@
/**
- * Destroy share-structure. Clients should never destroy share
- * structures that were passed to "GNUNET_FS_share_start" already.
+ * Destroy publish-structure. Clients should never destroy publish
+ * structures that were passed to "GNUNET_FS_publish_start" already.
*
* @param fi structure to destroy
* @param cleaner function to call on each entry in the structure
@@ -1684,21 +1684,21 @@
/**
- * Share a file or directory.
+ * Publish a file or directory.
*
* @param h handle to the file sharing subsystem
* @param ctx initial value to use for the '*ctx'
- * in the callback (for the GNUNET_FS_STATUS_SHARE_START event).
- * @param fi information about the file or directory structure to share
- * @param namespace namespace to share the file in, NULL for no namespace
- * @param nid identifier to use for the shared content in the namespace
+ * in the callback (for the GNUNET_FS_STATUS_PUBLISH_START event).
+ * @param fi information about the file or directory structure to publish
+ * @param namespace namespace to publish the file in, NULL for no namespace
+ * @param nid identifier to use for the publishd content in the namespace
* (can be NULL, must be NULL if namespace is NULL)
* @param nuid update-identifier that will be used for future updates
* (can be NULL, must be NULL if namespace or nid is NULL)
- * @return context that can be used to control the share operation
+ * @return context that can be used to control the publish operation
*/
-struct GNUNET_FS_ShareContext *
-GNUNET_FS_share_start (struct GNUNET_FS_Handle *h,
+struct GNUNET_FS_PublishContext *
+GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h,
void *ctx,
const struct GNUNET_FS_FileInformation *fi,
struct GNUNET_FS_Namespace *namespace,
@@ -1708,13 +1708,13 @@
/**
* Stop an upload. Will abort incomplete uploads (but
- * not remove blocks that have already been shared) or
+ * not remove blocks that have already been publishd) or
* simply clean up the state for completed uploads.
*
* @param sc context for the upload to stop
*/
void
-GNUNET_FS_share_stop (struct GNUNET_FS_ShareContext *sc);
+GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *sc);
/**
@@ -1840,9 +1840,8 @@
* @param h handle to the file sharing subsystem
* @param cb function to call on each known namespace
* @param cb_cls closure for cb
- * @return GNUNET_SYSERR on error, otherwise the number of pseudonyms in list
*/
-int
+void
GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
GNUNET_FS_NamespaceInfoProcessor cb,
void *cb_cls);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r8841 - in gnunet: . src/fs src/include,
gnunet <=