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.c482
1 files changed, 447 insertions, 35 deletions
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
index 6e2f32e..84539c5 100644
--- a/src/gnunet_chat_handle.c
+++ b/src/gnunet_chat_handle.c
@@ -25,57 +25,285 @@
25#include "gnunet_chat_lib.h" 25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_handle.h" 26#include "gnunet_chat_handle.h"
27#include "gnunet_chat_group.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"
28 31
29static void handle_arm_connection(void* cls, int connected) { 32static void*
30 struct GNUNET_CHAT_Handle *handle = cls; 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;
31 220
32 if (GNUNET_YES == connected) { 221 if (GNUNET_YES == connected) {
33 GNUNET_ARM_request_service_start(handle->handles.arm, "messenger", GNUNET_OS_INHERIT_STD_NONE, NULL, NULL); 222 GNUNET_ARM_request_service_start(chat->handles.arm, "messenger",
34 GNUNET_ARM_request_service_start(handle->handles.arm, "fs", GNUNET_OS_INHERIT_STD_NONE, NULL, NULL); 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);
35 } else { 226 } else {
36 GNUNET_ARM_request_service_start(handle->handles.arm, "arm", GNUNET_OS_INHERIT_STD_NONE, NULL, NULL); 227 GNUNET_ARM_request_service_start(chat->handles.arm, "arm",
228 GNUNET_OS_INHERIT_STD_NONE, NULL, NULL);
37 } 229 }
38} 230}
39 231
40struct GNUNET_CHAT_Handle* 232struct GNUNET_CHAT_Handle*
41GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle* cfg, 233GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle* cfg,
42 const char *name, 234 const char *name,
43 GNUNET_CHAT_WarningCallback warn_cb, 235 GNUNET_CHAT_WarningCallback warn_cb,
44 void *warn_cls) { 236 void *warn_cls,
237 GNUNET_CHAT_ContextMessageCallback msg_cb,
238 void *msg_cls)
239{
45 if (!cfg) 240 if (!cfg)
46 return NULL; 241 return NULL;
47 242
48 struct GNUNET_CHAT_Handle *handle = GNUNET_new(struct GNUNET_CHAT_Handle); 243 struct GNUNET_CHAT_Handle *chat = GNUNET_new(struct GNUNET_CHAT_Handle);
49 memset(handle, 0, sizeof(*handle)); 244 memset(chat, 0, sizeof(*chat));
50 handle->cfg = cfg; 245 chat->cfg = cfg;
51 246
52 handle->handles.arm = GNUNET_ARM_connect(cfg, &handle_arm_connection, handle); 247 chat->warn_cb = warn_cb;
248 chat->warn_cls = warn_cls;
53 249
54 if (handle->handles.arm) 250 chat->handles.arm = GNUNET_ARM_connect(cfg, &handle_arm_connection, chat);
55 handle_arm_connection(handle, GNUNET_NO); 251
252 if (chat->handles.arm)
253 handle_arm_connection(chat, GNUNET_NO);
56 254
57 handle->handles.messenger = GNUNET_MESSENGER_connect( 255 chat->handles.messenger = GNUNET_MESSENGER_connect(
58 cfg, name, NULL, NULL, NULL, NULL //TODO 256 cfg, name,
257 handle_on_identity, chat,
258 handle_on_message, chat
59 ); 259 );
60 260
61 if (!handle->handles.messenger) 261 if (!chat->handles.messenger)
62 { 262 {
63 GNUNET_CHAT_stop(handle); 263 GNUNET_CHAT_stop(chat);
64 return NULL; 264 return NULL;
65 } 265 }
66 266
67 handle->handles.fs = GNUNET_FS_start( 267 chat->handles.fs = GNUNET_FS_start(
68 cfg, 268 cfg,
69 NULL, //TODO 269 name,
70 NULL, 270 handle_fs_progress,
271 chat,
71 GNUNET_FS_FLAGS_NONE, 272 GNUNET_FS_FLAGS_NONE,
72 GNUNET_FS_OPTIONS_END 273 GNUNET_FS_OPTIONS_END
73 ); 274 );
74 275
75 handle->contacts = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 276 chat->contacts.short_map = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
76 handle->groups = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 277 chat->contacts.hash_map = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
278
279 chat->groups = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
280 chat->contexts = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
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}
77 298
78 return handle; 299static int
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;
79} 307}
80 308
81void 309void
@@ -102,18 +330,28 @@ GNUNET_CHAT_stop (struct GNUNET_CHAT_Handle *handle)
102 330
103 if (handle->groups) 331 if (handle->groups)
104 { 332 {
105 // TODO: destroy each 333 GNUNET_CONTAINER_multihashmap_iterate(
334 handle->groups, handle_iterate_destroy_groups, NULL
335 );
106 336
107 GNUNET_CONTAINER_multihashmap_destroy(handle->groups); 337 GNUNET_CONTAINER_multihashmap_destroy(handle->groups);
108 handle->groups = NULL; 338 handle->groups = NULL;
109 } 339 }
110 340
111 if (handle->contacts) 341 if (handle->contacts.hash_map)
112 { 342 {
113 // TODO: destroy each 343 GNUNET_CONTAINER_multihashmap_iterate(
344 handle->contacts.hash_map, handle_iterate_destroy_contacts, NULL
345 );
114 346
115 GNUNET_CONTAINER_multihashmap_destroy(handle->contacts); 347 GNUNET_CONTAINER_multihashmap_destroy(handle->contacts.hash_map);
116 handle->contacts = NULL; 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;
117 } 355 }
118 356
119 if (handle->handles.arm) 357 if (handle->handles.arm)
@@ -172,7 +410,8 @@ struct GNUNET_CHAT_IterateContacts
172}; 410};
173 411
174static int 412static int
175handle_iterate_contacts(void *cls, const struct GNUNET_HashCode *key, 413handle_iterate_contacts(void *cls,
414 GNUNET_UNUSED const struct GNUNET_HashCode *key,
176 void *value) 415 void *value)
177{ 416{
178 struct GNUNET_CHAT_IterateContacts *iterate = cls; 417 struct GNUNET_CHAT_IterateContacts *iterate = cls;
@@ -197,7 +436,7 @@ GNUNET_CHAT_iterate_contacts (struct GNUNET_CHAT_Handle *handle,
197 iterate.callback = callback; 436 iterate.callback = callback;
198 iterate.cls = cls; 437 iterate.cls = cls;
199 438
200 return GNUNET_CONTAINER_multihashmap_iterate(handle->contacts, 439 return GNUNET_CONTAINER_multihashmap_iterate(handle->contacts.hash_map,
201 handle_iterate_contacts, 440 handle_iterate_contacts,
202 &iterate); 441 &iterate);
203} 442}
@@ -209,7 +448,18 @@ GNUNET_CHAT_group_create (struct GNUNET_CHAT_Handle *handle,
209 if (!handle) 448 if (!handle)
210 return NULL; 449 return NULL;
211 450
212 return group_create(handle, topic); 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;
213} 463}
214 464
215struct GNUNET_CHAT_IterateGroups 465struct GNUNET_CHAT_IterateGroups
@@ -220,8 +470,9 @@ struct GNUNET_CHAT_IterateGroups
220}; 470};
221 471
222static int 472static int
223handle_iterate_groups(void *cls, const struct GNUNET_HashCode *key, 473handle_iterate_groups(void *cls,
224 void *value) 474 GNUNET_UNUSED const struct GNUNET_HashCode *key,
475 void *value)
225{ 476{
226 struct GNUNET_CHAT_IterateGroups *iterate = cls; 477 struct GNUNET_CHAT_IterateGroups *iterate = cls;
227 struct GNUNET_CHAT_Group *group = value; 478 struct GNUNET_CHAT_Group *group = value;
@@ -246,6 +497,167 @@ GNUNET_CHAT_iterate_groups (struct GNUNET_CHAT_Handle *handle,
246 iterate.cls = cls; 497 iterate.cls = cls;
247 498
248 return GNUNET_CONTAINER_multihashmap_iterate(handle->groups, 499 return GNUNET_CONTAINER_multihashmap_iterate(handle->groups,
249 handle_iterate_contacts, 500 handle_iterate_groups,
250 &iterate); 501 &iterate);
251} 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}