diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2015-11-20 13:59:10 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2015-11-20 13:59:10 +0000 |
commit | 05651b1889692c26533a9b30a9f7f79af2689675 (patch) | |
tree | 9184d53778bd47c3030e132d4362d41026bf2308 /src | |
parent | 1b41668499df4ced87b98c7b0727381456d39625 (diff) | |
download | gnunet-05651b1889692c26533a9b30a9f7f79af2689675.tar.gz gnunet-05651b1889692c26533a9b30a9f7f79af2689675.zip |
- update; add attribute updates
Diffstat (limited to 'src')
-rw-r--r-- | src/identity-token/gnunet-service-identity-token.c | 317 |
1 files changed, 296 insertions, 21 deletions
diff --git a/src/identity-token/gnunet-service-identity-token.c b/src/identity-token/gnunet-service-identity-token.c index 5e9376627..222b9d184 100644 --- a/src/identity-token/gnunet-service-identity-token.c +++ b/src/identity-token/gnunet-service-identity-token.c | |||
@@ -31,41 +31,113 @@ | |||
31 | #include <jansson.h> | 31 | #include <jansson.h> |
32 | #include "gnunet_signatures.h" | 32 | #include "gnunet_signatures.h" |
33 | 33 | ||
34 | /** | ||
35 | * First pass state | ||
36 | */ | ||
34 | #define STATE_INIT 0 | 37 | #define STATE_INIT 0 |
35 | 38 | ||
39 | /** | ||
40 | * Normal operation state | ||
41 | */ | ||
36 | #define STATE_POST_INIT 1 | 42 | #define STATE_POST_INIT 1 |
37 | 43 | ||
44 | /** | ||
45 | * Minimum interval between updates | ||
46 | */ | ||
38 | #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES | 47 | #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES |
39 | 48 | ||
49 | /** | ||
50 | * Service state (to detect initial update pass) | ||
51 | */ | ||
40 | static int state; | 52 | static int state; |
41 | 53 | ||
54 | /** | ||
55 | * Head of ego entry DLL | ||
56 | */ | ||
42 | static struct EgoEntry *ego_head; | 57 | static struct EgoEntry *ego_head; |
43 | 58 | ||
59 | /** | ||
60 | * Tail of ego entry DLL | ||
61 | */ | ||
44 | static struct EgoEntry *ego_tail; | 62 | static struct EgoEntry *ego_tail; |
45 | 63 | ||
64 | /** | ||
65 | * Identity handle | ||
66 | */ | ||
46 | static struct GNUNET_IDENTITY_Handle *identity_handle; | 67 | static struct GNUNET_IDENTITY_Handle *identity_handle; |
47 | 68 | ||
69 | /** | ||
70 | * Namestore handle | ||
71 | */ | ||
48 | static struct GNUNET_NAMESTORE_Handle *ns_handle; | 72 | static struct GNUNET_NAMESTORE_Handle *ns_handle; |
49 | 73 | ||
74 | /** | ||
75 | * Namestore qe | ||
76 | */ | ||
50 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | 77 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; |
51 | 78 | ||
79 | /** | ||
80 | * Namestore iterator | ||
81 | */ | ||
52 | static struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | 82 | static struct GNUNET_NAMESTORE_ZoneIterator *ns_it; |
53 | 83 | ||
84 | /** | ||
85 | * Timeout task | ||
86 | */ | ||
54 | static struct GNUNET_SCHEDULER_Task * timeout_task; | 87 | static struct GNUNET_SCHEDULER_Task * timeout_task; |
55 | 88 | ||
89 | |||
90 | /** | ||
91 | * Update task | ||
92 | */ | ||
56 | static struct GNUNET_SCHEDULER_Task * update_task; | 93 | static struct GNUNET_SCHEDULER_Task * update_task; |
57 | 94 | ||
95 | /** | ||
96 | * Timeout for next update pass | ||
97 | */ | ||
58 | static struct GNUNET_TIME_Relative min_rel_exp; | 98 | static struct GNUNET_TIME_Relative min_rel_exp; |
59 | 99 | ||
100 | |||
101 | /** | ||
102 | * Currently processed token | ||
103 | */ | ||
60 | static char* token; | 104 | static char* token; |
61 | 105 | ||
106 | /** | ||
107 | * Label for currently processed token | ||
108 | */ | ||
62 | static char* label; | 109 | static char* label; |
63 | 110 | ||
111 | /** | ||
112 | * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format | ||
113 | * | ||
114 | */ | ||
64 | struct EgoEntry | 115 | struct EgoEntry |
65 | { | 116 | { |
117 | /** | ||
118 | * DLL | ||
119 | */ | ||
66 | struct EgoEntry *next; | 120 | struct EgoEntry *next; |
121 | |||
122 | /** | ||
123 | * DLL | ||
124 | */ | ||
67 | struct EgoEntry *prev; | 125 | struct EgoEntry *prev; |
126 | |||
127 | /** | ||
128 | * Ego handle | ||
129 | */ | ||
68 | struct GNUNET_IDENTITY_Ego *ego; | 130 | struct GNUNET_IDENTITY_Ego *ego; |
131 | |||
132 | /** | ||
133 | * Attribute map. Contains the attributes as json_t | ||
134 | */ | ||
135 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; | ||
136 | |||
137 | /** | ||
138 | * Attributes are old and should be updated if GNUNET_YES | ||
139 | */ | ||
140 | int attributes_dirty; | ||
69 | }; | 141 | }; |
70 | 142 | ||
71 | /** | 143 | /** |
@@ -73,6 +145,14 @@ struct EgoEntry | |||
73 | */ | 145 | */ |
74 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 146 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
75 | 147 | ||
148 | |||
149 | /** | ||
150 | * Continuation for token store call | ||
151 | * | ||
152 | * @param cls NULL | ||
153 | * @param success error code | ||
154 | * @param emsg error message | ||
155 | */ | ||
76 | static void | 156 | static void |
77 | store_token_cont (void *cls, | 157 | store_token_cont (void *cls, |
78 | int32_t success, | 158 | int32_t success, |
@@ -86,10 +166,17 @@ store_token_cont (void *cls, | |||
86 | emsg); | 166 | emsg); |
87 | return; | 167 | return; |
88 | } | 168 | } |
89 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Next token\n"); | ||
90 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 169 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); |
91 | } | 170 | } |
92 | 171 | ||
172 | |||
173 | /** | ||
174 | * This function updates the old token with new attributes, | ||
175 | * removes deleted attributes and expiration times. | ||
176 | * | ||
177 | * @param cls the ego entry | ||
178 | * @param tc task context | ||
179 | */ | ||
93 | static void | 180 | static void |
94 | handle_token_update (void *cls, | 181 | handle_token_update (void *cls, |
95 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 182 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
@@ -108,6 +195,7 @@ handle_token_update (void *cls, | |||
108 | struct GNUNET_GNSRECORD_Data token_record; | 195 | struct GNUNET_GNSRECORD_Data token_record; |
109 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | 196 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; |
110 | struct GNUNET_CRYPTO_EcdsaSignature sig; | 197 | struct GNUNET_CRYPTO_EcdsaSignature sig; |
198 | struct GNUNET_HashCode key_hash; | ||
111 | struct GNUNET_TIME_Relative token_rel_exp; | 199 | struct GNUNET_TIME_Relative token_rel_exp; |
112 | struct GNUNET_TIME_Relative token_ttl; | 200 | struct GNUNET_TIME_Relative token_ttl; |
113 | struct GNUNET_TIME_Absolute token_exp; | 201 | struct GNUNET_TIME_Absolute token_exp; |
@@ -117,6 +205,7 @@ handle_token_update (void *cls, | |||
117 | struct GNUNET_TIME_Absolute new_nbf; | 205 | struct GNUNET_TIME_Absolute new_nbf; |
118 | json_t *payload_json; | 206 | json_t *payload_json; |
119 | json_t *value; | 207 | json_t *value; |
208 | json_t *cur_value; | ||
120 | json_t *new_payload_json; | 209 | json_t *new_payload_json; |
121 | json_t *token_nbf_json; | 210 | json_t *token_nbf_json; |
122 | json_t *token_exp_json; | 211 | json_t *token_exp_json; |
@@ -141,8 +230,6 @@ handle_token_update (void *cls, | |||
141 | strlen (token_payload), | 230 | strlen (token_payload), |
142 | &token_payload_json); | 231 | &token_payload_json); |
143 | 232 | ||
144 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Payload: %s\n", | ||
145 | token_payload_json); | ||
146 | payload_json = json_loads (token_payload_json, JSON_DECODE_ANY, &json_err); | 233 | payload_json = json_loads (token_payload_json, JSON_DECODE_ANY, &json_err); |
147 | GNUNET_free (token_payload_json); | 234 | GNUNET_free (token_payload_json); |
148 | 235 | ||
@@ -168,7 +255,7 @@ handle_token_update (void *cls, | |||
168 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 255 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); |
169 | return; | 256 | return; |
170 | } | 257 | } |
171 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 258 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
172 | "Token is expired. Create a new one\n"); | 259 | "Token is expired. Create a new one\n"); |
173 | new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); | 260 | new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); |
174 | new_nbf = GNUNET_TIME_absolute_get (); | 261 | new_nbf = GNUNET_TIME_absolute_get (); |
@@ -187,9 +274,26 @@ handle_token_update (void *cls, | |||
187 | { | 274 | { |
188 | json_object_set_new (new_payload_json, key, json_integer (new_iat.abs_value_us)); | 275 | json_object_set_new (new_payload_json, key, json_integer (new_iat.abs_value_us)); |
189 | } | 276 | } |
190 | else { | 277 | else if ((0 == strcmp (key, "iss")) |
278 | || (0 == strcmp (key, "aud")) | ||
279 | || (0 == strcmp (key, "sub")) | ||
280 | || (0 == strcmp (key, "rnl"))) | ||
281 | { | ||
191 | json_object_set (new_payload_json, key, value); | 282 | json_object_set (new_payload_json, key, value); |
192 | } | 283 | } |
284 | else { | ||
285 | GNUNET_CRYPTO_hash (key, | ||
286 | strlen (key), | ||
287 | &key_hash); | ||
288 | //Check if attr still exists. omit of not | ||
289 | if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map, | ||
290 | &key_hash)) | ||
291 | { | ||
292 | cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map, | ||
293 | &key_hash); | ||
294 | json_object_set (new_payload_json, key, cur_value); | ||
295 | } | ||
296 | } | ||
193 | } | 297 | } |
194 | 298 | ||
195 | // reassemble and set | 299 | // reassemble and set |
@@ -238,7 +342,7 @@ handle_token_update (void *cls, | |||
238 | &token_record, | 342 | &token_record, |
239 | &store_token_cont, | 343 | &store_token_cont, |
240 | ego_entry); | 344 | ego_entry); |
241 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Updating Token w/ %s\n", new_token); | 345 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token); |
242 | GNUNET_free (new_token); | 346 | GNUNET_free (new_token); |
243 | GNUNET_free (token); | 347 | GNUNET_free (token); |
244 | token = NULL; | 348 | token = NULL; |
@@ -250,6 +354,39 @@ static void | |||
250 | update_identities(void *cls, | 354 | update_identities(void *cls, |
251 | const struct GNUNET_SCHEDULER_TaskContext *tc); | 355 | const struct GNUNET_SCHEDULER_TaskContext *tc); |
252 | 356 | ||
357 | /** | ||
358 | * | ||
359 | * Cleanup attr_map | ||
360 | * | ||
361 | * @param cls NULL | ||
362 | * @param key the key | ||
363 | * @param value the json_t attribute value | ||
364 | * @return GNUNET_YES | ||
365 | */ | ||
366 | static int | ||
367 | clear_ego_attrs (void *cls, | ||
368 | const struct GNUNET_HashCode *key, | ||
369 | void *value) | ||
370 | { | ||
371 | json_t *attr_value = value; | ||
372 | |||
373 | json_decref (attr_value); | ||
374 | |||
375 | return GNUNET_YES; | ||
376 | } | ||
377 | |||
378 | |||
379 | /** | ||
380 | * | ||
381 | * Update all ID_TOKEN records for an identity and store them | ||
382 | * | ||
383 | * @param cls the identity entry | ||
384 | * @param zone the identity | ||
385 | * @param lbl the name of the record | ||
386 | * @param rd_count number of records | ||
387 | * @param rd record data | ||
388 | * | ||
389 | */ | ||
253 | static void | 390 | static void |
254 | token_collect (void *cls, | 391 | token_collect (void *cls, |
255 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 392 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, |
@@ -262,14 +399,17 @@ token_collect (void *cls, | |||
262 | if (NULL == lbl) | 399 | if (NULL == lbl) |
263 | { | 400 | { |
264 | //Done | 401 | //Done |
265 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 402 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
266 | ">>> Updating Ego finished\n"); | 403 | ">>> Updating Ego finished\n"); |
404 | //Clear attribute map for ego | ||
405 | GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, | ||
406 | &clear_ego_attrs, | ||
407 | ego_entry); | ||
408 | GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); | ||
267 | GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next); | 409 | GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next); |
268 | return; | 410 | return; |
269 | } | 411 | } |
270 | 412 | ||
271 | //TODO autopurge expired tokens here if set in config | ||
272 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Found record\n"); | ||
273 | //There should be only a single record for a token under a label | 413 | //There should be only a single record for a token under a label |
274 | if ((1 != rd_count) | 414 | if ((1 != rd_count) |
275 | || (rd->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN) | 415 | || (rd->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN) |
@@ -282,13 +422,102 @@ token_collect (void *cls, | |||
282 | rd->data, | 422 | rd->data, |
283 | rd->data_size); | 423 | rd->data_size); |
284 | label = GNUNET_strdup (lbl); | 424 | label = GNUNET_strdup (lbl); |
285 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got token: %s\n", token); | ||
286 | 425 | ||
287 | GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry); | 426 | GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry); |
288 | } | 427 | } |
289 | 428 | ||
290 | 429 | ||
430 | /** | ||
431 | * | ||
432 | * Collect all ID_ATTR records for an identity and store them | ||
433 | * | ||
434 | * @param cls the identity entry | ||
435 | * @param zone the identity | ||
436 | * @param lbl the name of the record | ||
437 | * @param rd_count number of records | ||
438 | * @param rd record data | ||
439 | * | ||
440 | */ | ||
441 | static void | ||
442 | attribute_collect (void *cls, | ||
443 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
444 | const char *lbl, | ||
445 | unsigned int rd_count, | ||
446 | const struct GNUNET_GNSRECORD_Data *rd) | ||
447 | { | ||
448 | struct EgoEntry *ego_entry = cls; | ||
449 | json_t *attr_value; | ||
450 | struct GNUNET_HashCode key; | ||
451 | char* attr; | ||
452 | int i; | ||
291 | 453 | ||
454 | if (NULL == lbl) | ||
455 | { | ||
456 | //Done | ||
457 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
458 | ">>> Updating Attributes finished\n"); | ||
459 | ego_entry->attributes_dirty = GNUNET_NO; | ||
460 | GNUNET_SCHEDULER_add_now (&update_identities, ego_entry); | ||
461 | return; | ||
462 | } | ||
463 | |||
464 | if (0 == rd_count) | ||
465 | { | ||
466 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
467 | return; | ||
468 | } | ||
469 | GNUNET_CRYPTO_hash (lbl, | ||
470 | strlen (lbl), | ||
471 | &key); | ||
472 | if (1 == rd_count) | ||
473 | { | ||
474 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | ||
475 | { | ||
476 | attr = GNUNET_GNSRECORD_value_to_string (rd->record_type, | ||
477 | rd->data, | ||
478 | rd->data_size); | ||
479 | attr_value = json_string (attr); | ||
480 | GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, | ||
481 | &key, | ||
482 | attr_value, | ||
483 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
484 | GNUNET_free (attr); | ||
485 | } | ||
486 | |||
487 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | attr_value = json_array(); | ||
492 | for (i = 0; i < rd_count; i++) | ||
493 | { | ||
494 | if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | ||
495 | { | ||
496 | attr = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
497 | rd[i].data, | ||
498 | rd[i].data_size); | ||
499 | json_array_append_new (attr_value, json_string (attr)); | ||
500 | GNUNET_free (attr); | ||
501 | } | ||
502 | |||
503 | } | ||
504 | GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, | ||
505 | &key, | ||
506 | attr_value, | ||
507 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
508 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | /** | ||
513 | * | ||
514 | * Update identity information for ego. If attribute map is | ||
515 | * dirty, first update the attributes. | ||
516 | * | ||
517 | * @param cls the ego to update | ||
518 | * param tc task context | ||
519 | * | ||
520 | */ | ||
292 | static void | 521 | static void |
293 | update_identities(void *cls, | 522 | update_identities(void *cls, |
294 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 523 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
@@ -299,33 +528,59 @@ update_identities(void *cls, | |||
299 | { | 528 | { |
300 | if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us) | 529 | if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us) |
301 | min_rel_exp = MIN_WAIT_TIME; | 530 | min_rel_exp = MIN_WAIT_TIME; |
302 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Finished. Rescheduling in %d\n", min_rel_exp.rel_value_us); | 531 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
532 | ">>> Finished. Rescheduling in %d\n", | ||
533 | min_rel_exp.rel_value_us); | ||
303 | ns_it = NULL; | 534 | ns_it = NULL; |
304 | //finished -> TODO reschedule | 535 | //finished -> TODO reschedule |
305 | update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, | 536 | update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, |
306 | &update_identities, | 537 | &update_identities, |
307 | ego_head); | 538 | ego_head); |
539 | min_rel_exp.rel_value_us = 0; | ||
308 | return; | 540 | return; |
309 | } | 541 | } |
310 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Updating Ego\n"); | ||
311 | priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego); | 542 | priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego); |
312 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | 543 | if (GNUNET_YES == next_ego->attributes_dirty) |
313 | priv_key, | 544 | { |
314 | &token_collect, | 545 | //Starting over. We must update the Attributes for they might have changed. |
315 | next_ego); | 546 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, |
547 | priv_key, | ||
548 | &attribute_collect, | ||
549 | next_ego); | ||
550 | |||
551 | } | ||
552 | else | ||
553 | { | ||
554 | //Ego will be dirty next time | ||
555 | next_ego->attributes_dirty = GNUNET_YES; | ||
556 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
557 | priv_key, | ||
558 | &token_collect, | ||
559 | next_ego); | ||
560 | } | ||
316 | } | 561 | } |
317 | 562 | ||
318 | 563 | ||
319 | /* ************************* Global helpers ********************* */ | ||
320 | 564 | ||
565 | /** | ||
566 | * Function called initially to start update task | ||
567 | */ | ||
321 | static void | 568 | static void |
322 | init_cont () | 569 | init_cont () |
323 | { | 570 | { |
324 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Starting Service\n"); | 571 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); |
325 | //Initially iterate all itenties and refresh all tokens | 572 | //Initially iterate all itenties and refresh all tokens |
326 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head); | 573 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head); |
327 | } | 574 | } |
328 | 575 | ||
576 | /** | ||
577 | * Initial ego collection function. | ||
578 | * | ||
579 | * @param cls NULL | ||
580 | * @param ego ego | ||
581 | * @param ctx context | ||
582 | * @param identifier ego name | ||
583 | */ | ||
329 | static void | 584 | static void |
330 | list_ego (void *cls, | 585 | list_ego (void *cls, |
331 | struct GNUNET_IDENTITY_Ego *ego, | 586 | struct GNUNET_IDENTITY_Ego *ego, |
@@ -342,10 +597,16 @@ list_ego (void *cls, | |||
342 | if (STATE_INIT == state) { | 597 | if (STATE_INIT == state) { |
343 | new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); | 598 | new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); |
344 | new_entry->ego = ego; | 599 | new_entry->ego = ego; |
600 | new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, | ||
601 | GNUNET_NO); | ||
602 | new_entry->attributes_dirty = GNUNET_YES; | ||
345 | GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry); | 603 | GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry); |
346 | } | 604 | } |
347 | } | 605 | } |
348 | 606 | ||
607 | /** | ||
608 | * Cleanup task | ||
609 | */ | ||
349 | static void | 610 | static void |
350 | cleanup() | 611 | cleanup() |
351 | { | 612 | { |
@@ -375,11 +636,25 @@ cleanup() | |||
375 | NULL != ego_entry;) | 636 | NULL != ego_entry;) |
376 | { | 637 | { |
377 | ego_tmp = ego_entry; | 638 | ego_tmp = ego_entry; |
639 | if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map)) | ||
640 | { | ||
641 | GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map, | ||
642 | &clear_ego_attrs, | ||
643 | ego_tmp); | ||
644 | |||
645 | } | ||
646 | GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); | ||
378 | ego_entry = ego_entry->next; | 647 | ego_entry = ego_entry->next; |
379 | GNUNET_free (ego_tmp); | 648 | GNUNET_free (ego_tmp); |
380 | } | 649 | } |
381 | } | 650 | } |
382 | 651 | ||
652 | /** | ||
653 | * Shutdown task | ||
654 | * | ||
655 | * @param cls NULL | ||
656 | * @param tc task context | ||
657 | */ | ||
383 | static void | 658 | static void |
384 | do_shutdown (void *cls, | 659 | do_shutdown (void *cls, |
385 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 660 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
@@ -410,7 +685,7 @@ run (void *cls, | |||
410 | ns_handle = GNUNET_NAMESTORE_connect (cfg); | 685 | ns_handle = GNUNET_NAMESTORE_connect (cfg); |
411 | if (NULL == ns_handle) | 686 | if (NULL == ns_handle) |
412 | { | 687 | { |
413 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connectin to namestore"); | 688 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore"); |
414 | } | 689 | } |
415 | 690 | ||
416 | identity_handle = GNUNET_IDENTITY_connect (cfg, | 691 | identity_handle = GNUNET_IDENTITY_connect (cfg, |