aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2021-07-11 02:33:00 +0200
committerTheJackiMonster <thejackimonster@gmail.com>2021-07-11 02:33:00 +0200
commitb880617514f9e64e991cb8d6fcff74ce3f292e36 (patch)
tree6f65a73f7ce40bdd3f5b3e9bc40f6477447cd8b3
parente366e189791025f7fad5572bc786f4883152812e (diff)
downloadlibgnunetchat-b880617514f9e64e991cb8d6fcff74ce3f292e36.tar.gz
libgnunetchat-b880617514f9e64e991cb8d6fcff74ce3f292e36.zip
Code reorganized and refactored, most features implemented
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--Makefile13
-rw-r--r--include/gnunet_chat_lib.h29
-rw-r--r--src/gnunet_chat_contact.c155
-rw-r--r--src/gnunet_chat_contact.h22
-rw-r--r--src/gnunet_chat_context.c160
-rw-r--r--src/gnunet_chat_context.h28
-rw-r--r--src/gnunet_chat_file.c84
-rw-r--r--src/gnunet_chat_file.h21
-rw-r--r--src/gnunet_chat_group.c201
-rw-r--r--src/gnunet_chat_group.h17
-rw-r--r--src/gnunet_chat_group_intern.c51
-rw-r--r--src/gnunet_chat_handle.c653
-rw-r--r--src/gnunet_chat_handle.h79
-rw-r--r--src/gnunet_chat_handle_intern.c308
-rw-r--r--src/gnunet_chat_invitation.c20
-rw-r--r--src/gnunet_chat_invitation.h19
-rw-r--r--src/gnunet_chat_lib.c693
-rw-r--r--src/gnunet_chat_lib_intern.c124
-rw-r--r--src/gnunet_chat_message.c68
-rw-r--r--src/gnunet_chat_message.h16
-rw-r--r--src/gnunet_chat_util.c45
-rw-r--r--src/gnunet_chat_util.h40
22 files changed, 1508 insertions, 1338 deletions
diff --git a/Makefile b/Makefile
index 39d00d3..c92dd87 100644
--- a/Makefile
+++ b/Makefile
@@ -4,14 +4,17 @@ INCLUDE_DIR = include/
4INSTALL_DIR = /usr/local/ 4INSTALL_DIR = /usr/local/
5 5
6LIBRARY = libgnunetchat.so 6LIBRARY = libgnunetchat.so
7SOURCES = gnunet_chat_handle.c\ 7SOURCES = gnunet_chat_lib.c\
8 gnunet_chat_contact.c\ 8 gnunet_chat_config.c\
9 gnunet_chat_contact.c\
10 gnunet_chat_context.c\
9 gnunet_chat_file.c\ 11 gnunet_chat_file.c\
10 gnunet_chat_invitation.c\
11 gnunet_chat_group.c\ 12 gnunet_chat_group.c\
12 gnunet_chat_context.c\ 13 gnunet_chat_handle.c\
14 gnunet_chat_invitation.c\
13 gnunet_chat_message.c\ 15 gnunet_chat_message.c\
14 gnunet_chat_config.c 16 gnunet_chat_util.c
17
15HEADERS = gnunet_chat_lib.h 18HEADERS = gnunet_chat_lib.h
16 19
17LIBRARIES = gnunetarm\ 20LIBRARIES = gnunetarm\
diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h
index f2605b9..4c15df5 100644
--- a/include/gnunet_chat_lib.h
+++ b/include/gnunet_chat_lib.h
@@ -29,9 +29,8 @@
29#ifndef GNUNET_CHAT_LIB_H_ 29#ifndef GNUNET_CHAT_LIB_H_
30#define GNUNET_CHAT_LIB_H_ 30#define GNUNET_CHAT_LIB_H_
31 31
32#define GNUNET_UNUSED __attribute__ ((unused))
33
34#include <gnunet/platform.h> 32#include <gnunet/platform.h>
33#include <gnunet/gnunet_common.h>
35#include <gnunet/gnunet_util_lib.h> 34#include <gnunet/gnunet_util_lib.h>
36 35
37/** 36/**
@@ -442,29 +441,13 @@ GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
442 * @param delay 441 * @param delay
443 */ 442 */
444void 443void
445GNUNET_CHAT_context_delete_message (struct GNUNET_CHAT_Context *context, 444GNUNET_CHAT_context_delete_message (const struct GNUNET_CHAT_Message *message,
446 const struct GNUNET_HashCode *hash,
447 struct GNUNET_TIME_Relative delay); 445 struct GNUNET_TIME_Relative delay);
448 446
449/** 447/**
450 * TODO 448 * TODO
451 * 449 *
452 * @param context 450 * @param context
453 * @param hash
454 * @param callback
455 * @param cls
456 * @return
457 */
458int
459GNUNET_CHAT_context_get_message (struct GNUNET_CHAT_Context *context,
460 const struct GNUNET_HashCode *hash,
461 GNUNET_CHAT_ContextMessageCallback callback,
462 void *cls);
463
464/**
465 * TODO
466 *
467 * @param context
468 * @param callback 451 * @param callback
469 * @param cls 452 * @param cls
470 * @return 453 * @return
@@ -615,12 +598,4 @@ GNUNET_CHAT_file_stop_download (struct GNUNET_CHAT_File *file);
615void 598void
616GNUNET_CHAT_invitation_accept (struct GNUNET_CHAT_Invitation *invitation); 599GNUNET_CHAT_invitation_accept (struct GNUNET_CHAT_Invitation *invitation);
617 600
618/**
619 * TODO
620 *
621 * @param invitation
622 */
623void
624GNUNET_CHAT_invitation_decline (struct GNUNET_CHAT_Invitation *invitation);
625
626#endif /* GNUNET_CHAT_LIB_H_ */ 601#endif /* GNUNET_CHAT_LIB_H_ */
diff --git a/src/gnunet_chat_contact.c b/src/gnunet_chat_contact.c
index d1d92ff..a172c8e 100644
--- a/src/gnunet_chat_contact.c
+++ b/src/gnunet_chat_contact.c
@@ -22,169 +22,26 @@
22 * @file gnunet_chat_contact.c 22 * @file gnunet_chat_contact.c
23 */ 23 */
24 24
25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_contact.h" 25#include "gnunet_chat_contact.h"
27#include "gnunet_chat_handle.h"
28 26
29struct GNUNET_CHAT_Contact* 27struct GNUNET_CHAT_Contact*
30contact_create (struct GNUNET_CHAT_Handle *handle, 28contact_create_from_member (struct GNUNET_CHAT_Handle *handle,
31 const struct GNUNET_MESSENGER_Contact *msg_contact) 29 const struct GNUNET_MESSENGER_Contact *member)
32{ 30{
33 struct GNUNET_CHAT_Contact* contact = GNUNET_new(struct GNUNET_CHAT_Contact); 31 struct GNUNET_CHAT_Contact* contact = GNUNET_new(struct GNUNET_CHAT_Contact);
34 32
35 contact->handle = handle; 33 contact->handle = handle;
36 contact->context = context_create( 34 contact->context = NULL;
37 handle,
38 GNUNET_CHAT_CONTEXT_TYPE_CONTACT,
39 NULL
40 ); // TODO: check for existing context?
41 35
42 contact->contact = msg_contact; 36 // TODO: search for private context? create private context?
43 37
44 if (!contact->context) 38 contact->member = member;
45 {
46 contact_destroy (contact);
47 return NULL;
48 }
49
50 const struct GNUNET_HashCode *key = context_get_key(contact->context);
51
52 const int result = GNUNET_CONTAINER_multihashmap_put(
53 handle->contacts,
54 key,
55 contact,
56 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
57 );
58
59 if (GNUNET_OK != result) {
60 contact_destroy (contact);
61 return NULL;
62 }
63 39
64 return contact; 40 return contact;
65} 41}
66 42
67void 43void
68contact_destroy (struct GNUNET_CHAT_Contact *contact) 44contact_destroy (struct GNUNET_CHAT_Contact* contact)
69{ 45{
70 if (!contact->context)
71 goto skip_context;
72
73 struct GNUNET_CHAT_Handle *handle = contact->handle;
74 const struct GNUNET_HashCode *key = context_get_key(contact->context);
75
76 GNUNET_CONTAINER_multihashmap_remove(
77 handle->contacts,
78 key,
79 contact
80 );
81
82 context_destroy(contact->context);
83
84skip_context:
85 GNUNET_free(contact); 46 GNUNET_free(contact);
86} 47}
87
88struct GNUNET_CHAT_SearchContact
89{
90 struct GNUNET_MESSENGER_Contact *contact;
91 const struct GNUNET_MESSENGER_Contact *msg_contact;
92};
93
94static int
95contact_search (void *cls, const struct GNUNET_HashCode *key, void *value)
96{
97 struct GNUNET_CHAT_Contact *contact = value;
98 struct GNUNET_CHAT_SearchContact *search = cls;
99
100 if (contact->contact == search->msg_contact)
101 {
102 search->contact = contact;
103 return GNUNET_NO;
104 }
105
106 return GNUNET_YES;
107}
108
109int
110contact_call (struct GNUNET_CHAT_Handle *handle,
111 const struct GNUNET_MESSENGER_Contact *msg_contact,
112 GNUNET_CHAT_ContactCallback callback,
113 void *cls)
114{
115 struct GNUNET_CHAT_SearchContact search;
116 search.contact = NULL;
117 search.msg_contact = msg_contact;
118
119 GNUNET_CONTAINER_multihashmap_iterate(
120 handle->contacts,
121 contact_search,
122 &search
123 );
124
125 if (search.contact)
126 return callback(cls, handle, search.contact);
127
128 search.contact = contact_create(handle, msg_contact);
129 int result = callback(cls, handle, search.contact);
130
131 // TODO: check if contact has private chat
132
133 contact_destroy(search.contact);
134 return result;
135}
136
137int
138GNUNET_CHAT_contact_delete (struct GNUNET_CHAT_Contact *contact)
139{
140 if (!contact)
141 return GNUNET_SYSERR;
142
143 if (GNUNET_YES != handle_update_chat_contact(contact->handle,
144 contact, GNUNET_YES))
145 return GNUNET_SYSERR;
146
147 if (contact->context)
148 GNUNET_MESSENGER_close_room(contact->context->room);
149
150 contact_destroy(contact);
151 return GNUNET_OK;
152}
153
154void
155GNUNET_CHAT_contact_set_name (struct GNUNET_CHAT_Contact *contact,
156 const char *name)
157{
158 if (!contact)
159 return;
160
161 if (contact->context)
162 context_set_nick(contact->context, name);
163}
164
165const char*
166GNUNET_CHAT_contact_get_name (const struct GNUNET_CHAT_Contact *contact)
167{
168 if (!contact)
169 return NULL;
170
171 if (!contact->context)
172 goto skip_context;
173
174 const char *nick = context_get_nick(contact->context);
175
176 if (nick)
177 return nick;
178
179skip_context:
180 return GNUNET_MESSENGER_contact_get_name(contact->contact);
181}
182
183struct GNUNET_CHAT_Context*
184GNUNET_CHAT_contact_get_context (struct GNUNET_CHAT_Contact *contact)
185{
186 if (!contact)
187 return NULL;
188
189 return contact->context;
190}
diff --git a/src/gnunet_chat_contact.h b/src/gnunet_chat_contact.h
index e215c5f..1cf5618 100644
--- a/src/gnunet_chat_contact.h
+++ b/src/gnunet_chat_contact.h
@@ -25,27 +25,27 @@
25#ifndef GNUNET_CHAT_CONTACT_H_ 25#ifndef GNUNET_CHAT_CONTACT_H_
26#define GNUNET_CHAT_CONTACT_H_ 26#define GNUNET_CHAT_CONTACT_H_
27 27
28#include "gnunet_chat_context.h" 28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
30#include <gnunet/gnunet_messenger_service.h>
31#include <gnunet/gnunet_util_lib.h>
32
33struct GNUNET_CHAT_Handle;
34struct GNUNET_CHAT_Context;
29 35
30struct GNUNET_CHAT_Contact 36struct GNUNET_CHAT_Contact
31{ 37{
32 struct GNUNET_CHAT_Handle *handle; 38 struct GNUNET_CHAT_Handle *handle;
33 struct GNUNET_CHAT_Context *context; 39 struct GNUNET_CHAT_Context *context;
34 40
35 const struct GNUNET_MESSENGER_Contact *contact; 41 const struct GNUNET_MESSENGER_Contact *member;
36}; 42};
37 43
38struct GNUNET_CHAT_Contact* 44struct GNUNET_CHAT_Contact*
39contact_create (struct GNUNET_CHAT_Handle *handle, 45contact_create_from_member (struct GNUNET_CHAT_Handle *handle,
40 const struct GNUNET_MESSENGER_Contact *msg_contact); 46 const struct GNUNET_MESSENGER_Contact *member);
41 47
42void 48void
43contact_destroy (struct GNUNET_CHAT_Contact *contact); 49contact_destroy (struct GNUNET_CHAT_Contact* contact);
44
45int
46contact_call (struct GNUNET_CHAT_Handle *handle,
47 const struct GNUNET_MESSENGER_Contact *msg_contact,
48 GNUNET_CHAT_ContactCallback callback,
49 void *cls);
50 50
51#endif /* GNUNET_CHAT_CONTACT_H_ */ 51#endif /* GNUNET_CHAT_CONTACT_H_ */
diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c
index 27e8f35..54c63f7 100644
--- a/src/gnunet_chat_context.c
+++ b/src/gnunet_chat_context.c
@@ -22,171 +22,37 @@
22 * @file gnunet_chat_context.c 22 * @file gnunet_chat_context.c
23 */ 23 */
24 24
25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_context.h" 25#include "gnunet_chat_context.h"
27#include "gnunet_chat_handle.h"
28 26
29struct GNUNET_CHAT_Context* 27struct GNUNET_CHAT_Context*
30context_create (struct GNUNET_CHAT_Handle *handle, 28context_create_from_room (struct GNUNET_CHAT_Handle *handle,
31 enum GNUNET_CHAT_ContextType type, 29 struct GNUNET_MESSENGER_Room *room)
32 const struct GNUNET_HashCode *key)
33{ 30{
34 struct GNUNET_MESSENGER_Handle *messenger = handle->handles.messenger;
35
36 struct GNUNET_HashCode _room_key;
37 const struct GNUNET_HashCode *room_key;
38
39 if (key)
40 room_key = key;
41 else
42 {
43 GNUNET_CRYPTO_random_block(
44 GNUNET_CRYPTO_QUALITY_WEAK,
45 &_room_key,
46 sizeof(_room_key)
47 );
48
49 room_key = &_room_key;
50 }
51
52 struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_open_room(
53 messenger, room_key
54 );
55
56 if (!room)
57 return NULL;
58
59 struct GNUNET_CHAT_Context* context = GNUNET_new(struct GNUNET_CHAT_Context); 31 struct GNUNET_CHAT_Context* context = GNUNET_new(struct GNUNET_CHAT_Context);
60 32
61 context->handle = handle; 33 context->handle = handle;
62 context->room = room;
63 34
64 context->type = type; 35 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN;
65 GNUNET_memcpy(&(context->key), room_key, sizeof(_room_key));
66 context->nick = NULL; 36 context->nick = NULL;
67 37
38 context->messages = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
39 context->invites = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
40 context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
41
42 context->room = room;
43
68 return context; 44 return context;
69} 45}
70 46
71void 47void
72context_destroy (struct GNUNET_CHAT_Context* context) 48context_destroy (struct GNUNET_CHAT_Context* context)
73{ 49{
74 GNUNET_free(context); 50 GNUNET_CONTAINER_multihashmap_destroy(context->messages);
75} 51 GNUNET_CONTAINER_multihashmap_destroy(context->invites);
76 52 GNUNET_CONTAINER_multihashmap_destroy(context->files);
77enum GNUNET_CHAT_ContextType
78context_get_type (struct GNUNET_CHAT_Context* context)
79{
80 return context->type;
81}
82 53
83const struct GNUNET_HashCode*
84context_get_key (struct GNUNET_CHAT_Context* context)
85{
86 return &(context->key);
87}
88
89const char*
90context_get_nick (struct GNUNET_CHAT_Context* context)
91{
92 return context->nick;
93}
94
95void
96context_set_nick (struct GNUNET_CHAT_Context* context,
97 const char *nick)
98{
99 if (context->nick) 54 if (context->nick)
100 GNUNET_free(context->nick); 55 GNUNET_free(context->nick);
101 56
102 context->nick = nick? GNUNET_strdup(nick) : NULL; 57 GNUNET_free(context);
103}
104
105void
106GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
107 const char *text)
108{
109 if (!context)
110 return;
111
112 struct GNUNET_MESSENGER_Message message;
113 message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
114 message.body.text.text = text;
115
116 GNUNET_MESSENGER_send_message(context->room, &message, NULL);
117}
118
119void
120GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context,
121 const char *path)
122{
123 //TODO: generate key, hash file, encrypt file, upload file, share uri & info
124}
125
126void
127GNUNET_CHAT_context_send_uri (struct GNUNET_CHAT_Context *context,
128 const char *uri)
129{
130 if (!context)
131 return;
132
133 struct GNUNET_MESSENGER_Message message;
134 message.header.kind = GNUNET_MESSENGER_KIND_FILE;
135
136 memset(&(message.body.file.key), 0, sizeof(message.body.file.key));
137
138 message.body.file.hash; // TODO: download & hash
139 GNUNET_memcpy(message.body.file.name, "", 1); // TODO: cut from uri or get from download?
140 message.body.file.uri = uri;
141
142 GNUNET_MESSENGER_send_message(context->room, &message, NULL);
143}
144
145void
146GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
147 const struct GNUNET_CHAT_File *file)
148{
149 //TODO: send copied message basically
150}
151
152void
153GNUNET_CHAT_context_delete_message (struct GNUNET_CHAT_Context *context,
154 const struct GNUNET_HashCode *hash,
155 struct GNUNET_TIME_Relative delay)
156{
157 if (!context)
158 return;
159
160 struct GNUNET_MESSENGER_Message message;
161 message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
162 GNUNET_memcpy(&(message.body.delete.hash), hash, sizeof(*hash));
163 message.body.delete.delay = GNUNET_TIME_relative_hton(delay);
164
165 GNUNET_MESSENGER_send_message(context->room, &message, NULL);
166}
167
168int
169GNUNET_CHAT_context_get_message (struct GNUNET_CHAT_Context *context,
170 const struct GNUNET_HashCode *hash,
171 GNUNET_CHAT_ContextMessageCallback callback,
172 void *cls)
173{
174 if (!context)
175 return GNUNET_SYSERR;
176
177 struct GNUNET_MESSENGER_Message *message = GNUNET_MESSENGER_get_message(
178 context->room, hash
179 );
180
181 //TODO: convert messenger-message to chat-message
182
183 return GNUNET_OK;
184}
185
186int
187GNUNET_CHAT_context_iterate_messages (struct GNUNET_CHAT_Context *context,
188 GNUNET_CHAT_ContextMessageCallback callback,
189 void *cls)
190{
191 return GNUNET_SYSERR;
192} 58}
diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h
index 87f7dfd..e975312 100644
--- a/src/gnunet_chat_context.h
+++ b/src/gnunet_chat_context.h
@@ -26,6 +26,8 @@
26#define GNUNET_CHAT_CONTEXT_H_ 26#define GNUNET_CHAT_CONTEXT_H_
27 27
28#include <gnunet/platform.h> 28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
30#include <gnunet/gnunet_container_lib.h>
29#include <gnunet/gnunet_messenger_service.h> 31#include <gnunet/gnunet_messenger_service.h>
30#include <gnunet/gnunet_util_lib.h> 32#include <gnunet/gnunet_util_lib.h>
31 33
@@ -41,32 +43,22 @@ struct GNUNET_CHAT_Handle;
41struct GNUNET_CHAT_Context 43struct GNUNET_CHAT_Context
42{ 44{
43 struct GNUNET_CHAT_Handle *handle; 45 struct GNUNET_CHAT_Handle *handle;
44 struct GNUNET_MESSENGER_Room *room;
45 46
46 enum GNUNET_CHAT_ContextType type; 47 enum GNUNET_CHAT_ContextType type;
47 struct GNUNET_HashCode key;
48 char *nick; 48 char *nick;
49
50 struct GNUNET_CONTAINER_MultiHashMap *messages;
51 struct GNUNET_CONTAINER_MultiHashMap *invites;
52 struct GNUNET_CONTAINER_MultiHashMap *files;
53
54 struct GNUNET_MESSENGER_Room *room;
49}; 55};
50 56
51struct GNUNET_CHAT_Context* 57struct GNUNET_CHAT_Context*
52context_create (struct GNUNET_CHAT_Handle *handle, 58context_create_from_room (struct GNUNET_CHAT_Handle *handle,
53 enum GNUNET_CHAT_ContextType type, 59 struct GNUNET_MESSENGER_Room *room);
54 const struct GNUNET_HashCode *key);
55 60
56void 61void
57context_destroy (struct GNUNET_CHAT_Context* context); 62context_destroy (struct GNUNET_CHAT_Context* context);
58 63
59enum GNUNET_CHAT_ContextType
60context_get_type (struct GNUNET_CHAT_Context* context);
61
62const struct GNUNET_HashCode*
63context_get_key (struct GNUNET_CHAT_Context* context);
64
65const char*
66context_get_nick (struct GNUNET_CHAT_Context* context);
67
68void
69context_set_nick (struct GNUNET_CHAT_Context* context,
70 const char *nick);
71
72#endif /* GNUNET_CHAT_CONTEXT_H_ */ 64#endif /* GNUNET_CHAT_CONTEXT_H_ */
diff --git a/src/gnunet_chat_file.c b/src/gnunet_chat_file.c
index b5f480c..d472551 100644
--- a/src/gnunet_chat_file.c
+++ b/src/gnunet_chat_file.c
@@ -22,81 +22,39 @@
22 * @file gnunet_chat_file.c 22 * @file gnunet_chat_file.c
23 */ 23 */
24 24
25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_file.h" 25#include "gnunet_chat_file.h"
27 26
28const struct GNUNET_HashCode* 27#include <limits.h>
29GNUNET_CHAT_file_get_hash (const struct GNUNET_CHAT_File *file)
30{
31 return &(file->hash);
32}
33 28
34uint64_t 29struct GNUNET_CHAT_File*
35GNUNET_CHAT_file_get_size (const struct GNUNET_CHAT_File *file) 30file_create_from_message (struct GNUNET_CHAT_Handle *handle,
31 const struct GNUNET_MESSENGER_MessageFile* message)
36{ 32{
37 return 0; 33 struct GNUNET_CHAT_File* file = GNUNET_new(struct GNUNET_CHAT_File);
38}
39 34
40int 35 file->handle = handle;
41GNUNET_CHAT_file_is_local (const struct GNUNET_CHAT_File *file)
42{
43 return GNUNET_NO;
44}
45 36
46int 37 file->name = GNUNET_strndup(message->name, NAME_MAX);
47GNUNET_CHAT_file_start_download (struct GNUNET_CHAT_File *file,
48 GNUNET_CHAT_MessageFileDownloadCallback callback,
49 void *cls)
50{
51 if (!file)
52 return GNUNET_SYSERR;
53 38
54 struct GNUNET_FS_Handle *handle; 39 GNUNET_memcpy(&(file->key), &(message->key), sizeof(file->key));
55 const char *path = ""; // TODO: path = download_directory + filename 40 GNUNET_memcpy(&(file->hash), &(message->hash), sizeof(file->hash));
56 41
57 GNUNET_FS_download_start( 42 file->uri = GNUNET_FS_uri_parse(message->uri, NULL);
58 handle, 43 file->download = NULL;
59 file->uri, 44 file->publish = NULL;
60 NULL, 45 file->unindex = NULL;
61 path,
62 NULL,
63 0,
64 0,
65 0,
66 GNUNET_FS_DOWNLOAD_OPTION_NONE,
67 NULL,
68 NULL
69 );
70 46
71 return GNUNET_OK; 47 return file;
72} 48}
73 49
74int 50void
75GNUNET_CHAT_file_pause_download (struct GNUNET_CHAT_File *file) 51file_destroy (struct GNUNET_CHAT_File* file)
76{ 52{
77 if (!file) 53 if (file->uri)
78 return GNUNET_SYSERR; 54 GNUNET_FS_uri_destroy(file->uri);
79 55
80 GNUNET_FS_download_suspend(file->context); 56 if (file->name)
81 return GNUNET_OK; 57 GNUNET_free(file->name);
82}
83
84int
85GNUNET_CHAT_file_resume_download (struct GNUNET_CHAT_File *file)
86{
87 if (!file)
88 return GNUNET_SYSERR;
89
90 GNUNET_FS_download_resume(file->context);
91 return GNUNET_OK;
92}
93
94int
95GNUNET_CHAT_file_stop_download (struct GNUNET_CHAT_File *file)
96{
97 if (!file)
98 return GNUNET_SYSERR;
99 58
100 GNUNET_FS_download_stop(file->context, GNUNET_YES); 59 GNUNET_free(file);
101 return GNUNET_OK;
102} 60}
diff --git a/src/gnunet_chat_file.h b/src/gnunet_chat_file.h
index ae45def..9669bf2 100644
--- a/src/gnunet_chat_file.h
+++ b/src/gnunet_chat_file.h
@@ -26,15 +26,34 @@
26#define GNUNET_CHAT_FILE_H_ 26#define GNUNET_CHAT_FILE_H_
27 27
28#include <gnunet/platform.h> 28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
30#include <gnunet/gnunet_crypto_lib.h>
29#include <gnunet/gnunet_fs_service.h> 31#include <gnunet/gnunet_fs_service.h>
30#include <gnunet/gnunet_messenger_service.h> 32#include <gnunet/gnunet_messenger_service.h>
31#include <gnunet/gnunet_util_lib.h> 33#include <gnunet/gnunet_util_lib.h>
32 34
35struct GNUNET_CHAT_Handle;
36
33struct GNUNET_CHAT_File 37struct GNUNET_CHAT_File
34{ 38{
39 struct GNUNET_CHAT_Handle *handle;
40
41 char *name;
42
35 struct GNUNET_HashCode hash; 43 struct GNUNET_HashCode hash;
44 struct GNUNET_CRYPTO_SymmetricSessionKey key;
45
36 struct GNUNET_FS_Uri* uri; 46 struct GNUNET_FS_Uri* uri;
37 struct GNUNET_FS_DownloadContext* context; 47 struct GNUNET_FS_DownloadContext* download;
48 struct GNUNET_FS_PublishContext* publish;
49 struct GNUNET_FS_UnindexContext* unindex;
38}; 50};
39 51
52struct GNUNET_CHAT_File*
53file_create_from_message (struct GNUNET_CHAT_Handle *handle,
54 const struct GNUNET_MESSENGER_MessageFile* message);
55
56void
57file_destroy (struct GNUNET_CHAT_File* file);
58
40#endif /* GNUNET_CHAT_FILE_H_ */ 59#endif /* GNUNET_CHAT_FILE_H_ */
diff --git a/src/gnunet_chat_group.c b/src/gnunet_chat_group.c
index e027b19..0c998ec 100644
--- a/src/gnunet_chat_group.c
+++ b/src/gnunet_chat_group.c
@@ -22,208 +22,53 @@
22 * @file gnunet_chat_group.c 22 * @file gnunet_chat_group.c
23 */ 23 */
24 24
25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_group.h" 25#include "gnunet_chat_group.h"
27#include "gnunet_chat_handle.h" 26
28#include "gnunet_chat_contact.h" 27#include "gnunet_chat_group_intern.c"
29 28
30struct GNUNET_CHAT_Group* 29struct GNUNET_CHAT_Group*
31group_create(struct GNUNET_CHAT_Handle *handle, 30group_create_from_context (struct GNUNET_CHAT_Handle *handle,
32 const char *topic) 31 struct GNUNET_CHAT_Context *context)
33{ 32{
34 struct GNUNET_HashCode topic_key; 33 struct GNUNET_CHAT_Group* group = GNUNET_new(struct GNUNET_CHAT_Group);
35
36 if (topic) {
37 GNUNET_CRYPTO_hash(topic, strlen(topic), &topic_key);
38 }
39
40 struct GNUNET_CHAT_Group *group = GNUNET_new(struct GNUNET_CHAT_Group);
41 34
42 group->handle = handle; 35 group->handle = handle;
43 group->context = context_create( 36 group->context = context;
44 handle, 37
45 GNUNET_CHAT_CONTEXT_TYPE_GROUP, 38 group->topic = NULL;
46 topic? &topic_key : NULL
47 );
48 39
49 group->is_public = topic? GNUNET_YES : GNUNET_NO;
50 group->announcement = NULL; 40 group->announcement = NULL;
51 group->search = NULL; 41 group->search = NULL;
52 42
53 if (!group->context)
54 {
55 group_destroy (group);
56 return NULL;
57 }
58
59 const struct GNUNET_HashCode *key = context_get_key(group->context);
60
61 const int result = GNUNET_CONTAINER_multihashmap_put(
62 handle->groups,
63 key,
64 group,
65 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
66 );
67
68 if (GNUNET_OK != result) {
69 group_destroy(group);
70 return NULL;
71 }
72
73 return group; 43 return group;
74} 44}
75 45
76void 46void
77group_destroy(struct GNUNET_CHAT_Group* group) 47group_destroy (struct GNUNET_CHAT_Group* group)
78{ 48{
79 if (!group->context) 49 if (group->search)
80 goto skip_context; 50 GNUNET_REGEX_search_cancel(group->search);
81 51
82 struct GNUNET_CHAT_Handle *handle = group->handle; 52 if (group->announcement)
83 const struct GNUNET_HashCode *key = context_get_key(group->context); 53 GNUNET_REGEX_announce_cancel(group->announcement);
84 54
85 GNUNET_CONTAINER_multihashmap_remove( 55 if (group->topic)
86 handle->groups, 56 GNUNET_free(group->topic);
87 key,
88 group
89 );
90 57
91 context_destroy(group->context);
92
93skip_context:
94 GNUNET_free(group); 58 GNUNET_free(group);
95} 59}
96 60
97int
98GNUNET_CHAT_group_leave (struct GNUNET_CHAT_Group *group)
99{
100 if (!group)
101 return GNUNET_SYSERR;
102
103 if (GNUNET_YES != handle_update_chat_group(group->handle, group, GNUNET_YES))
104 return GNUNET_SYSERR;
105
106 if (group->context)
107 GNUNET_MESSENGER_close_room(group->context->room);
108
109 group_destroy(group);
110 return GNUNET_OK;
111}
112
113void
114GNUNET_CHAT_group_set_name (struct GNUNET_CHAT_Group *group,
115 const char *name)
116{
117 if (!group)
118 return;
119
120 if (group->context)
121 context_set_nick(group->context, name);
122}
123
124const char*
125GNUNET_CHAT_group_get_name (const struct GNUNET_CHAT_Group *group)
126{
127 if (!group)
128 return NULL;
129
130 if (!group->context)
131 return NULL;
132
133 return context_get_nick(group->context);
134}
135
136void 61void
137GNUNET_CHAT_group_invite_contact (struct GNUNET_CHAT_Group *group, 62group_publish (struct GNUNET_CHAT_Group* group)
138 struct GNUNET_CHAT_Contact *contact)
139{ 63{
140 if ((!group) || (!contact)) 64 group->announcement = GNUNET_REGEX_announce(
141 return; 65 group->handle->cfg, group->topic, // TODO: raw topic?
142 66 GNUNET_TIME_relative_get_minute_(), // TODO: configure delay?
143 struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context(contact); 67 1 // TODO: no compression?
144
145 if (!context)
146 return;
147
148 struct GNUNET_MESSENGER_Handle *messenger = group->handle->handles.messenger;
149 GNUNET_MESSENGER_open_room(messenger, context_get_key(group->context));
150
151 struct GNUNET_MESSENGER_Message message;
152 message.header.kind = GNUNET_MESSENGER_KIND_INVITE;
153
154 int result = GNUNET_CRYPTO_get_peer_identity(
155 group->handle->cfg,
156 &(message.body.invite.door)
157 );
158
159 if (GNUNET_OK != result)
160 return;
161
162 GNUNET_memcpy(
163 &(message.body.invite.key),
164 context_get_key(group->context),
165 sizeof(message.body.invite.key)
166 );
167
168 GNUNET_MESSENGER_send_message(context->room, &message, NULL);
169}
170
171struct GNUNET_CHAT_GroupIterateContacts
172{
173 struct GNUNET_CHAT_Group *group;
174 GNUNET_CHAT_GroupContactCallback callback;
175 void *cls;
176};
177
178static int
179group_call_member (void* cls, struct GNUNET_CHAT_Handle *handle,
180 struct GNUNET_CHAT_Contact *contact)
181{
182 struct GNUNET_CHAT_GroupIterateContacts *iterate = cls;
183
184 return iterate->callback(iterate->cls, iterate->group, contact);
185}
186
187static int
188group_iterate_members (void* cls, struct GNUNET_MESSENGER_Room *room,
189 const struct GNUNET_MESSENGER_Contact *contact)
190{
191 struct GNUNET_CHAT_GroupIterateContacts *iterate = cls;
192
193 return contact_call(
194 iterate->group->handle,
195 contact,
196 group_call_member,
197 iterate
198 ); 68 );
199}
200
201int
202GNUNET_CHAT_group_iterate_contacts (struct GNUNET_CHAT_Group *group,
203 GNUNET_CHAT_GroupContactCallback callback,
204 void *cls)
205{
206 if (!group)
207 return GNUNET_SYSERR;
208
209 if (!callback)
210 return GNUNET_MESSENGER_iterate_members(group->context->room, NULL, cls);
211 69
212 struct GNUNET_CHAT_GroupIterateContacts iterate; 70 group->search = GNUNET_REGEX_search(
213 iterate.group = group; 71 group->handle->cfg, group->topic, // TODO: raw topic?
214 iterate.callback = callback; 72 search_group_by_topic, group
215 iterate.cls = cls;
216
217 return GNUNET_MESSENGER_iterate_members(
218 group->context->room, group_iterate_members, &iterate
219 ); 73 );
220} 74}
221
222struct GNUNET_CHAT_Context*
223GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group)
224{
225 if (!group)
226 return NULL;
227
228 return group->context;
229}
diff --git a/src/gnunet_chat_group.h b/src/gnunet_chat_group.h
index c0127bc..0130481 100644
--- a/src/gnunet_chat_group.h
+++ b/src/gnunet_chat_group.h
@@ -25,26 +25,33 @@
25#ifndef GNUNET_CHAT_GROUP_H_ 25#ifndef GNUNET_CHAT_GROUP_H_
26#define GNUNET_CHAT_GROUP_H_ 26#define GNUNET_CHAT_GROUP_H_
27 27
28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
28#include <gnunet/gnunet_regex_service.h> 30#include <gnunet/gnunet_regex_service.h>
31#include <gnunet/gnunet_util_lib.h>
29 32
30#include "gnunet_chat_context.h" 33struct GNUNET_CHAT_Handle;
34struct GNUNET_CHAT_Context;
31 35
32struct GNUNET_CHAT_Group 36struct GNUNET_CHAT_Group
33{ 37{
34 struct GNUNET_CHAT_Handle *handle; 38 struct GNUNET_CHAT_Handle *handle;
35 struct GNUNET_CHAT_Context *context; 39 struct GNUNET_CHAT_Context *context;
36 40
37 int is_public; 41 char *topic;
38 42
39 struct GNUNET_REGEX_Announcement *announcement; 43 struct GNUNET_REGEX_Announcement *announcement;
40 struct GNUNET_REGEX_Search *search; 44 struct GNUNET_REGEX_Search *search;
41}; 45};
42 46
43struct GNUNET_CHAT_Group* 47struct GNUNET_CHAT_Group*
44group_create(struct GNUNET_CHAT_Handle *handle, 48group_create_from_context (struct GNUNET_CHAT_Handle *handle,
45 const char *topic); 49 struct GNUNET_CHAT_Context *context);
46 50
47void 51void
48group_destroy(struct GNUNET_CHAT_Group* group); 52group_destroy (struct GNUNET_CHAT_Group* group);
53
54void
55group_publish (struct GNUNET_CHAT_Group* group);
49 56
50#endif /* GNUNET_CHAT_GROUP_H_ */ 57#endif /* GNUNET_CHAT_GROUP_H_ */
diff --git a/src/gnunet_chat_group_intern.c b/src/gnunet_chat_group_intern.c
new file mode 100644
index 0000000..b70b901
--- /dev/null
+++ b/src/gnunet_chat_group_intern.c
@@ -0,0 +1,51 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_group_intern.c
23 */
24
25#include "gnunet_chat_context.h"
26#include "gnunet_chat_handle.h"
27
28#define GNUNET_UNUSED __attribute__ ((unused))
29
30void
31search_group_by_topic(void *cls,
32 const struct GNUNET_PeerIdentity *door,
33 GNUNET_UNUSED const struct GNUNET_PeerIdentity *get_path,
34 GNUNET_UNUSED unsigned int get_path_length,
35 GNUNET_UNUSED const struct GNUNET_PeerIdentity *put_path,
36 GNUNET_UNUSED unsigned int put_path_length)
37{
38 struct GNUNET_CHAT_Group *group = cls;
39
40 struct GNUNET_PeerIdentity peer;
41 GNUNET_CRYPTO_get_peer_identity(group->handle->cfg, &peer);
42
43 if (0 == GNUNET_memcmp(&peer, door))
44 return;
45
46 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
47 group->context->room
48 );
49
50 GNUNET_MESSENGER_enter_room(group->handle->messenger, door, key);
51}
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}
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
index b287336..a0f44e0 100644
--- a/src/gnunet_chat_handle.h
+++ b/src/gnunet_chat_handle.h
@@ -26,86 +26,45 @@
26#define GNUNET_CHAT_HANDLE_H_ 26#define GNUNET_CHAT_HANDLE_H_
27 27
28#include <gnunet/platform.h> 28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
29#include <gnunet/gnunet_config.h> 30#include <gnunet/gnunet_config.h>
30#include <gnunet/gnunet_container_lib.h> 31#include <gnunet/gnunet_container_lib.h>
31#include <gnunet/gnunet_arm_service.h> 32#include <gnunet/gnunet_arm_service.h>
32#include <gnunet/gnunet_fs_service.h> 33#include <gnunet/gnunet_fs_service.h>
33#include <gnunet/gnunet_messenger_service.h> 34#include <gnunet/gnunet_messenger_service.h>
34#include <gnunet/gnunet_regex_service.h>
35#include <gnunet/gnunet_util_lib.h> 35#include <gnunet/gnunet_util_lib.h>
36 36
37#include "gnunet_chat_lib.h"
38
37struct GNUNET_CHAT_Handle 39struct GNUNET_CHAT_Handle
38{ 40{
39 const struct GNUNET_CONFIGURATION_Handle* cfg; 41 const struct GNUNET_CONFIGURATION_Handle* cfg;
40 42
41 struct {
42 /*
43 * feature: (automatically start required services)
44 */
45 struct GNUNET_ARM_Handle *arm;
46
47 /*
48 * required: (files can be uploaded/downloaded)
49 */
50 struct GNUNET_FS_Handle *fs;
51
52 /*
53 * required!
54 */
55 struct GNUNET_MESSENGER_Handle *messenger;
56 } handles;
57
58 struct {
59 struct GNUNET_CONTAINER_MultiShortmap *short_map;
60 struct GNUNET_CONTAINER_MultiHashMap *hash_map;
61 } contacts;
62
63 struct GNUNET_CONTAINER_MultiHashMap *groups;
64 struct GNUNET_CONTAINER_MultiHashMap *contexts;
65 struct GNUNET_CONTAINER_MultiHashMap *files;
66
67 GNUNET_CHAT_ContextMessageCallback msg_cb; 43 GNUNET_CHAT_ContextMessageCallback msg_cb;
68 void *msg_cls; 44 void *msg_cls;
69 45
70 GNUNET_CHAT_WarningCallback warn_cb; 46 GNUNET_CHAT_WarningCallback warn_cb;
71 void *warn_cls; 47 void *warn_cls;
72};
73
74int
75handle_update_chat_contact (struct GNUNET_CHAT_Handle *handle,
76 struct GNUNET_CHAT_Contact *chatContact,
77 int removeContact);
78
79int
80handle_update_chat_group (struct GNUNET_CHAT_Handle *handle,
81 struct GNUNET_CHAT_Group *chatGroup,
82 int removeGroup);
83 48
84int 49 struct GNUNET_CONTAINER_MultiHashMap *files;
85handle_update_chat_context (struct GNUNET_CHAT_Handle *handle, 50 struct GNUNET_CONTAINER_MultiHashMap *contexts;
86 struct GNUNET_CHAT_Context *context, 51 struct GNUNET_CONTAINER_MultiShortmap *contacts;
87 int removeContext); 52 struct GNUNET_CONTAINER_MultiHashMap *groups;
88 53
89int 54 struct GNUNET_ARM_Handle *arm;
90handle_update_chat_file (struct GNUNET_CHAT_Handle *handle, 55 struct GNUNET_FS_Handle *fs;
91 struct GNUNET_CHAT_File *file, 56 struct GNUNET_MESSENGER_Handle *messenger;
92 int removeFile); 57};
93 58
94struct GNUNET_CHAT_Contact* 59struct GNUNET_CHAT_Handle*
95handle_get_chat_contact (struct GNUNET_CHAT_Handle *handle, 60handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
96 const struct GNUNET_MESSENGER_Contact *contact); 61 const char* name,
62 GNUNET_CHAT_ContextMessageCallback msg_cb,
63 void *msg_cls,
64 GNUNET_CHAT_WarningCallback warn_cb,
65 void *warn_cls);
97 66
98void 67void
99handle_set_chat_contact (struct GNUNET_CHAT_Handle *handle, 68handle_destroy (struct GNUNET_CHAT_Handle* handle);
100 const struct GNUNET_MESSENGER_Contact *contact,
101 struct GNUNET_CHAT_Contact *chatContact);
102
103struct GNUNET_CHAT_Context*
104handle_get_chat_context (struct GNUNET_CHAT_Handle *handle,
105 const struct GNUNET_HashCode *key);
106
107struct GNUNET_CHAT_File*
108handle_get_chat_file (struct GNUNET_CHAT_Handle *handle,
109 const struct GNUNET_HashCode *hash);
110 69
111#endif /* GNUNET_CHAT_HANDLE_H_ */ 70#endif /* GNUNET_CHAT_HANDLE_H_ */
diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c
new file mode 100644
index 0000000..282492c
--- /dev/null
+++ b/src/gnunet_chat_handle_intern.c
@@ -0,0 +1,308 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_handle_intern.c
23 */
24
25#include "gnunet_chat_contact.h"
26#include "gnunet_chat_context.h"
27#include "gnunet_chat_group.h"
28#include "gnunet_chat_handle.h"
29#include "gnunet_chat_message.h"
30#include "gnunet_chat_util.h"
31
32#define GNUNET_UNUSED __attribute__ ((unused))
33
34void
35on_handle_arm_connection(void *cls, int connected)
36{
37 struct GNUNET_CHAT_Handle *chat = cls;
38
39 if (GNUNET_YES == connected) {
40 GNUNET_ARM_request_service_start(
41 chat->arm, "messenger",
42 GNUNET_OS_INHERIT_STD_NONE,
43 NULL, NULL
44 );
45
46 GNUNET_ARM_request_service_start(
47 chat->arm, "fs",
48 GNUNET_OS_INHERIT_STD_NONE,
49 NULL, NULL
50 );
51 } else {
52 GNUNET_ARM_request_service_start(
53 chat->arm, "arm",
54 GNUNET_OS_INHERIT_STD_NONE,
55 NULL, NULL
56 );
57 }
58}
59
60void*
61notify_handle_fs_progress(void* cls, const struct GNUNET_FS_ProgressInfo* info)
62{
63 struct GNUNET_CHAT_Handle *chat = cls;
64
65 if (!chat)
66 return NULL;
67
68 switch (info->status) {
69 case GNUNET_FS_STATUS_PUBLISH_START: {
70 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
71 publication->progress = 0.0f;
72
73 GNUNET_SCHEDULER_add_now(&CGTK_publication_progress, publication);
74
75 return publication;*/
76 break;
77 } case GNUNET_FS_STATUS_PUBLISH_PROGRESS: {
78 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
79 publication->progress = 1.0f * info->value.publish.completed / info->value.publish.size;
80
81 GNUNET_SCHEDULER_add_now(&CGTK_publication_progress, publication);
82
83 return publication;*/
84 break;
85 } case GNUNET_FS_STATUS_PUBLISH_COMPLETED: {
86 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
87 publication->uri = GNUNET_FS_uri_dup(info->value.publish.specifics.completed.chk_uri);
88 publication->progress = 1.0f;
89
90 GNUNET_SCHEDULER_add_now(&CGTK_publication_finish, publication);*/
91 break;
92 } case GNUNET_FS_STATUS_PUBLISH_ERROR: {
93 /*publication_t* publication = (publication_t*) info->value.publish.cctx;
94
95 GNUNET_SCHEDULER_add_now(&CGTK_publication_error, publication);*/
96 break;
97 } case GNUNET_FS_STATUS_DOWNLOAD_START: {
98 /*request_t* request = (request_t*) info->value.download.cctx;
99 request->progress = 0.0f;
100
101 return request;*/
102 break;
103 } case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: {
104 return info->value.download.cctx;
105 } case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: {
106 return info->value.download.cctx;
107 } case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: {
108 /*request_t* request = (request_t*) info->value.download.cctx;
109 request->progress = 1.0f * info->value.download.completed / info->value.download.size;
110
111 GNUNET_SCHEDULER_add_now(&CGTK_request_progress, request);
112
113 return request;*/
114 break;
115 } case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: {
116 /*request_t* request = (request_t*) info->value.download.cctx;
117 request->progress = 1.0f;
118
119 GNUNET_SCHEDULER_add_now(&CGTK_request_finish, request);*/
120 break;
121 } case GNUNET_FS_STATUS_DOWNLOAD_ERROR: {
122 /*request_t *request = (request_t *) info->value.download.cctx;
123
124 GNUNET_SCHEDULER_add_now(&CGTK_request_error, request);*/
125 break;
126 } case GNUNET_FS_STATUS_UNINDEX_START: {
127 /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
128 publication->progress = 0.0f;
129
130 return publication;*/
131 break;
132 } case GNUNET_FS_STATUS_UNINDEX_PROGRESS: {
133 /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
134 publication->progress = 1.0f * info->value.unindex.completed / info->value.unindex.size;
135
136 return publication;*/
137 break;
138 } case GNUNET_FS_STATUS_UNINDEX_COMPLETED: {
139 /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
140 publication->progress = 1.0f;
141
142 GNUNET_SCHEDULER_add_now(&CGTK_publication_unindex_finish, publication);*/
143 break;
144 } default: {
145 break;
146 }
147 }
148
149 return NULL;
150}
151
152struct GNUNET_CHAT_CheckHandleRoomMembers
153{
154 const struct GNUNET_IDENTITY_PublicKey *ignore_key;
155 const struct GNUNET_MESSENGER_Contact *contact;
156};
157
158int
159check_handle_room_members (void* cls,
160 GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
161 const struct GNUNET_MESSENGER_Contact *contact)
162{
163 struct GNUNET_CHAT_CheckHandleRoomMembers *check = cls;
164
165 const struct GNUNET_IDENTITY_PublicKey *contact_key = (
166 GNUNET_MESSENGER_contact_get_key(contact)
167 );
168
169 if (0 == GNUNET_memcmp(contact_key, check->ignore_key))
170 return GNUNET_YES;
171
172 if (check->contact)
173 return GNUNET_NO;
174
175 check->contact = contact;
176 return GNUNET_YES;
177}
178
179struct GNUNET_CHAT_Context*
180request_handle_context_by_room (struct GNUNET_CHAT_Handle *handle,
181 struct GNUNET_MESSENGER_Room *room)
182{
183 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(room);
184
185 struct GNUNET_CHAT_Context *context = GNUNET_CONTAINER_multihashmap_get(
186 handle->contexts, key
187 );
188
189 if (context)
190 return context;
191
192 context = context_create_from_room(handle, room);
193
194 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
195 handle->contexts, key, context,
196 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
197 {
198 context_destroy(context);
199 return NULL;
200 }
201
202 struct GNUNET_CHAT_CheckHandleRoomMembers check;
203 check.ignore_key = GNUNET_MESSENGER_get_key(handle->messenger);
204 check.contact = NULL;
205
206 GNUNET_MESSENGER_iterate_members(room, check_handle_room_members, &check);
207
208 if (check.contact)
209 {
210 context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT;
211
212 struct GNUNET_CHAT_Contact *contact = contact_create_from_member(
213 handle, check.contact
214 );
215
216 struct GNUNET_ShortHashCode shorthash;
217 util_shorthash_from_member(check.contact, &shorthash);
218
219 if (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(
220 handle->contacts, &shorthash, contact,
221 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
222 return context;
223
224 contact_destroy(contact);
225 }
226 else
227 {
228 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
229
230 struct GNUNET_CHAT_Group *group = group_create_from_context(
231 handle, context
232 );
233
234 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(
235 handle->groups, key, group,
236 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
237 return context;
238
239 group_destroy(group);
240 }
241
242 GNUNET_CONTAINER_multihashmap_remove(handle->contexts, key, context);
243 context_destroy(context);
244 return NULL;
245}
246
247int
248find_handle_rooms (void *cls, struct GNUNET_MESSENGER_Room *room,
249 GNUNET_UNUSED const struct GNUNET_MESSENGER_Contact *member)
250{
251 struct GNUNET_CHAT_Handle *handle = cls;
252
253 request_handle_context_by_room(
254 handle, room
255 );
256
257 return GNUNET_YES;
258}
259
260void
261on_handle_identity(void *cls,
262 GNUNET_UNUSED struct GNUNET_MESSENGER_Handle *messenger)
263{
264 struct GNUNET_CHAT_Handle *handle = cls;
265
266 GNUNET_MESSENGER_find_rooms(
267 handle->messenger, NULL, find_handle_rooms, handle
268 );
269}
270
271void
272on_handle_message (void *cls,
273 struct GNUNET_MESSENGER_Room *room,
274 GNUNET_UNUSED const struct GNUNET_MESSENGER_Contact *sender,
275 const struct GNUNET_MESSENGER_Message *msg,
276 const struct GNUNET_HashCode *hash,
277 GNUNET_UNUSED enum GNUNET_MESSENGER_MessageFlags flags)
278{
279 struct GNUNET_CHAT_Handle *handle = cls;
280
281 struct GNUNET_CHAT_Context *context = request_handle_context_by_room(
282 handle, room
283 );
284
285 if (!context)
286 return;
287
288 struct GNUNET_CHAT_Message *message = GNUNET_CONTAINER_multihashmap_get(
289 context->messages, hash
290 );
291
292 if (message)
293 goto process_callback;
294
295 message = message_create_from_msg(context, hash, msg);
296
297 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
298 context->messages, hash, message,
299 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
300 {
301 message_destroy(message);
302 return;
303 }
304
305process_callback:
306 if (handle->msg_cb)
307 handle->msg_cb(handle->msg_cls, context, message);
308}
diff --git a/src/gnunet_chat_invitation.c b/src/gnunet_chat_invitation.c
index 44f7787..9562daa 100644
--- a/src/gnunet_chat_invitation.c
+++ b/src/gnunet_chat_invitation.c
@@ -24,14 +24,24 @@
24 24
25#include "gnunet_chat_invitation.h" 25#include "gnunet_chat_invitation.h"
26 26
27void 27struct GNUNET_CHAT_Invitation*
28GNUNET_CHAT_invitation_accept (struct GNUNET_CHAT_Invitation *invitation) 28invitation_create_from_message (struct GNUNET_CHAT_Context *context,
29 const struct GNUNET_MESSENGER_MessageInvite *message)
29{ 30{
30 //TODO 31 struct GNUNET_CHAT_Invitation *invitation = GNUNET_new(struct GNUNET_CHAT_Invitation);
32
33 invitation->context = context;
34
35 GNUNET_memcpy(&(invitation->key), &(message->key), sizeof(invitation->key));
36 invitation->door = GNUNET_PEER_intern(&(message->door));
37
38 return invitation;
31} 39}
32 40
33void 41void
34GNUNET_CHAT_invitation_decline (struct GNUNET_CHAT_Invitation *invitation) 42invitation_destroy (struct GNUNET_CHAT_Invitation *invitation)
35{ 43{
36 //TODO 44 GNUNET_PEER_decrement_rcs(&(invitation->door), 1);
45
46 GNUNET_free(invitation);
37} 47}
diff --git a/src/gnunet_chat_invitation.h b/src/gnunet_chat_invitation.h
index dd2b8e8..433131e 100644
--- a/src/gnunet_chat_invitation.h
+++ b/src/gnunet_chat_invitation.h
@@ -25,11 +25,28 @@
25#ifndef GNUNET_CHAT_INVITATION_H_ 25#ifndef GNUNET_CHAT_INVITATION_H_
26#define GNUNET_CHAT_INVITATION_H_ 26#define GNUNET_CHAT_INVITATION_H_
27 27
28#include "gnunet_chat_lib.h" 28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
30#include <gnunet/gnunet_crypto_lib.h>
31#include <gnunet/gnunet_messenger_service.h>
32#include <gnunet/gnunet_peer_lib.h>
33#include <gnunet/gnunet_util_lib.h>
34
35struct GNUNET_CHAT_Context;
29 36
30struct GNUNET_CHAT_Invitation 37struct GNUNET_CHAT_Invitation
31{ 38{
39 struct GNUNET_CHAT_Context *context;
32 40
41 struct GNUNET_HashCode key;
42 GNUNET_PEER_Id door;
33}; 43};
34 44
45struct GNUNET_CHAT_Invitation*
46invitation_create_from_message (struct GNUNET_CHAT_Context *context,
47 const struct GNUNET_MESSENGER_MessageInvite *message);
48
49void
50invitation_destroy (struct GNUNET_CHAT_Invitation *invitation);
51
35#endif /* GNUNET_CHAT_INVITATION_H_ */ 52#endif /* GNUNET_CHAT_INVITATION_H_ */
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
new file mode 100644
index 0000000..23c541d
--- /dev/null
+++ b/src/gnunet_chat_lib.c
@@ -0,0 +1,693 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_lib.c
23 */
24
25#include "gnunet_chat_lib.h"
26
27#include <limits.h>
28
29#include "gnunet_chat_config.h"
30#include "gnunet_chat_contact.h"
31#include "gnunet_chat_context.h"
32#include "gnunet_chat_file.h"
33#include "gnunet_chat_group.h"
34#include "gnunet_chat_handle.h"
35#include "gnunet_chat_invitation.h"
36#include "gnunet_chat_message.h"
37#include "gnunet_chat_util.h"
38
39#include "gnunet_chat_lib_intern.c"
40
41struct GNUNET_CHAT_Handle*
42GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
43 const char *name,
44 GNUNET_CHAT_WarningCallback warn_cb, void *warn_cls,
45 GNUNET_CHAT_ContextMessageCallback msg_cb, void *msg_cls)
46{
47 if (!cfg)
48 return NULL;
49
50 if (!name)
51 return NULL;
52
53 return handle_create_from_config(
54 cfg, name, msg_cb, msg_cls, warn_cb, warn_cls
55 );
56}
57
58void
59GNUNET_CHAT_stop (struct GNUNET_CHAT_Handle *handle)
60{
61 if (!handle)
62 return;
63
64 handle_destroy(handle);
65}
66
67int
68GNUNET_CHAT_update (struct GNUNET_CHAT_Handle *handle)
69{
70 if (!handle)
71 return GNUNET_SYSERR;
72
73 return GNUNET_MESSENGER_update(handle->messenger);
74}
75
76int
77GNUNET_CHAT_set_name (struct GNUNET_CHAT_Handle *handle,
78 const char *name)
79{
80 if (!handle)
81 return GNUNET_SYSERR;
82
83 if (!name)
84 return GNUNET_NO;
85
86 return GNUNET_MESSENGER_set_name(handle->messenger, name);
87}
88
89const char*
90GNUNET_CHAT_get_name (const struct GNUNET_CHAT_Handle *handle)
91{
92 if (!handle)
93 return NULL;
94
95 return GNUNET_MESSENGER_get_name(handle->messenger);
96}
97
98const struct GNUNET_IDENTITY_PublicKey*
99GNUNET_CHAT_get_key (const struct GNUNET_CHAT_Handle *handle)
100{
101 if (!handle)
102 return NULL;
103
104 return GNUNET_MESSENGER_get_key(handle->messenger);
105}
106
107int
108GNUNET_CHAT_iterate_contacts (struct GNUNET_CHAT_Handle *handle,
109 GNUNET_CHAT_ContactCallback callback,
110 void *cls)
111{
112 if (!handle)
113 return GNUNET_SYSERR;
114
115 struct GNUNET_CHAT_HandleIterateContacts it;
116 it.handle = handle;
117 it.cb = callback;
118 it.cls = cls;
119
120 return GNUNET_CONTAINER_multishortmap_iterate(
121 handle->contacts, it_handle_iterate_contacts, &it
122 );
123}
124
125struct GNUNET_CHAT_Group *
126GNUNET_CHAT_group_create (struct GNUNET_CHAT_Handle *handle,
127 const char* topic)
128{
129 if (!handle)
130 return NULL;
131
132 struct GNUNET_HashCode key;
133
134 if (topic)
135 GNUNET_CRYPTO_hash(topic, strlen(topic), &key);
136 else
137 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, &key, sizeof(key));
138
139 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(
140 handle->contexts, &key))
141 return NULL;
142
143 struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_open_room(
144 handle->messenger, &key
145 );
146
147 struct GNUNET_CHAT_Context *context = context_create_from_room(handle, room);
148
149 context->type = GNUNET_CHAT_CONTEXT_TYPE_GROUP;
150
151 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
152 handle->contexts, &key, context,
153 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
154 goto destroy_context;
155
156 struct GNUNET_CHAT_Group *group = group_create_from_context(handle, context);
157
158 util_set_name_field(topic, &(group->topic));
159
160 if (group->topic)
161 group_publish(group);
162
163 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(
164 handle->groups, &key, group,
165 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
166 return group;
167
168 group_destroy(group);
169
170 GNUNET_CONTAINER_multihashmap_remove(handle->contexts, &key, context);
171
172destroy_context:
173 context_destroy(context);
174 return NULL;
175}
176
177int
178GNUNET_CHAT_iterate_groups (struct GNUNET_CHAT_Handle *handle,
179 GNUNET_CHAT_GroupCallback callback,
180 void *cls)
181{
182 if (!handle)
183 return GNUNET_SYSERR;
184
185 struct GNUNET_CHAT_HandleIterateGroups it;
186 it.handle = handle;
187 it.cb = callback;
188 it.cls = cls;
189
190 return GNUNET_CONTAINER_multihashmap_iterate(
191 handle->groups, it_handle_iterate_groups, &it
192 );
193}
194
195int
196GNUNET_CHAT_contact_delete (struct GNUNET_CHAT_Contact *contact)
197{
198 if (!contact)
199 return GNUNET_SYSERR;
200
201 struct GNUNET_ShortHashCode shorthash;
202 util_shorthash_from_member(contact->member, &shorthash);
203
204 GNUNET_CONTAINER_multishortmap_remove(
205 contact->handle->contacts, &shorthash, contact
206 );
207
208 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
209 contact->context->room
210 );
211
212 GNUNET_CONTAINER_multihashmap_remove(
213 contact->handle->contexts, key, contact->context
214 );
215
216 GNUNET_MESSENGER_close_room(contact->context->room);
217
218 context_destroy(contact->context);
219 contact_destroy(contact);
220 return GNUNET_OK;
221}
222
223void
224GNUNET_CHAT_contact_set_name (struct GNUNET_CHAT_Contact *contact,
225 const char *name)
226{
227 if (!contact)
228 return;
229
230 util_set_name_field(name, &(contact->context->nick));
231}
232
233
234const char*
235GNUNET_CHAT_contact_get_name (const struct GNUNET_CHAT_Contact *contact)
236{
237 if (!contact)
238 return NULL;
239
240 if (contact->context->nick)
241 return contact->context->nick;
242
243 return GNUNET_MESSENGER_contact_get_name(contact->member);
244}
245
246
247const struct GNUNET_IDENTITY_PublicKey*
248GNUNET_CHAT_contact_get_key (const struct GNUNET_CHAT_Contact *contact)
249{
250 if (!contact)
251 return NULL;
252
253 return GNUNET_MESSENGER_contact_get_key(contact->member);
254}
255
256
257struct GNUNET_CHAT_Context*
258GNUNET_CHAT_contact_get_context (struct GNUNET_CHAT_Contact *contact)
259{
260 if (!contact)
261 return NULL;
262
263 return contact->context;
264}
265
266
267int
268GNUNET_CHAT_group_leave (struct GNUNET_CHAT_Group *group)
269{
270 if (!group)
271 return GNUNET_SYSERR;
272
273 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
274 group->context->room
275 );
276
277 GNUNET_CONTAINER_multihashmap_remove(
278 group->handle->groups, key, group
279 );
280
281 GNUNET_CONTAINER_multihashmap_remove(
282 group->handle->contexts, key, group->context
283 );
284
285 GNUNET_MESSENGER_close_room(group->context->room);
286
287 context_destroy(group->context);
288 group_destroy(group);
289 return GNUNET_OK;
290}
291
292
293void
294GNUNET_CHAT_group_set_name (struct GNUNET_CHAT_Group *group,
295 const char *name)
296{
297 if (!group)
298 return;
299
300 util_set_name_field(name, &(group->context->nick));
301}
302
303
304const char*
305GNUNET_CHAT_group_get_name (const struct GNUNET_CHAT_Group *group)
306{
307 if (!group)
308 return NULL;
309
310 return group->context->nick;
311}
312
313
314void
315GNUNET_CHAT_group_invite_contact (struct GNUNET_CHAT_Group *group,
316 struct GNUNET_CHAT_Contact *contact)
317{
318 if ((!group) || (!contact))
319 return;
320
321 const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
322 group->context->room
323 );
324
325 GNUNET_MESSENGER_open_room(group->handle->messenger, key);
326
327 struct GNUNET_MESSENGER_Message msg;
328 msg.header.kind = GNUNET_MESSENGER_KIND_INVITE;
329 GNUNET_CRYPTO_get_peer_identity(group->handle->cfg, &(msg.body.invite.door));
330 GNUNET_memcpy(&(msg.body.invite.key), key, sizeof(msg.body.invite.key));
331
332 GNUNET_MESSENGER_send_message(contact->context->room, &msg, contact->member);
333}
334
335int
336GNUNET_CHAT_group_iterate_contacts (struct GNUNET_CHAT_Group *group,
337 GNUNET_CHAT_GroupContactCallback callback,
338 void *cls)
339{
340 if (!group)
341 return GNUNET_SYSERR;
342
343 struct GNUNET_CHAT_GroupIterateContacts it;
344 it.group = group;
345 it.cb = callback;
346 it.cls = cls;
347
348 return GNUNET_MESSENGER_iterate_members(
349 group->context->room, it_group_iterate_contacts, &it
350 );
351}
352
353
354struct GNUNET_CHAT_Context*
355GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group)
356{
357 if (!group)
358 return NULL;
359
360 return group->context;
361}
362
363void
364GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
365 const char *text)
366{
367 if ((!context) || (!text))
368 return;
369
370 struct GNUNET_MESSENGER_Message msg;
371 msg.header.kind = GNUNET_MESSENGER_KIND_TEXT;
372 msg.body.text.text = GNUNET_strdup(text);
373
374 GNUNET_MESSENGER_send_message(context->room, &msg, NULL);
375
376 GNUNET_free(msg.body.text.text);
377}
378
379
380void
381GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context,
382 const char *path)
383{
384 if ((!context) || (!path))
385 return;
386
387 // TODO: encrypt file, publish file, share file
388}
389
390
391void
392GNUNET_CHAT_context_send_uri (struct GNUNET_CHAT_Context *context,
393 const char *uri)
394{
395 if ((!context) || (!uri))
396 return;
397
398 struct GNUNET_FS_Uri *furi = GNUNET_FS_uri_parse(uri, NULL);
399
400 if (!furi)
401 return;
402
403 // TODO: download file, hash file, share file
404}
405
406
407void
408GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
409 const struct GNUNET_CHAT_File *file)
410{
411 if ((!context) || (!file) || (strlen(file->name) > NAME_MAX))
412 return;
413
414 struct GNUNET_MESSENGER_Message msg;
415 msg.header.kind = GNUNET_MESSENGER_KIND_FILE;
416 GNUNET_memcpy(&(msg.body.file.key), &(file->key), sizeof(file->key));
417 GNUNET_memcpy(&(msg.body.file.hash), &(file->hash), sizeof(file->hash));
418 GNUNET_strlcpy(msg.body.file.name, file->name, NAME_MAX);
419 msg.body.file.uri = GNUNET_FS_uri_to_string(file->uri);
420
421 GNUNET_MESSENGER_send_message(context->room, &msg, NULL);
422
423 GNUNET_free(msg.body.file.uri);
424}
425
426
427void
428GNUNET_CHAT_context_delete_message (const struct GNUNET_CHAT_Message *message,
429 struct GNUNET_TIME_Relative delay)
430{
431 if (!message)
432 return;
433
434 struct GNUNET_MESSENGER_Message msg;
435 msg.header.kind = GNUNET_MESSENGER_KIND_DELETE;
436 GNUNET_memcpy(&(msg.body.delete.hash), &(message->hash), sizeof(message->hash));
437 msg.body.delete.delay = GNUNET_TIME_relative_hton(delay);
438
439 GNUNET_MESSENGER_send_message(message->context->room, &msg, NULL);
440}
441
442
443
444int
445GNUNET_CHAT_context_iterate_messages (struct GNUNET_CHAT_Context *context,
446 GNUNET_CHAT_ContextMessageCallback callback,
447 void *cls)
448{
449 if (!context)
450 return GNUNET_SYSERR;
451
452 struct GNUNET_CHAT_ContextIterateMessages it;
453 it.context = context;
454 it.cb = callback;
455 it.cls = cls;
456
457 return GNUNET_CONTAINER_multihashmap_iterate(
458 context->messages, it_context_iterate_messages, &it
459 );
460}
461
462
463enum GNUNET_CHAT_MessageKind
464GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message)
465{
466 if (!message)
467 return GNUNET_CHAT_KIND_UNKNOWN;
468
469 switch (message->msg->header.kind)
470 {
471 case GNUNET_MESSENGER_KIND_INVITE:
472 return GNUNET_CHAT_KIND_INVITATION;
473 case GNUNET_MESSENGER_KIND_TEXT:
474 return GNUNET_CHAT_KIND_TEXT;
475 case GNUNET_MESSENGER_KIND_FILE:
476 return GNUNET_CHAT_KIND_FILE;
477 default:
478 return GNUNET_CHAT_KIND_UNKNOWN;
479 }
480}
481
482
483struct GNUNET_TIME_Absolute
484GNUNET_CHAT_message_get_timestamp (const struct GNUNET_CHAT_Message *message)
485{
486 if (!message)
487 return GNUNET_TIME_absolute_get_zero_();
488
489 return GNUNET_TIME_absolute_ntoh(message->msg->header.timestamp);
490}
491
492
493const struct GNUNET_CHAT_Contact*
494GNUNET_CHAT_message_get_sender (const struct GNUNET_CHAT_Message *message)
495{
496 if (!message)
497 return NULL;
498
499 const struct GNUNET_MESSENGER_Contact *sender = GNUNET_MESSENGER_get_sender(
500 message->context->room, &(message->hash)
501 );
502
503 if (!sender)
504 return NULL;
505
506 struct GNUNET_ShortHashCode shorthash;
507 util_shorthash_from_member(sender, &shorthash);
508
509 return GNUNET_CONTAINER_multishortmap_get(
510 message->context->handle->contacts, &shorthash
511 );
512}
513
514
515int
516GNUNET_CHAT_message_get_read_receipt (const struct GNUNET_CHAT_Message *message,
517 GNUNET_CHAT_MessageReadReceiptCallback callback,
518 void *cls)
519{
520 if (!message)
521 return GNUNET_SYSERR;
522
523 // TODO: request read receipt? / check if newer message was received of sender?
524
525 return GNUNET_SYSERR;
526}
527
528
529const char*
530GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message)
531{
532 if (!message)
533 return NULL;
534
535 if (GNUNET_MESSENGER_KIND_TEXT != message->msg->header.kind)
536 return NULL;
537
538 return message->msg->body.text.text;
539}
540
541
542struct GNUNET_CHAT_File*
543GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message)
544{
545 if (!message)
546 return NULL;
547
548 if (GNUNET_MESSENGER_KIND_FILE != message->msg->header.kind)
549 return NULL;
550
551 return GNUNET_CONTAINER_multihashmap_get(
552 message->context->handle->files,
553 &(message->msg->body.file.hash)
554 );
555}
556
557
558struct GNUNET_CHAT_Invitation*
559GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message)
560{
561 if (!message)
562 return NULL;
563
564 if (GNUNET_MESSENGER_KIND_INVITE != message->msg->header.kind)
565 return NULL;
566
567 return GNUNET_CONTAINER_multihashmap_get(
568 message->context->invites,
569 &(message->hash)
570 );
571}
572
573
574const struct GNUNET_HashCode*
575GNUNET_CHAT_file_get_hash (const struct GNUNET_CHAT_File *file)
576{
577 if (!file)
578 return NULL;
579
580 return &(file->hash);
581}
582
583
584uint64_t
585GNUNET_CHAT_file_get_size (const struct GNUNET_CHAT_File *file)
586{
587 if (!file)
588 return 0;
589
590 if (file->uri)
591 return GNUNET_FS_uri_chk_get_file_size(file->uri);
592
593 const char *path = ""; // TODO: path = download_directory + file->name
594
595 // TODO: check size through info or check locally?
596
597 return 0;
598}
599
600
601int
602GNUNET_CHAT_file_is_local (const struct GNUNET_CHAT_File *file)
603{
604 if (!file)
605 return GNUNET_SYSERR;
606
607 const char *path = ""; // TODO: path = download_directory + file->name
608
609 // TODO: check locally?
610
611 return GNUNET_SYSERR;
612}
613
614
615int
616GNUNET_CHAT_file_start_download (struct GNUNET_CHAT_File *file,
617 GNUNET_CHAT_MessageFileDownloadCallback callback,
618 void *cls)
619{
620 if (!file)
621 return GNUNET_SYSERR;
622
623 // TODO: check if downloading?
624
625 const char *path = ""; // TODO: path = download_directory + file->name
626
627 file->download = GNUNET_FS_download_start(
628 file->handle->fs,
629 file->uri,
630 NULL,
631 path,
632 NULL,
633 0,
634 0,
635 0,
636 GNUNET_FS_DOWNLOAD_OPTION_NONE,
637 NULL,
638 NULL
639 );
640
641 return GNUNET_OK;
642}
643
644
645int
646GNUNET_CHAT_file_pause_download (struct GNUNET_CHAT_File *file)
647{
648 if (!file)
649 return GNUNET_SYSERR;
650
651 GNUNET_FS_download_suspend(file->download);
652 return GNUNET_OK;
653}
654
655
656int
657GNUNET_CHAT_file_resume_download (struct GNUNET_CHAT_File *file)
658{
659 if (!file)
660 return GNUNET_SYSERR;
661
662 GNUNET_FS_download_resume(file->download);
663 return GNUNET_OK;
664}
665
666
667int
668GNUNET_CHAT_file_stop_download (struct GNUNET_CHAT_File *file)
669{
670 if (!file)
671 return GNUNET_SYSERR;
672
673 GNUNET_FS_download_stop(file->download, GNUNET_YES);
674 file->download = NULL;
675 return GNUNET_OK;
676}
677
678
679void
680GNUNET_CHAT_invitation_accept (struct GNUNET_CHAT_Invitation *invitation)
681{
682 if (!invitation)
683 return;
684
685 struct GNUNET_PeerIdentity door;
686 GNUNET_PEER_resolve(invitation->door, &door);
687
688 GNUNET_MESSENGER_enter_room(
689 invitation->context->handle->messenger,
690 &door, &(invitation->key)
691 );
692}
693
diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c
new file mode 100644
index 0000000..8ccfce5
--- /dev/null
+++ b/src/gnunet_chat_lib_intern.c
@@ -0,0 +1,124 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_lib_intern.c
23 */
24
25#define GNUNET_UNUSED __attribute__ ((unused))
26
27struct GNUNET_CHAT_HandleIterateContacts
28{
29 struct GNUNET_CHAT_Handle *handle;
30 GNUNET_CHAT_ContactCallback cb;
31 void *cls;
32};
33
34int
35it_handle_iterate_contacts (void *cls,
36 GNUNET_UNUSED const struct GNUNET_ShortHashCode *key,
37 void *value)
38{
39 struct GNUNET_CHAT_HandleIterateContacts *it = cls;
40
41 if (!(it->cb))
42 return GNUNET_YES;
43
44 struct GNUNET_CHAT_Contact *contact = value;
45
46 return it->cb(it->cls, it->handle, contact);
47}
48
49struct GNUNET_CHAT_HandleIterateGroups
50{
51 struct GNUNET_CHAT_Handle *handle;
52 GNUNET_CHAT_GroupCallback cb;
53 void *cls;
54};
55
56int
57it_handle_iterate_groups (void *cls,
58 GNUNET_UNUSED const struct GNUNET_HashCode *key,
59 void *value)
60{
61 struct GNUNET_CHAT_HandleIterateGroups *it = cls;
62
63 if (!(it->cb))
64 return GNUNET_YES;
65
66 struct GNUNET_CHAT_Group *group = value;
67
68 return it->cb(it->cls, it->handle, group);
69}
70
71struct GNUNET_CHAT_GroupIterateContacts
72{
73 struct GNUNET_CHAT_Group *group;
74 GNUNET_CHAT_GroupContactCallback cb;
75 void *cls;
76};
77
78int
79it_group_iterate_contacts (void* cls,
80 GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
81 const struct GNUNET_MESSENGER_Contact *member)
82{
83 struct GNUNET_CHAT_GroupIterateContacts *it = cls;
84
85 if (!(it->cb))
86 return GNUNET_YES;
87
88 struct GNUNET_ShortHashCode shorthash;
89 util_shorthash_from_member(member, &shorthash);
90
91 struct GNUNET_CHAT_Contact *contact = GNUNET_CONTAINER_multishortmap_get(
92 it->group->handle->contacts, &shorthash
93 );
94
95 return it->cb(it->cls, it->group, contact);
96}
97
98struct GNUNET_CHAT_ContextIterateMessages
99{
100 struct GNUNET_CHAT_Context *context;
101 GNUNET_CHAT_ContextMessageCallback cb;
102 void *cls;
103};
104
105int
106it_context_iterate_messages (void *cls,
107 GNUNET_UNUSED const struct GNUNET_HashCode *key,
108 void *value)
109{
110 struct GNUNET_CHAT_ContextIterateMessages *it = cls;
111
112 if (!(it->cb))
113 return GNUNET_YES;
114
115 struct GNUNET_CHAT_Message *message = value;
116
117 return it->cb(it->cls, it->context, message);
118}
119
120
121
122
123
124
diff --git a/src/gnunet_chat_message.c b/src/gnunet_chat_message.c
index 805453e..bff8a52 100644
--- a/src/gnunet_chat_message.c
+++ b/src/gnunet_chat_message.c
@@ -22,70 +22,26 @@
22 * @file gnunet_chat_message.c 22 * @file gnunet_chat_message.c
23 */ 23 */
24 24
25#include "gnunet_chat_lib.h"
26#include "gnunet_chat_message.h" 25#include "gnunet_chat_message.h"
27 26
28enum GNUNET_CHAT_MessageKind 27struct GNUNET_CHAT_Message*
29GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message) 28message_create_from_msg (struct GNUNET_CHAT_Context *context,
29 const struct GNUNET_HashCode *hash,
30 const struct GNUNET_MESSENGER_Message *msg)
30{ 31{
31 if (!message) 32 struct GNUNET_CHAT_Message *message = GNUNET_new(struct GNUNET_CHAT_Message);
32 return GNUNET_CHAT_KIND_UNKNOWN;
33 33
34 switch (message->message->header.kind) { 34 message->context = context;
35 case GNUNET_MESSENGER_KIND_INVITE:
36 return GNUNET_CHAT_KIND_INVITATION;
37 case GNUNET_MESSENGER_KIND_TEXT:
38 return GNUNET_CHAT_KIND_TEXT;
39 case GNUNET_MESSENGER_KIND_FILE:
40 return GNUNET_CHAT_KIND_FILE;
41 default:
42 return GNUNET_CHAT_KIND_UNKNOWN;
43 }
44}
45
46struct GNUNET_TIME_Absolute
47GNUNET_CHAT_message_get_timestamp (const struct GNUNET_CHAT_Message *message)
48{
49 if (!message)
50 return GNUNET_TIME_absolute_get_zero_();
51
52 return GNUNET_TIME_absolute_ntoh(message->message->header.timestamp);
53}
54
55const struct GNUNET_CHAT_Contact*
56GNUNET_CHAT_message_get_sender (const struct GNUNET_CHAT_Message *message)
57{
58 return NULL;
59}
60 35
61int 36 GNUNET_memcpy(&(message->hash), hash, sizeof(message->hash));
62GNUNET_CHAT_message_get_read_receipt (const struct GNUNET_CHAT_Message *message,
63 GNUNET_CHAT_MessageReadReceiptCallback callback,
64 void *cls)
65{
66 return GNUNET_SYSERR;
67}
68
69struct GNUNET_CHAT_Invitation*
70GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message)
71{
72 return NULL; //TODO
73}
74
75const char*
76GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message)
77{
78 if (!message)
79 return NULL;
80 37
81 if (GNUNET_MESSENGER_KIND_TEXT != message->message->header.kind) 38 message->msg = msg;
82 return NULL;
83 39
84 return message->message->body.text.text; 40 return message;
85} 41}
86 42
87struct GNUNET_CHAT_File* 43void
88GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message) 44message_destroy (struct GNUNET_CHAT_Message* message)
89{ 45{
90 return NULL; 46 GNUNET_free(message);
91} 47}
diff --git a/src/gnunet_chat_message.h b/src/gnunet_chat_message.h
index 6de7fae..7b3051c 100644
--- a/src/gnunet_chat_message.h
+++ b/src/gnunet_chat_message.h
@@ -26,13 +26,27 @@
26#define GNUNET_CHAT_MESSAGE_H_ 26#define GNUNET_CHAT_MESSAGE_H_
27 27
28#include <gnunet/platform.h> 28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
29#include <gnunet/gnunet_messenger_service.h> 30#include <gnunet/gnunet_messenger_service.h>
30#include <gnunet/gnunet_util_lib.h> 31#include <gnunet/gnunet_util_lib.h>
31 32
33struct GNUNET_CHAT_Context;
34
32struct GNUNET_CHAT_Message 35struct GNUNET_CHAT_Message
33{ 36{
37 struct GNUNET_CHAT_Context *context;
38
34 struct GNUNET_HashCode hash; 39 struct GNUNET_HashCode hash;
35 const struct GNUNET_MESSENGER_Message *message; 40
41 const struct GNUNET_MESSENGER_Message *msg;
36}; 42};
37 43
44struct GNUNET_CHAT_Message*
45message_create_from_msg (struct GNUNET_CHAT_Context *context,
46 const struct GNUNET_HashCode *hash,
47 const struct GNUNET_MESSENGER_Message *msg);
48
49void
50message_destroy (struct GNUNET_CHAT_Message* message);
51
38#endif /* GNUNET_CHAT_MESSAGE_H_ */ 52#endif /* GNUNET_CHAT_MESSAGE_H_ */
diff --git a/src/gnunet_chat_util.c b/src/gnunet_chat_util.c
new file mode 100644
index 0000000..1a75ba9
--- /dev/null
+++ b/src/gnunet_chat_util.c
@@ -0,0 +1,45 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_util.c
23 */
24
25#include "gnunet_chat_util.h"
26
27void
28util_shorthash_from_member (const struct GNUNET_MESSENGER_Contact *member,
29 struct GNUNET_ShortHashCode* shorthash)
30{
31 memset(shorthash, 0, sizeof(*shorthash));
32 GNUNET_memcpy(shorthash, &member, sizeof(member));
33}
34
35void
36util_set_name_field (const char *name, char** field)
37{
38 if (*field)
39 GNUNET_free(*field);
40
41 if (name)
42 *field = GNUNET_strdup(name);
43 else
44 *field = NULL;
45}
diff --git a/src/gnunet_chat_util.h b/src/gnunet_chat_util.h
new file mode 100644
index 0000000..d9ff947
--- /dev/null
+++ b/src/gnunet_chat_util.h
@@ -0,0 +1,40 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_util.h
23 */
24
25#ifndef GNUNET_CHAT_UTIL_H_
26#define GNUNET_CHAT_UTIL_H_
27
28#include <gnunet/platform.h>
29#include <gnunet/gnunet_common.h>
30#include <gnunet/gnunet_messenger_service.h>
31#include <gnunet/gnunet_util_lib.h>
32
33void
34util_shorthash_from_member (const struct GNUNET_MESSENGER_Contact *member,
35 struct GNUNET_ShortHashCode* shorthash);
36
37void
38util_set_name_field (const char *name, char** field);
39
40#endif /* GNUNET_CHAT_UTIL_H_ */