aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/messenger_api_room.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/messenger_api_room.c')
-rw-r--r--src/messenger/messenger_api_room.c214
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 @@
30struct GNUNET_MESSENGER_Room* 30struct GNUNET_MESSENGER_Room*
31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 31create_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
50static int 51static int
51iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) 52iterate_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
60void 62void
61destroy_room (struct GNUNET_MESSENGER_Room *room) 63destroy_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)
81const struct GNUNET_MESSENGER_Message* 85const struct GNUNET_MESSENGER_Message*
82get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) 86get_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
97struct GNUNET_MESSENGER_Contact*
98get_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
87static void 109static void
88handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 110handle_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
98static void 129static void
99handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 130handle_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
105static void 146static void
106handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 147handle_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
116static void 156static void
117handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 157handle_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
127static void 171static void
128handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 172handle_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
140static void 190static void
141handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 191handle_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
203static void
204handle_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
153void 219void
154handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 220handle_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
269struct GNUNET_MESSENGER_MemberCall
270{
271 struct GNUNET_MESSENGER_Room *room;
272 GNUNET_MESSENGER_MemberCallback callback;
273 void *cls;
274};
275
276static int
277iterate_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
285int
286iterate_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}