aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-03-10 02:18:22 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2022-03-10 02:18:22 +0100
commitfba50c0338fb76feec7fee5a12e27fc57df1972b (patch)
tree22dcdbf1d1c091d4f41a1b7e8b9f0ce12e9d9319
parent807dec8e802737fb46d015c48a7859a6ec504f74 (diff)
downloadlibgnunetchat-fba50c0338fb76feec7fee5a12e27fc57df1972b.tar.gz
libgnunetchat-fba50c0338fb76feec7fee5a12e27fc57df1972b.zip
Replace local files with namestore usage
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--Makefile1
-rw-r--r--include/gnunet_chat_lib.h25
-rw-r--r--src/gnunet_chat_context.c303
-rw-r--r--src/gnunet_chat_context.h15
-rw-r--r--src/gnunet_chat_context_intern.c16
-rw-r--r--src/gnunet_chat_group.c89
-rw-r--r--src/gnunet_chat_group.h8
-rw-r--r--src/gnunet_chat_handle.c41
-rw-r--r--src/gnunet_chat_handle.h6
-rw-r--r--src/gnunet_chat_handle_intern.c115
-rw-r--r--src/gnunet_chat_lib.c53
11 files changed, 454 insertions, 218 deletions
diff --git a/Makefile b/Makefile
index d1ae23c..82c739f 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ LIBRARIES = gnunetarm\
25 gnunetfs\ 25 gnunetfs\
26 gnunetidentity\ 26 gnunetidentity\
27 gnunetmessenger\ 27 gnunetmessenger\
28 gnunetnamestore\
28 gnunetregex\ 29 gnunetregex\
29 gnunetutil 30 gnunetutil
30 31
diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h
index e09643e..10e36a4 100644
--- a/include/gnunet_chat_lib.h
+++ b/include/gnunet_chat_lib.h
@@ -781,6 +781,31 @@ GNUNET_CHAT_context_iterate_files (struct GNUNET_CHAT_Context *context,
781 void *cls); 781 void *cls);
782 782
783/** 783/**
784 * Sets a custom <i>user pointer</i> to a given <i>member</i> relative to a
785 * <i>context</i> so it can be accessed in member related callbacks.
786 *
787 * @param[in,out] context Chat context
788 * @param[in] member Contact
789 * @param[in] user_pointer Custom user pointer
790 */
791void
792GNUNET_CHAT_member_set_user_pointer (struct GNUNET_CHAT_Context *context,
793 const struct GNUNET_CHAT_Contact *member,
794 void *user_pointer);
795
796/**
797 * Returns the custom user pointer of a given <i>contact</i> or NULL if it was
798 * not set any.
799 *
800 * @param[in] context Chat context
801 * @param[in] member Contact
802 * @return Custom user pointer or NULL
803 */
804void*
805GNUNET_CHAT_member_get_user_pointer (const struct GNUNET_CHAT_Context *context,
806 const struct GNUNET_CHAT_Contact *member);
807
808/**
784 * Returns the kind of a given <i>message</i> to determine its content and 809 * Returns the kind of a given <i>message</i> to determine its content and
785 * related usage. 810 * related usage.
786 * 811 *
diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c
index 316ffc1..cf7046b 100644
--- a/src/gnunet_chat_context.c
+++ b/src/gnunet_chat_context.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "gnunet_chat_context.h" 25#include "gnunet_chat_context.h"
26#include "gnunet_chat_group.h"
26#include "gnunet_chat_handle.h" 27#include "gnunet_chat_handle.h"
27#include "gnunet_chat_util.h" 28#include "gnunet_chat_util.h"
28 29
@@ -40,6 +41,7 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle,
40 41
41 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN; 42 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN;
42 context->nick = NULL; 43 context->nick = NULL;
44 context->topic = NULL;
43 45
44 context->timestamps = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO); 46 context->timestamps = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
45 context->messages = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 47 context->messages = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
@@ -51,6 +53,10 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle,
51 53
52 context->user_pointer = NULL; 54 context->user_pointer = NULL;
53 55
56 context->member_pointers = GNUNET_CONTAINER_multishortmap_create(
57 8, GNUNET_NO
58 );
59
54 return context; 60 return context;
55} 61}
56 62
@@ -66,6 +72,7 @@ context_create_from_contact (struct GNUNET_CHAT_Handle *handle,
66 72
67 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT; 73 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
68 context->nick = NULL; 74 context->nick = NULL;
75 context->topic = NULL;
69 76
70 context->timestamps = GNUNET_CONTAINER_multishortmap_create(4, GNUNET_NO); 77 context->timestamps = GNUNET_CONTAINER_multishortmap_create(4, GNUNET_NO);
71 context->messages = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO); 78 context->messages = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
@@ -77,6 +84,10 @@ context_create_from_contact (struct GNUNET_CHAT_Handle *handle,
77 84
78 context->user_pointer = NULL; 85 context->user_pointer = NULL;
79 86
87 context->member_pointers = GNUNET_CONTAINER_multishortmap_create(
88 8, GNUNET_NO
89 );
90
80 return context; 91 return context;
81} 92}
82 93
@@ -101,11 +112,16 @@ context_destroy (struct GNUNET_CHAT_Context *context)
101 context->invites, it_destroy_context_invites, NULL 112 context->invites, it_destroy_context_invites, NULL
102 ); 113 );
103 114
115 GNUNET_CONTAINER_multishortmap_destroy(context->member_pointers);
116
104 GNUNET_CONTAINER_multishortmap_destroy(context->timestamps); 117 GNUNET_CONTAINER_multishortmap_destroy(context->timestamps);
105 GNUNET_CONTAINER_multihashmap_destroy(context->messages); 118 GNUNET_CONTAINER_multihashmap_destroy(context->messages);
106 GNUNET_CONTAINER_multihashmap_destroy(context->invites); 119 GNUNET_CONTAINER_multihashmap_destroy(context->invites);
107 GNUNET_CONTAINER_multihashmap_destroy(context->files); 120 GNUNET_CONTAINER_multihashmap_destroy(context->files);
108 121
122 if (context->topic)
123 GNUNET_free(context->topic);
124
109 if (context->nick) 125 if (context->nick)
110 GNUNET_free(context->nick); 126 GNUNET_free(context->nick);
111 127
@@ -141,6 +157,11 @@ context_update_room (struct GNUNET_CHAT_Context *context,
141 GNUNET_CONTAINER_multihashmap_clear(context->files); 157 GNUNET_CONTAINER_multihashmap_clear(context->files);
142 158
143 context->room = room; 159 context->room = room;
160
161 if (!(context->room))
162 return;
163
164 context_write_records(context);
144} 165}
145 166
146void 167void
@@ -163,169 +184,235 @@ context_update_nick (struct GNUNET_CHAT_Context *context,
163} 184}
164 185
165void 186void
166context_load_config (struct GNUNET_CHAT_Context *context) 187context_read_records (struct GNUNET_CHAT_Context *context,
188 const char *label,
189 unsigned int count,
190 const struct GNUNET_GNSRECORD_Data *data)
167{ 191{
168 GNUNET_assert((context) && 192 GNUNET_assert((context) &&
169 (context->handle) && 193 (context->room));
170 (context->room));
171
172 const char *directory = handle_get_directory(context->handle);
173 194
174 if (!directory) 195 char *nick = NULL;
175 return; 196 char *topic = NULL;
176 197
177 const struct GNUNET_HashCode *hash = GNUNET_MESSENGER_room_get_key( 198 for (unsigned int i = 0; i < count; i++)
178 context->room 199 {
179 ); 200 if (!(GNUNET_GNSRECORD_RF_SUPPLEMENTAL & data[i].flags))
201 continue;
180 202
181 char* filename; 203 if (GNUNET_GNSRECORD_TYPE_NICK == data[i].record_type)
182 util_get_filename(directory, "chats", hash, &filename); 204 {
205 if (nick)
206 continue;
183 207
184 if (GNUNET_YES != GNUNET_DISK_file_test(filename)) 208 nick = GNUNET_strndup(data[i].data, data[i].data_size);
185 goto free_filename; 209 }
186 210
187 struct GNUNET_CONFIGURATION_Handle *config = GNUNET_CONFIGURATION_create(); 211 if (GNUNET_DNSPARSER_TYPE_TXT == data[i].record_type)
212 {
213 if (topic)
214 continue;
188 215
189 if (GNUNET_OK != GNUNET_CONFIGURATION_load(config, filename)) 216 topic = GNUNET_strndup(data[i].data, data[i].data_size);
190 goto destroy_config; 217 }
218 }
191 219
192 char* name = NULL; 220 context_update_nick(context, nick);
193 221
194 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string( 222 if (nick)
195 config, "chat", "name", &name)) 223 GNUNET_free(nick);
196 context_update_nick(context, name);
197 224
198 if (name) 225 if (topic)
199 GNUNET_free(name); 226 {
227 struct GNUNET_HashCode topic_hash;
228 GNUNET_CRYPTO_hash(topic, strlen(topic), &topic_hash);
200 229
201 unsigned long long type_number; 230 const struct GNUNET_HashCode *hash = GNUNET_MESSENGER_room_get_key(
231 context->room
232 );
202 233
203 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number( 234 if (0 != GNUNET_CRYPTO_hash_cmp(&topic_hash, hash))
204 config, "chat", "type", &type_number)) 235 {
205 switch (type_number) { 236 GNUNET_free(topic);
206 case GNUNET_CHAT_CONTEXT_TYPE_CONTACT: 237 topic = NULL;
207 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
208 break;
209 case GNUNET_CHAT_CONTEXT_TYPE_GROUP:
210 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
211 break;
212 default:
213 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN;
214 break;
215 } 238 }
239 }
216 240
217destroy_config: 241 util_set_name_field(topic, &(context->topic));
218 GNUNET_CONFIGURATION_destroy(config);
219 242
220free_filename: 243 if (topic)
221 GNUNET_free(filename); 244 GNUNET_free(topic);
245
246 if (0 == strncmp(label, "group_", 6))
247 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
248 else if (0 == strncmp(label, "contact_", 8))
249 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
250 else
251 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN;
222} 252}
223 253
224void 254void
225context_save_config (const struct GNUNET_CHAT_Context *context) 255context_write_records (struct GNUNET_CHAT_Context *context)
226{ 256{
227 GNUNET_assert((context) && 257 GNUNET_assert((context) &&
228 (context->handle) && 258 (context->handle) &&
229 (context->room)); 259 (context->room));
230 260
231 const char *directory = handle_get_directory(context->handle); 261 const struct GNUNET_IDENTITY_PrivateKey *zone = handle_get_key(
262 context->handle
263 );
232 264
233 if (!directory) 265 if (!zone)
234 return; 266 return;
235 267
236 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key( 268 const struct GNUNET_HashCode *hash = GNUNET_MESSENGER_room_get_key(
237 context->room 269 context->room
238 ); 270 );
239 271
240 struct GNUNET_CONFIGURATION_Handle *config = GNUNET_CONFIGURATION_create(); 272 struct GNUNET_TIME_Absolute expiration = GNUNET_TIME_absolute_get_forever_();
241 273
242 if (context->room) 274 struct GNUNET_MESSENGER_RoomEntryRecord room;
243 GNUNET_CONFIGURATION_set_value_string( 275 GNUNET_CRYPTO_get_peer_identity(context->handle->cfg, &(room.door));
244 config, "chat", "key", GNUNET_h2s_full(key)
245 );
246
247 if (context->nick)
248 GNUNET_CONFIGURATION_set_value_string(
249 config, "chat", "name", context->nick
250 );
251 276
252 if (GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN != context->type) 277 GNUNET_memcpy(
253 GNUNET_CONFIGURATION_set_value_number( 278 &(room.key),
254 config, "chat", "type", context->type 279 hash,
255 ); 280 sizeof(room.key)
281 );
256 282
257 char* filename; 283 const char *nick = context->nick;
258 util_get_filename(directory, "chats", key, &filename); 284 const char *topic = context->topic;
259 285
260 if (GNUNET_OK == GNUNET_DISK_directory_create_for_file(filename)) 286 if (topic)
261 GNUNET_CONFIGURATION_write(config, filename); 287 {
288 struct GNUNET_HashCode topic_hash;
289 GNUNET_CRYPTO_hash(topic, strlen(topic), &topic_hash);
262 290
263 GNUNET_CONFIGURATION_destroy(config); 291 if (0 != GNUNET_CRYPTO_hash_cmp(&topic_hash, hash))
292 topic = NULL;
293 }
264 294
265 GNUNET_free(filename); 295 unsigned int count = 1;
266}
267 296
268enum GNUNET_GenericReturnValue 297 struct GNUNET_GNSRECORD_Data data [3];
269callback_scan_for_configs (void *cls, 298 data[0].record_type = GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY;
270 const char *filename) 299 data[0].data = &room;
271{ 300 data[0].data_size = sizeof(room);
272 struct GNUNET_CHAT_Handle *handle = (struct GNUNET_CHAT_Handle*) cls; 301 data[0].expiration_time = expiration.abs_value_us;
273 struct GNUNET_PeerIdentity door; 302 data[0].flags = GNUNET_GNSRECORD_RF_PRIVATE;
274 struct GNUNET_HashCode key;
275 303
276 memset(&door, 0, sizeof(door)); 304 if (nick)
277 memset(&key, 0, sizeof(key)); 305 {
306 data[count].record_type = GNUNET_GNSRECORD_TYPE_NICK;
307 data[count].data = nick;
308 data[count].data_size = strlen(nick);
309 data[count].expiration_time = expiration.abs_value_us;
310 data[count].flags = (
311 GNUNET_GNSRECORD_RF_PRIVATE |
312 GNUNET_GNSRECORD_RF_SUPPLEMENTAL
313 );
278 314
279 if ((!filename) || 315 count++;
280 (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity(handle->cfg, &door))) 316 }
281 return GNUNET_YES;
282 317
283 struct GNUNET_CONFIGURATION_Handle *config = GNUNET_CONFIGURATION_create(); 318 if (topic)
319 {
320 data[count].record_type = GNUNET_DNSPARSER_TYPE_TXT;
321 data[count].data = topic;
322 data[count].data_size = strlen(topic);
323 data[count].expiration_time = expiration.abs_value_us;
324 data[count].flags = (
325 GNUNET_GNSRECORD_RF_PRIVATE |
326 GNUNET_GNSRECORD_RF_SUPPLEMENTAL
327 );
284 328
285 if (GNUNET_OK != GNUNET_CONFIGURATION_load(config, filename)) 329 count++;
286 goto destroy_config; 330 }
287 331
288 char* key_value = NULL; 332 const char *type_string = "chat";
289 333
290 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string( 334 switch (context->type)
291 config, "chat", "key", &key_value)) &&
292 (GNUNET_OK == GNUNET_CRYPTO_hash_from_string(key_value, &key)))
293 { 335 {
294 handle_send_room_name(handle, GNUNET_MESSENGER_enter_room( 336 case GNUNET_CHAT_CONTEXT_TYPE_CONTACT:
295 handle->messenger, &door, &key 337 type_string = "contact";
296 )); 338 break;
339 case GNUNET_CHAT_CONTEXT_TYPE_GROUP:
340 type_string = "group";
341 break;
342 default:
343 break;
297 } 344 }
298 345
299 if (key_value) 346 char *label;
300 GNUNET_free(key_value); 347 GNUNET_asprintf (
348 &label,
349 "%s_%s",
350 type_string,
351 GNUNET_h2s(hash)
352 );
353
354 GNUNET_NAMESTORE_records_store(
355 context->handle->namestore,
356 zone,
357 label,
358 count,
359 data,
360 cont_context_write_records,
361 context
362 );
301 363
302destroy_config: 364 GNUNET_free(label);
303 GNUNET_CONFIGURATION_destroy(config);
304 return GNUNET_YES;
305} 365}
306 366
307void 367void
308context_scan_configs (struct GNUNET_CHAT_Handle *handle) 368context_delete_records (struct GNUNET_CHAT_Context *context)
309{ 369{
310 GNUNET_assert((handle) && (handle->messenger)); 370 GNUNET_assert((context) &&
371 (context->handle) &&
372 (context->room));
311 373
312 const char *directory = handle_get_directory(handle); 374 const struct GNUNET_IDENTITY_PrivateKey *zone = handle_get_key(
375 context->handle
376 );
313 377
314 if (!directory) 378 if (!zone)
315 return; 379 return;
316 380
317 char* dirname; 381 const struct GNUNET_HashCode *hash = GNUNET_MESSENGER_room_get_key(
318 util_get_dirname(directory, "chats", &dirname); 382 context->room
383 );
319 384
320 if (GNUNET_YES != GNUNET_DISK_directory_test(dirname, GNUNET_YES)) 385 const char *type_string = "chat";
321 goto free_dirname; 386
387 switch (context->type)
388 {
389 case GNUNET_CHAT_CONTEXT_TYPE_CONTACT:
390 type_string = "contact";
391 break;
392 case GNUNET_CHAT_CONTEXT_TYPE_GROUP:
393 type_string = "group";
394 break;
395 default:
396 break;
397 }
398
399 char *label;
400 GNUNET_asprintf (
401 &label,
402 "%s_%s",
403 type_string,
404 GNUNET_h2s(hash)
405 );
322 406
323 GNUNET_DISK_directory_scan( 407 GNUNET_NAMESTORE_records_store(
324 dirname, 408 context->handle->namestore,
325 callback_scan_for_configs, 409 zone,
326 handle 410 label,
411 0,
412 NULL,
413 cont_context_write_records,
414 context
327 ); 415 );
328 416
329free_dirname: 417 GNUNET_free(label);
330 GNUNET_free(dirname);
331} 418}
diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h
index f68ecb8..f0272f0 100644
--- a/src/gnunet_chat_context.h
+++ b/src/gnunet_chat_context.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V. 3 Copyright (C) 2021--2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,7 @@
29#include <gnunet/gnunet_common.h> 29#include <gnunet/gnunet_common.h>
30#include <gnunet/gnunet_configuration_lib.h> 30#include <gnunet/gnunet_configuration_lib.h>
31#include <gnunet/gnunet_container_lib.h> 31#include <gnunet/gnunet_container_lib.h>
32#include <gnunet/gnunet_gnsrecord_lib.h>
32#include <gnunet/gnunet_messenger_service.h> 33#include <gnunet/gnunet_messenger_service.h>
33#include <gnunet/gnunet_util_lib.h> 34#include <gnunet/gnunet_util_lib.h>
34 35
@@ -47,6 +48,7 @@ struct GNUNET_CHAT_Context
47 48
48 enum GNUNET_CHAT_ContextType type; 49 enum GNUNET_CHAT_ContextType type;
49 char *nick; 50 char *nick;
51 char *topic;
50 52
51 struct GNUNET_CONTAINER_MultiShortmap *timestamps; 53 struct GNUNET_CONTAINER_MultiShortmap *timestamps;
52 struct GNUNET_CONTAINER_MultiHashMap *messages; 54 struct GNUNET_CONTAINER_MultiHashMap *messages;
@@ -57,6 +59,8 @@ struct GNUNET_CHAT_Context
57 const struct GNUNET_MESSENGER_Contact *contact; 59 const struct GNUNET_MESSENGER_Contact *contact;
58 60
59 void *user_pointer; 61 void *user_pointer;
62
63 struct GNUNET_CONTAINER_MultiShortmap *member_pointers;
60}; 64};
61 65
62struct GNUNET_CHAT_Context* 66struct GNUNET_CHAT_Context*
@@ -79,12 +83,15 @@ context_update_nick (struct GNUNET_CHAT_Context *context,
79 const char *nick); 83 const char *nick);
80 84
81void 85void
82context_load_config (struct GNUNET_CHAT_Context *context); 86context_read_records (struct GNUNET_CHAT_Context *context,
87 const char *label,
88 unsigned int count,
89 const struct GNUNET_GNSRECORD_Data *data);
83 90
84void 91void
85context_save_config (const struct GNUNET_CHAT_Context *context); 92context_write_records (struct GNUNET_CHAT_Context *context);
86 93
87void 94void
88context_scan_configs (struct GNUNET_CHAT_Handle *handle); 95context_delete_records (struct GNUNET_CHAT_Context *context);
89 96
90#endif /* GNUNET_CHAT_CONTEXT_H_ */ 97#endif /* GNUNET_CHAT_CONTEXT_H_ */
diff --git a/src/gnunet_chat_context_intern.c b/src/gnunet_chat_context_intern.c
index ed1cd27..c4a3d5b 100644
--- a/src/gnunet_chat_context_intern.c
+++ b/src/gnunet_chat_context_intern.c
@@ -62,3 +62,19 @@ it_destroy_context_invites (GNUNET_UNUSED void *cls,
62 invitation_destroy(invitation); 62 invitation_destroy(invitation);
63 return GNUNET_YES; 63 return GNUNET_YES;
64} 64}
65
66void
67cont_context_write_records (void *cls,
68 GNUNET_UNUSED int32_t success,
69 const char *emsg)
70{
71 struct GNUNET_CHAT_Context *context = cls;
72
73 if (emsg)
74 handle_send_internal_message(
75 context->handle,
76 context,
77 GNUNET_CHAT_FLAG_WARNING,
78 emsg
79 );
80}
diff --git a/src/gnunet_chat_group.c b/src/gnunet_chat_group.c
index 7fcc98e..d102893 100644
--- a/src/gnunet_chat_group.c
+++ b/src/gnunet_chat_group.c
@@ -38,8 +38,6 @@ group_create_from_context (struct GNUNET_CHAT_Handle *handle,
38 group->handle = handle; 38 group->handle = handle;
39 group->context = context; 39 group->context = context;
40 40
41 group->topic = NULL;
42
43 group->announcement = NULL; 41 group->announcement = NULL;
44 group->search = NULL; 42 group->search = NULL;
45 43
@@ -64,9 +62,6 @@ group_destroy (struct GNUNET_CHAT_Group* group)
64 if (group->announcement) 62 if (group->announcement)
65 GNUNET_REGEX_announce_cancel(group->announcement); 63 GNUNET_REGEX_announce_cancel(group->announcement);
66 64
67 if (group->topic)
68 GNUNET_free(group->topic);
69
70 GNUNET_free(group); 65 GNUNET_free(group);
71} 66}
72 67
@@ -74,7 +69,8 @@ void
74group_publish (struct GNUNET_CHAT_Group* group) 69group_publish (struct GNUNET_CHAT_Group* group)
75{ 70{
76 GNUNET_assert((group) && 71 GNUNET_assert((group) &&
77 (group->topic) && 72 (group->context) &&
73 (group->context->topic) &&
78 (group->handle) && 74 (group->handle) &&
79 (group->handle->cfg)); 75 (group->handle->cfg));
80 76
@@ -82,7 +78,7 @@ group_publish (struct GNUNET_CHAT_Group* group)
82 GNUNET_asprintf ( 78 GNUNET_asprintf (
83 &topic, 79 &topic,
84 "GNUNET_CHAT_%s", 80 "GNUNET_CHAT_%s",
85 group->topic 81 group->context->topic
86 ); 82 );
87 83
88 group->announcement = GNUNET_REGEX_announce( 84 group->announcement = GNUNET_REGEX_announce(
@@ -98,82 +94,3 @@ group_publish (struct GNUNET_CHAT_Group* group)
98 94
99 GNUNET_free(topic); 95 GNUNET_free(topic);
100} 96}
101
102void
103group_load_config (struct GNUNET_CHAT_Group *group)
104{
105 GNUNET_assert((group) && (group->handle));
106
107 const char *directory = handle_get_directory(group->handle);
108
109 if ((!directory) || (!(group->context)))
110 return;
111
112 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
113 group->context->room
114 );
115
116 char* filename;
117 util_get_filename(directory, "groups", key, &filename);
118
119 if (GNUNET_YES != GNUNET_DISK_file_test(filename))
120 goto free_filename;
121
122 struct GNUNET_CONFIGURATION_Handle *config = GNUNET_CONFIGURATION_create();
123
124 if (GNUNET_OK != GNUNET_CONFIGURATION_load(config, filename))
125 goto destroy_config;
126
127 char* name = NULL;
128
129 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(
130 config, "group", "topic", &name))
131 util_set_name_field(name, &(group->topic));
132
133 if (name)
134 GNUNET_free(name);
135
136destroy_config:
137 GNUNET_CONFIGURATION_destroy(config);
138
139free_filename:
140 GNUNET_free(filename);
141}
142
143void
144group_save_config (const struct GNUNET_CHAT_Group *group)
145{
146 GNUNET_assert((group) && (group->handle));
147
148 const char *directory = handle_get_directory(group->handle);
149
150 if ((!directory) || (!(group->context)))
151 return;
152
153 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
154 group->context->room
155 );
156
157 struct GNUNET_CONFIGURATION_Handle *config = GNUNET_CONFIGURATION_create();
158
159 if (group->topic)
160 {
161 struct GNUNET_HashCode topic_hash;
162 GNUNET_CRYPTO_hash(group->topic, strlen(group->topic), &topic_hash);
163
164 if (0 == GNUNET_memcmp(key, &topic_hash))
165 GNUNET_CONFIGURATION_set_value_string(
166 config, "group", "topic", group->topic
167 );
168 }
169
170 char* filename;
171 util_get_filename(directory, "groups", key, &filename);
172
173 if (GNUNET_OK == GNUNET_DISK_directory_create_for_file(filename))
174 GNUNET_CONFIGURATION_write(config, filename);
175
176 GNUNET_CONFIGURATION_destroy(config);
177
178 GNUNET_free(filename);
179}
diff --git a/src/gnunet_chat_group.h b/src/gnunet_chat_group.h
index a02c8aa..4c2bf9d 100644
--- a/src/gnunet_chat_group.h
+++ b/src/gnunet_chat_group.h
@@ -39,8 +39,6 @@ struct GNUNET_CHAT_Group
39 struct GNUNET_CHAT_Handle *handle; 39 struct GNUNET_CHAT_Handle *handle;
40 struct GNUNET_CHAT_Context *context; 40 struct GNUNET_CHAT_Context *context;
41 41
42 char *topic;
43
44 struct GNUNET_REGEX_Announcement *announcement; 42 struct GNUNET_REGEX_Announcement *announcement;
45 struct GNUNET_REGEX_Search *search; 43 struct GNUNET_REGEX_Search *search;
46 44
@@ -59,10 +57,4 @@ group_destroy (struct GNUNET_CHAT_Group* group);
59void 57void
60group_publish (struct GNUNET_CHAT_Group* group); 58group_publish (struct GNUNET_CHAT_Group* group);
61 59
62void
63group_load_config (struct GNUNET_CHAT_Group *group);
64
65void
66group_save_config (const struct GNUNET_CHAT_Group *group);
67
68#endif /* GNUNET_CHAT_GROUP_H_ */ 60#endif /* GNUNET_CHAT_GROUP_H_ */
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
index 732dfbd..5205aa9 100644
--- a/src/gnunet_chat_handle.c
+++ b/src/gnunet_chat_handle.c
@@ -58,6 +58,7 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
58 58
59 handle->current = NULL; 59 handle->current = NULL;
60 handle->creation_op = NULL; 60 handle->creation_op = NULL;
61 handle->monitor = NULL;
61 62
62 handle->files = NULL; 63 handle->files = NULL;
63 handle->contexts = NULL; 64 handle->contexts = NULL;
@@ -78,6 +79,10 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
78 handle 79 handle
79 ); 80 );
80 81
82 handle->namestore = GNUNET_NAMESTORE_connect(
83 handle->cfg
84 );
85
81 handle->fs = NULL; 86 handle->fs = NULL;
82 handle->messenger = NULL; 87 handle->messenger = NULL;
83 88
@@ -114,12 +119,18 @@ handle_destroy (struct GNUNET_CHAT_Handle *handle)
114 if (handle->shutdown_hook) 119 if (handle->shutdown_hook)
115 GNUNET_SCHEDULER_cancel(handle->shutdown_hook); 120 GNUNET_SCHEDULER_cancel(handle->shutdown_hook);
116 121
122 if (handle->monitor)
123 GNUNET_NAMESTORE_zone_monitor_stop(handle->monitor);
124
117 if (handle->creation_op) 125 if (handle->creation_op)
118 GNUNET_IDENTITY_cancel(handle->creation_op); 126 GNUNET_IDENTITY_cancel(handle->creation_op);
119 127
120 if (handle->current) 128 if (handle->current)
121 handle_disconnect(handle); 129 handle_disconnect(handle);
122 130
131 if (handle->namestore)
132 GNUNET_NAMESTORE_disconnect(handle->namestore);
133
123 if (handle->identity) 134 if (handle->identity)
124 GNUNET_IDENTITY_disconnect(handle->identity); 135 GNUNET_IDENTITY_disconnect(handle->identity);
125 136
@@ -177,6 +188,12 @@ handle_connect (struct GNUNET_CHAT_Handle *handle,
177 (!(handle->contexts)) && 188 (!(handle->contexts)) &&
178 (!(handle->files))); 189 (!(handle->files)));
179 190
191 if (handle->monitor)
192 {
193 GNUNET_NAMESTORE_zone_monitor_stop(handle->monitor);
194 handle->monitor = NULL;
195 }
196
180 handle->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 197 handle->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
181 handle->contexts = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 198 handle->contexts = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
182 handle->contacts = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO); 199 handle->contacts = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
@@ -274,6 +291,19 @@ handle_get_directory (const struct GNUNET_CHAT_Handle *handle)
274 return handle->current->directory; 291 return handle->current->directory;
275} 292}
276 293
294const struct GNUNET_IDENTITY_PrivateKey*
295handle_get_key (const struct GNUNET_CHAT_Handle *handle)
296{
297 GNUNET_assert(handle);
298
299 if ((!(handle->current)) || (!(handle->current->ego)))
300 return NULL;
301
302 return GNUNET_IDENTITY_ego_get_private_key(
303 handle->current->ego
304 );
305}
306
277void 307void
278handle_send_internal_message (struct GNUNET_CHAT_Handle *handle, 308handle_send_internal_message (struct GNUNET_CHAT_Handle *handle,
279 struct GNUNET_CHAT_Context *context, 309 struct GNUNET_CHAT_Context *context,
@@ -351,7 +381,6 @@ handle_request_context_by_room (struct GNUNET_CHAT_Handle *handle,
351 return GNUNET_OK; 381 return GNUNET_OK;
352 382
353 context = context_create_from_room(handle, room); 383 context = context_create_from_room(handle, room);
354 context_load_config(context);
355 384
356 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put( 385 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
357 handle->contexts, key, context, 386 handle->contexts, key, context,
@@ -376,9 +405,14 @@ check_type:
376 (GNUNET_OK == intern_provide_contact_for_member(handle, 405 (GNUNET_OK == intern_provide_contact_for_member(handle,
377 check.contact, 406 check.contact,
378 context))) 407 context)))
408 {
409 context_delete_records(context);
379 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT; 410 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
411 context_write_records(context);
412 }
380 else if (checks >= 2) 413 else if (checks >= 2)
381 { 414 {
415 context_delete_records(context);
382 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP; 416 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
383 417
384 if (context->contact) 418 if (context->contact)
@@ -405,9 +439,7 @@ setup_group:
405 handle, context 439 handle, context
406 ); 440 );
407 441
408 group_load_config(group); 442 if (context->topic)
409
410 if (group->topic)
411 group_publish(group); 443 group_publish(group);
412 444
413 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put( 445 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(
@@ -421,6 +453,7 @@ setup_group:
421 NULL 453 NULL
422 ); 454 );
423 455
456 context_write_records(context);
424 return GNUNET_OK; 457 return GNUNET_OK;
425 } 458 }
426 459
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
index 6004e5d..0713bf1 100644
--- a/src/gnunet_chat_handle.h
+++ b/src/gnunet_chat_handle.h
@@ -33,6 +33,7 @@
33#include <gnunet/gnunet_fs_service.h> 33#include <gnunet/gnunet_fs_service.h>
34#include <gnunet/gnunet_identity_service.h> 34#include <gnunet/gnunet_identity_service.h>
35#include <gnunet/gnunet_messenger_service.h> 35#include <gnunet/gnunet_messenger_service.h>
36#include <gnunet/gnunet_namestore_service.h>
36#include <gnunet/gnunet_scheduler_lib.h> 37#include <gnunet/gnunet_scheduler_lib.h>
37#include <gnunet/gnunet_util_lib.h> 38#include <gnunet/gnunet_util_lib.h>
38 39
@@ -72,6 +73,7 @@ struct GNUNET_CHAT_Handle
72 73
73 const struct GNUNET_CHAT_Account *current; 74 const struct GNUNET_CHAT_Account *current;
74 struct GNUNET_IDENTITY_Operation *creation_op; 75 struct GNUNET_IDENTITY_Operation *creation_op;
76 struct GNUNET_NAMESTORE_ZoneMonitor *monitor;
75 77
76 struct GNUNET_CONTAINER_MultiHashMap *files; 78 struct GNUNET_CONTAINER_MultiHashMap *files;
77 struct GNUNET_CONTAINER_MultiHashMap *contexts; 79 struct GNUNET_CONTAINER_MultiHashMap *contexts;
@@ -82,6 +84,7 @@ struct GNUNET_CHAT_Handle
82 struct GNUNET_FS_Handle *fs; 84 struct GNUNET_FS_Handle *fs;
83 struct GNUNET_IDENTITY_Handle *identity; 85 struct GNUNET_IDENTITY_Handle *identity;
84 struct GNUNET_MESSENGER_Handle *messenger; 86 struct GNUNET_MESSENGER_Handle *messenger;
87 struct GNUNET_NAMESTORE_Handle *namestore;
85 88
86 char *public_key; 89 char *public_key;
87 void *user_pointer; 90 void *user_pointer;
@@ -109,6 +112,9 @@ handle_disconnect (struct GNUNET_CHAT_Handle *handle);
109const char* 112const char*
110handle_get_directory (const struct GNUNET_CHAT_Handle *handle); 113handle_get_directory (const struct GNUNET_CHAT_Handle *handle);
111 114
115const struct GNUNET_IDENTITY_PrivateKey*
116handle_get_key (const struct GNUNET_CHAT_Handle *handle);
117
112void 118void
113handle_send_internal_message (struct GNUNET_CHAT_Handle *handle, 119handle_send_internal_message (struct GNUNET_CHAT_Handle *handle,
114 struct GNUNET_CHAT_Context *context, 120 struct GNUNET_CHAT_Context *context,
diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c
index d3f4694..0662850 100644
--- a/src/gnunet_chat_handle_intern.c
+++ b/src/gnunet_chat_handle_intern.c
@@ -64,6 +64,12 @@ on_handle_arm_connection(void *cls,
64 GNUNET_OS_INHERIT_STD_NONE, 64 GNUNET_OS_INHERIT_STD_NONE,
65 NULL, NULL 65 NULL, NULL
66 ); 66 );
67
68 GNUNET_ARM_request_service_start(
69 chat->arm, "namestore",
70 GNUNET_OS_INHERIT_STD_NONE,
71 NULL, NULL
72 );
67 } else { 73 } else {
68 GNUNET_ARM_request_service_start( 74 GNUNET_ARM_request_service_start(
69 chat->arm, "arm", 75 chat->arm, "arm",
@@ -359,6 +365,93 @@ scan_handle_room_members (void* cls,
359} 365}
360 366
361void 367void
368on_monitor_namestore_record(void *cls,
369 GNUNET_UNUSED const
370 struct GNUNET_IDENTITY_PrivateKey *zone,
371 const char *label,
372 unsigned int count,
373 const struct GNUNET_GNSRECORD_Data *data)
374{
375 struct GNUNET_CHAT_Handle *chat = cls;
376
377 if (count <= 0)
378 goto skip_records;
379
380 const struct GNUNET_MESSENGER_RoomEntryRecord *record = NULL;
381
382 for (unsigned int i = 0; i < count; i++)
383 {
384 if (GNUNET_YES == GNUNET_GNSRECORD_is_expired(data + i))
385 continue;
386
387 if ((GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY == data[i].record_type) &&
388 (!(GNUNET_GNSRECORD_RF_SUPPLEMENTAL & data[i].flags)))
389 {
390 record = data[i].data;
391 break;
392 }
393 }
394
395 if (!record)
396 goto skip_records;
397
398 struct GNUNET_CHAT_Context *context = GNUNET_CONTAINER_multihashmap_get(
399 chat->contexts,
400 &(record->key)
401 );
402
403 if (context)
404 {
405 context_read_records(context, label, count, data);
406
407 printf("PATCH: %s %u %d %s\n", label, count, (int) context->type, context->topic);
408
409 goto skip_records;
410 }
411
412 struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_enter_room(
413 chat->messenger,
414 &(record->door),
415 &(record->key)
416 );
417
418 if (!room)
419 goto skip_records;
420
421 context = context_create_from_room(chat, room);
422 context_read_records(context, label, count, data);
423
424 printf("READ: %s %u %d %s\n", label, count, (int) context->type, context->topic);
425
426 handle_send_room_name(chat, room);
427
428 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
429 chat->contexts, &(record->key), context,
430 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
431 {
432 context_destroy(context);
433 goto skip_records;
434 }
435
436 if (GNUNET_CHAT_CONTEXT_TYPE_GROUP != context->type)
437 goto skip_records;
438
439 struct GNUNET_CHAT_Group *group = group_create_from_context(chat, context);
440
441 if (context->topic)
442 group_publish(group);
443
444 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
445 chat->groups, &(record->key), group,
446 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
447 group_destroy(group);
448
449skip_records:
450 if (chat->monitor)
451 GNUNET_NAMESTORE_zone_monitor_next(chat->monitor, 1);
452}
453
454void
362on_handle_identity(void *cls, 455on_handle_identity(void *cls,
363 GNUNET_UNUSED struct GNUNET_MESSENGER_Handle *messenger) 456 GNUNET_UNUSED struct GNUNET_MESSENGER_Handle *messenger)
364{ 457{
@@ -377,7 +470,8 @@ on_handle_identity(void *cls,
377 return; 470 return;
378 471
379 GNUNET_assert(handle->messenger); 472 GNUNET_assert(handle->messenger);
380 context_scan_configs(handle); 473
474 printf("HURRAY!\n");
381 475
382 handle_send_internal_message( 476 handle_send_internal_message(
383 handle, 477 handle,
@@ -385,6 +479,23 @@ on_handle_identity(void *cls,
385 GNUNET_CHAT_FLAG_LOGIN, 479 GNUNET_CHAT_FLAG_LOGIN,
386 NULL 480 NULL
387 ); 481 );
482
483 const struct GNUNET_IDENTITY_PrivateKey *zone = handle_get_key(handle);
484
485 if ((!zone) || (handle->monitor))
486 return;
487
488 handle->monitor = GNUNET_NAMESTORE_zone_monitor_start(
489 handle->cfg,
490 zone,
491 GNUNET_YES,
492 NULL,
493 NULL,
494 on_monitor_namestore_record,
495 handle,
496 NULL,
497 NULL
498 );
388} 499}
389 500
390void 501void
@@ -583,7 +694,6 @@ it_destroy_handle_groups (GNUNET_UNUSED void *cls,
583 GNUNET_assert(value); 694 GNUNET_assert(value);
584 695
585 struct GNUNET_CHAT_Group *group = value; 696 struct GNUNET_CHAT_Group *group = value;
586 group_save_config(group);
587 group_destroy(group); 697 group_destroy(group);
588 return GNUNET_YES; 698 return GNUNET_YES;
589} 699}
@@ -608,7 +718,6 @@ it_destroy_handle_contexts (GNUNET_UNUSED void *cls,
608 GNUNET_assert(value); 718 GNUNET_assert(value);
609 719
610 struct GNUNET_CHAT_Context *context = value; 720 struct GNUNET_CHAT_Context *context = value;
611 context_save_config(context);
612 context_destroy(context); 721 context_destroy(context);
613 return GNUNET_YES; 722 return GNUNET_YES;
614} 723}
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
index 16fb27d..8c6a109 100644
--- a/src/gnunet_chat_lib.c
+++ b/src/gnunet_chat_lib.c
@@ -310,6 +310,8 @@ GNUNET_CHAT_group_create (struct GNUNET_CHAT_Handle *handle,
310 310
311 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP; 311 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
312 312
313 util_set_name_field(topic, &(context->topic));
314
313 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put( 315 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
314 handle->contexts, &key, context, 316 handle->contexts, &key, context,
315 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 317 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
@@ -317,15 +319,16 @@ GNUNET_CHAT_group_create (struct GNUNET_CHAT_Handle *handle,
317 319
318 struct GNUNET_CHAT_Group *group = group_create_from_context(handle, context); 320 struct GNUNET_CHAT_Group *group = group_create_from_context(handle, context);
319 321
320 util_set_name_field(topic, &(group->topic)); 322 if (context->topic)
321
322 if (group->topic)
323 group_publish(group); 323 group_publish(group);
324 324
325 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put( 325 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(
326 handle->groups, &key, group, 326 handle->groups, &key, group,
327 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 327 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
328 {
329 context_write_records(context);
328 return group; 330 return group;
331 }
329 332
330 group_destroy(group); 333 group_destroy(group);
331 334
@@ -513,10 +516,13 @@ GNUNET_CHAT_group_set_name (struct GNUNET_CHAT_Group *group,
513const char* 516const char*
514GNUNET_CHAT_group_get_name (const struct GNUNET_CHAT_Group *group) 517GNUNET_CHAT_group_get_name (const struct GNUNET_CHAT_Group *group)
515{ 518{
516 if (!group) 519 if ((!group) || (!(group->context)))
517 return NULL; 520 return NULL;
518 521
519 return group->context->nick; 522 if (group->context->nick)
523 return group->context->nick;
524
525 return group->context->topic;
520} 526}
521 527
522 528
@@ -911,6 +917,43 @@ GNUNET_CHAT_context_iterate_files (struct GNUNET_CHAT_Context *context,
911} 917}
912 918
913 919
920void
921GNUNET_CHAT_member_set_user_pointer (struct GNUNET_CHAT_Context *context,
922 const struct GNUNET_CHAT_Contact *member,
923 void *user_pointer)
924{
925 if ((!context) || (!member))
926 return;
927
928 struct GNUNET_ShortHashCode hash;
929 util_shorthash_from_member(member->member, &hash);
930
931 GNUNET_CONTAINER_multishortmap_put(
932 context->member_pointers,
933 &hash,
934 user_pointer,
935 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
936 );
937}
938
939
940void*
941GNUNET_CHAT_member_get_user_pointer (const struct GNUNET_CHAT_Context *context,
942 const struct GNUNET_CHAT_Contact *member)
943{
944 if ((!context) || (!member))
945 return NULL;
946
947 struct GNUNET_ShortHashCode hash;
948 util_shorthash_from_member(member->member, &hash);
949
950 return GNUNET_CONTAINER_multishortmap_get(
951 context->member_pointers,
952 &hash
953 );
954}
955
956
914enum GNUNET_CHAT_MessageKind 957enum GNUNET_CHAT_MessageKind
915GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message) 958GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message)
916{ 959{