diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-07-29 08:05:52 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-07-29 08:05:52 +0000 |
commit | b80e650bad570e01b5600aab2a667d177fc17770 (patch) | |
tree | ae5b933796c34f8c0e56f54448da98c4174f683c | |
parent | 673dda8cec9a607d77543abd697982fc1fe9e271 (diff) | |
download | gnunet-b80e650bad570e01b5600aab2a667d177fc17770.tar.gz gnunet-b80e650bad570e01b5600aab2a667d177fc17770.zip |
travelhacking
28 files changed, 2706 insertions, 214 deletions
@@ -16,20 +16,21 @@ away), in order in which they will likely be done: | |||
16 | PHASE #2: (Goal: recover basic file-sharing functionality) | 16 | PHASE #2: (Goal: recover basic file-sharing functionality) |
17 | * TESTING (needed for DV, DHT, Topology) | 17 | * TESTING (needed for DV, DHT, Topology) |
18 | - implement library for local testing | 18 | - implement library for local testing |
19 | + check API for hostname specification; | ||
20 | maybe use space-separated list instead? | ||
21 | + modify configuration to allow controlling | 19 | + modify configuration to allow controlling |
22 | connections for non-local starts | 20 | connections for non-local starts |
23 | + starting of groups of peers (and auto-setting | 21 | + CORE service does not start with valid peer ID (all zeross) |
24 | of PORT options) | 22 | -- testcase fails! |
25 | + testbed creation with topology | 23 | + consider changing API for peer-group termination |
26 | + testbed with churn | 24 | to call continuation when done |
25 | + testbed creation with topology (needs working F2F topology) [Nate] | ||
26 | + testbed with churn [Nate] | ||
27 | - implement testcases for library | 27 | - implement testcases for library |
28 | + test basic peer start | 28 | + get test for basic peer start to work! |
29 | + test basic peer connect | 29 | + test basic peer connect |
30 | + test group start | 30 | + test group start |
31 | + test topology creation | 31 | + test basic peer re-configure [Nate] |
32 | + test churn generation | 32 | + test topology creation [Nate] |
33 | + test churn generation [Nate] | ||
33 | * TOPOLOGY: | 34 | * TOPOLOGY: |
34 | - implement testcases (needs TESTING) | 35 | - implement testcases (needs TESTING) |
35 | * HOSTLIST: | 36 | * HOSTLIST: |
diff --git a/src/Makefile.am b/src/Makefile.am index 92be62974..9b3aa46ab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -18,10 +18,10 @@ SUBDIRS = \ | |||
18 | statistics \ | 18 | statistics \ |
19 | datacache \ | 19 | datacache \ |
20 | datastore \ | 20 | datastore \ |
21 | testing \ | ||
22 | template \ | 21 | template \ |
23 | transport \ | 22 | transport \ |
24 | core \ | 23 | core \ |
24 | testing \ | ||
25 | $(HOSTLIST_DIR) \ | 25 | $(HOSTLIST_DIR) \ |
26 | topology | 26 | topology |
27 | 27 | ||
diff --git a/src/arm/arm.h b/src/arm/arm.h index 2293ec036..a8f5d0706 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h | |||
@@ -27,6 +27,6 @@ | |||
27 | 27 | ||
28 | #include "gnunet_common.h" | 28 | #include "gnunet_common.h" |
29 | 29 | ||
30 | #define DEBUG_ARM GNUNET_NO | 30 | #define DEBUG_ARM GNUNET_YES |
31 | 31 | ||
32 | #endif | 32 | #endif |
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index 32674117c..ac58904ed 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c | |||
@@ -167,6 +167,8 @@ signal_result (struct GNUNET_SERVER_Client *client, | |||
167 | { | 167 | { |
168 | uint16_t *res; | 168 | uint16_t *res; |
169 | 169 | ||
170 | if (NULL == client) | ||
171 | return; | ||
170 | #if DEBUG_ARM | 172 | #if DEBUG_ARM |
171 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
172 | "Telling client that service `%s' is now %s\n", | 174 | "Telling client that service `%s' is now %s\n", |
@@ -387,7 +389,8 @@ start_service (struct GNUNET_SERVER_Client *client, const char *servicename) | |||
387 | sl->mtime = sbuf.st_mtime; | 389 | sl->mtime = sbuf.st_mtime; |
388 | running = sl; | 390 | running = sl; |
389 | start_process (sl); | 391 | start_process (sl); |
390 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP); | 392 | if (NULL != client) |
393 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP); | ||
391 | } | 394 | } |
392 | 395 | ||
393 | 396 | ||
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c index 63f8cbd67..e8ef5cd09 100644 --- a/src/datacache/plugin_datacache_sqlite.c +++ b/src/datacache/plugin_datacache_sqlite.c | |||
@@ -405,7 +405,10 @@ libgnunet_plugin_datacache_sqlite_done (void *cls) | |||
405 | struct GNUNET_DATACACHE_PluginFunctions *api = cls; | 405 | struct GNUNET_DATACACHE_PluginFunctions *api = cls; |
406 | struct Plugin *plugin = api->cls; | 406 | struct Plugin *plugin = api->cls; |
407 | 407 | ||
408 | UNLINK (plugin->fn); | 408 | if (0 != UNLINK (plugin->fn)) |
409 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
410 | "unlink", | ||
411 | plugin->fn); | ||
409 | GNUNET_free (plugin->fn); | 412 | GNUNET_free (plugin->fn); |
410 | sqlite3_close (plugin->dbh); | 413 | sqlite3_close (plugin->dbh); |
411 | GNUNET_free (plugin); | 414 | GNUNET_free (plugin); |
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c index 26e894bf4..977f1398e 100644 --- a/src/datastore/gnunet-service-datastore.c +++ b/src/datastore/gnunet-service-datastore.c | |||
@@ -527,7 +527,8 @@ transmit_status (struct GNUNET_SERVER_Client *client, | |||
527 | sm->header.size = htons(sizeof(struct StatusMessage) + slen); | 527 | sm->header.size = htons(sizeof(struct StatusMessage) + slen); |
528 | sm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_STATUS); | 528 | sm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_STATUS); |
529 | sm->status = htonl(code); | 529 | sm->status = htonl(code); |
530 | memcpy (&sm[1], msg, slen); | 530 | if (slen > 0) |
531 | memcpy (&sm[1], msg, slen); | ||
531 | transmit (client, &sm->header, NULL, NULL, GNUNET_YES); | 532 | transmit (client, &sm->header, NULL, NULL, GNUNET_YES); |
532 | } | 533 | } |
533 | 534 | ||
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am new file mode 100644 index 000000000..03c40a5da --- /dev/null +++ b/src/fs/Makefile.am | |||
@@ -0,0 +1,61 @@ | |||
1 | INCLUDES = -I$(top_srcdir)/src/include | ||
2 | |||
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage -O0 | ||
9 | XLIB = -lgcov | ||
10 | endif | ||
11 | |||
12 | |||
13 | lib_LTLIBRARIES = libgnunetfs.la | ||
14 | |||
15 | libgnunetfs_la_SOURCES = \ | ||
16 | fs_getopt.c \ | ||
17 | fs_uri.c | ||
18 | libgnunetfs_la_LIBADD = \ | ||
19 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
20 | $(GN_LIBINTL) $(XLIB) | ||
21 | libgnunetfs_la_LDFLAGS = \ | ||
22 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
23 | -version-info 0:0:0 | ||
24 | |||
25 | |||
26 | #bin_PROGRAMS = \ | ||
27 | # gnunet-directory \ | ||
28 | # gnunet-download \ | ||
29 | # gnunet-pseudonym \ | ||
30 | # gnunet-search \ | ||
31 | # gnunet-share \ | ||
32 | # gnunet-unindex | ||
33 | |||
34 | #gnunet_directory_SOURCES = \ | ||
35 | # gnunet-directory.c | ||
36 | #gnunet_directory_LDADD = \ | ||
37 | # $(top_builddir)/src/fs/libgnunetfs.la \ | ||
38 | # $(top_builddir)/src/util/libgnunetutil.la \ | ||
39 | # $(GN_LIBINTL) | ||
40 | |||
41 | |||
42 | check_PROGRAMS = \ | ||
43 | test_fs_getopt \ | ||
44 | test_fs_uri | ||
45 | |||
46 | TESTS = $(check_PROGRAMS) | ||
47 | |||
48 | test_fs_uri_SOURCES = \ | ||
49 | test_fs_uri.c | ||
50 | test_fs_LDADD = \ | ||
51 | $(top_builddir)/src/fs/libgnunetfs.la \ | ||
52 | $(top_builddir)/src/util/libgnunetutil.la | ||
53 | |||
54 | test_fs_getopt_SOURCES = \ | ||
55 | test_fs_getopt.c | ||
56 | test_fs_LDADD = \ | ||
57 | $(top_builddir)/src/fs/libgnunetfs.la \ | ||
58 | $(top_builddir)/src/util/libgnunetutil.la | ||
59 | |||
60 | #EXTRA_DIST = \ | ||
61 | # test_fs_data.conf | ||
diff --git a/src/fs/fs.h b/src/fs/fs.h new file mode 100644 index 000000000..c6d5d38cc --- /dev/null +++ b/src/fs/fs.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file fs/fs.h | ||
23 | * @brief definitions for the entire fs module | ||
24 | * @author Igor Wronsky, Christian Grothoff | ||
25 | */ | ||
26 | #ifndef FS_H | ||
27 | #define FS_H | ||
28 | |||
29 | /** | ||
30 | * @brief content hash key | ||
31 | */ | ||
32 | struct ContentHashKey | ||
33 | { | ||
34 | GNUNET_HashCode key; | ||
35 | GNUNET_HashCode query; | ||
36 | }; | ||
37 | |||
38 | |||
39 | /** | ||
40 | * @brief complete information needed | ||
41 | * to download a file. | ||
42 | */ | ||
43 | struct FileIdentifier | ||
44 | { | ||
45 | |||
46 | /** | ||
47 | * Total size of the file in bytes. (network byte order (!)) | ||
48 | */ | ||
49 | unsigned long long file_length; | ||
50 | |||
51 | /** | ||
52 | * Query and key of the top GNUNET_EC_IBlock. | ||
53 | */ | ||
54 | struct ContentHashKey chk; | ||
55 | |||
56 | }; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Information about a file and its location | ||
61 | * (peer claiming to share the file). | ||
62 | */ | ||
63 | struct Location | ||
64 | { | ||
65 | /** | ||
66 | * Information about the shared file. | ||
67 | */ | ||
68 | struct FileIdentifier fi; | ||
69 | |||
70 | /** | ||
71 | * Identity of the peer sharing the file. | ||
72 | */ | ||
73 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded peer; | ||
74 | |||
75 | /** | ||
76 | * Time when the HELLO *and* this location URI | ||
77 | * expire (they expire together!). | ||
78 | */ | ||
79 | struct GNUNET_TIME_Absolute expirationTime; | ||
80 | |||
81 | /** | ||
82 | * RSA signature over the GNUNET_EC_FileIdentifier, | ||
83 | * GNUNET_hash of the peer and expiration time. | ||
84 | */ | ||
85 | struct GNUNET_CRYPTO_RsaSignature contentSignature; | ||
86 | |||
87 | }; | ||
88 | |||
89 | enum uri_types | ||
90 | { chk, sks, ksk, loc }; | ||
91 | |||
92 | /** | ||
93 | * A Universal Resource Identifier (URI), opaque. | ||
94 | */ | ||
95 | struct GNUNET_FS_Uri | ||
96 | { | ||
97 | enum uri_types type; | ||
98 | union | ||
99 | { | ||
100 | struct | ||
101 | { | ||
102 | /** | ||
103 | * Keywords start with a '+' if they are | ||
104 | * mandatory (in which case the '+' is NOT | ||
105 | * part of the keyword) and with a | ||
106 | * simple space if they are optional | ||
107 | * (in which case the space is ALSO not | ||
108 | * part of the actual keyword). | ||
109 | * | ||
110 | * Double-quotes to protect spaces and | ||
111 | * %-encoding are NOT used internally | ||
112 | * (only in URI-strings). | ||
113 | */ | ||
114 | char **keywords; | ||
115 | unsigned int keywordCount; | ||
116 | } ksk; | ||
117 | struct | ||
118 | { | ||
119 | GNUNET_HashCode namespace; | ||
120 | char *identifier; | ||
121 | } sks; | ||
122 | struct FileIdentifier chk; | ||
123 | struct Location loc; | ||
124 | } data; | ||
125 | |||
126 | }; | ||
127 | |||
128 | #endif | ||
diff --git a/src/fs/fs_getopt.c b/src/fs/fs_getopt.c new file mode 100644 index 000000000..8afe49852 --- /dev/null +++ b/src/fs/fs_getopt.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file fs/fs_getopt.c | ||
23 | * @brief helper functions for command-line argument processing | ||
24 | * @author Igor Wronsky, Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_fs_lib.h" | ||
28 | |||
29 | |||
30 | |||
31 | /* ******************** command-line option parsing API *********************** */ | ||
32 | |||
33 | /** | ||
34 | * Command-line option parser function that allows the user | ||
35 | * to specify one or more '-k' options with keywords. Each | ||
36 | * specified keyword will be added to the URI. A pointer to | ||
37 | * the URI must be passed as the "scls" argument. | ||
38 | * | ||
39 | * @param ctx command line processor context | ||
40 | * @param scls must be of type "struct GNUNET_FS_Uri **" | ||
41 | * @param option name of the option (typically 'k') | ||
42 | * @param value command line argument given | ||
43 | * @return GNUNET_OK on success | ||
44 | */ | ||
45 | int | ||
46 | GNUNET_FS_getopt_configure_set_keywords (GNUNET_GETOPT_CommandLineProcessorContext* ctx, | ||
47 | void *scls, | ||
48 | const char *option, | ||
49 | const char *value) | ||
50 | { | ||
51 | struct GNUNET_FS_Uri **uri = scls; | ||
52 | struct GNUNET_FS_Uri *u = *uri; | ||
53 | char *val; | ||
54 | size_t slen; | ||
55 | |||
56 | if (u == NULL) | ||
57 | { | ||
58 | u = GNUNET_malloc (sizeof (struct GNUNET_ECRS_URI)); | ||
59 | *uri = u; | ||
60 | u->type = ksk; | ||
61 | u->data.ksk.keywordCount = 0; | ||
62 | u->data.ksk.keywords = NULL; | ||
63 | } | ||
64 | else | ||
65 | { | ||
66 | GNUNET_assert (u->type == ksk); | ||
67 | } | ||
68 | slen = strlen (value); | ||
69 | if (slen == 0) | ||
70 | return GNUNET_SYSERR; /* cannot be empty */ | ||
71 | if (value[0] == '+') | ||
72 | { | ||
73 | /* simply preserve the "mandatory" flag */ | ||
74 | if (slen < 2) | ||
75 | return GNUNET_SYSERR; /* empty keywords not allowed */ | ||
76 | if ((value[1] == '"') && (slen > 3) && (value[slen - 1] == '"')) | ||
77 | { | ||
78 | /* remove the quotes, keep the '+' */ | ||
79 | val = GNUNET_malloc (slen - 1); | ||
80 | val[0] = '+'; | ||
81 | memcpy (&val[1], &value[2], slen - 3); | ||
82 | val[slen - 2] = '\0'; | ||
83 | } | ||
84 | else | ||
85 | { | ||
86 | /* no quotes, just keep the '+' */ | ||
87 | val = GNUNET_strdup (value); | ||
88 | } | ||
89 | } | ||
90 | else | ||
91 | { | ||
92 | if ((value[0] == '"') && (slen > 2) && (value[slen - 1] == '"')) | ||
93 | { | ||
94 | /* remove the quotes, add a space */ | ||
95 | val = GNUNET_malloc (slen); | ||
96 | val[0] = ' '; | ||
97 | memcpy (&val[1], &value[1], slen - 2); | ||
98 | val[slen - 1] = '\0'; | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | /* add a space to indicate "not mandatory" */ | ||
103 | val = GNUNET_malloc (slen + 2); | ||
104 | strcpy (val, " "); | ||
105 | strcat (val, value); | ||
106 | } | ||
107 | } | ||
108 | GNUNET_array_grow (u->data.ksk.keywords, | ||
109 | u->data.ksk.keywordCount, u->data.ksk.keywordCount + 1); | ||
110 | u->data.ksk.keywords[u->data.ksk.keywordCount - 1] = val; | ||
111 | return GNUNET_OK; | ||
112 | } | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Command-line option parser function that allows the user to specify | ||
117 | * one or more '-m' options with metadata. Each specified entry of | ||
118 | * the form "type=value" will be added to the metadata. A pointer to | ||
119 | * the metadata must be passed as the "scls" argument. | ||
120 | * | ||
121 | * @param ctx command line processor context | ||
122 | * @param scls must be of type "struct GNUNET_MetaData **" | ||
123 | * @param option name of the option (typically 'k') | ||
124 | * @param value command line argument given | ||
125 | * @return GNUNET_OK on success | ||
126 | */ | ||
127 | int | ||
128 | GNUNET_FS_getopt_configure_set_metadata (GNUNET_GETOPT_CommandLineProcessorContext* ctx, | ||
129 | void *scls, | ||
130 | const char *option, | ||
131 | const char *value) | ||
132 | |||
133 | { | ||
134 | struct GNUNET_CONTAINER_MetaData **mm = scls; | ||
135 | EXTRACTOR_KeywordType type; | ||
136 | const char *typename; | ||
137 | const char *typename_i18n; | ||
138 | struct GNUNET_CONTAINER_MetaData *meta; | ||
139 | char *tmp; | ||
140 | |||
141 | meta = *mm; | ||
142 | if (meta == NULL) | ||
143 | { | ||
144 | meta = GNUNET_CONTAINER_meta_data_create (); | ||
145 | *mm = meta; | ||
146 | } | ||
147 | |||
148 | tmp = GNUNET_STRINGS_to_utf8 (NULL, value, strlen (value), | ||
149 | #if ENABLE_NLS | ||
150 | nl_langinfo (CODESET) | ||
151 | #else | ||
152 | "utf-8" | ||
153 | #endif | ||
154 | ); | ||
155 | type = EXTRACTOR_getHighestKeywordTypeNumber (); | ||
156 | while (type > 0) | ||
157 | { | ||
158 | type--; | ||
159 | typename = EXTRACTOR_getKeywordTypeAsString (type); | ||
160 | typename_i18n = dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, typename); | ||
161 | if ((strlen (tmp) >= strlen (typename) + 1) && | ||
162 | (tmp[strlen (typename)] == ':') && | ||
163 | (0 == strncmp (typename, tmp, strlen (typename)))) | ||
164 | { | ||
165 | GNUNET_CONTAINER_meta_data_insert (meta, type, &tmp[strlen (typename) + 1]); | ||
166 | GNUNET_free (tmp); | ||
167 | tmp = NULL; | ||
168 | break; | ||
169 | } | ||
170 | if ((strlen (tmp) >= strlen (typename_i18n) + 1) && | ||
171 | (tmp[strlen (typename_i18n)] == ':') && | ||
172 | (0 == strncmp (typename_i18n, tmp, strlen (typename_i18n)))) | ||
173 | { | ||
174 | GNUNET_CONTAINER_meta_data_insert (meta, type, | ||
175 | &tmp[strlen (typename_i18n) + 1]); | ||
176 | GNUNET_free (tmp); | ||
177 | tmp = NULL; | ||
178 | break; | ||
179 | } | ||
180 | } | ||
181 | if (tmp != NULL) | ||
182 | { | ||
183 | GNUNET_CONTAINER_meta_data_insert (meta, EXTRACTOR_UNKNOWN, tmp); | ||
184 | GNUNET_free (tmp); | ||
185 | printf (_ | ||
186 | ("Unknown metadata type in metadata option `%s'. Using metadata type `unknown' instead.\n"), | ||
187 | value); | ||
188 | } | ||
189 | return GNUNET_OK; | ||
190 | } | ||
191 | |||
192 | /* end of fs_getopt.c */ | ||
diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c new file mode 100644 index 000000000..863ab475d --- /dev/null +++ b/src/fs/fs_uri.c | |||
@@ -0,0 +1,1317 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file fs/fs_uri.c | ||
23 | * @brief Parses and produces uri strings. | ||
24 | * @author Igor Wronsky, Christian Grothoff | ||
25 | * | ||
26 | * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER". | ||
27 | * The specific structure of "IDENTIFIER" depends on the module and | ||
28 | * maybe differenciated into additional subcategories if applicable. | ||
29 | * This module only deals with ecrs identifiers (MODULE = "ecrs"). | ||
30 | * <p> | ||
31 | * | ||
32 | * This module only parses URIs for the AFS module. The ECRS URIs fall | ||
33 | * into four categories, "chk", "sks", "ksk" and "loc". The first three | ||
34 | * categories were named in analogy (!) to Freenet, but they do NOT | ||
35 | * work in exactly the same way. They are very similar from the user's | ||
36 | * point of view (unique file identifier, subspace, keyword), but the | ||
37 | * implementation is rather different in pretty much every detail. | ||
38 | * The concrete URI formats are: | ||
39 | * | ||
40 | * <ul><li> | ||
41 | * | ||
42 | * First, there are URIs that identify a file. They have the format | ||
43 | * "gnunet://ecrs/chk/HEX1.HEX2.SIZE". These URIs can be used to | ||
44 | * download the file. The description, filename, mime-type and other | ||
45 | * meta-data is NOT part of the file-URI since a URI uniquely | ||
46 | * identifies a resource (and the contents of the file would be the | ||
47 | * same even if it had a different description). | ||
48 | * | ||
49 | * </li><li> | ||
50 | * | ||
51 | * The second category identifies entries in a namespace. The format | ||
52 | * is "gnunet://ecrs/sks/NAMESPACE/IDENTIFIER" where the namespace | ||
53 | * should be given in HEX. Applications may allow using a nickname | ||
54 | * for the namespace if the nickname is not ambiguous. The identifier | ||
55 | * can be either an ASCII sequence or a HEX-encoding. If the | ||
56 | * identifier is in ASCII but the format is ambiguous and could denote | ||
57 | * a HEX-string a "/" is appended to indicate ASCII encoding. | ||
58 | * | ||
59 | * </li> <li> | ||
60 | * | ||
61 | * The third category identifies ordinary searches. The format is | ||
62 | * "gnunet://ecrs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax | ||
63 | * it is possible to encode searches with the boolean "AND" operator. | ||
64 | * "+" is used since it indicates a commutative 'and' operation and | ||
65 | * is unlikely to be used in a keyword by itself. | ||
66 | * | ||
67 | * </li><li> | ||
68 | * | ||
69 | * The last category identifies a datum on a specific machine. The | ||
70 | * format is "gnunet://ecrs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is | ||
71 | * the BinName of the public key of the peer storing the datum. The | ||
72 | * signature (SIG) certifies that this peer has this content. | ||
73 | * HEX1, HEX2 and SIZE correspond to a 'chk' URI. | ||
74 | * | ||
75 | * </li></ul> | ||
76 | * | ||
77 | * The encoding for hexadecimal values is defined in the hashing.c | ||
78 | * module in the gnunetutil library and discussed there. | ||
79 | * <p> | ||
80 | */ | ||
81 | #include "platform.h" | ||
82 | #include "gnunet_fs_lib.h" | ||
83 | #include "fs.h" | ||
84 | |||
85 | |||
86 | /** | ||
87 | * Get a unique key from a URI. This is for putting URIs | ||
88 | * into HashMaps. The key may change between FS implementations. | ||
89 | * | ||
90 | * @param uri uri to convert to a unique key | ||
91 | * @param key wherer to store the unique key | ||
92 | */ | ||
93 | void | ||
94 | GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, | ||
95 | GNUNET_HashCode * key) | ||
96 | { | ||
97 | switch (uri->type) | ||
98 | { | ||
99 | case chk: | ||
100 | *key = uri->data.fi.chk.query; | ||
101 | return; | ||
102 | case sks: | ||
103 | GNUNET_hash (uri->data.sks.identifier, | ||
104 | strlen (uri->data.sks.identifier), key); | ||
105 | break; | ||
106 | case ksk: | ||
107 | if (uri->data.ksk.keywordCount > 0) | ||
108 | GNUNET_hash (uri->data.ksk.keywords[0], | ||
109 | strlen (uri->data.ksk.keywords[0]), key); | ||
110 | break; | ||
111 | case loc: | ||
112 | GNUNET_hash (&uri->data.loc.fi, | ||
113 | sizeof (GNUNET_EC_FileIdentifier) + | ||
114 | sizeof (GNUNET_RSA_PublicKey), key); | ||
115 | break; | ||
116 | default: | ||
117 | memset (key, 0, sizeof (GNUNET_HashCode)); | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Convert a URI to a UTF-8 String. | ||
125 | * | ||
126 | * @param uri uri to convert to a string | ||
127 | * @return the UTF-8 string | ||
128 | */ | ||
129 | char * | ||
130 | GNUNET_FS_uri_to_string (const struct GNUNET_FS_Uri *uri); | ||
131 | |||
132 | |||
133 | /** | ||
134 | * Convert keyword URI to a human readable format | ||
135 | * (i.e. the search query that was used in the first place) | ||
136 | * | ||
137 | * @param uri ksk uri to convert to a string | ||
138 | * @return string with the keywords | ||
139 | */ | ||
140 | char * | ||
141 | GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri); | ||
142 | |||
143 | /** | ||
144 | * Convert a UTF-8 String to a URI. | ||
145 | * | ||
146 | * @param uri string to parse | ||
147 | * @param emsg where to store the parser error message (if any) | ||
148 | * @return NULL on error | ||
149 | */ | ||
150 | struct GNUNET_FS_Uri * | ||
151 | GNUNET_FS_uri_parse (const char *uri, | ||
152 | char **emsg); | ||
153 | |||
154 | /** | ||
155 | * Free URI. | ||
156 | * | ||
157 | * @param uri uri to free | ||
158 | */ | ||
159 | void | ||
160 | GNUNET_FS_uri_destroy (struct GNUNET_FS_Uri *uri) | ||
161 | { | ||
162 | unsigned int i; | ||
163 | |||
164 | GNUNET_assert (uri != NULL); | ||
165 | switch (uri->type) | ||
166 | { | ||
167 | case ksk: | ||
168 | for (i = 0; i < uri->data.ksk.keywordCount; i++) | ||
169 | GNUNET_free (uri->data.ksk.keywords[i]); | ||
170 | GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, | ||
171 | 0); | ||
172 | break; | ||
173 | case sks: | ||
174 | GNUNET_free (uri->data.sks.identifier); | ||
175 | break; | ||
176 | case loc: | ||
177 | break; | ||
178 | default: | ||
179 | /* do nothing */ | ||
180 | break; | ||
181 | } | ||
182 | GNUNET_free (uri); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * How many keywords are ANDed in this keyword URI? | ||
187 | * | ||
188 | * @param uri ksk uri to get the number of keywords from | ||
189 | * @return 0 if this is not a keyword URI | ||
190 | */ | ||
191 | unsigned int | ||
192 | GNUNET_FS_uri_ksk_get_keyword_count (const struct GNUNET_FS_Uri *uri) | ||
193 | { | ||
194 | if (uri->type != ksk) | ||
195 | return 0; | ||
196 | return uri->data.ksk.keywordCount; | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Iterate over all keywords in this keyword URI. | ||
202 | * | ||
203 | * @param uri ksk uri to get the keywords from | ||
204 | * @param iterator function to call on each keyword | ||
205 | * @param iterator_cls closure for iterator | ||
206 | * @return -1 if this is not a keyword URI, otherwise number of | ||
207 | * keywords iterated over until iterator aborted | ||
208 | */ | ||
209 | int | ||
210 | GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri, | ||
211 | GNUNET_FS_KeywordIterator iterator, | ||
212 | void *iterator_cls) | ||
213 | { | ||
214 | unsigned int i; | ||
215 | char *keyword; | ||
216 | |||
217 | if (uri->type != ksk) | ||
218 | return -1; | ||
219 | if (iterator == NULL) | ||
220 | return uri->data.ksk.keywordCount; | ||
221 | for (i = 0; i < uri->data.ksk.keywordCount; i++) | ||
222 | { | ||
223 | keyword = uri->data.ksk.keywords[i]; | ||
224 | /* first character of keyword indicates | ||
225 | if it is mandatory or not */ | ||
226 | if (GNUNET_OK != iterator (&keyword[1], keyword[0] == '+', cls)) | ||
227 | return i; | ||
228 | } | ||
229 | return i; | ||
230 | } | ||
231 | |||
232 | |||
233 | /** | ||
234 | * Obtain the identity of the peer offering the data | ||
235 | * | ||
236 | * @param uri the location URI to inspect | ||
237 | * @param peer where to store the identify of the peer (presumably) offering the content | ||
238 | * @return GNUNET_SYSERR if this is not a location URI, otherwise GNUNET_OK | ||
239 | */ | ||
240 | int | ||
241 | GNUNET_FS_uri_loc_get_peer_identity (const struct GNUNET_FS_Uri *uri, | ||
242 | struct GNUNET_PeerIdentity * peer) | ||
243 | { | ||
244 | if (uri->type != loc) | ||
245 | return GNUNET_SYSERR; | ||
246 | GNUNET_hash (&uri->data.loc.peer, sizeof (GNUNET_RSA_PublicKey), | ||
247 | &peer->hashPubKey); | ||
248 | return GNUNET_OK; | ||
249 | } | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Obtain the URI of the content itself. | ||
254 | * | ||
255 | * @param uri location URI to get the content URI from | ||
256 | * @return NULL if argument is not a location URI | ||
257 | */ | ||
258 | struct GNUNET_FS_Uri * | ||
259 | GNUNET_FS_uri_loc_get_uri (const struct GNUNET_FS_Uri *uri) | ||
260 | { | ||
261 | struct GNUNET_ECRS_Uri *ret; | ||
262 | |||
263 | if (uri->type != loc) | ||
264 | return NULL; | ||
265 | ret = GNUNET_malloc (sizeof (struct GNUNET_ECRS_Uri)); | ||
266 | ret->type = chk; | ||
267 | ret->data.chk = uri->data.loc.fi; | ||
268 | return ret; | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Construct a location URI (this peer will be used for the location). | ||
274 | * | ||
275 | * @param baseURI content offered by the sender | ||
276 | * @param cfg configuration information (used to find our hostkey) | ||
277 | * @param expiration_time how long will the content be offered? | ||
278 | * @return the location URI, NULL on error | ||
279 | */ | ||
280 | struct GNUNET_FS_Uri * | ||
281 | GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri, | ||
282 | struct GNUNET_CONFIGURATION_Handle *cfg, | ||
283 | struct GNUNET_TIME_Absolute expiration_time); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Canonicalize keyword URI. Performs operations such | ||
288 | * as decapitalization and removal of certain characters. | ||
289 | * (useful for search). | ||
290 | * | ||
291 | * @param uri the URI to canonicalize | ||
292 | * @return canonicalized version of the URI, NULL on error | ||
293 | */ | ||
294 | struct GNUNET_FS_Uri * | ||
295 | GNUNET_FS_uri_ksk_canonicalize (const struct GNUNET_FS_Uri *uri); | ||
296 | |||
297 | |||
298 | /** | ||
299 | * Merge the sets of keywords from two KSK URIs. | ||
300 | * (useful for merging the canonicalized keywords with | ||
301 | * the original keywords for sharing). | ||
302 | * | ||
303 | * @param u1 first uri | ||
304 | * @param u2 second uri | ||
305 | * @return merged URI, NULL on error | ||
306 | */ | ||
307 | struct GNUNET_FS_Uri * | ||
308 | GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1, | ||
309 | const struct GNUNET_FS_Uri *u2); | ||
310 | |||
311 | |||
312 | /** | ||
313 | * Duplicate URI. | ||
314 | * | ||
315 | * @param uri the URI to duplicate | ||
316 | * @return copy of the URI | ||
317 | */ | ||
318 | struct GNUNET_FS_Uri * | ||
319 | GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri) | ||
320 | { | ||
321 | struct GNUNET_ECRS_URI *ret; | ||
322 | unsigned int i; | ||
323 | |||
324 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); | ||
325 | memcpy (ret, uri, sizeof (struct GNUNET_FS_Uri)); | ||
326 | switch (ret->type) | ||
327 | { | ||
328 | case ksk: | ||
329 | if (ret->data.ksk.keywordCount > 0) | ||
330 | { | ||
331 | ret->data.ksk.keywords | ||
332 | = GNUNET_malloc (ret->data.ksk.keywordCount * sizeof (char *)); | ||
333 | for (i = 0; i < ret->data.ksk.keywordCount; i++) | ||
334 | ret->data.ksk.keywords[i] = | ||
335 | GNUNET_strdup (uri->data.ksk.keywords[i]); | ||
336 | } | ||
337 | else | ||
338 | ret->data.ksk.keywords = NULL; /* just to be sure */ | ||
339 | break; | ||
340 | case sks: | ||
341 | ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier); | ||
342 | break; | ||
343 | case loc: | ||
344 | break; | ||
345 | default: | ||
346 | break; | ||
347 | } | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Create an FS URI from a single user-supplied string of keywords. | ||
354 | * The string is broken up at spaces into individual keywords. | ||
355 | * Keywords that start with "+" are mandatory. Double-quotes can | ||
356 | * be used to prevent breaking up strings at spaces (and also | ||
357 | * to specify non-mandatory keywords starting with "+"). | ||
358 | * | ||
359 | * Keywords must contain a balanced number of double quotes and | ||
360 | * double quotes can not be used in the actual keywords (for | ||
361 | * example, the string '""foo bar""' will be turned into two | ||
362 | * "OR"ed keywords 'foo' and 'bar', not into '"foo bar"'. | ||
363 | * | ||
364 | * @param keywords the keyword string | ||
365 | * @return an FS URI for the given keywords, NULL | ||
366 | * if keywords is not legal (i.e. empty). | ||
367 | */ | ||
368 | struct GNUNET_FS_Uri * | ||
369 | GNUNET_FS_uri_ksk_create (const char *keywords); | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Create an FS URI from a user-supplied command line of keywords. | ||
374 | * Arguments should start with "+" to indicate mandatory | ||
375 | * keywords. | ||
376 | * | ||
377 | * @param argc number of keywords | ||
378 | * @param argv keywords (double quotes are not required for | ||
379 | * keywords containing spaces; however, double | ||
380 | * quotes are required for keywords starting with | ||
381 | * "+"); there is no mechanism for having double | ||
382 | * quotes in the actual keywords (if the user | ||
383 | * did specifically specify double quotes, the | ||
384 | * caller should convert each double quote | ||
385 | * into two single quotes). | ||
386 | * @return an FS URI for the given keywords, NULL | ||
387 | * if keywords is not legal (i.e. empty). | ||
388 | */ | ||
389 | struct GNUNET_FS_Uri * | ||
390 | GNUNET_FS_uri_ksk_create_from_args (unsigned int argc, | ||
391 | const char **argv); | ||
392 | |||
393 | |||
394 | /** | ||
395 | * Test if two URIs are equal. | ||
396 | * | ||
397 | * @param u1 one of the URIs | ||
398 | * @param u2 the other URI | ||
399 | * @return GNUNET_YES if the URIs are equal | ||
400 | */ | ||
401 | int | ||
402 | GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1, | ||
403 | const struct GNUNET_FS_Uri *u2) | ||
404 | { | ||
405 | int ret; | ||
406 | unsigned int i; | ||
407 | unsigned int j; | ||
408 | |||
409 | GNUNET_assert (uri1 != NULL); | ||
410 | GNUNET_assert (uri2 != NULL); | ||
411 | if (uri1->type != uri2->type) | ||
412 | return GNUNET_NO; | ||
413 | switch (uri1->type) | ||
414 | { | ||
415 | case chk: | ||
416 | if (0 == memcmp (&uri1->data.chk, | ||
417 | &uri2->data.chk, | ||
418 | sizeof (struct FileIdentifier))) | ||
419 | return GNUNET_YES; | ||
420 | return GNUNET_NO; | ||
421 | case sks: | ||
422 | if ((0 == memcmp (&uri1->data.sks.namespace, | ||
423 | &uri2->data.sks.namespace, | ||
424 | sizeof (GNUNET_HashCode))) && | ||
425 | (0 == strcmp (uri1->data.sks.identifier, | ||
426 | uri2->data.sks.identifier))) | ||
427 | |||
428 | return GNUNET_YES; | ||
429 | return GNUNET_NO; | ||
430 | case ksk: | ||
431 | if (uri1->data.ksk.keywordCount != uri2->data.ksk.keywordCount) | ||
432 | return GNUNET_NO; | ||
433 | for (i = 0; i < uri1->data.ksk.keywordCount; i++) | ||
434 | { | ||
435 | ret = GNUNET_NO; | ||
436 | for (j = 0; j < uri2->data.ksk.keywordCount; j++) | ||
437 | { | ||
438 | if (0 == strcmp (uri1->data.ksk.keywords[i], | ||
439 | uri2->data.ksk.keywords[j])) | ||
440 | { | ||
441 | ret = GNUNET_YES; | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | if (ret == GNUNET_NO) | ||
446 | return GNUNET_NO; | ||
447 | } | ||
448 | return GNUNET_YES; | ||
449 | case loc: | ||
450 | if (memcmp (&uri1->data.loc, | ||
451 | &uri2->data.loc, | ||
452 | sizeof (struct FileIdentifier) + | ||
453 | sizeof (GNUNET_RSA_PublicKey) + | ||
454 | sizeof (struct GNUNET_TIME_Absolute) + | ||
455 | sizeof (unsigned short) + sizeof (unsigned short)) != 0) | ||
456 | return GNUNET_NO; | ||
457 | return GNUNET_YES; | ||
458 | default: | ||
459 | return GNUNET_NO; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
465 | * Is this a namespace URI? | ||
466 | * | ||
467 | * @param uri the uri to check | ||
468 | * @return GNUNET_YES if this is an SKS uri | ||
469 | */ | ||
470 | int | ||
471 | GNUNET_FS_uri_test_sks (const struct GNUNET_FS_Uri *uri) | ||
472 | { | ||
473 | return uri->type == sks; | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | ||
478 | * Get the ID of a namespace from the given | ||
479 | * namespace URI. | ||
480 | * | ||
481 | * @param uri the uri to get the namespace ID from | ||
482 | * @param nsid where to store the ID of the namespace | ||
483 | * @return GNUNET_OK on success | ||
484 | */ | ||
485 | int | ||
486 | GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri, | ||
487 | GNUNET_HashCode * nsid) | ||
488 | { | ||
489 | if (! GNUNET_FS_uri_test_sks (uri)) | ||
490 | { | ||
491 | GNUNET_break (0); | ||
492 | return GNUNET_SYSERR; | ||
493 | } | ||
494 | *id = uri->data.sks.namespace; | ||
495 | return GNUNET_OK; | ||
496 | } | ||
497 | |||
498 | |||
499 | /** | ||
500 | * Get the content identifier of an SKS URI. | ||
501 | * | ||
502 | * @param uri the sks uri | ||
503 | * @return NULL on error (not a valid SKS URI) | ||
504 | */ | ||
505 | char * | ||
506 | GNUNET_FS_uri_sks_get_content_id (const struct GNUNET_FS_Uri *uri) | ||
507 | { | ||
508 | if (!GNUNET_FS_uri_test_sks (uri)) | ||
509 | { | ||
510 | GNUNET_break (0); | ||
511 | return NULL; | ||
512 | } | ||
513 | return GNUNET_strdup (uri->data.sks.identifier); | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
518 | * Convert namespace URI to a human readable format | ||
519 | * (using the namespace description, if available). | ||
520 | * | ||
521 | * @param cfg configuration to use | ||
522 | * @param uri SKS uri to convert | ||
523 | * @return NULL on error (not an SKS URI) | ||
524 | */ | ||
525 | char * | ||
526 | GNUNET_FS_uri_sks_to_string_fancy (struct GNUNET_CONFIGURATION_Handle *cfg, | ||
527 | const struct GNUNET_FS_Uri *uri); | ||
528 | |||
529 | |||
530 | /** | ||
531 | * Is this a keyword URI? | ||
532 | * | ||
533 | * @param uri the uri | ||
534 | * @return GNUNET_YES if this is a KSK uri | ||
535 | */ | ||
536 | int | ||
537 | GNUNET_FS_uri_test_ksk (const struct GNUNET_FS_Uri *uri) | ||
538 | { | ||
539 | #if EXTRA_CHECKS | ||
540 | unsigned int i; | ||
541 | |||
542 | if (uri->type == ksk) | ||
543 | { | ||
544 | for (i = uri->data.ksk.keywordCount - 1; i >= 0; i--) | ||
545 | GNUNET_assert (uri->data.ksk.keywords[i] != NULL); | ||
546 | } | ||
547 | #endif | ||
548 | return uri->type == ksk; | ||
549 | } | ||
550 | |||
551 | |||
552 | /** | ||
553 | * Is this a file (or directory) URI? | ||
554 | * | ||
555 | * @param uri the uri to check | ||
556 | * @return GNUNET_YES if this is a CHK uri | ||
557 | */ | ||
558 | int | ||
559 | GNUNET_FS_uri_test_chk (const struct GNUNET_FS_Uri *uri) | ||
560 | { | ||
561 | return uri->type == chk; | ||
562 | } | ||
563 | |||
564 | |||
565 | /** | ||
566 | * What is the size of the file that this URI | ||
567 | * refers to? | ||
568 | * | ||
569 | * @param uri the CHK URI to inspect | ||
570 | * @return size of the file as specified in the CHK URI | ||
571 | */ | ||
572 | uint64_t | ||
573 | GNUNET_FS_uri_chk_get_file_size (const struct GNUNET_FS_Uri *uri) | ||
574 | { | ||
575 | switch (uri->type) | ||
576 | { | ||
577 | case chk: | ||
578 | return GNUNET_ntohll (uri->data.chk.file_length); | ||
579 | case loc: | ||
580 | return GNUNET_ntohll (uri->data.loc.fi.file_length); | ||
581 | default: | ||
582 | GNUNET_assert (0); | ||
583 | } | ||
584 | return 0; /* unreachable */ | ||
585 | } | ||
586 | |||
587 | |||
588 | /** | ||
589 | * Is this a location URI? | ||
590 | * | ||
591 | * @param uri the uri to check | ||
592 | * @return GNUNET_YES if this is a LOC uri | ||
593 | */ | ||
594 | int | ||
595 | GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri) | ||
596 | { | ||
597 | return uri->type == loc; | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Function called on each value in the meta data. | ||
603 | * Adds it to the URI. | ||
604 | * | ||
605 | * @param cls URI to update | ||
606 | * @param type type of the meta data | ||
607 | * @param data value of the meta data | ||
608 | * @return GNUNET_OK (always) | ||
609 | */ | ||
610 | static int | ||
611 | gather_uri_data (void *cls, | ||
612 | EXTRACTOR_KeywordType type, | ||
613 | const char *data) | ||
614 | { | ||
615 | struct GNUNET_FS_Uri *uri = cls; | ||
616 | char *nkword; | ||
617 | int j; | ||
618 | |||
619 | for (j = uri->data.ksk.keywordCount - 1; j >= 0; j--) | ||
620 | if (0 == strcmp (&uri->data.ksk.keywords[j][1], data)) | ||
621 | return GNUNET_OK; | ||
622 | nkword = GNUNET_malloc (strlen (data) + 2); | ||
623 | strcpy (nkword, " "); /* not mandatory */ | ||
624 | strcat (nkword, data); | ||
625 | uri->data.ksk.keywords[uri->data.ksk.keywordCount++] = nkword; | ||
626 | return GNUNET_OK; | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Construct a keyword-URI from meta-data (take all entries | ||
632 | * in the meta-data and construct one large keyword URI | ||
633 | * that lists all keywords that can be found in the meta-data). | ||
634 | * @deprecated | ||
635 | */ | ||
636 | struct GNUNET_FS_Uri * | ||
637 | GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_MetaData *md) | ||
638 | { | ||
639 | struct GNUNET_FS_Uri *ret; | ||
640 | |||
641 | if (md == NULL) | ||
642 | return NULL; | ||
643 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); | ||
644 | ret->type = ksk; | ||
645 | ret->data.ksk.keywordCount = 0; | ||
646 | ret->data.ksk.keywords = NULL; | ||
647 | ret->data.ksk.keywords | ||
648 | = GNUNET_malloc (sizeof (char *) * | ||
649 | GNUNET_meta_data_get_contents (md, NULL, NULL)); | ||
650 | GNUNET_meta_data_get_contents (md, &gather_uri_data, ret); | ||
651 | return ret; | ||
652 | |||
653 | } | ||
654 | |||
655 | #if 0 | ||
656 | |||
657 | // old code... | ||
658 | |||
659 | |||
660 | |||
661 | /** | ||
662 | * In URI-encoding, does the given character | ||
663 | * need to be encoded using %-encoding? | ||
664 | */ | ||
665 | static int | ||
666 | needs_percent (char c) | ||
667 | { | ||
668 | return (!((isalnum (c)) || | ||
669 | (c == '-') || (c == '_') || (c == '.') || (c == '~'))); | ||
670 | } | ||
671 | |||
672 | /** | ||
673 | * Generate a keyword URI. | ||
674 | * @return NULL on error (i.e. keywordCount == 0) | ||
675 | */ | ||
676 | static char * | ||
677 | createKeywordURI (char **keywords, unsigned int keywordCount) | ||
678 | { | ||
679 | size_t n; | ||
680 | char *ret; | ||
681 | unsigned int i; | ||
682 | unsigned int j; | ||
683 | unsigned int wpos; | ||
684 | size_t slen; | ||
685 | const char *keyword; | ||
686 | |||
687 | n = | ||
688 | keywordCount + strlen (GNUNET_ECRS_URI_PREFIX) + | ||
689 | strlen (GNUNET_ECRS_SEARCH_INFIX) + 1; | ||
690 | for (i = 0; i < keywordCount; i++) | ||
691 | { | ||
692 | keyword = keywords[i]; | ||
693 | slen = strlen (keyword); | ||
694 | n += slen; | ||
695 | for (j = 0; j < slen; j++) | ||
696 | { | ||
697 | if ((j == 0) && (keyword[j] == ' ')) | ||
698 | { | ||
699 | n--; | ||
700 | continue; /* skip leading space */ | ||
701 | } | ||
702 | if (needs_percent (keyword[j])) | ||
703 | n += 2; /* will use %-encoding */ | ||
704 | } | ||
705 | } | ||
706 | ret = GNUNET_malloc (n); | ||
707 | strcpy (ret, GNUNET_ECRS_URI_PREFIX); | ||
708 | strcat (ret, GNUNET_ECRS_SEARCH_INFIX); | ||
709 | wpos = strlen (ret); | ||
710 | for (i = 0; i < keywordCount; i++) | ||
711 | { | ||
712 | keyword = keywords[i]; | ||
713 | slen = strlen (keyword); | ||
714 | for (j = 0; j < slen; j++) | ||
715 | { | ||
716 | if ((j == 0) && (keyword[j] == ' ')) | ||
717 | continue; /* skip leading space */ | ||
718 | if (needs_percent (keyword[j])) | ||
719 | { | ||
720 | sprintf (&ret[wpos], "%%%02X", keyword[j]); | ||
721 | wpos += 3; | ||
722 | } | ||
723 | else | ||
724 | { | ||
725 | ret[wpos++] = keyword[j]; | ||
726 | } | ||
727 | } | ||
728 | if (i != keywordCount - 1) | ||
729 | ret[wpos++] = '+'; | ||
730 | } | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | /** | ||
735 | * Generate a subspace URI. | ||
736 | */ | ||
737 | static char * | ||
738 | createSubspaceURI (const GNUNET_HashCode * namespace, const char *identifier) | ||
739 | { | ||
740 | size_t n; | ||
741 | char *ret; | ||
742 | GNUNET_EncName ns; | ||
743 | |||
744 | n = | ||
745 | sizeof (GNUNET_EncName) + strlen (GNUNET_ECRS_URI_PREFIX) + | ||
746 | strlen (GNUNET_ECRS_SUBSPACE_INFIX) + 1 + strlen (identifier); | ||
747 | ret = GNUNET_malloc (n); | ||
748 | GNUNET_hash_to_enc (namespace, &ns); | ||
749 | GNUNET_snprintf (ret, n, | ||
750 | "%s%s%s/%s", | ||
751 | GNUNET_ECRS_URI_PREFIX, GNUNET_ECRS_SUBSPACE_INFIX, | ||
752 | (const char *) &ns, identifier); | ||
753 | return ret; | ||
754 | } | ||
755 | |||
756 | /** | ||
757 | * Generate a file URI. | ||
758 | */ | ||
759 | static char * | ||
760 | createFileURI (const GNUNET_EC_FileIdentifier * fi) | ||
761 | { | ||
762 | char *ret; | ||
763 | GNUNET_EncName keyhash; | ||
764 | GNUNET_EncName queryhash; | ||
765 | size_t n; | ||
766 | |||
767 | GNUNET_hash_to_enc (&fi->chk.key, &keyhash); | ||
768 | GNUNET_hash_to_enc (&fi->chk.query, &queryhash); | ||
769 | |||
770 | n = | ||
771 | strlen (GNUNET_ECRS_URI_PREFIX) + 2 * sizeof (GNUNET_EncName) + 8 + 16 + | ||
772 | 32 + strlen (GNUNET_ECRS_FILE_INFIX); | ||
773 | ret = GNUNET_malloc (n); | ||
774 | GNUNET_snprintf (ret, | ||
775 | n, | ||
776 | "%s%s%s.%s.%llu", | ||
777 | GNUNET_ECRS_URI_PREFIX, | ||
778 | GNUNET_ECRS_FILE_INFIX, | ||
779 | (char *) &keyhash, (char *) &queryhash, | ||
780 | GNUNET_ntohll (fi->file_length)); | ||
781 | return ret; | ||
782 | } | ||
783 | |||
784 | #include "bincoder.c" | ||
785 | |||
786 | /** | ||
787 | * Create a (string) location URI from a Location. | ||
788 | */ | ||
789 | static char * | ||
790 | createLocURI (const Location * loc) | ||
791 | { | ||
792 | size_t n; | ||
793 | char *ret; | ||
794 | GNUNET_EncName keyhash; | ||
795 | GNUNET_EncName queryhash; | ||
796 | char *peerId; | ||
797 | char *peerSig; | ||
798 | |||
799 | GNUNET_hash_to_enc (&loc->fi.chk.key, &keyhash); | ||
800 | GNUNET_hash_to_enc (&loc->fi.chk.query, &queryhash); | ||
801 | n = 2148; | ||
802 | peerId = bin2enc (&loc->peer, sizeof (GNUNET_RSA_PublicKey)); | ||
803 | peerSig = bin2enc (&loc->contentSignature, sizeof (GNUNET_RSA_Signature)); | ||
804 | ret = GNUNET_malloc (n); | ||
805 | GNUNET_snprintf (ret, | ||
806 | n, | ||
807 | "%s%s%s.%s.%llu.%s.%s.%u", | ||
808 | GNUNET_ECRS_URI_PREFIX, | ||
809 | GNUNET_ECRS_LOCATION_INFIX, | ||
810 | (char *) &keyhash, | ||
811 | (char *) &queryhash, | ||
812 | GNUNET_ntohll (loc->fi.file_length), | ||
813 | peerId, peerSig, loc->expirationTime); | ||
814 | GNUNET_free (peerSig); | ||
815 | GNUNET_free (peerId); | ||
816 | return ret; | ||
817 | } | ||
818 | |||
819 | /** | ||
820 | * Convert a URI to a UTF-8 String. | ||
821 | */ | ||
822 | char * | ||
823 | GNUNET_ECRS_uri_to_string (const struct GNUNET_ECRS_URI *uri) | ||
824 | { | ||
825 | if (uri == NULL) | ||
826 | { | ||
827 | GNUNET_GE_BREAK (NULL, 0); | ||
828 | return NULL; | ||
829 | } | ||
830 | switch (uri->type) | ||
831 | { | ||
832 | case ksk: | ||
833 | return createKeywordURI (uri->data.ksk.keywords, | ||
834 | uri->data.ksk.keywordCount); | ||
835 | case sks: | ||
836 | return createSubspaceURI (&uri->data.sks.namespace, | ||
837 | uri->data.sks.identifier); | ||
838 | case chk: | ||
839 | return createFileURI (&uri->data.fi); | ||
840 | case loc: | ||
841 | return createLocURI (&uri->data.loc); | ||
842 | default: | ||
843 | GNUNET_GE_BREAK (NULL, 0); | ||
844 | return NULL; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /** | ||
849 | * Convert keyword URI to a human readable format | ||
850 | * (i.e. the search query that was used in the first place) | ||
851 | */ | ||
852 | char * | ||
853 | GNUNET_ECRS_ksk_uri_to_human_readable_string (const struct GNUNET_ECRS_URI | ||
854 | *uri) | ||
855 | { | ||
856 | size_t n; | ||
857 | char *ret; | ||
858 | unsigned int i; | ||
859 | const char *keyword; | ||
860 | char **keywords; | ||
861 | unsigned int keywordCount; | ||
862 | |||
863 | if ((uri == NULL) || (uri->type != ksk)) | ||
864 | { | ||
865 | GNUNET_GE_BREAK (NULL, 0); | ||
866 | return NULL; | ||
867 | } | ||
868 | keywords = uri->data.ksk.keywords; | ||
869 | keywordCount = uri->data.ksk.keywordCount; | ||
870 | n = keywordCount + 1; | ||
871 | for (i = 0; i < keywordCount; i++) | ||
872 | { | ||
873 | keyword = keywords[i]; | ||
874 | n += strlen (keyword) - 1; | ||
875 | if (NULL != strstr (&keyword[1], " ")) | ||
876 | n += 2; | ||
877 | if (keyword[0] == '+') | ||
878 | n++; | ||
879 | } | ||
880 | ret = GNUNET_malloc (n); | ||
881 | strcpy (ret, ""); | ||
882 | for (i = 0; i < keywordCount; i++) | ||
883 | { | ||
884 | keyword = keywords[i]; | ||
885 | if (NULL != strstr (&keyword[1], " ")) | ||
886 | { | ||
887 | strcat (ret, "\""); | ||
888 | if (keyword[0] == '+') | ||
889 | strcat (ret, keyword); | ||
890 | else | ||
891 | strcat (ret, &keyword[1]); | ||
892 | strcat (ret, "\""); | ||
893 | } | ||
894 | else | ||
895 | { | ||
896 | if (keyword[0] == '+') | ||
897 | strcat (ret, keyword); | ||
898 | else | ||
899 | strcat (ret, &keyword[1]); | ||
900 | } | ||
901 | strcat (ret, " "); | ||
902 | } | ||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | /** | ||
907 | * Given a keyword with %-encoding (and possibly quotes to protect | ||
908 | * spaces), return a copy of the keyword without %-encoding and | ||
909 | * without double-quotes (%22). Also, add a space at the beginning | ||
910 | * if there is not a '+'. | ||
911 | */ | ||
912 | static char * | ||
913 | percent_decode_keyword (const char *in) | ||
914 | { | ||
915 | char *out; | ||
916 | char *ret; | ||
917 | unsigned int rpos; | ||
918 | unsigned int wpos; | ||
919 | unsigned int hx; | ||
920 | |||
921 | out = GNUNET_strdup (in); | ||
922 | rpos = 0; | ||
923 | wpos = 0; | ||
924 | while (out[rpos] != '\0') | ||
925 | { | ||
926 | if (out[rpos] == '%') | ||
927 | { | ||
928 | if (1 != sscanf (&out[rpos + 1], "%2X", &hx)) | ||
929 | { | ||
930 | GNUNET_free (out); | ||
931 | return NULL; | ||
932 | } | ||
933 | rpos += 3; | ||
934 | if (hx == '"') | ||
935 | continue; /* skip double quote */ | ||
936 | out[wpos++] = (char) hx; | ||
937 | } | ||
938 | else | ||
939 | { | ||
940 | out[wpos++] = out[rpos++]; | ||
941 | } | ||
942 | } | ||
943 | out[wpos] = '\0'; | ||
944 | if (out[0] == '+') | ||
945 | { | ||
946 | ret = GNUNET_strdup (out); | ||
947 | } | ||
948 | else | ||
949 | { | ||
950 | /* need to prefix with space */ | ||
951 | ret = GNUNET_malloc (strlen (out) + 2); | ||
952 | strcpy (ret, " "); | ||
953 | strcat (ret, out); | ||
954 | } | ||
955 | GNUNET_free (out); | ||
956 | return ret; | ||
957 | } | ||
958 | |||
959 | /** | ||
960 | * Parses an ECRS search URI. | ||
961 | * | ||
962 | * @param uri an uri string | ||
963 | * @param keyword will be set to an array with the keywords | ||
964 | * @return GNUNET_SYSERR if this is not a search URI, otherwise | ||
965 | * the number of keywords placed in the array | ||
966 | */ | ||
967 | static int | ||
968 | parseKeywordURI (struct GNUNET_GE_Context *ectx, const char *uri, | ||
969 | char ***keywords) | ||
970 | { | ||
971 | unsigned int pos; | ||
972 | int ret; | ||
973 | int iret; | ||
974 | int i; | ||
975 | size_t slen; | ||
976 | char *dup; | ||
977 | int saw_quote; | ||
978 | |||
979 | GNUNET_GE_ASSERT (ectx, uri != NULL); | ||
980 | |||
981 | slen = strlen (uri); | ||
982 | pos = strlen (GNUNET_ECRS_URI_PREFIX); | ||
983 | |||
984 | if (0 != strncmp (uri, GNUNET_ECRS_URI_PREFIX, pos)) | ||
985 | return GNUNET_SYSERR; | ||
986 | if (0 != | ||
987 | strncmp (&uri[pos], GNUNET_ECRS_SEARCH_INFIX, | ||
988 | strlen (GNUNET_ECRS_SEARCH_INFIX))) | ||
989 | return GNUNET_SYSERR; | ||
990 | pos += strlen (GNUNET_ECRS_SEARCH_INFIX); | ||
991 | if (slen == pos) | ||
992 | { | ||
993 | /* no keywords */ | ||
994 | (*keywords) = NULL; | ||
995 | return 0; | ||
996 | } | ||
997 | if ((uri[slen - 1] == '+') || (uri[pos] == '+')) | ||
998 | return GNUNET_SYSERR; /* no keywords / malformed */ | ||
999 | |||
1000 | ret = 1; | ||
1001 | saw_quote = 0; | ||
1002 | for (i = pos; i < slen; i++) | ||
1003 | { | ||
1004 | if ((uri[i] == '%') && (&uri[i] == strstr (&uri[i], "%22"))) | ||
1005 | { | ||
1006 | saw_quote = (saw_quote + 1) % 2; | ||
1007 | i += 3; | ||
1008 | continue; | ||
1009 | } | ||
1010 | if ((uri[i] == '+') && (saw_quote == 0)) | ||
1011 | { | ||
1012 | ret++; | ||
1013 | if (uri[i - 1] == '+') | ||
1014 | return GNUNET_SYSERR; /* "++" not allowed */ | ||
1015 | } | ||
1016 | } | ||
1017 | if (saw_quote == 1) | ||
1018 | return GNUNET_SYSERR; /* quotes not balanced */ | ||
1019 | iret = ret; | ||
1020 | dup = GNUNET_strdup (uri); | ||
1021 | (*keywords) = GNUNET_malloc (ret * sizeof (char *)); | ||
1022 | for (i = 0; i < ret; i++) | ||
1023 | (*keywords)[i] = NULL; | ||
1024 | for (i = slen - 1; i >= pos; i--) | ||
1025 | { | ||
1026 | if ((uri[i] == '%') && (&uri[i] == strstr (&uri[i], "%22"))) | ||
1027 | { | ||
1028 | saw_quote = (saw_quote + 1) % 2; | ||
1029 | i += 3; | ||
1030 | continue; | ||
1031 | } | ||
1032 | if ((dup[i] == '+') && (saw_quote == 0)) | ||
1033 | { | ||
1034 | (*keywords)[--ret] = percent_decode_keyword (&dup[i + 1]); | ||
1035 | if (NULL == (*keywords)[ret]) | ||
1036 | goto CLEANUP; | ||
1037 | dup[i] = '\0'; | ||
1038 | } | ||
1039 | } | ||
1040 | (*keywords)[--ret] = percent_decode_keyword (&dup[pos]); | ||
1041 | if (NULL == (*keywords)[ret]) | ||
1042 | goto CLEANUP; | ||
1043 | GNUNET_GE_ASSERT (ectx, ret == 0); | ||
1044 | GNUNET_free (dup); | ||
1045 | return iret; | ||
1046 | CLEANUP: | ||
1047 | for (i = 0; i < ret; i++) | ||
1048 | GNUNET_free_non_null ((*keywords)[i]); | ||
1049 | GNUNET_free (*keywords); | ||
1050 | *keywords = NULL; | ||
1051 | GNUNET_free (dup); | ||
1052 | return GNUNET_SYSERR; | ||
1053 | } | ||
1054 | |||
1055 | /** | ||
1056 | * Parses an AFS namespace / subspace identifier URI. | ||
1057 | * | ||
1058 | * @param uri an uri string | ||
1059 | * @param namespace set to the namespace ID | ||
1060 | * @param identifier set to the ID in the namespace | ||
1061 | * @return GNUNET_OK on success, GNUNET_SYSERR if this is not a namespace URI | ||
1062 | */ | ||
1063 | static int | ||
1064 | parseSubspaceURI (struct GNUNET_GE_Context *ectx, | ||
1065 | const char *uri, | ||
1066 | GNUNET_HashCode * namespace, char **identifier) | ||
1067 | { | ||
1068 | unsigned int pos; | ||
1069 | size_t slen; | ||
1070 | char *up; | ||
1071 | |||
1072 | GNUNET_GE_ASSERT (ectx, uri != NULL); | ||
1073 | |||
1074 | slen = strlen (uri); | ||
1075 | pos = strlen (GNUNET_ECRS_URI_PREFIX); | ||
1076 | |||
1077 | if (0 != strncmp (uri, GNUNET_ECRS_URI_PREFIX, pos)) | ||
1078 | return GNUNET_SYSERR; | ||
1079 | if (0 != strncmp (&uri[pos], | ||
1080 | GNUNET_ECRS_SUBSPACE_INFIX, | ||
1081 | strlen (GNUNET_ECRS_SUBSPACE_INFIX))) | ||
1082 | return GNUNET_SYSERR; | ||
1083 | pos += strlen (GNUNET_ECRS_SUBSPACE_INFIX); | ||
1084 | if ((slen < pos + sizeof (GNUNET_EncName) + 1) || | ||
1085 | (!((uri[pos + sizeof (GNUNET_EncName) - 1] == '/') || | ||
1086 | (uri[pos + sizeof (GNUNET_EncName) - 1] == '\\')))) | ||
1087 | return GNUNET_SYSERR; | ||
1088 | |||
1089 | up = GNUNET_strdup (uri); | ||
1090 | up[pos + sizeof (GNUNET_EncName) - 1] = '\0'; | ||
1091 | if ((GNUNET_OK != GNUNET_enc_to_hash (&up[pos], namespace))) | ||
1092 | { | ||
1093 | GNUNET_free (up); | ||
1094 | return GNUNET_SYSERR; | ||
1095 | } | ||
1096 | *identifier = GNUNET_strdup (&up[pos + sizeof (GNUNET_EncName)]); | ||
1097 | GNUNET_free (up); | ||
1098 | return GNUNET_OK; | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1102 | * Parses an URI that identifies a file | ||
1103 | * | ||
1104 | * @param uri an uri string | ||
1105 | * @param fi the file identifier | ||
1106 | * @return GNUNET_OK on success, GNUNET_SYSERR if this is not a file URI | ||
1107 | */ | ||
1108 | static int | ||
1109 | parseFileURI (struct GNUNET_GE_Context *ectx, const char *uri, | ||
1110 | GNUNET_EC_FileIdentifier * fi) | ||
1111 | { | ||
1112 | unsigned int pos; | ||
1113 | size_t slen; | ||
1114 | char *dup; | ||
1115 | |||
1116 | GNUNET_GE_ASSERT (ectx, uri != NULL); | ||
1117 | |||
1118 | slen = strlen (uri); | ||
1119 | pos = strlen (GNUNET_ECRS_URI_PREFIX); | ||
1120 | |||
1121 | if (0 != strncmp (uri, GNUNET_ECRS_URI_PREFIX, pos)) | ||
1122 | return GNUNET_SYSERR; | ||
1123 | if (0 != | ||
1124 | strncmp (&uri[pos], GNUNET_ECRS_FILE_INFIX, | ||
1125 | strlen (GNUNET_ECRS_FILE_INFIX))) | ||
1126 | return GNUNET_SYSERR; | ||
1127 | pos += strlen (GNUNET_ECRS_FILE_INFIX); | ||
1128 | if ((slen < pos + 2 * sizeof (GNUNET_EncName) + 1) || | ||
1129 | (uri[pos + sizeof (GNUNET_EncName) - 1] != '.') || | ||
1130 | (uri[pos + sizeof (GNUNET_EncName) * 2 - 1] != '.')) | ||
1131 | return GNUNET_SYSERR; | ||
1132 | |||
1133 | dup = GNUNET_strdup (uri); | ||
1134 | dup[pos + sizeof (GNUNET_EncName) - 1] = '\0'; | ||
1135 | dup[pos + sizeof (GNUNET_EncName) * 2 - 1] = '\0'; | ||
1136 | if ((GNUNET_OK != GNUNET_enc_to_hash (&dup[pos], | ||
1137 | &fi->chk.key)) || | ||
1138 | (GNUNET_OK != GNUNET_enc_to_hash (&dup[pos + sizeof (GNUNET_EncName)], | ||
1139 | &fi->chk.query)) || | ||
1140 | (1 != SSCANF (&dup[pos + sizeof (GNUNET_EncName) * 2], | ||
1141 | "%llu", &fi->file_length))) | ||
1142 | { | ||
1143 | GNUNET_free (dup); | ||
1144 | return GNUNET_SYSERR; | ||
1145 | } | ||
1146 | GNUNET_free (dup); | ||
1147 | fi->file_length = GNUNET_htonll (fi->file_length); | ||
1148 | return GNUNET_OK; | ||
1149 | } | ||
1150 | |||
1151 | /** | ||
1152 | * Parses an URI that identifies a location (and file). | ||
1153 | * Also verifies validity of the location URI. | ||
1154 | * | ||
1155 | * @param uri an uri string | ||
1156 | * @param loc where to store the location | ||
1157 | * @return GNUNET_OK on success, GNUNET_SYSERR if this is not a file URI | ||
1158 | */ | ||
1159 | static int | ||
1160 | parseLocationURI (struct GNUNET_GE_Context *ectx, const char *uri, | ||
1161 | Location * loc) | ||
1162 | { | ||
1163 | unsigned int pos; | ||
1164 | unsigned int npos; | ||
1165 | int ret; | ||
1166 | size_t slen; | ||
1167 | char *dup; | ||
1168 | char *addr; | ||
1169 | |||
1170 | |||
1171 | GNUNET_GE_ASSERT (ectx, uri != NULL); | ||
1172 | addr = NULL; | ||
1173 | slen = strlen (uri); | ||
1174 | pos = strlen (GNUNET_ECRS_URI_PREFIX); | ||
1175 | |||
1176 | if (0 != strncmp (uri, GNUNET_ECRS_URI_PREFIX, pos)) | ||
1177 | return GNUNET_SYSERR; | ||
1178 | if (0 != strncmp (&uri[pos], | ||
1179 | GNUNET_ECRS_LOCATION_INFIX, | ||
1180 | strlen (GNUNET_ECRS_LOCATION_INFIX))) | ||
1181 | return GNUNET_SYSERR; | ||
1182 | pos += strlen (GNUNET_ECRS_LOCATION_INFIX); | ||
1183 | if ((slen < pos + 2 * sizeof (GNUNET_EncName) + 1) || | ||
1184 | (uri[pos + sizeof (GNUNET_EncName) - 1] != '.') || | ||
1185 | (uri[pos + sizeof (GNUNET_EncName) * 2 - 1] != '.')) | ||
1186 | return GNUNET_SYSERR; | ||
1187 | |||
1188 | dup = GNUNET_strdup (uri); | ||
1189 | dup[pos + sizeof (GNUNET_EncName) - 1] = '\0'; | ||
1190 | dup[pos + sizeof (GNUNET_EncName) * 2 - 1] = '\0'; | ||
1191 | npos = pos + sizeof (GNUNET_EncName) * 2; | ||
1192 | while ((uri[npos] != '\0') && (uri[npos] != '.')) | ||
1193 | npos++; | ||
1194 | if (dup[npos] == '\0') | ||
1195 | goto ERR; | ||
1196 | dup[npos++] = '\0'; | ||
1197 | if ((GNUNET_OK != GNUNET_enc_to_hash (&dup[pos], | ||
1198 | &loc->fi.chk.key)) || | ||
1199 | (GNUNET_OK != GNUNET_enc_to_hash (&dup[pos + sizeof (GNUNET_EncName)], | ||
1200 | &loc->fi.chk.query)) || | ||
1201 | (1 != SSCANF (&dup[pos + sizeof (GNUNET_EncName) * 2], | ||
1202 | "%llu", &loc->fi.file_length))) | ||
1203 | goto ERR; | ||
1204 | loc->fi.file_length = GNUNET_htonll (loc->fi.file_length); | ||
1205 | ret = enc2bin (&dup[npos], &loc->peer, sizeof (GNUNET_RSA_PublicKey)); | ||
1206 | if (ret == -1) | ||
1207 | goto ERR; | ||
1208 | npos += ret; | ||
1209 | if (dup[npos++] != '.') | ||
1210 | goto ERR; | ||
1211 | ret = | ||
1212 | enc2bin (&dup[npos], &loc->contentSignature, | ||
1213 | sizeof (GNUNET_RSA_Signature)); | ||
1214 | if (ret == -1) | ||
1215 | goto ERR; | ||
1216 | npos += ret; | ||
1217 | if (dup[npos++] != '.') | ||
1218 | goto ERR; | ||
1219 | if (1 != SSCANF (&dup[npos], "%u", &loc->expirationTime)) | ||
1220 | goto ERR; | ||
1221 | /* Finally: verify sigs! */ | ||
1222 | if (GNUNET_OK != GNUNET_RSA_verify (&loc->fi, | ||
1223 | sizeof (GNUNET_EC_FileIdentifier) + | ||
1224 | sizeof (GNUNET_PeerIdentity) + | ||
1225 | sizeof (GNUNET_Int32Time), | ||
1226 | &loc->contentSignature, &loc->peer)) | ||
1227 | goto ERR; | ||
1228 | GNUNET_free (dup); | ||
1229 | return GNUNET_OK; | ||
1230 | ERR: | ||
1231 | GNUNET_free (dup); | ||
1232 | GNUNET_free_non_null (addr); | ||
1233 | return GNUNET_SYSERR; | ||
1234 | } | ||
1235 | |||
1236 | /** | ||
1237 | * Convert a UTF-8 String to a URI. | ||
1238 | */ | ||
1239 | URI * | ||
1240 | GNUNET_ECRS_string_to_uri (struct GNUNET_GE_Context * ectx, const char *uri) | ||
1241 | { | ||
1242 | URI *ret; | ||
1243 | int len; | ||
1244 | |||
1245 | ret = GNUNET_malloc (sizeof (URI)); | ||
1246 | if (GNUNET_OK == parseFileURI (ectx, uri, &ret->data.fi)) | ||
1247 | { | ||
1248 | ret->type = chk; | ||
1249 | return ret; | ||
1250 | } | ||
1251 | if (GNUNET_OK == parseSubspaceURI (ectx, | ||
1252 | uri, | ||
1253 | &ret->data.sks.namespace, | ||
1254 | &ret->data.sks.identifier)) | ||
1255 | { | ||
1256 | ret->type = sks; | ||
1257 | return ret; | ||
1258 | } | ||
1259 | if (GNUNET_OK == parseLocationURI (ectx, uri, &ret->data.loc)) | ||
1260 | { | ||
1261 | ret->type = loc; | ||
1262 | return ret; | ||
1263 | } | ||
1264 | len = parseKeywordURI (ectx, uri, &ret->data.ksk.keywords); | ||
1265 | if (len < 0) | ||
1266 | { | ||
1267 | GNUNET_free (ret); | ||
1268 | return NULL; | ||
1269 | } | ||
1270 | ret->type = ksk; | ||
1271 | ret->data.ksk.keywordCount = len; | ||
1272 | return ret; | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | |||
1277 | /** | ||
1278 | * Construct a location URI. | ||
1279 | * | ||
1280 | * @param baseURI content offered by the sender | ||
1281 | * @param sender identity of the peer with the content | ||
1282 | * @param expiration_time how long will the content be offered? | ||
1283 | * @param proto transport protocol to reach the peer | ||
1284 | * @param sas sender address size (for HELLO) | ||
1285 | * @param address sas bytes of address information | ||
1286 | * @param signer function to call for obtaining | ||
1287 | * RSA signatures for "sender". | ||
1288 | * @return the location URI | ||
1289 | */ | ||
1290 | struct GNUNET_ECRS_URI * | ||
1291 | GNUNET_ECRS_location_to_uri (const struct GNUNET_ECRS_URI *baseUri, | ||
1292 | const GNUNET_RSA_PublicKey * sender, | ||
1293 | GNUNET_Int32Time expirationTime, | ||
1294 | GNUNET_ECRS_SignFunction signer, | ||
1295 | void *signer_cls) | ||
1296 | { | ||
1297 | struct GNUNET_ECRS_URI *uri; | ||
1298 | |||
1299 | if (baseUri->type != chk) | ||
1300 | return NULL; | ||
1301 | |||
1302 | uri = GNUNET_malloc (sizeof (struct GNUNET_ECRS_URI)); | ||
1303 | uri->type = loc; | ||
1304 | uri->data.loc.fi = baseUri->data.fi; | ||
1305 | uri->data.loc.peer = *sender; | ||
1306 | uri->data.loc.expirationTime = expirationTime; | ||
1307 | signer (signer_cls, | ||
1308 | sizeof (GNUNET_EC_FileIdentifier) + | ||
1309 | sizeof (GNUNET_PeerIdentity) + | ||
1310 | sizeof (GNUNET_Int32Time), | ||
1311 | &uri->data.loc.fi, &uri->data.loc.contentSignature); | ||
1312 | return uri; | ||
1313 | } | ||
1314 | |||
1315 | #endif | ||
1316 | |||
1317 | /* end of uri.c */ | ||
diff --git a/src/fs/test_fs_getopt.c b/src/fs/test_fs_getopt.c new file mode 100644 index 000000000..2c0a0eba4 --- /dev/null +++ b/src/fs/test_fs_getopt.c | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file fs/test_fs_getopt.c | ||
22 | * @brief test for fs_getopt.c | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_fs_lib.h" | ||
27 | |||
28 | int | ||
29 | main (int argc, char *argv[]) | ||
30 | { | ||
31 | fprintf (stderr, "WARNING: testcase not yet written.\n"); | ||
32 | return 0; /* testcase passed */ | ||
33 | } | ||
diff --git a/src/fs/test_fs_uri.c b/src/fs/test_fs_uri.c new file mode 100644 index 000000000..f24f4fe27 --- /dev/null +++ b/src/fs/test_fs_uri.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2003, 2004, 2006, 2007 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file applications/fs/ecrs/uritest.c | ||
23 | * @brief Test for uri.c | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util.h" | ||
29 | #include "gnunet_ecrs_lib.h" | ||
30 | #include "ecrs.h" | ||
31 | |||
32 | #define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); return 1; } | ||
33 | |||
34 | static int | ||
35 | testKeyword () | ||
36 | { | ||
37 | char *uri; | ||
38 | struct GNUNET_ECRS_URI *ret; | ||
39 | |||
40 | if (NULL != GNUNET_ECRS_string_to_uri (NULL, "gnunet://ecrs/ksk/++")) | ||
41 | ABORT (); | ||
42 | ret = GNUNET_ECRS_string_to_uri (NULL, "gnunet://ecrs/ksk/foo+bar"); | ||
43 | if (ret == NULL) | ||
44 | ABORT (); | ||
45 | if (!GNUNET_ECRS_uri_test_ksk (ret)) | ||
46 | { | ||
47 | GNUNET_ECRS_uri_destroy (ret); | ||
48 | ABORT (); | ||
49 | } | ||
50 | if ((2 != ret->data.ksk.keywordCount) || | ||
51 | (0 != strcmp (" foo", ret->data.ksk.keywords[0])) || | ||
52 | (0 != strcmp (" bar", ret->data.ksk.keywords[1]))) | ||
53 | { | ||
54 | GNUNET_ECRS_uri_destroy (ret); | ||
55 | ABORT (); | ||
56 | } | ||
57 | |||
58 | uri = GNUNET_ECRS_uri_to_string (ret); | ||
59 | if (0 != strcmp (uri, "gnunet://ecrs/ksk/foo+bar")) | ||
60 | { | ||
61 | GNUNET_free (uri); | ||
62 | GNUNET_ECRS_uri_destroy (ret); | ||
63 | ABORT (); | ||
64 | } | ||
65 | GNUNET_free (uri); | ||
66 | GNUNET_ECRS_uri_destroy (ret); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int | ||
71 | testLocation () | ||
72 | { | ||
73 | struct GNUNET_ECRS_URI *uri; | ||
74 | char *uric; | ||
75 | struct GNUNET_ECRS_URI *uri2; | ||
76 | GNUNET_RSA_PublicKey pk; | ||
77 | struct GNUNET_RSA_PrivateKey *hk; | ||
78 | struct GNUNET_ECRS_URI *baseURI; | ||
79 | |||
80 | baseURI = | ||
81 | GNUNET_ECRS_string_to_uri (NULL, | ||
82 | "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"); | ||
83 | hk = GNUNET_RSA_create_key (); | ||
84 | GNUNET_RSA_get_public_key (hk, &pk); | ||
85 | uri = GNUNET_ECRS_location_to_uri (baseURI, | ||
86 | &pk, 43, | ||
87 | (GNUNET_ECRS_SignFunction) & | ||
88 | GNUNET_RSA_sign, hk); | ||
89 | GNUNET_RSA_free_key (hk); | ||
90 | if (uri == NULL) | ||
91 | { | ||
92 | GNUNET_GE_BREAK (NULL, 0); | ||
93 | GNUNET_ECRS_uri_destroy (baseURI); | ||
94 | return 1; | ||
95 | } | ||
96 | if (!GNUNET_ECRS_uri_test_loc (uri)) | ||
97 | { | ||
98 | GNUNET_GE_BREAK (NULL, 0); | ||
99 | GNUNET_ECRS_uri_destroy (uri); | ||
100 | GNUNET_ECRS_uri_destroy (baseURI); | ||
101 | return 1; | ||
102 | } | ||
103 | uri2 = GNUNET_ECRS_uri_get_content_uri_from_loc (uri); | ||
104 | if (!GNUNET_ECRS_uri_test_equal (baseURI, uri2)) | ||
105 | { | ||
106 | GNUNET_GE_BREAK (NULL, 0); | ||
107 | GNUNET_ECRS_uri_destroy (uri); | ||
108 | GNUNET_ECRS_uri_destroy (uri2); | ||
109 | GNUNET_ECRS_uri_destroy (baseURI); | ||
110 | return 1; | ||
111 | } | ||
112 | GNUNET_ECRS_uri_destroy (uri2); | ||
113 | GNUNET_ECRS_uri_destroy (baseURI); | ||
114 | uric = GNUNET_ECRS_uri_to_string (uri); | ||
115 | #if 0 | ||
116 | /* not for the faint of heart: */ | ||
117 | printf ("URI: `%s'\n", uric); | ||
118 | #endif | ||
119 | uri2 = GNUNET_ECRS_string_to_uri (NULL, uric); | ||
120 | GNUNET_free (uric); | ||
121 | if (uri2 == NULL) | ||
122 | { | ||
123 | GNUNET_GE_BREAK (NULL, 0); | ||
124 | GNUNET_ECRS_uri_destroy (uri); | ||
125 | return 1; | ||
126 | } | ||
127 | if (GNUNET_YES != GNUNET_ECRS_uri_test_equal (uri, uri2)) | ||
128 | { | ||
129 | GNUNET_GE_BREAK (NULL, 0); | ||
130 | GNUNET_ECRS_uri_destroy (uri); | ||
131 | GNUNET_ECRS_uri_destroy (uri2); | ||
132 | return 1; | ||
133 | } | ||
134 | GNUNET_ECRS_uri_destroy (uri2); | ||
135 | GNUNET_ECRS_uri_destroy (uri); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int | ||
140 | testNamespace (int i) | ||
141 | { | ||
142 | char *uri; | ||
143 | struct GNUNET_ECRS_URI *ret; | ||
144 | |||
145 | if (NULL != | ||
146 | GNUNET_ECRS_string_to_uri (NULL, | ||
147 | "gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK")) | ||
148 | ABORT (); | ||
149 | if (NULL != | ||
150 | GNUNET_ECRS_string_to_uri (NULL, | ||
151 | "gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test")) | ||
152 | ABORT (); | ||
153 | if (NULL != GNUNET_ECRS_string_to_uri (NULL, "gnunet://ecrs/sks/test")) | ||
154 | ABORT (); | ||
155 | ret = | ||
156 | GNUNET_ECRS_string_to_uri (NULL, | ||
157 | "gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test"); | ||
158 | if (ret == NULL) | ||
159 | ABORT (); | ||
160 | if (GNUNET_ECRS_uri_test_ksk (ret)) | ||
161 | { | ||
162 | GNUNET_ECRS_uri_destroy (ret); | ||
163 | ABORT (); | ||
164 | } | ||
165 | if (!GNUNET_ECRS_uri_test_sks (ret)) | ||
166 | { | ||
167 | GNUNET_ECRS_uri_destroy (ret); | ||
168 | ABORT (); | ||
169 | } | ||
170 | |||
171 | uri = GNUNET_ECRS_uri_to_string (ret); | ||
172 | if (0 != strcmp (uri, | ||
173 | "gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test")) | ||
174 | { | ||
175 | GNUNET_ECRS_uri_destroy (ret); | ||
176 | GNUNET_free (uri); | ||
177 | ABORT (); | ||
178 | } | ||
179 | GNUNET_free (uri); | ||
180 | GNUNET_ECRS_uri_destroy (ret); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int | ||
185 | testFile (int i) | ||
186 | { | ||
187 | char *uri; | ||
188 | struct GNUNET_ECRS_URI *ret; | ||
189 | |||
190 | if (NULL != | ||
191 | GNUNET_ECRS_string_to_uri (NULL, | ||
192 | "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42")) | ||
193 | ABORT (); | ||
194 | if (NULL != | ||
195 | GNUNET_ECRS_string_to_uri (NULL, | ||
196 | "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000")) | ||
197 | ABORT (); | ||
198 | if (NULL != | ||
199 | GNUNET_ECRS_string_to_uri (NULL, | ||
200 | "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH")) | ||
201 | ABORT (); | ||
202 | ret = | ||
203 | GNUNET_ECRS_string_to_uri (NULL, | ||
204 | "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"); | ||
205 | if (ret == NULL) | ||
206 | ABORT (); | ||
207 | if (GNUNET_ECRS_uri_test_ksk (ret)) | ||
208 | { | ||
209 | GNUNET_ECRS_uri_destroy (ret); | ||
210 | ABORT (); | ||
211 | } | ||
212 | if (GNUNET_ECRS_uri_test_sks (ret)) | ||
213 | { | ||
214 | GNUNET_ECRS_uri_destroy (ret); | ||
215 | ABORT (); | ||
216 | } | ||
217 | if (GNUNET_ntohll (ret->data.fi.file_length) != 42) | ||
218 | { | ||
219 | GNUNET_ECRS_uri_destroy (ret); | ||
220 | ABORT (); | ||
221 | } | ||
222 | |||
223 | uri = GNUNET_ECRS_uri_to_string (ret); | ||
224 | if (0 != strcmp (uri, | ||
225 | "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42")) | ||
226 | { | ||
227 | GNUNET_free (uri); | ||
228 | GNUNET_ECRS_uri_destroy (ret); | ||
229 | ABORT (); | ||
230 | } | ||
231 | GNUNET_free (uri); | ||
232 | GNUNET_ECRS_uri_destroy (ret); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | int | ||
237 | main (int argc, char *argv[]) | ||
238 | { | ||
239 | int failureCount = 0; | ||
240 | int i; | ||
241 | |||
242 | GNUNET_disable_entropy_gathering (); | ||
243 | failureCount += testKeyword (); | ||
244 | failureCount += testLocation (); | ||
245 | for (i = 0; i < 255; i++) | ||
246 | { | ||
247 | failureCount += testNamespace (i); | ||
248 | failureCount += testFile (i); | ||
249 | } | ||
250 | if (failureCount != 0) | ||
251 | return 1; | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | /* end of uritest.c */ | ||
diff --git a/src/hostlist/hostlist-client.c b/src/hostlist/hostlist-client.c index bc98a2bcf..468c6b64c 100644 --- a/src/hostlist/hostlist-client.c +++ b/src/hostlist/hostlist-client.c | |||
@@ -625,11 +625,12 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, | |||
625 | cfg = c; | 625 | cfg = c; |
626 | sched = s; | 626 | sched = s; |
627 | stats = st; | 627 | stats = st; |
628 | proxy = NULL; | 628 | if (GNUNET_OK != |
629 | GNUNET_CONFIGURATION_get_value_string (cfg, | 629 | GNUNET_CONFIGURATION_get_value_string (cfg, |
630 | "HOSTLIST", | 630 | "HOSTLIST", |
631 | "HTTP-PROXY", | 631 | "HTTP-PROXY", |
632 | &proxy); | 632 | &proxy)) |
633 | proxy = NULL; | ||
633 | *ch = &connect_handler; | 634 | *ch = &connect_handler; |
634 | *dh = &disconnect_handler; | 635 | *dh = &disconnect_handler; |
635 | GNUNET_STATISTICS_get (stats, | 636 | GNUNET_STATISTICS_get (stats, |
diff --git a/src/hostlist/hostlist-server.c b/src/hostlist/hostlist-server.c index 34e9310e4..5cc26c409 100644 --- a/src/hostlist/hostlist-server.c +++ b/src/hostlist/hostlist-server.c | |||
@@ -116,7 +116,10 @@ host_processor (void *cls, | |||
116 | size_t s; | 116 | size_t s; |
117 | 117 | ||
118 | if (peer == NULL) | 118 | if (peer == NULL) |
119 | finish_response (results); | 119 | { |
120 | finish_response (results); | ||
121 | return; | ||
122 | } | ||
120 | old = results->size; | 123 | old = results->size; |
121 | s = GNUNET_HELLO_size(hello); | 124 | s = GNUNET_HELLO_size(hello); |
122 | if (old + s >= GNUNET_MAX_MALLOC_CHECKED) | 125 | if (old + s >= GNUNET_MAX_MALLOC_CHECKED) |
diff --git a/src/include/gnunet_configuration_lib.h b/src/include/gnunet_configuration_lib.h index abbfe2eec..c5ea21ed8 100644 --- a/src/include/gnunet_configuration_lib.h +++ b/src/include/gnunet_configuration_lib.h | |||
@@ -47,16 +47,27 @@ struct GNUNET_CONFIGURATION_Handle; | |||
47 | 47 | ||
48 | /** | 48 | /** |
49 | * Create a new configuration object. | 49 | * Create a new configuration object. |
50 | * | 50 | * @return fresh configuration object |
51 | * @param component name of responsible component | ||
52 | */ | 51 | */ |
53 | struct GNUNET_CONFIGURATION_Handle *GNUNET_CONFIGURATION_create (void); | 52 | struct GNUNET_CONFIGURATION_Handle *GNUNET_CONFIGURATION_create (void); |
54 | 53 | ||
54 | |||
55 | /** | ||
56 | * Duplicate an existing configuration object. | ||
57 | * | ||
58 | * @param c configuration to duplicate | ||
59 | * @return duplicate configuration | ||
60 | */ | ||
61 | struct GNUNET_CONFIGURATION_Handle * | ||
62 | GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *c); | ||
63 | |||
64 | |||
55 | /** | 65 | /** |
56 | * Destroy configuration object. | 66 | * Destroy configuration object. |
57 | */ | 67 | */ |
58 | void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg); | 68 | void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg); |
59 | 69 | ||
70 | |||
60 | /** | 71 | /** |
61 | * Load configuration. This function will first parse the | 72 | * Load configuration. This function will first parse the |
62 | * defaults and then parse the specific configuration file | 73 | * defaults and then parse the specific configuration file |
@@ -68,6 +79,7 @@ void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg); | |||
68 | int GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, | 79 | int GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, |
69 | const char *filename); | 80 | const char *filename); |
70 | 81 | ||
82 | |||
71 | /** | 83 | /** |
72 | * Parse a configuration file, add all of the options in the | 84 | * Parse a configuration file, add all of the options in the |
73 | * file to the configuration environment. | 85 | * file to the configuration environment. |
@@ -76,6 +88,7 @@ int GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
76 | int GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, | 88 | int GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, |
77 | const char *filename); | 89 | const char *filename); |
78 | 90 | ||
91 | |||
79 | /** | 92 | /** |
80 | * Write configuration file. | 93 | * Write configuration file. |
81 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 94 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
@@ -83,6 +96,7 @@ int GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
83 | int GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, | 96 | int GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, |
84 | const char *filename); | 97 | const char *filename); |
85 | 98 | ||
99 | |||
86 | /** | 100 | /** |
87 | * Test if there are configuration options that were | 101 | * Test if there are configuration options that were |
88 | * changed since the last save. | 102 | * changed since the last save. |
@@ -90,6 +104,33 @@ int GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
90 | */ | 104 | */ |
91 | int GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg); | 105 | int GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg); |
92 | 106 | ||
107 | |||
108 | /** | ||
109 | * Function to iterate over options. | ||
110 | * | ||
111 | * @param cls closure | ||
112 | * @param section name of the section | ||
113 | * @param option name of the option | ||
114 | * @param value value of the option | ||
115 | */ | ||
116 | typedef void (*GNUNET_CONFIGURATION_Iterator)(void *cls, | ||
117 | const char *section, | ||
118 | const char *option, | ||
119 | const char *value); | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Iterate over all options in the configuration. | ||
124 | * | ||
125 | * @param cfg configuration to inspect | ||
126 | * @param iter function to call on each option | ||
127 | * @param iter_cls closure for iter | ||
128 | */ | ||
129 | void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
130 | GNUNET_CONFIGURATION_Iterator iter, | ||
131 | void *iter_cls); | ||
132 | |||
133 | |||
93 | /** | 134 | /** |
94 | * Get a configuration value that should be a number. | 135 | * Get a configuration value that should be a number. |
95 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 136 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
@@ -240,6 +281,7 @@ int GNUNET_CONFIGURATION_append_value_filename (struct | |||
240 | const char *option, | 281 | const char *option, |
241 | const char *value); | 282 | const char *value); |
242 | 283 | ||
284 | |||
243 | #if 0 /* keep Emacsens' auto-indent happy */ | 285 | #if 0 /* keep Emacsens' auto-indent happy */ |
244 | { | 286 | { |
245 | #endif | 287 | #endif |
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h index 255f68a89..c3a9a79ba 100644 --- a/src/include/gnunet_container_lib.h +++ b/src/include/gnunet_container_lib.h | |||
@@ -189,11 +189,15 @@ struct GNUNET_CONTAINER_MetaData; | |||
189 | 189 | ||
190 | /** | 190 | /** |
191 | * Iterator over meta data. | 191 | * Iterator over meta data. |
192 | * | ||
193 | * @param cls closure | ||
194 | * @param type type of the meta data | ||
195 | * @param data value of the meta data | ||
192 | * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR to abort | 196 | * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR to abort |
193 | */ | 197 | */ |
194 | typedef int (*GNUNET_CONTAINER_MetaDataProcessor) (EXTRACTOR_KeywordType type, | 198 | typedef int (*GNUNET_CONTAINER_MetaDataProcessor) (void *cls, |
195 | const char *data, | 199 | EXTRACTOR_KeywordType type, |
196 | void *closure); | 200 | const char *data); |
197 | 201 | ||
198 | /** | 202 | /** |
199 | * Create a fresh MetaData token. | 203 | * Create a fresh MetaData token. |
diff --git a/src/include/gnunet_testing_lib.h b/src/include/gnunet_testing_lib.h index dbd8a3d3f..8de354853 100644 --- a/src/include/gnunet_testing_lib.h +++ b/src/include/gnunet_testing_lib.h | |||
@@ -85,7 +85,7 @@ typedef void (*GNUNET_TESTING_NotifyDaemonRunning)(void *cls, | |||
85 | */ | 85 | */ |
86 | struct GNUNET_TESTING_Daemon * | 86 | struct GNUNET_TESTING_Daemon * |
87 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | 87 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, |
88 | struct GNUNET_CONFIGURATION_Handle *cfg, | 88 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
89 | const char *hostname, | 89 | const char *hostname, |
90 | GNUNET_TESTING_NotifyDaemonRunning cb, | 90 | GNUNET_TESTING_NotifyDaemonRunning cb, |
91 | void *cb_cls); | 91 | void *cb_cls); |
@@ -163,50 +163,17 @@ struct GNUNET_TESTING_PeerGroup; | |||
163 | * @param total number of daemons to start | 163 | * @param total number of daemons to start |
164 | * @param cb function to call on each daemon that was started | 164 | * @param cb function to call on each daemon that was started |
165 | * @param cb_cls closure for cb | 165 | * @param cb_cls closure for cb |
166 | * @param hostname where to run the peers; can be NULL (to run | 166 | * @param hostnames space-separated list of hostnames to use, |
167 | * everything on localhost). | 167 | * NULL to use localhost only |
168 | * @param va Additional hosts can be specified using a NULL-terminated list of | ||
169 | * varargs, hosts will then be used round-robin from that | ||
170 | * list; va only contains anything if hostname != NULL. | ||
171 | * @return NULL on error, otherwise handle to control peer group | ||
172 | */ | ||
173 | struct GNUNET_TESTING_PeerGroup * | ||
174 | GNUNET_TESTING_daemons_start_va (struct GNUNET_SCHEDULER_Handle *sched, | ||
175 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
176 | unsigned int total, | ||
177 | GNUNET_TESTING_NotifyDaemonRunning cb, | ||
178 | void *cb_cls, | ||
179 | const char *hostname, | ||
180 | va_list va); | ||
181 | |||
182 | |||
183 | /** | ||
184 | * Start count gnunetd processes with the same set of | ||
185 | * transports and applications. The port numbers will | ||
186 | * be computed by adding delta each time (zero | ||
187 | * times for the first peer). | ||
188 | * | ||
189 | * @param sched scheduler to use | ||
190 | * @param cfg configuration template to use | ||
191 | * @param total number of daemons to start | ||
192 | * @param timeout how long is this allowed to take? | ||
193 | * @param cb function to call on each daemon that was started | ||
194 | * @param cb_cls closure for cb | ||
195 | * @param hostname where to run the peers; can be NULL (to run | ||
196 | * everything on localhost). Additional | ||
197 | * hosts can be specified using a NULL-terminated list of | ||
198 | * varargs, hosts will then be used round-robin from that | ||
199 | * list. | ||
200 | * @return NULL on error, otherwise handle to control peer group | 168 | * @return NULL on error, otherwise handle to control peer group |
201 | */ | 169 | */ |
202 | struct GNUNET_TESTING_PeerGroup * | 170 | struct GNUNET_TESTING_PeerGroup * |
203 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | 171 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, |
204 | struct GNUNET_CONFIGURATION_Handle *cfg, | 172 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
205 | unsigned int total, | 173 | unsigned int total, |
206 | GNUNET_TESTING_NotifyDaemonRunning cb, | 174 | GNUNET_TESTING_NotifyDaemonRunning cb, |
207 | void *cb_cls, | 175 | void *cb_cls, |
208 | const char *hostname, | 176 | const char *hostnames); |
209 | ...); | ||
210 | 177 | ||
211 | 178 | ||
212 | /** | 179 | /** |
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 635570482..9ac831a88 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am | |||
@@ -15,17 +15,20 @@ libgnunettesting_la_SOURCES = \ | |||
15 | testing.c \ | 15 | testing.c \ |
16 | testing_group.c \ | 16 | testing_group.c \ |
17 | testing_testbed.c | 17 | testing_testbed.c |
18 | libgnunettesting_la_LIBADD = \ | 18 | libgnunettesting_la_LIBADD = $(XLIB) \ |
19 | $(top_builddir)/src/util/libgnunetutil.la $(XLIB) | 19 | $(top_builddir)/src/core/libgnunetcore.la \ |
20 | 20 | $(top_builddir)/src/transport/libgnunettransport.la \ | |
21 | #check_PROGRAMS = \ | 21 | $(top_builddir)/src/util/libgnunetutil.la |
22 | # test_testing | ||
23 | # | ||
24 | #TESTS = $(check_PROGRAMS) | ||
25 | # | ||
26 | #test_testing_SOURCES = \ | ||
27 | # test_testing.c | ||
28 | #test_testing_LDADD = \ | ||
29 | # $(top_builddir)/src/testing/libgnunettesting.la \ | ||
30 | # $(top_builddir)/src/util/libgnunetutil.la | ||
31 | 22 | ||
23 | check_PROGRAMS = \ | ||
24 | test_testing | ||
25 | |||
26 | TESTS = $(check_PROGRAMS) | ||
27 | |||
28 | test_testing_SOURCES = \ | ||
29 | test_testing.c | ||
30 | test_testing_LDADD = \ | ||
31 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
32 | $(top_builddir)/src/util/libgnunetutil.la | ||
33 | |||
34 | EXTRA_DIST = test_testing_data.conf | ||
diff --git a/src/testing/test_testing.c b/src/testing/test_testing.c new file mode 100644 index 000000000..cbedf60fb --- /dev/null +++ b/src/testing/test_testing.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing.c | ||
22 | * @brief testcase for testing.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | |||
27 | #define VERBOSE GNUNET_YES | ||
28 | |||
29 | static int ok; | ||
30 | |||
31 | static void end_cb(void *cls, | ||
32 | const char *emsg) | ||
33 | { | ||
34 | GNUNET_assert (emsg == NULL); | ||
35 | #if VERBOSE | ||
36 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
37 | "Daemon terminated, will now exit.\n"); | ||
38 | #endif | ||
39 | ok = 0; | ||
40 | } | ||
41 | |||
42 | static void my_cb(void *cls, | ||
43 | const struct GNUNET_PeerIdentity *id, | ||
44 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
45 | struct GNUNET_TESTING_Daemon *d, | ||
46 | const char *emsg) | ||
47 | { | ||
48 | GNUNET_assert (id != NULL); | ||
49 | #if VERBOSE | ||
50 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
51 | "Daemon started, will now stop it.\n"); | ||
52 | #endif | ||
53 | GNUNET_TESTING_daemon_stop (d, &end_cb, NULL); | ||
54 | } | ||
55 | |||
56 | |||
57 | static void | ||
58 | run (void *cls, | ||
59 | struct GNUNET_SCHEDULER_Handle *sched, | ||
60 | char *const *args, | ||
61 | const char *cfgfile, | ||
62 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
63 | { | ||
64 | struct GNUNET_TESTING_Daemon *d; | ||
65 | |||
66 | ok = 1; | ||
67 | #if VERBOSE | ||
68 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
69 | "Starting daemon.\n"); | ||
70 | #endif | ||
71 | d = GNUNET_TESTING_daemon_start (sched, | ||
72 | cfg, | ||
73 | NULL, | ||
74 | &my_cb, | ||
75 | NULL); | ||
76 | GNUNET_assert (d != NULL); | ||
77 | } | ||
78 | |||
79 | static int | ||
80 | check () | ||
81 | { | ||
82 | char *const argv[] = { "test-testing", | ||
83 | "-c", | ||
84 | "test_testing_data.conf", | ||
85 | #if VERBOSE | ||
86 | "-L", "DEBUG", | ||
87 | #endif | ||
88 | NULL | ||
89 | }; | ||
90 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
91 | GNUNET_GETOPT_OPTION_END | ||
92 | }; | ||
93 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | ||
94 | argv, "test-tesing", "nohelp", | ||
95 | options, &run, &ok); | ||
96 | return ok; | ||
97 | } | ||
98 | |||
99 | int | ||
100 | main (int argc, char *argv[]) | ||
101 | { | ||
102 | int ret; | ||
103 | |||
104 | GNUNET_log_setup ("test-testing", | ||
105 | #if VERBOSE | ||
106 | "DEBUG", | ||
107 | #else | ||
108 | "WARNING", | ||
109 | #endif | ||
110 | NULL); | ||
111 | ret = check (); | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | /* end of test_testing.c */ | ||
diff --git a/src/testing/test_testing_data.conf b/src/testing/test_testing_data.conf new file mode 100644 index 000000000..7c46fdf34 --- /dev/null +++ b/src/testing/test_testing_data.conf | |||
@@ -0,0 +1,29 @@ | |||
1 | [PATHS] | ||
2 | SERVICEHOME = /tmp/test-gnunet-testing/ | ||
3 | DEFAULTCONFIG = test_testing_data.conf | ||
4 | |||
5 | [resolver] | ||
6 | PORT = 2564 | ||
7 | |||
8 | [transport] | ||
9 | PORT = 2565 | ||
10 | PLUGINS = tcp | ||
11 | |||
12 | [arm] | ||
13 | PORT = 2566 | ||
14 | DEFAULTSERVICES = transport core | ||
15 | |||
16 | [statistics] | ||
17 | PORT = 2567 | ||
18 | |||
19 | [tcp] | ||
20 | PORT = 2568 | ||
21 | |||
22 | [peerinfo] | ||
23 | PORT = 2569 | ||
24 | |||
25 | [core] | ||
26 | PORT = 2570 | ||
27 | |||
28 | [testing] | ||
29 | WEAKRANDOM = YES | ||
diff --git a/src/testing/testing.c b/src/testing/testing.c index 3406355c5..5d465e05f 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c | |||
@@ -85,7 +85,7 @@ struct GNUNET_TESTING_Daemon | |||
85 | /** | 85 | /** |
86 | * Our configuration. | 86 | * Our configuration. |
87 | */ | 87 | */ |
88 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 88 | struct GNUNET_CONFIGURATION_Handle *cfg; |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * Host to run GNUnet on. | 91 | * Host to run GNUnet on. |
@@ -202,10 +202,11 @@ testing_init (void *cls, | |||
202 | d->cb = NULL; | 202 | d->cb = NULL; |
203 | if (server == NULL) | 203 | if (server == NULL) |
204 | { | 204 | { |
205 | cb (d->cb_cls, NULL, d->cfg, d, | ||
206 | _("Failed to connect to core service\n")); | ||
207 | if (GNUNET_YES == d->dead) | 205 | if (GNUNET_YES == d->dead) |
208 | GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); | 206 | GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); |
207 | else if (NULL != cb) | ||
208 | cb (d->cb_cls, NULL, d->cfg, d, | ||
209 | _("Failed to connect to core service\n")); | ||
209 | return; | 210 | return; |
210 | } | 211 | } |
211 | #if DEBUG_TESTING | 212 | #if DEBUG_TESTING |
@@ -216,7 +217,7 @@ testing_init (void *cls, | |||
216 | d->id = *my_identity; | 217 | d->id = *my_identity; |
217 | if (GNUNET_YES == d->dead) | 218 | if (GNUNET_YES == d->dead) |
218 | GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); | 219 | GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); |
219 | else | 220 | else if (NULL != cb) |
220 | cb (d->cb_cls, my_identity, d->cfg, d, NULL); | 221 | cb (d->cb_cls, my_identity, d->cfg, d, NULL); |
221 | d->server = server; | 222 | d->server = server; |
222 | } | 223 | } |
@@ -240,6 +241,11 @@ start_fsm (void *cls, | |||
240 | unsigned long code; | 241 | unsigned long code; |
241 | char *dst; | 242 | char *dst; |
242 | 243 | ||
244 | #if DEBUG_TESTING | ||
245 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
246 | "Peer FSM is in phase %u.\n", | ||
247 | d->phase); | ||
248 | #endif | ||
243 | d->task = GNUNET_SCHEDULER_NO_TASK; | 249 | d->task = GNUNET_SCHEDULER_NO_TASK; |
244 | switch (d->phase) | 250 | switch (d->phase) |
245 | { | 251 | { |
@@ -255,11 +261,12 @@ start_fsm (void *cls, | |||
255 | { | 261 | { |
256 | cb = d->cb; | 262 | cb = d->cb; |
257 | d->cb = NULL; | 263 | d->cb = NULL; |
258 | cb (d->cb_cls, | 264 | if (NULL != cb) |
259 | NULL, | 265 | cb (d->cb_cls, |
260 | d->cfg, | 266 | NULL, |
261 | d, | 267 | d->cfg, |
262 | _("`scp' does not seem to terminate.\n")); | 268 | d, |
269 | _("`scp' does not seem to terminate.\n")); | ||
263 | return; | 270 | return; |
264 | } | 271 | } |
265 | /* wait some more */ | 272 | /* wait some more */ |
@@ -278,11 +285,12 @@ start_fsm (void *cls, | |||
278 | { | 285 | { |
279 | cb = d->cb; | 286 | cb = d->cb; |
280 | d->cb = NULL; | 287 | d->cb = NULL; |
281 | cb (d->cb_cls, | 288 | if (NULL != cb) |
282 | NULL, | 289 | cb (d->cb_cls, |
283 | d->cfg, | 290 | NULL, |
284 | d, | 291 | d->cfg, |
285 | _("`scp' did not complete cleanly.\n")); | 292 | d, |
293 | _("`scp' did not complete cleanly.\n")); | ||
286 | return; | 294 | return; |
287 | } | 295 | } |
288 | #if DEBUG_TESTING | 296 | #if DEBUG_TESTING |
@@ -299,7 +307,11 @@ start_fsm (void *cls, | |||
299 | "gnunet-service-arm", | 307 | "gnunet-service-arm", |
300 | "-c", | 308 | "-c", |
301 | d->cfgfile, | 309 | d->cfgfile, |
310 | #if DEBUG_TESTING | ||
311 | "-L", "DEBUG", | ||
312 | #else | ||
302 | "-d", | 313 | "-d", |
314 | #endif | ||
303 | NULL); | 315 | NULL); |
304 | } | 316 | } |
305 | else | 317 | else |
@@ -328,16 +340,31 @@ start_fsm (void *cls, | |||
328 | (NULL == d->hostname) ? "gnunet-service-arm" : "ssh"); | 340 | (NULL == d->hostname) ? "gnunet-service-arm" : "ssh"); |
329 | cb = d->cb; | 341 | cb = d->cb; |
330 | d->cb = NULL; | 342 | d->cb = NULL; |
331 | cb (d->cb_cls, | 343 | if (NULL != cb) |
332 | NULL, | 344 | cb (d->cb_cls, |
333 | d->cfg, | 345 | NULL, |
334 | d, | 346 | d->cfg, |
335 | (NULL == d->hostname) | 347 | d, |
336 | ? _("Failed to start `gnunet-service-arm' process.\n") | 348 | (NULL == d->hostname) |
337 | : _("Failed to start `ssh' process.\n")); | 349 | ? _("Failed to start `gnunet-service-arm' process.\n") |
350 | : _("Failed to start `ssh' process.\n")); | ||
338 | } | 351 | } |
352 | #if DEBUG_TESTING | ||
353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
354 | "Started `%s', waiting for `%s' to be up.\n", | ||
355 | "gnunet-service-arm", | ||
356 | "gnunet-service-core"); | ||
357 | #endif | ||
339 | d->phase = SP_START_ARMING; | 358 | d->phase = SP_START_ARMING; |
340 | d->wait_runs = 0; | 359 | d->wait_runs = 0; |
360 | d->task | ||
361 | = GNUNET_SCHEDULER_add_delayed (d->sched, | ||
362 | GNUNET_NO, | ||
363 | GNUNET_SCHEDULER_PRIORITY_KEEP, | ||
364 | GNUNET_SCHEDULER_NO_TASK, | ||
365 | GNUNET_CONSTANTS_EXEC_WAIT, | ||
366 | &start_fsm, | ||
367 | d); | ||
341 | break; | 368 | break; |
342 | case SP_START_ARMING: | 369 | case SP_START_ARMING: |
343 | if (GNUNET_OK != | 370 | if (GNUNET_OK != |
@@ -350,13 +377,14 @@ start_fsm (void *cls, | |||
350 | { | 377 | { |
351 | cb = d->cb; | 378 | cb = d->cb; |
352 | d->cb = NULL; | 379 | d->cb = NULL; |
353 | cb (d->cb_cls, | 380 | if (NULL != cb) |
354 | NULL, | 381 | cb (d->cb_cls, |
355 | d->cfg, | 382 | NULL, |
356 | d, | 383 | d->cfg, |
357 | (NULL == d->hostname) | 384 | d, |
358 | ? _("`gnunet-service-arm' does not seem to terminate.\n") | 385 | (NULL == d->hostname) |
359 | : _("`ssh' does not seem to terminate.\n")); | 386 | ? _("`gnunet-service-arm' does not seem to terminate.\n") |
387 | : _("`ssh' does not seem to terminate.\n")); | ||
360 | return; | 388 | return; |
361 | } | 389 | } |
362 | /* wait some more */ | 390 | /* wait some more */ |
@@ -424,18 +452,24 @@ start_fsm (void *cls, | |||
424 | if ( (type != GNUNET_OS_PROCESS_EXITED) || | 452 | if ( (type != GNUNET_OS_PROCESS_EXITED) || |
425 | (code != 0) ) | 453 | (code != 0) ) |
426 | { | 454 | { |
427 | d->dead_cb (d->dead_cb_cls, | 455 | if (NULL != d->dead_cb) |
428 | _("`sshp' did not complete cleanly.\n")); | 456 | d->dead_cb (d->dead_cb_cls, |
457 | _("`ssh' did not complete cleanly.\n")); | ||
429 | GNUNET_free (d->cfgfile); | 458 | GNUNET_free (d->cfgfile); |
430 | GNUNET_free_non_null (d->hostname); | 459 | GNUNET_free_non_null (d->hostname); |
431 | GNUNET_free_non_null (d->username); | 460 | GNUNET_free_non_null (d->username); |
432 | GNUNET_free (d); | 461 | GNUNET_free (d); |
433 | return; | 462 | return; |
434 | } | 463 | } |
464 | #if DEBUG_TESTING | ||
465 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
466 | "Peer shutdown complete.\n"); | ||
467 | #endif | ||
435 | GNUNET_free (d->cfgfile); | 468 | GNUNET_free (d->cfgfile); |
436 | GNUNET_free_non_null (d->hostname); | 469 | GNUNET_free_non_null (d->hostname); |
437 | GNUNET_free_non_null (d->username); | 470 | GNUNET_free_non_null (d->username); |
438 | d->dead_cb (d->dead_cb_cls, NULL); | 471 | if (NULL != d->dead_cb) |
472 | d->dead_cb (d->dead_cb_cls, NULL); | ||
439 | GNUNET_free (d); | 473 | GNUNET_free (d); |
440 | break; | 474 | break; |
441 | case SP_CONFIG_UPDATE: | 475 | case SP_CONFIG_UPDATE: |
@@ -450,11 +484,12 @@ start_fsm (void *cls, | |||
450 | { | 484 | { |
451 | cb = d->cb; | 485 | cb = d->cb; |
452 | d->cb = NULL; | 486 | d->cb = NULL; |
453 | cb (d->cb_cls, | 487 | if (NULL != cb) |
454 | NULL, | 488 | cb (d->cb_cls, |
455 | d->cfg, | 489 | NULL, |
456 | d, | 490 | d->cfg, |
457 | _("`scp' does not seem to terminate.\n")); | 491 | d, |
492 | _("`scp' does not seem to terminate.\n")); | ||
458 | return; | 493 | return; |
459 | } | 494 | } |
460 | /* wait some more */ | 495 | /* wait some more */ |
@@ -471,15 +506,17 @@ start_fsm (void *cls, | |||
471 | if ( (type != GNUNET_OS_PROCESS_EXITED) || | 506 | if ( (type != GNUNET_OS_PROCESS_EXITED) || |
472 | (code != 0) ) | 507 | (code != 0) ) |
473 | { | 508 | { |
474 | d->update_cb (d->update_cb_cls, | 509 | if (NULL != d->update_cb) |
475 | _("`scp' did not complete cleanly.\n")); | 510 | d->update_cb (d->update_cb_cls, |
511 | _("`scp' did not complete cleanly.\n")); | ||
476 | return; | 512 | return; |
477 | } | 513 | } |
478 | #if DEBUG_TESTING | 514 | #if DEBUG_TESTING |
479 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 515 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
480 | "Successfully copied configuration file.\n"); | 516 | "Successfully copied configuration file.\n"); |
481 | #endif | 517 | #endif |
482 | d->update_cb (d->update_cb_cls, NULL); | 518 | if (NULL != d->update_cb) |
519 | d->update_cb (d->update_cb_cls, NULL); | ||
483 | d->phase = SP_START_DONE; | 520 | d->phase = SP_START_DONE; |
484 | break; | 521 | break; |
485 | } | 522 | } |
@@ -502,7 +539,7 @@ start_fsm (void *cls, | |||
502 | */ | 539 | */ |
503 | struct GNUNET_TESTING_Daemon * | 540 | struct GNUNET_TESTING_Daemon * |
504 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | 541 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, |
505 | struct GNUNET_CONFIGURATION_Handle *cfg, | 542 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
506 | const char *hostname, | 543 | const char *hostname, |
507 | GNUNET_TESTING_NotifyDaemonRunning cb, | 544 | GNUNET_TESTING_NotifyDaemonRunning cb, |
508 | void *cb_cls) | 545 | void *cb_cls) |
@@ -513,9 +550,13 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
513 | 550 | ||
514 | ret = GNUNET_malloc (sizeof(struct GNUNET_TESTING_Daemon)); | 551 | ret = GNUNET_malloc (sizeof(struct GNUNET_TESTING_Daemon)); |
515 | ret->sched = sched; | 552 | ret->sched = sched; |
516 | ret->cfg = cfg; | ||
517 | ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname); | 553 | ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname); |
518 | ret->cfgfile = GNUNET_DISK_mktemp ("gnunet-testing-config"); | 554 | ret->cfgfile = GNUNET_DISK_mktemp ("gnunet-testing-config"); |
555 | #if DEBUG_TESTING | ||
556 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
557 | "Setting up peer with configuration file `%s'.\n", | ||
558 | ret->cfgfile); | ||
559 | #endif | ||
519 | if (NULL == ret->cfgfile) | 560 | if (NULL == ret->cfgfile) |
520 | { | 561 | { |
521 | GNUNET_free_non_null (ret->hostname); | 562 | GNUNET_free_non_null (ret->hostname); |
@@ -524,15 +565,21 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
524 | } | 565 | } |
525 | ret->cb = cb; | 566 | ret->cb = cb; |
526 | ret->cb_cls = cb_cls; | 567 | ret->cb_cls = cb_cls; |
568 | ret->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
569 | GNUNET_CONFIGURATION_set_value_string (ret->cfg, | ||
570 | "PATHS", | ||
571 | "DEFAULTCONFIG", | ||
572 | ret->cfgfile); | ||
527 | /* 1) write configuration to temporary file */ | 573 | /* 1) write configuration to temporary file */ |
528 | if (GNUNET_OK != | 574 | if (GNUNET_OK != |
529 | GNUNET_CONFIGURATION_write (cfg, | 575 | GNUNET_CONFIGURATION_write (ret->cfg, |
530 | ret->cfgfile)) | 576 | ret->cfgfile)) |
531 | { | 577 | { |
532 | if (0 != UNLINK (ret->cfgfile)) | 578 | if (0 != UNLINK (ret->cfgfile)) |
533 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 579 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, |
534 | "unlink", | 580 | "unlink", |
535 | ret->cfgfile); | 581 | ret->cfgfile); |
582 | GNUNET_CONFIGURATION_destroy (ret->cfg); | ||
536 | GNUNET_free_non_null (ret->hostname); | 583 | GNUNET_free_non_null (ret->hostname); |
537 | GNUNET_free (ret->cfgfile); | 584 | GNUNET_free (ret->cfgfile); |
538 | GNUNET_free (ret); | 585 | GNUNET_free (ret); |
@@ -581,6 +628,7 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
581 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 628 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, |
582 | "unlink", | 629 | "unlink", |
583 | ret->cfgfile); | 630 | ret->cfgfile); |
631 | GNUNET_CONFIGURATION_destroy (ret->cfg); | ||
584 | GNUNET_free_non_null (ret->hostname); | 632 | GNUNET_free_non_null (ret->hostname); |
585 | GNUNET_free_non_null (ret->username); | 633 | GNUNET_free_non_null (ret->username); |
586 | GNUNET_free (ret->cfgfile); | 634 | GNUNET_free (ret->cfgfile); |
@@ -589,7 +637,7 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
589 | } | 637 | } |
590 | ret->task | 638 | ret->task |
591 | = GNUNET_SCHEDULER_add_delayed (sched, | 639 | = GNUNET_SCHEDULER_add_delayed (sched, |
592 | GNUNET_NO, | 640 | GNUNET_YES, |
593 | GNUNET_SCHEDULER_PRIORITY_KEEP, | 641 | GNUNET_SCHEDULER_PRIORITY_KEEP, |
594 | GNUNET_SCHEDULER_NO_TASK, | 642 | GNUNET_SCHEDULER_NO_TASK, |
595 | GNUNET_CONSTANTS_EXEC_WAIT, | 643 | GNUNET_CONSTANTS_EXEC_WAIT, |
@@ -597,6 +645,10 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
597 | ret); | 645 | ret); |
598 | return ret; | 646 | return ret; |
599 | } | 647 | } |
648 | #if DEBUG_TESTING | ||
649 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
650 | "No need to copy configuration file since we are running locally.\n"); | ||
651 | #endif | ||
600 | ret->phase = SP_COPIED; | 652 | ret->phase = SP_COPIED; |
601 | GNUNET_SCHEDULER_add_continuation (sched, | 653 | GNUNET_SCHEDULER_add_continuation (sched, |
602 | GNUNET_NO, | 654 | GNUNET_NO, |
@@ -687,7 +739,7 @@ void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, | |||
687 | d->dead_cb_cls = cb_cls; | 739 | d->dead_cb_cls = cb_cls; |
688 | d->task | 740 | d->task |
689 | = GNUNET_SCHEDULER_add_delayed (d->sched, | 741 | = GNUNET_SCHEDULER_add_delayed (d->sched, |
690 | GNUNET_NO, | 742 | GNUNET_YES, |
691 | GNUNET_SCHEDULER_PRIORITY_KEEP, | 743 | GNUNET_SCHEDULER_PRIORITY_KEEP, |
692 | GNUNET_SCHEDULER_NO_TASK, | 744 | GNUNET_SCHEDULER_NO_TASK, |
693 | GNUNET_CONSTANTS_EXEC_WAIT, | 745 | GNUNET_CONSTANTS_EXEC_WAIT, |
@@ -695,11 +747,13 @@ void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, | |||
695 | d); | 747 | d); |
696 | return; | 748 | return; |
697 | } | 749 | } |
750 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
698 | GNUNET_free (d->cfgfile); | 751 | GNUNET_free (d->cfgfile); |
699 | GNUNET_free_non_null (d->hostname); | 752 | GNUNET_free_non_null (d->hostname); |
700 | GNUNET_free_non_null (d->username); | 753 | GNUNET_free_non_null (d->username); |
701 | GNUNET_free (d); | 754 | GNUNET_free (d); |
702 | cb (cb_cls, NULL); | 755 | if (NULL != cb) |
756 | cb (cb_cls, NULL); | ||
703 | } | 757 | } |
704 | 758 | ||
705 | 759 | ||
@@ -720,8 +774,9 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, | |||
720 | 774 | ||
721 | if (d->phase != SP_START_DONE) | 775 | if (d->phase != SP_START_DONE) |
722 | { | 776 | { |
723 | cb (cb_cls, | 777 | if (NULL != cb) |
724 | _("Peer not yet running, can not change configuration at this point.")); | 778 | cb (cb_cls, |
779 | _("Peer not yet running, can not change configuration at this point.")); | ||
725 | return; | 780 | return; |
726 | } | 781 | } |
727 | 782 | ||
@@ -730,7 +785,8 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, | |||
730 | GNUNET_CONFIGURATION_write (cfg, | 785 | GNUNET_CONFIGURATION_write (cfg, |
731 | d->cfgfile)) | 786 | d->cfgfile)) |
732 | { | 787 | { |
733 | cb (cb_cls, | 788 | if (NULL != cb) |
789 | cb (cb_cls, | ||
734 | _("Failed to write new configuration to disk.")); | 790 | _("Failed to write new configuration to disk.")); |
735 | return; | 791 | return; |
736 | } | 792 | } |
@@ -739,7 +795,8 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, | |||
739 | if (NULL == d->hostname) | 795 | if (NULL == d->hostname) |
740 | { | 796 | { |
741 | /* signal success */ | 797 | /* signal success */ |
742 | cb (cb_cls, NULL); | 798 | if (NULL != cb) |
799 | cb (cb_cls, NULL); | ||
743 | return; | 800 | return; |
744 | } | 801 | } |
745 | d->phase = SP_CONFIG_UPDATE; | 802 | d->phase = SP_CONFIG_UPDATE; |
@@ -765,8 +822,9 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, | |||
765 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 822 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
766 | _("Could not start `%s' process to copy configuration file.\n"), | 823 | _("Could not start `%s' process to copy configuration file.\n"), |
767 | "scp"); | 824 | "scp"); |
768 | cb (cb_cls, | 825 | if (NULL != cb) |
769 | _("Failed to copy new configuration to remote machine.")); | 826 | cb (cb_cls, |
827 | _("Failed to copy new configuration to remote machine.")); | ||
770 | d->phase = SP_START_DONE; | 828 | d->phase = SP_START_DONE; |
771 | return; | 829 | return; |
772 | } | 830 | } |
@@ -802,10 +860,14 @@ static size_t | |||
802 | transmit_ready (void *cls, size_t size, void *buf) | 860 | transmit_ready (void *cls, size_t size, void *buf) |
803 | { | 861 | { |
804 | struct ConnectContext *ctx = cls; | 862 | struct ConnectContext *ctx = cls; |
805 | if (buf == NULL) | 863 | |
806 | ctx->cb (ctx->cb_cls, _("Peers failed to connect")); | 864 | if (NULL != ctx->cb) |
807 | else | 865 | { |
808 | ctx->cb (ctx->cb_cls, NULL); | 866 | if (buf == NULL) |
867 | ctx->cb (ctx->cb_cls, _("Peers failed to connect")); | ||
868 | else | ||
869 | ctx->cb (ctx->cb_cls, NULL); | ||
870 | } | ||
809 | GNUNET_free (ctx); | 871 | GNUNET_free (ctx); |
810 | return 0; | 872 | return 0; |
811 | } | 873 | } |
@@ -831,8 +893,9 @@ process_hello (void *cls, | |||
831 | if (peer == NULL) | 893 | if (peer == NULL) |
832 | { | 894 | { |
833 | /* signal error */ | 895 | /* signal error */ |
834 | ctx->cb (ctx->cb_cls, | 896 | if (NULL != ctx->cb) |
835 | _("Failed to receive `HELLO' from peer\n")); | 897 | ctx->cb (ctx->cb_cls, |
898 | _("Failed to receive `HELLO' from peer\n")); | ||
836 | GNUNET_TRANSPORT_disconnect (ctx->d1th); | 899 | GNUNET_TRANSPORT_disconnect (ctx->d1th); |
837 | GNUNET_TRANSPORT_disconnect (ctx->d2th); | 900 | GNUNET_TRANSPORT_disconnect (ctx->d2th); |
838 | GNUNET_free (ctx); | 901 | GNUNET_free (ctx); |
@@ -873,7 +936,8 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
873 | if ( (d1->server == NULL) || | 936 | if ( (d1->server == NULL) || |
874 | (d2->server == NULL) ) | 937 | (d2->server == NULL) ) |
875 | { | 938 | { |
876 | cb (cb_cls, _("Peers are not fully running yet, can not connect!\n")); | 939 | if (NULL != cb) |
940 | cb (cb_cls, _("Peers are not fully running yet, can not connect!\n")); | ||
877 | return; | 941 | return; |
878 | } | 942 | } |
879 | ctx = GNUNET_malloc (sizeof(struct ConnectContext)); | 943 | ctx = GNUNET_malloc (sizeof(struct ConnectContext)); |
@@ -886,7 +950,8 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
886 | if (ctx->d1th == NULL) | 950 | if (ctx->d1th == NULL) |
887 | { | 951 | { |
888 | GNUNET_free (ctx); | 952 | GNUNET_free (ctx); |
889 | cb (cb_cls, _("Failed to connect to transport service!\n")); | 953 | if (NULL != cb) |
954 | cb (cb_cls, _("Failed to connect to transport service!\n")); | ||
890 | return; | 955 | return; |
891 | } | 956 | } |
892 | ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, d2->cfg, d2, NULL, NULL, NULL); | 957 | ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, d2->cfg, d2, NULL, NULL, NULL); |
@@ -894,7 +959,8 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
894 | { | 959 | { |
895 | GNUNET_TRANSPORT_disconnect (ctx->d1th); | 960 | GNUNET_TRANSPORT_disconnect (ctx->d1th); |
896 | GNUNET_free (ctx); | 961 | GNUNET_free (ctx); |
897 | cb (cb_cls, _("Failed to connect to transport service!\n")); | 962 | if (NULL != cb) |
963 | cb (cb_cls, _("Failed to connect to transport service!\n")); | ||
898 | return; | 964 | return; |
899 | } | 965 | } |
900 | GNUNET_TRANSPORT_get_hello (ctx->d1th, | 966 | GNUNET_TRANSPORT_get_hello (ctx->d1th, |
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 917a524de..b87507364 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c | |||
@@ -27,6 +27,58 @@ | |||
27 | #include "gnunet_arm_service.h" | 27 | #include "gnunet_arm_service.h" |
28 | #include "gnunet_testing_lib.h" | 28 | #include "gnunet_testing_lib.h" |
29 | 29 | ||
30 | /** | ||
31 | * Lowest port used for GNUnet testing. Should be high enough to not | ||
32 | * conflict with other applications running on the hosts but be low | ||
33 | * enough to not conflict with client-ports (typically starting around | ||
34 | * 32k). | ||
35 | */ | ||
36 | #define LOW_PORT 10000 | ||
37 | |||
38 | /** | ||
39 | * Highest port used for GNUnet testing. Should be low enough to not | ||
40 | * conflict with the port range for "local" ports (client apps; see | ||
41 | * /proc/sys/net/ipv4/ip_local_port_range on Linux for example). | ||
42 | */ | ||
43 | #define HIGH_PORT 32000 | ||
44 | |||
45 | /** | ||
46 | * Data we keep per peer. | ||
47 | */ | ||
48 | struct PeerData | ||
49 | { | ||
50 | /** | ||
51 | * (Initial) configuration of the host. | ||
52 | * (initial because clients could change | ||
53 | * it and we would not know about those | ||
54 | * updates). | ||
55 | */ | ||
56 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
57 | |||
58 | /** | ||
59 | * Handle for controlling the daemon. | ||
60 | */ | ||
61 | struct GNUNET_TESTING_Daemon *daemon; | ||
62 | }; | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Data we keep per host. | ||
67 | */ | ||
68 | struct HostData | ||
69 | { | ||
70 | /** | ||
71 | * Name of the host. | ||
72 | */ | ||
73 | char *hostname; | ||
74 | |||
75 | /** | ||
76 | * Lowest port that we have not yet used | ||
77 | * for GNUnet. | ||
78 | */ | ||
79 | uint16_t minport; | ||
80 | }; | ||
81 | |||
30 | 82 | ||
31 | /** | 83 | /** |
32 | * Handle to a group of GNUnet peers. | 84 | * Handle to a group of GNUnet peers. |
@@ -41,7 +93,7 @@ struct GNUNET_TESTING_PeerGroup | |||
41 | /** | 93 | /** |
42 | * Configuration template. | 94 | * Configuration template. |
43 | */ | 95 | */ |
44 | struct GNUNET_CONFIGURATION_Handle *cfg; | 96 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
45 | 97 | ||
46 | /** | 98 | /** |
47 | * Function to call on each started daemon. | 99 | * Function to call on each started daemon. |
@@ -54,14 +106,15 @@ struct GNUNET_TESTING_PeerGroup | |||
54 | void *cb_cls; | 106 | void *cb_cls; |
55 | 107 | ||
56 | /** | 108 | /** |
57 | * NULL-terminated array of hostnames. | 109 | * NULL-terminated array of information about |
110 | * hosts. | ||
58 | */ | 111 | */ |
59 | char **hostnames; | 112 | struct HostData *hosts; |
60 | 113 | ||
61 | /** | 114 | /** |
62 | * Array of "total" peers. | 115 | * Array of "total" peers. |
63 | */ | 116 | */ |
64 | struct GNUNET_TESTING_Daemon **peers; | 117 | struct PeerData *peers; |
65 | 118 | ||
66 | /** | 119 | /** |
67 | * Number of peers in this group. | 120 | * Number of peers in this group. |
@@ -71,79 +124,212 @@ struct GNUNET_TESTING_PeerGroup | |||
71 | }; | 124 | }; |
72 | 125 | ||
73 | 126 | ||
127 | struct UpdateContext | ||
128 | { | ||
129 | struct GNUNET_CONFIGURATION_Handle *ret; | ||
130 | unsigned int nport; | ||
131 | }; | ||
132 | |||
74 | /** | 133 | /** |
75 | * Start count gnunetd processes with the same set of transports and | 134 | * Function to iterate over options. Copies |
76 | * applications. The port numbers (any option called "PORT") will be | 135 | * the options to the target configuration, |
77 | * adjusted to ensure that no two peers running on the same system | 136 | * updating PORT values as needed. |
78 | * have the same port(s) in their respective configurations. | ||
79 | * | 137 | * |
80 | * @param sched scheduler to use | 138 | * @param cls closure |
81 | * @param cfg configuration template to use | 139 | * @param section name of the section |
82 | * @param total number of daemons to start | 140 | * @param option name of the option |
83 | * @param cb function to call on each daemon that was started | 141 | * @param value value of the option |
84 | * @param cb_cls closure for cb | ||
85 | * @param hostname where to run the peers; can be NULL (to run | ||
86 | * everything on localhost). | ||
87 | * @param va Additional hosts can be specified using a NULL-terminated list of | ||
88 | * varargs, hosts will then be used round-robin from that | ||
89 | * list; va only contains anything if hostname != NULL. | ||
90 | * @return NULL on error, otherwise handle to control peer group | ||
91 | */ | 142 | */ |
92 | struct GNUNET_TESTING_PeerGroup * | 143 | static void |
93 | GNUNET_TESTING_daemons_start_va (struct GNUNET_SCHEDULER_Handle *sched, | 144 | update_config(void *cls, |
94 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 145 | const char *section, |
95 | unsigned int total, | 146 | const char *option, |
96 | GNUNET_TESTING_NotifyDaemonRunning cb, | 147 | const char *value) |
97 | void *cb_cls, | ||
98 | const char *hostname, | ||
99 | va_list va) | ||
100 | { | 148 | { |
101 | struct GNUNET_TESTING_PeerGroup *pg; | 149 | struct UpdateContext *ctx = cls; |
102 | 150 | unsigned int ival; | |
103 | pg = GNUNET_malloc (sizeof(struct GNUNET_TESTING_PeerGroup)); | 151 | char cval[12]; |
104 | return pg; | 152 | |
153 | if ( (0 == strcmp (option, "PORT")) && | ||
154 | (1 == sscanf (value, "%u", &ival)) ) | ||
155 | { | ||
156 | GNUNET_snprintf (cval, | ||
157 | sizeof(cval), | ||
158 | "%u", | ||
159 | ctx->nport++); | ||
160 | value = cval; | ||
161 | } | ||
162 | GNUNET_CONFIGURATION_set_value_string (ctx->ret, | ||
163 | section, | ||
164 | option, | ||
165 | value); | ||
105 | } | 166 | } |
106 | 167 | ||
107 | 168 | ||
108 | /** | 169 | /** |
109 | * Start count gnunetd processes with the same set of | 170 | * Create a new configuration using the given configuration |
110 | * transports and applications. The port numbers will | 171 | * as a template; however, each PORT in the existing cfg |
111 | * be computed by adding delta each time (zero | 172 | * must be renumbered by incrementing "*port". If we run |
112 | * times for the first peer). | 173 | * out of "*port" numbers, return NULL. |
174 | * | ||
175 | * @param cfg template configuration | ||
176 | * @param port port numbers to use, update to reflect | ||
177 | * port numbers that were used | ||
178 | * @return new configuration, NULL on error | ||
179 | */ | ||
180 | static struct GNUNET_CONFIGURATION_Handle* | ||
181 | make_config (const struct GNUNET_CONFIGURATION_Handle*cfg, | ||
182 | uint16_t *port) | ||
183 | { | ||
184 | struct UpdateContext uc; | ||
185 | uint16_t orig; | ||
186 | |||
187 | orig = *port; | ||
188 | uc.nport = *port; | ||
189 | uc.ret = GNUNET_CONFIGURATION_create (); | ||
190 | GNUNET_CONFIGURATION_iterate (cfg, | ||
191 | &update_config, | ||
192 | &uc); | ||
193 | if (uc.nport >= HIGH_PORT) | ||
194 | { | ||
195 | *port = orig; | ||
196 | GNUNET_CONFIGURATION_destroy (uc.ret); | ||
197 | return NULL; | ||
198 | } | ||
199 | *port = (uint16_t) uc.nport; | ||
200 | return uc.ret; | ||
201 | } | ||
202 | |||
203 | |||
204 | /** | ||
205 | * Start count gnunetd processes with the same set of transports and | ||
206 | * applications. The port numbers (any option called "PORT") will be | ||
207 | * adjusted to ensure that no two peers running on the same system | ||
208 | * have the same port(s) in their respective configurations. | ||
113 | * | 209 | * |
114 | * @param sched scheduler to use | 210 | * @param sched scheduler to use |
115 | * @param cfg configuration template to use | 211 | * @param cfg configuration template to use |
116 | * @param total number of daemons to start | 212 | * @param total number of daemons to start |
117 | * @param timeout how long is this allowed to take? | ||
118 | * @param cb function to call on each daemon that was started | 213 | * @param cb function to call on each daemon that was started |
119 | * @param cb_cls closure for cb | 214 | * @param cb_cls closure for cb |
120 | * @param hostname where to run the peers; can be NULL (to run | 215 | * @param hostnames space-separated list of hostnames to use; can be NULL (to run |
121 | * everything on localhost). Additional | 216 | * everything on localhost). |
122 | * hosts can be specified using a NULL-terminated list of | ||
123 | * varargs, hosts will then be used round-robin from that | ||
124 | * list. | ||
125 | * @return NULL on error, otherwise handle to control peer group | 217 | * @return NULL on error, otherwise handle to control peer group |
126 | */ | 218 | */ |
127 | struct GNUNET_TESTING_PeerGroup * | 219 | struct GNUNET_TESTING_PeerGroup * |
128 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | 220 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, |
129 | struct GNUNET_CONFIGURATION_Handle *cfg, | 221 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
130 | unsigned int total, | 222 | unsigned int total, |
131 | GNUNET_TESTING_NotifyDaemonRunning cb, | 223 | GNUNET_TESTING_NotifyDaemonRunning cb, |
132 | void *cb_cls, | 224 | void *cb_cls, |
133 | const char *hostname, | 225 | const char *hostnames) |
134 | ...) | ||
135 | { | 226 | { |
136 | struct GNUNET_TESTING_PeerGroup * ret; | 227 | struct GNUNET_TESTING_PeerGroup *pg; |
137 | va_list va; | 228 | const char *rpos; |
138 | 229 | char *pos; | |
139 | va_start (va, hostname); | 230 | char *start; |
140 | ret = GNUNET_TESTING_daemons_start_va (sched, cfg, | 231 | const char *hostname; |
141 | total, cb, cb_cls, hostname, | 232 | struct GNUNET_CONFIGURATION_Handle *pcfg; |
142 | va); | 233 | unsigned int off; |
143 | va_end (va); | 234 | unsigned int hostcnt; |
144 | return ret; | 235 | uint16_t minport; |
145 | } | ||
146 | 236 | ||
237 | if (0 == total) | ||
238 | { | ||
239 | GNUNET_break (0); | ||
240 | return NULL; | ||
241 | } | ||
242 | pg = GNUNET_malloc (sizeof(struct GNUNET_TESTING_PeerGroup)); | ||
243 | pg->sched = sched; | ||
244 | pg->cfg = cfg; | ||
245 | pg->cb = cb; | ||
246 | pg->cb_cls = cb_cls; | ||
247 | pg->total = total; | ||
248 | pg->peers = GNUNET_malloc (total * sizeof(struct PeerData)); | ||
249 | if (NULL != hostnames) | ||
250 | { | ||
251 | off = 2; | ||
252 | /* skip leading spaces */ | ||
253 | while ( (0 != *hostnames) && | ||
254 | (isspace(*hostnames))) | ||
255 | hostnames++; | ||
256 | rpos = hostnames; | ||
257 | while ('\0' != *rpos) | ||
258 | { | ||
259 | if (isspace (*rpos)) | ||
260 | off++; | ||
261 | rpos++; | ||
262 | } | ||
263 | pg->hosts = GNUNET_malloc (off * sizeof (struct HostData)); | ||
264 | off = 0; | ||
265 | start = GNUNET_strdup (hostnames); | ||
266 | pos = start; | ||
267 | while ('\0' != *pos) | ||
268 | { | ||
269 | if (isspace (*pos)) | ||
270 | { | ||
271 | *pos = '\0'; | ||
272 | if (strlen(start) > 0) | ||
273 | { | ||
274 | pg->hosts[off].minport = LOW_PORT; | ||
275 | pg->hosts[off++].hostname = start; | ||
276 | } | ||
277 | start = pos+1; | ||
278 | } | ||
279 | pos++; | ||
280 | } | ||
281 | if (strlen(start) > 0) | ||
282 | { | ||
283 | pg->hosts[off].minport = LOW_PORT; | ||
284 | pg->hosts[off++].hostname = start; | ||
285 | } | ||
286 | if (off == 0) | ||
287 | { | ||
288 | GNUNET_free (start); | ||
289 | GNUNET_free (pg->hosts); | ||
290 | pg->hosts = NULL; | ||
291 | } | ||
292 | hostcnt = off; | ||
293 | minport = 0; /* make gcc happy */ | ||
294 | } | ||
295 | else | ||
296 | { | ||
297 | hostcnt = 0; | ||
298 | minport = LOW_PORT; | ||
299 | } | ||
300 | for (off = 0; off < total; off++) | ||
301 | { | ||
302 | if (hostcnt > 0) | ||
303 | { | ||
304 | hostname = pg->hosts[off % hostcnt].hostname; | ||
305 | pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport); | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | hostname = NULL; | ||
310 | pcfg = make_config (cfg, &minport); | ||
311 | } | ||
312 | if (NULL == pcfg) | ||
313 | { | ||
314 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
315 | _("Could not create configuration for peer number %u on `%s'!\n"), | ||
316 | off, | ||
317 | hostname == NULL ? "localhost" : hostname); | ||
318 | continue; | ||
319 | } | ||
320 | pg->peers[off].cfg = pcfg; | ||
321 | pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched, | ||
322 | pcfg, | ||
323 | hostname, | ||
324 | cb, | ||
325 | cb_cls); | ||
326 | if (NULL == pg->peers[off].daemon) | ||
327 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
328 | _("Could not start peer number %u!\n"), | ||
329 | off); | ||
330 | } | ||
331 | return pg; | ||
332 | } | ||
147 | 333 | ||
148 | 334 | ||
149 | /** | 335 | /** |
@@ -154,7 +340,26 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
154 | void | 340 | void |
155 | GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) | 341 | GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) |
156 | { | 342 | { |
157 | 343 | unsigned int off; | |
344 | |||
345 | for (off = 0; off < pg->total; off++) | ||
346 | { | ||
347 | /* FIXME: should we wait for our | ||
348 | continuations to be called here? This | ||
349 | would require us to take a continuation | ||
350 | as well... */ | ||
351 | if (NULL != pg->peers[off].daemon) | ||
352 | GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, | ||
353 | NULL, NULL); | ||
354 | if (NULL != pg->peers[off].cfg) | ||
355 | GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); | ||
356 | } | ||
357 | GNUNET_free (pg->peers); | ||
358 | if (NULL != pg->hosts) | ||
359 | { | ||
360 | GNUNET_free (pg->hosts[0].hostname); | ||
361 | GNUNET_free (pg->hosts); | ||
362 | } | ||
158 | GNUNET_free (pg); | 363 | GNUNET_free (pg); |
159 | } | 364 | } |
160 | 365 | ||
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c index a67023542..12171139e 100644 --- a/src/topology/gnunet-daemon-topology.c +++ b/src/topology/gnunet-daemon-topology.c | |||
@@ -508,7 +508,7 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello) | |||
508 | &have_address); | 508 | &have_address); |
509 | if (GNUNET_NO == have_address) | 509 | if (GNUNET_NO == have_address) |
510 | return; /* no point in advertising this one... */ | 510 | return; /* no point in advertising this one... */ |
511 | GNUNET_HELLO_get_id (hello, &pid); | 511 | GNUNET_break (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid)); |
512 | pos = hellos; | 512 | pos = hellos; |
513 | while (pos != NULL) | 513 | while (pos != NULL) |
514 | { | 514 | { |
@@ -736,11 +736,18 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
736 | unsigned int entries_found; | 736 | unsigned int entries_found; |
737 | struct PeerList *fl; | 737 | struct PeerList *fl; |
738 | 738 | ||
739 | fn = NULL; | 739 | if (GNUNET_OK != |
740 | GNUNET_CONFIGURATION_get_value_filename (cfg, | 740 | GNUNET_CONFIGURATION_get_value_filename (cfg, |
741 | "TOPOLOGY", | 741 | "TOPOLOGY", |
742 | "FRIENDS", | 742 | "FRIENDS", |
743 | &fn); | 743 | &fn)) |
744 | { | ||
745 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
746 | _("Option `%s' in section `%s' not specified!\n"), | ||
747 | "FRIENDS", | ||
748 | "TOPOLOGY"); | ||
749 | return; | ||
750 | } | ||
744 | if (GNUNET_OK != GNUNET_DISK_file_test (fn)) | 751 | if (GNUNET_OK != GNUNET_DISK_file_test (fn)) |
745 | GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ | 752 | GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ |
746 | | GNUNET_DISK_PERM_USER_WRITE); | 753 | | GNUNET_DISK_PERM_USER_WRITE); |
@@ -920,7 +927,7 @@ hello_advertising (void *cls, | |||
920 | if (0 == GNUNET_TIME_absolute_get_remaining (pos->expiration).value) | 927 | if (0 == GNUNET_TIME_absolute_get_remaining (pos->expiration).value) |
921 | { | 928 | { |
922 | /* time to discard... */ | 929 | /* time to discard... */ |
923 | if (prev == NULL) | 930 | if (prev != NULL) |
924 | prev->next = next; | 931 | prev->next = next; |
925 | else | 932 | else |
926 | hellos = next; | 933 | hellos = next; |
@@ -1015,17 +1022,19 @@ run (void *cls, | |||
1015 | friends_only = GNUNET_CONFIGURATION_get_value_yesno (cfg, | 1022 | friends_only = GNUNET_CONFIGURATION_get_value_yesno (cfg, |
1016 | "TOPOLOGY", | 1023 | "TOPOLOGY", |
1017 | "FRIENDS-ONLY"); | 1024 | "FRIENDS-ONLY"); |
1018 | opt = 0; | 1025 | if (GNUNET_OK != |
1019 | GNUNET_CONFIGURATION_get_value_number (cfg, | 1026 | GNUNET_CONFIGURATION_get_value_number (cfg, |
1020 | "TOPOLOGY", | 1027 | "TOPOLOGY", |
1021 | "MINIMUM-FRIENDS", | 1028 | "MINIMUM-FRIENDS", |
1022 | &opt); | 1029 | &opt)) |
1030 | opt = 0; | ||
1023 | minimum_friend_count = (unsigned int) opt; | 1031 | minimum_friend_count = (unsigned int) opt; |
1024 | opt = 16; | 1032 | if (GNUNET_OK != |
1025 | GNUNET_CONFIGURATION_get_value_number (cfg, | 1033 | GNUNET_CONFIGURATION_get_value_number (cfg, |
1026 | "TOPOLOGY", | 1034 | "TOPOLOGY", |
1027 | "TARGET-CONNECTION-COUNT", | 1035 | "TARGET-CONNECTION-COUNT", |
1028 | &opt); | 1036 | &opt)) |
1037 | opt = 16; | ||
1029 | target_connection_count = (unsigned int) opt; | 1038 | target_connection_count = (unsigned int) opt; |
1030 | 1039 | ||
1031 | if ( (friends_only == GNUNET_YES) || | 1040 | if ( (friends_only == GNUNET_YES) || |
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index d97cb15eb..2b1e82d21 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c | |||
@@ -2132,7 +2132,8 @@ plugin_env_receive (void *cls, | |||
2132 | _ | 2132 | _ |
2133 | ("Dropping incoming message due to repeated bandwidth quota violations.\n")); | 2133 | ("Dropping incoming message due to repeated bandwidth quota violations.\n")); |
2134 | /* TODO: call stats */ | 2134 | /* TODO: call stats */ |
2135 | GNUNET_assert (NULL != service_context->neighbour); | 2135 | GNUNET_assert ( (service_context == NULL) || |
2136 | (NULL != service_context->neighbour) ); | ||
2136 | return service_context; | 2137 | return service_context; |
2137 | } | 2138 | } |
2138 | switch (ntohs (message->type)) | 2139 | switch (ntohs (message->type)) |
diff --git a/src/util/configuration.c b/src/util/configuration.c index 769d2aadc..ff177d966 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c | |||
@@ -315,6 +315,49 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *data, | |||
315 | } | 315 | } |
316 | 316 | ||
317 | 317 | ||
318 | void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
319 | GNUNET_CONFIGURATION_Iterator iter, | ||
320 | void *iter_cls) | ||
321 | { | ||
322 | struct ConfigSection *spos; | ||
323 | struct ConfigEntry *epos; | ||
324 | |||
325 | spos = cfg->sections; | ||
326 | while (spos != NULL) | ||
327 | { | ||
328 | epos = spos->entries; | ||
329 | while (epos != NULL) | ||
330 | { | ||
331 | iter (iter_cls, spos->name, epos->key, epos->val); | ||
332 | epos = epos->next; | ||
333 | } | ||
334 | spos = spos->next; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | |||
339 | static void | ||
340 | copy_entry (void *cls, | ||
341 | const char *section, | ||
342 | const char *option, | ||
343 | const char *value) | ||
344 | { | ||
345 | struct GNUNET_CONFIGURATION_Handle *dst = cls; | ||
346 | GNUNET_CONFIGURATION_set_value_string (dst, section, option, value); | ||
347 | } | ||
348 | |||
349 | |||
350 | struct GNUNET_CONFIGURATION_Handle * | ||
351 | GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
352 | { | ||
353 | struct GNUNET_CONFIGURATION_Handle *ret; | ||
354 | |||
355 | ret = GNUNET_CONFIGURATION_create (); | ||
356 | GNUNET_CONFIGURATION_iterate (cfg, ©_entry, ret); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | |||
318 | static struct ConfigSection * | 361 | static struct ConfigSection * |
319 | findSection (const struct GNUNET_CONFIGURATION_Handle *data, const char *section) | 362 | findSection (const struct GNUNET_CONFIGURATION_Handle *data, const char *section) |
320 | { | 363 | { |
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c index b79de57d2..6265fc142 100644 --- a/src/util/container_meta_data.c +++ b/src/util/container_meta_data.c | |||
@@ -187,8 +187,9 @@ GNUNET_CONTAINER_meta_data_get_contents (const struct | |||
187 | if (!EXTRACTOR_isBinaryType (md->items[i].type)) | 187 | if (!EXTRACTOR_isBinaryType (md->items[i].type)) |
188 | { | 188 | { |
189 | if ((iterator != NULL) && | 189 | if ((iterator != NULL) && |
190 | (GNUNET_OK != iterator (md->items[i].type, | 190 | (GNUNET_OK != iterator (closure, |
191 | md->items[i].data, closure))) | 191 | md->items[i].type, |
192 | md->items[i].data))) | ||
192 | return GNUNET_SYSERR; | 193 | return GNUNET_SYSERR; |
193 | } | 194 | } |
194 | else | 195 | else |
diff --git a/src/util/crypto_ksk.c b/src/util/crypto_ksk.c index 45f11f8fe..170974b2f 100644 --- a/src/util/crypto_ksk.c +++ b/src/util/crypto_ksk.c | |||
@@ -790,7 +790,9 @@ entropy_generator (void *cls, | |||
790 | { | 790 | { |
791 | if (genproc != 0) | 791 | if (genproc != 0) |
792 | { | 792 | { |
793 | PLIBC_KILL(genproc, SIGTERM); | 793 | if (0 != PLIBC_KILL(genproc, SIGTERM)) |
794 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
795 | "kill"); | ||
794 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); | 796 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); |
795 | genproc = 0; | 797 | genproc = 0; |
796 | } | 798 | } |
@@ -808,7 +810,9 @@ entropy_generator (void *cls, | |||
808 | GNUNET_break (0); | 810 | GNUNET_break (0); |
809 | return; | 811 | return; |
810 | } | 812 | } |
811 | PLIBC_KILL(genproc, SIGTERM); | 813 | if (0 != PLIBC_KILL(genproc, SIGTERM)) |
814 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
815 | "kill"); | ||
812 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); | 816 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); |
813 | genproc = 0; | 817 | genproc = 0; |
814 | } | 818 | } |
diff --git a/src/util/disk.c b/src/util/disk.c index 738839807..08f14caf6 100644 --- a/src/util/disk.c +++ b/src/util/disk.c | |||
@@ -234,7 +234,10 @@ GNUNET_DISK_mktemp (const char *template) | |||
234 | GNUNET_free (fn); | 234 | GNUNET_free (fn); |
235 | return NULL; | 235 | return NULL; |
236 | } | 236 | } |
237 | CLOSE (fd); | 237 | if (0 != CLOSE (fd)) |
238 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
239 | "close", | ||
240 | fn); | ||
238 | return fn; | 241 | return fn; |
239 | } | 242 | } |
240 | 243 | ||
@@ -1043,6 +1046,7 @@ GNUNET_DISK_file_open (const char *fn, int flags, ...) | |||
1043 | else | 1046 | else |
1044 | { | 1047 | { |
1045 | GNUNET_break (0); | 1048 | GNUNET_break (0); |
1049 | GNUNET_free (expfn); | ||
1046 | return NULL; | 1050 | return NULL; |
1047 | } | 1051 | } |
1048 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) | 1052 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) |