aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet_chat_handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnunet_chat_handle.c')
-rw-r--r--src/gnunet_chat_handle.c653
1 files changed, 42 insertions, 611 deletions
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
index 84539c5..11b57ac 100644
--- a/src/gnunet_chat_handle.c
+++ b/src/gnunet_chat_handle.c
@@ -22,642 +22,73 @@
22 * @file gnunet_chat_handle.c 22 * @file gnunet_chat_handle.c
23 */ 23 */
24 24
25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_handle.h" 25#include "gnunet_chat_handle.h"
27#include "gnunet_chat_group.h"
28#include "gnunet_chat_contact.h"
29#include "gnunet_chat_message.h"
30#include "gnunet_chat_file.h"
31 26
32static void* 27#include "gnunet_chat_handle_intern.c"
33handle_fs_progress(void* cls, const struct GNUNET_FS_ProgressInfo* info)
34{
35 struct GNUNET_CHAT_Handle *chat = cls;
36
37 if (!chat)
38 return NULL;
39
40 switch (info->status) {
41 case GNUNET_FS_STATUS_PUBLISH_START: {
42 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
43 publication->progress = 0.0f;
44
45 GNUNET_SCHEDULER_add_now(&CGTK_publication_progress, publication);
46
47 return publication;*/
48 } case GNUNET_FS_STATUS_PUBLISH_PROGRESS: {
49 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
50 publication->progress = 1.0f * info->value.publish.completed / info->value.publish.size;
51
52 GNUNET_SCHEDULER_add_now(&CGTK_publication_progress, publication);
53
54 return publication;*/
55 } case GNUNET_FS_STATUS_PUBLISH_COMPLETED: {
56 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
57 publication->uri = GNUNET_FS_uri_dup(info->value.publish.specifics.completed.chk_uri);
58 publication->progress = 1.0f;
59
60 GNUNET_SCHEDULER_add_now(&CGTK_publication_finish, publication);*/
61 break;
62 } case GNUNET_FS_STATUS_PUBLISH_ERROR: {
63 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
64
65 GNUNET_SCHEDULER_add_now(&CGTK_publication_error, publication);*/
66 break;
67 } case GNUNET_FS_STATUS_DOWNLOAD_START: {
68 /*request_t* request = (request_t*) info->value.download.cctx;
69 request->progress = 0.0f;
70
71 return request;*/
72 } case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: {
73 return info->value.download.cctx;
74 } case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: {
75 return info->value.download.cctx;
76 } case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: {
77 /*request_t* request = (request_t*) info->value.download.cctx;
78 request->progress = 1.0f * info->value.download.completed / info->value.download.size;
79
80 GNUNET_SCHEDULER_add_now(&CGTK_request_progress, request);
81
82 return request;*/
83 } case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: {
84 /*request_t* request = (request_t*) info->value.download.cctx;
85 request->progress = 1.0f;
86
87 GNUNET_SCHEDULER_add_now(&CGTK_request_finish, request);*/
88 break;
89 } case GNUNET_FS_STATUS_DOWNLOAD_ERROR: {
90 /*request_t *request = (request_t *) info->value.download.cctx;
91
92 GNUNET_SCHEDULER_add_now(&CGTK_request_error, request);*/
93 break;
94 } case GNUNET_FS_STATUS_UNINDEX_START: {
95 /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
96 publication->progress = 0.0f;
97
98 return publication;*/
99 } case GNUNET_FS_STATUS_UNINDEX_PROGRESS: {
100 /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
101 publication->progress = 1.0f * info->value.unindex.completed / info->value.unindex.size;
102
103 return publication;*/
104 } case GNUNET_FS_STATUS_UNINDEX_COMPLETED: {
105 /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
106 publication->progress = 1.0f;
107
108 GNUNET_SCHEDULER_add_now(&CGTK_publication_unindex_finish, publication);*/
109 break;
110 } default: {
111 break;
112 }
113 }
114
115 return NULL;
116}
117
118static void
119handle_on_message (void *cls,
120 GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
121 GNUNET_UNUSED const struct GNUNET_MESSENGER_Contact *sender,
122 const struct GNUNET_MESSENGER_Message *message,
123 const struct GNUNET_HashCode *hash,
124 GNUNET_UNUSED enum GNUNET_MESSENGER_MessageFlags flags)
125{
126 struct GNUNET_CHAT_Handle *chat = cls;
127
128 //TODO
129
130 struct GNUNET_CHAT_Message msg;
131 GNUNET_memcpy(&(msg.hash), hash, sizeof(msg.hash));
132 msg.message = message;
133
134 if ((GNUNET_CHAT_KIND_UNKNOWN == GNUNET_CHAT_message_get_kind(&msg)) ||
135 (!chat->msg_cb))
136 return;
137
138 chat->msg_cb(chat->msg_cls, NULL /* TODO */, &msg);
139}
140
141struct GNUNET_CHAT_CheckRoomMembers
142{
143 const struct GNUNET_IDENTITY_PublicKey *ignore_key;
144 const struct GNUNET_MESSENGER_Contact *contact;
145};
146
147static int
148handle_check_room_members (void* cls,
149 GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
150 const struct GNUNET_MESSENGER_Contact *contact)
151{
152 struct GNUNET_CHAT_CheckRoomMembers *check = cls;
153 const struct GNUNET_IDENTITY_PublicKey *contact_key = (
154 GNUNET_MESSENGER_contact_get_key(contact)
155 );
156
157 if (0 == GNUNET_memcmp(contact_key, check->ignore_key))
158 return GNUNET_YES;
159
160 if (check->contact)
161 return GNUNET_NO;
162
163 check->contact = contact;
164 return GNUNET_YES;
165}
166
167static int
168handle_initialize_context (void *cls, struct GNUNET_MESSENGER_Room *room,
169 GNUNET_UNUSED const struct GNUNET_MESSENGER_Contact *contact)
170{
171 struct GNUNET_CHAT_Handle *chat = cls;
172
173 struct GNUNET_CHAT_CheckRoomMembers check;
174 check.ignore_key = GNUNET_CHAT_get_key(chat);
175 check.contact = NULL;
176
177 const int amount = GNUNET_MESSENGER_iterate_members(
178 room, handle_check_room_members, &check
179 );
180
181 if (amount <= 1)
182 return GNUNET_YES;
183
184 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(room);
185 struct GNUNET_CHAT_Context *context = handle_get_chat_context(chat, key);
186 enum GNUNET_CHAT_ContextType type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN;
187
188 if (check.contact)
189 type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
190 else
191 type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
192
193 if (!context)
194 context = context_create(chat, type, key);
195 else
196 context->type = type;
197
198 if (GNUNET_YES != handle_update_chat_context(chat, context, GNUNET_NO))
199 context_destroy(context);
200
201 return GNUNET_YES;
202}
203
204static void
205handle_on_identity(void *cls, struct GNUNET_MESSENGER_Handle *handle)
206{
207 struct GNUNET_CHAT_Handle *chat = cls;
208
209 //TODO
210
211 GNUNET_MESSENGER_find_rooms(
212 chat->handles.messenger, NULL, handle_initialize_context, handle
213 );
214}
215
216static void
217handle_arm_connection(void *cls, int connected)
218{
219 struct GNUNET_CHAT_Handle *chat = cls;
220
221 if (GNUNET_YES == connected) {
222 GNUNET_ARM_request_service_start(chat->handles.arm, "messenger",
223 GNUNET_OS_INHERIT_STD_NONE, NULL, NULL);
224 GNUNET_ARM_request_service_start(chat->handles.arm, "fs",
225 GNUNET_OS_INHERIT_STD_NONE, NULL, NULL);
226 } else {
227 GNUNET_ARM_request_service_start(chat->handles.arm, "arm",
228 GNUNET_OS_INHERIT_STD_NONE, NULL, NULL);
229 }
230}
231 28
232struct GNUNET_CHAT_Handle* 29struct GNUNET_CHAT_Handle*
233GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle* cfg, 30handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
234 const char *name, 31 const char* name,
235 GNUNET_CHAT_WarningCallback warn_cb, 32 GNUNET_CHAT_ContextMessageCallback msg_cb,
236 void *warn_cls, 33 void *msg_cls,
237 GNUNET_CHAT_ContextMessageCallback msg_cb, 34 GNUNET_CHAT_WarningCallback warn_cb,
238 void *msg_cls) 35 void *warn_cls)
239{ 36{
240 if (!cfg) 37 struct GNUNET_CHAT_Handle* handle = GNUNET_new(struct GNUNET_CHAT_Handle);
241 return NULL;
242 38
243 struct GNUNET_CHAT_Handle *chat = GNUNET_new(struct GNUNET_CHAT_Handle); 39 handle->cfg = cfg;
244 memset(chat, 0, sizeof(*chat));
245 chat->cfg = cfg;
246 40
247 chat->warn_cb = warn_cb; 41 handle->msg_cb = msg_cb;
248 chat->warn_cls = warn_cls; 42 handle->msg_cls = msg_cls;
249 43
250 chat->handles.arm = GNUNET_ARM_connect(cfg, &handle_arm_connection, chat); 44 handle->warn_cb = warn_cb;
45 handle->warn_cls = warn_cls;
251 46
252 if (chat->handles.arm) 47 handle->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
253 handle_arm_connection(chat, GNUNET_NO); 48 handle->contexts = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
49 handle->contacts = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
50 handle->groups = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
254 51
255 chat->handles.messenger = GNUNET_MESSENGER_connect( 52 handle->arm = GNUNET_ARM_connect(
256 cfg, name, 53 handle->cfg,
257 handle_on_identity, chat, 54 on_handle_arm_connection, handle
258 handle_on_message, chat
259 ); 55 );
260 56
261 if (!chat->handles.messenger) 57 if (handle->arm)
262 { 58 on_handle_arm_connection(handle, GNUNET_NO);
263 GNUNET_CHAT_stop(chat);
264 return NULL;
265 }
266 59
267 chat->handles.fs = GNUNET_FS_start( 60 handle->fs = GNUNET_FS_start(
268 cfg, 61 handle->cfg, name, // TODO: raw name?
269 name, 62 notify_handle_fs_progress, handle,
270 handle_fs_progress,
271 chat,
272 GNUNET_FS_FLAGS_NONE, 63 GNUNET_FS_FLAGS_NONE,
273 GNUNET_FS_OPTIONS_END 64 GNUNET_FS_OPTIONS_END
274 ); 65 );
275 66
276 chat->contacts.short_map = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO); 67 handle->messenger = GNUNET_MESSENGER_connect(
277 chat->contacts.hash_map = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 68 handle->cfg, name,
278 69 on_handle_identity, handle,
279 chat->groups = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 70 on_handle_message, handle
280 chat->contexts = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 71 );
281 chat->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
282
283 chat->msg_cb = msg_cb;
284 chat->msg_cls = msg_cls;
285
286 return chat;
287}
288
289static int
290handle_iterate_destroy_contacts (GNUNET_UNUSED void *cls,
291 GNUNET_UNUSED const struct GNUNET_HashCode *key,
292 void *value)
293{
294 struct GNUNET_CHAT_Contact *contact = value;
295 contact_destroy(contact);
296 return GNUNET_YES;
297}
298 72
299static int 73 return handle;
300handle_iterate_destroy_groups (GNUNET_UNUSED void *cls,
301 GNUNET_UNUSED const struct GNUNET_HashCode *key,
302 void *value)
303{
304 struct GNUNET_CHAT_Group *group = value;
305 group_destroy(group);
306 return GNUNET_YES;
307} 74}
308 75
309void 76void
310GNUNET_CHAT_stop (struct GNUNET_CHAT_Handle *handle) 77handle_destroy (struct GNUNET_CHAT_Handle* handle)
311{ 78{
312 if (!handle) 79 if (handle->messenger)
313 return; 80 GNUNET_MESSENGER_disconnect(handle->messenger);
314
315 if (handle->handles.fs)
316 {
317 // TODO: stop each action
318
319 GNUNET_FS_stop(handle->handles.fs);
320 handle->handles.fs = NULL;
321 }
322
323 if (handle->handles.messenger)
324 {
325 // TODO: stop everything related
326
327 GNUNET_MESSENGER_disconnect(handle->handles.messenger);
328 handle->handles.messenger = NULL;
329 }
330 81
331 if (handle->groups) 82 if (handle->files)
332 { 83 GNUNET_FS_stop(handle->fs);
333 GNUNET_CONTAINER_multihashmap_iterate(
334 handle->groups, handle_iterate_destroy_groups, NULL
335 );
336 84
337 GNUNET_CONTAINER_multihashmap_destroy(handle->groups); 85 if (handle->arm)
338 handle->groups = NULL; 86 GNUNET_ARM_disconnect(handle->arm);
339 }
340 87
341 if (handle->contacts.hash_map) 88 GNUNET_CONTAINER_multihashmap_destroy(handle->groups);
342 { 89 GNUNET_CONTAINER_multishortmap_destroy(handle->contacts);
343 GNUNET_CONTAINER_multihashmap_iterate( 90 GNUNET_CONTAINER_multihashmap_destroy(handle->contexts);
344 handle->contacts.hash_map, handle_iterate_destroy_contacts, NULL 91 GNUNET_CONTAINER_multihashmap_destroy(handle->files);
345 );
346
347 GNUNET_CONTAINER_multihashmap_destroy(handle->contacts.hash_map);
348 handle->contacts.hash_map = NULL;
349 }
350
351 if (handle->contacts.short_map)
352 {
353 GNUNET_CONTAINER_multishortmap_destroy(handle->contacts.short_map);
354 handle->contacts.short_map = NULL;
355 }
356
357 if (handle->handles.arm)
358 {
359 //TODO: stop started services?
360
361 GNUNET_ARM_disconnect(handle->handles.arm);
362 handle->handles.arm = NULL;
363 }
364 92
365 GNUNET_free(handle); 93 GNUNET_free(handle);
366} 94}
367
368int
369GNUNET_CHAT_update (struct GNUNET_CHAT_Handle *handle)
370{
371 if (!handle)
372 return GNUNET_SYSERR;
373
374 return GNUNET_MESSENGER_update(handle->handles.messenger);
375}
376
377int
378GNUNET_CHAT_set_name (struct GNUNET_CHAT_Handle *handle,
379 const char *name)
380{
381 if (!handle)
382 return GNUNET_SYSERR;
383
384 return GNUNET_MESSENGER_set_name(handle->handles.messenger, name);
385}
386
387const char*
388GNUNET_CHAT_get_name (const struct GNUNET_CHAT_Handle *handle)
389{
390 if (!handle)
391 return NULL;
392
393 return GNUNET_MESSENGER_get_name(handle->handles.messenger);
394}
395
396const struct GNUNET_IDENTITY_PublicKey*
397GNUNET_CHAT_get_key (const struct GNUNET_CHAT_Handle *handle)
398{
399 if (!handle)
400 return NULL;
401
402 return GNUNET_MESSENGER_get_key(handle->handles.messenger);
403}
404
405struct GNUNET_CHAT_IterateContacts
406{
407 struct GNUNET_CHAT_Handle *handle;
408 GNUNET_CHAT_ContactCallback callback;
409 void *cls;
410};
411
412static int
413handle_iterate_contacts(void *cls,
414 GNUNET_UNUSED const struct GNUNET_HashCode *key,
415 void *value)
416{
417 struct GNUNET_CHAT_IterateContacts *iterate = cls;
418 struct GNUNET_CHAT_Contact *contact = value;
419
420 if (!iterate->callback)
421 return GNUNET_YES;
422
423 return iterate->callback(iterate->cls, iterate->handle, contact);
424}
425
426int
427GNUNET_CHAT_iterate_contacts (struct GNUNET_CHAT_Handle *handle,
428 GNUNET_CHAT_ContactCallback callback,
429 void *cls)
430{
431 if (!handle)
432 return GNUNET_SYSERR;
433
434 struct GNUNET_CHAT_IterateContacts iterate;
435 iterate.handle = handle;
436 iterate.callback = callback;
437 iterate.cls = cls;
438
439 return GNUNET_CONTAINER_multihashmap_iterate(handle->contacts.hash_map,
440 handle_iterate_contacts,
441 &iterate);
442}
443
444struct GNUNET_CHAT_Group*
445GNUNET_CHAT_group_create (struct GNUNET_CHAT_Handle *handle,
446 const char *topic)
447{
448 if (!handle)
449 return NULL;
450
451 struct GNUNET_CHAT_Group *group = group_create(handle, topic);
452
453 if (!group)
454 return NULL;
455
456 if (GNUNET_YES != handle_update_chat_group(handle, group, GNUNET_NO))
457 {
458 group_destroy(group);
459 return NULL;
460 }
461
462 return group;
463}
464
465struct GNUNET_CHAT_IterateGroups
466{
467 struct GNUNET_CHAT_Handle *handle;
468 GNUNET_CHAT_GroupCallback callback;
469 void *cls;
470};
471
472static int
473handle_iterate_groups(void *cls,
474 GNUNET_UNUSED const struct GNUNET_HashCode *key,
475 void *value)
476{
477 struct GNUNET_CHAT_IterateGroups *iterate = cls;
478 struct GNUNET_CHAT_Group *group = value;
479
480 if (!iterate->callback)
481 return GNUNET_YES;
482
483 return iterate->callback(iterate->cls, iterate->handle, group);
484}
485
486int
487GNUNET_CHAT_iterate_groups (struct GNUNET_CHAT_Handle *handle,
488 GNUNET_CHAT_GroupCallback callback,
489 void *cls)
490{
491 if (!handle)
492 return GNUNET_SYSERR;
493
494 struct GNUNET_CHAT_IterateGroups iterate;
495 iterate.handle = handle;
496 iterate.callback = callback;
497 iterate.cls = cls;
498
499 return GNUNET_CONTAINER_multihashmap_iterate(handle->groups,
500 handle_iterate_groups,
501 &iterate);
502}
503
504int
505handle_update_chat_contact (struct GNUNET_CHAT_Handle *handle,
506 struct GNUNET_CHAT_Contact *chatContact,
507 int removeContact)
508{
509 const struct GNUNET_HashCode *key = context_get_key(chatContact->context);
510
511 if (GNUNET_YES == removeContact)
512 {
513 const int result = GNUNET_CONTAINER_multihashmap_remove(
514 handle->contacts.hash_map, key, chatContact
515 );
516
517 if (GNUNET_YES == result)
518 return handle_update_chat_context(handle, chatContact->context,
519 GNUNET_YES);
520 else
521 return GNUNET_NO;
522 }
523 else
524 {
525 const int result = GNUNET_CONTAINER_multihashmap_put(
526 handle->contacts.hash_map, key, chatContact,
527 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
528 );
529
530 if (GNUNET_OK != result)
531 return GNUNET_NO;
532 else
533 return handle_update_chat_context(handle, chatContact->context,
534 GNUNET_NO);
535 }
536}
537
538int
539handle_update_chat_group (struct GNUNET_CHAT_Handle *handle,
540 struct GNUNET_CHAT_Group *chatGroup,
541 int removeGroup)
542{
543 const struct GNUNET_HashCode *key = context_get_key(chatGroup->context);
544
545 if (GNUNET_YES == removeGroup)
546 {
547 const int result = GNUNET_CONTAINER_multihashmap_remove(
548 handle->groups, key, chatGroup
549 );
550
551 if (GNUNET_YES == result)
552 return handle_update_chat_context(handle, chatGroup->context,
553 GNUNET_YES);
554 else
555 return GNUNET_NO;
556 }
557 else
558 {
559 const int result = GNUNET_CONTAINER_multihashmap_put(
560 handle->groups, key, chatGroup,
561 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
562 );
563
564 if (GNUNET_OK != result)
565 return GNUNET_NO;
566 else
567 return handle_update_chat_context(handle, chatGroup->context,
568 GNUNET_NO);
569 }
570}
571
572int
573handle_update_chat_context (struct GNUNET_CHAT_Handle *handle,
574 struct GNUNET_CHAT_Context *context,
575 int removeContext)
576{
577 const struct GNUNET_HashCode *key = context_get_key(context);
578
579 if (GNUNET_YES == removeContext)
580 return GNUNET_CONTAINER_multihashmap_remove(
581 handle->contexts, key, context
582 );
583 else
584 {
585 const int result = GNUNET_CONTAINER_multihashmap_put(
586 handle->contexts, key, context,
587 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
588 );
589
590 if (GNUNET_OK != result)
591 return GNUNET_NO;
592 else
593 return GNUNET_YES;
594 }
595}
596
597int
598handle_update_chat_file (struct GNUNET_CHAT_Handle *handle,
599 struct GNUNET_CHAT_File *file,
600 int removeFile)
601{
602 const struct GNUNET_HashCode *hash = GNUNET_CHAT_file_get_hash(file);
603
604 if (GNUNET_YES == removeFile)
605 return GNUNET_CONTAINER_multihashmap_remove(
606 handle->files, hash, file
607 );
608 else
609 {
610 const int result = GNUNET_CONTAINER_multihashmap_put(
611 handle->files, hash, file,
612 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
613 );
614
615 if (GNUNET_OK != result)
616 return GNUNET_NO;
617 else
618 return GNUNET_YES;
619 }
620}
621
622static void
623handle_get_short_of_contact(struct GNUNET_ShortHashCode *shortHash,
624 const struct GNUNET_MESSENGER_Contact *contact)
625{
626 memset(shortHash, 0, sizeof(*shortHash));
627 GNUNET_memcpy(shortHash, &contact, sizeof(contact));
628}
629
630struct GNUNET_CHAT_Contact*
631handle_get_chat_contact (struct GNUNET_CHAT_Handle *handle,
632 const struct GNUNET_MESSENGER_Contact *contact)
633{
634 struct GNUNET_ShortHashCode shortHash;
635 handle_get_short_of_contact (&shortHash, contact);
636
637 struct GNUNET_CHAT_Contact* chatContact = GNUNET_CONTAINER_multishortmap_get(
638 handle->contacts.short_map, &shortHash
639 );
640
641 return chatContact;
642}
643
644void
645handle_set_chat_contact (struct GNUNET_CHAT_Handle *handle,
646 const struct GNUNET_MESSENGER_Contact *contact,
647 struct GNUNET_CHAT_Contact *chatContact)
648{
649 struct GNUNET_ShortHashCode shortHash;
650 handle_get_short_of_contact (&shortHash, contact);
651
652 if (chatContact)
653 {
654 GNUNET_CONTAINER_multishortmap_remove_all(handle->contacts.short_map,
655 &shortHash);
656 return;
657 }
658
659 GNUNET_CONTAINER_multishortmap_put(
660 handle->contacts.short_map, &shortHash, chatContact,
661 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
662 );
663}