[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r6162 - in GNUnet: . libltdl src/applications src/applicati
From: |
gnunet |
Subject: |
[GNUnet-SVN] r6162 - in GNUnet: . libltdl src/applications src/applications/fs src/applications/fs/ecrs src/applications/fs/gap src/applications/fs/lib src/applications/stats src/include src/server |
Date: |
Wed, 6 Feb 2008 00:11:29 -0700 (MST) |
Author: grothoff
Date: 2008-02-06 00:11:29 -0700 (Wed, 06 Feb 2008)
New Revision: 6162
Removed:
GNUnet/src/applications/gap/
GNUnet/src/include/gnunet_gap_service.h
Modified:
GNUnet/ChangeLog
GNUnet/configure.ac
GNUnet/libltdl/ltdl.c
GNUnet/libltdl/ltmain.sh
GNUnet/src/applications/Makefile.am
GNUnet/src/applications/fs/Makefile.am
GNUnet/src/applications/fs/ecrs/download.c
GNUnet/src/applications/fs/ecrs/search.c
GNUnet/src/applications/fs/gap/plan.c
GNUnet/src/applications/fs/lib/fslib.c
GNUnet/src/applications/stats/clientapi.c
GNUnet/src/include/Makefile.am
GNUnet/src/include/ecrs_core.h
GNUnet/src/include/fs.h
GNUnet/src/include/gnunet_core.h
GNUnet/src/include/gnunet_dht_service.h
GNUnet/src/include/gnunet_fs_lib.h
GNUnet/src/include/gnunet_protocols.h
GNUnet/src/server/core.c
GNUnet/todo
Log:
uploading draft of new gap/fs code
Modified: GNUnet/ChangeLog
===================================================================
--- GNUnet/ChangeLog 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/ChangeLog 2008-02-06 07:11:29 UTC (rev 6162)
@@ -1,3 +1,14 @@
+Sun Feb 3 13:17:09 MST 2008
+ Dramatic changes to the GAP implementation (breaking
+ protocol compatibility). Essentially, we can save
+ a few bytes in each reply. More importantly, the new
+ code allows the searching client to specify a set of
+ replies that are not desired (hopefully helping to
+ dramatically increase the diversity of search replies
+ obtained over time). Note that the actual encoding
+ and databases are not affected (just P2P protocol).
+ The update is not complete yet, but should compile.
+
Tue Jan 8 20:07:20 MST 2008
Added option for testing ("make check") to use weak(er)
PRNG for key generation (thanks to Werner Koch for
Modified: GNUnet/configure.ac
===================================================================
--- GNUnet/configure.ac 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/configure.ac 2008-02-06 07:11:29 UTC (rev 6162)
@@ -863,11 +863,10 @@
src/applications/fs/ecrs/Makefile
src/applications/fs/fsui/Makefile
src/applications/fs/lib/Makefile
-src/applications/fs/module/Makefile
+src/applications/fs/gap/Makefile
src/applications/fs/namespace/Makefile
src/applications/fs/uritrack/Makefile
src/applications/fs/tools/Makefile
-src/applications/gap/Makefile
src/applications/getoption/Makefile
src/applications/identity/Makefile
src/applications/kvstore_sqlite/Makefile
Modified: GNUnet/libltdl/ltdl.c
===================================================================
--- GNUnet/libltdl/ltdl.c 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/libltdl/ltdl.c 2008-02-06 07:11:29 UTC (rev 6162)
@@ -1,4560 +0,0 @@
-/* ltdl.c -- system independent dlopen wrapper
- Copyright (C) 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc.
- Originally by Thomas Tanner <address@hidden>
- This file is part of GNU Libtool.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-As a special exception to the GNU Lesser General Public License,
-if you distribute this file as part of a program or library that
-is built using GNU libtool, you may include it under the same
-distribution terms that you use for the rest of that program.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA
-
-*/
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if HAVE_STDIO_H
-# include <stdio.h>
-#endif
-
-/* Include the header defining malloc. On K&R C compilers,
- that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */
-#if HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-# if HAVE_GNUNET_malloc_H
-# include <malloc.h>
-# endif
-#endif
-
-#if HAVE_STRING_H
-# include <string.h>
-#else
-# if HAVE_STRINGS_H
-# include <strings.h>
-# endif
-#endif
-
-#if HAVE_CTYPE_H
-# include <ctype.h>
-#endif
-
-#if HAVE_MEMORY_H
-# include <memory.h>
-#endif
-
-#if HAVE_ERRNO_H
-# include <errno.h>
-#endif
-
-
-#ifndef __WINDOWS__
-# ifdef __WIN32__
-# define __WINDOWS__
-# endif
-#endif
-
-
-#undef LT_USE_POSIX_DIRENT
-#ifdef HAVE_CLOSEDIR
-# ifdef HAVE_OPENDIR
-# ifdef HAVE_READDIR
-# ifdef HAVE_DIRENT_H
-# define LT_USE_POSIX_DIRENT
-# endif /* HAVE_DIRENT_H */
-# endif /* HAVE_READDIR */
-# endif /* HAVE_OPENDIR */
-#endif /* HAVE_CLOSEDIR */
-
-
-#undef LT_USE_WINDOWS_DIRENT_EMULATION
-#ifndef LT_USE_POSIX_DIRENT
-# ifdef __WINDOWS__
-# define LT_USE_WINDOWS_DIRENT_EMULATION
-# endif /* __WINDOWS__ */
-#endif /* LT_USE_POSIX_DIRENT */
-
-
-#ifdef LT_USE_POSIX_DIRENT
-# include <dirent.h>
-# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
-#else
-# ifdef LT_USE_WINDOWS_DIRENT_EMULATION
-# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
-# else
-# define dirent direct
-# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-# endif
-#endif
-
-#if HAVE_ARGZ_H
-# include <argz.h>
-#endif
-
-#if HAVE_ASSERT_H
-# include <assert.h>
-#else
-# define assert(arg) ((void) 0)
-#endif
-
-#include "ltdl.h"
-
-#if WITH_DGNUNET_malloc
-# include <dmalloc.h>
-#endif
-
-
-
-
-/* --- WINDOWS SUPPORT --- */
-
-
-#ifdef DLL_EXPORT
-# define LT_GLOBAL_DATA __declspec(dllexport)
-#else
-# define LT_GLOBAL_DATA
-#endif
-
-/* fopen() mode flags for reading a text file */
-#undef LT_READTEXT_MODE
-#ifdef __WINDOWS__
-# define LT_READTEXT_MODE "rt"
-#else
-# define LT_READTEXT_MODE "r"
-#endif
-
-#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
-
-#include <windows.h>
-
-#define dirent lt_dirent
-#define DIR lt_DIR
-
-struct dirent
-{
- char d_name[2048];
- int d_namlen;
-};
-
-typedef struct _DIR
-{
- HANDLE hSearch;
- WIN32_FIND_DATA Win32FindData;
- BOOL firsttime;
- struct dirent file_info;
-} DIR;
-
-#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
-
-
-/* --- MANIFEST CONSTANTS --- */
-
-
-/* Standard libltdl search path environment variable name */
-#undef LTDL_SEARCHPATH_VAR
-#define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
-
-/* Standard libtool archive file extension. */
-#undef LTDL_ARCHIVE_EXT
-#define LTDL_ARCHIVE_EXT ".la"
-
-/* max. filename length */
-#ifndef LT_FILENAME_MAX
-# define LT_FILENAME_MAX 1024
-#endif
-
-/* This is the maximum symbol size that won't require malloc/free */
-#undef LT_SYMBOL_LENGTH
-#define LT_SYMBOL_LENGTH 128
-
-/* This accounts for the _LTX_ separator */
-#undef LT_SYMBOL_OVERHEAD
-#define LT_SYMBOL_OVERHEAD 5
-
-
-
-
-/* --- MEMORY HANDLING --- */
-
-
-/* These are the functions used internally. In addition to making
- use of the associated function pointers above, they also perform
- error handling. */
-static char *lt_estrdup LT_PARAMS ((const char *str));
-static lt_ptr lt_emalloc LT_PARAMS ((size_t size));
-static lt_ptr lt_erealloc LT_PARAMS ((lt_ptr addr, size_t size));
-
-/* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
-#define rpl_realloc realloc
-
-/* These are the pointers that can be changed by the caller: */
-LT_GLOBAL_DATA
-lt_ptr (*lt_dlmalloc)
-LT_PARAMS ((size_t size)) = (lt_ptr (*)LT_PARAMS ((size_t))) malloc;
- LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)
- LT_PARAMS ((lt_ptr ptr, size_t size)) =
- (lt_ptr (*)LT_PARAMS ((lt_ptr, size_t))) rpl_realloc;
- LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS ((lt_ptr ptr)) =
- (void (*)LT_PARAMS ((lt_ptr))) free;
-
-/* The following macros reduce the amount of typing needed to cast
- assigned memory. */
-#if WITH_DGNUNET_malloc
-
-#define LT_DLGNUNET_malloc(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
-#define LT_DLGNUNET_realloc(tp, p, n) ((tp *) xrealloc ((p), (n) *
sizeof(tp)))
-#define LT_DLGNUNET_free(p) \
- LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
-
-#define LT_EGNUNET_malloc(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
-#define LT_EGNUNET_realloc(tp, p, n) ((tp *) xrealloc ((p), (n) *
sizeof(tp)))
-
-#else
-
-#define LT_DLGNUNET_malloc(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
-#define LT_DLGNUNET_realloc(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) *
sizeof(tp)))
-#define LT_DLGNUNET_free(p) \
- LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
-
-#define LT_EGNUNET_malloc(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
-#define LT_EGNUNET_realloc(tp, p, n) ((tp *) lt_erealloc ((p), (n) *
sizeof(tp)))
-
-#endif
-
-#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
- if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
- } LT_STMT_END
-
-
-/* --- REPLACEMENT FUNCTIONS --- */
-
-
-#undef strdup
-#define strdup rpl_strdup
-
- static char *strdup LT_PARAMS ((const char *str));
-
- static char *strdup (str)
- const char *str;
-{
- char *tmp = 0;
-
- if (str)
- {
- tmp = LT_DLGNUNET_malloc (char, 1 + strlen (str));
- if (tmp)
- {
- strcpy (tmp, str);
- }
- }
-
- return tmp;
-}
-
-
-#if ! HAVE_STRCMP
-
-#undef strcmp
-#define strcmp rpl_strcmp
-
-static int strcmp LT_PARAMS ((const char *str1, const char *str2));
-
-static int
-strcmp (str1, str2)
- const char *str1;
- const char *str2;
-{
- if (str1 == str2)
- return 0;
- if (str1 == 0)
- return -1;
- if (str2 == 0)
- return 1;
-
- for (; *str1 && *str2; ++str1, ++str2)
- {
- if (*str1 != *str2)
- break;
- }
-
- return (int) (*str1 - *str2);
-}
-#endif
-
-
-#if ! HAVE_STRCHR
-
-# if HAVE_INDEX
-# define strchr index
-# else
-# define strchr rpl_strchr
-
-static const char *strchr LT_PARAMS ((const char *str, int ch));
-
-static const char *
-strchr (str, ch)
- const char *str;
- int ch;
-{
- const char *p;
-
- for (p = str; *p != (char) ch && *p != LT_EOS_CHAR; ++p)
- /*NOWORK*/;
-
- return (*p == (char) ch) ? p : 0;
-}
-
-# endif
-#endif /* !HAVE_STRCHR */
-
-
-#if ! HAVE_STRRCHR
-
-# if HAVE_RINDEX
-# define strrchr rindex
-# else
-# define strrchr rpl_strrchr
-
-static const char *strrchr LT_PARAMS ((const char *str, int ch));
-
-static const char *
-strrchr (str, ch)
- const char *str;
- int ch;
-{
- const char *p, *q = 0;
-
- for (p = str; *p != LT_EOS_CHAR; ++p)
- {
- if (*p == (char) ch)
- {
- q = p;
- }
- }
-
- return q;
-}
-
-# endif
-#endif
-
-/* NOTE: Neither bcopy nor the memcpy implementation below can
- reliably handle copying in overlapping areas of memory. Use
- memmove (for which there is a fallback implmentation below)
- if you need that behaviour. */
-#if ! HAVE_MEMCPY
-
-# if HAVE_BCOPY
-# define memcpy(dest, src, size) bcopy (src, dest, size)
-# else
-# define memcpy rpl_memcpy
-
-static lt_ptr memcpy LT_PARAMS ((lt_ptr dest, const lt_ptr src, size_t size));
-
-static lt_ptr
-memcpy (dest, src, size)
- lt_ptr dest;
- const lt_ptr src;
- size_t size;
-{
- const char *s = src;
- char *d = dest;
- size_t i = 0;
-
- for (i = 0; i < size; ++i)
- {
- d[i] = s[i];
- }
-
- return dest;
-}
-
-# endif /* !HAVE_BCOPY */
-#endif /* !HAVE_MEMCPY */
-
-#if ! HAVE_MEMMOVE
-# define memmove rpl_memmove
-
-static lt_ptr memmove
-LT_PARAMS ((lt_ptr dest, const lt_ptr src, size_t size));
-
-static lt_ptr
-memmove (dest, src, size)
- lt_ptr dest;
- const lt_ptr src;
- size_t size;
-{
- const char *s = src;
- char *d = dest;
- size_t i;
-
- if (d < s)
- for (i = 0; i < size; ++i)
- {
- d[i] = s[i];
- }
- else if (d > s && size > 0)
- for (i = size - 1;; --i)
- {
- d[i] = s[i];
- if (i == 0)
- break;
- }
-
- return dest;
-}
-
-#endif /* !HAVE_MEMMOVE */
-
-#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
-
-static void closedir LT_PARAMS ((DIR * entry));
-
-static void
-closedir (entry)
- DIR *entry;
-{
- assert (entry != (DIR *) NULL);
- FindClose (entry->hSearch);
- lt_dlfree ((lt_ptr) entry);
-}
-
-
-static DIR *opendir LT_PARAMS ((const char *path));
-
-static DIR *
-opendir (path)
- const char *path;
-{
- char file_specification[LT_FILENAME_MAX];
- DIR *entry;
-
- assert (path != (char *) NULL);
- /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
- (void) strncpy (file_specification, path, LT_FILENAME_MAX - 6);
- file_specification[LT_FILENAME_MAX - 6] = LT_EOS_CHAR;
- (void) strcat (file_specification, "\\");
- entry = LT_DLGNUNET_malloc (DIR, sizeof (DIR));
- if (entry != (DIR *) 0)
- {
- entry->firsttime = TRUE;
- entry->hSearch =
- FindFirstFile (file_specification, &entry->Win32FindData);
- }
- if (entry->hSearch == INVALID_HANDLE_VALUE)
- {
- (void) strcat (file_specification, "\\*.*");
- entry->hSearch =
- FindFirstFile (file_specification, &entry->Win32FindData);
- if (entry->hSearch == INVALID_HANDLE_VALUE)
- {
- LT_DLGNUNET_free (entry);
- return (DIR *) 0;
- }
- }
- return (entry);
-}
-
-
-static struct dirent *readdir LT_PARAMS ((DIR * entry));
-
-static struct dirent *
-readdir (entry)
- DIR *entry;
-{
- int status;
-
- if (entry == (DIR *) 0)
- return ((struct dirent *) 0);
- if (!entry->firsttime)
- {
- status = FindNextFile (entry->hSearch, &entry->Win32FindData);
- if (status == 0)
- return ((struct dirent *) 0);
- }
- entry->firsttime = FALSE;
- (void) strncpy (entry->file_info.d_name, entry->Win32FindData.cFileName,
- LT_FILENAME_MAX - 1);
- entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
- entry->file_info.d_namlen = strlen (entry->file_info.d_name);
- return (&entry->file_info);
-}
-
-#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
-
-/* According to Alexandre Oliva <address@hidden>,
- ``realloc is not entirely portable''
- In any case we want to use the allocator supplied by the user without
- burdening them with an lt_dlrealloc function pointer to maintain.
- Instead implement our own version (with known boundary conditions)
- using lt_dlmalloc and lt_dlfree. */
-
-/* #undef realloc
- #define realloc rpl_realloc
-*/
-#if 0
- /* You can't (re)define realloc unless you also (re)define malloc.
- Right now, this code uses the size of the *destination* to decide
- how much to copy. That's not right, but you can't know the size
- of the source unless you know enough about, or wrote malloc. So
- this code is disabled... */
-
-static lt_ptr
-realloc (ptr, size)
- lt_ptr ptr;
- size_t size;
-{
- if (size == 0)
- {
- /* For zero or less bytes, free the original memory */
- if (ptr != 0)
- {
- lt_dlfree (ptr);
- }
-
- return (lt_ptr) 0;
- }
- else if (ptr == 0)
- {
- /* Allow reallocation of a NULL pointer. */
- return lt_dlmalloc (size);
- }
- else
- {
- /* Allocate a new block, copy and free the old block. */
- lt_ptr mem = lt_dlmalloc (size);
-
- if (mem)
- {
- memcpy (mem, ptr, size);
- lt_dlfree (ptr);
- }
-
- /* Note that the contents of PTR are not damaged if there is
- insufficient memory to realloc. */
- return mem;
- }
-}
-#endif
-
-
-#if ! HAVE_ARGZ_GNUNET_array_append
-# define argz_append rpl_argz_append
-
-static error_t argz_append LT_PARAMS ((char **pargz, size_t * pargz_len,
- const char *buf, size_t buf_len));
-
-static error_t
-argz_append (pargz, pargz_len, buf, buf_len)
- char **pargz;
- size_t *pargz_len;
- const char *buf;
- size_t buf_len;
-{
- size_t argz_len;
- char *argz;
-
- assert (pargz);
- assert (pargz_len);
- assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
-
- /* If nothing needs to be appended, no more work is required. */
- if (buf_len == 0)
- return 0;
-
- /* Ensure there is enough room to append BUF_LEN. */
- argz_len = *pargz_len + buf_len;
- argz = LT_DLGNUNET_realloc (char, *pargz, argz_len);
- if (!argz)
- return ENOMEM;
-
- /* Copy characters from BUF after terminating '\0' in ARGZ. */
- memcpy (argz + *pargz_len, buf, buf_len);
-
- /* Assign new values. */
- *pargz = argz;
- *pargz_len = argz_len;
-
- return 0;
-}
-#endif /* !HAVE_ARGZ_GNUNET_array_append */
-
-
-#if ! HAVE_ARGZ_CREATE_SEP
-# define argz_create_sep rpl_argz_create_sep
-
-static error_t argz_create_sep LT_PARAMS ((const char *str, int delim,
- char **pargz, size_t * pargz_len));
-
-static error_t
-argz_create_sep (str, delim, pargz, pargz_len)
- const char *str;
- int delim;
- char **pargz;
- size_t *pargz_len;
-{
- size_t argz_len;
- char *argz = 0;
-
- assert (str);
- assert (pargz);
- assert (pargz_len);
-
- /* Make a copy of STR, but replacing each occurrence of
- DELIM with '\0'. */
- argz_len = 1 + LT_STRLEN (str);
- if (argz_len)
- {
- const char *p;
- char *q;
-
- argz = LT_DLGNUNET_malloc (char, argz_len);
- if (!argz)
- return ENOMEM;
-
- for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
- {
- if (*p == delim)
- {
- /* Ignore leading delimiters, and fold consecutive
- delimiters in STR into a single '\0' in ARGZ. */
- if ((q > argz) && (q[-1] != LT_EOS_CHAR))
- *q++ = LT_EOS_CHAR;
- else
- --argz_len;
- }
- else
- *q++ = *p;
- }
- /* Copy terminating LT_EOS_CHAR. */
- *q = *p;
- }
-
- /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
- if (!argz_len)
- LT_DLGNUNET_free (argz);
-
- /* Assign new values. */
- *pargz = argz;
- *pargz_len = argz_len;
-
- return 0;
-}
-#endif /* !HAVE_ARGZ_CREATE_SEP */
-
-
-#if ! HAVE_ARGZ_INSERT
-# define argz_insert rpl_argz_insert
-
-static error_t argz_insert LT_PARAMS ((char **pargz, size_t * pargz_len,
- char *before, const char *entry));
-
-static error_t
-argz_insert (pargz, pargz_len, before, entry)
- char **pargz;
- size_t *pargz_len;
- char *before;
- const char *entry;
-{
- assert (pargz);
- assert (pargz_len);
- assert (entry && *entry);
-
- /* No BEFORE address indicates ENTRY should be inserted after the
- current last element. */
- if (!before)
- return argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
-
- /* This probably indicates a programmer error, but to preserve
- semantics, scan back to the start of an entry if BEFORE points
- into the middle of it. */
- while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
- --before;
-
- {
- size_t entry_len = 1 + LT_STRLEN (entry);
- size_t argz_len = *pargz_len + entry_len;
- size_t offset = before - *pargz;
- char *argz = LT_DLGNUNET_realloc (char, *pargz, argz_len);
-
- if (!argz)
- return ENOMEM;
-
- /* Make BEFORE point to the equivalent offset in ARGZ that it
- used to have in *PARGZ incase realloc() moved the block. */
- before = argz + offset;
-
- /* Move the ARGZ entries starting at BEFORE up into the new
- space at the end -- making room to copy ENTRY into the
- resulting gap. */
- memmove (before + entry_len, before, *pargz_len - offset);
- memcpy (before, entry, entry_len);
-
- /* Assign new values. */
- *pargz = argz;
- *pargz_len = argz_len;
- }
-
- return 0;
-}
-#endif /* !HAVE_ARGZ_INSERT */
-
-
-#if ! HAVE_ARGZ_NEXT
-# define argz_next rpl_argz_next
-
-static char *argz_next LT_PARAMS ((char *argz, size_t argz_len,
- const char *entry));
-
-static char *
-argz_next (argz, argz_len, entry)
- char *argz;
- size_t argz_len;
- const char *entry;
-{
- assert ((argz && argz_len) || (!argz && !argz_len));
-
- if (entry)
- {
- /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
- within the ARGZ vector. */
- assert ((!argz && !argz_len)
- || ((argz <= entry) && (entry < (argz + argz_len))));
-
- /* Move to the char immediately after the terminating
- '\0' of ENTRY. */
- entry = 1 + strchr (entry, LT_EOS_CHAR);
-
- /* Return either the new ENTRY, or else NULL if ARGZ is
- exhausted. */
- return (entry >= argz + argz_len) ? 0 : (char *) entry;
- }
- else
- {
- /* This should probably be flagged as a programmer error,
- since starting an argz_next loop with the iterator set
- to ARGZ is safer. To preserve semantics, handle the NULL
- case by returning the start of ARGZ (if any). */
- if (argz_len > 0)
- return argz;
- else
- return 0;
- }
-}
-#endif /* !HAVE_ARGZ_NEXT */
-
-
-
-#if ! HAVE_ARGZ_STRINGIFY
-# define argz_stringify rpl_argz_stringify
-
-static void argz_stringify LT_PARAMS ((char *argz, size_t argz_len, int sep));
-
-static void
-argz_stringify (argz, argz_len, sep)
- char *argz;
- size_t argz_len;
- int sep;
-{
- assert ((argz && argz_len) || (!argz && !argz_len));
-
- if (sep)
- {
- --argz_len; /* don't stringify the terminating EOS */
- while (--argz_len > 0)
- {
- if (argz[argz_len] == LT_EOS_CHAR)
- argz[argz_len] = sep;
- }
- }
-}
-#endif /* !HAVE_ARGZ_STRINGIFY */
-
-
-
-
-/* --- TYPE DEFINITIONS -- */
-
-
-/* This type is used for the array of caller data sets in each handler. */
-typedef struct
-{
- lt_dlcaller_id key;
- lt_ptr data;
-} lt_caller_data;
-
-
-
-
-/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
-
-
-/* Extract the diagnostic strings from the error table macro in the same
- order as the enumerated indices in ltdl.h. */
-
-static const char *lt_dlerror_strings[] = {
-#define LT_ERROR(name, diagnostic) (diagnostic),
- lt_dlerror_table
-#undef LT_ERROR
- 0
-};
-
-/* This structure is used for the list of registered loaders. */
-struct lt_dlloader
-{
- struct lt_dlloader *next;
- const char *loader_name; /* identifying name for each loader */
- const char *sym_prefix; /* prefix for symbols */
- lt_module_open *module_open;
- lt_module_close *module_close;
- lt_find_sym *find_sym;
- lt_dlloader_exit *dlloader_exit;
- lt_user_data dlloader_data;
-};
-
-struct lt_dlhandle_struct
-{
- struct lt_dlhandle_struct *next;
- lt_dlloader *loader; /* dlopening interface */
- lt_dlinfo info;
- int depcount; /* number of dependencies */
- lt_dlhandle *deplibs; /* dependencies */
- lt_module module; /* system module handle */
- lt_ptr system; /* system specific data */
- lt_caller_data *caller_data; /* per caller associated data */
- int flags; /* various boolean stats */
-};
-
-/* Various boolean flags can be stored in the flags field of an
- lt_dlhandle_struct... */
-#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
-#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
-
-#define LT_DLRESIDENT_FLAG (0x01 << 0)
-/* ...add more flags here... */
-
-#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
-
-
-#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
-
-static const char objdir[] = LTDL_OBJDIR;
-static const char archive_ext[] = LTDL_ARCHIVE_EXT;
-#ifdef LTDL_SHLIB_EXT
-static const char shlib_ext[] = LTDL_SHLIB_EXT;
-#endif
-#ifdef LTDL_SYSSEARCHPATH
-static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
-#endif
-
-
-
-
-/* --- GNUNET_Mutex LOCKING --- */
-
-
-/* Macros to make it easier to run the lock functions only if they have
- been registered. The reason for the complicated lock macro is to
- ensure that the stored error message from the last error is not
- accidentally erased if the current function doesn't generate an
- error of its own. */
-#define LT_DLGNUNET_mutex_lock() LT_STMT_START { \
- if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
- } LT_STMT_END
-#define LT_DLGNUNET_mutex_unlock() LT_STMT_START { \
- if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
- } LT_STMT_END
-#define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
- if (lt_dlmutex_seterror_func) \
- (*lt_dlmutex_seterror_func) (errormsg); \
- else lt_dllast_error = (errormsg); } LT_STMT_END
-#define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
- if (lt_dlmutex_seterror_func) \
- (errormsg) = (*lt_dlmutex_geterror_func) (); \
- else (errormsg) = lt_dllast_error; } LT_STMT_END
-
-/* The mutex functions stored here are global, and are necessarily the
- same for all threads that wish to share access to libltdl. */
-static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
-static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
-static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
-static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
-static const char *lt_dllast_error = 0;
-
-
-/* Either set or reset the mutex functions. Either all the arguments must
- be valid functions, or else all can be NULL to turn off locking entirely.
- The registered functions should be manipulating a static global lock
- from the lock() and unlock() callbacks, which needs to be reentrant. */
-int
-lt_dlmutex_register (lock, unlock, seterror, geterror)
- lt_dlmutex_lock *lock;
- lt_dlmutex_unlock *unlock;
- lt_dlmutex_seterror *seterror;
- lt_dlmutex_geterror *geterror;
-{
- lt_dlmutex_unlock *old_unlock = unlock;
- int errors = 0;
-
- /* Lock using the old lock() callback, if any. */
- LT_DLGNUNET_mutex_lock ();
-
- if ((lock && unlock && seterror && geterror)
- || !(lock || unlock || seterror || geterror))
- {
- lt_dlmutex_lock_func = lock;
- lt_dlmutex_unlock_func = unlock;
- lt_dlmutex_geterror_func = geterror;
- }
- else
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
- ++errors;
- }
-
- /* Use the old unlock() callback we saved earlier, if any. Otherwise
- record any errors using internal storage. */
- if (old_unlock)
- (*old_unlock) ();
-
- /* Return the number of errors encountered during the execution of
- this function. */
- return errors;
-}
-
-
-
-
-/* --- ERROR HANDLING --- */
-
-
-static const char **user_error_strings = 0;
-static int errorcount = LT_ERROR_MAX;
-
-int
-lt_dladderror (diagnostic)
- const char *diagnostic;
-{
- int errindex = 0;
- int result = -1;
- const char **temp = (const char **) 0;
-
- assert (diagnostic);
-
- LT_DLGNUNET_mutex_lock ();
-
- errindex = errorcount - LT_ERROR_MAX;
- temp = LT_EGNUNET_realloc (const char *, user_error_strings, 1 + errindex);
- if (temp)
- {
- user_error_strings = temp;
- user_error_strings[errindex] = diagnostic;
- result = errorcount++;
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return result;
-}
-
-int
-lt_dlseterror (errindex)
- int errindex;
-{
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
-
- if (errindex >= errorcount || errindex < 0)
- {
- /* Ack! Error setting the error message! */
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
- ++errors;
- }
- else if (errindex < LT_ERROR_MAX)
- {
- /* No error setting the error message! */
- LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
- }
- else
- {
- /* No error setting the error message! */
- LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-static lt_ptr
-lt_emalloc (size)
- size_t size;
-{
- lt_ptr mem = lt_dlmalloc (size);
- if (size && !mem)
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
- return mem;
-}
-
-static lt_ptr
-lt_erealloc (addr, size)
- lt_ptr addr;
- size_t size;
-{
- lt_ptr mem = lt_dlrealloc (addr, size);
- if (size && !mem)
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
- return mem;
-}
-
-static char *
-lt_estrdup (str)
- const char *str;
-{
- char *copy = strdup (str);
- if (LT_STRLEN (str) && !copy)
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
- return copy;
-}
-
-
-
-
-/* --- DLOPEN() INTERFACE LOADER --- */
-
-
-#if HAVE_LIBDL
-
-/* dynamic linking with dlopen/dlsym */
-
-#if HAVE_DLFCN_H
-# include <dlfcn.h>
-#endif
-
-#if HAVE_SYS_DL_H
-# include <sys/dl.h>
-#endif
-
-/* We may have to define LT_LAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_LAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_LAZY_OR_NOW DL_LAZY
-# endif
-# endif /* !RTLD_LAZY */
-#endif
-#ifndef LT_LAZY_OR_NOW
-# ifdef RTLD_NOW
-# define LT_LAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_LAZY_OR_NOW DL_NOW
-# endif
-# endif /* !RTLD_NOW */
-#endif
-#ifndef LT_LAZY_OR_NOW
-# define LT_LAZY_OR_NOW 0
-#endif /* !LT_LAZY_OR_NOW */
-
-#if HAVE_DLERROR
-# define DLERROR(arg) dlerror ()
-#else
-# define DLERROR(arg) LT_DLSTRERROR (arg)
-#endif
-
-static lt_module
-sys_dl_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- lt_module module = dlopen (filename, LT_LAZY_OR_NOW);
-
- if (!module)
- {
- LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
- }
-
- return module;
-}
-
-static int
-sys_dl_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- int errors = 0;
-
- if (dlclose (module) != 0)
- {
- LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
- ++errors;
- }
-
- return errors;
-}
-
-static lt_ptr
-sys_dl_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_ptr address = dlsym (module, symbol);
-
- if (!address)
- {
- LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
- }
-
- return address;
-}
-
-static struct lt_user_dlloader sys_dl = {
-# ifdef NEED_USCORE
- "_",
-# else
- 0,
-# endif
- sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0
-};
-
-
-#endif /* HAVE_LIBDL */
-
-
-
-/* --- SHL_LOAD() INTERFACE LOADER --- */
-
-#if HAVE_SHL_LOAD
-
-/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
-
-#ifdef HAVE_DL_H
-# include <dl.h>
-#endif
-
-/* some flags are missing on some systems, so we provide
- * harmless defaults.
- *
- * Mandatory:
- * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
- * BIND_DEFERRED - Delay code symbol resolution until actual reference.
- *
- * Optionally:
- * BIND_FIRST - Place the library at the head of the symbol search
- * order.
- * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
- * unsatisfied symbols as fatal. This flag allows
- * binding of unsatisfied code symbols to be deferred
- * until use.
- * [Perl: For certain libraries, like DCE, deferred
- * binding often causes run time problems. Adding
- * BIND_NONFATAL to BIND_IMMEDIATE still allows
- * unresolved references in situations like this.]
- * BIND_NOSTART - Do not call the initializer for the shared library
- * when the library is loaded, nor on a future call to
- * shl_unload().
- * BIND_VERBOSE - Print verbose messages concerning possible
- * unsatisfied symbols.
- *
- * hp9000s700/hp9000s800:
- * BIND_RESTRICTED - Restrict symbols visible by the library to those
- * present at library load time.
- * DYNAMIC_PATH - Allow the loader to dynamically search for the
- * library specified by the path argument.
- */
-
-#ifndef DYNAMIC_PATH
-# define DYNAMIC_PATH 0
-#endif
-#ifndef BIND_RESTRICTED
-# define BIND_RESTRICTED 0
-#endif
-
-#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
-
-static lt_module
-sys_shl_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- static shl_t self = (shl_t) 0;
- lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
-
- /* Since searching for a symbol against a NULL module handle will also
- look in everything else that was already loaded and exported with
- the -E compiler flag, we always cache a handle saved before any
- modules are loaded. */
- if (!self)
- {
- lt_ptr address;
- shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
- }
-
- if (!filename)
- {
- module = self;
- }
- else
- {
- module = shl_load (filename, LT_BIND_FLAGS, 0L);
-
- if (!module)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
- }
- }
-
- return module;
-}
-
-static int
-sys_shl_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- int errors = 0;
-
- if (module && (shl_unload ((shl_t) (module)) != 0))
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
- ++errors;
- }
-
- return errors;
-}
-
-static lt_ptr
-sys_shl_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_ptr address = 0;
-
- /* sys_shl_open should never return a NULL module handle */
- if (module == (lt_module) 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
- }
- else
- if (!shl_findsym ((shl_t *) & module, symbol, TYPE_UNDEFINED, &address))
- {
- if (!address)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
- }
- }
-
- return address;
-}
-
-static struct lt_user_dlloader sys_shl = {
- 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
-};
-
-#endif /* HAVE_SHL_LOAD */
-
-
-
-
-/* --- LOADLIBRARY() INTERFACE LOADER --- */
-
-#ifdef __WINDOWS__
-
-/* dynamic linking for Win32 */
-
-#include <windows.h>
-
-/* Forward declaration; required to implement handle search below. */
-static lt_dlhandle handles;
-
-static lt_module
-sys_wll_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- lt_dlhandle cur;
- lt_module module = 0;
- const char *errormsg = 0;
- char *searchname = 0;
- char *ext;
- char self_name_buf[MAX_PATH];
-
- if (!filename)
- {
- /* Get the name of main module */
- *self_name_buf = 0;
- GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
- filename = ext = self_name_buf;
- }
- else
- {
- ext = strrchr (filename, '.');
- }
-
- if (ext)
- {
- /* FILENAME already has an extension. */
- searchname = lt_estrdup (filename);
- }
- else
- {
- /* Append a `.' to stop Windows from adding an
- implicit `.dll' extension. */
- searchname = LT_EGNUNET_malloc (char, 2 + LT_STRLEN (filename));
- if (searchname)
- sprintf (searchname, "%s.", filename);
- }
- if (!searchname)
- return 0;
-
- {
- /* Silence dialog from LoadLibrary on some failures.
- No way to get the error mode, but to set it,
- so set it twice to preserve any previous flags. */
- UINT errormode = SetErrorMode (SEM_FAILCRITICALERRORS);
- SetErrorMode (errormode | SEM_FAILCRITICALERRORS);
-
-#if defined(__CYGWIN__)
- {
- char wpath[MAX_PATH];
- cygwin_conv_to_full_win32_path (searchname, wpath);
- module = LoadLibrary (wpath);
- }
-#else
- module = LoadLibrary (searchname);
-#endif
-
- /* Restore the error mode. */
- SetErrorMode (errormode);
- }
-
- LT_DLGNUNET_free (searchname);
-
- /* libltdl expects this function to fail if it is unable
- to physically load the library. Sadly, LoadLibrary
- will search the loaded libraries for a match and return
- one of them if the path search load fails.
-
- We check whether LoadLibrary is returning a handle to
- an already loaded module, and simulate failure if we
- find one. */
- LT_DLGNUNET_mutex_lock ();
- cur = handles;
- while (cur)
- {
- if (!cur->module)
- {
- cur = 0;
- break;
- }
-
- if (cur->module == module)
- {
- break;
- }
-
- cur = cur->next;
- }
- LT_DLGNUNET_mutex_unlock ();
-
- if (cur || !module)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
- module = 0;
- }
-
- return module;
-}
-
-static int
-sys_wll_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- int errors = 0;
-
- if (FreeLibrary (module) == 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
- ++errors;
- }
-
- return errors;
-}
-
-static lt_ptr
-sys_wll_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_ptr address = GetProcAddress (module, symbol);
-
- if (!address)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
- }
-
- return address;
-}
-
-static struct lt_user_dlloader sys_wll = {
- 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
-};
-
-#endif /* __WINDOWS__ */
-
-
-
-
-/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
-
-
-#ifdef __BEOS__
-
-/* dynamic linking for BeOS */
-
-#include <kernel/image.h>
-
-static lt_module
-sys_bedl_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- image_id image = 0;
-
- if (filename)
- {
- image = load_add_on (filename);
- }
- else
- {
- image_info info;
- int32 cookie = 0;
- if (get_next_image_info (0, &cookie, &info) == B_OK)
- image = load_add_on (info.name);
- }
-
- if (image <= 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
- image = 0;
- }
-
- return (lt_module) image;
-}
-
-static int
-sys_bedl_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- int errors = 0;
-
- if (unload_add_on ((image_id) module) != B_OK)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
- ++errors;
- }
-
- return errors;
-}
-
-static lt_ptr
-sys_bedl_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_ptr address = 0;
- image_id image = (image_id) module;
-
- if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
- address = 0;
- }
-
- return address;
-}
-
-static struct lt_user_dlloader sys_bedl = {
- 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
-};
-
-#endif /* __BEOS__ */
-
-
-
-
-/* --- DLD_LINK() INTERFACE LOADER --- */
-
-
-#if HAVE_DLD
-
-/* dynamic linking with dld */
-
-#if HAVE_DLD_H
-#include <dld.h>
-#endif
-
-static lt_module
-sys_dld_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- lt_module module = strdup (filename);
-
- if (dld_link (filename) != 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
- LT_DLGNUNET_free (module);
- module = 0;
- }
-
- return module;
-}
-
-static int
-sys_dld_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- int errors = 0;
-
- if (dld_unlink_by_file ((char *) (module), 1) != 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
- ++errors;
- }
- else
- {
- LT_DLGNUNET_free (module);
- }
-
- return errors;
-}
-
-static lt_ptr
-sys_dld_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_ptr address = dld_get_func (symbol);
-
- if (!address)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
- }
-
- return address;
-}
-
-static struct lt_user_dlloader sys_dld = {
- 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
-};
-
-#endif /* HAVE_DLD */
-
-/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
-#if HAVE_DYLD
-
-
-#if HAVE_MACH_O_DYLD_H
-#if !defined(__APPLE_CC__) && !defined(__MWERKS__) &&
!defined(__private_extern__)
-/* Is this correct? Does it still function properly? */
-#define __private_extern__ extern
-#endif
-# include <mach-o/dyld.h>
-#endif
-#include <mach-o/getsect.h>
-
-/* We have to put some stuff here that isn't in older dyld.h files */
-#ifndef ENUM_DYLD_BOOL
-# define ENUM_DYLD_BOOL
-# undef FALSE
-# undef TRUE
-enum DYLD_BOOL
-{
- FALSE,
- TRUE
-};
-#endif
-#ifndef LC_REQ_DYLD
-# define LC_REQ_DYLD 0x80000000
-#endif
-#ifndef LC_LOAD_WEAK_DYLIB
-# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
-#endif
-static const struct mach_header *(*ltdl_NSAddImage) (const char *image_name,
- unsigned long options) =
- 0;
-static NSSymbol (*ltdl_NSLookupSymbolInImage) (const struct mach_header *
- image, const char *symbolName,
- unsigned long options) = 0;
-static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage) (const struct
- mach_header *
- image,
- const char
- *symbolName) = 0;
-static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic) (NSModule module) = 0;
-
-#ifndef NSADDIMAGE_OPTION_NONE
-#define NSADDIMAGE_OPTION_NONE 0x0
-#endif
-#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
-#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
-#endif
-#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
-#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
-#endif
-#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
-#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
-#endif
-#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
-#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
-#endif
-#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
-#endif
-#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
-#endif
-#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
-#endif
-#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
-#endif
-
-
-static const char *
-lt_int_dyld_error (othererror)
- char *othererror;
-{
-/* return the dyld error string, or the passed in error string if none */
- NSLinkEditErrors ler;
- int lerno;
- const char *errstr;
- const char *file;
- NSLinkEditError (&ler, &lerno, &file, &errstr);
- if (!errstr || !strlen (errstr))
- errstr = othererror;
- return errstr;
-}
-
-static const struct mach_header *
-lt_int_dyld_get_mach_header_from_nsmodule (module)
- NSModule module;
-{
-/* There should probably be an apple dyld api for this */
- int i = _dyld_image_count ();
- int j;
- const char *modname = NSNameOfModule (module);
- const struct mach_header *mh = NULL;
- if (!modname)
- return NULL;
- for (j = 0; j < i; j++)
- {
- if (!strcmp (_dyld_get_image_name (j), modname))
- {
- mh = _dyld_get_image_header (j);
- break;
- }
- }
- return mh;
-}
-
-static const char *
-lt_int_dyld_lib_install_name (mh)
- const struct mach_header *mh;
-{
-/* NSAddImage is also used to get the loaded image, but it only works if the
lib
- is installed, for uninstalled libs we need to check the install_names
against
- each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
- different lib was loaded as a result
-*/
- int j;
- struct load_command *lc;
- unsigned long offset = sizeof (struct mach_header);
- const char *retStr = NULL;
- for (j = 0; j < mh->ncmds; j++)
- {
- lc = (struct load_command *) (((unsigned long) mh) + offset);
- if (LC_ID_DYLIB == lc->cmd)
- {
- retStr =
- (char *) (((struct dylib_command *) lc)->dylib.name.offset +
- (unsigned long) lc);
- }
- offset += lc->cmdsize;
- }
- return retStr;
-}
-
-static const struct mach_header *
-lt_int_dyld_match_loaded_lib_by_install_name (const char *name)
-{
- int i = _dyld_image_count ();
- int j;
- const struct mach_header *mh = NULL;
- const char *id = NULL;
- for (j = 0; j < i; j++)
- {
- id = lt_int_dyld_lib_install_name (_dyld_get_image_header (j));
- if ((id) && (!strcmp (id, name)))
- {
- mh = _dyld_get_image_header (j);
- break;
- }
- }
- return mh;
-}
-
-static NSSymbol
-lt_int_dyld_NSlookupSymbolInLinkedLibs (symbol, mh)
- const char *symbol;
- const struct mach_header *mh;
-{
- /* Safe to assume our mh is good */
- int j;
- struct load_command *lc;
- unsigned long offset = sizeof (struct mach_header);
- NSSymbol retSym = 0;
- const struct mach_header *mh1;
- if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined (symbol))
- {
- for (j = 0; j < mh->ncmds; j++)
- {
- lc = (struct load_command *) (((unsigned long) mh) + offset);
- if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
- {
- mh1 =
- lt_int_dyld_match_loaded_lib_by_install_name ((char
- *) (((struct
-
dylib_command
- *) lc)->
- dylib.name.
- offset +
- (unsigned
- long)
- lc));
- if (!mh1)
- {
- /* Maybe NSAddImage can find it */
- mh1 =
- ltdl_NSAddImage ((char *) (((struct dylib_command *) lc)->
- dylib.name.offset +
- (unsigned long) lc),
- NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
- NSADDIMAGE_OPTION_WITH_SEARCHING +
- NSADDIMAGE_OPTION_RETURN_ON_ERROR);
- }
- if (mh1)
- {
- retSym = ltdl_NSLookupSymbolInImage (mh1,
- symbol,
-
NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
- |
-
NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
- if (retSym)
- break;
- }
- }
- offset += lc->cmdsize;
- }
- }
- return retSym;
-}
-
-static int
-sys_dyld_init ()
-{
- int retCode = 0;
- int err = 0;
- if (!_dyld_present ())
- {
- retCode = 1;
- }
- else
- {
- err =
- _dyld_func_lookup ("__dyld_NSAddImage",
- (unsigned long *) <dl_NSAddImage);
- err =
- _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
- (unsigned long *) <dl_NSLookupSymbolInImage);
- err =
- _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
- (unsigned long *)
- <dl_NSIsSymbolNameDefinedInImage);
- err =
- _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic",
- (unsigned long *) <dl_NSMakePrivateModulePublic);
- }
- return retCode;
-}
-
-static lt_module
-sys_dyld_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- lt_module module = 0;
- NSObjectFileImage ofi = 0;
- NSObjectFileImageReturnCode ofirc;
-
- if (!filename)
- return (lt_module) - 1;
- ofirc = NSCreateObjectFileImageFromFile (filename, &ofi);
- switch (ofirc)
- {
- case NSObjectFileImageSuccess:
- module = NSLinkModule (ofi, filename,
- NSLINKMODULE_OPTION_RETURN_ON_ERROR
- | NSLINKMODULE_OPTION_PRIVATE
- | NSLINKMODULE_OPTION_BINDNOW);
- NSDestroyObjectFileImage (ofi);
- if (module)
- ltdl_NSMakePrivateModulePublic (module);
- break;
- case NSObjectFileImageInappropriateFile:
- if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
- {
- module =
- (lt_module) ltdl_NSAddImage (filename,
- NSADDIMAGE_OPTION_RETURN_ON_ERROR);
- break;
- }
- default:
- LT_DLMUTEX_SETERROR (lt_int_dyld_error (LT_DLSTRERROR (CANNOT_OPEN)));
- return 0;
- }
- if (!module)
- LT_DLMUTEX_SETERROR (lt_int_dyld_error (LT_DLSTRERROR (CANNOT_OPEN)));
- return module;
-}
-
-static int
-sys_dyld_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- int retCode = 0;
- int flags = 0;
- if (module == (lt_module) - 1)
- return 0;
-#ifdef __BIG_ENDIAN__
- if (((struct mach_header *) module)->magic == MH_MAGIC)
-#else
- if (((struct mach_header *) module)->magic == MH_CIGAM)
-#endif
- {
- LT_DLMUTEX_SETERROR ("Can not close a dylib");
- retCode = 1;
- }
- else
- {
-#if 1
-/* Currently, if a module contains c++ static destructors and it is unloaded,
we
- get a segfault in atexit(), due to compiler and dynamic loader differences
of
- opinion, this works around that.
-*/
- if ((const struct section *) NULL !=
- getsectbynamefromheader (lt_int_dyld_get_mach_header_from_nsmodule
- (module), "__DATA", "__mod_term_func"))
- {
- flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
- }
-#endif
-#ifdef __ppc__
- flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
-#endif
- if (!NSUnLinkModule (module, flags))
- {
- retCode = 1;
- LT_DLMUTEX_SETERROR (lt_int_dyld_error
- (LT_DLSTRERROR (CANNOT_CLOSE)));
- }
- }
-
- return retCode;
-}
-
-static lt_ptr
-sys_dyld_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_ptr address = 0;
- NSSymbol *nssym = 0;
- void *unused;
- const struct mach_header *mh = NULL;
- char saveError[256] = "Symbol not found";
- if (module == (lt_module) - 1)
- {
- _dyld_lookup_and_bind (symbol, (unsigned long *) &address, &unused);
- return address;
- }
-#ifdef __BIG_ENDIAN__
- if (((struct mach_header *) module)->magic == MH_MAGIC)
-#else
- if (((struct mach_header *) module)->magic == MH_CIGAM)
-#endif
- {
- if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
- {
- mh = module;
- if (ltdl_NSIsSymbolNameDefinedInImage
- ((struct mach_header *) module, symbol))
- {
- nssym =
- ltdl_NSLookupSymbolInImage ((struct mach_header *) module,
- symbol,
-
NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
- |
-
NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
- }
- }
-
- }
- else
- {
- nssym = NSLookupSymbolInModule (module, symbol);
- }
- if (!nssym)
- {
- strncpy (saveError,
- lt_int_dyld_error (LT_DLSTRERROR (SYMBOL_NOT_FOUND)), 255);
- saveError[255] = 0;
- if (!mh)
- mh = lt_int_dyld_get_mach_header_from_nsmodule (module);
- nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs (symbol, mh);
- }
- if (!nssym)
- {
- LT_DLMUTEX_SETERROR (saveError);
- return NULL;
- }
- return NSAddressOfSymbol (nssym);
-}
-
-static struct lt_user_dlloader sys_dyld =
- { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
-
-
-#endif /* HAVE_DYLD */
-
-
-/* --- DLPREOPEN() INTERFACE LOADER --- */
-
-
-/* emulate dynamic linking using preloaded_symbols */
-
-typedef struct lt_dlsymlists_t
-{
- struct lt_dlsymlists_t *next;
- const lt_dlsymlist *syms;
-} lt_dlsymlists_t;
-
-static const lt_dlsymlist *default_preloaded_symbols = 0;
-static lt_dlsymlists_t *preloaded_symbols = 0;
-
-static int
-presym_init (loader_data)
- lt_user_data loader_data;
-{
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
-
- preloaded_symbols = 0;
- if (default_preloaded_symbols)
- {
- errors = lt_dlpreload (default_preloaded_symbols);
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-static int
-presym_free_symlists ()
-{
- lt_dlsymlists_t *lists;
-
- LT_DLGNUNET_mutex_lock ();
-
- lists = preloaded_symbols;
- while (lists)
- {
- lt_dlsymlists_t *tmp = lists;
-
- lists = lists->next;
- LT_DLGNUNET_free (tmp);
- }
- preloaded_symbols = 0;
-
- LT_DLGNUNET_mutex_unlock ();
-
- return 0;
-}
-
-static int
-presym_exit (loader_data)
- lt_user_data loader_data;
-{
- presym_free_symlists ();
- return 0;
-}
-
-static int
-presym_add_symlist (preloaded)
- const lt_dlsymlist *preloaded;
-{
- lt_dlsymlists_t *tmp;
- lt_dlsymlists_t *lists;
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
-
- lists = preloaded_symbols;
- while (lists)
- {
- if (lists->syms == preloaded)
- {
- goto done;
- }
- lists = lists->next;
- }
-
- tmp = LT_EGNUNET_malloc (lt_dlsymlists_t, 1);
- if (tmp)
- {
- memset (tmp, 0, sizeof (lt_dlsymlists_t));
- tmp->syms = preloaded;
- tmp->next = preloaded_symbols;
- preloaded_symbols = tmp;
- }
- else
- {
- ++errors;
- }
-
-done:
- LT_DLGNUNET_mutex_unlock ();
- return errors;
-}
-
-static lt_module
-presym_open (loader_data, filename)
- lt_user_data loader_data;
- const char *filename;
-{
- lt_dlsymlists_t *lists;
- lt_module module = (lt_module) 0;
-
- LT_DLGNUNET_mutex_lock ();
- lists = preloaded_symbols;
-
- if (!lists)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
- goto done;
- }
-
- /* Can't use NULL as the reflective symbol header, as NULL is
- used to mark the end of the entire symbol list. Self-dlpreopened
- symbols follow this magic number, chosen to be an unlikely
- clash with a real module name. */
- if (!filename)
- {
- filename = "@PROGRAM@";
- }
-
- while (lists)
- {
- const lt_dlsymlist *syms = lists->syms;
-
- while (syms->name)
- {
- if (!syms->address && strcmp (syms->name, filename) == 0)
- {
- module = (lt_module) syms;
- goto done;
- }
- ++syms;
- }
-
- lists = lists->next;
- }
-
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
-
-done:
- LT_DLGNUNET_mutex_unlock ();
- return module;
-}
-
-static int
-presym_close (loader_data, module)
- lt_user_data loader_data;
- lt_module module;
-{
- /* Just to silence gcc -Wall */
- module = 0;
- return 0;
-}
-
-static lt_ptr
-presym_sym (loader_data, module, symbol)
- lt_user_data loader_data;
- lt_module module;
- const char *symbol;
-{
- lt_dlsymlist *syms = (lt_dlsymlist *) module;
-
- ++syms;
- while (syms->address)
- {
- if (strcmp (syms->name, symbol) == 0)
- {
- return syms->address;
- }
-
- ++syms;
- }
-
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
-
- return 0;
-}
-
-static struct lt_user_dlloader presym = {
- 0, presym_open, presym_close, presym_sym, presym_exit, 0
-};
-
-
-
-
-
-/* --- DYNAMIC MODULE LOADING --- */
-
-
-/* The type of a function used at each iteration of foreach_dirinpath(). */
-typedef int foreach_callback_func LT_PARAMS ((char *filename, lt_ptr data1,
- lt_ptr data2));
-
-static int foreach_dirinpath LT_PARAMS ((const char *search_path,
- const char *base_name,
- foreach_callback_func * func,
- lt_ptr data1, lt_ptr data2));
-
-static int find_file_callback LT_PARAMS ((char *filename, lt_ptr data,
- lt_ptr ignored));
-static int find_handle_callback LT_PARAMS ((char *filename, lt_ptr data,
- lt_ptr ignored));
-static int foreachfile_callback LT_PARAMS ((char *filename, lt_ptr data1,
- lt_ptr data2));
-
-
-static int canonicalize_path LT_PARAMS ((const char *path,
- char **pcanonical));
-static int argzize_path LT_PARAMS ((const char *path,
- char **pargz, size_t * pargz_len));
-static FILE *find_file LT_PARAMS ((const char *search_path,
- const char *base_name, char **pdir));
-static lt_dlhandle *find_handle LT_PARAMS ((const char *search_path,
- const char *base_name,
- lt_dlhandle * handle));
-static int find_module LT_PARAMS ((lt_dlhandle * handle,
- const char *dir,
- const char *libdir,
- const char *dlname,
- const char *old_name, int installed));
-static int free_vars LT_PARAMS ((char *dlname, char *oldname,
- char *libdir, char *deplibs));
-static int load_deplibs LT_PARAMS ((lt_dlhandle handle, char *deplibs));
-static int trim LT_PARAMS ((char **dest, const char *str));
-static int try_dlopen LT_PARAMS ((lt_dlhandle * handle,
- const char *filename));
-static int tryall_dlopen LT_PARAMS ((lt_dlhandle * handle,
- const char *filename));
-static int unload_deplibs LT_PARAMS ((lt_dlhandle handle));
-static int lt_argz_insert LT_PARAMS ((char **pargz,
- size_t * pargz_len,
- char *before, const char *entry));
-static int lt_argz_insertinorder LT_PARAMS ((char **pargz,
- size_t * pargz_len,
- const char *entry));
-static int lt_argz_insertdir LT_PARAMS ((char **pargz,
- size_t * pargz_len,
- const char *dirnam,
- struct dirent * dp));
-static int lt_dlpath_insertdir LT_PARAMS ((char **ppath,
- char *before, const char *dir));
-static int list_files_by_dir LT_PARAMS ((const char *dirnam,
- char **pargz, size_t * pargz_len));
-static int file_not_found LT_PARAMS ((void));
-
-static char *user_search_path = 0;
-static lt_dlloader *loaders = 0;
-static lt_dlhandle handles = 0;
-static int initialized = 0;
-
-/* Initialize libltdl. */
-int
-lt_dlinit ()
-{
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
-
- /* Initialize only at first call. */
- if (++initialized == 1)
- {
- handles = 0;
- user_search_path = 0; /* empty search path */
-
-#if HAVE_LIBDL
- errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
-#endif
-#if HAVE_SHL_LOAD
- errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
-#endif
-#ifdef __WINDOWS__
- errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
-#endif
-#ifdef __BEOS__
- errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
-#endif
-#if HAVE_DLD
- errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
-#endif
-#if HAVE_DYLD
- errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
- errors += sys_dyld_init ();
-#endif
- errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
-
- if (presym_init (presym.dlloader_data))
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
- ++errors;
- }
- else if (errors != 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
- ++errors;
- }
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-int
-lt_dlpreload (preloaded)
- const lt_dlsymlist *preloaded;
-{
- int errors = 0;
-
- if (preloaded)
- {
- errors = presym_add_symlist (preloaded);
- }
- else
- {
- presym_free_symlists ();
-
- LT_DLGNUNET_mutex_lock ();
- if (default_preloaded_symbols)
- {
- errors = lt_dlpreload (default_preloaded_symbols);
- }
- LT_DLGNUNET_mutex_unlock ();
- }
-
- return errors;
-}
-
-int
-lt_dlpreload_default (preloaded)
- const lt_dlsymlist *preloaded;
-{
- LT_DLGNUNET_mutex_lock ();
- default_preloaded_symbols = preloaded;
- LT_DLGNUNET_mutex_unlock ();
- return 0;
-}
-
-int
-lt_dlexit ()
-{
- /* shut down libltdl */
- lt_dlloader *loader;
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
- loader = loaders;
-
- if (!initialized)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
- ++errors;
- goto done;
- }
-
- /* shut down only at last call. */
- if (--initialized == 0)
- {
- int level;
-
- while (handles && LT_DLIS_RESIDENT (handles))
- {
- handles = handles->next;
- }
-
- /* close all modules */
- for (level = 1; handles; ++level)
- {
- lt_dlhandle cur = handles;
- int saw_nonresident = 0;
-
- while (cur)
- {
- lt_dlhandle tmp = cur;
- cur = cur->next;
- if (!LT_DLIS_RESIDENT (tmp))
- saw_nonresident = 1;
- if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
- {
- if (lt_dlclose (tmp))
- {
- ++errors;
- }
- }
- }
- /* done if only resident modules are left */
- if (!saw_nonresident)
- break;
- }
-
- /* close all loaders */
- while (loader)
- {
- lt_dlloader *next = loader->next;
- lt_user_data data = loader->dlloader_data;
- if (loader->dlloader_exit && loader->dlloader_exit (data))
- {
- ++errors;
- }
-
- LT_DLMEM_REASSIGN (loader, next);
- }
- loaders = 0;
- }
-
-done:
- LT_DLGNUNET_mutex_unlock ();
- return errors;
-}
-
-static int
-tryall_dlopen (handle, filename)
- lt_dlhandle *handle;
- const char *filename;
-{
- lt_dlhandle cur;
- lt_dlloader *loader;
- const char *saved_error;
- int errors = 0;
-
- LT_DLMUTEX_GETERROR (saved_error);
- LT_DLGNUNET_mutex_lock ();
-
- cur = handles;
- loader = loaders;
-
- /* check whether the module was already opened */
- while (cur)
- {
- /* try to dlopen the program itself? */
- if (!cur->info.filename && !filename)
- {
- break;
- }
-
- if (cur->info.filename && filename
- && strcmp (cur->info.filename, filename) == 0)
- {
- break;
- }
-
- cur = cur->next;
- }
-
- if (cur)
- {
- ++cur->info.ref_count;
- *handle = cur;
- goto done;
- }
-
- cur = *handle;
- if (filename)
- {
- /* Comment out the check of file permissions using access.
- This call seems to always return -1 with error EACCES.
- */
- /* We need to catch missing file errors early so that
- file_not_found() can detect what happened.
- if (access (filename, R_OK) != 0)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
- ++errors;
- goto done;
- } */
-
- cur->info.filename = lt_estrdup (filename);
- if (!cur->info.filename)
- {
- ++errors;
- goto done;
- }
- }
- else
- {
- cur->info.filename = 0;
- }
-
- while (loader)
- {
- lt_user_data data = loader->dlloader_data;
-
- cur->module = loader->module_open (data, filename);
-
- if (cur->module != 0)
- {
- break;
- }
- loader = loader->next;
- }
-
- if (!loader)
- {
- LT_DLGNUNET_free (cur->info.filename);
- ++errors;
- goto done;
- }
-
- cur->loader = loader;
- LT_DLMUTEX_SETERROR (saved_error);
-
-done:
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-static int
-tryall_dlopen_module (handle, prefix, dirname, dlname)
- lt_dlhandle *handle;
- const char *prefix;
- const char *dirname;
- const char *dlname;
-{
- int error = 0;
- char *filename = 0;
- size_t filename_len = 0;
- size_t dirname_len = LT_STRLEN (dirname);
-
- assert (handle);
- assert (dirname);
- assert (dlname);
-#ifdef LT_DIRSEP_CHAR
- /* Only canonicalized names (i.e. with DIRSEP chars already converted)
- should make it into this function: */
- assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
-#endif
-
- if (dirname_len > 0)
- if (dirname[dirname_len - 1] == '/')
- --dirname_len;
- filename_len = dirname_len + 1 + LT_STRLEN (dlname);
-
- /* Allocate memory, and combine DIRNAME and MODULENAME into it.
- The PREFIX (if any) is handled below. */
- filename = LT_EGNUNET_malloc (char, dirname_len + 1 + filename_len + 1);
- if (!filename)
- return 1;
-
- sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
-
- /* Now that we have combined DIRNAME and MODULENAME, if there is
- also a PREFIX to contend with, simply recurse with the arguments
- shuffled. Otherwise, attempt to open FILENAME as a module. */
- if (prefix)
- {
- error += tryall_dlopen_module (handle,
- (const char *) 0, prefix, filename);
- }
- else if (tryall_dlopen (handle, filename) != 0)
- {
- ++error;
- }
-
- LT_DLGNUNET_free (filename);
- return error;
-}
-
-static int
-find_module (handle, dir, libdir, dlname, old_name, installed)
- lt_dlhandle *handle;
- const char *dir;
- const char *libdir;
- const char *dlname;
- const char *old_name;
- int installed;
-{
- /* Try to open the old library first; if it was dlpreopened,
- we want the preopened version of it, even if a dlopenable
- module is available. */
- if (old_name && tryall_dlopen (handle, old_name) == 0)
- {
- return 0;
- }
-
- /* Try to open the dynamic library. */
- if (dlname)
- {
- /* try to open the installed module */
- if (installed && libdir)
- {
- if (tryall_dlopen_module (handle,
- (const char *) 0, libdir, dlname) == 0)
- return 0;
- }
-
- /* try to open the not-installed module */
- if (!installed)
- {
- if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
- return 0;
- }
-
- /* maybe it was moved to another directory */
- {
- if (dir && (tryall_dlopen_module (handle,
- (const char *) 0, dir,
- dlname) == 0))
- return 0;
- }
- }
-
- return 1;
-}
-
-
-static int
-canonicalize_path (path, pcanonical)
- const char *path;
- char **pcanonical;
-{
- char *canonical = 0;
-
- assert (path && *path);
- assert (pcanonical);
-
- canonical = LT_EGNUNET_malloc (char, 1 + LT_STRLEN (path));
- if (!canonical)
- return 1;
-
- {
- size_t dest = 0;
- size_t src;
- for (src = 0; path[src] != LT_EOS_CHAR; ++src)
- {
- /* Path separators are not copied to the beginning or end of
- the destination, or if another separator would follow
- immediately. */
- if (path[src] == LT_PATHSEP_CHAR)
- {
- if ((dest == 0)
- || (path[1 + src] == LT_PATHSEP_CHAR)
- || (path[1 + src] == LT_EOS_CHAR))
- continue;
- }
-
- /* Anything other than a directory separator is copied verbatim. */
- if ((path[src] != '/')
-#ifdef LT_DIRSEP_CHAR
- && (path[src] != LT_DIRSEP_CHAR)
-#endif
- )
- {
- canonical[dest++] = path[src];
- }
- /* Directory separators are converted and copied only if they are
- not at the end of a path -- i.e. before a path separator or
- NULL terminator. */
- else if ((path[1 + src] != LT_PATHSEP_CHAR)
- && (path[1 + src] != LT_EOS_CHAR)
-#ifdef LT_DIRSEP_CHAR
- && (path[1 + src] != LT_DIRSEP_CHAR)
-#endif
- && (path[1 + src] != '/'))
- {
- canonical[dest++] = '/';
- }
- }
-
- /* Add an end-of-string marker at the end. */
- canonical[dest] = LT_EOS_CHAR;
- }
-
- /* Assign new value. */
- *pcanonical = canonical;
-
- return 0;
-}
-
-static int
-argzize_path (path, pargz, pargz_len)
- const char *path;
- char **pargz;
- size_t *pargz_len;
-{
- error_t error;
-
- assert (path);
- assert (pargz);
- assert (pargz_len);
-
- if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
- {
- switch (error)
- {
- case ENOMEM:
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
- break;
- default:
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
- break;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
- of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
- non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
- it is appended to each SEARCH_PATH element before FUNC is called. */
-static int
-foreach_dirinpath (search_path, base_name, func, data1, data2)
- const char *search_path;
- const char *base_name;
- foreach_callback_func *func;
- lt_ptr data1;
- lt_ptr data2;
-{
- int result = 0;
- int filenamesize = 0;
- size_t lenbase = LT_STRLEN (base_name);
- size_t argz_len = 0;
- char *argz = 0;
- char *filename = 0;
- char *canonical = 0;
-
- LT_DLGNUNET_mutex_lock ();
-
- if (!search_path || !*search_path)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
- goto cleanup;
- }
-
- if (canonicalize_path (search_path, &canonical) != 0)
- goto cleanup;
-
- if (argzize_path (canonical, &argz, &argz_len) != 0)
- goto cleanup;
-
- {
- char *dir_name = 0;
- while ((dir_name = argz_next (argz, argz_len, dir_name)))
- {
- size_t lendir = LT_STRLEN (dir_name);
-
- if (lendir + 1 + lenbase >= filenamesize)
- {
- LT_DLGNUNET_free (filename);
- filenamesize = lendir + 1 + lenbase + 1; /* "/d" + '/' + "f" +
'\0' */
- filename = LT_EGNUNET_malloc (char, filenamesize);
- if (!filename)
- goto cleanup;
- }
-
- assert (filenamesize > lendir);
- strcpy (filename, dir_name);
-
- if (base_name && *base_name)
- {
- if (filename[lendir - 1] != '/')
- filename[lendir++] = '/';
- strcpy (filename + lendir, base_name);
- }
-
- if ((result = (*func) (filename, data1, data2)))
- {
- break;
- }
- }
- }
-
-cleanup:
- LT_DLGNUNET_free (argz);
- LT_DLGNUNET_free (canonical);
- LT_DLGNUNET_free (filename);
-
- LT_DLGNUNET_mutex_unlock ();
-
- return result;
-}
-
-/* If FILEPATH can be opened, store the name of the directory component
- in DATA1, and the opened FILE* structure address in DATA2. Otherwise
- DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
-static int
-find_file_callback (filename, data1, data2)
- char *filename;
- lt_ptr data1;
- lt_ptr data2;
-{
- char **pdir = (char **) data1;
- FILE **pfile = (FILE **) data2;
- int is_done = 0;
-
- assert (filename && *filename);
- assert (pdir);
- assert (pfile);
-
- if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
- {
- char *dirend = strrchr (filename, '/');
-
- if (dirend > filename)
- *dirend = LT_EOS_CHAR;
-
- LT_DLGNUNET_free (*pdir);
- *pdir = lt_estrdup (filename);
- is_done = (*pdir == 0) ? -1 : 1;
- }
-
- return is_done;
-}
-
-static FILE *
-find_file (search_path, base_name, pdir)
- const char *search_path;
- const char *base_name;
- char **pdir;
-{
- FILE *file = 0;
-
- foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
-
- return file;
-}
-
-static int
-find_handle_callback (filename, data, ignored)
- char *filename;
- lt_ptr data;
- lt_ptr ignored;
-{
- lt_dlhandle *handle = (lt_dlhandle *) data;
- int notfound = access (filename, R_OK);
-
- /* Bail out if file cannot be read... */
- if (notfound)
- return 0;
-
- /* Try to dlopen the file, but do not continue searching in any
- case. */
- if (tryall_dlopen (handle, filename) != 0)
- *handle = 0;
-
- return 1;
-}
-
-/* If HANDLE was found return it, otherwise return 0. If HANDLE was
- found but could not be opened, *HANDLE will be set to 0. */
-static lt_dlhandle *
-find_handle (search_path, base_name, handle)
- const char *search_path;
- const char *base_name;
- lt_dlhandle *handle;
-{
- if (!search_path)
- return 0;
-
- if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
- handle, 0))
- return 0;
-
- return handle;
-}
-
-static int
-load_deplibs (handle, deplibs)
- lt_dlhandle handle;
- char *deplibs;
-{
-#if LTDL_DLOPEN_DEPLIBS
- char *p, *save_search_path = 0;
- int depcount = 0;
- int i;
- char **names = 0;
-#endif
- int errors = 0;
-
- handle->depcount = 0;
-
-#if LTDL_DLOPEN_DEPLIBS
- if (!deplibs)
- {
- return errors;
- }
- ++errors;
-
- LT_DLGNUNET_mutex_lock ();
- if (user_search_path)
- {
- save_search_path = lt_estrdup (user_search_path);
- if (!save_search_path)
- goto cleanup;
- }
-
- /* extract search paths and count deplibs */
- p = deplibs;
- while (*p)
- {
- if (!isspace ((int) *p))
- {
- char *end = p + 1;
- while (*end && !isspace ((int) *end))
- {
- ++end;
- }
-
- if (strncmp (p, "-L", 2) == 0 || strncmp (p, "-R", 2) == 0)
- {
- char save = *end;
- *end = 0; /* set a temporary string terminator */
- if (lt_dladdsearchdir (p + 2))
- {
- goto cleanup;
- }
- *end = save;
- }
- else
- {
- ++depcount;
- }
-
- p = end;
- }
- else
- {
- ++p;
- }
- }
-
- if (!depcount)
- {
- errors = 0;
- goto cleanup;
- }
-
- names = LT_EGNUNET_malloc (char *, depcount * sizeof (char *));
- if (!names)
- goto cleanup;
-
- /* now only extract the actual deplibs */
- depcount = 0;
- p = deplibs;
- while (*p)
- {
- if (isspace ((int) *p))
- {
- ++p;
- }
- else
- {
- char *end = p + 1;
- while (*end && !isspace ((int) *end))
- {
- ++end;
- }
-
- if (strncmp (p, "-L", 2) != 0 && strncmp (p, "-R", 2) != 0)
- {
- char *name;
- char save = *end;
- *end = 0; /* set a temporary string terminator */
- if (strncmp (p, "-l", 2) == 0)
- {
- size_t name_len = 3 + /* "lib" */ LT_STRLEN (p + 2);
- name = LT_EGNUNET_malloc (char, 1 + name_len);
- if (name)
- sprintf (name, "lib%s", p + 2);
- }
- else
- name = lt_estrdup (p);
-
- if (!name)
- goto cleanup_names;
-
- names[depcount++] = name;
- *end = save;
- }
- p = end;
- }
- }
-
- /* load the deplibs (in reverse order)
- At this stage, don't worry if the deplibs do not load correctly,
- they may already be statically linked into the loading application
- for instance. There will be a more enlightening error message
- later on if the loaded module cannot resolve all of its symbols. */
- if (depcount)
- {
- int j = 0;
-
- handle->deplibs =
- (lt_dlhandle *) LT_EGNUNET_malloc (lt_dlhandle *, depcount);
- if (!handle->deplibs)
- goto cleanup;
-
- for (i = 0; i < depcount; ++i)
- {
- handle->deplibs[j] = lt_dlopenext (names[depcount - 1 - i]);
- if (handle->deplibs[j])
- {
- ++j;
- }
- }
-
- handle->depcount = j; /* Number of successfully loaded deplibs */
- errors = 0;
- }
-
-cleanup_names:
- for (i = 0; i < depcount; ++i)
- {
- LT_DLGNUNET_free (names[i]);
- }
-
-cleanup:
- LT_DLGNUNET_free (names);
- /* restore the old search path */
- if (user_search_path)
- {
- LT_DLGNUNET_free (user_search_path);
- user_search_path = save_search_path;
- }
- LT_DLGNUNET_mutex_unlock ();
-
-#endif
-
- return errors;
-}
-
-static int
-unload_deplibs (handle)
- lt_dlhandle handle;
-{
- int i;
- int errors = 0;
-
- if (handle->depcount)
- {
- for (i = 0; i < handle->depcount; ++i)
- {
- if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
- {
- errors += lt_dlclose (handle->deplibs[i]);
- }
- }
- }
-
- return errors;
-}
-
-static int
-trim (dest, str)
- char **dest;
- const char *str;
-{
- /* remove the leading and trailing "'" from str
- and store the result in dest */
- const char *end = strrchr (str, '\'');
- size_t len = LT_STRLEN (str);
- char *tmp;
-
- LT_DLGNUNET_free (*dest);
-
- if (!end)
- return 1;
-
- if (len > 3 && str[0] == '\'')
- {
- tmp = LT_EGNUNET_malloc (char, end - str);
- if (!tmp)
- return 1;
-
- strncpy (tmp, &str[1], (end - str) - 1);
- tmp[len - 3] = LT_EOS_CHAR;
- *dest = tmp;
- }
- else
- {
- *dest = 0;
- }
-
- return 0;
-}
-
-static int
-free_vars (dlname, oldname, libdir, deplibs)
- char *dlname;
- char *oldname;
- char *libdir;
- char *deplibs;
-{
- LT_DLGNUNET_free (dlname);
- LT_DLGNUNET_free (oldname);
- LT_DLGNUNET_free (libdir);
- LT_DLGNUNET_free (deplibs);
-
- return 0;
-}
-
-static int
-try_dlopen (phandle, filename)
- lt_dlhandle *phandle;
- const char *filename;
-{
- const char *ext = 0;
- const char *saved_error = 0;
- char *canonical = 0;
- char *base_name = 0;
- char *dir = 0;
- char *name = 0;
- int errors = 0;
- lt_dlhandle newhandle;
-
- assert (phandle);
- assert (*phandle == 0);
-
- LT_DLMUTEX_GETERROR (saved_error);
-
- /* dlopen self? */
- if (!filename)
- {
- *phandle =
- (lt_dlhandle) LT_EGNUNET_malloc (struct lt_dlhandle_struct, 1);
- if (*phandle == 0)
- return 1;
-
- memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
- newhandle = *phandle;
-
- /* lt_dlclose()ing yourself is very bad! Disallow it. */
- LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
-
- if (tryall_dlopen (&newhandle, 0) != 0)
- {
- LT_DLGNUNET_free (*phandle);
- return 1;
- }
-
- goto register_handle;
- }
-
- assert (filename && *filename);
-
- /* Doing this immediately allows internal functions to safely
- assume only canonicalized paths are passed. */
- if (canonicalize_path (filename, &canonical) != 0)
- {
- ++errors;
- goto cleanup;
- }
-
- /* If the canonical module name is a path (relative or absolute)
- then split it into a directory part and a name part. */
- base_name = strrchr (canonical, '/');
- if (base_name)
- {
- size_t dirlen = (1 + base_name) - canonical;
-
- dir = LT_EGNUNET_malloc (char, 1 + dirlen);
- if (!dir)
- {
- ++errors;
- goto cleanup;
- }
-
- strncpy (dir, canonical, dirlen);
- dir[dirlen] = LT_EOS_CHAR;
-
- ++base_name;
- }
- else
- base_name = canonical;
-
- assert (base_name && *base_name);
-
- /* Check whether we are opening a libtool module (.la extension). */
- ext = strrchr (base_name, '.');
- if (ext && strcmp (ext, archive_ext) == 0)
- {
- /* this seems to be a libtool module */
- FILE *file = 0;
- char *dlname = 0;
- char *old_name = 0;
- char *libdir = 0;
- char *deplibs = 0;
- char *line = 0;
- size_t line_len;
-
- /* if we can't find the installed flag, it is probably an
- installed libtool archive, produced with an old version
- of libtool */
- int installed = 1;
-
- /* extract the module name from the file name */
- name = LT_EGNUNET_malloc (char, ext - base_name + 1);
- if (!name)
- {
- ++errors;
- goto cleanup;
- }
-
- /* canonicalize the module name */
- {
- size_t i;
- for (i = 0; i < ext - base_name; ++i)
- {
- if (isalnum ((int) (base_name[i])))
- {
- name[i] = base_name[i];
- }
- else
- {
- name[i] = '_';
- }
- }
- name[ext - base_name] = LT_EOS_CHAR;
- }
-
- /* Now try to open the .la file. If there is no directory name
- component, try to find it first in user_search_path and then other
- prescribed paths. Otherwise (or in any case if the module was not
- yet found) try opening just the module name as passed. */
- if (!dir)
- {
- const char *search_path;
-
- LT_DLGNUNET_mutex_lock ();
- search_path = user_search_path;
- if (search_path)
- file = find_file (user_search_path, base_name, &dir);
- LT_DLGNUNET_mutex_unlock ();
-
- if (!file)
- {
- search_path = getenv (LTDL_SEARCHPATH_VAR);
- if (search_path)
- file = find_file (search_path, base_name, &dir);
- }
-
-#ifdef LTDL_SHLIBPATH_VAR
- if (!file)
- {
- search_path = getenv (LTDL_SHLIBPATH_VAR);
- if (search_path)
- file = find_file (search_path, base_name, &dir);
- }
-#endif
-#ifdef LTDL_SYSSEARCHPATH
- if (!file && sys_search_path)
- {
- file = find_file (sys_search_path, base_name, &dir);
- }
-#endif
- }
- if (!file)
- {
- file = fopen (filename, LT_READTEXT_MODE);
- }
-
- /* If we didn't find the file by now, it really isn't there. Set
- the status flag, and bail out. */
- if (!file)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
- ++errors;
- goto cleanup;
- }
-
- line_len = LT_FILENAME_MAX;
- line = LT_EGNUNET_malloc (char, line_len);
- if (!line)
- {
- fclose (file);
- ++errors;
- goto cleanup;
- }
-
- /* read the .la file */
- while (!feof (file))
- {
- if (!fgets (line, (int) line_len, file))
- {
- break;
- }
-
- /* Handle the case where we occasionally need to read a line
- that is longer than the initial buffer size. */
- while ((line[LT_STRLEN (line) - 1] != '\n') && (!feof (file)))
- {
- line = LT_DLGNUNET_realloc (char, line, line_len * 2);
- if (!fgets (&line[line_len - 1], (int) line_len + 1, file))
- {
- break;
- }
- line_len *= 2;
- }
-
- if (line[0] == '\n' || line[0] == '#')
- {
- continue;
- }
-
-#undef STR_DLNAME
-#define STR_DLNAME "dlname="
- if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
- {
- errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
- }
-
-#undef STR_OLD_LIBRARY
-#define STR_OLD_LIBRARY "old_library="
- else if (strncmp (line, STR_OLD_LIBRARY,
- sizeof (STR_OLD_LIBRARY) - 1) == 0)
- {
- errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
- }
-#undef STR_LIBDIR
-#define STR_LIBDIR "libdir="
- else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
- {
- errors += trim (&libdir, &line[sizeof (STR_LIBDIR) - 1]);
- }
-
-#undef STR_DL_DEPLIBS
-#define STR_DL_DEPLIBS "dependency_libs="
- else if (strncmp (line, STR_DL_DEPLIBS,
- sizeof (STR_DL_DEPLIBS) - 1) == 0)
- {
- errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
- }
- else if (strcmp (line, "installed=yes\n") == 0)
- {
- installed = 1;
- }
- else if (strcmp (line, "installed=no\n") == 0)
- {
- installed = 0;
- }
-
-#undef STR_LIBRARY_NAMES
-#define STR_LIBRARY_NAMES "library_names="
- else if (!dlname && strncmp (line, STR_LIBRARY_NAMES,
- sizeof (STR_LIBRARY_NAMES) - 1) == 0)
- {
- char *last_libname;
- errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
- if (!errors
- && dlname && (last_libname = strrchr (dlname, ' ')) != 0)
- {
- last_libname = lt_estrdup (last_libname + 1);
- if (!last_libname)
- {
- ++errors;
- goto cleanup;
- }
- LT_DLMEM_REASSIGN (dlname, last_libname);
- }
- }
-
- if (errors)
- break;
- }
-
- fclose (file);
- LT_DLGNUNET_free (line);
-
- /* allocate the handle */
- *phandle =
- (lt_dlhandle) LT_EGNUNET_malloc (struct lt_dlhandle_struct, 1);
- if (*phandle == 0)
- ++errors;
-
- if (errors)
- {
- free_vars (dlname, old_name, libdir, deplibs);
- LT_DLGNUNET_free (*phandle);
- goto cleanup;
- }
-
- assert (*phandle);
-
- memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
- if (load_deplibs (*phandle, deplibs) == 0)
- {
- newhandle = *phandle;
- /* find_module may replace newhandle */
- if (find_module
- (&newhandle, dir, libdir, dlname, old_name, installed))
- {
- unload_deplibs (*phandle);
- ++errors;
- }
- }
- else
- {
- ++errors;
- }
-
- free_vars (dlname, old_name, libdir, deplibs);
- if (errors)
- {
- LT_DLGNUNET_free (*phandle);
- goto cleanup;
- }
-
- if (*phandle != newhandle)
- {
- unload_deplibs (*phandle);
- }
- }
- else
- {
- /* not a libtool module */
- *phandle =
- (lt_dlhandle) LT_EGNUNET_malloc (struct lt_dlhandle_struct, 1);
- if (*phandle == 0)
- {
- ++errors;
- goto cleanup;
- }
-
- memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
- newhandle = *phandle;
-
- /* If the module has no directory name component, try to find it
- first in user_search_path and then other prescribed paths.
- Otherwise (or in any case if the module was not yet found) try
- opening just the module name as passed. */
- if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
- && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
- &newhandle)
-#ifdef LTDL_SHLIBPATH_VAR
- && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
- &newhandle)
-#endif
-#ifdef LTDL_SYSSEARCHPATH
- && !find_handle (sys_search_path, base_name, &newhandle)
-#endif
- )))
- {
- if (tryall_dlopen (&newhandle, filename) != 0)
- {
- newhandle = NULL;
- }
- }
-
- if (!newhandle)
- {
- LT_DLGNUNET_free (*phandle);
- ++errors;
- goto cleanup;
- }
- }
-
-register_handle:
- LT_DLMEM_REASSIGN (*phandle, newhandle);
-
- if ((*phandle)->info.ref_count == 0)
- {
- (*phandle)->info.ref_count = 1;
- LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
-
- LT_DLGNUNET_mutex_lock ();
- (*phandle)->next = handles;
- handles = *phandle;
- LT_DLGNUNET_mutex_unlock ();
- }
-
- LT_DLMUTEX_SETERROR (saved_error);
-
-cleanup:
- LT_DLGNUNET_free (dir);
- LT_DLGNUNET_free (name);
- LT_DLGNUNET_free (canonical);
-
- return errors;
-}
-
-lt_dlhandle
-lt_dlopen (filename)
- const char *filename;
-{
- lt_dlhandle handle = 0;
-
- /* Just incase we missed a code path in try_dlopen() that reports
- an error, but forgets to reset handle... */
- if (try_dlopen (&handle, filename) != 0)
- return 0;
-
- return handle;
-}
-
-/* If the last error messge store was `FILE_NOT_FOUND', then return
- non-zero. */
-static int
-file_not_found ()
-{
- const char *error = 0;
-
- LT_DLMUTEX_GETERROR (error);
- if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
- return 1;
-
- return 0;
-}
-
-/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
- open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
- and if a file is still not found try again with SHLIB_EXT appended
- instead. */
-lt_dlhandle
-lt_dlopenext (filename)
- const char *filename;
-{
- lt_dlhandle handle = 0;
- char *tmp = 0;
- char *ext = 0;
- size_t len;
- int errors = 0;
-
- if (!filename)
- {
- return lt_dlopen (filename);
- }
-
- assert (filename);
-
- len = LT_STRLEN (filename);
- ext = strrchr (filename, '.');
-
- /* If FILENAME already bears a suitable extension, there is no need
- to try appending additional extensions. */
- if (ext && ((strcmp (ext, archive_ext) == 0)
-#ifdef LTDL_SHLIB_EXT
- || (strcmp (ext, shlib_ext) == 0)
-#endif
- ))
- {
- return lt_dlopen (filename);
- }
-
- /* First try appending ARCHIVE_EXT. */
- tmp = LT_EGNUNET_malloc (char, len + LT_STRLEN (archive_ext) + 1);
- if (!tmp)
- return 0;
-
- strcpy (tmp, filename);
- strcat (tmp, archive_ext);
- errors = try_dlopen (&handle, tmp);
-
- /* If we found FILENAME, stop searching -- whether we were able to
- load the file as a module or not. If the file exists but loading
- failed, it is better to return an error message here than to
- report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
- in the module search path. */
- if (handle || ((errors > 0) && !file_not_found ()))
- {
- LT_DLGNUNET_free (tmp);
- return handle;
- }
-
-#ifdef LTDL_SHLIB_EXT
- /* Try appending SHLIB_EXT. */
- if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
- {
- LT_DLGNUNET_free (tmp);
- tmp = LT_EGNUNET_malloc (char, len + LT_STRLEN (shlib_ext) + 1);
- if (!tmp)
- return 0;
-
- strcpy (tmp, filename);
- }
- else
- {
- tmp[len] = LT_EOS_CHAR;
- }
-
- strcat (tmp, shlib_ext);
- errors = try_dlopen (&handle, tmp);
-
- /* As before, if the file was found but loading failed, return now
- with the current error message. */
- if (handle || ((errors > 0) && !file_not_found ()))
- {
- LT_DLGNUNET_free (tmp);
- return handle;
- }
-#endif
-
- /* Still here? Then we really did fail to locate any of the file
- names we tried. */
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
- LT_DLGNUNET_free (tmp);
- return 0;
-}
-
-
-static int
-lt_argz_insert (pargz, pargz_len, before, entry)
- char **pargz;
- size_t *pargz_len;
- char *before;
- const char *entry;
-{
- error_t error;
-
- /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
- pargz_len, NULL, entry) failed with EINVAL. */
- if (before)
- error = argz_insert (pargz, pargz_len, before, entry);
- else
- error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
-
- if (error)
- {
- switch (error)
- {
- case ENOMEM:
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
- break;
- default:
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
- break;
- }
- return 1;
- }
-
- return 0;
-}
-
-static int
-lt_argz_insertinorder (pargz, pargz_len, entry)
- char **pargz;
- size_t *pargz_len;
- const char *entry;
-{
- char *before = 0;
-
- assert (pargz);
- assert (pargz_len);
- assert (entry && *entry);
-
- if (*pargz)
- while ((before = argz_next (*pargz, *pargz_len, before)))
- {
- int cmp = strcmp (entry, before);
-
- if (cmp < 0)
- break;
- if (cmp == 0)
- return 0; /* No duplicates! */
- }
-
- return lt_argz_insert (pargz, pargz_len, before, entry);
-}
-
-static int
-lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
- char **pargz;
- size_t *pargz_len;
- const char *dirnam;
- struct dirent *dp;
-{
- char *buf = 0;
- size_t buf_len = 0;
- char *end = 0;
- size_t end_offset = 0;
- size_t dir_len = 0;
- int errors = 0;
-
- assert (pargz);
- assert (pargz_len);
- assert (dp);
-
- dir_len = LT_STRLEN (dirnam);
- end = dp->d_name + LT_D_NAMLEN (dp);
-
- /* Ignore version numbers. */
- {
- char *p;
- for (p = end; p - 1 > dp->d_name; --p)
- if (strchr (".0123456789", p[-1]) == 0)
- break;
-
- if (*p == '.')
- end = p;
- }
-
- /* Ignore filename extension. */
- {
- char *p;
- for (p = end - 1; p > dp->d_name; --p)
- if (*p == '.')
- {
- end = p;
- break;
- }
- }
-
- /* Prepend the directory name. */
- end_offset = end - dp->d_name;
- buf_len = dir_len + 1 + end_offset;
- buf = LT_EGNUNET_malloc (char, 1 + buf_len);
- if (!buf)
- return ++errors;
-
- assert (buf);
-
- strcpy (buf, dirnam);
- strcat (buf, "/");
- strncat (buf, dp->d_name, end_offset);
- buf[buf_len] = LT_EOS_CHAR;
-
- /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
- if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
- ++errors;
-
- LT_DLGNUNET_free (buf);
-
- return errors;
-}
-
-static int
-list_files_by_dir (dirnam, pargz, pargz_len)
- const char *dirnam;
- char **pargz;
- size_t *pargz_len;
-{
- DIR *dirp = 0;
- int errors = 0;
-
- assert (dirnam && *dirnam);
- assert (pargz);
- assert (pargz_len);
- assert (dirnam[LT_STRLEN (dirnam) - 1] != '/');
-
- dirp = opendir (dirnam);
- if (dirp)
- {
- struct dirent *dp = 0;
-
- while ((dp = readdir (dirp)))
- if (dp->d_name[0] != '.')
- if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
- {
- ++errors;
- break;
- }
-
- closedir (dirp);
- }
- else
- ++errors;
-
- return errors;
-}
-
-
-/* If there are any files in DIRNAME, call the function passed in
- DATA1 (with the name of each file and DATA2 as arguments). */
-static int
-foreachfile_callback (dirname, data1, data2)
- char *dirname;
- lt_ptr data1;
- lt_ptr data2;
-{
- int (*func) LT_PARAMS ((const char *filename, lt_ptr data))
- = (int (*)LT_PARAMS ((const char *filename, lt_ptr data))) data1;
-
- int is_done = 0;
- char *argz = 0;
- size_t argz_len = 0;
-
- if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
- goto cleanup;
- if (!argz)
- goto cleanup;
-
- {
- char *filename = 0;
- while ((filename = argz_next (argz, argz_len, filename)))
- if ((is_done = (*func) (filename, data2)))
- break;
- }
-
-cleanup:
- LT_DLGNUNET_free (argz);
-
- return is_done;
-}
-
-
-/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
- with DATA. The filenames passed to FUNC would be suitable for
- passing to lt_dlopenext. The extensions are stripped so that
- individual modules do not generate several entries (e.g. libfoo.la,
- libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
- then the same directories that lt_dlopen would search are examined. */
-int
-lt_dlforeachfile (search_path, func, data)
- const char *search_path;
- int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
- lt_ptr data;
-{
- int is_done = 0;
-
- if (search_path)
- {
- /* If a specific path was passed, search only the directories
- listed in it. */
- is_done = foreach_dirinpath (search_path, 0,
- foreachfile_callback, func, data);
- }
- else
- {
- /* Otherwise search the default paths. */
- is_done = foreach_dirinpath (user_search_path, 0,
- foreachfile_callback, func, data);
- if (!is_done)
- {
- is_done = foreach_dirinpath (getenv ("LTDL_LIBRARY_PATH"), 0,
- foreachfile_callback, func, data);
- }
-
-#ifdef LTDL_SHLIBPATH_VAR
- if (!is_done)
- {
- is_done = foreach_dirinpath (getenv (LTDL_SHLIBPATH_VAR), 0,
- foreachfile_callback, func, data);
- }
-#endif
-#ifdef LTDL_SYSSEARCHPATH
- if (!is_done)
- {
- is_done = foreach_dirinpath (getenv (LTDL_SYSSEARCHPATH), 0,
- foreachfile_callback, func, data);
- }
-#endif
- }
-
- return is_done;
-}
-
-int
-lt_dlclose (handle)
- lt_dlhandle handle;
-{
- lt_dlhandle cur, last;
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
-
- /* check whether the handle is valid */
- last = cur = handles;
- while (cur && handle != cur)
- {
- last = cur;
- cur = cur->next;
- }
-
- if (!cur)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
- ++errors;
- goto done;
- }
-
- handle->info.ref_count--;
-
- /* Note that even with resident modules, we must track the ref_count
- correctly incase the user decides to reset the residency flag
- later (even though the API makes no provision for that at the
- moment). */
- if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
- {
- lt_user_data data = handle->loader->dlloader_data;
-
- if (handle != handles)
- {
- last->next = handle->next;
- }
- else
- {
- handles = handle->next;
- }
-
- errors += handle->loader->module_close (data, handle->module);
- errors += unload_deplibs (handle);
-
- /* It is up to the callers to free the data itself. */
- LT_DLGNUNET_free (handle->caller_data);
-
- LT_DLGNUNET_free (handle->info.filename);
- LT_DLGNUNET_free (handle->info.name);
- LT_DLGNUNET_free (handle);
-
- goto done;
- }
-
- if (LT_DLIS_RESIDENT (handle))
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
- ++errors;
- }
-
-done:
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-lt_ptr
-lt_dlsym (handle, symbol)
- lt_dlhandle handle;
- const char *symbol;
-{
- size_t lensym;
- char lsym[LT_SYMBOL_LENGTH];
- char *sym;
- lt_ptr address;
- lt_user_data data;
-
- if (!handle)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
- return 0;
- }
-
- if (!symbol)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
- return 0;
- }
-
- lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
- + LT_STRLEN (handle->info.name);
-
- if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
- {
- sym = lsym;
- }
- else
- {
- sym = LT_EGNUNET_malloc (char, lensym + LT_SYMBOL_OVERHEAD + 1);
- if (!sym)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
- return 0;
- }
- }
-
- data = handle->loader->dlloader_data;
- if (handle->info.name)
- {
- const char *saved_error;
-
- LT_DLMUTEX_GETERROR (saved_error);
-
- /* this is a libtool module */
- if (handle->loader->sym_prefix)
- {
- strcpy (sym, handle->loader->sym_prefix);
- strcat (sym, handle->info.name);
- }
- else
- {
- strcpy (sym, handle->info.name);
- }
-
- strcat (sym, "_LTX_");
- strcat (sym, symbol);
-
- /* try "modulename_LTX_symbol" */
- address = handle->loader->find_sym (data, handle->module, sym);
- if (address)
- {
- if (sym != lsym)
- {
- LT_DLGNUNET_free (sym);
- }
- return address;
- }
- LT_DLMUTEX_SETERROR (saved_error);
- }
-
- /* otherwise try "symbol" */
- if (handle->loader->sym_prefix)
- {
- strcpy (sym, handle->loader->sym_prefix);
- strcat (sym, symbol);
- }
- else
- {
- strcpy (sym, symbol);
- }
-
- address = handle->loader->find_sym (data, handle->module, sym);
- if (sym != lsym)
- {
- LT_DLGNUNET_free (sym);
- }
-
- return address;
-}
-
-const char *
-lt_dlerror ()
-{
- const char *error;
-
- LT_DLMUTEX_GETERROR (error);
- LT_DLMUTEX_SETERROR (0);
-
- return error ? error : NULL;
-}
-
-static int
-lt_dlpath_insertdir (ppath, before, dir)
- char **ppath;
- char *before;
- const char *dir;
-{
- int errors = 0;
- char *canonical = 0;
- char *argz = 0;
- size_t argz_len = 0;
-
- assert (ppath);
- assert (dir && *dir);
-
- if (canonicalize_path (dir, &canonical) != 0)
- {
- ++errors;
- goto cleanup;
- }
-
- assert (canonical && *canonical);
-
- /* If *PPATH is empty, set it to DIR. */
- if (*ppath == 0)
- {
- assert (!before); /* BEFORE cannot be set without PPATH. */
- assert (dir); /* Without DIR, don't call this function! */
-
- *ppath = lt_estrdup (dir);
- if (*ppath == 0)
- ++errors;
-
- return errors;
- }
-
- assert (ppath && *ppath);
-
- if (argzize_path (*ppath, &argz, &argz_len) != 0)
- {
- ++errors;
- goto cleanup;
- }
-
- /* Convert BEFORE into an equivalent offset into ARGZ. This only works
- if *PPATH is already canonicalized, and hence does not change length
- with respect to ARGZ. We canonicalize each entry as it is added to
- the search path, and don't call this function with (uncanonicalized)
- user paths, so this is a fair assumption. */
- if (before)
- {
- assert (*ppath <= before);
- assert (before - *ppath <= strlen (*ppath));
-
- before = before - *ppath + argz;
- }
-
- if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
- {
- ++errors;
- goto cleanup;
- }
-
- argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
- LT_DLMEM_REASSIGN (*ppath, argz);
-
-cleanup:
- LT_DLGNUNET_free (canonical);
- LT_DLGNUNET_free (argz);
-
- return errors;
-}
-
-int
-lt_dladdsearchdir (search_dir)
- const char *search_dir;
-{
- int errors = 0;
-
- if (search_dir && *search_dir)
- {
- LT_DLGNUNET_mutex_lock ();
- if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
- ++errors;
- LT_DLGNUNET_mutex_unlock ();
- }
-
- return errors;
-}
-
-int
-lt_dlinsertsearchdir (before, search_dir)
- const char *before;
- const char *search_dir;
-{
- int errors = 0;
-
- if (before)
- {
- LT_DLGNUNET_mutex_lock ();
- if ((before < user_search_path)
- || (before >= user_search_path + LT_STRLEN (user_search_path)))
- {
- LT_DLGNUNET_mutex_unlock ();
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
- return 1;
- }
- LT_DLGNUNET_mutex_unlock ();
- }
-
- if (search_dir && *search_dir)
- {
- LT_DLGNUNET_mutex_lock ();
- if (lt_dlpath_insertdir (&user_search_path,
- (char *) before, search_dir) != 0)
- {
- ++errors;
- }
- LT_DLGNUNET_mutex_unlock ();
- }
-
- return errors;
-}
-
-int
-lt_dlsetsearchpath (search_path)
- const char *search_path;
-{
- int errors = 0;
-
- LT_DLGNUNET_mutex_lock ();
- LT_DLGNUNET_free (user_search_path);
- LT_DLGNUNET_mutex_unlock ();
-
- if (!search_path || !LT_STRLEN (search_path))
- {
- return errors;
- }
-
- LT_DLGNUNET_mutex_lock ();
- if (canonicalize_path (search_path, &user_search_path) != 0)
- ++errors;
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-const char *
-lt_dlgetsearchpath ()
-{
- const char *saved_path;
-
- LT_DLGNUNET_mutex_lock ();
- saved_path = user_search_path;
- LT_DLGNUNET_mutex_unlock ();
-
- return saved_path;
-}
-
-int
-lt_dlmakeresident (handle)
- lt_dlhandle handle;
-{
- int errors = 0;
-
- if (!handle)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
- ++errors;
- }
- else
- {
- LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
- }
-
- return errors;
-}
-
-int
-lt_dlisresident (handle)
- lt_dlhandle handle;
-{
- if (!handle)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
- return -1;
- }
-
- return LT_DLIS_RESIDENT (handle);
-}
-
-
-
-
-/* --- MODULE INFORMATION --- */
-
-const lt_dlinfo *
-lt_dlgetinfo (handle)
- lt_dlhandle handle;
-{
- if (!handle)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
- return 0;
- }
-
- return &(handle->info);
-}
-
-lt_dlhandle
-lt_dlhandle_next (place)
- lt_dlhandle place;
-{
- return place ? place->next : handles;
-}
-
-int
-lt_dlforeach (func, data)
- int (*func) LT_PARAMS ((lt_dlhandle handle, lt_ptr data));
- lt_ptr data;
-{
- int errors = 0;
- lt_dlhandle cur;
-
- LT_DLGNUNET_mutex_lock ();
-
- cur = handles;
- while (cur)
- {
- lt_dlhandle tmp = cur;
-
- cur = cur->next;
- if ((*func) (tmp, data))
- {
- ++errors;
- break;
- }
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-lt_dlcaller_id
-lt_dlcaller_register ()
-{
- static lt_dlcaller_id last_caller_id = 0;
- int result;
-
- LT_DLGNUNET_mutex_lock ();
- result = ++last_caller_id;
- LT_DLGNUNET_mutex_unlock ();
-
- return result;
-}
-
-lt_ptr
-lt_dlcaller_set_data (key, handle, data)
- lt_dlcaller_id key;
- lt_dlhandle handle;
- lt_ptr data;
-{
- int n_elements = 0;
- lt_ptr stale = (lt_ptr) 0;
- int i;
-
- /* This needs to be locked so that the caller data can be updated
- simultaneously by different threads. */
- LT_DLGNUNET_mutex_lock ();
-
- if (handle->caller_data)
- while (handle->caller_data[n_elements].key)
- ++n_elements;
-
- for (i = 0; i < n_elements; ++i)
- {
- if (handle->caller_data[i].key == key)
- {
- stale = handle->caller_data[i].data;
- break;
- }
- }
-
- /* Ensure that there is enough room in this handle's caller_data
- array to accept a new element (and an empty end marker). */
- if (i == n_elements)
- {
- lt_caller_data *temp
- = LT_DLGNUNET_realloc (lt_caller_data, handle->caller_data,
- 2 + n_elements);
-
- if (!temp)
- {
- stale = 0;
- goto done;
- }
-
- handle->caller_data = temp;
-
- /* We only need this if we needed to allocate a new caller_data. */
- handle->caller_data[i].key = key;
- handle->caller_data[1 + i].key = 0;
- }
-
- handle->caller_data[i].data = data;
-
-done:
- LT_DLGNUNET_mutex_unlock ();
-
- return stale;
-}
-
-lt_ptr
-lt_dlcaller_get_data (key, handle)
- lt_dlcaller_id key;
- lt_dlhandle handle;
-{
- lt_ptr result = (lt_ptr) 0;
-
- /* This needs to be locked so that the caller data isn't updated by
- another thread part way through this function. */
- LT_DLGNUNET_mutex_lock ();
-
- /* Locate the index of the element with a matching KEY. */
- {
- int i;
- for (i = 0; handle->caller_data[i].key; ++i)
- {
- if (handle->caller_data[i].key == key)
- {
- result = handle->caller_data[i].data;
- break;
- }
- }
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return result;
-}
-
-
-
-/* --- USER MODULE LOADER API --- */
-
-
-int
-lt_dlloader_add (place, dlloader, loader_name)
- lt_dlloader *place;
- const struct lt_user_dlloader *dlloader;
- const char *loader_name;
-{
- int errors = 0;
- lt_dlloader *node = 0, *ptr = 0;
-
- if ((dlloader == 0) /* diagnose null parameters */
- || (dlloader->module_open == 0)
- || (dlloader->module_close == 0) || (dlloader->find_sym == 0))
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
- return 1;
- }
-
- /* Create a new dlloader node with copies of the user callbacks. */
- node = LT_EGNUNET_malloc (lt_dlloader, 1);
- if (!node)
- return 1;
-
- node->next = 0;
- node->loader_name = loader_name;
- node->sym_prefix = dlloader->sym_prefix;
- node->dlloader_exit = dlloader->dlloader_exit;
- node->module_open = dlloader->module_open;
- node->module_close = dlloader->module_close;
- node->find_sym = dlloader->find_sym;
- node->dlloader_data = dlloader->dlloader_data;
-
- LT_DLGNUNET_mutex_lock ();
- if (!loaders)
- {
- /* If there are no loaders, NODE becomes the list! */
- loaders = node;
- }
- else if (!place)
- {
- /* If PLACE is not set, add NODE to the end of the
- LOADERS list. */
- for (ptr = loaders; ptr->next; ptr = ptr->next)
- {
- /*NOWORK*/;
- }
-
- ptr->next = node;
- }
- else if (loaders == place)
- {
- /* If PLACE is the first loader, NODE goes first. */
- node->next = place;
- loaders = node;
- }
- else
- {
- /* Find the node immediately preceding PLACE. */
- for (ptr = loaders; ptr->next != place; ptr = ptr->next)
- {
- /*NOWORK*/;
- }
-
- if (ptr->next != place)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
- ++errors;
- }
- else
- {
- /* Insert NODE between PTR and PLACE. */
- node->next = place;
- ptr->next = node;
- }
- }
-
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-int
-lt_dlloader_remove (loader_name)
- const char *loader_name;
-{
- lt_dlloader *place = lt_dlloader_find (loader_name);
- lt_dlhandle handle;
- int errors = 0;
-
- if (!place)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
- return 1;
- }
-
- LT_DLGNUNET_mutex_lock ();
-
- /* Fail if there are any open modules which use this loader. */
- for (handle = handles; handle; handle = handle->next)
- {
- if (handle->loader == place)
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
- ++errors;
- goto done;
- }
- }
-
- if (place == loaders)
- {
- /* PLACE is the first loader in the list. */
- loaders = loaders->next;
- }
- else
- {
- /* Find the loader before the one being removed. */
- lt_dlloader *prev;
- for (prev = loaders; prev->next; prev = prev->next)
- {
- if (!strcmp (prev->next->loader_name, loader_name))
- {
- break;
- }
- }
-
- place = prev->next;
- prev->next = prev->next->next;
- }
-
- if (place->dlloader_exit)
- {
- errors = place->dlloader_exit (place->dlloader_data);
- }
-
- LT_DLGNUNET_free (place);
-
-done:
- LT_DLGNUNET_mutex_unlock ();
-
- return errors;
-}
-
-lt_dlloader *
-lt_dlloader_next (place)
- lt_dlloader *place;
-{
- lt_dlloader *next;
-
- LT_DLGNUNET_mutex_lock ();
- next = place ? place->next : loaders;
- LT_DLGNUNET_mutex_unlock ();
-
- return next;
-}
-
-const char *
-lt_dlloader_name (place)
- lt_dlloader *place;
-{
- const char *name = 0;
-
- if (place)
- {
- LT_DLGNUNET_mutex_lock ();
- name = place ? place->loader_name : 0;
- LT_DLGNUNET_mutex_unlock ();
- }
- else
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
- }
-
- return name;
-}
-
-lt_user_data *
-lt_dlloader_data (place)
- lt_dlloader *place;
-{
- lt_user_data *data = 0;
-
- if (place)
- {
- LT_DLGNUNET_mutex_lock ();
- data = place ? &(place->dlloader_data) : 0;
- LT_DLGNUNET_mutex_unlock ();
- }
- else
- {
- LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
- }
-
- return data;
-}
-
-lt_dlloader *
-lt_dlloader_find (loader_name)
- const char *loader_name;
-{
- lt_dlloader *place = 0;
-
- LT_DLGNUNET_mutex_lock ();
- for (place = loaders; place; place = place->next)
- {
- if (strcmp (place->loader_name, loader_name) == 0)
- {
- break;
- }
- }
- LT_DLGNUNET_mutex_unlock ();
-
- return place;
-}
Modified: GNUnet/libltdl/ltmain.sh
===================================================================
--- GNUnet/libltdl/ltmain.sh 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/libltdl/ltmain.sh 2008-02-06 07:11:29 UTC (rev 6162)
@@ -43,7 +43,7 @@
PROGRAM=ltmain.sh
PACKAGE=libtool
-VERSION="1.5.24 Debian 1.5.24-1"
+VERSION="1.5.24 Debian 1.5.24-2"
TIMESTAMP=" (1.1220.2.456 2007/06/24 02:25:32)"
# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
Modified: GNUnet/src/applications/Makefile.am
===================================================================
--- GNUnet/src/applications/Makefile.am 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/applications/Makefile.am 2008-02-06 07:11:29 UTC (rev 6162)
@@ -6,9 +6,6 @@
SQLITE_DIR = sqstore_sqlite kvstore_sqlite dstore_sqlite
endif
-if !MINGW
-# TESTBED_DIR = testbed
-endif
if LINUX
VPN_DIR = vpn
endif
@@ -34,9 +31,7 @@
traffic \
transport \
advertising \
- gap \
dht \
tracekit \
$(VPN_DIR)
-# $(TESTBED_DIR)
# chat
Modified: GNUnet/src/applications/fs/Makefile.am
===================================================================
--- GNUnet/src/applications/fs/Makefile.am 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/applications/fs/Makefile.am 2008-02-06 07:11:29 UTC (rev
6162)
@@ -1,5 +1,5 @@
SUBDIRS = \
- . module lib ecrs uritrack namespace fsui collection tools
+ . gap lib ecrs uritrack namespace fsui collection tools
INCLUDES = -I$(top_srcdir)/src/include
Modified: GNUnet/src/applications/fs/ecrs/download.c
===================================================================
--- GNUnet/src/applications/fs/ecrs/download.c 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/applications/fs/ecrs/download.c 2008-02-06 07:11:29 UTC (rev
6162)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other
contributing authors)
+ (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and
other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -19,7 +19,7 @@
*/
/**
* @file applications/fs/ecrs/download.c
- * @brief GNUNET_ND_DOWNLOAD helper methods (which do the real work).
+ * @brief DOWNLOAD helper methods (which do the real work).
* @author Christian Grothoff
*/
@@ -35,48 +35,114 @@
#define DEBUG_DOWNLOAD GNUNET_NO
/**
- * Highest TTL allowed? (equivalent of 25-50 HOPS distance!)
+ * Node-specific data (not shared, keep small!). 152 bytes.
+ * Nodes are kept in a doubly-linked list.
*/
-#define MAX_TTL (100 * TTL_DECREMENT)
+struct Node
+{
+ /**
+ * Pointer to shared data between all nodes (request manager,
+ * progress data, etc.).
+ */
+ struct RequestManager *ctx;
-/**
- * After how many retries do we print a warning?
- */
-#define MAX_TRIES 500
+ /**
+ * Previous entry in DLL.
+ */
+ struct Node * prev;
+ /**
+ * Next entry in DLL.
+ */
+ struct Node * next;
-/* ****************** IO context **************** */
+ /**
+ * What is the CHK for this block?
+ */
+ CHK 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 IO context for reading-writing file blocks.
+ * @brief structure that keeps track of currently pending requests for
+ * a download
*
- * In GNUnet, files are stored in the form of a balanced tree, not
- * unlike INodes in unix filesystems. When we download files, the
- * inner nodes of the tree are stored under FILENAME.X (where X
- * characterizes the level of the node in the tree). If the download
- * is aborted and resumed later, these .X files can be used to avoid
- * downloading the inner blocks again. The successfully received leaf
- * nodes in FILENAME (the target file) are of course also not
- * downloaded again.<p>
- *
- * The IOContext struct presents an easy api to access the various
- * dot-files. It uses function pointers to allow implementors to
- * provide a different mechanism (other than files on the drive) to
- * cache the IBlocks.
+ * 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.
*/
-typedef struct IOContext
+struct RequestManager
{
- struct GNUNET_GE_Context *ectx;
+ /**
+ * Total number of bytes in the file.
+ */
+ unsigned long long total;
/**
- * A lock for synchronizing access.
+ * 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;
+
+ /**
+ * Mutex for synchronizing access to this struct
+ */
struct GNUNET_Mutex *lock;
/**
- * The file handles for each level in the tree.
+ * 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 handles for each level in the download-tree.
+ */
int *handles;
/**
@@ -85,12 +151,51 @@
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.
+ */
+ 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;
-} IOContext;
+};
+
/**
* Close the files in the IOContext and free
* the associated resources. Does NOT free
@@ -103,30 +208,51 @@
* is not complete and may be resumed later.
*/
static void
-freeIOC (IOContext * this, int unlinkTreeFiles)
+free_request_manager(struct RequestManager * rm,
+ int unlinkTreeFiles)
{
int i;
char *fn;
+ struct Node * pos;
- for (i = 0; i <= this->treedepth; i++)
+ GNUNET_mutex_lock (rm->lock);
+ /* cannot hold lock during shutdown since
+ fslib may have to aquire it; but we can
+ flag that we are in the shutdown process
+ and start to ignore fslib events! */
+ rm->abortFlag = GNUNET_YES;
+ GNUNET_mutex_unlock (rm->lock);
+ GNUNET_FS_destroy_search_context(rm->sctx);
+ rm->sctx = NULL;
+ while (rm->head != NULL)
{
- if (this->handles[i] != -1)
+ pos = rm->head;
+ rm->head = pos->next;
+ GNUNET_free(pos);
+ }
+ rm->tail = NULL;
+ for (i = 0; i <= rm->treedepth; i++)
+ {
+ if (rm->handles[i] != -1)
{
- CLOSE (this->handles[i]);
- this->handles[i] = -1;
+ CLOSE (rm->handles[i]);
+ rm->handles[i] = -1;
}
}
- GNUNET_mutex_destroy (this->lock);
+ if (rm->lock != NULL)
+ GNUNET_mutex_destroy (rm->lock);
+ if (rm->main != NULL)
+ GNUNET_thread_release_self(rm->main);
if (GNUNET_YES == unlinkTreeFiles)
{
- for (i = 1; i <= this->treedepth; i++)
+ for (i = 1; i <= rm->treedepth; i++)
{
- fn = GNUNET_malloc (strlen (this->filename) + 3);
- strcpy (fn, this->filename);
+ fn = GNUNET_malloc (strlen (rm->filename) + 3);
+ strcpy (fn, rm->filename);
strcat (fn, ".A");
fn[strlen (fn) - 1] += i;
if (0 != UNLINK (fn))
- GNUNET_GE_LOG (this->ectx,
+ GNUNET_GE_LOG (rm->ectx,
GNUNET_GE_WARNING | GNUNET_GE_BULK |
GNUNET_GE_USER,
_("Could not unlink temporary file `%s': %s\n"),
@@ -134,78 +260,11 @@
GNUNET_free (fn);
}
}
- GNUNET_free (this->filename);
- GNUNET_free (this->handles);
+ GNUNET_free_non_null (rm->filename);
+ GNUNET_free_non_null (rm->handles);
}
/**
- * Initialize an IOContext.
- *
- * @param this the context to initialize
- * @param no_temporaries disallow creation of temp files
- * @param filesize the size of the file
- * @param filename the name of the level-0 file
- * @return GNUNET_OK on success, GNUNET_SYSERR on failure
- */
-static int
-createIOContext (struct GNUNET_GE_Context *ectx,
- IOContext * this,
- int no_temporaries,
- unsigned long long filesize, const char *filename)
-{
- int i;
- char *fn;
- struct stat st;
-
- this->ectx = ectx;
- GNUNET_GE_ASSERT (ectx, filename != NULL);
- this->treedepth = GNUNET_ECRS_compute_depth (filesize);
- this->lock = GNUNET_mutex_create (GNUNET_NO);
- this->handles = GNUNET_malloc (sizeof (int) * (this->treedepth + 1));
- this->filename = GNUNET_strdup (filename);
-
- if ((0 == STAT (filename, &st)) && ((size_t) st.st_size > filesize))
- {
- /* if exists and oversized, truncate */
- if (truncate (filename, filesize) != 0)
- {
- GNUNET_GE_LOG_STRERROR_FILE (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
- GNUNET_GE_BULK, "truncate", filename);
- return GNUNET_SYSERR;
- }
- }
- for (i = 0; i <= this->treedepth; i++)
- this->handles[i] = -1;
-
- for (i = 0; i <= this->treedepth; i++)
- {
- if ((i == 0) || (no_temporaries != GNUNET_YES))
- {
- fn = GNUNET_malloc (strlen (filename) + 3);
- strcpy (fn, filename);
- if (i > 0)
- {
- strcat (fn, ".A");
- fn[strlen (fn) - 1] += i;
- }
- this->handles[i] = GNUNET_disk_file_open (ectx,
- fn,
- O_CREAT | O_RDWR,
- S_IRUSR | S_IWUSR);
- if (this->handles[i] < 0)
- {
- freeIOC (this, GNUNET_YES);
- GNUNET_free (fn);
- return GNUNET_SYSERR;
- }
- GNUNET_free (fn);
- }
- }
- return GNUNET_OK;
-}
-
-/**
* Read method.
*
* @param this reference to the IOContext
@@ -216,21 +275,16 @@
* @return number of bytes read, GNUNET_SYSERR on error
*/
static int
-readFromIOC (IOContext * this,
+read_from_files (struct RequestManager * this,
unsigned int level,
unsigned long long pos, void *buf, unsigned int len)
{
int ret;
- GNUNET_mutex_lock (this->lock);
if (this->handles[level] == -1)
- {
- GNUNET_mutex_unlock (this->lock);
- return GNUNET_SYSERR;
- }
+ return GNUNET_SYSERR;
LSEEK (this->handles[level], pos, SEEK_SET);
ret = READ (this->handles[level], buf, len);
- GNUNET_mutex_unlock (this->lock);
#if DEBUG_DOWNLOAD
GNUNET_GE_LOG (this->ectx,
GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
@@ -251,18 +305,14 @@
* @return number of bytes written, GNUNET_SYSERR on error
*/
static int
-writeToIOC (IOContext * this,
+write_to_files (struct RequestManager * this,
unsigned int level,
unsigned long long pos, void *buf, unsigned int len)
{
int ret;
- GNUNET_mutex_lock (this->lock);
if ((this->handles[level] == -1) && (level > 0))
- {
- GNUNET_mutex_unlock (this->lock);
- return len; /* lie -- no temps allowed... */
- }
+ return len; /* lie -- no temps allowed... */
LSEEK (this->handles[level], pos, SEEK_SET);
ret = WRITE (this->handles[level], buf, len);
if (ret != len)
@@ -272,400 +322,77 @@
_("Write(%d, %p, %d) failed: %s\n"),
this->handles[level], buf, len, STRERROR (errno));
}
- GNUNET_mutex_unlock (this->lock);
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (this->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "IOC write at level %u offset %llu writes %u\n", level, pos,
- len);
-#endif
return ret;
}
-/* ********************* request manager **************** */
+static int
+content_receive_callback (const GNUNET_HashCode * query,
+ const GNUNET_DatastoreValue * reply, void *cls,
+ unsigned long long uid);
/**
- * Node-specific data (not shared, keep small!). 56 bytes.
- */
-typedef struct
-{
- /**
- * Pointer to shared data between all nodes (request manager,
- * progress data, etc.).
- */
- struct CommonCtx *ctx;
-
- /**
- * What is the CHK for this block?
- */
- CHK chk;
-
- /**
- * At what offset (on the respective level!) is this
- * block?
- */
- unsigned long long offset;
-
- /**
- * 0 for dblocks, >0 for iblocks.
- */
- unsigned int level;
-} NodeClosure;
-
-/**
- * @brief Format of a request as tracked by the RequestManager.
+ * Queue a request for execution.
*
- * This structure together with the NodeContext determine the memory
- * requirements, so try keeping it as small as possible! (currently
- * 32 bytes, plus 56 in the NodeContext => roughly 88 byte per block!)
- *
- * Estimate: max ~12 MB memory for a 4 GB file in the end (assuming
- * maximum parallelism, which is likely, so we are really going to use
- * about 12 MB, but that should be acceptable).
- *
- * Design question: why not union RequestEntry and NodeClosure (would
- * save yet another 4 bytes / entry)?
- */
-typedef struct RequestEntry
-{
-
- /**
- * The node for which this entry keeps data.
- */
- NodeClosure *node;
-
- /**
- * Search handle of the last request (NULL if never
- * requested).
- */
- struct GNUNET_FS_SearchHandle *searchHandle;
-
- /**
- * Last time the query was send.
- */
- GNUNET_CronTime lasttime;
-
- /**
- * Timeout used for the last search (ttl in request is
- * = lastTimeout - lasttime modulo corrections in gap
- * with respect to priority cap).
- */
- GNUNET_CronTime lastTimeout;
-
- /**
- * How long have we been actively trying this one?
- */
- unsigned int tries;
-
- /**
- * Priority used for the last request.
- */
- unsigned int lastPriority;
-
-} RequestEntry;
-
-/**
- * @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.
- */
-typedef struct RequestManager
-{
-
- /**
- * Mutex for synchronizing access to this struct
- */
- struct GNUNET_Mutex *lock;
-
- /**
- * Current list of all pending requests
- */
- RequestEntry **requestList;
-
- struct GNUNET_FS_SearchContext *sctx;
-
- struct GNUNET_ThreadHandle *requestThread;
-
- struct GNUNET_GE_Context *ectx;
-
- struct GNUNET_GC_Configuration *cfg;
-
- GNUNET_PeerIdentity target;
-
- /**
- * Number of pending requests (highest used index)
- */
- unsigned int requestListIndex;
-
- /**
- * Number of entries allocated for requestList
- */
- unsigned int requestListSize;
-
- /**
- * Current "good" TTL (initial) [64s]. In HOST byte order.
- */
- unsigned int initialTTL;
-
- /**
- * Congestion window. How many messages
- * should be pending concurrently?
- */
- unsigned int congestionWindow;
-
- /**
- * Slow-start threshold (see RFC 2001)
- */
- unsigned int ssthresh;
-
- /**
- * What was the last time we updated ssthresh?
- */
- GNUNET_Int32Time lastDET;
-
- /**
- * Abort? Flag that can be set at any time
- * to abort the RM as soon as possible.
- */
- int abortFlag;
-
- /**
- * Is the request manager being destroyed?
- * (if so, accessing the request list is illegal!)
- */
- int shutdown;
-
- /**
- * Do we have a specific peer from which we download
- * from?
- */
- int have_target;
-
-} RequestManager;
-
-/**
- * Create a request manager. Will create the request manager
- * datastructures. Use destroyRequestManager to abort and/or to free
- * resources after the download is complete.
- *
- * @return NULL on error
- */
-static RequestManager *
-createRequestManager (struct GNUNET_GE_Context *ectx,
- struct GNUNET_GC_Configuration *cfg)
-{
- RequestManager *rm;
-
- rm = GNUNET_malloc (sizeof (RequestManager));
- rm->shutdown = GNUNET_NO;
- rm->lock = GNUNET_mutex_create (GNUNET_YES);
- rm->sctx = GNUNET_FS_create_search_context (ectx, cfg, rm->lock);
- if (rm->sctx == NULL)
- {
- GNUNET_mutex_destroy (rm->lock);
- GNUNET_free (rm);
- return NULL;
- }
- rm->ectx = ectx;
- rm->cfg = cfg;
- rm->requestThread = GNUNET_thread_get_self ();
- rm->abortFlag = GNUNET_NO;
- rm->lastDET = 0;
- rm->requestListIndex = 0;
- rm->requestListSize = 0;
- rm->requestList = NULL;
- rm->have_target = GNUNET_NO;
- GNUNET_array_grow (rm->requestList, rm->requestListSize, 256);
- rm->initialTTL = 5 * GNUNET_CRON_SECONDS;
- /* RFC 2001 suggests to use 1 segment size initially;
- Given 1500 octets per message in GNUnet, we would
- have 2-3 queries of maximum size (552); but since
- we are multi-casting to many peers at the same
- time AND since queries can be much smaller,
- we do WHAT??? */
- rm->congestionWindow = 1; /* RSS is 1 */
- rm->ssthresh = 65535;
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "created request manager %p\n", rm);
-#endif
- return rm;
-}
-
-/**
- * Destroy the resources associated with a request manager.
- * Invoke this method to abort the download or to clean up
- * after the download is complete.
- *
* @param rm the request manager struct from createRequestManager
+ * @param node the node to call once a reply is received
*/
static void
-destroyRequestManager (RequestManager * rm)
+addRequest (struct Node * node)
{
- int i;
+ struct RequestManager * rm = node->ctx;
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (rm->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "destroying request manager %p\n", rm);
-#endif
- GNUNET_mutex_lock (rm->lock);
- /* cannot hold lock during shutdown since
- fslib may have to aquire it; but we can
- flag that we are in the shutdown process
- and start to ignore fslib events! */
- rm->shutdown = GNUNET_YES;
- GNUNET_mutex_unlock (rm->lock);
- for (i = 0; i < rm->requestListIndex; i++)
- {
- if (rm->requestList[i]->searchHandle != NULL)
- GNUNET_FS_stop_search (rm->sctx, rm->requestList[i]->searchHandle);
- GNUNET_free (rm->requestList[i]->node);
- GNUNET_free (rm->requestList[i]);
- }
- GNUNET_array_grow (rm->requestList, rm->requestListSize, 0);
- GNUNET_FS_destroy_search_context (rm->sctx);
- rm->sctx = NULL;
- GNUNET_mutex_destroy (rm->lock);
- GNUNET_thread_release_self (rm->requestThread);
- GNUNET_free (rm);
+ node->next = rm->head;
+ node->next->prev = node;
+ node->prev = NULL;
+ rm->head = node;
+ if (rm->tail == NULL)
+ 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);
}
-/**
- * We are approaching the end of the download. Cut
- * all TTLs in half.
- */
static void
-requestManagerEndgame (RequestManager * rm)
+signal_abort(struct RequestManager * rm)
{
- int i;
-
- GNUNET_mutex_lock (rm->lock);
- if (rm->shutdown == GNUNET_NO)
- {
- for (i = 0; i < rm->requestListIndex; i++)
- {
- RequestEntry *entry = rm->requestList[i];
- /* cut TTL in half */
- entry->lasttime += (entry->lasttime + entry->lastTimeout) / 2;
- }
- }
- GNUNET_mutex_unlock (rm->lock);
+ rm->abortFlag = GNUNET_YES;
+ GNUNET_thread_stop_sleep(rm->main);
}
/**
- * Queue a request for execution.
+ * Dequeue a request.
*
- * @param rm the request manager struct from createRequestManager
- * @param node the node to call once a reply is received
- */
-static void
-addRequest (RequestManager * rm, NodeClosure * node)
-{
- RequestEntry *entry;
-#if DEBUG_DOWNLOAD
- GNUNET_EncName enc;
-
- IF_GELOG (rm->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- GNUNET_hash_to_enc (&node->chk.query, &enc));
- GNUNET_GE_LOG (rm->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Queuing request (query: %s)\n", &enc);
-#endif
-
- GNUNET_GE_ASSERT (rm->ectx, node != NULL);
- entry = GNUNET_malloc (sizeof (RequestEntry));
- entry->node = node;
- entry->lasttime = 0; /* never sent */
- entry->lastTimeout = 0;
- entry->tries = 0; /* not tried so far */
- entry->lastPriority = 0;
- entry->searchHandle = NULL;
- GNUNET_mutex_lock (rm->lock);
- if (rm->shutdown == GNUNET_NO)
- {
- GNUNET_GE_ASSERT (rm->ectx, rm->requestListSize > 0);
- if (rm->requestListSize == rm->requestListIndex)
- GNUNET_array_grow (rm->requestList, rm->requestListSize,
- rm->requestListSize * 2);
- rm->requestList[rm->requestListIndex++] = entry;
- }
- else
- {
- GNUNET_GE_BREAK (rm->ectx, 0);
- GNUNET_free (entry);
- }
- GNUNET_mutex_unlock (rm->lock);
-}
-
-
-/**
- * Cancel a request.
- *
* @param this the request manager struct from createRequestManager
* @param node the block for which the request is canceled
*/
static void
-delRequest (RequestManager * rm, NodeClosure * node)
+delete_node (struct Node * node)
{
- int i;
- RequestEntry *re;
+ struct RequestManager * rm = node->ctx;
- GNUNET_mutex_lock (rm->lock);
- if (rm->shutdown == GNUNET_NO)
- {
- for (i = 0; i < rm->requestListIndex; i++)
- {
- re = rm->requestList[i];
- if (re->node == node)
- {
- rm->requestList[i] = rm->requestList[--rm->requestListIndex];
- rm->requestList[rm->requestListIndex] = NULL;
- GNUNET_mutex_unlock (rm->lock);
- if (NULL != re->searchHandle)
- GNUNET_FS_stop_search (rm->sctx, re->searchHandle);
- GNUNET_free (re);
- return;
- }
- }
- }
- GNUNET_mutex_unlock (rm->lock);
- GNUNET_GE_BREAK (rm->ectx, 0); /* uh uh - at least a memory leak... */
+ if (node->prev == NULL)
+ rm->head = node->next;
+ else
+ node->prev->next = node->next;
+ if (node->next == NULL)
+ rm->tail = node->prev;
+ else
+ node->next->prev = node->prev;
+ GNUNET_free(node);
+ if (rm->head == NULL)
+ signal_abort(rm);
}
-
-/* ****************** tree nodes ***************** */
-
/**
- * Data shared between all tree nodes.
- * Design Question: integrate with IOContext?
- */
-typedef struct CommonCtx
-{
- unsigned long long total;
- unsigned long long completed;
- unsigned long long offset;
- unsigned long long length;
- GNUNET_CronTime startTime;
- GNUNET_CronTime TTL_DECREMENT;
- RequestManager *rm;
- IOContext *ioc;
- GNUNET_ECRS_DownloadProgressCallback dpcb;
- void *dpcbClosure;
- unsigned int anonymityLevel;
-} CommonCtx;
-
-/**
* Compute how many bytes of data are stored in
* this node.
*/
static unsigned int
-getNodeSize (const NodeClosure * node)
+get_node_size (const struct Node * node)
{
unsigned int i;
unsigned int ret;
@@ -673,7 +400,7 @@
unsigned long long spos;
unsigned long long epos;
- GNUNET_GE_ASSERT (node->ctx->rm->ectx, node->offset < node->ctx->total);
+ GNUNET_GE_ASSERT (node->ctx->ectx, node->offset < node->ctx->total);
if (node->level == 0)
{
ret = DBLOCK_SIZE;
@@ -707,111 +434,38 @@
}
/**
- * Update progress information. Also updates
- * request manager structures, like ttl.
+ * Notify client about progress.
*/
static void
-updateProgress (const NodeClosure * node, const char *data, unsigned int size)
+notify_client_about_progress (const struct Node * node, const char *data,
unsigned int size)
{
- RequestManager *rm;
- RequestEntry *entry;
- int pos;
- int i;
+ struct RequestManager *rm = node->ctx;
+ GNUNET_CronTime eta;
- /* locking? */
- if (node->level == 0)
- {
- GNUNET_CronTime eta;
-
- node->ctx->completed += size;
- eta = GNUNET_get_time ();
- if (node->ctx->completed > 0)
- {
- eta = (GNUNET_CronTime) (node->ctx->startTime +
- (((double) (eta - node->ctx->startTime) /
- (double) node->ctx->completed)) *
- (double) node->ctx->length);
- }
- if (node->ctx->dpcb != NULL)
- {
- node->ctx->dpcb (node->ctx->length,
- node->ctx->completed,
- eta,
- node->offset, data, size, node->ctx->dpcbClosure);
- }
- }
- rm = node->ctx->rm;
- GNUNET_mutex_lock (rm->lock);
- if (rm->shutdown == GNUNET_YES)
- {
- GNUNET_mutex_unlock (rm->lock);
- return;
- }
-
- /* check type of reply msg, fill in query */
- pos = -1;
- /* find which query matches the reply, call the callback
- and recycle the slot */
- for (i = 0; i < rm->requestListIndex; i++)
- if (rm->requestList[i]->node == node)
- pos = i;
- if (pos == -1)
- {
- /* GNUNET_GE_BREAK(ectx, 0); *//* should never happen */
- GNUNET_mutex_unlock (rm->lock);
- return;
- }
- entry = rm->requestList[pos];
-
- if ((entry->lasttime < GNUNET_get_time ()) && (entry->lasttime != 0))
- {
- unsigned int weight = 15;
- unsigned int ettl = entry->lastTimeout - entry->lasttime;
- if ((ettl > 4 * rm->initialTTL) &&
- ((GNUNET_get_time () - entry->lasttime) < rm->initialTTL))
- {
- weight = 127;
- /* eTTL is MUCH bigger than what we currently expect AND the time
- between the last query and the reply was in the range of the
- expected TTL => don't take ettl too much into account! */
- }
- rm->initialTTL = ((rm->initialTTL) * weight + ettl) / (weight + 1);
-
- /* RFC 2001: increase cwnd; note that we can't really discriminate
between
- slow-start and cong. control mode since our RSS is too small... */
- if (rm->congestionWindow < rm->ssthresh)
- rm->congestionWindow += 2; /* slow start */
- else
- rm->congestionWindow += 1; /* slower start :-) */
- }
- if (entry->tries > 1)
- {
- GNUNET_Int32Time nowTT;
-
- GNUNET_get_time_int32 (&nowTT);
- if ((nowTT - rm->initialTTL) > rm->lastDET)
- {
- /* only consider congestion control every
- "average" TTL seconds, otherwise the system
- reacts to events that are far too old! */
- /* we performed retransmission, treat as congestion (RFC 2001) */
- rm->ssthresh = rm->congestionWindow / 2;
- if (rm->ssthresh < 2)
- rm->ssthresh = 2;
- rm->congestionWindow = rm->ssthresh + 1;
- rm->lastDET = nowTT;
- }
- }
- GNUNET_mutex_unlock (rm->lock);
+ if ( (rm->abortFlag == GNUNET_YES) ||
+ (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);
}
/**
- * GNUNET_ND_DOWNLOAD children of this IBlock.
+ * DOWNLOAD children of this IBlock.
*
* @param rm the node that should downloaded
*/
-static void iblock_download_children (NodeClosure * node,
+static void iblock_download_children (struct Node * node,
char *data, unsigned int size);
/**
@@ -829,7 +483,7 @@
* @return GNUNET_YES if present, GNUNET_NO if not.
*/
static int
-checkPresent (NodeClosure * node)
+check_node_present (struct Node * node)
{
int res;
int ret;
@@ -837,27 +491,24 @@
unsigned int size;
GNUNET_HashCode hc;
- size = getNodeSize (node);
-
+ 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)))
+ 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);
- res = readFromIOC (node->ctx->ioc, node->level, node->offset, data, size);
+ 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)))
{
- updateProgress (node, data, size);
+ notify_client_about_progress (node, data, size);
if (node->level > 0)
iblock_download_children (node, data, size);
-
ret = GNUNET_YES;
}
else
@@ -866,27 +517,20 @@
else
ret = GNUNET_NO;
GNUNET_free (data);
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (node->ctx->rm->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Checked presence of block at %llu level %u. Result: %s\n",
- node->offset, node->level, ret == GNUNET_YES ? "YES" : "NO");
-#endif
-
return ret;
}
/**
- * GNUNET_ND_DOWNLOAD children of this IBlock.
+ * DOWNLOAD children of this IBlock.
*
* @param this the node that should downloaded
*/
static void
-iblock_download_children (NodeClosure * node, char *data, unsigned int size)
+iblock_download_children (struct Node * node, char *data, unsigned int size)
{
- struct GNUNET_GE_Context *ectx = node->ctx->rm->ectx;
+ struct GNUNET_GE_Context *ectx = node->ctx->ectx;
int i;
- NodeClosure *child;
+ struct Node *child;
unsigned int childcount;
CHK *chks;
unsigned int levelSize;
@@ -912,7 +556,7 @@
chks = (CHK *) data;
for (i = 0; i < childcount; i++)
{
- child = GNUNET_malloc (sizeof (NodeClosure));
+ child = GNUNET_malloc (sizeof (struct Node));
child->ctx = node->ctx;
child->chk = chks[i];
child->offset = baseOffset + i * levelSize;
@@ -920,8 +564,8 @@
child->level = node->level - 1;
GNUNET_GE_ASSERT (ectx, (child->level != 0) ||
((child->offset % DBLOCK_SIZE) == 0));
- if (GNUNET_NO == checkPresent (child))
- addRequest (node->ctx->rm, child);
+ if (GNUNET_NO == check_node_present (child))
+ addRequest (child);
else
GNUNET_free (child); /* done already! */
}
@@ -938,21 +582,18 @@
* @returns GNUNET_OK on success, GNUNET_SYSERR on error
*/
static int
-decryptContent (const char *data,
+decrypt_content (const char *data,
unsigned int size, const GNUNET_HashCode * hashcode,
char *result)
{
GNUNET_AES_InitializationVector iv;
GNUNET_AES_SessionKey skey;
- GNUNET_GE_ASSERT (NULL, (data != NULL) && (hashcode != NULL)
- && (result != NULL));
- /* get key and init value from the GNUNET_hash code */
+ /* 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 CHK reply for a block. Decrypt. Note
* that the caller (fslib) has already aquired the
@@ -967,362 +608,130 @@
* @return GNUNET_OK if the reply was valid, GNUNET_SYSERR on error
*/
static int
-nodeReceive (const GNUNET_HashCode * query,
+content_receive_callback (const GNUNET_HashCode * query,
const GNUNET_DatastoreValue * reply, void *cls,
unsigned long long uid)
{
- NodeClosure *node = cls;
- struct GNUNET_GE_Context *ectx = node->ctx->rm->ectx;
+ struct Node *node = cls;
+ struct RequestManager * rm = node->ctx;
+ struct GNUNET_GE_Context *ectx = rm->ectx;
GNUNET_HashCode hc;
unsigned int size;
- int i;
char *data;
-#if DEBUG_DOWNLOAD
- GNUNET_EncName enc;
- IF_GELOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- GNUNET_hash_to_enc (query, &enc));
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Receiving reply to query `%s'\n", &enc);
-#endif
+ GNUNET_mutex_lock (rm->lock);
+ if (rm->abortFlag != GNUNET_NO) {
+ GNUNET_mutex_unlock (rm->lock);
+ 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 (DBlock)) ||
- (size - sizeof (DBlock) != getNodeSize (node)))
+ (size - sizeof (DBlock) != get_node_size (node)))
{
GNUNET_GE_BREAK (ectx, 0);
+ GNUNET_mutex_unlock (rm->lock);
return GNUNET_SYSERR; /* invalid size! */
}
size -= sizeof (DBlock);
data = GNUNET_malloc (size);
- if (GNUNET_SYSERR == decryptContent ((char *) &((DBlock *) & reply[1])[1],
+ if (GNUNET_SYSERR == decrypt_content ((char *) &((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)))
{
- delRequest (node->ctx->rm, node);
GNUNET_free (data);
GNUNET_GE_BREAK (ectx, 0);
GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
_("Decrypted content does not match key. "
"This is either a bug or a maliciously inserted "
"file. Download aborted.\n"));
- node->ctx->rm->abortFlag = GNUNET_YES;
+ signal_abort(rm);
+ GNUNET_mutex_unlock (rm->lock);
return GNUNET_SYSERR;
}
- if (size != writeToIOC (node->ctx->ioc,
+ 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");
- node->ctx->rm->abortFlag = GNUNET_YES;
+ signal_abort(rm);
+ GNUNET_mutex_unlock (rm->lock);
return GNUNET_SYSERR;
}
- updateProgress (node, data, size);
+ notify_client_about_progress (node, data, size);
if (node->level > 0)
iblock_download_children (node, data, size);
/* request satisfied, stop requesting! */
- delRequest (node->ctx->rm, node);
-
- for (i = 0; i < 10; i++)
- {
- if ((node->ctx->completed * 10000L >
- node->ctx->length * (10000L - (1024 >> i))) &&
- ((node->ctx->completed - size) * 10000L <=
- node->ctx->length * (10000L - (1024 >> i))))
- {
- /* end-game boundary crossed, slaughter TTLs */
- requestManagerEndgame (node->ctx->rm);
- }
- }
- GNUNET_GE_ASSERT (node->ctx->rm->ectx,
- node->ctx->rm->requestThread != NULL);
- GNUNET_thread_stop_sleep (node->ctx->rm->requestThread);
+ delete_node (node);
GNUNET_free (data);
- GNUNET_free (node);
+ GNUNET_mutex_unlock (rm->lock);
return GNUNET_OK;
}
/**
- * Send the request from the requestList[requestIndex] out onto
- * the network.
- *
- * @param this the RequestManager
- * @param requestIndex the index of the Request to issue
+ * Helper function to sanitize filename
+ * and create necessary directories.
*/
-static void
-issueRequest (RequestManager * rm, int requestIndex)
+static char *
+get_real_download_filename(struct GNUNET_GE_Context * ectx,
+ const char * filename)
{
- static unsigned int lastmpriority;
- static GNUNET_CronTime lastmpritime;
- RequestEntry *entry;
- GNUNET_CronTime now;
- unsigned int priority;
- unsigned int mpriority;
- GNUNET_CronTime timeout;
- unsigned int ttl;
- int TTL_DECREMENT;
-#if DEBUG_DOWNLOAD
- GNUNET_EncName enc;
-#endif
+ struct stat buf;
+ char *realFN;
+ char *path;
+ char *pos;
- now = GNUNET_get_time ();
- entry = rm->requestList[requestIndex];
-
- /* compute priority */
- if (lastmpritime + 10 * GNUNET_CRON_SECONDS < now)
+ if ((filename[strlen (filename) - 1] == '/') ||
+ (filename[strlen (filename) - 1] == '\\'))
{
- /* only update avg. priority at most every
- 10 seconds */
- struct GNUNET_ClientServerConnection *sock;
-
- sock = GNUNET_client_connection_create (rm->ectx, rm->cfg);
- lastmpriority = GNUNET_FS_get_current_average_priority (sock);
- lastmpritime = now;
- GNUNET_client_connection_destroy (sock);
+ realFN =
+ GNUNET_malloc (strlen (filename) + strlen (GNUNET_DIRECTORY_EXT));
+ strcpy (realFN, filename);
+ realFN[strlen (filename) - 1] = '\0';
+ strcat (realFN, GNUNET_DIRECTORY_EXT);
}
- mpriority = lastmpriority;
- priority =
- entry->lastPriority + GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- 1 + entry->tries);
- if (priority > mpriority)
- {
- /* mpriority is (2 * (current average priority + 2)) and
- is used as the maximum priority that we use; if the
- calculated tpriority is above it, we reduce tpriority
- to random value between the average (mpriority/2) but
- bounded by mpriority */
- priority =
- 1 + mpriority / 2 +
- (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 2 + mpriority / 2));
- }
- if (priority > 0x0FFFFFF)
- priority = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 0xFFFFFF);
/* bound! */
-
- /* compute TTL */
-
- TTL_DECREMENT = entry->node->ctx->TTL_DECREMENT;
-
- if (entry->lastTimeout + TTL_DECREMENT > now)
- GNUNET_GE_BREAK (rm->ectx, 0);
- if (entry->lasttime == 0)
- {
- timeout = now + rm->initialTTL;
- }
else
{
- ttl = entry->lastTimeout - entry->lasttime;
- if (ttl > MAX_TTL)
- {
- ttl =
- MAX_TTL + GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- 2 * TTL_DECREMENT);
- }
- else if (ttl > rm->initialTTL)
- {
- /* switch to slow back-off */
- unsigned int rd;
- if (rm->initialTTL == 0)
- rd = ttl;
- else
- rd = ttl / rm->initialTTL;
- if (rd == 0)
- rd = 1; /* how? */
- rd = TTL_DECREMENT / rd;
- if (rd == 0)
- rd = 1;
- ttl +=
- GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- 50 * GNUNET_CRON_MILLISECONDS + rd);
- /* rd == TTL_DECREMENT / (con->ttl / rm->initialTTL) + saveguards
- 50ms: minimum increment */
- }
- else
- {
- ttl += GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, ttl + 2 *
TTL_DECREMENT); /* exponential backoff with random factor */
- }
- if (ttl > (priority + 8) * TTL_DECREMENT)
- ttl = (priority + 8) * TTL_DECREMENT; /* see adjustTTL in gap */
- timeout = now + ttl;
+ realFN = GNUNET_strdup (filename);
}
-
-#if DEBUG_DOWNLOAD
- IF_GELOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- GNUNET_hash_to_enc (&entry->node->chk.query, &enc));
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Starting FS search for %s:%llu:%u `%s'\n",
- entry->node->ctx->ioc->filename,
- entry->node->offset, entry->node->level, &enc);
-#endif
-
- if (entry->searchHandle != NULL)
- GNUNET_FS_stop_search (rm->sctx, entry->searchHandle);
- entry->searchHandle
- = GNUNET_FS_start_search (rm->sctx,
- rm->have_target ==
- GNUNET_NO ? NULL : &rm->target,
- GNUNET_ECRS_BLOCKTYPE_DATA, 1,
- &entry->node->chk.query,
- entry->node->ctx->anonymityLevel, priority,
- timeout, &nodeReceive, entry->node);
- if (entry->searchHandle != NULL)
+ path = GNUNET_malloc (strlen (realFN) * strlen (GNUNET_DIRECTORY_EXT) + 1);
+ strcpy (path, realFN);
+ pos = path;
+ while (*pos != '\0')
{
- entry->lastPriority = priority;
- entry->lastTimeout = timeout;
- entry->lasttime = now + 2 * TTL_DECREMENT;
- if (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 1 + entry->tries) >
- 1)
+ if (*pos == DIR_SEPARATOR)
{
- /* do linear (in tries) extra back-off (in addition to ttl)
- to avoid repeatedly tie-ing with other peers; rm is somewhat
- equivalent to what ethernet is doing, only that 'tries' is our
- (rough) indicator for collisions. For ethernet back-off, see:
- http://www.industrialethernetuniversity.com/courses/101_4.htm
- */
- entry->lasttime +=
- GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- TTL_DECREMENT * (1 + entry->tries));
- }
- entry->tries++;
- }
- /* warn if number of attempts goes too high */
- if ((0 == (entry->tries % MAX_TRIES)) && (entry->tries > 0))
- {
- GNUNET_EncName enc;
- IF_GELOG (rm->ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- GNUNET_hash_to_enc (&entry->node->chk.key, &enc));
- GNUNET_GE_LOG (rm->ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _
- ("Content `%s' seems to be not available on the network
(tried %u times).\n"),
- &enc, entry->tries);
- }
-}
-
-/**
- * Cron job that re-issues requests. Should compute how long to sleep
- * (min ttl until next job is ready) and re-schedule itself
- * accordingly!
- */
-static GNUNET_CronTime
-processRequests (RequestManager * rm)
-{
- GNUNET_CronTime minSleep;
- GNUNET_CronTime now;
- GNUNET_CronTime delta;
- int i;
- unsigned int pending;
- unsigned int *perm;
- unsigned int TTL_DECREMENT;
-
- GNUNET_mutex_lock (rm->lock);
- if ((rm->shutdown == GNUNET_YES) || (rm->requestListIndex == 0))
- {
- GNUNET_mutex_unlock (rm->lock);
- return 0;
- }
- now = GNUNET_get_time ();
- pending = 0;
- TTL_DECREMENT = 0;
- if (rm->requestListIndex > 0)
- TTL_DECREMENT = rm->requestList[0]->node->ctx->TTL_DECREMENT;
-
- for (i = 0; i < rm->requestListIndex; i++)
- {
- if (rm->requestList[i]->lastTimeout >= now - TTL_DECREMENT)
- {
- pending++;
- }
- else if (rm->requestList[i]->searchHandle != NULL)
- {
- GNUNET_FS_stop_search (rm->sctx, rm->requestList[i]->searchHandle);
- rm->requestList[i]->searchHandle = NULL;
- }
- }
-
- minSleep = 5000 * GNUNET_CRON_MILLISECONDS; /* max-sleep! */
- perm = GNUNET_permute (GNUNET_RANDOM_QUALITY_WEAK, rm->requestListIndex);
- for (i = 0; i < rm->requestListIndex; i++)
- {
- int j = perm[i];
- if (rm->requestList[j]->lastTimeout + TTL_DECREMENT < now)
- {
- int pOCWCubed;
- int pendingOverCWin = pending - rm->congestionWindow;
- if (pendingOverCWin <= 0)
- pendingOverCWin = -1; /* avoid 0! */
- pOCWCubed = pendingOverCWin * pendingOverCWin * pendingOverCWin;
- if ((pOCWCubed <= 0) ||
- (pOCWCubed * rm->requestListIndex <= 0) /* see #642 */ ||
- /* avoid no-start: override congestionWindow occasionally... */
- (0 ==
- GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- rm->requestListIndex * pOCWCubed)))
+ *pos = '\0';
+ if ((0 == STAT (path, &buf)) && (!S_ISDIR (buf.st_mode)))
{
- issueRequest (rm, j);
- delta = (rm->requestList[j]->lastTimeout - now) + TTL_DECREMENT;
- pending++;
+ *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
{
- delta = 0;
+ *pos = DIR_SEPARATOR;
}
}
- else
- {
- delta = (rm->requestList[j]->lastTimeout + TTL_DECREMENT - now);
- }
- if (delta < minSleep)
- minSleep = delta;
+ pos++;
}
- GNUNET_free (perm);
- if (minSleep < GNUNET_CRON_MILLISECONDS * 100)
- minSleep = GNUNET_CRON_MILLISECONDS * 100; /* maximum resolution: 100ms */
- GNUNET_mutex_unlock (rm->lock);
- return minSleep;
+ GNUNET_free (realFN);
+ return path;
}
-
-
/* ***************** main method **************** */
/**
- * GNUNET_ND_DOWNLOAD a file.
- *
- * @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);
-}
-
-
-/**
- * GNUNET_ND_DOWNLOAD parts of a file. Note that this will store
+ * 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
@@ -1354,152 +763,131 @@
GNUNET_ECRS_TestTerminate tt,
void *ttClosure)
{
- IOContext ioc;
- RequestManager *rm;
- int ret;
- CommonCtx ctx;
- NodeClosure *top;
- FileIdentifier fid;
- GNUNET_CronTime minSleep;
- char *realFN;
- char *path;
- char *pos;
+ struct RequestManager rm;
struct stat buf;
+ struct Node *top;
+ char *fn;
+ char *rdir;
+ int ret;
+ int i;
+ int len;
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "`%s' running for file `%s'\n", __FUNCTION__, filename);
-#endif
- GNUNET_GE_ASSERT (ectx, filename != NULL);
- if ((filename[strlen (filename) - 1] == '/') ||
- (filename[strlen (filename) - 1] == '\\'))
+ if ((!GNUNET_ECRS_uri_test_chk (uri)) && (!GNUNET_ECRS_uri_test_loc (uri)))
{
- realFN =
- GNUNET_malloc (strlen (filename) + strlen (GNUNET_DIRECTORY_EXT));
- strcpy (realFN, filename);
- realFN[strlen (filename) - 1] = '\0';
- strcat (realFN, GNUNET_DIRECTORY_EXT);
+ GNUNET_GE_BREAK (ectx, 0);
+ return GNUNET_SYSERR;
}
- 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);
- realFN = path;
- if (GNUNET_SYSERR == GNUNET_disk_directory_create_for_file (ectx, realFN))
+ memset(&rm, 0, sizeof(struct RequestManager));
+ 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 = get_real_download_filename(ectx,
+ filename);
+
+ if (GNUNET_SYSERR == GNUNET_disk_directory_create_for_file (ectx,
rm.filename))
{
- GNUNET_free (realFN);
+ free_request_manager(&rm, GNUNET_NO);
return GNUNET_SYSERR;
}
- if (0 == GNUNET_ECRS_uri_get_file_size (uri))
+ if (0 == rm.total)
{
ret = GNUNET_disk_file_open (ectx,
- realFN,
+ rm.filename,
O_CREAT | O_WRONLY | O_TRUNC,
S_IRUSR | S_IWUSR);
- GNUNET_free (realFN);
if (ret == -1)
- return GNUNET_SYSERR;
+ {
+ free_request_manager(&rm, GNUNET_NO);
+ return GNUNET_SYSERR;
+ }
CLOSE (ret);
- dpcb (0, 0, GNUNET_get_time (), 0, NULL, 0, dpcbClosure);
+ dpcb (0, 0, rm.startTime, 0, NULL, 0, dpcbClosure);
+ free_request_manager(&rm, GNUNET_NO);
return GNUNET_OK;
}
- fid = uri->data.fi;
-
- if ((!GNUNET_ECRS_uri_test_chk (uri)) && (!GNUNET_ECRS_uri_test_loc (uri)))
+ rm.treedepth = GNUNET_ECRS_compute_depth (rm.total);
+ rm.handles = GNUNET_malloc (sizeof (int) * (rm.treedepth + 1));
+ for (i = 0; i <= rm.treedepth; i++)
+ rm.handles[i] = -1;
+ if ((0 == STAT (rm.filename, &buf)) && ((size_t) buf.st_size > rm.total))
{
- GNUNET_GE_BREAK (ectx, 0);
- GNUNET_free (realFN);
- return GNUNET_SYSERR;
+ /* 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, GNUNET_NO);
+ return GNUNET_SYSERR;
+ }
}
-
- if (GNUNET_OK != createIOContext (ectx,
- &ioc,
- no_temporaries,
- GNUNET_ntohll (fid.file_length), realFN))
+ for (i = 0; i <= rm.treedepth; i++)
{
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "`%s' aborted for file `%s'\n", __FUNCTION__, realFN);
-#endif
- GNUNET_free (realFN);
- return GNUNET_SYSERR;
+ if ((i == 0) || (no_temporaries != GNUNET_YES))
+ {
+ fn = GNUNET_malloc (strlen (rm.filename) + 3);
+ strcpy (fn, rm.filename);
+ if (i > 0)
+ {
+ strcat (fn, ".A");
+ fn[strlen (fn) - 1] += i;
+ }
+ rm.handles[i] = GNUNET_disk_file_open (ectx,
+ fn,
+ O_CREAT | O_RDWR,
+ S_IRUSR | S_IWUSR);
+ if (rm.handles[i] < 0)
+ {
+ free_request_manager(&rm, GNUNET_NO);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (fn);
+ }
}
- rm = createRequestManager (ectx, cfg);
- if (rm == NULL)
+ rm.lock = GNUNET_mutex_create (GNUNET_YES);
+ rm.sctx = GNUNET_FS_create_search_context (ectx, cfg, rm.lock);
+ if (rm.sctx == NULL)
{
- freeIOC (&ioc, GNUNET_YES);
- GNUNET_free (realFN);
+ free_request_manager(&rm, GNUNET_NO);
return GNUNET_SYSERR;
}
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;
+ &rm.target.hashPubKey);
+ rm.have_target = GNUNET_YES;
}
- ctx.startTime = GNUNET_get_time ();
- ctx.anonymityLevel = anonymityLevel;
- ctx.offset = offset;
- ctx.length = length;
- ctx.TTL_DECREMENT = 5 * GNUNET_CRON_SECONDS; /* HACK! */
- ctx.rm = rm;
- ctx.ioc = &ioc;
- ctx.dpcb = dpcb;
- ctx.dpcbClosure = dpcbClosure;
- ctx.total = GNUNET_ntohll (fid.file_length);
- ctx.completed = 0;
- top = GNUNET_malloc (sizeof (NodeClosure));
- top->ctx = &ctx;
- top->chk = fid.chk;
+ 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 = GNUNET_ECRS_compute_depth (ctx.total);
- if (GNUNET_NO == checkPresent (top))
- addRequest (rm, top);
+ top->level = rm.treedepth;
+
+ GNUNET_mutex_lock (rm.lock);
+ if (GNUNET_NO == check_node_present (top))
+ addRequest (top);
else
GNUNET_free (top);
- while ((GNUNET_OK == tt (ttClosure)) &&
- (rm->abortFlag == GNUNET_NO) && (rm->requestListIndex != 0))
+ GNUNET_mutex_unlock (rm.lock);
+ while ( (GNUNET_OK == tt (ttClosure)) &&
+ (rm.abortFlag == GNUNET_NO) &&
+ (rm.head != NULL) )
+ GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
+ if ((rm.head == NULL) &&
+ ((rm.completed == rm.total) ||
+ ((rm.total != rm.length) &&
+ (rm.completed >= rm.length))) && (rm.abortFlag == GNUNET_NO))
{
- minSleep = processRequests (rm);
- if ((GNUNET_OK == tt (ttClosure)) &&
- (rm->abortFlag == GNUNET_NO) && (rm->requestListIndex != 0))
- GNUNET_thread_sleep (minSleep);
- }
-
- if ((rm->requestListIndex == 0) &&
- ((ctx.completed == ctx.total) ||
- ((ctx.total != ctx.length) &&
- (ctx.completed >= ctx.length))) && (rm->abortFlag == GNUNET_NO))
- {
ret = GNUNET_OK;
}
else
@@ -1508,31 +896,31 @@
GNUNET_GE_LOG (ectx,
GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
"Download ends prematurely: %d %llu == %llu %d TT: %d\n",
- rm->requestListIndex,
- ctx.completed, ctx.total, rm->abortFlag, tt (ttClosure));
+ rm.requestListIndex,
+ ctx.completed, ctx.total, rm.abortFlag, tt (ttClosure));
#endif
ret = GNUNET_SYSERR;
}
- destroyRequestManager (rm);
- if (ret == GNUNET_OK)
+#if DEBUG_DOWNLOAD
+ GNUNET_GE_LOG (ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "`%s' terminating for file `%s' with result %s\n",
+ __FUNCTION__, filename,
+ ret == GNUNET_OK ? "SUCCESS" : "INCOMPLETE");
+#endif
+ if ( (ret == GNUNET_SYSERR) &&
+ (tt(ttClosure) == GNUNET_SYSERR) )
{
- freeIOC (&ioc, GNUNET_YES);
- }
- else if (tt (ttClosure) == GNUNET_SYSERR)
- {
- freeIOC (&ioc, GNUNET_YES);
- if (0 != UNLINK (realFN))
+ if (0 != UNLINK (rm.filename))
{
GNUNET_GE_LOG_STRERROR_FILE (ectx,
GNUNET_GE_WARNING | GNUNET_GE_USER |
- GNUNET_GE_BULK, "unlink", realFN);
+ GNUNET_GE_BULK, "unlink", rm.filename);
}
else
- { /* delete empty directories */
- char *rdir;
- int len;
-
- rdir = GNUNET_strdup (realFN);
+ {
+ /* delete empty directories */
+ rdir = GNUNET_strdup (rm.filename);
len = strlen (rdir);
do
{
@@ -1543,20 +931,39 @@
while ((len > 0) && (0 == rmdir (rdir)));
GNUNET_free (rdir);
}
- }
- else
- {
- freeIOC (&ioc, GNUNET_NO); /* aborted */
- }
-#if DEBUG_DOWNLOAD
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "`%s' terminating for file `%s' with result %s\n",
- __FUNCTION__, filename,
- ret == GNUNET_OK ? "SUCCESS" : "INCOMPLETE");
-#endif
- GNUNET_free (realFN);
+ }
+ free_request_manager (&rm,
+ ( (ret == GNUNET_OK) ||
+ (tt(ttClosure) == GNUNET_SYSERR) )
+ ? GNUNET_YES
+ : GNUNET_NO);
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 */
Modified: GNUnet/src/applications/fs/ecrs/search.c
===================================================================
--- GNUnet/src/applications/fs/ecrs/search.c 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/applications/fs/ecrs/search.c 2008-02-06 07:11:29 UTC (rev
6162)
@@ -33,42 +33,22 @@
#define DEBUG_SEARCH GNUNET_NO
-typedef struct
+/**
+ * This struct is followed by keyCount keys of
+ * type "GNUNET_HashCode".
+ */
+struct PendingSearch
{
+ struct PendingSearch *next;
- /**
- * The handle for the query.
- */
- struct GNUNET_FS_SearchHandle *handle;
+ struct SearchContext *context;
/**
- * The keys (for the search).
- */
- GNUNET_HashCode *keys;
-
- /**
- * When does this query time-out (we may want
- * to refresh it at that point).
- */
- GNUNET_CronTime timeout;
-
- /**
- * What was the last time we transmitted
- * this query?
- */
- GNUNET_CronTime lastTransmission;
-
- /**
* The key (for decryption)
*/
GNUNET_HashCode decryptKey;
/**
- * With which priority does the query run?
- */
- unsigned int priority;
-
- /**
* What type of query is it?
*/
unsigned int type;
@@ -78,12 +58,12 @@
*/
unsigned int keyCount;
-} PendingSearch;
+};
/**
- * Context of the sendQueries cron-job.
+ * Context for search operation.
*/
-typedef struct
+struct SearchContext
{
/**
* Time when the cron-job was first started.
@@ -101,9 +81,9 @@
struct GNUNET_FS_SearchContext *sctx;
/**
- * queryCount pending searches.
+ * Active searches.
*/
- PendingSearch **queries;
+ struct PendingSearch *queries;
GNUNET_ECRS_SearchResultProcessor spcb;
@@ -117,38 +97,45 @@
int aborted;
- /**
- * Number of queries running at the moment.
- */
- unsigned int queryCount;
+ unsigned int anonymityLevel;
-} SendQueriesContext;
+};
+static int
+receive_response_callback (const GNUNET_HashCode * key,
+ const GNUNET_DatastoreValue * value, void *cls);
+
/**
* Add a query to the SQC.
*/
static void
-addPS (unsigned int type,
- unsigned int keyCount,
- const GNUNET_HashCode * keys,
- const GNUNET_HashCode * dkey, SendQueriesContext * sqc)
+add_search (unsigned int type,
+ unsigned int keyCount,
+ const GNUNET_HashCode * keys,
+ const GNUNET_HashCode * dkey, struct SearchContext *sqc)
{
- PendingSearch *ps;
+ struct PendingSearch *ps;
- ps = GNUNET_malloc (sizeof (PendingSearch));
- ps->timeout = 0;
- ps->lastTransmission = 0;
- ps->priority = 5 + GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 20);
+ ps =
+ GNUNET_malloc (sizeof (struct PendingSearch) +
+ sizeof (GNUNET_HashCode) * keyCount);
ps->type = type;
ps->keyCount = keyCount;
- ps->keys = GNUNET_malloc (sizeof (GNUNET_HashCode) * keyCount);
- memcpy (ps->keys, keys, sizeof (GNUNET_HashCode) * keyCount);
+ memcpy (&ps[1], keys, sizeof (GNUNET_HashCode) * keyCount);
ps->decryptKey = *dkey;
- ps->handle = NULL;
+ ps->context = sqc;
GNUNET_mutex_lock (sqc->lock);
- GNUNET_array_grow (sqc->queries, sqc->queryCount, sqc->queryCount + 1);
- sqc->queries[sqc->queryCount - 1] = ps;
+ ps->next = sqc->queries;
+ sqc->queries = ps;
GNUNET_mutex_unlock (sqc->lock);
+ GNUNET_FS_start_search (sqc->sctx,
+ NULL,
+ type,
+ keyCount,
+ keys,
+ sqc->anonymityLevel,
+ (GNUNET_DatastoreValueIterator) &
+ receive_response_callback, ps);
}
/**
@@ -156,7 +143,8 @@
* to the SQC.
*/
static void
-addQueryForURI (const struct GNUNET_ECRS_URI *uri, SendQueriesContext * sqc)
+add_search_for_uri (const struct GNUNET_ECRS_URI *uri,
+ struct SearchContext *sqc)
{
struct GNUNET_GE_Context *ectx = sqc->ectx;
@@ -176,8 +164,8 @@
&hk);
GNUNET_hash_xor (&hk, &uri->data.sks.namespace, &keys[0]); /*
compute routing key r = H(identifier) ^ namespace */
keys[1] = uri->data.sks.namespace;
- addPS (GNUNET_ECRS_BLOCKTYPE_SIGNED, 2, &keys[0],
&uri->data.sks.identifier, /* identifier = decryption key */
- sqc);
+ add_search (GNUNET_ECRS_BLOCKTYPE_SIGNED, 2, &keys[0],
&uri->data.sks.identifier, /* identifier = decryption key */
+ sqc);
break;
}
case ksk:
@@ -200,8 +188,8 @@
pk = GNUNET_RSA_create_key_from_hash (&hc);
GNUNET_RSA_get_public_key (pk, &pub);
GNUNET_hash (&pub, sizeof (GNUNET_RSA_PublicKey), &query);
- addPS (GNUNET_ECRS_BLOCKTYPE_ANY, /*
GNUNET_ECRS_BLOCKTYPE_KEYWORD, GNUNET_ECRS_BLOCKTYPE_NAMESPACE or
GNUNET_ECRS_BLOCKTYPE_KEYWORD_FOR_NAMESPACE ok */
- 1, &query, &hc, sqc);
+ 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
@@ -234,7 +222,8 @@
* @param c the resulting current ID (set)
*/
static int
-computeIdAtTime (const SBlock * sb, GNUNET_Int32Time now, GNUNET_HashCode * c)
+compute_id_at_time (const SBlock * sb, GNUNET_Int32Time now,
+ GNUNET_HashCode * c)
{
GNUNET_Int32Time pos;
GNUNET_HashCode tmp;
@@ -276,9 +265,9 @@
* namespace advertisement.
*/
static int
-processNBlock (const NBlock * nb,
- const GNUNET_HashCode * key,
- unsigned int size, SendQueriesContext * sqc)
+process_nblock_result (const NBlock * nb,
+ const GNUNET_HashCode * key,
+ unsigned int size, struct SearchContext *sqc)
{
struct GNUNET_GE_Context *ectx = sqc->ectx;
GNUNET_ECRS_FileInfo fi;
@@ -317,15 +306,15 @@
* @return GNUNET_SYSERR if the entry is malformed
*/
static int
-receiveReplies (const GNUNET_HashCode * key,
- const GNUNET_DatastoreValue * value, SendQueriesContext * sqc)
+receive_response_callback (const GNUNET_HashCode * key,
+ const GNUNET_DatastoreValue * value, void *cls)
{
+ struct PendingSearch *ps = cls;
+ struct SearchContext *sqc = ps->context;
struct GNUNET_GE_Context *ectx = sqc->ectx;
unsigned int type;
GNUNET_ECRS_FileInfo fi;
- int i;
unsigned int size;
- PendingSearch *ps;
int ret;
GNUNET_HashCode query;
@@ -342,219 +331,208 @@
(const DBlock *) &value[1],
GNUNET_YES, &query))
return GNUNET_SYSERR;
- for (i = 0; i < sqc->queryCount; i++)
+ 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 DBlock *)
+ &value[1], &query,
+ ps->keyCount,
+ (GNUNET_HashCode *) &
+ ps[1]))))
+ return GNUNET_OK; /* not a match */
+
+ switch (type)
{
- ps = sqc->queries[i];
- if ((0 == memcmp (&query,
- &ps->keys[0], sizeof (GNUNET_HashCode))) &&
- ((ps->type == type) ||
- (ps->type == GNUNET_ECRS_BLOCKTYPE_ANY)) &&
- (GNUNET_YES == GNUNET_EC_is_block_applicable_for_query (type,
- size,
- (const
- DBlock *)
- &value[1],
- &query,
- ps->
- keyCount,
- ps->keys)))
- {
- switch (type)
- {
- case GNUNET_ECRS_BLOCKTYPE_KEYWORD:
- {
- KBlock *kb;
- const char *dstURI;
+ case GNUNET_ECRS_BLOCKTYPE_KEYWORD:
+ {
+ KBlock *kb;
+ const char *dstURI;
#if DEBUG_SEARCH
- GNUNET_EncName enc;
+ GNUNET_EncName enc;
#endif
- int j;
+ int j;
- if (size < sizeof (KBlock))
- return GNUNET_SYSERR;
- kb = GNUNET_malloc (size);
- memcpy (kb, &value[1], size);
+ if (size < sizeof (KBlock))
+ 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);
+ 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 (KBlock));
- j = sizeof (KBlock);
- while ((j < size) && (((const char *) kb)[j] != '\0'))
- j++;
- if (j == size)
- {
- GNUNET_GE_BREAK (ectx, 0); /* kblock malformed */
- GNUNET_free (kb);
- return GNUNET_SYSERR;
- }
- dstURI = (const char *) &kb[1];
- j++;
- fi.meta = GNUNET_ECRS_meta_data_deserialize (ectx,
- &((const char *)
- kb)[j],
- size - j);
- if (fi.meta == NULL)
- {
- GNUNET_GE_BREAK (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 (ectx, 0); /* kblock malformed */
- GNUNET_ECRS_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_ECRS_meta_data_destroy (fi.meta);
- GNUNET_free (kb);
- return ret;
- }
- case GNUNET_ECRS_BLOCKTYPE_NAMESPACE:
- {
- const NBlock *nb;
+ GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
+ &kb[1], size - sizeof (KBlock));
+ j = sizeof (KBlock);
+ while ((j < size) && (((const char *) kb)[j] != '\0'))
+ j++;
+ if (j == size)
+ {
+ GNUNET_GE_BREAK (ectx, 0); /* kblock malformed */
+ GNUNET_free (kb);
+ return GNUNET_SYSERR;
+ }
+ dstURI = (const char *) &kb[1];
+ j++;
+ fi.meta = GNUNET_ECRS_meta_data_deserialize (ectx,
+ &((const char *)
+ kb)[j], size - j);
+ if (fi.meta == NULL)
+ {
+ GNUNET_GE_BREAK (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 (ectx, 0); /* kblock malformed */
+ GNUNET_ECRS_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_ECRS_meta_data_destroy (fi.meta);
+ GNUNET_free (kb);
+ return ret;
+ }
+ case GNUNET_ECRS_BLOCKTYPE_NAMESPACE:
+ {
+ const NBlock *nb;
- if (size < sizeof (NBlock))
- return GNUNET_SYSERR;
- nb = (const NBlock *) &value[1];
- return processNBlock (nb, NULL, size, sqc);
- }
- case GNUNET_ECRS_BLOCKTYPE_KEYWORD_FOR_NAMESPACE:
- {
- KNBlock *kb;
- int ret;
+ if (size < sizeof (NBlock))
+ return GNUNET_SYSERR;
+ nb = (const NBlock *) &value[1];
+ return process_nblock_result (nb, NULL, size, sqc);
+ }
+ case GNUNET_ECRS_BLOCKTYPE_KEYWORD_FOR_NAMESPACE:
+ {
+ KNBlock *kb;
+ int ret;
- if (size < sizeof (KNBlock))
- return GNUNET_SYSERR;
- kb = GNUNET_malloc (size);
- memcpy (kb, &value[1], size);
- GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
- &kb->nblock,
- size - sizeof (KBlock) -
- sizeof (unsigned int));
- ret =
- processNBlock (&kb->nblock, &ps->decryptKey,
+ if (size < sizeof (KNBlock))
+ return GNUNET_SYSERR;
+ kb = GNUNET_malloc (size);
+ memcpy (kb, &value[1], size);
+ GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
+ &kb->nblock,
+ size - sizeof (KBlock) -
+ sizeof (unsigned int));
+ ret =
+ process_nblock_result (&kb->nblock, &ps->decryptKey,
size - sizeof (KNBlock) + sizeof (NBlock),
sqc);
- GNUNET_free (kb);
- return ret;
- }
- case GNUNET_ECRS_BLOCKTYPE_SIGNED:
- {
- SBlock *sb;
- const char *dstURI;
- int j;
- GNUNET_Int32Time now;
- GNUNET_HashCode updateId;
- URI updateURI;
+ GNUNET_free (kb);
+ return ret;
+ }
+ case GNUNET_ECRS_BLOCKTYPE_SIGNED:
+ {
+ SBlock *sb;
+ const char *dstURI;
+ int j;
+ GNUNET_Int32Time now;
+ GNUNET_HashCode updateId;
+ URI updateURI;
- if (size < sizeof (SBlock))
- return GNUNET_SYSERR;
- sb = GNUNET_malloc (size);
- memcpy (sb, &value[1], size);
- GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
- &sb->creationTime,
- size
- - sizeof (unsigned int)
- - sizeof (GNUNET_RSA_Signature)
- - sizeof (GNUNET_RSA_PublicKey)
- - sizeof (GNUNET_HashCode));
- j = 0;
- dstURI = (const char *) &sb[1];
- while ((j < size - sizeof (SBlock)) && (dstURI[j] != '\0'))
- j++;
- if (j == size - sizeof (SBlock))
- {
- GNUNET_GE_BREAK (ectx, 0); /* sblock malformed */
- GNUNET_free (sb);
- return GNUNET_SYSERR;
- }
- j++;
- /* j == strlen(dstURI) + 1 */
- fi.meta = GNUNET_ECRS_meta_data_deserialize (ectx,
- &dstURI[j],
- size - j -
- sizeof (SBlock));
- if (fi.meta == NULL)
- {
- GNUNET_GE_BREAK (ectx, 0); /* sblock malformed */
- GNUNET_free (sb);
- return GNUNET_SYSERR;
- }
- fi.uri = GNUNET_ECRS_string_to_uri (ectx, dstURI);
- if (fi.uri == NULL)
- {
- GNUNET_GE_BREAK (ectx, 0); /* sblock malformed */
- GNUNET_ECRS_meta_data_destroy (fi.meta);
- GNUNET_free (sb);
- return GNUNET_SYSERR;
- }
- if (sqc->spcb != NULL)
- {
- ret = sqc->spcb (&fi, NULL, GNUNET_NO, sqc->spcbClosure);
- if (ret == GNUNET_SYSERR)
- sqc->aborted = GNUNET_YES;
- }
- else
- ret = GNUNET_OK;
- GNUNET_ECRS_uri_destroy (fi.uri);
- GNUNET_ECRS_meta_data_destroy (fi.meta);
+ if (size < sizeof (SBlock))
+ return GNUNET_SYSERR;
+ sb = GNUNET_malloc (size);
+ memcpy (sb, &value[1], size);
+ GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
+ &sb->creationTime,
+ size
+ - sizeof (unsigned int)
+ - sizeof (GNUNET_RSA_Signature)
+ - sizeof (GNUNET_RSA_PublicKey)
+ - sizeof (GNUNET_HashCode));
+ j = 0;
+ dstURI = (const char *) &sb[1];
+ while ((j < size - sizeof (SBlock)) && (dstURI[j] != '\0'))
+ j++;
+ if (j == size - sizeof (SBlock))
+ {
+ GNUNET_GE_BREAK (ectx, 0); /* sblock malformed */
+ GNUNET_free (sb);
+ return GNUNET_SYSERR;
+ }
+ j++;
+ /* j == strlen(dstURI) + 1 */
+ fi.meta = GNUNET_ECRS_meta_data_deserialize (ectx,
+ &dstURI[j],
+ size - j -
+ sizeof (SBlock));
+ if (fi.meta == NULL)
+ {
+ GNUNET_GE_BREAK (ectx, 0); /* sblock malformed */
+ GNUNET_free (sb);
+ return GNUNET_SYSERR;
+ }
+ fi.uri = GNUNET_ECRS_string_to_uri (ectx, dstURI);
+ if (fi.uri == NULL)
+ {
+ GNUNET_GE_BREAK (ectx, 0); /* sblock malformed */
+ GNUNET_ECRS_meta_data_destroy (fi.meta);
+ GNUNET_free (sb);
+ return GNUNET_SYSERR;
+ }
+ if (sqc->spcb != NULL)
+ {
+ ret = sqc->spcb (&fi, NULL, GNUNET_NO, sqc->spcbClosure);
+ if (ret == GNUNET_SYSERR)
+ sqc->aborted = GNUNET_YES;
+ }
+ else
+ ret = GNUNET_OK;
+ GNUNET_ECRS_uri_destroy (fi.uri);
+ GNUNET_ECRS_meta_data_destroy (fi.meta);
- /* compute current/NEXT URI (if updateable SBlock) and issue
- respective query automatically! */
- GNUNET_get_time_int32 (&now);
- if (GNUNET_OK != computeIdAtTime (sb, now, &updateId))
- {
- GNUNET_free (sb);
- return GNUNET_SYSERR;
- }
- if (0 ==
- memcmp (&updateId, &ps->decryptKey,
- sizeof (GNUNET_HashCode)))
- {
- GNUNET_free (sb);
- return ret; /* have latest version */
- }
- if (ps->keyCount != 2)
- {
- GNUNET_GE_BREAK (ectx, 0);
- GNUNET_free (sb);
- return GNUNET_SYSERR;
- }
+ /* compute current/NEXT URI (if updateable SBlock) and issue
+ respective query automatically! */
+ GNUNET_get_time_int32 (&now);
+ if (GNUNET_OK != compute_id_at_time (sb, now, &updateId))
+ {
+ GNUNET_free (sb);
+ return GNUNET_SYSERR;
+ }
+ if (0 ==
+ memcmp (&updateId, &ps->decryptKey, sizeof (GNUNET_HashCode)))
+ {
+ GNUNET_free (sb);
+ return ret; /* have latest version */
+ }
+ if (ps->keyCount != 2)
+ {
+ GNUNET_GE_BREAK (ectx, 0);
+ GNUNET_free (sb);
+ return GNUNET_SYSERR;
+ }
- updateURI.type = sks;
- updateURI.data.sks.namespace = ps->keys[1];
- updateURI.data.sks.identifier = updateId;
- addQueryForURI (&updateURI, sqc);
- GNUNET_free (sb);
- return ret;
- }
- default:
- GNUNET_GE_BREAK (ectx, 0);
- break;
- } /* end switch */
- } /* for all matches */
- } /* for all pending queries */
+ updateURI.type = sks;
+ updateURI.data.sks.namespace = ((GNUNET_HashCode *) & ps[1])[1];
+ updateURI.data.sks.identifier = updateId;
+ add_search_for_uri (&updateURI, sqc);
+ GNUNET_free (sb);
+ return ret;
+ }
+ default:
+ GNUNET_GE_BREAK (ectx, 0);
+ break;
+ } /* end switch */
return GNUNET_OK;
}
@@ -576,103 +554,44 @@
void *spcbClosure, GNUNET_ECRS_TestTerminate tt,
void *ttClosure)
{
- SendQueriesContext ctx;
- PendingSearch *ps;
- int i;
+ struct PendingSearch *pos;
+ struct SearchContext ctx;
GNUNET_CronTime now;
GNUNET_CronTime remTime;
- GNUNET_CronTime new_ttl;
- unsigned int new_priority;
- ctx.start = GNUNET_get_time ();
now = GNUNET_get_time ();
- timeout += now;
+ ctx.start = now;
+ ctx.anonymityLevel = anonymityLevel;
+ if (timeout != 0)
+ timeout += now;
ctx.ectx = ectx;
ctx.cfg = cfg;
ctx.timeout = timeout;
- ctx.queryCount = 0;
ctx.queries = NULL;
ctx.spcb = spcb;
ctx.spcbClosure = spcbClosure;
ctx.aborted = GNUNET_NO;
ctx.lock = GNUNET_mutex_create (GNUNET_YES);
ctx.sctx = GNUNET_FS_create_search_context (ectx, cfg, ctx.lock);
- addQueryForURI (uri, &ctx);
+ add_search_for_uri (uri, &ctx);
while (((NULL == tt) ||
(GNUNET_OK == tt (ttClosure))) &&
(GNUNET_NO == GNUNET_shutdown_test ()) &&
- (timeout > now) && (ctx.aborted == GNUNET_NO))
+ ((timeout == 0) || (timeout > now)) && (ctx.aborted == GNUNET_NO))
{
remTime = timeout - now;
-
- GNUNET_mutex_lock (ctx.lock);
- for (i = 0; i < ctx.queryCount; i++)
- {
- ps = ctx.queries[i];
- if ((now < ps->timeout) && (ps->timeout != 0))
- continue;
- if (ps->handle != NULL)
- GNUNET_FS_stop_search (ctx.sctx, ps->handle);
- /* increase ttl/priority */
- new_ttl = ps->timeout - ps->lastTransmission;
- if (new_ttl < 4 * 5 * GNUNET_CRON_SECONDS)
- new_ttl =
- 4 * 5 * GNUNET_CRON_SECONDS +
- GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- 5 * GNUNET_CRON_SECONDS);
- new_ttl =
- new_ttl + GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- 5 * GNUNET_CRON_SECONDS +
- 2 * new_ttl);
- if (new_ttl > 0xFFFFFF)
- new_ttl = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
0xFFFFFF); /* if we get to large, reduce! */
- if (remTime < new_ttl)
- new_ttl = remTime;
- ps->timeout = new_ttl + now;
- new_priority = ps->priority;
- new_priority =
- new_priority + GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
- 4 + 2 * new_priority);
- if (new_priority > 0xFFFFFF)
- new_priority = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK,
0xFFFFFF); /* if we get to large, reduce! */
- ps->priority = new_priority;
- ps->lastTransmission = now;
-#if DEBUG_SEARCH
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "ECRS initiating FS search with timeout %llus and
priority %u.\n",
- (ps->timeout - now) / GNUNET_CRON_SECONDS,
- ps->priority);
-#endif
- ps->handle
- = GNUNET_FS_start_search (ctx.sctx,
- NULL,
- ps->type,
- ps->keyCount,
- ps->keys,
- anonymityLevel,
- ps->priority,
- ps->timeout,
- (GNUNET_DatastoreValueIterator) &
- receiveReplies, &ctx);
- }
- GNUNET_mutex_unlock (ctx.lock);
- if (((NULL != tt) &&
- (GNUNET_OK != tt (ttClosure))) || (timeout <= now)
- || (ctx.aborted != GNUNET_NO))
- break;
- GNUNET_thread_sleep (100 * GNUNET_CRON_MILLISECONDS);
+ if (remTime > 100 * GNUNET_CRON_MILLISECONDS)
+ remTime = 100 * GNUNET_CRON_MILLISECONDS;
+ GNUNET_thread_sleep (remTime);
now = GNUNET_get_time ();
}
- for (i = 0; i < ctx.queryCount; i++)
+ GNUNET_FS_destroy_search_context (ctx.sctx);
+ while (ctx.queries != NULL)
{
- if (ctx.queries[i]->handle != NULL)
- GNUNET_FS_stop_search (ctx.sctx, ctx.queries[i]->handle);
- GNUNET_free (ctx.queries[i]->keys);
- GNUNET_free (ctx.queries[i]);
+ pos = ctx.queries;
+ ctx.queries = pos->next;
+ GNUNET_free (pos);
}
- GNUNET_array_grow (ctx.queries, ctx.queryCount, 0);
- GNUNET_FS_destroy_search_context (ctx.sctx);
GNUNET_mutex_destroy (ctx.lock);
return GNUNET_OK;
}
Modified: GNUnet/src/applications/fs/gap/plan.c
===================================================================
--- GNUnet/src/applications/fs/gap/plan.c 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/applications/fs/gap/plan.c 2008-02-06 07:11:29 UTC (rev
6162)
@@ -410,7 +410,7 @@
rpc.info = info;
rpc.request = request;
rpc.rankings = NULL;
- total_peers = coreAPI->(rank_peers,
+ total_peers = coreAPI->forAllConnectedNodes(rank_peers,
&rpc);
/* use request type, priority, system load and
entropy of ranking to determine number of peers
Modified: GNUnet/src/applications/fs/lib/fslib.c
===================================================================
--- GNUnet/src/applications/fs/lib/fslib.c 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/applications/fs/lib/fslib.c 2008-02-06 07:11:29 UTC (rev
6162)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006, 2007 Christian Grothoff (and other contributing
authors)
+ (C) 2004, 2005, 2006, 2007, 2008 Christian Grothoff (and other
contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -32,47 +32,121 @@
#define DEBUG_FSLIB GNUNET_NO
-typedef struct GNUNET_FS_SearchHandle
+/**
+ * How often should we automatically retry a request
+ * that failed? (Note that searches are retried
+ * indefinitely in any case; this only applies
+ * to upload/delete operations).
+ */
+#define AUTO_RETRY 5
+
+/**
+ * In memory, the search handle is followed
+ * by a copy of the corresponding request of
+ * type "CS_fs_request_search_MESSAGE *".
+ */
+struct GNUNET_FS_SearchHandle
{
- CS_fs_request_search_MESSAGE *req;
+ /**
+ * This is a linked list.
+ */
+ struct GNUNET_FS_SearchHandle *next;
+
+ /**
+ * Function to call with results.
+ */
GNUNET_DatastoreValueIterator callback;
+
+ /**
+ * Extra argument to pass to callback.
+ */
void *closure;
-} SEARCH_HANDLE;
+};
-typedef struct GNUNET_FS_SearchContext
+/**
+ * Context for a set of search operations.
+ */
+struct GNUNET_FS_SearchContext
{
+ /**
+ * Configuration data.
+ */
struct GNUNET_GC_Configuration *cfg;
+
+ /**
+ * Error logging.
+ */
struct GNUNET_GE_Context *ectx;
+
+ /**
+ * Connection to gnunetd.
+ */
struct GNUNET_ClientServerConnection *sock;
+
+ /**
+ * Thread listening for replies.
+ */
struct GNUNET_ThreadHandle *thread;
+
+ /**
+ * Lock for access to this struct.
+ */
struct GNUNET_Mutex *lock;
- SEARCH_HANDLE **handles;
- unsigned int handleCount;
- unsigned int handleSize;
+
+ /**
+ * List of active requests.
+ */
+ struct GNUNET_FS_SearchHandle *handles;
+
+ /**
+ * Flag to signal that we should abort.
+ */
int abort;
-} SEARCH_CONTEXT;
+};
/**
- * How often should we automatically retry if we
- * get a transient error back from gnunetd?
+ * Retransmit all of the requests to gnunetd
+ * (used after a disconnect).
*/
-#define AUTO_RETRY 4
+static int
+reissue_requests (struct GNUNET_FS_SearchContext *ctx)
+{
+ const CS_fs_request_search_MESSAGE *req;
+ struct GNUNET_FS_SearchHandle *pos;
+ pos = ctx->handles;
+ while (pos != NULL)
+ {
+ req = (const CS_fs_request_search_MESSAGE *) &pos[1];
+ if (GNUNET_OK !=
+ GNUNET_client_connection_write (ctx->sock, &req->header))
+ return GNUNET_SYSERR;
+ pos = pos->next;
+ }
+ if (GNUNET_SYSERR == GNUNET_client_connection_ensure_connected (ctx->sock))
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+}
+
/**
* Thread that processes replies from gnunetd and
* calls the appropriate callback.
*/
static void *
-processReplies (void *cls)
+reply_process_thread (void *cls)
{
- SEARCH_CONTEXT *ctx = cls;
+ struct GNUNET_FS_SearchContext *ctx = cls;
GNUNET_MessageHeader *hdr;
- int i;
int matched;
const CS_fs_reply_content_MESSAGE *rep;
GNUNET_HashCode query;
unsigned int size;
GNUNET_CronTime delay;
+ const CS_fs_request_search_MESSAGE *req;
+ GNUNET_DatastoreValue *value;
+ struct GNUNET_FS_SearchHandle *pos;
+ struct GNUNET_FS_SearchHandle *prev;
+ int unique;
delay = 100 * GNUNET_CRON_MILLISECONDS;
while (ctx->abort == GNUNET_NO)
@@ -105,44 +179,54 @@
GNUNET_free (hdr);
continue;
}
+ unique =
+ GNUNET_EC_file_block_get_type (size,
+ (DBlock *) & rep[1]) ==
+ GNUNET_ECRS_BLOCKTYPE_DATA;
+ value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
+ value->size = htonl (size + sizeof (GNUNET_DatastoreValue));
+ value->type =
+ htonl (GNUNET_EC_file_block_get_type (size, (DBlock *) & rep[1]));
+ value->prio = htonl (0);
+ value->anonymityLevel = rep->anonymityLevel;
+ value->expirationTime = rep->expirationTime;
+ memcpy (&value[1], &rep[1], size);
matched = 0;
GNUNET_mutex_lock (ctx->lock);
- for (i = ctx->handleCount - 1; i >= 0; i--)
+ prev = NULL;
+ pos = ctx->handles;
+ while (pos != NULL)
{
+ req = (const CS_fs_request_search_MESSAGE *) &pos[1];
if (0 ==
- memcmp (&query, &ctx->handles[i]->req->query[0],
- sizeof (GNUNET_HashCode)))
+ memcmp (&query, &req->query[0], sizeof (GNUNET_HashCode)))
{
- GNUNET_DatastoreValue *value;
-
matched++;
- if (ctx->handles[i]->callback != NULL)
- {
- value =
- GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
- value->size =
- htonl (size + sizeof (GNUNET_DatastoreValue));
- value->type =
- htonl (GNUNET_EC_file_block_get_type
- (size, (DBlock *) & rep[1]));
- value->prio = htonl (0);
- value->anonymityLevel = rep->anonymityLevel;
- value->expirationTime = rep->expirationTime;
- memcpy (&value[1], &rep[1], size);
- if (GNUNET_SYSERR == ctx->handles[i]->callback (&query,
- value,
- ctx->
- handles
- [i]->
- closure,
- 0))
- {
- ctx->handles[i]->callback = NULL;
- }
- GNUNET_free (value);
- }
+ if ((pos->callback != NULL) &&
+ (GNUNET_SYSERR == pos->callback (&query,
+ value,
+ pos->closure, 0)))
+ pos->callback = NULL;
}
+ if (unique)
+ {
+ if (prev == NULL)
+ ctx->handles = pos->next;
+ else
+ prev->next = pos->next;
+ GNUNET_free (pos);
+ if (prev == NULL)
+ pos = ctx->handles;
+ else
+ pos = prev->next;
+ }
+ else
+ {
+ prev = pos;
+ pos = pos->next;
+ }
}
+ GNUNET_free (value);
GNUNET_mutex_unlock (ctx->lock);
#if DEBUG_FSLIB
if (matched == 0)
@@ -154,32 +238,32 @@
}
else
{
-#if DEBUG_FSLIB
- GNUNET_GE_LOG (ctx->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "FSLIB: error communicating with gnunetd; sleeping
for %ums\n",
- delay);
-#endif
- if (ctx->abort == GNUNET_NO)
- GNUNET_thread_sleep (delay);
- delay *= 2;
- if (delay > 5 * GNUNET_CRON_SECONDS)
- delay = 5 * GNUNET_CRON_SECONDS;
+ while (GNUNET_NO == ctx->abort)
+ {
+ GNUNET_thread_sleep (delay);
+ delay *= 2;
+ if (delay > 5 * GNUNET_CRON_SECONDS)
+ delay = 5 * GNUNET_CRON_SECONDS;
+ if ((GNUNET_OK ==
+ GNUNET_client_connection_ensure_connected (ctx->sock))
+ && (GNUNET_OK == reissue_requests (ctx)))
+ break; /* we're back, continue outer loop! */
+ }
}
GNUNET_free_non_null (hdr);
}
return NULL;
}
-SEARCH_CONTEXT *
-GNUNET_FS_create_search_context (struct GNUNET_GE_Context * ectx,
- struct GNUNET_GC_Configuration * cfg,
- struct GNUNET_Mutex * lock)
+struct GNUNET_FS_SearchContext *
+GNUNET_FS_create_search_context (struct GNUNET_GE_Context *ectx,
+ struct GNUNET_GC_Configuration *cfg,
+ struct GNUNET_Mutex *lock)
{
- SEARCH_CONTEXT *ret;
+ struct GNUNET_FS_SearchContext *ret;
GNUNET_GE_ASSERT (ectx, lock != NULL);
- ret = GNUNET_malloc (sizeof (SEARCH_CONTEXT));
+ ret = GNUNET_malloc (sizeof (struct GNUNET_FS_SearchContext));
ret->ectx = ectx;
ret->cfg = cfg;
ret->lock = lock;
@@ -190,10 +274,8 @@
return NULL;
}
ret->handles = NULL;
- ret->handleCount = 0;
- ret->handleSize = 0;
ret->abort = GNUNET_NO;
- ret->thread = GNUNET_thread_create (&processReplies, ret, 128 * 1024);
+ ret->thread = GNUNET_thread_create (&reply_process_thread, ret, 128 * 1024);
if (ret->thread == NULL)
GNUNET_GE_DIE_STRERROR (ectx,
GNUNET_GE_FATAL | GNUNET_GE_ADMIN |
@@ -205,9 +287,9 @@
GNUNET_FS_destroy_search_context (struct GNUNET_FS_SearchContext *ctx)
{
void *unused;
+ struct GNUNET_FS_SearchHandle *pos;
GNUNET_mutex_lock (ctx->lock);
- GNUNET_GE_ASSERT (ctx->ectx, ctx->handleCount == 0);
ctx->abort = GNUNET_YES;
GNUNET_client_connection_close_forever (ctx->sock);
GNUNET_mutex_unlock (ctx->lock);
@@ -215,7 +297,12 @@
GNUNET_thread_join (ctx->thread, &unused);
ctx->lock = NULL;
GNUNET_client_connection_destroy (ctx->sock);
- GNUNET_array_grow (ctx->handles, ctx->handleSize, 0);
+ while (ctx->handles != NULL)
+ {
+ pos = ctx->handles;
+ ctx->handles = pos->next;
+ GNUNET_free (pos);
+ }
GNUNET_free (ctx);
}
@@ -229,140 +316,51 @@
* @param callback method to call for each result
* @param prio priority to use for the search
*/
-SEARCH_HANDLE *
-GNUNET_FS_start_search (SEARCH_CONTEXT * ctx,
+int
+GNUNET_FS_start_search (struct GNUNET_FS_SearchContext *ctx,
const GNUNET_PeerIdentity * target,
unsigned int type,
unsigned int keyCount,
const GNUNET_HashCode * keys,
unsigned int anonymityLevel,
- unsigned int prio,
- GNUNET_CronTime timeout,
GNUNET_DatastoreValueIterator callback, void *closure)
{
- SEARCH_HANDLE *ret;
+ struct GNUNET_FS_SearchHandle *ret;
CS_fs_request_search_MESSAGE *req;
#if DEBUG_FSLIB
GNUNET_EncName enc;
#endif
- ret = GNUNET_malloc (sizeof (SEARCH_HANDLE));
+ ret = GNUNET_malloc (sizeof (struct GNUNET_FS_SearchHandle) +
+ sizeof (CS_fs_request_search_MESSAGE) +
+ (keyCount - 1) * sizeof (GNUNET_HashCode));
+ req = (CS_fs_request_search_MESSAGE *) & ret[1];
#if DEBUG_FSLIB
GNUNET_GE_LOG (ctx->ectx,
GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
"FSLIB: start search (%p)\n", ret);
#endif
- req =
- GNUNET_malloc (sizeof (CS_fs_request_search_MESSAGE) +
- (keyCount - 1) * sizeof (GNUNET_HashCode));
req->header.size =
htons (sizeof (CS_fs_request_search_MESSAGE) +
(keyCount - 1) * sizeof (GNUNET_HashCode));
req->header.type = htons (GNUNET_CS_PROTO_GAP_QUERY_START);
- req->prio = htonl (prio);
req->anonymityLevel = htonl (anonymityLevel);
- req->expiration = GNUNET_htonll (timeout);
req->type = htonl (type);
if (target != NULL)
req->target = *target;
else
memset (&req->target, 0, sizeof (GNUNET_PeerIdentity));
memcpy (&req->query[0], keys, keyCount * sizeof (GNUNET_HashCode));
- ret->req = req;
ret->callback = callback;
ret->closure = closure;
GNUNET_mutex_lock (ctx->lock);
- if (ctx->handleCount == ctx->handleSize)
- {
- GNUNET_array_grow (ctx->handles, ctx->handleSize,
- ctx->handleSize * 2 + 4);
- }
- ctx->handles[ctx->handleCount++] = ret;
+ ret->next = ctx->handles;
+ ctx->handles = ret;
GNUNET_mutex_unlock (ctx->lock);
-#if DEBUG_FSLIB
- IF_GELOG (ctx->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- GNUNET_hash_to_enc (&req->query[0], &enc));
- GNUNET_GE_LOG (ctx->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "FSLIB: initiating search for `%s' of type %u\n", &enc,
- type);
-#endif
- GNUNET_GE_ASSERT (NULL, ctx->sock != NULL);
- if (GNUNET_OK != GNUNET_client_connection_write (ctx->sock, &req->header))
- {
- GNUNET_FS_stop_search (ctx, ret);
- return NULL;
- }
-#if DEBUG_FSLIB
- GNUNET_GE_LOG (ctx->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "FSLIB: search started (%p)\n", ret);
-#endif
- return ret;
+ return GNUNET_OK;
}
/**
- * Stop searching.
- */
-void
-GNUNET_FS_stop_search (SEARCH_CONTEXT * ctx, SEARCH_HANDLE * handle)
-{
- int i;
-
-#if DEBUG_FSLIB
- GNUNET_GE_LOG (ctx->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "FSLIB: stop search (%p)\n", handle);
-#endif
- handle->req->header.type = htons (GNUNET_CS_PROTO_GAP_QUERY_STOP);
- GNUNET_GE_ASSERT (NULL, ctx->sock != NULL);
- if (GNUNET_OK !=
- GNUNET_client_connection_write (ctx->sock, &handle->req->header))
- {
- GNUNET_GE_LOG (ctx->ectx,
- GNUNET_GE_WARNING | GNUNET_GE_REQUEST |
- GNUNET_GE_DEVELOPER,
- "FSLIB: failed to request stop search with gnunetd\n");
- }
- GNUNET_mutex_lock (ctx->lock);
- for (i = ctx->handleCount - 1; i >= 0; i--)
- if (ctx->handles[i] == handle)
- {
- ctx->handles[i] = ctx->handles[--ctx->handleCount];
- break;
- }
- GNUNET_mutex_unlock (ctx->lock);
- GNUNET_free (handle->req);
-#if DEBUG_FSLIB
- GNUNET_GE_LOG (ctx->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "FSLIB: search stopped (%p)\n", handle);
-#endif
- GNUNET_free (handle);
-}
-
-/**
- * What is the current average priority of entries
- * in the routing table like? Returns -1 on error.
- */
-int
-GNUNET_FS_get_current_average_priority (struct GNUNET_ClientServerConnection
- *sock)
-{
- GNUNET_MessageHeader req;
- int ret;
-
- req.size = htons (sizeof (GNUNET_MessageHeader));
- req.type = htons (GNUNET_CS_PROTO_GAP_GET_AVG_PRIORITY);
- if (GNUNET_OK != GNUNET_client_connection_write (sock, &req))
- return -1;
- if (GNUNET_OK != GNUNET_client_connection_read_result (sock, &ret))
- return -1;
- return ret;
-}
-
-/**
* Insert a block.
*
* @param block the block (properly encoded and all)
@@ -590,10 +588,10 @@
GNUNET_FS_test_indexed (struct GNUNET_ClientServerConnection *sock,
const GNUNET_HashCode * hc)
{
- RequestTestindex ri;
+ CS_fs_request_test_index_MESSAGE ri;
int ret;
- ri.header.size = htons (sizeof (RequestTestindex));
+ ri.header.size = htons (sizeof (CS_fs_request_test_index_MESSAGE));
ri.header.type = htons (GNUNET_CS_PROTO_GAP_TESTINDEX);
ri.reserved = htonl (0);
ri.fileId = *hc;
Modified: GNUnet/src/applications/stats/clientapi.c
===================================================================
--- GNUnet/src/applications/stats/clientapi.c 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/applications/stats/clientapi.c 2008-02-06 07:11:29 UTC (rev
6162)
@@ -164,9 +164,8 @@
case GNUNET_CS_PROTO_GAP_QUERY_START:
name = "CS_PROTO_gap_QUERY_START";
break;
- case GNUNET_CS_PROTO_GAP_QUERY_STOP:
- /* case GNUNET_CS_PROTO_GAP_RESULT : */
- name = "CS_PROTO_gap_QUERY_STOP or CS_PROTO_gap_RESULT";
+ case GNUNET_CS_PROTO_GAP_RESULT :
+ name = "CS_PROTO_gap_RESULT";
break;
case GNUNET_CS_PROTO_GAP_INSERT:
name = "CS_PROTO_gap_INSERT";
@@ -183,9 +182,6 @@
case GNUNET_CS_PROTO_GAP_TESTINDEX:
name = "CS_PROTO_gap_TESTINDEX";
break;
- case GNUNET_CS_PROTO_GAP_GET_AVG_PRIORITY:
- name = "CS_PROTO_gap_GET_AVG_PRIORITY";
- break;
case GNUNET_CS_PROTO_GAP_INIT_INDEX:
name = "CS_PROTO_gap_INIT_INDEX";
break;
Modified: GNUnet/src/include/Makefile.am
===================================================================
--- GNUnet/src/include/Makefile.am 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/include/Makefile.am 2008-02-06 07:11:29 UTC (rev 6162)
@@ -26,7 +26,6 @@
gnunet_fragmentation_service.h \
gnunet_fs_lib.h \
gnunet_fsui_lib.h \
- gnunet_gap_service.h \
gnunet_getoption_lib.h \
gnunet_identity_lib.h \
gnunet_identity_service.h \
Modified: GNUnet/src/include/ecrs_core.h
===================================================================
--- GNUnet/src/include/ecrs_core.h 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/include/ecrs_core.h 2008-02-06 07:11:29 UTC (rev 6162)
@@ -247,6 +247,8 @@
/**
* Get the query that will be used to query for
* a certain block of data.
+ *
+ * @param db the block in plaintext
*/
void GNUNET_EC_file_block_get_query (const DBlock * data,
unsigned int len,
@@ -287,7 +289,7 @@
* Verify that the given Datum is a valid response
* to a given query.
*
- * @param type the type of the queryo
+ * @param type the type of the query
* @param size the size of the data
* @param data the encoded data
* @param knownDatumQuery result of GNUNET_EC_file_block_check_and_get_query
Modified: GNUnet/src/include/fs.h
===================================================================
--- GNUnet/src/include/fs.h 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/include/fs.h 2008-02-06 07:11:29 UTC (rev 6162)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Christian Grothoff (and
other contributing authors)
+ (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 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
@@ -20,13 +20,13 @@
/**
* @file applications/fs/module/fs.h
- * @brief FS Client-Server messages
+ * @brief FS Client-Server and P2P message formats
* @author Christian Grothoff
*/
#ifndef FS_H
#define FS_H
-#include "gnunet_blockstore.h"
+#include "gnunet_util.h"
/**
* Client to server: search for content. Variable
@@ -39,16 +39,11 @@
GNUNET_MessageHeader header;
/**
- * Priority of the search.
+ * Should be zero.
*/
- unsigned int prio;
+ int reserved;
/**
- * At what time does the search expire?
- */
- GNUNET_CronTime expiration;
-
- /**
* Type of the content that we're looking for.
* 0 for any.
*/
@@ -77,15 +72,22 @@
/**
* Server to client: content (in response to a CS_fs_request_search_MESSAGE).
The
- * header is followed by variable size data (the data portion
- * of the GNUNET_DatastoreValue).
+ * header is followed by the variable size data of a DBlock (as
+ * defined in ecrs_core.h).
*/
typedef struct
{
GNUNET_MessageHeader header;
+ /**
+ * Anonymity level for the content, maybe
+ * 0 if not known.
+ */
unsigned int anonymityLevel;
+ /**
+ * Expiration time of the response (relative to now).
+ */
GNUNET_CronTime expirationTime;
} CS_fs_reply_content_MESSAGE;
@@ -94,21 +96,21 @@
/**
* Client to server: insert content.
* This struct is followed by a variable
- * number of bytes of content.
+ * number of bytes of content (a DBlock).
*/
typedef struct
{
GNUNET_MessageHeader header;
/**
- * Priority for the on-demand encoded entry.
+ * Reserved (should be zero). For alignment.
*/
- unsigned int prio;
+ int reserved;
/**
- * At what time does the entry expire?
+ * Priority for the on-demand encoded entry.
*/
- GNUNET_CronTime expiration;
+ unsigned int prio;
/**
* What are the anonymity requirements for this content?
@@ -117,6 +119,11 @@
*/
unsigned int anonymityLevel;
+ /**
+ * At what time does the entry expire?
+ */
+ GNUNET_CronTime expiration;
+
} CS_fs_request_insert_MESSAGE;
/**
@@ -148,11 +155,23 @@
GNUNET_MessageHeader header;
/**
+ * Reserved (should be zero). For alignment.
+ */
+ int reserved;
+
+ /**
* Priority for the on-demand encoded entry.
*/
unsigned int prio;
/**
+ * What are the anonymity requirements for this content?
+ * Use 0 if anonymity is not required (enables direct
+ * sharing / DHT routing).
+ */
+ unsigned int anonymityLevel;
+
+ /**
* At what time does the entry expire?
*/
GNUNET_CronTime expiration;
@@ -170,26 +189,23 @@
*/
GNUNET_HashCode fileId;
- /**
- * What are the anonymity requirements for this content?
- * Use 0 if anonymity is not required (enables direct
- * sharing / DHT routing).
- */
- unsigned int anonymityLevel;
-
} CS_fs_request_index_MESSAGE;
/**
- * Client to server: delete content. This struct is followed by a
- * variable number of bytes of the content that is to be deleted.
+ * Client to server: delete content. This struct is followed by
+ * the DBlock (of variable size) of the content that is to be deleted.
*/
typedef struct
{
GNUNET_MessageHeader header;
+ /**
+ * Reserved (should be zero). For alignment.
+ */
+ int reserved;
+
} CS_fs_request_delete_MESSAGE;
-
/**
* Client to server: unindex file.
*/
@@ -225,20 +241,208 @@
*/
GNUNET_HashCode fileId;
-} RequestTestindex;
+} CS_fs_request_test_index_MESSAGE;
/**
- * Encapsulation of the data in the format that is passed through gap.
- * We essentially add the timeout value since that part is supposed to
- * be communicated to other peers.
+ * Request for content. The number of queries can
+ * be determined from the header. This struct
+ * maybe followed by a bloom filter (size determined
+ * by the header) which includes hashes of responses
+ * that should NOT be returned. If there is no
+ * bloom filter, the filter_mutator
+ * should be zero.
*/
typedef struct
{
- GNUNET_DataContainer dc;
- unsigned int reserved; /* for 64-bit alignment */
- unsigned long long timeout;
-} GapWrapper;
+ GNUNET_MessageHeader header;
+ /**
+ * Type of the query (block type).
+ */
+ unsigned int type;
+ /**
+ * How important is this request (network byte order)
+ */
+ unsigned int priority;
+
+ /**
+ * Relative time to live in GNUNET_CRON_MILLISECONDS (network byte order)
+ */
+ int ttl;
+
+ /**
+ * The content hash should be mutated using this value
+ * before checking against the bloomfilter (used to
+ * get many different filters for the same hash codes).
+ */
+ int filter_mutator;
+
+ /**
+ * How many queries do we have (should be
+ * greater than zero).
+ */
+ unsigned int number_of_queries;
+
+ /**
+ * To whom to return results?
+ */
+ GNUNET_PeerIdentity returnTo;
+
+ /**
+ * Hashcodes of the file(s) we're looking for.
+ * Details depend on the query type.
+ */
+ GNUNET_HashCode queries[1];
+
+} P2P_gap_query_MESSAGE;
+
+/**
+ * Return message for search result. This struct
+ * is always followed by a DBlock (see ecrs_core.h)
+ * which contains the GNUNET_ECRS_BLOCKTYPE followed
+ * by the actual (encrypted) data.
+ */
+typedef struct
+{
+ GNUNET_MessageHeader header;
+
+ /**
+ * Always zero (for now).
+ */
+ unsigned int reserved; /* for 64-bit alignment */
+
+ /**
+ * When does this result expire? The given time
+ * is relative (and in big-endian).
+ */
+ unsigned long long expiration;
+
+} P2P_gap_reply_MESSAGE;
+
+
+/* ***************** policy constants **************** */
+
+/**
+ * Bandwidth value of an (effectively) 0-priority query.
+ */
+#define QUERY_BANDWIDTH_VALUE 0.001
+
+/**
+ * Bandwidth value of a 0-priority content (must be
+ * fairly high compared to query since content is
+ * typically significantly larger -- and more valueable
+ * since it can take many queries to get one piece of
+ * content).
+ */
+#define CONTENT_BANDWIDTH_VALUE 0.8
+
+/**
+ * By which amount do we decrement the TTL for simple forwarding /
+ * indirection of the query; in milli-seconds. Set somewhat in
+ * accordance to your network latency (above the time it'll take you
+ * to send a packet and get a reply).
+ */
+#define TTL_DECREMENT (5 * GNUNET_CRON_SECONDS)
+
+/**
+ * Until which load do we consider the peer idle and do not
+ * charge at all? (should be larger than GNUNET_IDLE_LOAD_THRESHOLD used
+ * by the rest of the code)!
+ */
+#define GAP_IDLE_LOAD_THRESHOLD ((100 + GNUNET_IDLE_LOAD_THRESHOLD) / 2)
+
+/**
+ * How many bits should we have per entry in the
+ * bloomfilter?
+ */
+#define GAP_BLOOMFILTER_K 16
+
+/**
+ * Minimum size of the GAP routing table.
+ */
+#define MIN_INDIRECTION_TABLE_SIZE 4
+
+
+/**
+ * How much is a response worth 'in general'. Since replies are
+ * roughly 1k and should be much (factor of 4) preferred over queries
+ * (which have a base priority of 20, which yields a base unit of
+ * roughly 1 per byte). Thus if we set this value to 4092 we'd rather
+ * send a reply instead of a query unless the queries have (on
+ * average) a priority that is more than double the reply priority
+ * (note that querymanager multiplies the query priority with 2 to
+ * compute the scheduling priority).
+ */
+#define BASE_REPLY_PRIORITY 4092
+
+/**
+ * What is the maximum time that any peer
+ * should delay forwarding a response (when
+ * waiting for bandwidth).
+ */
+#define MAX_GAP_DELAY (60 * GNUNET_CRON_SECONDS)
+
+
+/**
+ * How long should DHT requests live?
+ */
+#define MAX_DHT_DELAY (60 * GNUNET_CRON_SECONDS)
+
+
+/**
+ * What is the maximum expiration time for migrated content?
+ *
+ * This is a non-trivial issue. If we have a ceiling for migration
+ * time, it would violate anonymity if we send out content with an
+ * expiration time above that ceiling (since it would expose the
+ * content to originate from this peer). But we want to store a
+ * higher expiration time for our content in the DB.
+ *
+ * A first idea would be to pick a random time smaller than the limit
+ * for outgoing content; that does not _quite_ work since that could
+ * also expose us as the originator: only for our own content the
+ * expiration time would randomly go up and down.
+ *
+ * The current best solution is to first bound the expiration time by
+ * this ceiling (for inbound and outbound ETs, not for the database
+ * entries locally) using modulo (to, in practice, get a constant
+ * bound for the local content just like for the migrated content).
+ * Then that number is randomized for _all_ outgoing content. This
+ * way, the time left changes for all entries, but statistically
+ * always decreases on average as time progresses (also for all
+ * entries).
+ *
+ * Now, for local content eventually modulo will rebound to the MAX
+ * (whereas for migrated content it will hit 0 and disappear). But
+ * that is GNUNET_OK: the adversary cannot distinguish the modulo wraparound
+ * from content migration (refresh with higher lifetime) which could
+ * plausibly happen from the original node (and in fact would happen
+ * around the same time!). This design also achieves the design goal
+ * that if the original node disappears, the migrated content will
+ * eventually time-out (which is good since we don't want dangling
+ * search results to stay around).
+ *
+ * However, this does NOT mean that migrated content cannot live
+ * longer than 1 month -- remember, GNUnet peers discard expired
+ * content _if they run out of space_. So it is perfectly plausible
+ * that content stays around longer. Finally, clients (UI) may want
+ * to filter / rank / display search results with their current
+ * expiration to give the user some indication about availability.
+ *
+ */
+#define MAX_MIGRATION_EXP (1L * GNUNET_CRON_MONTHS)
+
+/**
+ * Estimated size of most blocks transported with
+ * the GAP protocol. 32k DBlocks plus overhead.
+ */
+#define GNUNET_GAP_ESTIMATED_DATA_SIZE (33*1024)
+
+
+
+
+
+
#endif
Modified: GNUnet/src/include/gnunet_core.h
===================================================================
--- GNUnet/src/include/gnunet_core.h 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/include/gnunet_core.h 2008-02-06 07:11:29 UTC (rev 6162)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing
authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -49,7 +49,7 @@
* roughly the main GNUnet version scheme, but is
* more a compatibility ID.
*/
-#define GNUNET_CORE_VERSION 0x00070300
+#define GNUNET_CORE_VERSION 0x00070399
/**
@@ -164,20 +164,6 @@
unsigned short len);
/**
- * Send a message to the client identified by the handle. Note that
- * the core will typically buffer these messages as much as possible
- * and only return GNUNET_SYSERR if it runs out of buffers. Returning
GNUNET_OK
- * on the other hand does NOT confirm delivery since the actual
- * transfer happens asynchronously.
- *
- * @param force GNUNET_YES if this message MUST be queued
- */
-typedef int (*GNUNET_SendToClientCallback) (struct GNUNET_ClientHandle *
- handle,
- const GNUNET_MessageHeader *
- message, int force);
-
-/**
* GNUnet CORE API for applications and services that are implemented
* on top of the GNUnet core.
*/
@@ -215,33 +201,9 @@
struct GNUNET_CronManager *cron;
- /* ****************** services and applications **************** */
+ /* ****************** services **************** */
/**
- * Load an application module. This function must be called
- * while cron is suspended. Note that the initialization and
- * shutdown function of modules are always run while cron is
- * disabled, so suspending cron is not necesary if modules
- * are loaded or unloaded inside the module initialization or
- * shutdown code.
- *
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- */
- int (*loadApplicationModule) (const char *name);
-
- /**
- * Unload an application module. This function must be called
- * while cron is suspended. Note that the initialization and
- * shutdown function of modules are always run while cron is
- * disabled, so suspending cron is not necesary if modules
- * are loaded or unloaded inside the module initialization or
- * shutdown code.
- *
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- */
- int (*unloadApplicationModule) (const char *name);
-
- /**
* Load a service module of the given name. This function must be
* called while cron is suspended. Note that the initialization and
* shutdown function of modules are always run while cron is
@@ -266,6 +228,19 @@
/* ****************** P2P data exchange **************** */
/**
+ * Send an encrypted message to another node.
+ *
+ * @param receiver the target node
+ * @param msg the message to send, NULL to tell
+ * the core to try to establish a session
+ * @param importance how important is the message?
+ * @param maxdelay how long can the message be delayed?
+ */
+ void (*unicast) (const GNUNET_PeerIdentity * receiver,
+ const GNUNET_MessageHeader * msg,
+ unsigned int importance, unsigned int maxdelay);
+
+ /**
* Send a plaintext message to another node. This is
* not the usual way for communication and should ONLY be
* used by modules that are responsible for setting up
@@ -281,19 +256,6 @@
const char *msg, unsigned int size);
/**
- * Send an encrypted message to another node.
- *
- * @param receiver the target node
- * @param msg the message to send, NULL to tell
- * the core to try to establish a session
- * @param importance how important is the message?
- * @param maxdelay how long can the message be delayed?
- */
- void (*unicast) (const GNUNET_PeerIdentity * receiver,
- const GNUNET_MessageHeader * msg,
- unsigned int importance, unsigned int maxdelay);
-
- /**
* Send an encrypted, on-demand build message to another node.
*
* @param receiver the target node
@@ -312,15 +274,6 @@
unsigned int importance,
unsigned int maxdelay);
- /**
- * Perform an operation for all connected hosts.
- * No synchronization or other checks are performed.
- *
- * @param method the method to invoke (NULL for counting only)
- * @param arg the second argument to the method
- * @return the number of connected hosts
- */
- int (*forAllConnectedNodes) (GNUNET_NodeIteratorCallback method, void *arg);
/**
* Register a callback method that should be invoked whenever a message
@@ -362,7 +315,28 @@
GNUNET_BufferFillCallback
callback);
+ /* *********************** notifications ********************* */
+
/**
+ * Call the given function whenever we get
+ * disconnected from a particular peer.
+ *
+ * @return GNUNET_OK
+ */
+ int (*register_notify_peer_disconnect)(GNUNET_NodeIteratorCallback callback,
+ void * cls);
+
+ /**
+ * Stop calling the given function whenever we get
+ * disconnected from a particular peer.
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR
+ * if this callback is not registered
+ */
+ int (*unregister_notify_peer_disconnect)(GNUNET_NodeIteratorCallback
callback,
+ void * cls);
+
+ /**
* Register a handler that is to be called for each
* message that leaves the peer.
*
@@ -454,7 +428,34 @@
/* ***************** traffic management ******************* */
+
/**
+ * Perform an operation for all connected hosts.
+ * No synchronization or other checks are performed.
+ *
+ * @param method the method to invoke (NULL for counting only)
+ * @param arg the second argument to the method
+ * @return the number of connected hosts
+ */
+ int (*forAllConnectedNodes) (GNUNET_NodeIteratorCallback method, void *arg);
+
+ /**
+ * Try to reserve downstream bandwidth for a particular peer.
+ *
+ * @param peer with whom should bandwidth be reserved?
+ * @param amount how many bytes should we expect to receive?
+ * (negative amounts can be used to undo a (recent)
+ * reservation request
+ * @param timeframe in what time interval should the other
+ * peer be able to transmit the amount? Use zero
+ * when undoing a reservation
+ * @return amount that could actually be reserved
+ */
+ int (*reserve_downstream_bandwidth)(const GNUNET_NodeIteratorCallback * peer,
+ int amount,
+ GNUNET_CronTime timeframe);
+
+ /**
* Offer the core a session for communication with the
* given peer. This is useful after establishing a connection
* with another peer to hand it of to the core. Note that
@@ -559,8 +560,23 @@
* and only return GNUNET_SYSERR if it runs out of buffers. Returning
GNUNET_OK
* on the other hand does NOT confirm delivery since the actual
* transfer happens asynchronously.
+ *
+ * @param force GNUNET_YES if this message MUST be queued
*/
- GNUNET_SendToClientCallback cs_send_to_client;
+ int (*cs_send_to_client)(struct GNUNET_ClientHandle *
+ handle,
+ const GNUNET_MessageHeader *
+ message, int force);
+
+ /**
+ * Send a message to the client identified by the handle. Note that
+ * the core will typically buffer these messages as much as possible
+ * and only return GNUNET_SYSERR if it runs out of buffers. Returning
GNUNET_OK
+ * on the other hand does NOT confirm delivery since the actual
+ * transfer happens asynchronously.
+ */
+ int (*sendErrorMessageToClient) (struct GNUNET_ClientHandle * handle,
+ GNUNET_GE_KIND kind, const char *value);
/**
* Register a method as a handler for specific message
@@ -609,7 +625,14 @@
void (*cs_terminate_client_connection) (struct
GNUNET_ClientHandle * handle);
+ /**
+ * Create a log context that will transmit errors to the
+ * given client.
+ */
+ struct GNUNET_GE_Context
+ *(*cs_create_client_log_context) (struct GNUNET_ClientHandle * handle);
+
/* ************************ MISC ************************ */
/**
@@ -665,21 +688,10 @@
* peer,
GNUNET_CronTime * time);
- /* here for binary compatibility (for now) */
-
/**
- * Send a message to the client identified by the handle. Note that
- * the core will typically buffer these messages as much as possible
- * and only return GNUNET_SYSERR if it runs out of buffers. Returning
GNUNET_OK
- * on the other hand does NOT confirm delivery since the actual
- * transfer happens asynchronously.
+ * Assert that the given tsession is no longer
+ * in use by the core.
*/
- int (*sendErrorMessageToClient) (struct GNUNET_ClientHandle * handle,
- GNUNET_GE_KIND kind, const char *value);
-
- struct GNUNET_GE_Context
- *(*cs_create_client_log_context) (struct GNUNET_ClientHandle * handle);
-
int (*connection_assert_tsession_unused) (GNUNET_TSession * tsession);
} GNUNET_CoreAPIForPlugins;
Modified: GNUnet/src/include/gnunet_dht_service.h
===================================================================
--- GNUnet/src/include/gnunet_dht_service.h 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/include/gnunet_dht_service.h 2008-02-06 07:11:29 UTC (rev
6162)
@@ -51,14 +51,10 @@
{
/**
- * Perform an asynchronous GET operation on the DHT identified by
- * 'table' using 'key' as the key. The peer does not have to be part
- * of the table (if so, we will attempt to locate a peer that is!)
+ * Perform an asynchronous GET operation on the DHT identified.
*
- * @param table table to use for the lookup
+ * @param type expected type of the response object
* @param key the key to look up
- * @param timeout how long to wait until this operation should
- * automatically time-out
* @param callback function to call on each result
* @param closure extra argument to callback
* @return handle to stop the async get
Modified: GNUnet/src/include/gnunet_fs_lib.h
===================================================================
--- GNUnet/src/include/gnunet_fs_lib.h 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/include/gnunet_fs_lib.h 2008-02-06 07:11:29 UTC (rev 6162)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing
authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -46,66 +46,48 @@
struct GNUNET_FS_SearchContext;
-struct GNUNET_FS_SearchContext *GNUNET_FS_create_search_context (struct
-
GNUNET_GE_Context
- *ectx,
- struct
-
GNUNET_GC_Configuration
- *cfg,
- struct
- GNUNET_Mutex
- *lock);
+struct GNUNET_FS_SearchContext *
+GNUNET_FS_create_search_context (struct
+ GNUNET_GE_Context
+ *ectx,
+ struct
+ GNUNET_GC_Configuration
+ *cfg,
+ struct
+ GNUNET_Mutex
+ *lock);
void GNUNET_FS_destroy_search_context (struct GNUNET_FS_SearchContext *ctx);
-struct GNUNET_FS_SearchHandle;
-
/**
* Search for blocks matching the given key and type.
*
* @param target identity of host known to have the
* content, NULL if no such identity is known
- * @param timeout how long to search
* @param anonymityLevel what are the anonymity
* requirements for this request? 0 for no
* anonymity (DHT/direct transfer ok)
* @param callback method to call for each result
- * @param prio priority to use for the search
+ * @return GNUNET_OK
*/
-struct GNUNET_FS_SearchHandle *GNUNET_FS_start_search (struct
- GNUNET_FS_SearchContext
- *ctx,
- const
- GNUNET_PeerIdentity *
- target,
- unsigned int type,
- unsigned int keyCount,
- const GNUNET_HashCode *
- keys,
- unsigned int
- anonymityLevel,
- unsigned int prio,
- GNUNET_CronTime
- timeout,
-
GNUNET_DatastoreValueIterator
- callback,
- void *closure);
+int
+GNUNET_FS_start_search (struct
+ GNUNET_FS_SearchContext
+ *ctx,
+ const
+ GNUNET_PeerIdentity *
+ target,
+ unsigned int type,
+ unsigned int keyCount,
+ const GNUNET_HashCode *
+ keys,
+ unsigned int
+ anonymityLevel,
+ GNUNET_DatastoreValueIterator
+ callback,
+ void *closure);
/**
- * Stop searching.
- */
-void GNUNET_FS_stop_search (struct GNUNET_FS_SearchContext *ctx,
- struct GNUNET_FS_SearchHandle *handle);
-
-/**
- * What is the current average priority of entries
- * in the routing table like? Returns -1 on error.
- */
-int GNUNET_FS_get_current_average_priority (struct
- GNUNET_ClientServerConnection
- *sock);
-
-/**
* Insert a block. Note that while the API is VERY similar to
* GNUNET_FS_index in terms of signature, the block for GNUNET_FS_index must
be in
* plaintext, whereas the block passed to GNUNET_FS_insert must be encrypted!
Deleted: GNUnet/src/include/gnunet_gap_service.h
===================================================================
--- GNUnet/src/include/gnunet_gap_service.h 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/include/gnunet_gap_service.h 2008-02-06 07:11:29 UTC (rev
6162)
@@ -1,148 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file include/gnunet_gap_service.h
- * @brief API to the GAP-module. This API is what will be used by
- * GAP clients that run as modules within gnunetd. GAP is
- * currently not supposed to be used directly by clients,
- * look at the gnunet_fs_lib.h for the lowest-level client API.
- * @author Christian Grothoff
- */
-
-#ifndef GAP_SERVICE_API_H
-#define GAP_SERVICE_API_H
-
-#include "gnunet_core.h"
-#include "gnunet_blockstore.h"
-
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-/**
- * Estimated size of most blocks transported with
- * the GAP protocol. 32k DBlocks plus overhead.
- */
-#define GNUNET_GAP_ESTIMATED_DATA_SIZE (33*1024)
-
-/**
- * Function that helps the routing code to find out if
- * a given reply is the one and only reply for a given
- * request.
- * @param verify check that content is valid? (GNUNET_YES/GNUNET_NO)
- */
-typedef int (*GNUNET_UniqueReplyIdentifierCallback) (const
- GNUNET_DataContainer *
- content,
- unsigned int query_type,
- int verify,
- const GNUNET_HashCode *
- primaryKey);
-
-/**
- * Given some content, compute the unique
- * GNUNET_hash of the content that can then be used
- * to sort out duplicates.
- */
-typedef int (*GNUNET_ReplyHashingCallback) (const GNUNET_DataContainer * data,
- GNUNET_HashCode * hc);
-
-/**
- * Functions of the GAP Service API.
- */
-typedef struct
-{
-
- /**
- * Start GAP.
- *
- * @param datastore the storage callbacks to use for storing data
- * @return GNUNET_SYSERR on error, GNUNET_OK on success
- */
- int (*init) (GNUNET_Blockstore * datastore,
- GNUNET_UniqueReplyIdentifierCallback uri,
- GNUNET_ReplyHashingCallback rhf);
-
- /**
- * Perform a GET operation using 'key' as the key. Note that no
- * callback is given for the results since GAP just calls PUT on the
- * datastore on anything that is received, and the caller will be
- * listening for these puts.
- *
- * @param target peer to ask primarily (maybe NULL)
- * @param type the type of the block that we're looking for
- * @param keys the keys to query for
- * @param timeout how long to wait until this operation should
- * automatically time-out
- * @return GNUNET_OK if we will start to query, GNUNET_SYSERR if all of our
- * buffers are full or other error
- */
- int (*get_start) (const GNUNET_PeerIdentity * target,
- unsigned int type,
- unsigned int anonymityLevel,
- unsigned int keyCount,
- const GNUNET_HashCode * keys,
- GNUNET_CronTime timeout, unsigned int prio);
-
- /**
- * Stop sending out queries for a given key. GAP will automatically
- * stop sending queries at some point, but this method can be used
- * to stop it earlier.
- */
- int (*get_stop) (unsigned int type,
- unsigned int keyCount, const GNUNET_HashCode * keys);
-
- /**
- * Try to migrate the given content.
- *
- * @param data the content to migrate
- * @param position where to write the message
- * @param padding the maximum size that the message may be
- * @return the number of bytes written to
- * that buffer (must be a positive number).
- */
- unsigned int (*tryMigrate) (const GNUNET_DataContainer * data,
- const GNUNET_HashCode * primaryKey,
- char *position, unsigned int padding);
-
- /**
- * What is the average priority of requests that we
- * are currently routing?
- */
- unsigned int (*getAvgPriority) (void);
-
-} GNUNET_GAP_ServiceAPI;
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* GAP_SERVICE_API_H */
Modified: GNUnet/src/include/gnunet_protocols.h
===================================================================
--- GNUnet/src/include/gnunet_protocols.h 2008-02-06 06:52:39 UTC (rev
6161)
+++ GNUnet/src/include/gnunet_protocols.h 2008-02-06 07:11:29 UTC (rev
6162)
@@ -135,11 +135,6 @@
#define GNUNET_CS_PROTO_GAP_QUERY_START 8
/**
- * client to gnunetd: stop query
- */
-#define GNUNET_CS_PROTO_GAP_QUERY_STOP 9
-
-/**
* gnunetd to client: here is your answer
*/
#define GNUNET_CS_PROTO_GAP_RESULT 9
@@ -170,12 +165,6 @@
#define GNUNET_CS_PROTO_GAP_TESTINDEX 14
/**
- * Client to gnunetd: what is the average priority of entries in the
- * routing table?
- */
-#define GNUNET_CS_PROTO_GAP_GET_AVG_PRIORITY 15
-
-/**
* client to gnunetd: initialize to index file
*/
#define GNUNET_CS_PROTO_GAP_INIT_INDEX 16
@@ -375,12 +364,12 @@
/**
* Query for content.
*/
-#define GNUNET_P2P_PROTO_GAP_QUERY 16
+#define GNUNET_P2P_PROTO_GAP_QUERY 8
/**
* receive content
*/
-#define GNUNET_P2P_PROTO_GAP_RESULT 17
+#define GNUNET_P2P_PROTO_GAP_RESULT 9
/************** p2p DHT application messages ************/
@@ -485,7 +474,21 @@
#define GNUNET_ECRS_BLOCKTYPE_ONDEMAND_OLD 0xFFFFFFFF
+/* ************* priorities for poll-content ************ */
+/* note that the absolute values do not matter;
+ highest priority first is the rule!
+ The naming-prefix used is after the name of
+ the module using the respective constant. */
+
+#define GNUNET_FS_GAP_QUERY_POLL_PRIORITY 100
+
+#define GNUNET_DHT_QUERY_POLL_PRIORITY 2
+
+#define GNUNET_FS_GAP_CONTENT_MIGRATION_PRIORITY 1
+
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: GNUnet/src/server/core.c
===================================================================
--- GNUnet/src/server/core.c 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/src/server/core.c 2008-02-06 07:11:29 UTC (rev 6162)
@@ -530,8 +530,6 @@
applicationCore.cron = cron;
applicationCore.version = 0;
applicationCore.myIdentity = NULL; /* for now */
- applicationCore.loadApplicationModule = &loadApplicationModule; /*
core.c */
- applicationCore.unloadApplicationModule = &unloadApplicationModule; /*
core.c */
applicationCore.request_service = &GNUNET_CORE_request_service; /*
core.c */
applicationCore.release_service = &GNUNET_CORE_release_service; /*
core.c */
Modified: GNUnet/todo
===================================================================
--- GNUnet/todo 2008-02-06 06:52:39 UTC (rev 6161)
+++ GNUnet/todo 2008-02-06 07:11:29 UTC (rev 6162)
@@ -13,6 +13,7 @@
gnunet-insert only if the file is actually needed!)
- power insert [#854]
- RPC API and testcase
+- switch libgcrypt to not use entropy during testcases
1.0.0 (aka "userfriendly"):
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r6162 - in GNUnet: . libltdl src/applications src/applications/fs src/applications/fs/ecrs src/applications/fs/gap src/applications/fs/lib src/applications/stats src/include src/server,
gnunet <=