aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2021-12-06 23:43:36 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2021-12-06 23:43:36 +0100
commitcbdb8030c9cbea9e00e5d569a0d90dabbd4155ea (patch)
tree8dd93b8161b209db5a1ae068c9d9f71e5099e549
parent5f187deccd1685385b03e20d7f3b55f600adf6ac (diff)
downloadlibgnunetchat-cbdb8030c9cbea9e00e5d569a0d90dabbd4155ea.tar.gz
libgnunetchat-cbdb8030c9cbea9e00e5d569a0d90dabbd4155ea.zip
Added status to context for edge cases with direct contact communication
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--include/gnunet_chat_lib.h22
-rw-r--r--src/gnunet_chat_contact.c41
-rw-r--r--src/gnunet_chat_contact_intern.c14
-rw-r--r--src/gnunet_chat_context.c27
-rw-r--r--src/gnunet_chat_context.h5
-rw-r--r--src/gnunet_chat_handle.c14
-rw-r--r--src/gnunet_chat_handle.h4
-rw-r--r--src/gnunet_chat_lib.c104
-rw-r--r--src/gnunet_chat_lib_intern.c21
9 files changed, 186 insertions, 66 deletions
diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h
index ddf58f9..b0665d9 100644
--- a/include/gnunet_chat_lib.h
+++ b/include/gnunet_chat_lib.h
@@ -528,6 +528,28 @@ struct GNUNET_CHAT_Context*
528GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group); 528GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group);
529 529
530/** 530/**
531 * Returns the current status of a given <i>context</i> whether it is usable
532 * or not to communicate with other contacts.
533 *
534 * @param[in] context Context
535 * @return #GNUNET_OK if usable, #GNUNET_NO if the context has been requested,
536 * #GNUNET_SYSERR otherwise.
537 */
538int
539GNUNET_CHAT_context_get_status (const struct GNUNET_CHAT_Context *context);
540
541/**
542 * Requests a <i>context</i> to get established between all required contacts.
543 * The current status of this request can be tracked via
544 * #GNUNET_CHAT_context_get_status() and will only change through the
545 * receivement of new messages.
546 *
547 * @param[in,out] context Context
548 */
549void
550GNUNET_CHAT_context_request (struct GNUNET_CHAT_Context *context);
551
552/**
531 * Returns the chat contact which uses a given <i>context</i>. 553 * Returns the chat contact which uses a given <i>context</i>.
532 * 554 *
533 * @param[in] context Context 555 * @param[in] context Context
diff --git a/src/gnunet_chat_contact.c b/src/gnunet_chat_contact.c
index 190c13a..c7004d3 100644
--- a/src/gnunet_chat_contact.c
+++ b/src/gnunet_chat_contact.c
@@ -77,7 +77,9 @@ contact_find_context (struct GNUNET_CHAT_Contact *contact)
77 return contact->context; 77 return contact->context;
78 78
79 struct GNUNET_CHAT_ContactFindRoom find; 79 struct GNUNET_CHAT_ContactFindRoom find;
80 find.member_count = 0;
80 find.room = NULL; 81 find.room = NULL;
82
81 GNUNET_MESSENGER_find_rooms( 83 GNUNET_MESSENGER_find_rooms(
82 contact->handle->messenger, 84 contact->handle->messenger,
83 contact->member, 85 contact->member,
@@ -85,46 +87,13 @@ contact_find_context (struct GNUNET_CHAT_Contact *contact)
85 &find 87 &find
86 ); 88 );
87 89
88 // TODO: Check if the found room is a group or not
89
90 if (!(find.room)) 90 if (!(find.room))
91 return NULL; 91 return NULL;
92 92
93 struct GNUNET_HashCode key; 93 return GNUNET_CONTAINER_multihashmap_get(
94 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, &key, sizeof(key)); 94 contact->handle->contexts,
95 95 GNUNET_MESSENGER_room_get_key(find.room)
96 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(
97 contact->handle->contexts, &key))
98 return NULL;
99
100 struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_open_room(
101 contact->handle->messenger, &key
102 );
103
104 if (!room)
105 return NULL;
106
107 struct GNUNET_CHAT_Context *context = context_create_from_room(
108 contact->handle, room
109 ); 96 );
110
111 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
112 contact->handle->contexts, &key, context,
113 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
114 {
115 context_destroy(context);
116 return NULL;
117 }
118
119 struct GNUNET_MESSENGER_Message msg;
120 msg.header.kind = GNUNET_MESSENGER_KIND_INVITE;
121 GNUNET_CRYPTO_get_peer_identity(contact->handle->cfg, &(msg.body.invite.door));
122 GNUNET_memcpy(&(msg.body.invite.key), &key, sizeof(msg.body.invite.key));
123
124 GNUNET_MESSENGER_send_message(find.room, &msg, contact->member);
125
126 contact->context = context;
127 return contact->context;
128} 97}
129 98
130void 99void
diff --git a/src/gnunet_chat_contact_intern.c b/src/gnunet_chat_contact_intern.c
index 3e89663..5005651 100644
--- a/src/gnunet_chat_contact_intern.c
+++ b/src/gnunet_chat_contact_intern.c
@@ -26,6 +26,7 @@
26 26
27struct GNUNET_CHAT_ContactFindRoom 27struct GNUNET_CHAT_ContactFindRoom
28{ 28{
29 int member_count;
29 struct GNUNET_MESSENGER_Room *room; 30 struct GNUNET_MESSENGER_Room *room;
30}; 31};
31 32
@@ -36,7 +37,16 @@ it_contact_find_room (void *cls,
36{ 37{
37 GNUNET_assert((cls) && (room)); 38 GNUNET_assert((cls) && (room));
38 39
40 const int member_count = GNUNET_MESSENGER_iterate_members(room, NULL, NULL);
41
39 struct GNUNET_CHAT_ContactFindRoom *find = cls; 42 struct GNUNET_CHAT_ContactFindRoom *find = cls;
40 find->room = room; 43
41 return GNUNET_NO; 44 if ((find->member_count <= 0) ||
45 ((member_count >= 1) && (member_count < find->member_count)))
46 {
47 find->member_count = member_count;
48 find->room = room;
49 }
50
51 return GNUNET_YES;
42} 52}
diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c
index 458063f..a95c869 100644
--- a/src/gnunet_chat_context.c
+++ b/src/gnunet_chat_context.c
@@ -47,6 +47,33 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle,
47 context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 47 context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
48 48
49 context->room = room; 49 context->room = room;
50 context->contact = NULL;
51
52 context->user_pointer = NULL;
53
54 return context;
55}
56
57struct GNUNET_CHAT_Context*
58context_create_from_contact (struct GNUNET_CHAT_Handle *handle,
59 const struct GNUNET_MESSENGER_Contact *contact)
60{
61 GNUNET_assert((handle) && (contact));
62
63 struct GNUNET_CHAT_Context* context = GNUNET_new(struct GNUNET_CHAT_Context);
64
65 context->handle = handle;
66
67 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
68 context->nick = NULL;
69
70 context->timestamps = GNUNET_CONTAINER_multishortmap_create(4, GNUNET_NO);
71 context->messages = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
72 context->invites = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
73 context->files = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
74
75 context->room = NULL;
76 context->contact = contact;
50 77
51 context->user_pointer = NULL; 78 context->user_pointer = NULL;
52 79
diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h
index cb4528a..9830233 100644
--- a/src/gnunet_chat_context.h
+++ b/src/gnunet_chat_context.h
@@ -54,6 +54,7 @@ struct GNUNET_CHAT_Context
54 struct GNUNET_CONTAINER_MultiHashMap *files; 54 struct GNUNET_CONTAINER_MultiHashMap *files;
55 55
56 struct GNUNET_MESSENGER_Room *room; 56 struct GNUNET_MESSENGER_Room *room;
57 const struct GNUNET_MESSENGER_Contact *contact;
57 58
58 void *user_pointer; 59 void *user_pointer;
59}; 60};
@@ -62,6 +63,10 @@ struct GNUNET_CHAT_Context*
62context_create_from_room (struct GNUNET_CHAT_Handle *handle, 63context_create_from_room (struct GNUNET_CHAT_Handle *handle,
63 struct GNUNET_MESSENGER_Room *room); 64 struct GNUNET_MESSENGER_Room *room);
64 65
66struct GNUNET_CHAT_Context*
67context_create_from_contact (struct GNUNET_CHAT_Handle *handle,
68 const struct GNUNET_MESSENGER_Contact *contact);
69
65void 70void
66context_destroy (struct GNUNET_CHAT_Context* context); 71context_destroy (struct GNUNET_CHAT_Context* context);
67 72
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
index 92b4fbe..668aeec 100644
--- a/src/gnunet_chat_handle.c
+++ b/src/gnunet_chat_handle.c
@@ -164,3 +164,17 @@ handle_destroy (struct GNUNET_CHAT_Handle* handle)
164 164
165 GNUNET_free(handle); 165 GNUNET_free(handle);
166} 166}
167
168struct GNUNET_CHAT_Contact*
169handle_get_contact_from_messenger (const struct GNUNET_CHAT_Handle *handle,
170 const struct GNUNET_MESSENGER_Contact *contact)
171{
172 GNUNET_assert((handle) && (handle->contacts) && (contact));
173
174 struct GNUNET_ShortHashCode shorthash;
175 util_shorthash_from_member(contact, &shorthash);
176
177 return GNUNET_CONTAINER_multishortmap_get(
178 handle->contacts, &shorthash
179 );
180}
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
index ab7291e..c8afb0a 100644
--- a/src/gnunet_chat_handle.h
+++ b/src/gnunet_chat_handle.h
@@ -73,4 +73,8 @@ handle_update_key (struct GNUNET_CHAT_Handle *handle);
73void 73void
74handle_destroy (struct GNUNET_CHAT_Handle* handle); 74handle_destroy (struct GNUNET_CHAT_Handle* handle);
75 75
76struct GNUNET_CHAT_Contact*
77handle_get_contact_from_messenger (const struct GNUNET_CHAT_Handle *handle,
78 const struct GNUNET_MESSENGER_Contact *contact);
79
76#endif /* GNUNET_CHAT_HANDLE_H_ */ 80#endif /* GNUNET_CHAT_HANDLE_H_ */
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
index 1d12bdd..23b2c3e 100644
--- a/src/gnunet_chat_lib.c
+++ b/src/gnunet_chat_lib.c
@@ -293,7 +293,20 @@ GNUNET_CHAT_contact_get_context (struct GNUNET_CHAT_Contact *contact)
293 if (!contact) 293 if (!contact)
294 return NULL; 294 return NULL;
295 295
296 return contact_find_context(contact); 296 if (contact->context)
297 return contact->context;
298
299 struct GNUNET_CHAT_Context *context = contact_find_context(contact);
300
301 if ((context) && (GNUNET_CHAT_CONTEXT_TYPE_CONTACT == context->type))
302 return context;
303
304 context = context_create_from_contact(contact->handle, contact->member);
305
306 if (context)
307 contact->context = context;
308
309 return context;
297} 310}
298 311
299 312
@@ -444,15 +457,79 @@ GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group)
444} 457}
445 458
446 459
460int
461GNUNET_CHAT_context_get_status (const struct GNUNET_CHAT_Context *context)
462{
463 if ((!context) || (!(context->room)))
464 return GNUNET_SYSERR;
465
466 if (1 <= GNUNET_MESSENGER_iterate_members(context->room, NULL, NULL))
467 return GNUNET_NO;
468
469 return GNUNET_YES;
470}
471
472
473void
474GNUNET_CHAT_context_request (struct GNUNET_CHAT_Context *context)
475{
476 if ((!context) || (context->room))
477 return;
478
479 struct GNUNET_CHAT_Handle *handle = context->handle;
480
481 if ((!handle) || (!(context->contact)))
482 return;
483
484 struct GNUNET_CHAT_Contact *contact = contact_create_from_member(
485 handle, context->contact
486 );
487
488 if (!contact)
489 return;
490
491 struct GNUNET_CHAT_Context *other = contact_find_context(contact);
492
493 if ((!other) || (!(other->room)))
494 return;
495
496 struct GNUNET_HashCode key;
497 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, &key, sizeof(key));
498
499 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(
500 handle->contexts, &key))
501 return;
502
503 struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_open_room(
504 handle->messenger, &key
505 );
506
507 if (!room)
508 return;
509
510 struct GNUNET_MESSENGER_Message msg;
511 msg.header.kind = GNUNET_MESSENGER_KIND_INVITE;
512 GNUNET_CRYPTO_get_peer_identity(handle->cfg, &(msg.body.invite.door));
513 GNUNET_memcpy(&(msg.body.invite.key), &key, sizeof(msg.body.invite.key));
514
515 GNUNET_MESSENGER_send_message(other->room, &msg, context->contact);
516 context->room = room;
517}
518
519
447const struct GNUNET_CHAT_Contact* 520const struct GNUNET_CHAT_Contact*
448GNUNET_CHAT_context_get_contact (const struct GNUNET_CHAT_Context *context) 521GNUNET_CHAT_context_get_contact (const struct GNUNET_CHAT_Context *context)
449{ 522{
450 if ((!context) || (GNUNET_CHAT_CONTEXT_TYPE_CONTACT != context->type)) 523 if ((!context) || (GNUNET_CHAT_CONTEXT_TYPE_CONTACT != context->type))
451 return NULL; 524 return NULL;
452 525
526 if (context->contact)
527 return handle_get_contact_from_messenger(context->handle, context->contact);
528
453 struct GNUNET_MESSENGER_Room *room = context->room; 529 struct GNUNET_MESSENGER_Room *room = context->room;
454 struct GNUNET_CHAT_RoomFindContact find; 530 struct GNUNET_CHAT_RoomFindContact find;
455 531
532 find.ignore_key = GNUNET_MESSENGER_get_key(context->handle->messenger);
456 find.contact = NULL; 533 find.contact = NULL;
457 534
458 GNUNET_MESSENGER_iterate_members( 535 GNUNET_MESSENGER_iterate_members(
@@ -464,16 +541,7 @@ GNUNET_CHAT_context_get_contact (const struct GNUNET_CHAT_Context *context)
464 if (!find.contact) 541 if (!find.contact)
465 return NULL; 542 return NULL;
466 543
467 struct GNUNET_ShortHashCode shorthash; 544 return handle_get_contact_from_messenger(context->handle, find.contact);
468 util_shorthash_from_member(find.contact, &shorthash);
469
470 const struct GNUNET_CHAT_Contact *contact;
471 contact = GNUNET_CONTAINER_multishortmap_get(
472 context->handle->contacts, &shorthash
473 );
474
475 GNUNET_assert((contact == NULL) || (contact->context == context));
476 return contact;
477} 545}
478 546
479 547
@@ -524,7 +592,7 @@ int
524GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context, 592GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
525 const char *text) 593 const char *text)
526{ 594{
527 if ((!context) || (!text)) 595 if ((!context) || (!text) || (!(context->room)))
528 return GNUNET_SYSERR; 596 return GNUNET_SYSERR;
529 597
530 struct GNUNET_MESSENGER_Message msg; 598 struct GNUNET_MESSENGER_Message msg;
@@ -544,7 +612,7 @@ GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context,
544 GNUNET_CHAT_FileUploadCallback callback, 612 GNUNET_CHAT_FileUploadCallback callback,
545 void *cls) 613 void *cls)
546{ 614{
547 if ((!context) || (!path)) 615 if ((!context) || (!path) || (!(context->room)))
548 return GNUNET_SYSERR; 616 return GNUNET_SYSERR;
549 617
550 if (!(context->handle->directory)) 618 if (!(context->handle->directory))
@@ -620,7 +688,8 @@ int
620GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context, 688GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
621 const struct GNUNET_CHAT_File *file) 689 const struct GNUNET_CHAT_File *file)
622{ 690{
623 if ((!context) || (!file) || (strlen(file->name) > NAME_MAX)) 691 if ((!context) || (!file) || (strlen(file->name) > NAME_MAX) ||
692 (!(context->room)))
624 return GNUNET_SYSERR; 693 return GNUNET_SYSERR;
625 694
626 struct GNUNET_MESSENGER_Message msg; 695 struct GNUNET_MESSENGER_Message msg;
@@ -741,12 +810,7 @@ GNUNET_CHAT_message_get_sender (const struct GNUNET_CHAT_Message *message)
741 if (!sender) 810 if (!sender)
742 return NULL; 811 return NULL;
743 812
744 struct GNUNET_ShortHashCode shorthash; 813 return handle_get_contact_from_messenger(message->context->handle, sender);
745 util_shorthash_from_member(sender, &shorthash);
746
747 return GNUNET_CONTAINER_multishortmap_get(
748 message->context->handle->contacts, &shorthash
749 );
750} 814}
751 815
752 816
diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c
index a770367..0ef2b72 100644
--- a/src/gnunet_chat_lib_intern.c
+++ b/src/gnunet_chat_lib_intern.c
@@ -95,6 +95,7 @@ it_handle_iterate_groups (void *cls,
95 95
96struct GNUNET_CHAT_RoomFindContact 96struct GNUNET_CHAT_RoomFindContact
97{ 97{
98 const struct GNUNET_IDENTITY_PublicKey *ignore_key;
98 const struct GNUNET_MESSENGER_Contact *contact; 99 const struct GNUNET_MESSENGER_Contact *contact;
99}; 100};
100 101
@@ -105,7 +106,16 @@ it_room_find_contact (void *cls,
105{ 106{
106 GNUNET_assert((cls) && (member)); 107 GNUNET_assert((cls) && (member));
107 108
109 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_contact_get_key(
110 member
111 );
112
108 struct GNUNET_CHAT_RoomFindContact *find = cls; 113 struct GNUNET_CHAT_RoomFindContact *find = cls;
114
115 if ((find->ignore_key) && (key) &&
116 (0 == GNUNET_memcmp(find->ignore_key, key)))
117 return GNUNET_YES;
118
109 find->contact = member; 119 find->contact = member;
110 return GNUNET_NO; 120 return GNUNET_NO;
111} 121}
@@ -129,14 +139,9 @@ it_group_iterate_contacts (void* cls,
129 if (!(it->cb)) 139 if (!(it->cb))
130 return GNUNET_YES; 140 return GNUNET_YES;
131 141
132 struct GNUNET_ShortHashCode shorthash; 142 return it->cb(it->cls, it->group, handle_get_contact_from_messenger(
133 util_shorthash_from_member(member, &shorthash); 143 it->group->handle, member
134 144 ));
135 struct GNUNET_CHAT_Contact *contact = GNUNET_CONTAINER_multishortmap_get(
136 it->group->handle->contacts, &shorthash
137 );
138
139 return it->cb(it->cls, it->group, contact);
140} 145}
141 146
142struct GNUNET_CHAT_ContextIterateMessages 147struct GNUNET_CHAT_ContextIterateMessages