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 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
26#include "nilorea/n_user.h"
27
34 N_USERLIST* ulist = NULL;
35 __n_assert(max > 0, return NULL);
36 Malloc(ulist, N_USERLIST, 1);
37 __n_assert(ulist, return NULL);
38
39 Malloc(ulist->list, N_USER, (size_t)max);
40 __n_assert(ulist->list, Free(ulist); return NULL);
41
42 ulist->max = max;
43 ulist->highter = -1;
44 for (int it = 0; it < max; it++) {
45 ulist->list[it].state = 0;
46 ulist->list[it].nb_rec_pos = 10;
47 ulist->list[it].only_last_pos = 1;
48 ulist->list[it].id = -1;
49 Malloc(ulist->list[it].last_positions, VECTOR3D, 10);
51 memset(ulist->list[it].position, 0, 3 * sizeof(double));
52 ulist->list[it].netw = NULL;
53 memset(ulist->list[it].name, 0, 1024);
54 ulist->list[it].netw = NULL;
55 }
56
57 init_lock(ulist->user_rwbolt);
58
59 return ulist;
60} /* userlist_new() */
61
70int userlist_set_position_behavior(N_USERLIST* ulist, int id, int nb_rec_pos, int only_last_pos) {
71 __n_assert(ulist, return FALSE);
72 /* nb_rec_pos must be at least 1 */
73 if (nb_rec_pos < 1) return FALSE;
74 /* only_last_pos is a boolean: 0 or 1 */
75 if (only_last_pos < 0 || only_last_pos > 1) return FALSE;
76
77 read_lock(ulist->user_rwbolt);
78 if (id < 0 || id >= ulist->max) {
79 unlock(ulist->user_rwbolt);
80 return FALSE;
81 }
82 /* user slot must be active */
83 if (ulist->list[id].state == 0) {
84 unlock(ulist->user_rwbolt);
85 return FALSE;
86 }
87 unlock(ulist->user_rwbolt);
88
89 write_lock(ulist->user_rwbolt);
90 ulist->list[id].nb_rec_pos = nb_rec_pos;
91 ulist->list[id].only_last_pos = only_last_pos;
92 if (only_last_pos) {
93 if (Realloc(ulist->list[id].last_positions, VECTOR3D, 1) == FALSE) {
94 n_log(LOG_ERR, "could not resize to only_last_pos VECTOR3D");
95 unlock(ulist->user_rwbolt);
96 return FALSE;
97 }
98 } else {
99 if (Realloc(ulist->list[id].last_positions, VECTOR3D, (size_t)nb_rec_pos) == FALSE) {
100 n_log(LOG_ERR, "could not resize to %d VECTOR3D", nb_rec_pos);
101 unlock(ulist->user_rwbolt);
102 return FALSE;
103 }
104 /* nb_rec_pos is already set correctly above; do not overwrite it */
105 }
106 unlock(ulist->user_rwbolt);
107
108 return TRUE;
109} /* userlist_set_position_behavior() */
110
118 __n_assert(ulist, return -1);
119 __n_assert(netw, return -1);
120
121 int it = -1;
122 write_lock(ulist->user_rwbolt);
123 do {
124 it++;
125 } while (it < ulist->max && ulist->list[it].state != 0);
126 if (it < ulist->max) {
127 ulist->list[it].state = 1;
128 ulist->list[it].netw = netw;
129 if (it > ulist->highter)
130 ulist->highter = it;
131 unlock(ulist->user_rwbolt);
132 return it;
133 }
134 unlock(ulist->user_rwbolt);
135 return -1;
136} /* userlist_add_user() */
137
144int userlist_del_user(N_USERLIST* ulist, int id) {
145 __n_assert(ulist, return FALSE);
146 __n_assert(id >= 0, return FALSE);
147
148 write_lock(ulist->user_rwbolt);
149 if (id >= ulist->max) {
150 unlock(ulist->user_rwbolt);
151 return FALSE;
152 }
153 if (ulist->list[id].state == 0) {
154 unlock(ulist->user_rwbolt);
155 return FALSE;
156 }
157 ulist->list[id].state = 0;
158 ulist->list[id].nb_rec_pos = 1;
159 ulist->list[id].only_last_pos = 1;
160 ulist->list[id].id = -1;
161 if (Realloc(ulist->list[id].last_positions, VECTOR3D, 1) == FALSE) {
162 n_log(LOG_ERR, "couldn't resize to 1 element");
163 }
164 list_empty(ulist->list[id].netw_waitlist);
165 memset(ulist->list[id].position, 0, 3 * sizeof(double));
166 ulist->list[id].netw = NULL;
167 memset(ulist->list[id].name, 0, 1024);
168
169 if (id >= ulist->highter) {
170 int it = id;
171 while (it >= 0) {
172 if (ulist->list[it].state == 1) {
173 ulist->highter = it;
174 break;
175 }
176 it--;
177 }
178 if (it < 0) ulist->highter = -1;
179 }
180 unlock(ulist->user_rwbolt);
181 return TRUE;
182} /* userlist_del_user() */
183
192int userlist_add_msg_to_ex(N_USERLIST* ulist, N_STR* msg, int mode, int id) {
193 __n_assert(ulist, return FALSE);
194 __n_assert(msg, return FALSE);
195
196 switch (mode) {
197 case (USERLIST_ALL):
198 read_lock(ulist->user_rwbolt);
199 for (int it = 0; it <= ulist->highter; it++) {
200 if (ulist->list[it].state == 1)
201 netw_add_msg(ulist->list[it].netw, nstrdup(msg));
202 }
203 unlock(ulist->user_rwbolt);
204 break;
205 case (USERLIST_ALL_EXCEPT):
206 __n_assert(id >= 0, return FALSE);
207 read_lock(ulist->user_rwbolt);
208 for (int it = 0; it <= ulist->highter; it++) {
209 if (it == id)
210 continue;
211 if (ulist->list[it].state == 1)
212 netw_add_msg(ulist->list[it].netw, nstrdup(msg));
213 }
214 unlock(ulist->user_rwbolt);
215 break;
216 default:
217 case (USERLIST_ONE):
218 __n_assert(id >= 0, return FALSE);
219
220 read_lock(ulist->user_rwbolt);
221 netw_add_msg(ulist->list[id].netw, msg);
222 unlock(ulist->user_rwbolt);
223 break;
224 }
225 return TRUE;
226} /* userlist_add_msg_to_ex() */
227
235int userlist_add_msg_to(N_USERLIST* ulist, N_STR* msg, int id) {
236 return userlist_add_msg_to_ex(ulist, msg, USERLIST_ONE, id);
237} /* userlist_add_msg_to() */
238
246 return userlist_add_msg_to_ex(ulist, msg, USERLIST_ALL, -1);
247} /* userlist_add_msg_to_all() */
248
257 return userlist_add_msg_to_ex(ulist, msg, USERLIST_ALL_EXCEPT, id);
258} /* userlist_add_msg_to_all_except() */
259
266 __n_assert(ulist && (*ulist), return FALSE);
267
268 write_lock((*ulist)->user_rwbolt);
269 for (int it = 0; it < (*ulist)->max; it++) {
270 Free((*ulist)->list[it].last_positions);
271 list_destroy(&(*ulist)->list[it].netw_waitlist);
272 }
273 Free((*ulist)->list);
274 unlock((*ulist)->user_rwbolt);
275
276 pthread_rwlock_destroy(&(*ulist)->user_rwbolt);
277 Free((*ulist));
278
279 return TRUE;
280} /* userlist_destroy() */
281
289int userlist_user_add_waiting_msg(N_USERLIST* ulist, int id, N_STR* netmsg) {
290 __n_assert(ulist, return FALSE);
291 __n_assert(netmsg, return FALSE);
292 __n_assert(id >= 0, return FALSE);
293
294 int ret = FALSE;
295
296 write_lock(ulist->user_rwbolt);
297 if (id <= ulist->highter) {
298 if (ulist->list[id].state == 1) {
299 ret = list_push(ulist->list[id].netw_waitlist, netmsg, NULL);
300 }
301 }
302 unlock(ulist->user_rwbolt);
303 return ret;
304} /* userlist_user_add_waiting_msg() */
305
313 __n_assert(ulist, return FALSE);
314 __n_assert(id >= 0, return FALSE);
315
316 write_lock(ulist->user_rwbolt);
317 if (id <= ulist->highter) {
318 if (ulist->list[id].state == 1) {
319 list_foreach(node, ulist->list[id].netw_waitlist) {
320 N_STR* netmsg = (N_STR*)node->ptr;
321 netw_add_msg(ulist->list[id].netw, netmsg);
322 }
323 list_empty(ulist->list[id].netw_waitlist);
324 }
325 }
326 unlock(ulist->user_rwbolt);
327 return TRUE;
328} /* userlist_user_send_waiting_msgs() */
329
336 __n_assert(ulist, return FALSE);
337
338 write_lock(ulist->user_rwbolt);
339 for (int id = 0; id <= ulist->highter; id++) {
340 if (ulist->list[id].state == 1) {
341 list_foreach(node, ulist->list[id].netw_waitlist) {
342 N_STR* netmsg = (N_STR*)node->ptr;
343 netw_add_msg(ulist->list[id].netw, netmsg);
344 }
345 list_empty(ulist->list[id].netw_waitlist);
346 }
347 }
348 unlock(ulist->user_rwbolt);
349 return TRUE;
350} /* userlist_send_waiting_msgs() */
static int mode
NETWORK * netw
Network for server mode, accepting incomming.
Definition ex_network.c:38
#define init_lock(__rwlock_mutex)
Macro for initializing a rwlock.
Definition n_common.h:349
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:203
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:278
#define unlock(__rwlock_mutex)
Macro for releasing read/write lock a rwlock mutex.
Definition n_common.h:395
#define write_lock(__rwlock_mutex)
Macro for acquiring a write lock on a rwlock mutex.
Definition n_common.h:381
#define Realloc(__ptr, __struct, __size)
Realloc Handler to get errors.
Definition n_common.h:230
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
#define read_lock(__rwlock_mutex)
Macro for acquiring a read lock on a rwlock mutex.
Definition n_common.h:367
int list_empty(LIST *list)
Empty a LIST list of pointers.
Definition n_list.c:500
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:227
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
Definition n_list.h:88
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:547
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:36
#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:74
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_ERR
error conditions
Definition n_log.h:75
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
Definition n_str.c:708
A box including a string and his lenght.
Definition n_str.h:60
char name[1024]
User Name.
Definition n_user.h:55
VECTOR3D * last_positions
Last nb_rec_pos position messages, for a better dead reckoning / lag simulation.
Definition n_user.h:70
int only_last_pos
1 => keep only_last_position in waitlist , 0 => send all the positions, default: 1
Definition n_user.h:65
int max
Maximum of user inside the list.
Definition n_user.h:85
LIST * netw_waitlist
N_STR *messages waiting to be sent.
Definition n_user.h:75
pthread_rwlock_t user_rwbolt
Mutex for thread safe user management.
Definition n_user.h:90
int state
State of the current user.
Definition n_user.h:61
VECTOR3D position
actual position
Definition n_user.h:72
NETWORK * netw
Associated NETWORK.
Definition n_user.h:58
int highter
Position of the highter user inside the list.
Definition n_user.h:87
int id
Unique world ident.
Definition n_user.h:67
int nb_rec_pos
Number of saved positions , default: 10.
Definition n_user.h:63
N_USER * list
Pointer to the allocated list of user.
Definition n_user.h:82
int userlist_del_user(N_USERLIST *ulist, int id)
delete an user from the list
Definition n_user.c:144
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:235
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:192
#define USERLIST_ONE
flag to target one user in the list
Definition n_user.h:50
int userlist_user_send_waiting_msgs(N_USERLIST *ulist, int id)
send all waiting messages in user 'id' waiting list
Definition n_user.c:312
#define USERLIST_ALL_EXCEPT
flag to target all users in the list except one
Definition n_user.h:48
N_USERLIST * userlist_new(int max)
create a new N_USERLIST user list with 'max' users
Definition n_user.c:33
#define USERLIST_ALL
flag to target all users in the list
Definition n_user.h:46
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:245
int userlist_send_waiting_msgs(N_USERLIST *ulist)
send all waiting messages for each user of the list
Definition n_user.c:335
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:70
int userlist_add_user(N_USERLIST *ulist, NETWORK *netw)
add an user to the list
Definition n_user.c:117
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:256
int userlist_destroy(N_USERLIST **ulist)
destroy and free a N_USERLIST *userlist
Definition n_user.c:265
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:289
USER management cell.
Definition n_user.h:53
USER list.
Definition n_user.h:80
int netw_add_msg(NETWORK *netw, N_STR *msg)
Add a message to send in aimed NETWORK.
Definition n_network.c:2914
Structure of a NETWORK.
Definition n_network.h:258
double VECTOR3D[3]
struct of a point
Definition n_3d.h:58
USERS handling for tiny game apps.