diff options
Diffstat (limited to 'src/messenger/messenger_api_room.c')
-rw-r--r-- | src/messenger/messenger_api_room.c | 214 |
1 files changed, 164 insertions, 50 deletions
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c index 5fedf1a78..df141ca12 100644 --- a/src/messenger/messenger_api_room.c +++ b/src/messenger/messenger_api_room.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2020 GNUnet e.V. | 3 | Copyright (C) 2020--2021 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | under the terms of the GNU Affero General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
@@ -30,6 +30,8 @@ | |||
30 | struct GNUNET_MESSENGER_Room* | 30 | struct GNUNET_MESSENGER_Room* |
31 | create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | 31 | create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) |
32 | { | 32 | { |
33 | GNUNET_assert((handle) && (key)); | ||
34 | |||
33 | struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room); | 35 | struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room); |
34 | 36 | ||
35 | room->handle = handle; | 37 | room->handle = handle; |
@@ -38,11 +40,10 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod | |||
38 | room->opened = GNUNET_NO; | 40 | room->opened = GNUNET_NO; |
39 | room->contact_id = NULL; | 41 | room->contact_id = NULL; |
40 | 42 | ||
41 | room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); | ||
42 | |||
43 | init_list_tunnels (&(room->entries)); | 43 | init_list_tunnels (&(room->entries)); |
44 | 44 | ||
45 | room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | 45 | room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); |
46 | room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); | ||
46 | 47 | ||
47 | return room; | 48 | return room; |
48 | } | 49 | } |
@@ -50,9 +51,10 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod | |||
50 | static int | 51 | static int |
51 | iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) | 52 | iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) |
52 | { | 53 | { |
53 | struct GNUNET_MESSENGER_Message *message = value; | 54 | struct GNUNET_MESSENGER_RoomMessageEntry *entry = value; |
54 | 55 | ||
55 | destroy_message (message); | 56 | destroy_message (entry->message); |
57 | GNUNET_free(entry); | ||
56 | 58 | ||
57 | return GNUNET_YES; | 59 | return GNUNET_YES; |
58 | } | 60 | } |
@@ -60,8 +62,7 @@ iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *val | |||
60 | void | 62 | void |
61 | destroy_room (struct GNUNET_MESSENGER_Room *room) | 63 | destroy_room (struct GNUNET_MESSENGER_Room *room) |
62 | { | 64 | { |
63 | if (room->members) | 65 | GNUNET_assert(room); |
64 | GNUNET_CONTAINER_multishortmap_destroy (room->members); | ||
65 | 66 | ||
66 | clear_list_tunnels (&(room->entries)); | 67 | clear_list_tunnels (&(room->entries)); |
67 | 68 | ||
@@ -72,6 +73,9 @@ destroy_room (struct GNUNET_MESSENGER_Room *room) | |||
72 | GNUNET_CONTAINER_multihashmap_destroy (room->messages); | 73 | GNUNET_CONTAINER_multihashmap_destroy (room->messages); |
73 | } | 74 | } |
74 | 75 | ||
76 | if (room->members) | ||
77 | GNUNET_CONTAINER_multishortmap_destroy (room->members); | ||
78 | |||
75 | if (room->contact_id) | 79 | if (room->contact_id) |
76 | GNUNET_free(room->contact_id); | 80 | GNUNET_free(room->contact_id); |
77 | 81 | ||
@@ -81,65 +85,111 @@ destroy_room (struct GNUNET_MESSENGER_Room *room) | |||
81 | const struct GNUNET_MESSENGER_Message* | 85 | const struct GNUNET_MESSENGER_Message* |
82 | get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) | 86 | get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) |
83 | { | 87 | { |
84 | return GNUNET_CONTAINER_multihashmap_get (room->messages, hash); | 88 | GNUNET_assert((room) && (hash)); |
89 | |||
90 | struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get ( | ||
91 | room->messages, hash | ||
92 | ); | ||
93 | |||
94 | return (entry? entry->message : NULL); | ||
95 | } | ||
96 | |||
97 | struct GNUNET_MESSENGER_Contact* | ||
98 | get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) | ||
99 | { | ||
100 | GNUNET_assert((room) && (hash)); | ||
101 | |||
102 | struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get ( | ||
103 | room->messages, hash | ||
104 | ); | ||
105 | |||
106 | return (entry? entry->sender : NULL); | ||
85 | } | 107 | } |
86 | 108 | ||
87 | static void | 109 | static void |
88 | handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 110 | handle_join_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
89 | const struct GNUNET_HashCode *hash) | 111 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
90 | { | 112 | { |
91 | struct GNUNET_MESSENGER_Contact *contact = get_handle_contact_by_pubkey (room->handle, &(message->body.join.key)); | 113 | if (!sender) |
114 | { | ||
115 | struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle); | ||
116 | struct GNUNET_HashCode context; | ||
117 | |||
118 | get_context_from_member(&(room->key), &(message->header.sender_id), &context); | ||
119 | |||
120 | sender = get_store_contact(store, &context, &(message->body.join.key)); | ||
121 | } | ||
92 | 122 | ||
93 | if (contact) | 123 | if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) && |
94 | GNUNET_CONTAINER_multishortmap_put (room->members, &(message->header.sender_id), contact, | 124 | (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender, |
95 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | 125 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))) |
126 | increase_contact_rc(sender); | ||
96 | } | 127 | } |
97 | 128 | ||
98 | static void | 129 | static void |
99 | handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 130 | handle_leave_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
100 | const struct GNUNET_HashCode *hash) | 131 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
101 | { | 132 | { |
102 | GNUNET_CONTAINER_multishortmap_remove_all (room->members, &(message->header.sender_id)); | 133 | if ((!sender) || |
134 | (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender))) | ||
135 | return; | ||
136 | |||
137 | struct GNUNET_HashCode context; | ||
138 | get_context_from_member(&(room->key), &(message->header.sender_id), &context); | ||
139 | |||
140 | struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle); | ||
141 | |||
142 | if (GNUNET_YES == decrease_contact_rc(sender)) | ||
143 | remove_store_contact(store, sender, &context); | ||
103 | } | 144 | } |
104 | 145 | ||
105 | static void | 146 | static void |
106 | handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 147 | handle_name_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
107 | const struct GNUNET_HashCode *hash) | 148 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
108 | { | 149 | { |
109 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | 150 | if (!sender) |
110 | &(message->header.sender_id)); | 151 | return; |
111 | 152 | ||
112 | if (contact) | 153 | set_contact_name (sender, message->body.name.name); |
113 | set_contact_name (contact, message->body.name.name); | ||
114 | } | 154 | } |
115 | 155 | ||
116 | static void | 156 | static void |
117 | handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 157 | handle_key_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
118 | const struct GNUNET_HashCode *hash) | 158 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
119 | { | 159 | { |
120 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | 160 | if (!sender) |
121 | &(message->header.sender_id)); | 161 | return; |
162 | |||
163 | struct GNUNET_HashCode context; | ||
164 | get_context_from_member(&(room->key), &(message->header.sender_id), &context); | ||
122 | 165 | ||
123 | if (contact) | 166 | struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle); |
124 | swap_handle_contact_by_pubkey (room->handle, contact, &(message->body.key.key)); | 167 | |
168 | update_store_contact(store, sender, &context, &context, &(message->body.key.key)); | ||
125 | } | 169 | } |
126 | 170 | ||
127 | static void | 171 | static void |
128 | handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 172 | handle_id_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
129 | const struct GNUNET_HashCode *hash) | 173 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
130 | { | 174 | { |
131 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | 175 | if ((!sender) || |
132 | &(message->header.sender_id)); | 176 | (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) || |
177 | (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender, | ||
178 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))) | ||
179 | return; | ||
180 | |||
181 | struct GNUNET_HashCode context, next_context; | ||
182 | get_context_from_member(&(room->key), &(message->header.sender_id), &context); | ||
183 | get_context_from_member(&(room->key), &(message->body.id.id), &next_context); | ||
133 | 184 | ||
134 | if ((contact) && (GNUNET_OK | 185 | struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle); |
135 | == GNUNET_CONTAINER_multishortmap_put (room->members, &(message->body.id.id), contact, | 186 | |
136 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | 187 | update_store_contact(store, sender, &context, &next_context, get_contact_key(sender)); |
137 | GNUNET_CONTAINER_multishortmap_remove (room->members, &(message->header.sender_id), contact); | ||
138 | } | 188 | } |
139 | 189 | ||
140 | static void | 190 | static void |
141 | handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 191 | handle_miss_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
142 | const struct GNUNET_HashCode *hash) | 192 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
143 | { | 193 | { |
144 | if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id))) | 194 | if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id))) |
145 | { | 195 | { |
@@ -150,9 +200,25 @@ handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MES | |||
150 | } | 200 | } |
151 | } | 201 | } |
152 | 202 | ||
203 | static void | ||
204 | handle_delete_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, | ||
205 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
206 | { | ||
207 | struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get ( | ||
208 | room->messages, &(message->body.delete.hash) | ||
209 | ); | ||
210 | |||
211 | if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) && | ||
212 | (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.delete.hash), entry))) | ||
213 | { | ||
214 | destroy_message (entry->message); | ||
215 | GNUNET_free(entry); | ||
216 | } | ||
217 | } | ||
218 | |||
153 | void | 219 | void |
154 | handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 220 | handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, |
155 | const struct GNUNET_HashCode *hash) | 221 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) |
156 | { | 222 | { |
157 | if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash)) | 223 | if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash)) |
158 | return; | 224 | return; |
@@ -160,30 +226,78 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MES | |||
160 | switch (message->header.kind) | 226 | switch (message->header.kind) |
161 | { | 227 | { |
162 | case GNUNET_MESSENGER_KIND_JOIN: | 228 | case GNUNET_MESSENGER_KIND_JOIN: |
163 | handle_join_message (room, message, hash); | 229 | handle_join_message (room, sender, message, hash); |
164 | break; | 230 | break; |
165 | case GNUNET_MESSENGER_KIND_LEAVE: | 231 | case GNUNET_MESSENGER_KIND_LEAVE: |
166 | handle_leave_message (room, message, hash); | 232 | handle_leave_message (room, sender, message, hash); |
167 | break; | 233 | break; |
168 | case GNUNET_MESSENGER_KIND_NAME: | 234 | case GNUNET_MESSENGER_KIND_NAME: |
169 | handle_name_message (room, message, hash); | 235 | handle_name_message (room, sender, message, hash); |
170 | break; | 236 | break; |
171 | case GNUNET_MESSENGER_KIND_KEY: | 237 | case GNUNET_MESSENGER_KIND_KEY: |
172 | handle_key_message (room, message, hash); | 238 | handle_key_message (room, sender, message, hash); |
173 | break; | 239 | break; |
174 | case GNUNET_MESSENGER_KIND_ID: | 240 | case GNUNET_MESSENGER_KIND_ID: |
175 | handle_id_message (room, message, hash); | 241 | handle_id_message (room, sender, message, hash); |
176 | break; | 242 | break; |
177 | case GNUNET_MESSENGER_KIND_MISS: | 243 | case GNUNET_MESSENGER_KIND_MISS: |
178 | handle_miss_message (room, message, hash); | 244 | handle_miss_message (room, sender, message, hash); |
245 | break; | ||
246 | case GNUNET_MESSENGER_KIND_DELETE: | ||
247 | handle_delete_message (room, sender, message, hash); | ||
179 | break; | 248 | break; |
180 | default: | 249 | default: |
181 | break; | 250 | break; |
182 | } | 251 | } |
183 | 252 | ||
184 | struct GNUNET_MESSENGER_Message *clone = copy_message (message); | 253 | struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry); |
254 | |||
255 | if (!entry) | ||
256 | return; | ||
257 | |||
258 | entry->sender = sender; | ||
259 | entry->message = copy_message (message); | ||
185 | 260 | ||
186 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, clone, | 261 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry, |
187 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | 262 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) |
188 | destroy_message (clone); | 263 | { |
264 | destroy_message (entry->message); | ||
265 | GNUNET_free(entry); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | struct GNUNET_MESSENGER_MemberCall | ||
270 | { | ||
271 | struct GNUNET_MESSENGER_Room *room; | ||
272 | GNUNET_MESSENGER_MemberCallback callback; | ||
273 | void *cls; | ||
274 | }; | ||
275 | |||
276 | static int | ||
277 | iterate_local_members (void* cls, const struct GNUNET_ShortHashCode *key, void *value) | ||
278 | { | ||
279 | struct GNUNET_MESSENGER_MemberCall *call = cls; | ||
280 | struct GNUNET_MESSENGER_Contact *contact = value; | ||
281 | |||
282 | return call->callback(call->cls, call->room, contact); | ||
283 | } | ||
284 | |||
285 | int | ||
286 | iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback, | ||
287 | void* cls) | ||
288 | { | ||
289 | GNUNET_assert(room); | ||
290 | |||
291 | if (!callback) | ||
292 | return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL); | ||
293 | |||
294 | struct GNUNET_MESSENGER_MemberCall call; | ||
295 | |||
296 | call.room = room; | ||
297 | call.callback = callback; | ||
298 | call.cls = cls; | ||
299 | |||
300 | GNUNET_assert(callback); | ||
301 | |||
302 | return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call); | ||
189 | } | 303 | } |