diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-08-06 20:46:22 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-08-06 20:46:22 +0000 |
commit | 303ab4dafbc680b1b362f95df5b12dae831b1593 (patch) | |
tree | 8b2f411b0b31e500ce2988404b2501db03bed945 /src/fs/fs_namespace.c | |
parent | 1360f8a1e5877a8796dc8e7d0c55d78481382e80 (diff) | |
download | gnunet-303ab4dafbc680b1b362f95df5b12dae831b1593.tar.gz gnunet-303ab4dafbc680b1b362f95df5b12dae831b1593.zip |
-fixing main FS build, updating man page of gnunet-pseudonym
Diffstat (limited to 'src/fs/fs_namespace.c')
-rw-r--r-- | src/fs/fs_namespace.c | 772 |
1 files changed, 256 insertions, 516 deletions
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c index d456dc34b..8537ba0e6 100644 --- a/src/fs/fs_namespace.c +++ b/src/fs/fs_namespace.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Christian Grothoff (and other contributing authors) | 3 | (C) 2003-2013 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file fs/fs_namespace.c | 22 | * @file fs/fs_namespace.c |
23 | * @brief create and destroy namespaces | 23 | * @brief publishing to namespaces, and tracking updateable entries |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | */ | 25 | */ |
26 | #include "platform.h" | 26 | #include "platform.h" |
@@ -29,30 +29,91 @@ | |||
29 | #include "gnunet_util_lib.h" | 29 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_fs_service.h" | 30 | #include "gnunet_fs_service.h" |
31 | #include "fs_api.h" | 31 | #include "fs_api.h" |
32 | #include "fs_publish_ublock.h" | ||
32 | 33 | ||
33 | 34 | ||
34 | /** | 35 | /** |
35 | * Return the name of the directory in which we store | 36 | * Information about an (updateable) node in the |
36 | * our local namespaces (or rather, their public keys). | 37 | * namespace. |
37 | * | ||
38 | * @param h global fs handle | ||
39 | * @return NULL on error, otherwise the name of the directory | ||
40 | */ | 38 | */ |
41 | static char * | 39 | struct NamespaceUpdateNode |
42 | get_namespace_directory (struct GNUNET_FS_Handle *h) | ||
43 | { | 40 | { |
44 | char *dn; | 41 | /** |
42 | * Identifier for this node. | ||
43 | */ | ||
44 | char *id; | ||
45 | 45 | ||
46 | if (GNUNET_OK != | 46 | /** |
47 | GNUNET_CONFIGURATION_get_value_filename (h->cfg, "FS", "IDENTITY_DIR", | 47 | * Identifier of children of this node. |
48 | &dn)) | 48 | */ |
49 | { | 49 | char *update; |
50 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | 50 | |
51 | "fs", "IDENTITY_DIR"); | 51 | /** |
52 | return NULL; | 52 | * Metadata for this entry. |
53 | } | 53 | */ |
54 | return dn; | 54 | struct GNUNET_CONTAINER_MetaData *md; |
55 | } | 55 | |
56 | /** | ||
57 | * URI of this entry in the namespace. | ||
58 | */ | ||
59 | struct GNUNET_FS_Uri *uri; | ||
60 | |||
61 | /** | ||
62 | * Namespace update generation ID. Used to ensure | ||
63 | * freshness of the tree_id. | ||
64 | */ | ||
65 | unsigned int nug; | ||
66 | |||
67 | /** | ||
68 | * TREE this entry belongs to (if nug is current). | ||
69 | */ | ||
70 | unsigned int tree_id; | ||
71 | |||
72 | }; | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Handle to update information for a namespace. | ||
77 | */ | ||
78 | struct GNUNET_FS_UpdateInformationGraph | ||
79 | { | ||
80 | |||
81 | /** | ||
82 | * Handle to the FS service context. | ||
83 | */ | ||
84 | struct GNUNET_FS_Handle *h; | ||
85 | |||
86 | /** | ||
87 | * Array with information about nodes in the namespace. | ||
88 | */ | ||
89 | struct NamespaceUpdateNode **update_nodes; | ||
90 | |||
91 | /** | ||
92 | * Private key for the namespace. | ||
93 | */ | ||
94 | struct GNUNET_CRYPTO_EccPrivateKey ns; | ||
95 | |||
96 | /** | ||
97 | * Hash map mapping identifiers of update nodes | ||
98 | * to the update nodes (initialized on-demand). | ||
99 | */ | ||
100 | struct GNUNET_CONTAINER_MultiHashMap *update_map; | ||
101 | |||
102 | /** | ||
103 | * Size of the update nodes array. | ||
104 | */ | ||
105 | unsigned int update_node_count; | ||
106 | |||
107 | /** | ||
108 | * Reference counter. | ||
109 | */ | ||
110 | unsigned int rc; | ||
111 | |||
112 | /** | ||
113 | * Generator for unique nug numbers. | ||
114 | */ | ||
115 | unsigned int nug_gen; | ||
116 | }; | ||
56 | 117 | ||
57 | 118 | ||
58 | /** | 119 | /** |
@@ -63,32 +124,71 @@ get_namespace_directory (struct GNUNET_FS_Handle *h) | |||
63 | * @return NULL on error, otherwise the name of the directory | 124 | * @return NULL on error, otherwise the name of the directory |
64 | */ | 125 | */ |
65 | static char * | 126 | static char * |
66 | get_update_information_directory (struct GNUNET_FS_Namespace *ns) | 127 | get_update_information_directory (struct GNUNET_FS_Handle *h, |
128 | const struct GNUNET_CRYPTO_EccPrivateKey *ns) | ||
67 | { | 129 | { |
68 | char *dn; | 130 | char *dn; |
69 | char *ret; | 131 | char *ret; |
132 | struct GNUNET_CRYPTO_EccPublicKey pub; | ||
133 | struct GNUNET_CRYPTO_ShortHashCode hc; | ||
134 | struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; | ||
70 | 135 | ||
71 | if (GNUNET_OK != | 136 | if (GNUNET_OK != |
72 | GNUNET_CONFIGURATION_get_value_filename (ns->h->cfg, "FS", "UPDATE_DIR", | 137 | GNUNET_CONFIGURATION_get_value_filename (h->cfg, "FS", "UPDATE_DIR", |
73 | &dn)) | 138 | &dn)) |
74 | { | 139 | { |
75 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | 140 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, |
76 | "fs", "UPDATE_DIR"); | 141 | "fs", "UPDATE_DIR"); |
77 | return NULL; | 142 | return NULL; |
78 | } | 143 | } |
79 | GNUNET_asprintf (&ret, "%s%s%s", dn, DIR_SEPARATOR_STR, ns->name); | 144 | GNUNET_CRYPTO_ecc_key_get_public (ns, &pub); |
145 | GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &hc); | ||
146 | GNUNET_CRYPTO_short_hash_to_enc (&hc, | ||
147 | &enc); | ||
148 | GNUNET_asprintf (&ret, "%s%s%s", | ||
149 | dn, | ||
150 | DIR_SEPARATOR_STR, | ||
151 | (const char *) enc.short_encoding); | ||
80 | GNUNET_free (dn); | 152 | GNUNET_free (dn); |
81 | return ret; | 153 | return ret; |
82 | } | 154 | } |
83 | 155 | ||
84 | 156 | ||
85 | /** | 157 | /** |
158 | * Release memory occupied by UIG datastructure. | ||
159 | * | ||
160 | * @param uig data structure to free | ||
161 | */ | ||
162 | static void | ||
163 | free_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig) | ||
164 | { | ||
165 | unsigned int i; | ||
166 | struct NamespaceUpdateNode *nsn; | ||
167 | |||
168 | for (i = 0; i < uig->update_node_count; i++) | ||
169 | { | ||
170 | nsn = uig->update_nodes[i]; | ||
171 | GNUNET_CONTAINER_meta_data_destroy (nsn->md); | ||
172 | GNUNET_FS_uri_destroy (nsn->uri); | ||
173 | GNUNET_free (nsn->id); | ||
174 | GNUNET_free (nsn->update); | ||
175 | GNUNET_free (nsn); | ||
176 | } | ||
177 | GNUNET_array_grow (uig->update_nodes, uig->update_node_count, | ||
178 | 0); | ||
179 | if (NULL != uig->update_map) | ||
180 | GNUNET_CONTAINER_multihashmap_destroy (uig->update_map); | ||
181 | GNUNET_free (uig); | ||
182 | } | ||
183 | |||
184 | |||
185 | /** | ||
86 | * Write the namespace update node graph to a file. | 186 | * Write the namespace update node graph to a file. |
87 | * | 187 | * |
88 | * @param ns namespace to dump | 188 | * @param ns namespace to dump |
89 | */ | 189 | */ |
90 | static void | 190 | static void |
91 | write_update_information_graph (struct GNUNET_FS_Namespace *ns) | 191 | write_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig) |
92 | { | 192 | { |
93 | char *fn; | 193 | char *fn; |
94 | struct GNUNET_BIO_WriteHandle *wh; | 194 | struct GNUNET_BIO_WriteHandle *wh; |
@@ -96,7 +196,8 @@ write_update_information_graph (struct GNUNET_FS_Namespace *ns) | |||
96 | struct NamespaceUpdateNode *n; | 196 | struct NamespaceUpdateNode *n; |
97 | char *uris; | 197 | char *uris; |
98 | 198 | ||
99 | fn = get_update_information_directory (ns); | 199 | fn = get_update_information_directory (uig->h, |
200 | &uig->ns); | ||
100 | wh = GNUNET_BIO_write_open (fn); | 201 | wh = GNUNET_BIO_write_open (fn); |
101 | if (NULL == wh) | 202 | if (NULL == wh) |
102 | { | 203 | { |
@@ -105,11 +206,11 @@ write_update_information_graph (struct GNUNET_FS_Namespace *ns) | |||
105 | GNUNET_free (fn); | 206 | GNUNET_free (fn); |
106 | return; | 207 | return; |
107 | } | 208 | } |
108 | if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, ns->update_node_count)) | 209 | if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, uig->update_node_count)) |
109 | goto END; | 210 | goto END; |
110 | for (i = 0; i < ns->update_node_count; i++) | 211 | for (i = 0; i < uig->update_node_count; i++) |
111 | { | 212 | { |
112 | n = ns->update_nodes[i]; | 213 | n = uig->update_nodes[i]; |
113 | uris = GNUNET_FS_uri_to_string (n->uri); | 214 | uris = GNUNET_FS_uri_to_string (n->uri); |
114 | if ((GNUNET_OK != GNUNET_BIO_write_string (wh, n->id)) || | 215 | if ((GNUNET_OK != GNUNET_BIO_write_string (wh, n->id)) || |
115 | (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, n->md)) || | 216 | (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, n->md)) || |
@@ -132,11 +233,15 @@ END: | |||
132 | /** | 233 | /** |
133 | * Read the namespace update node graph from a file. | 234 | * Read the namespace update node graph from a file. |
134 | * | 235 | * |
236 | * @param h FS handle to use | ||
135 | * @param ns namespace to read | 237 | * @param ns namespace to read |
238 | * @return update graph, never NULL | ||
136 | */ | 239 | */ |
137 | static void | 240 | static struct GNUNET_FS_UpdateInformationGraph * |
138 | read_update_information_graph (struct GNUNET_FS_Namespace *ns) | 241 | read_update_information_graph (struct GNUNET_FS_Handle *h, |
242 | const struct GNUNET_CRYPTO_EccPrivateKey *ns) | ||
139 | { | 243 | { |
244 | struct GNUNET_FS_UpdateInformationGraph *uig; | ||
140 | char *fn; | 245 | char *fn; |
141 | struct GNUNET_BIO_ReadHandle *rh; | 246 | struct GNUNET_BIO_ReadHandle *rh; |
142 | unsigned int i; | 247 | unsigned int i; |
@@ -145,40 +250,43 @@ read_update_information_graph (struct GNUNET_FS_Namespace *ns) | |||
145 | uint32_t count; | 250 | uint32_t count; |
146 | char *emsg; | 251 | char *emsg; |
147 | 252 | ||
148 | fn = get_update_information_directory (ns); | 253 | uig = GNUNET_new (struct GNUNET_FS_UpdateInformationGraph); |
254 | uig->h = h; | ||
255 | uig->ns = *ns; | ||
256 | fn = get_update_information_directory (h, ns); | ||
149 | if (GNUNET_YES != GNUNET_DISK_file_test (fn)) | 257 | if (GNUNET_YES != GNUNET_DISK_file_test (fn)) |
150 | { | 258 | { |
151 | GNUNET_free (fn); | 259 | GNUNET_free (fn); |
152 | return; | 260 | return uig; |
153 | } | 261 | } |
154 | rh = GNUNET_BIO_read_open (fn); | 262 | rh = GNUNET_BIO_read_open (fn); |
155 | if (NULL == rh) | 263 | if (NULL == rh) |
156 | { | 264 | { |
157 | GNUNET_free (fn); | 265 | GNUNET_free (fn); |
158 | return; | 266 | return uig; |
159 | } | 267 | } |
160 | if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &count)) | 268 | if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &count)) |
161 | { | 269 | { |
162 | GNUNET_break (0); | 270 | GNUNET_break (0); |
163 | goto END; | 271 | goto ERROR; |
164 | } | 272 | } |
165 | if (count > 1024 * 1024) | 273 | if (count > 1024 * 1024) |
166 | { | 274 | { |
167 | GNUNET_break (0); | 275 | GNUNET_break (0); |
168 | goto END; | 276 | goto ERROR; |
169 | } | 277 | } |
170 | if (0 == count) | 278 | if (0 == count) |
171 | { | 279 | { |
172 | GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL)); | 280 | GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL)); |
173 | GNUNET_free (fn); | 281 | GNUNET_free (fn); |
174 | return; | 282 | return uig; |
175 | } | 283 | } |
176 | ns->update_nodes = | 284 | uig->update_nodes = |
177 | GNUNET_malloc (count * sizeof (struct NamespaceUpdateNode *)); | 285 | GNUNET_malloc (count * sizeof (struct NamespaceUpdateNode *)); |
178 | 286 | ||
179 | for (i = 0; i < count; i++) | 287 | for (i = 0; i < count; i++) |
180 | { | 288 | { |
181 | n = GNUNET_malloc (sizeof (struct NamespaceUpdateNode)); | 289 | n = GNUNET_new (struct NamespaceUpdateNode); |
182 | if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "identifier", &n->id, 1024)) | 290 | if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "identifier", &n->id, 1024)) |
183 | || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "meta", &n->md)) || | 291 | || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "meta", &n->md)) || |
184 | (GNUNET_OK != | 292 | (GNUNET_OK != |
@@ -205,304 +313,25 @@ read_update_information_graph (struct GNUNET_FS_Namespace *ns) | |||
205 | GNUNET_free (n); | 313 | GNUNET_free (n); |
206 | break; | 314 | break; |
207 | } | 315 | } |
208 | ns->update_nodes[i] = n; | 316 | uig->update_nodes[i] = n; |
209 | } | 317 | } |
210 | ns->update_node_count = i; | 318 | uig->update_node_count = i; |
211 | END: | ||
212 | if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) | 319 | if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) |
213 | { | 320 | { |
214 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write `%s': %s\n"), emsg); | 321 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read `%s': %s\n"), |
322 | fn, emsg); | ||
215 | GNUNET_free (emsg); | 323 | GNUNET_free (emsg); |
216 | } | 324 | } |
217 | GNUNET_free (fn); | 325 | return uig; |
218 | } | 326 | ERROR: |
219 | 327 | if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) | |
220 | |||
221 | /** | ||
222 | * Create a namespace with the given name; if one already | ||
223 | * exists, return a handle to the existing namespace. | ||
224 | * | ||
225 | * @param h handle to the file sharing subsystem | ||
226 | * @param name name to use for the namespace | ||
227 | * @return handle to the namespace, NULL on error (i.e. invalid filename) | ||
228 | */ | ||
229 | struct GNUNET_FS_Namespace * | ||
230 | GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h, const char *name) | ||
231 | { | ||
232 | char *dn; | ||
233 | char *fn; | ||
234 | struct GNUNET_FS_Namespace *ret; | ||
235 | |||
236 | dn = get_namespace_directory (h); | ||
237 | if (NULL == dn) | ||
238 | { | ||
239 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
240 | _("Can't determine where namespace directory is\n")); | ||
241 | return NULL; | ||
242 | } | ||
243 | GNUNET_asprintf (&fn, "%s%s%s", dn, DIR_SEPARATOR_STR, name); | ||
244 | GNUNET_free (dn); | ||
245 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); | ||
246 | ret->h = h; | ||
247 | ret->rc = 1; | ||
248 | ret->key = GNUNET_FS_pseudonym_create (fn); | ||
249 | if (NULL == ret->key) | ||
250 | { | ||
251 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
252 | _("Failed to create or read private key for namespace `%s'\n"), | ||
253 | name); | ||
254 | GNUNET_free (ret); | ||
255 | GNUNET_free (fn); | ||
256 | return NULL; | ||
257 | } | ||
258 | ret->name = GNUNET_strdup (name); | ||
259 | ret->filename = fn; | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | |||
264 | /** | ||
265 | * Open the namespace with the given name; if it does not exist, | ||
266 | * or the key file is corrupted, the function fails. | ||
267 | * | ||
268 | * @param h handle to the file sharing subsystem | ||
269 | * @param name name of the namespace | ||
270 | * @return handle to the namespace, | ||
271 | * NULL on error (i.e. invalid filename, non-existent filename) | ||
272 | */ | ||
273 | struct GNUNET_FS_Namespace * | ||
274 | GNUNET_FS_namespace_open_existing (struct GNUNET_FS_Handle *h, const char *name) | ||
275 | { | ||
276 | char *dn; | ||
277 | char *fn; | ||
278 | struct GNUNET_FS_Namespace *ret; | ||
279 | |||
280 | dn = get_namespace_directory (h); | ||
281 | if (NULL == dn) | ||
282 | { | ||
283 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
284 | _("Can't determine where namespace directory is\n")); | ||
285 | return NULL; | ||
286 | } | ||
287 | GNUNET_asprintf (&fn, "%s%s%s", dn, DIR_SEPARATOR_STR, name); | ||
288 | GNUNET_free (dn); | ||
289 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); | ||
290 | ret->h = h; | ||
291 | ret->rc = 1; | ||
292 | ret->key = GNUNET_FS_pseudonym_create_from_existing_file (fn); | ||
293 | if (NULL == ret->key) | ||
294 | { | ||
295 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
296 | _("Failed to read private key for namespace `%s'\n"), name); | ||
297 | GNUNET_free (ret); | ||
298 | GNUNET_free (fn); | ||
299 | return NULL; | ||
300 | } | ||
301 | ret->name = GNUNET_strdup (name); | ||
302 | ret->filename = fn; | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | |||
307 | /** | ||
308 | * Rename a local namespace. | ||
309 | * | ||
310 | * @param h handle to the file sharing subsystem | ||
311 | * @param old_name old name of the namespace | ||
312 | * @param new_name new name of the namespace | ||
313 | * @return GNUNET_OK on success, GNUNET_SYSERR on error (see errno for details) | ||
314 | */ | ||
315 | int | ||
316 | GNUNET_FS_namespace_rename (struct GNUNET_FS_Handle *h, | ||
317 | const char *old_name, | ||
318 | const char *new_name) | ||
319 | { | ||
320 | char *dn; | ||
321 | char *fn_old; | ||
322 | char *fn_new; | ||
323 | int result; | ||
324 | int save_errno; | ||
325 | |||
326 | dn = get_namespace_directory (h); | ||
327 | if (NULL == dn) | ||
328 | { | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
330 | _("Can't determine where namespace directory is\n")); | ||
331 | return GNUNET_SYSERR; | ||
332 | } | ||
333 | GNUNET_asprintf (&fn_old, "%s%s%s", dn, DIR_SEPARATOR_STR, old_name); | ||
334 | GNUNET_asprintf (&fn_new, "%s%s%s", dn, DIR_SEPARATOR_STR, new_name); | ||
335 | GNUNET_free (dn); | ||
336 | result = RENAME (fn_old, fn_new); | ||
337 | save_errno = errno; | ||
338 | GNUNET_free (fn_old); | ||
339 | GNUNET_free (fn_new); | ||
340 | errno = save_errno; | ||
341 | if (result == 0) | ||
342 | return GNUNET_OK; | ||
343 | return GNUNET_SYSERR; | ||
344 | } | ||
345 | |||
346 | |||
347 | /** | ||
348 | * Duplicate a namespace handle. | ||
349 | * | ||
350 | * @param ns namespace handle | ||
351 | * @return duplicated handle to the namespace | ||
352 | */ | ||
353 | struct GNUNET_FS_Namespace * | ||
354 | GNUNET_FS_namespace_dup (struct GNUNET_FS_Namespace *ns) | ||
355 | { | ||
356 | ns->rc++; | ||
357 | return ns; | ||
358 | } | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Delete a namespace handle. Can be used for a clean shutdown (free | ||
363 | * memory) or also to freeze the namespace to prevent further | ||
364 | * insertions by anyone. | ||
365 | * | ||
366 | * @param ns handle to the namespace that should be deleted / freed | ||
367 | * @param freeze prevents future insertions; creating a namespace | ||
368 | * with the same name again will create a fresh namespace instead | ||
369 | * | ||
370 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
371 | */ | ||
372 | int | ||
373 | GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *ns, int freeze) | ||
374 | { | ||
375 | unsigned int i; | ||
376 | struct NamespaceUpdateNode *nsn; | ||
377 | |||
378 | ns->rc--; | ||
379 | if (freeze) | ||
380 | { | ||
381 | if (0 != UNLINK (ns->filename)) | ||
382 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", | ||
383 | ns->filename); | ||
384 | } | ||
385 | if (0 != ns->rc) | ||
386 | return GNUNET_OK; | ||
387 | GNUNET_FS_pseudonym_destroy (ns->key); | ||
388 | GNUNET_free (ns->filename); | ||
389 | GNUNET_free (ns->name); | ||
390 | for (i = 0; i < ns->update_node_count; i++) | ||
391 | { | ||
392 | nsn = ns->update_nodes[i]; | ||
393 | GNUNET_CONTAINER_meta_data_destroy (nsn->md); | ||
394 | GNUNET_FS_uri_destroy (nsn->uri); | ||
395 | GNUNET_free (nsn->id); | ||
396 | GNUNET_free (nsn->update); | ||
397 | GNUNET_free (nsn); | ||
398 | } | ||
399 | GNUNET_array_grow (ns->update_nodes, ns->update_node_count, | ||
400 | 0); | ||
401 | if (ns->update_map != NULL) | ||
402 | GNUNET_CONTAINER_multihashmap_destroy (ns->update_map); | ||
403 | GNUNET_free (ns); | ||
404 | return GNUNET_OK; | ||
405 | } | ||
406 | |||
407 | |||
408 | /** | ||
409 | * Context for the 'process_namespace' callback. | ||
410 | * Specifies a function to call on each namespace. | ||
411 | */ | ||
412 | struct ProcessNamespaceContext | ||
413 | { | ||
414 | /** | ||
415 | * Function to call. | ||
416 | */ | ||
417 | GNUNET_FS_NamespaceInfoProcessor cb; | ||
418 | |||
419 | /** | ||
420 | * Closure for 'cb'. | ||
421 | */ | ||
422 | void *cb_cls; | ||
423 | }; | ||
424 | |||
425 | |||
426 | /** | ||
427 | * Get hash of the public key of a namespace. | ||
428 | * | ||
429 | * @param ns namespace | ||
430 | * @param id buffer to store the key in | ||
431 | * @return GNUNET_OK on success | ||
432 | * GNUNET_SYSERR on failure (contents of id remain intact) | ||
433 | */ | ||
434 | int | ||
435 | GNUNET_FS_namespace_get_public_identifier (struct GNUNET_FS_Namespace *ns, | ||
436 | struct GNUNET_FS_PseudonymIdentifier *id) | ||
437 | { | ||
438 | if ((NULL == ns) || (NULL == id)) | ||
439 | return GNUNET_SYSERR; | ||
440 | GNUNET_FS_pseudonym_get_identifier (ns->key, id); | ||
441 | return GNUNET_OK; | ||
442 | } | ||
443 | |||
444 | |||
445 | /** | ||
446 | * Function called with a filename of a namespace. Reads the key and | ||
447 | * calls the callback. | ||
448 | * | ||
449 | * @param cls closure (struct ProcessNamespaceContext) | ||
450 | * @param filename complete filename (absolute path) | ||
451 | * @return GNUNET_OK to continue to iterate, | ||
452 | * GNUNET_SYSERR to abort iteration with error! | ||
453 | */ | ||
454 | static int | ||
455 | process_namespace (void *cls, const char *filename) | ||
456 | { | ||
457 | struct ProcessNamespaceContext *pnc = cls; | ||
458 | struct GNUNET_FS_PseudonymHandle *ph; | ||
459 | struct GNUNET_FS_PseudonymIdentifier id; | ||
460 | const char *name; | ||
461 | const char *t; | ||
462 | |||
463 | if (NULL == (ph = GNUNET_FS_pseudonym_create (filename))) | ||
464 | { | 328 | { |
465 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 329 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read `%s': %s\n"), |
466 | _ | 330 | fn, emsg); |
467 | ("Failed to read namespace private key file `%s', deleting it!\n"), | 331 | GNUNET_free (emsg); |
468 | filename); | ||
469 | if (0 != UNLINK (filename)) | ||
470 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); | ||
471 | return GNUNET_OK; | ||
472 | } | 332 | } |
473 | GNUNET_FS_pseudonym_get_identifier (ph, &id); | 333 | GNUNET_free (fn); |
474 | GNUNET_FS_pseudonym_destroy (ph); | 334 | return uig; |
475 | name = filename; | ||
476 | while (NULL != (t = strstr (name, DIR_SEPARATOR_STR))) | ||
477 | name = t + 1; | ||
478 | pnc->cb (pnc->cb_cls, name, &id); | ||
479 | return GNUNET_OK; | ||
480 | } | ||
481 | |||
482 | |||
483 | /** | ||
484 | * Build a list of all available local (!) namespaces The returned | ||
485 | * names are only the nicknames since we only iterate over the local | ||
486 | * namespaces. | ||
487 | * | ||
488 | * @param h handle to the file sharing subsystem | ||
489 | * @param cb function to call on each known namespace | ||
490 | * @param cb_cls closure for cb | ||
491 | */ | ||
492 | void | ||
493 | GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h, | ||
494 | GNUNET_FS_NamespaceInfoProcessor cb, void *cb_cls) | ||
495 | { | ||
496 | char *dn; | ||
497 | struct ProcessNamespaceContext ctx; | ||
498 | |||
499 | dn = get_namespace_directory (h); | ||
500 | if (NULL == dn) | ||
501 | return; | ||
502 | ctx.cb = cb; | ||
503 | ctx.cb_cls = cb_cls; | ||
504 | GNUNET_DISK_directory_scan (dn, &process_namespace, &ctx); | ||
505 | GNUNET_free (dn); | ||
506 | } | 335 | } |
507 | 336 | ||
508 | 337 | ||
@@ -526,7 +355,7 @@ struct GNUNET_FS_PublishSksContext | |||
526 | /** | 355 | /** |
527 | * Namespace we're publishing to. | 356 | * Namespace we're publishing to. |
528 | */ | 357 | */ |
529 | struct GNUNET_FS_Namespace *ns; | 358 | struct GNUNET_CRYPTO_EccPrivateKey ns; |
530 | 359 | ||
531 | /** | 360 | /** |
532 | * Handle to the datastore. | 361 | * Handle to the datastore. |
@@ -534,6 +363,11 @@ struct GNUNET_FS_PublishSksContext | |||
534 | struct GNUNET_DATASTORE_Handle *dsh; | 363 | struct GNUNET_DATASTORE_Handle *dsh; |
535 | 364 | ||
536 | /** | 365 | /** |
366 | * Handle to FS. | ||
367 | */ | ||
368 | struct GNUNET_FS_Handle *h; | ||
369 | |||
370 | /** | ||
537 | * Function to call once we're done. | 371 | * Function to call once we're done. |
538 | */ | 372 | */ |
539 | GNUNET_FS_PublishContinuation cont; | 373 | GNUNET_FS_PublishContinuation cont; |
@@ -544,31 +378,28 @@ struct GNUNET_FS_PublishSksContext | |||
544 | void *cont_cls; | 378 | void *cont_cls; |
545 | 379 | ||
546 | /** | 380 | /** |
547 | * Handle for our datastore request. | 381 | * Handle for our UBlock operation request. |
548 | */ | 382 | */ |
549 | struct GNUNET_DATASTORE_QueueEntry *dqe; | 383 | struct GNUNET_FS_PublishUblockContext *uc; |
550 | }; | 384 | }; |
551 | 385 | ||
552 | 386 | ||
553 | /** | 387 | /** |
554 | * Function called by the datastore API with | 388 | * Function called by the UBlock construction with |
555 | * the result from the PUT (UBlock) request. | 389 | * the result from the PUT (UBlock) request. |
556 | * | 390 | * |
557 | * @param cls closure of type "struct GNUNET_FS_PublishSksContext*" | 391 | * @param cls closure of type "struct GNUNET_FS_PublishSksContext*" |
558 | * @param success GNUNET_OK on success | ||
559 | * @param min_expiration minimum expiration time required for content to be stored | ||
560 | * @param msg error message (or NULL) | 392 | * @param msg error message (or NULL) |
561 | */ | 393 | */ |
562 | static void | 394 | static void |
563 | sb_put_cont (void *cls, int success, | 395 | sks_publish_cont (void *cls, |
564 | struct GNUNET_TIME_Absolute min_expiration, | 396 | const char *msg) |
565 | const char *msg) | ||
566 | { | 397 | { |
567 | struct GNUNET_FS_PublishSksContext *psc = cls; | 398 | struct GNUNET_FS_PublishSksContext *psc = cls; |
568 | struct GNUNET_HashCode hc; | 399 | struct GNUNET_FS_UpdateInformationGraph *uig; |
569 | 400 | ||
570 | psc->dqe = NULL; | 401 | psc->uc = NULL; |
571 | if (GNUNET_OK != success) | 402 | if (NULL != msg) |
572 | { | 403 | { |
573 | if (NULL != psc->cont) | 404 | if (NULL != psc->cont) |
574 | psc->cont (psc->cont_cls, NULL, msg); | 405 | psc->cont (psc->cont_cls, NULL, msg); |
@@ -580,19 +411,14 @@ sb_put_cont (void *cls, int success, | |||
580 | /* FIXME: this can be done much more | 411 | /* FIXME: this can be done much more |
581 | * efficiently by simply appending to the | 412 | * efficiently by simply appending to the |
582 | * file and overwriting the 4-byte header */ | 413 | * file and overwriting the 4-byte header */ |
583 | if (psc->ns->update_nodes == NULL) | 414 | uig = read_update_information_graph (psc->h, |
584 | read_update_information_graph (psc->ns); | 415 | &psc->ns); |
585 | GNUNET_array_append (psc->ns->update_nodes, | 416 | GNUNET_array_append (uig->update_nodes, |
586 | psc->ns->update_node_count, psc->nsn); | 417 | uig->update_node_count, |
587 | if (NULL != psc->ns->update_map) | 418 | psc->nsn); |
588 | { | ||
589 | GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc); | ||
590 | GNUNET_CONTAINER_multihashmap_put (psc->ns->update_map, &hc, | ||
591 | psc->nsn, | ||
592 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
593 | } | ||
594 | psc->nsn = NULL; | 419 | psc->nsn = NULL; |
595 | write_update_information_graph (psc->ns); | 420 | write_update_information_graph (uig); |
421 | free_update_information_graph (uig); | ||
596 | } | 422 | } |
597 | if (NULL != psc->cont) | 423 | if (NULL != psc->cont) |
598 | psc->cont (psc->cont_cls, psc->uri, NULL); | 424 | psc->cont (psc->cont_cls, psc->uri, NULL); |
@@ -617,7 +443,7 @@ sb_put_cont (void *cls, int success, | |||
617 | */ | 443 | */ |
618 | struct GNUNET_FS_PublishSksContext * | 444 | struct GNUNET_FS_PublishSksContext * |
619 | GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, | 445 | GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, |
620 | struct GNUNET_FS_Namespace *ns, | 446 | const struct GNUNET_CRYPTO_EccPrivateKey *ns, |
621 | const char *identifier, const char *update, | 447 | const char *identifier, const char *update, |
622 | const struct GNUNET_CONTAINER_MetaData *meta, | 448 | const struct GNUNET_CONTAINER_MetaData *meta, |
623 | const struct GNUNET_FS_Uri *uri, | 449 | const struct GNUNET_FS_Uri *uri, |
@@ -626,144 +452,49 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, | |||
626 | GNUNET_FS_PublishContinuation cont, void *cont_cls) | 452 | GNUNET_FS_PublishContinuation cont, void *cont_cls) |
627 | { | 453 | { |
628 | struct GNUNET_FS_PublishSksContext *psc; | 454 | struct GNUNET_FS_PublishSksContext *psc; |
629 | struct GNUNET_CRYPTO_AesSessionKey sk; | ||
630 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
631 | struct GNUNET_FS_Uri *sks_uri; | 455 | struct GNUNET_FS_Uri *sks_uri; |
632 | char *uris; | 456 | |
633 | size_t size; | 457 | sks_uri = GNUNET_new (struct GNUNET_FS_Uri); |
634 | size_t slen; | ||
635 | size_t nidlen; | ||
636 | size_t idlen; | ||
637 | ssize_t mdsize; | ||
638 | struct UBlock *ub; | ||
639 | struct UBlock *ub_enc; | ||
640 | char *dest; | ||
641 | struct GNUNET_CONTAINER_MetaData *mmeta; | ||
642 | struct GNUNET_HashCode id_hash; /* hash of thisId */ | ||
643 | struct GNUNET_HashCode ns_hash; /* hash of namespace public key */ | ||
644 | struct GNUNET_HashCode key; /* id_hash ^ ns_hash, for AES key */ | ||
645 | struct GNUNET_HashCode signing_key; /* H(key) = input for public key */ | ||
646 | struct GNUNET_HashCode query; /* H(verification_key) = query */ | ||
647 | |||
648 | idlen = strlen (identifier); | ||
649 | if (NULL != update) | ||
650 | nidlen = strlen (update) + 1; | ||
651 | else | ||
652 | nidlen = 1; | ||
653 | uris = GNUNET_FS_uri_to_string (uri); | ||
654 | slen = strlen (uris) + 1; | ||
655 | if ( (slen >= MAX_UBLOCK_SIZE - sizeof (struct UBlock)) || | ||
656 | (nidlen >= MAX_UBLOCK_SIZE - sizeof (struct UBlock) - slen) ) | ||
657 | { | ||
658 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
659 | _("Identifiers or URI too long to create UBlock")); | ||
660 | GNUNET_free (uris); | ||
661 | return NULL; | ||
662 | } | ||
663 | if (NULL == meta) | ||
664 | mmeta = GNUNET_CONTAINER_meta_data_create (); | ||
665 | else | ||
666 | mmeta = GNUNET_CONTAINER_meta_data_duplicate (meta); | ||
667 | mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (mmeta); | ||
668 | size = sizeof (struct UBlock) + slen + nidlen + mdsize; | ||
669 | if ( (size > MAX_UBLOCK_SIZE) || | ||
670 | (size < sizeof (struct UBlock) + slen + nidlen) ) | ||
671 | { | ||
672 | size = MAX_UBLOCK_SIZE; | ||
673 | mdsize = MAX_UBLOCK_SIZE - (sizeof (struct UBlock) + slen + nidlen); | ||
674 | } | ||
675 | ub = GNUNET_malloc (sizeof (struct UBlock) + size); | ||
676 | dest = (char *) &ub[1]; | ||
677 | if (NULL != update) | ||
678 | memcpy (dest, update, nidlen); | ||
679 | else | ||
680 | memset (dest, 0, 1); | ||
681 | dest += nidlen; | ||
682 | memcpy (dest, uris, slen); | ||
683 | GNUNET_free (uris); | ||
684 | dest += slen; | ||
685 | mdsize = | ||
686 | GNUNET_CONTAINER_meta_data_serialize (mmeta, &dest, mdsize, | ||
687 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); | ||
688 | GNUNET_CONTAINER_meta_data_destroy (mmeta); | ||
689 | if (-1 == mdsize) | ||
690 | { | ||
691 | GNUNET_break (0); | ||
692 | GNUNET_free (ub); | ||
693 | if (NULL != cont) | ||
694 | cont (cont_cls, NULL, _("Internal error.")); | ||
695 | return NULL; | ||
696 | } | ||
697 | sks_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); | ||
698 | sks_uri->type = GNUNET_FS_URI_SKS; | 458 | sks_uri->type = GNUNET_FS_URI_SKS; |
699 | sks_uri->data.sks.identifier = GNUNET_strdup (identifier); | 459 | sks_uri->data.sks.identifier = GNUNET_strdup (identifier); |
700 | GNUNET_FS_namespace_get_public_identifier (ns, | 460 | GNUNET_CRYPTO_ecc_key_get_public (ns, |
701 | &sks_uri->data.sks.ns); | 461 | &sks_uri->data.sks.ns); |
702 | 462 | ||
703 | size = sizeof (struct UBlock) + mdsize + slen + nidlen; | 463 | psc = GNUNET_new (struct GNUNET_FS_PublishSksContext); |
704 | ub_enc = GNUNET_malloc (size); | 464 | psc->h = h; |
705 | GNUNET_CRYPTO_hash (identifier, idlen, &id_hash); | ||
706 | GNUNET_CRYPTO_hash (&sks_uri->data.sks.ns, | ||
707 | sizeof (sks_uri->data.sks.ns), &ns_hash); | ||
708 | GNUNET_CRYPTO_hash_xor (&id_hash, &ns_hash, &key); | ||
709 | GNUNET_CRYPTO_hash_to_aes_key (&key, &sk, &iv); | ||
710 | GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &signing_key); | ||
711 | |||
712 | GNUNET_CRYPTO_aes_encrypt (&ub[1], | ||
713 | size - sizeof (struct UBlock), | ||
714 | &sk, &iv, | ||
715 | &ub_enc[1]); | ||
716 | ub_enc->purpose.size = htonl (nidlen + slen + mdsize + sizeof (struct UBlock) | ||
717 | - sizeof (struct GNUNET_FS_PseudonymSignature)); | ||
718 | ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); | ||
719 | GNUNET_FS_pseudonym_derive_verification_key (&sks_uri->data.sks.ns, | ||
720 | &signing_key, | ||
721 | &ub_enc->verification_key); | ||
722 | GNUNET_CRYPTO_hash (&ub_enc->verification_key, | ||
723 | sizeof (ub_enc->verification_key), | ||
724 | &query); | ||
725 | GNUNET_FS_pseudonym_sign (ns->key, | ||
726 | &ub_enc->purpose, | ||
727 | NULL, | ||
728 | &signing_key, | ||
729 | &ub_enc->signature); | ||
730 | psc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishSksContext)); | ||
731 | psc->uri = sks_uri; | 465 | psc->uri = sks_uri; |
732 | psc->cont = cont; | 466 | psc->cont = cont; |
733 | psc->ns = GNUNET_FS_namespace_dup (ns); | ||
734 | psc->cont_cls = cont_cls; | 467 | psc->cont_cls = cont_cls; |
735 | if (0 != (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) | 468 | psc->ns = *ns; |
736 | { | 469 | if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) |
737 | GNUNET_free (ub_enc); | ||
738 | GNUNET_free (ub); | ||
739 | sb_put_cont (psc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL); | ||
740 | return NULL; | ||
741 | } | ||
742 | psc->dsh = GNUNET_DATASTORE_connect (h->cfg); | ||
743 | if (NULL == psc->dsh) | ||
744 | { | 470 | { |
745 | GNUNET_free (ub_enc); | 471 | psc->dsh = GNUNET_DATASTORE_connect (h->cfg); |
746 | GNUNET_free (ub); | 472 | if (NULL == psc->dsh) |
747 | sb_put_cont (psc, GNUNET_NO, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to connect to datastore.")); | 473 | { |
748 | return NULL; | 474 | sks_publish_cont (psc, |
475 | _("Failed to connect to datastore.")); | ||
476 | return NULL; | ||
477 | } | ||
749 | } | 478 | } |
750 | |||
751 | if (NULL != update) | 479 | if (NULL != update) |
752 | { | 480 | { |
753 | psc->nsn = GNUNET_malloc (sizeof (struct NamespaceUpdateNode)); | 481 | psc->nsn = GNUNET_new (struct NamespaceUpdateNode); |
754 | psc->nsn->id = GNUNET_strdup (identifier); | 482 | psc->nsn->id = GNUNET_strdup (identifier); |
755 | psc->nsn->update = GNUNET_strdup (update); | 483 | psc->nsn->update = GNUNET_strdup (update); |
756 | psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta); | 484 | psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta); |
757 | psc->nsn->uri = GNUNET_FS_uri_dup (uri); | 485 | psc->nsn->uri = GNUNET_FS_uri_dup (uri); |
758 | } | 486 | } |
759 | 487 | psc->uc = GNUNET_FS_publish_ublock_ (h, | |
760 | psc->dqe = GNUNET_DATASTORE_put (psc->dsh, 0, &query, size, ub_enc, | 488 | psc->dsh, |
761 | GNUNET_BLOCK_TYPE_FS_UBLOCK, bo->content_priority, | 489 | identifier, |
762 | bo->anonymity_level, bo->replication_level, | 490 | update, |
763 | bo->expiration_time, -2, 1, | 491 | ns, |
764 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, &sb_put_cont, psc); | 492 | meta, |
765 | GNUNET_free (ub); | 493 | uri, |
766 | GNUNET_free (ub_enc); | 494 | bo, |
495 | options, | ||
496 | &sks_publish_cont, | ||
497 | psc); | ||
767 | return psc; | 498 | return psc; |
768 | } | 499 | } |
769 | 500 | ||
@@ -776,17 +507,16 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, | |||
776 | void | 507 | void |
777 | GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc) | 508 | GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc) |
778 | { | 509 | { |
779 | if (NULL != psc->dqe) | 510 | if (NULL != psc->uc) |
780 | { | 511 | { |
781 | GNUNET_DATASTORE_cancel (psc->dqe); | 512 | GNUNET_FS_publish_ublock_cancel_ (psc->uc); |
782 | psc->dqe = NULL; | 513 | psc->uc = NULL; |
783 | } | 514 | } |
784 | if (NULL != psc->dsh) | 515 | if (NULL != psc->dsh) |
785 | { | 516 | { |
786 | GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO); | 517 | GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO); |
787 | psc->dsh = NULL; | 518 | psc->dsh = NULL; |
788 | } | 519 | } |
789 | GNUNET_FS_namespace_delete (psc->ns, GNUNET_NO); | ||
790 | GNUNET_FS_uri_destroy (psc->uri); | 520 | GNUNET_FS_uri_destroy (psc->uri); |
791 | if (NULL != psc->nsn) | 521 | if (NULL != psc->nsn) |
792 | { | 522 | { |
@@ -828,12 +558,18 @@ struct ProcessUpdateClosure | |||
828 | * GNUNET_NO if not. | 558 | * GNUNET_NO if not. |
829 | */ | 559 | */ |
830 | static int | 560 | static int |
831 | process_update_node (void *cls, const struct GNUNET_HashCode * key, void *value) | 561 | process_update_node (void *cls, |
562 | const struct GNUNET_HashCode *key, | ||
563 | void *value) | ||
832 | { | 564 | { |
833 | struct ProcessUpdateClosure *pc = cls; | 565 | struct ProcessUpdateClosure *pc = cls; |
834 | struct NamespaceUpdateNode *nsn = value; | 566 | struct NamespaceUpdateNode *nsn = value; |
835 | 567 | ||
836 | pc->ip (pc->ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update); | 568 | pc->ip (pc->ip_cls, |
569 | nsn->id, | ||
570 | nsn->uri, | ||
571 | nsn->md, | ||
572 | nsn->update); | ||
837 | return GNUNET_YES; | 573 | return GNUNET_YES; |
838 | } | 574 | } |
839 | 575 | ||
@@ -844,9 +580,9 @@ process_update_node (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
844 | struct FindTreeClosure | 580 | struct FindTreeClosure |
845 | { | 581 | { |
846 | /** | 582 | /** |
847 | * Namespace we are operating on. | 583 | * UIG we are operating on. |
848 | */ | 584 | */ |
849 | struct GNUNET_FS_Namespace *ns; | 585 | struct GNUNET_FS_UpdateInformationGraph *uig; |
850 | 586 | ||
851 | /** | 587 | /** |
852 | * Array with 'head's of TREEs. | 588 | * Array with 'head's of TREEs. |
@@ -891,7 +627,9 @@ struct FindTreeClosure | |||
891 | * GNUNET_NO if not. | 627 | * GNUNET_NO if not. |
892 | */ | 628 | */ |
893 | static int | 629 | static int |
894 | find_trees (void *cls, const struct GNUNET_HashCode * key, void *value) | 630 | find_trees (void *cls, |
631 | const struct GNUNET_HashCode *key, | ||
632 | void *value) | ||
895 | { | 633 | { |
896 | struct FindTreeClosure *fc = cls; | 634 | struct FindTreeClosure *fc = cls; |
897 | struct NamespaceUpdateNode *nsn = value; | 635 | struct NamespaceUpdateNode *nsn = value; |
@@ -918,7 +656,7 @@ find_trees (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
918 | nsn->tree_id = UINT_MAX; /* mark as undef */ | 656 | nsn->tree_id = UINT_MAX; /* mark as undef */ |
919 | /* trace */ | 657 | /* trace */ |
920 | GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc); | 658 | GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc); |
921 | GNUNET_CONTAINER_multihashmap_get_multiple (fc->ns->update_map, &hc, | 659 | GNUNET_CONTAINER_multihashmap_get_multiple (fc->uig->update_map, &hc, |
922 | &find_trees, fc); | 660 | &find_trees, fc); |
923 | } | 661 | } |
924 | return GNUNET_YES; | 662 | return GNUNET_YES; |
@@ -942,13 +680,15 @@ find_trees (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
942 | * I know, odd definition of a tree, but the GUI will display an actual | 680 | * I know, odd definition of a tree, but the GUI will display an actual |
943 | * tree (GtkTreeView), so that's what counts for the term here. | 681 | * tree (GtkTreeView), so that's what counts for the term here. |
944 | * | 682 | * |
683 | * @param h fs handle to use | ||
945 | * @param ns namespace to inspect for updateable content | 684 | * @param ns namespace to inspect for updateable content |
946 | * @param next_id ID to look for; use NULL to look for tree roots | 685 | * @param next_id ID to look for; use NULL to look for tree roots |
947 | * @param ip function to call on each updateable identifier | 686 | * @param ip function to call on each updateable identifier |
948 | * @param ip_cls closure for ip | 687 | * @param ip_cls closure for ip |
949 | */ | 688 | */ |
950 | void | 689 | void |
951 | GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, | 690 | GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Handle *h, |
691 | const struct GNUNET_CRYPTO_EccPrivateKey *ns, | ||
952 | const char *next_id, | 692 | const char *next_id, |
953 | GNUNET_FS_IdentifierProcessor ip, | 693 | GNUNET_FS_IdentifierProcessor ip, |
954 | void *ip_cls) | 694 | void *ip_cls) |
@@ -959,50 +699,48 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, | |||
959 | struct NamespaceUpdateNode *nsn; | 699 | struct NamespaceUpdateNode *nsn; |
960 | struct ProcessUpdateClosure pc; | 700 | struct ProcessUpdateClosure pc; |
961 | struct FindTreeClosure fc; | 701 | struct FindTreeClosure fc; |
702 | struct GNUNET_FS_UpdateInformationGraph *uig; | ||
962 | 703 | ||
963 | if (NULL == ns->update_nodes) | 704 | uig = read_update_information_graph (h, ns); |
964 | read_update_information_graph (ns); | 705 | if (NULL == uig->update_nodes) |
965 | if (NULL == ns->update_nodes) | ||
966 | { | 706 | { |
967 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 707 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
968 | "No updateable nodes found for ID `%s'\n", next_id); | 708 | "No updateable nodes found for ID `%s'\n", next_id); |
709 | free_update_information_graph (uig); | ||
969 | return; /* no nodes */ | 710 | return; /* no nodes */ |
970 | } | 711 | } |
971 | if (NULL == ns->update_map) | 712 | uig->update_map = |
713 | GNUNET_CONTAINER_multihashmap_create (2 + | ||
714 | 3 * uig->update_node_count / | ||
715 | 4, | ||
716 | GNUNET_NO); | ||
717 | for (i = 0; i < uig->update_node_count; i++) | ||
972 | { | 718 | { |
973 | /* need to construct */ | 719 | nsn = uig->update_nodes[i]; |
974 | ns->update_map = | 720 | GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); |
975 | GNUNET_CONTAINER_multihashmap_create (2 + | 721 | GNUNET_CONTAINER_multihashmap_put (uig->update_map, &hc, nsn, |
976 | 3 * ns->update_node_count / | 722 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); |
977 | 4, | ||
978 | GNUNET_NO); | ||
979 | for (i = 0; i < ns->update_node_count; i++) | ||
980 | { | ||
981 | nsn = ns->update_nodes[i]; | ||
982 | GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); | ||
983 | GNUNET_CONTAINER_multihashmap_put (ns->update_map, &hc, nsn, | ||
984 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
985 | } | ||
986 | } | 723 | } |
987 | if (NULL != next_id) | 724 | if (NULL != next_id) |
988 | { | 725 | { |
989 | GNUNET_CRYPTO_hash (next_id, strlen (next_id), &hc); | 726 | GNUNET_CRYPTO_hash (next_id, strlen (next_id), &hc); |
990 | pc.ip = ip; | 727 | pc.ip = ip; |
991 | pc.ip_cls = ip_cls; | 728 | pc.ip_cls = ip_cls; |
992 | GNUNET_CONTAINER_multihashmap_get_multiple (ns->update_map, &hc, | 729 | GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, |
993 | &process_update_node, &pc); | 730 | &process_update_node, &pc); |
731 | free_update_information_graph (uig); | ||
994 | return; | 732 | return; |
995 | } | 733 | } |
996 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 734 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
997 | "Calculating TREEs to find roots of update trees\n"); | 735 | "Calculating TREEs to find roots of update trees\n"); |
998 | /* Find heads of TREEs in update graph */ | 736 | /* Find heads of TREEs in update graph */ |
999 | nug = ++ns->nug_gen; | 737 | nug = ++uig->nug_gen; |
1000 | fc.tree_array = NULL; | 738 | fc.tree_array = NULL; |
1001 | fc.tree_array_size = 0; | 739 | fc.tree_array_size = 0; |
1002 | 740 | ||
1003 | for (i = 0; i < ns->update_node_count; i++) | 741 | for (i = 0; i < uig->update_node_count; i++) |
1004 | { | 742 | { |
1005 | nsn = ns->update_nodes[i]; | 743 | nsn = uig->update_nodes[i]; |
1006 | if (nsn->nug == nug) | 744 | if (nsn->nug == nug) |
1007 | { | 745 | { |
1008 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, | 746 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, |
@@ -1014,15 +752,15 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, | |||
1014 | nsn->tree_id = UINT_MAX; | 752 | nsn->tree_id = UINT_MAX; |
1015 | fc.id = UINT_MAX; | 753 | fc.id = UINT_MAX; |
1016 | fc.nug = nug; | 754 | fc.nug = nug; |
1017 | fc.ns = ns; | 755 | fc.uig = uig; |
1018 | GNUNET_CONTAINER_multihashmap_get_multiple (ns->update_map, &hc, | 756 | GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, |
1019 | &find_trees, &fc); | 757 | &find_trees, &fc); |
1020 | if (UINT_MAX == fc.id) | 758 | if (UINT_MAX == fc.id) |
1021 | { | 759 | { |
1022 | /* start new TREE */ | 760 | /* start new TREE */ |
1023 | for (fc.id = 0; fc.id < fc.tree_array_size; fc.id++) | 761 | for (fc.id = 0; fc.id < fc.tree_array_size; fc.id++) |
1024 | { | 762 | { |
1025 | if (fc.tree_array[fc.id] == NULL) | 763 | if (NULL == fc.tree_array[fc.id]) |
1026 | { | 764 | { |
1027 | fc.tree_array[fc.id] = nsn; | 765 | fc.tree_array[fc.id] = nsn; |
1028 | nsn->tree_id = fc.id; | 766 | nsn->tree_id = fc.id; |
@@ -1041,8 +779,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, | |||
1041 | GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); | 779 | GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); |
1042 | fc.id = nsn->tree_id; | 780 | fc.id = nsn->tree_id; |
1043 | fc.nug = nug; | 781 | fc.nug = nug; |
1044 | fc.ns = ns; | 782 | fc.uig = uig; |
1045 | GNUNET_CONTAINER_multihashmap_get_multiple (ns->update_map, &hc, | 783 | GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, |
1046 | &find_trees, &fc); | 784 | &find_trees, &fc); |
1047 | } | 785 | } |
1048 | else | 786 | else |
@@ -1051,7 +789,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, | |||
1051 | fc.tree_array[fc.id] = nsn; | 789 | fc.tree_array[fc.id] = nsn; |
1052 | nsn->tree_id = fc.id; | 790 | nsn->tree_id = fc.id; |
1053 | } | 791 | } |
1054 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, | 792 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
793 | "TREE of node `%s' is %u\n", nsn->id, | ||
1055 | fc.id); | 794 | fc.id); |
1056 | } | 795 | } |
1057 | for (i = 0; i < fc.tree_array_size; i++) | 796 | for (i = 0; i < fc.tree_array_size; i++) |
@@ -1066,6 +805,7 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, | |||
1066 | } | 805 | } |
1067 | GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0); | 806 | GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0); |
1068 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n"); | 807 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n"); |
808 | free_update_information_graph (uig); | ||
1069 | } | 809 | } |
1070 | 810 | ||
1071 | 811 | ||