Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_user.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27#include "nilorea/n_user.h"
28
35 N_USERLIST* ulist = NULL;
36 __n_assert(max > 0, return NULL);
37 Malloc(ulist, N_USERLIST, 1);
38 __n_assert(ulist, return NULL);
39
40 Malloc(ulist->list, N_USER, (size_t)max);
41 __n_assert(ulist->list, Free(ulist); return NULL);
42
43 ulist->max = max;
44 ulist->highter = -1;
45 for (int it = 0; it < max; it++) {
46 ulist->list[it].state = 0;
47 ulist->list[it].nb_rec_pos = 10;
48 ulist->list[it].only_last_pos = 1;
49 ulist->list[it].id = -1;
50 Malloc(ulist->list[it].last_positions, VECTOR3D, 10);
52 memset(ulist->list[it].position, 0, 3 * sizeof(double));
53 ulist->list[it].netw = NULL;
54 memset(ulist->list[it].name, 0, 1024);
55 ulist->list[it].netw = NULL;
56 }
57
58 init_lock(ulist->user_rwbolt);
59
60 return ulist;
61} /* userlist_new() */
62
71int userlist_set_position_behavior(N_USERLIST* ulist, int id, int nb_rec_pos, int only_last_pos) {
72 __n_assert(ulist, return FALSE);
73 /* nb_rec_pos must be at least 1 */
74 if (nb_rec_pos < 1) return FALSE;
75 /* only_last_pos is a boolean: 0 or 1 */
76 if (only_last_pos < 0 || only_last_pos > 1) return FALSE;
77
78 read_lock(ulist->user_rwbolt);
79 if (id < 0 || id >= ulist->max) {
80 unlock(ulist->user_rwbolt);
81 return FALSE;
82 }
83 /* user slot must be active */
84 if (ulist->list[id].state == 0) {
85 unlock(ulist->user_rwbolt);
86 return FALSE;
87 }
88 unlock(ulist->user_rwbolt);
89
90 write_lock(ulist->user_rwbolt);
91 ulist->list[id].nb_rec_pos = nb_rec_pos;
92 ulist->list[id].only_last_pos = only_last_pos;
93 if (only_last_pos) {
94 if (Realloc(ulist->list[id].last_positions, VECTOR3D, 1) == FALSE) {
95 n_log(LOG_ERR, "could not resize to only_last_pos VECTOR3D");
96 unlock(ulist->user_rwbolt);
97 return FALSE;
98 }
99 } else {
100 if (Realloc(ulist->list[id].last_positions, VECTOR3D, (size_t)nb_rec_pos) == FALSE) {
101 n_log(LOG_ERR, "could not resize to %d VECTOR3D", nb_rec_pos);
102 unlock(ulist->user_rwbolt);
103 return FALSE;
104 }
105 /* nb_rec_pos is already set correctly above; do not overwrite it */
106 }
107 unlock(ulist->user_rwbolt);
108
109 return TRUE;
110} /* userlist_set_position_behavior() */
111
119 __n_assert(ulist, return -1);
120 __n_assert(netw, return -1);
121
122 int it = -1;
123 write_lock(ulist->user_rwbolt);
124 do {
125 it++;
126 } while (it < ulist->max && ulist->list[it].state != 0);
127 if (it < ulist->max) {
128 ulist->list[it].state = 1;
129 ulist->list[it].netw = netw;
130 if (it > ulist->highter)
131 ulist->highter = it;
132 unlock(ulist->user_rwbolt);
133 return it;
134 }
135 unlock(ulist->user_rwbolt);
136 return -1;
137} /* userlist_add_user() */
138
145int userlist_del_user(N_USERLIST* ulist, int id) {
146 __n_assert(ulist, return FALSE);
147 __n_assert(id >= 0, return FALSE);
148
149 write_lock(ulist->user_rwbolt);
150 if (id >= ulist->max) {
151 unlock(ulist->user_rwbolt);
152 return FALSE;
153 }
154 if (ulist->list[id].state == 0) {
155 unlock(ulist->user_rwbolt);
156 return FALSE;
157 }
158 ulist->list[id].state = 0;
159 ulist->list[id].nb_rec_pos = 1;
160 ulist->list[id].only_last_pos = 1;
161 ulist->list[id].id = -1;
162 if (Realloc(ulist->list[id].last_positions, VECTOR3D, 1) == FALSE) {
163 n_log(LOG_ERR, "couldn't resize to 1 element");
164 }
165 list_empty(ulist->list[id].netw_waitlist);
166 memset(ulist->list[id].position, 0, 3 * sizeof(double));
167 ulist->list[id].netw = NULL;
168 memset(ulist->list[id].name, 0, 1024);
169
170 if (id >= ulist->highter) {
171 int it = id;
172 while (it >= 0) {
173 if (ulist->list[it].state == 1) {
174 ulist->highter = it;
175 break;
176 }
177 it--;
178 }
179 if (it < 0) ulist->highter = -1;
180 }
181 unlock(ulist->user_rwbolt);
182 return TRUE;
183} /* userlist_del_user() */
184
193int userlist_add_msg_to_ex(N_USERLIST* ulist, N_STR* msg, int mode, int id) {
194 __n_assert(ulist, return FALSE);
195 __n_assert(msg, return FALSE);
196
197 switch (mode) {
198 case (USERLIST_ALL):
199 read_lock(ulist->user_rwbolt);
200 for (int it = 0; it <= ulist->highter; it++) {
201 if (ulist->list[it].state == 1)
202 netw_add_msg(ulist->list[it].netw, nstrdup(msg));
203 }
204 unlock(ulist->user_rwbolt);
205 break;
206 case (USERLIST_ALL_EXCEPT):
207 __n_assert(id >= 0, return FALSE);
208 read_lock(ulist->user_rwbolt);
209 for (int it = 0; it <= ulist->highter; it++) {
210 if (it == id)
211 continue;
212 if (ulist->list[it].state == 1)
213 netw_add_msg(ulist->list[it].netw, nstrdup(msg));
214 }
215 unlock(ulist->user_rwbolt);
216 break;
217 default:
218 case (USERLIST_ONE):
219 __n_assert(id >= 0, return FALSE);
220
221 read_lock(ulist->user_rwbolt);
222 netw_add_msg(ulist->list[id].netw, msg);
223 unlock(ulist->user_rwbolt);
224 break;
225 }
226 return TRUE;
227} /* userlist_add_msg_to_ex() */
228
236int userlist_add_msg_to(N_USERLIST* ulist, N_STR* msg, int id) {
237 return userlist_add_msg_to_ex(ulist, msg, USERLIST_ONE, id);
238} /* userlist_add_msg_to() */
239
247 return userlist_add_msg_to_ex(ulist, msg, USERLIST_ALL, -1);
248} /* userlist_add_msg_to_all() */
249
258 return userlist_add_msg_to_ex(ulist, msg, USERLIST_ALL_EXCEPT, id);
259} /* userlist_add_msg_to_all_except() */
260
267 __n_assert(ulist && (*ulist), return FALSE);
268
269 write_lock((*ulist)->user_rwbolt);
270 for (int it = 0; it < (*ulist)->max; it++) {
271 Free((*ulist)->list[it].last_positions);
272 list_destroy(&(*ulist)->list[it].netw_waitlist);
273 }
274 Free((*ulist)->list);
275 unlock((*ulist)->user_rwbolt);
276
277 pthread_rwlock_destroy(&(*ulist)->user_rwbolt);
278 Free((*ulist));
279
280 return TRUE;
281} /* userlist_destroy() */
282
290int userlist_user_add_waiting_msg(N_USERLIST* ulist, int id, N_STR* netmsg) {
291 __n_assert(ulist, return FALSE);
292 __n_assert(netmsg, return FALSE);
293 __n_assert(id >= 0, return FALSE);
294
295 int ret = FALSE;
296
297 write_lock(ulist->user_rwbolt);
298 if (id <= ulist->highter) {
299 if (ulist->list[id].state == 1) {
300 ret = list_push(ulist->list[id].netw_waitlist, netmsg, NULL);
301 }
302 }
303 unlock(ulist->user_rwbolt);
304 return ret;
305} /* userlist_user_add_waiting_msg() */
306
314 __n_assert(ulist, return FALSE);
315 __n_assert(id >= 0, return FALSE);
316
317 write_lock(ulist->user_rwbolt);
318 if (id <= ulist->highter) {
319 if (ulist->list[id].state == 1) {
320 list_foreach(node, ulist->list[id].netw_waitlist) {
321 N_STR* netmsg = (N_STR*)node->ptr;
322 netw_add_msg(ulist->list[id].netw, netmsg);
323 }
324 list_empty(ulist->list[id].netw_waitlist);
325 }
326 }
327 unlock(ulist->user_rwbolt);
328 return TRUE;
329} /* userlist_user_send_waiting_msgs() */
330
337 __n_assert(ulist, return FALSE);
338
339 write_lock(ulist->user_rwbolt);
340 for (int id = 0; id <= ulist->highter; id++) {
341 if (ulist->list[id].state == 1) {
342 list_foreach(node, ulist->list[id].netw_waitlist) {
343 N_STR* netmsg = (N_STR*)node->ptr;
344 netw_add_msg(ulist->list[id].netw, netmsg);
345 }
346 list_empty(ulist->list[id].netw_waitlist);
347 }
348 }
349 unlock(ulist->user_rwbolt);
350 return TRUE;
351} /* userlist_send_waiting_msgs() */
static int mode
NETWORK * netw
Network for server mode, accepting incomming.
Definition ex_network.c:39
#define init_lock(__rwlock_mutex)
Macro for initializing a rwlock.
Definition n_common.h:350
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:204
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define unlock(__rwlock_mutex)
Macro for releasing read/write lock a rwlock mutex.
Definition n_common.h:396
#define write_lock(__rwlock_mutex)
Macro for acquiring a write lock on a rwlock mutex.
Definition n_common.h:382
#define Realloc(__ptr, __struct, __size)
Realloc Handler to get errors.
Definition n_common.h:231
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:263
#define read_lock(__rwlock_mutex)
Macro for acquiring a read lock on a rwlock mutex.
Definition n_common.h:368
int list_empty(LIST *list)
Empty a LIST list of pointers.
Definition n_list.c:501
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:228
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
Definition n_list.h:89
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:548
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:37
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Definition n_list.h:75
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_ERR
error conditions
Definition n_log.h:76
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
Definition n_str.c:716
A box including a string and his lenght.
Definition n_str.h:61
char name[1024]
User Name.
Definition n_user.h:56
VECTOR3D * last_positions
Last nb_rec_pos position messages, for a better dead reckoning / lag simulation.
Definition n_user.h:71
int only_last_pos
1 => keep only_last_position in waitlist , 0 => send all the positions, default: 1
Definition n_user.h:66
int max
Maximum of user inside the list.
Definition n_user.h:86
LIST * netw_waitlist
N_STR *messages waiting to be sent.
Definition n_user.h:76
pthread_rwlock_t user_rwbolt
Mutex for thread safe user management.
Definition n_user.h:91
int state
State of the current user.
Definition n_user.h:62
VECTOR3D position
actual position
Definition n_user.h:73
NETWORK * netw
Associated NETWORK.
Definition n_user.h:59
int highter
Position of the highter user inside the list.
Definition n_user.h:88
int id
Unique world ident.
Definition n_user.h:68
int nb_rec_pos
Number of saved positions , default: 10.
Definition n_user.h:64
N_USER * list
Pointer to the allocated list of user.
Definition n_user.h:83
int userlist_del_user(N_USERLIST *ulist, int id)
delete an user from the list
Definition n_user.c:145
int userlist_add_msg_to(N_USERLIST *ulist, N_STR *msg, int id)
add a N_STR *message to user list (USERLIST_ONE)
Definition n_user.c:236
int userlist_add_msg_to_ex(N_USERLIST *ulist, N_STR *msg, int mode, int id)
add a N_STR *message to user list
Definition n_user.c:193
#define USERLIST_ONE
flag to target one user in the list
Definition n_user.h:51
int userlist_user_send_waiting_msgs(N_USERLIST *ulist, int id)
send all waiting messages in user 'id' waiting list
Definition n_user.c:313
#define USERLIST_ALL_EXCEPT
flag to target all users in the list except one
Definition n_user.h:49
N_USERLIST * userlist_new(int max)
create a new N_USERLIST user list with 'max' users
Definition n_user.c:34
#define USERLIST_ALL
flag to target all users in the list
Definition n_user.h:47
int userlist_add_msg_to_all(N_USERLIST *ulist, N_STR *msg)
add a N_STR *message to user list (USERLIST_ALL)
Definition n_user.c:246
int userlist_send_waiting_msgs(N_USERLIST *ulist)
send all waiting messages for each user of the list
Definition n_user.c:336
int userlist_set_position_behavior(N_USERLIST *ulist, int id, int nb_rec_pos, int only_last_pos)
set the position parameters for trajectory processing for user 'id'
Definition n_user.c:71
int userlist_add_user(N_USERLIST *ulist, NETWORK *netw)
add an user to the list
Definition n_user.c:118
int userlist_add_msg_to_all_except(N_USERLIST *ulist, N_STR *msg, int id)
add a N_STR *message to user list except user 'id' (USERLIST_ALL_EXCEPT)
Definition n_user.c:257
int userlist_destroy(N_USERLIST **ulist)
destroy and free a N_USERLIST *userlist
Definition n_user.c:266
int userlist_user_add_waiting_msg(N_USERLIST *ulist, int id, N_STR *netmsg)
add a network message to specified user 'id'
Definition n_user.c:290
USER management cell.
Definition n_user.h:54
USER list.
Definition n_user.h:81
int netw_add_msg(NETWORK *netw, N_STR *msg)
Add a message to send in aimed NETWORK.
Definition n_network.c:3569
Structure of a NETWORK.
Definition n_network.h:309
double VECTOR3D[3]
struct of a point
Definition n_3d.h:59
USERS handling for tiny game apps.