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.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c
new file mode 100644
index 000000000..5fedf1a78
--- /dev/null
+++ b/src/messenger/messenger_api_room.c
@@ -0,0 +1,189 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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 src/messenger/messenger_api_room.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_room.h"
27
28#include "messenger_api_handle.h"
29
30struct GNUNET_MESSENGER_Room*
31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
32{
33 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
34
35 room->handle = handle;
36 GNUNET_memcpy(&(room->key), key, sizeof(*key));
37
38 room->opened = GNUNET_NO;
39 room->contact_id = NULL;
40
41 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
42
43 init_list_tunnels (&(room->entries));
44
45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
46
47 return room;
48}
49
50static int
51iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value)
52{
53 struct GNUNET_MESSENGER_Message *message = value;
54
55 destroy_message (message);
56
57 return GNUNET_YES;
58}
59
60void
61destroy_room (struct GNUNET_MESSENGER_Room *room)
62{
63 if (room->members)
64 GNUNET_CONTAINER_multishortmap_destroy (room->members);
65
66 clear_list_tunnels (&(room->entries));
67
68 if (room->messages)
69 {
70 GNUNET_CONTAINER_multihashmap_iterate (room->messages, iterate_destroy_message, NULL);
71
72 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
73 }
74
75 if (room->contact_id)
76 GNUNET_free(room->contact_id);
77
78 GNUNET_free(room);
79}
80
81const struct GNUNET_MESSENGER_Message*
82get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
83{
84 return GNUNET_CONTAINER_multihashmap_get (room->messages, hash);
85}
86
87static void
88handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
89 const struct GNUNET_HashCode *hash)
90{
91 struct GNUNET_MESSENGER_Contact *contact = get_handle_contact_by_pubkey (room->handle, &(message->body.join.key));
92
93 if (contact)
94 GNUNET_CONTAINER_multishortmap_put (room->members, &(message->header.sender_id), contact,
95 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
96}
97
98static void
99handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
100 const struct GNUNET_HashCode *hash)
101{
102 GNUNET_CONTAINER_multishortmap_remove_all (room->members, &(message->header.sender_id));
103}
104
105static void
106handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
107 const struct GNUNET_HashCode *hash)
108{
109 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members,
110 &(message->header.sender_id));
111
112 if (contact)
113 set_contact_name (contact, message->body.name.name);
114}
115
116static void
117handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
118 const struct GNUNET_HashCode *hash)
119{
120 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members,
121 &(message->header.sender_id));
122
123 if (contact)
124 swap_handle_contact_by_pubkey (room->handle, contact, &(message->body.key.key));
125}
126
127static void
128handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
129 const struct GNUNET_HashCode *hash)
130{
131 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members,
132 &(message->header.sender_id));
133
134 if ((contact) && (GNUNET_OK
135 == GNUNET_CONTAINER_multishortmap_put (room->members, &(message->body.id.id), contact,
136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
137 GNUNET_CONTAINER_multishortmap_remove (room->members, &(message->header.sender_id), contact);
138}
139
140static void
141handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
142 const struct GNUNET_HashCode *hash)
143{
144 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
145 {
146 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL);
147
148 if (match)
149 remove_from_list_tunnels (&(room->entries), match);
150 }
151}
152
153void
154handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
155 const struct GNUNET_HashCode *hash)
156{
157 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
158 return;
159
160 switch (message->header.kind)
161 {
162 case GNUNET_MESSENGER_KIND_JOIN:
163 handle_join_message (room, message, hash);
164 break;
165 case GNUNET_MESSENGER_KIND_LEAVE:
166 handle_leave_message (room, message, hash);
167 break;
168 case GNUNET_MESSENGER_KIND_NAME:
169 handle_name_message (room, message, hash);
170 break;
171 case GNUNET_MESSENGER_KIND_KEY:
172 handle_key_message (room, message, hash);
173 break;
174 case GNUNET_MESSENGER_KIND_ID:
175 handle_id_message (room, message, hash);
176 break;
177 case GNUNET_MESSENGER_KIND_MISS:
178 handle_miss_message (room, message, hash);
179 break;
180 default:
181 break;
182 }
183
184 struct GNUNET_MESSENGER_Message *clone = copy_message (message);
185
186 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, clone,
187 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
188 destroy_message (clone);
189}