GNUnet  0.17.6
messenger_api_room.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2020--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  */
26 #include "messenger_api_room.h"
27 
28 #include "messenger_api_handle.h"
29 
32  const struct GNUNET_HashCode *key)
33 {
34  GNUNET_assert((handle) && (key));
35 
37 
38  room->handle = handle;
39  GNUNET_memcpy(&(room->key), key, sizeof(*key));
40 
41  room->opened = GNUNET_NO;
42  room->contact_id = NULL;
43 
44  init_list_tunnels (&(room->entries));
45 
48 
49  return room;
50 }
51 
52 static int
54  const struct GNUNET_HashCode *key,
55  void *value)
56 {
58 
59  destroy_message (entry->message);
60  GNUNET_free(entry);
61 
62  return GNUNET_YES;
63 }
64 
65 void
67 {
68  GNUNET_assert(room);
69 
70  clear_list_tunnels (&(room->entries));
71 
72  if (room->messages)
73  {
75 
77  }
78 
79  if (room->members)
81 
82  if (room->contact_id)
83  GNUNET_free(room->contact_id);
84 
85  GNUNET_free(room);
86 }
87 
88 const struct GNUNET_MESSENGER_Message*
90  const struct GNUNET_HashCode *hash)
91 {
92  GNUNET_assert((room) && (hash));
93 
95  room->messages, hash
96  );
97 
98  return (entry? entry->message : NULL);
99 }
100 
103  const struct GNUNET_HashCode *hash)
104 {
105  GNUNET_assert((room) && (hash));
106 
108  room->messages, hash
109  );
110 
111  return (entry? entry->sender : NULL);
112 }
113 
114 static struct GNUNET_MESSENGER_Contact*
116  struct GNUNET_MESSENGER_Contact *sender,
117  const struct GNUNET_MESSENGER_Message *message,
118  const struct GNUNET_HashCode *hash)
119 {
120  if (!sender)
121  {
123  struct GNUNET_HashCode context;
124 
125  get_context_from_member(&(room->key), &(message->header.sender_id), &context);
126 
127  sender = get_store_contact(store, &context, &(message->body.join.key));
128  }
129 
133  increase_contact_rc(sender);
134 
135  return sender;
136 }
137 
138 static void
140  struct GNUNET_MESSENGER_Contact *sender,
141  const struct GNUNET_MESSENGER_Message *message,
142  const struct GNUNET_HashCode *hash)
143 {
144  if ((!sender) ||
146  return;
147 
148  struct GNUNET_HashCode context;
149  get_context_from_member(&(room->key), &(message->header.sender_id), &context);
150 
151  if (GNUNET_YES == decrease_contact_rc(sender))
152  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room with you anymore!\n");
153 }
154 
155 static void
157  struct GNUNET_MESSENGER_Contact *sender,
158  const struct GNUNET_MESSENGER_Message *message,
159  const struct GNUNET_HashCode *hash)
160 {
161  if (!sender)
162  return;
163 
164  set_contact_name (sender, message->body.name.name);
165 }
166 
167 static void
169  struct GNUNET_MESSENGER_Contact *sender,
170  const struct GNUNET_MESSENGER_Message *message,
171  const struct GNUNET_HashCode *hash)
172 {
173  if (!sender)
174  return;
175 
176  struct GNUNET_HashCode context;
177  get_context_from_member(&(room->key), &(message->header.sender_id), &context);
178 
180 
181  update_store_contact(store, sender, &context, &context, &(message->body.key.key));
182 }
183 
184 static void
186  struct GNUNET_MESSENGER_Contact *sender,
187  const struct GNUNET_MESSENGER_Message *message,
188  const struct GNUNET_HashCode *hash)
189 {
190  if ((!sender) ||
191  (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
192  (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
194  return;
195 
196  struct GNUNET_HashCode context, next_context;
197  get_context_from_member(&(room->key), &(message->header.sender_id), &context);
198  get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
199 
201 
202  update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
203 }
204 
205 static void
207  struct GNUNET_MESSENGER_Contact *sender,
208  const struct GNUNET_MESSENGER_Message *message,
209  const struct GNUNET_HashCode *hash)
210 {
211  if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
212  {
213  struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL);
214 
215  if (match)
216  remove_from_list_tunnels (&(room->entries), match);
217  }
218 }
219 
220 static void
222  struct GNUNET_MESSENGER_Contact *sender,
223  const struct GNUNET_MESSENGER_Message *message,
224  const struct GNUNET_HashCode *hash)
225 {
227  room->messages, &(message->body.deletion.hash)
228  );
229 
230  if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
232  {
233  destroy_message (entry->message);
234  GNUNET_free(entry);
235  }
236 }
237 
240  struct GNUNET_MESSENGER_Contact *sender,
241  const struct GNUNET_MESSENGER_Message *message,
242  const struct GNUNET_HashCode *hash)
243 {
245  return sender;
246 
247  switch (message->header.kind)
248  {
250  sender = handle_join_message (room, sender, message, hash);
251  break;
253  handle_leave_message (room, sender, message, hash);
254  break;
256  handle_name_message (room, sender, message, hash);
257  break;
259  handle_key_message (room, sender, message, hash);
260  break;
262  handle_id_message (room, sender, message, hash);
263  break;
265  handle_miss_message (room, sender, message, hash);
266  break;
268  handle_delete_message (room, sender, message, hash);
269  break;
270  default:
271  break;
272  }
273 
275 
276  if (!entry)
277  return sender;
278 
279  entry->sender = sender;
280  entry->message = copy_message (message);
281 
282  if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
284  {
285  destroy_message (entry->message);
286  GNUNET_free(entry);
287  }
288 
289  return sender;
290 }
291 
293 {
296  void *cls;
297 };
298 
299 static int
301  const struct GNUNET_ShortHashCode *key,
302  void *value)
303 {
305  struct GNUNET_MESSENGER_Contact *contact = value;
306 
307  return call->callback(call->cls, call->room, contact);
308 }
309 
310 int
313  void* cls)
314 {
315  GNUNET_assert(room);
316 
317  if (!callback)
318  return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
319 
321 
322  call.room = room;
323  call.callback = callback;
324  call.cls = cls;
325 
327 
329 }
330 
332 {
334  int result;
335 };
336 
337 static int
339  const struct GNUNET_ShortHashCode *key,
340  void *value)
341 {
342  struct GNUNET_MESSENGER_MemberFind *find = cls;
343  struct GNUNET_MESSENGER_Contact *contact = value;
344 
345  if (contact == find->contact)
346  {
347  find->result = GNUNET_YES;
348  return GNUNET_NO;
349  }
350 
351  return GNUNET_YES;
352 }
353 
354 int
356  const struct GNUNET_MESSENGER_Contact *contact)
357 {
358  GNUNET_assert(room);
359 
360  struct GNUNET_MESSENGER_MemberFind find;
361 
362  find.contact = contact;
363  find.result = GNUNET_NO;
364 
366 
367  return find.result;
368 }
static struct GNUNET_CONVERSATION_Call * call
Call handle (for active outgoing call).
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
static pa_context * context
Pulseaudio context.
static char * value
Value of the record to add/remove.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multishortmap_iterate(struct GNUNET_CONTAINER_MultiShortmap *map, GNUNET_CONTAINER_ShortmapIterator it, void *it_cls)
Iterate over all entries in the map.
int GNUNET_CONTAINER_multishortmap_contains_value(const struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Check if the map contains the given value under the given key.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
int(* GNUNET_MESSENGER_MemberCallback)(void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact)
Method called for each member in a room during iteration.
@ GNUNET_MESSENGER_KIND_MISS
The miss kind.
@ GNUNET_MESSENGER_KIND_NAME
The name kind.
@ GNUNET_MESSENGER_KIND_LEAVE
The leave kind.
@ GNUNET_MESSENGER_KIND_KEY
The key kind.
@ GNUNET_MESSENGER_KIND_JOIN
The join kind.
@ GNUNET_MESSENGER_KIND_DELETE
The delete kind.
@ GNUNET_MESSENGER_KIND_ID
The id kind.
void set_contact_name(struct GNUNET_MESSENGER_Contact *contact, const char *name)
Changes the current name of a given contact by copying it from the parameter name.
int decrease_contact_rc(struct GNUNET_MESSENGER_Contact *contact)
Decreases the reference counter if possible (can not underflow!) of a given contact and returns GNUNE...
void increase_contact_rc(struct GNUNET_MESSENGER_Contact *contact)
Increases the reference counter of a given contact which is zero as default.
void get_context_from_member(const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id, struct GNUNET_HashCode *context)
Calculates the context hash of a member in a room and returns it.
const struct GNUNET_IDENTITY_PublicKey * get_contact_key(const struct GNUNET_MESSENGER_Contact *contact)
Returns the public key of a given contact.
struct GNUNET_MESSENGER_Contact * get_store_contact(struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context, const struct GNUNET_IDENTITY_PublicKey *pubkey)
Returns a contact using a specific public key.
void update_store_contact(struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact *contact, const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context, const struct GNUNET_IDENTITY_PublicKey *pubkey)
Moves a contact from the store to another location matching a given public key and member context.
struct GNUNET_MESSENGER_Contact * get_handle_contact(struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
Returns the contact of a given handle in a room identified by a given key.
struct GNUNET_MESSENGER_ContactStore * get_handle_contact_store(struct GNUNET_MESSENGER_Handle *handle)
Returns the used contact store of a given handle.
messenger api: client implementation of GNUnet MESSENGER service
void init_list_tunnels(struct GNUNET_MESSENGER_ListTunnels *tunnels)
Initializes list of tunnels peer identities as empty list.
struct GNUNET_MESSENGER_ListTunnel * remove_from_list_tunnels(struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element)
Removes a specific element from the list of tunnels peer identities and returns the next element in t...
struct GNUNET_MESSENGER_ListTunnel * find_list_tunnels(struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index)
Searches linearly through the list of tunnels peer identities for matching a specific peer identity a...
void clear_list_tunnels(struct GNUNET_MESSENGER_ListTunnels *tunnels)
Clears the list of tunnels peer identities.
struct GNUNET_MESSENGER_Message * copy_message(const struct GNUNET_MESSENGER_Message *message)
Creates and allocates a copy of a given message.
void destroy_message(struct GNUNET_MESSENGER_Message *message)
Destroys a message and frees its memory fully.
static struct GNUNET_MESSENGER_Contact * handle_join_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
static int iterate_local_members(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
static void handle_key_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
static void handle_delete_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
static int iterate_find_member(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
static void handle_leave_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
struct GNUNET_MESSENGER_Contact * handle_room_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
Handles a message with a given hash in a room for the client API to update members and its informatio...
struct GNUNET_MESSENGER_Contact * get_room_sender(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Returns a messages sender locally stored from a map for a given hash in a room.
const struct GNUNET_MESSENGER_Message * get_room_message(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Returns a message locally stored from a map for a given hash in a room.
static int iterate_destroy_message(void *cls, const struct GNUNET_HashCode *key, void *value)
int find_room_member(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact)
Checks through all members of a given room if a specific contact is found and returns a result depend...
struct GNUNET_MESSENGER_Room * create_room(struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
Creates and allocates a new room for a handle with a given key for the client API.
static void handle_id_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
static void handle_name_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
int iterate_room_members(struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback, void *cls)
Iterates through all members of a given room to forward each of them to a selected callback with a cu...
void destroy_room(struct GNUNET_MESSENGER_Room *room)
Destroys a room and frees its memory fully from the client API.
static void handle_miss_message(struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
messenger api: client implementation of GNUnet MESSENGER service
A 512-bit hashcode.
GNUNET_MESSENGER_MemberCallback callback
struct GNUNET_MESSENGER_Room * room
const struct GNUNET_MESSENGER_Contact * contact
struct GNUNET_MESSENGER_MessageId id
struct GNUNET_MESSENGER_MessageName name
struct GNUNET_MESSENGER_MessageKey key
struct GNUNET_MESSENGER_MessageMiss miss
struct GNUNET_MESSENGER_MessageJoin join
struct GNUNET_MESSENGER_MessageDelete deletion
struct GNUNET_HashCode hash
The hash of the message to delete.
enum GNUNET_MESSENGER_MessageKind kind
The kind of the message.
struct GNUNET_ShortHashCode sender_id
The senders id inside of the room the message was sent in.
struct GNUNET_ShortHashCode id
The new id which will replace the senders id in a room.
struct GNUNET_IDENTITY_PublicKey key
The senders public key to verify its signatures.
struct GNUNET_IDENTITY_PublicKey key
The new public key which replaces the current senders public key.
struct GNUNET_PeerIdentity peer
The peer identity of a disconnected door to a room.
char * name
The new name which replaces the current senders name.
struct GNUNET_MESSENGER_MessageHeader header
Header.
struct GNUNET_MESSENGER_MessageBody body
Body.
struct GNUNET_MESSENGER_Message * message
struct GNUNET_MESSENGER_Contact * sender
struct GNUNET_MESSENGER_Handle * handle
struct GNUNET_CONTAINER_MultiShortmap * members
struct GNUNET_CONTAINER_MultiHashMap * messages
struct GNUNET_MESSENGER_ListTunnels entries
struct GNUNET_ShortHashCode * contact_id
struct GNUNET_HashCode key
A 256-bit hashcode.