44
44
45
45
/** @internal
46
46
* Holds a pointer to the first element of the list
47
- */
48
- static t_client * firstclient = NULL ;
47
+ */
48
+ static t_client * firstclient = NULL ;
49
+
50
+ /** @internal
51
+ * Client ID
52
+ */
53
+ static volatile unsigned long long client_id = 1 ;
54
+
55
+ /**
56
+ * Mutex to protect client_id and guarantee uniqueness.
57
+ */
58
+ static pthread_mutex_t client_id_mutex = PTHREAD_MUTEX_INITIALIZER ;
49
59
50
60
/** Global mutex to protect access to the client list */
51
61
pthread_mutex_t client_list_mutex = PTHREAD_MUTEX_INITIALIZER ;
@@ -82,66 +92,135 @@ client_list_init(void)
82
92
* @param Pointer to t_client object.
83
93
*/
84
94
void
85
- client_list_insert_client (t_client * client )
95
+ client_list_insert_client (t_client * client )
86
96
{
87
97
t_client * prev_head ;
88
98
99
+ pthread_mutex_lock (& client_id_mutex );
100
+ client -> id = client_id ++ ;
101
+ pthread_mutex_unlock (& client_id_mutex );
89
102
prev_head = firstclient ;
90
103
client -> next = prev_head ;
91
104
firstclient = client ;
92
105
}
93
106
94
-
95
107
/** Based on the parameters it receives, this function creates a new entry
96
108
* in the connections list. All the memory allocation is done here.
109
+ * Client is inserted at the head of the list.
97
110
* @param ip IP address
98
111
* @param mac MAC address
99
112
* @param token Token
100
113
* @return Pointer to the client we just created
101
114
*/
102
- t_client *
103
- client_list_append (const char * ip , const char * mac , const char * token )
115
+ t_client *
116
+ client_list_add (const char * ip , const char * mac , const char * token )
104
117
{
105
- t_client * curclient , * prevclient ;
106
-
107
- prevclient = NULL ;
108
- curclient = firstclient ;
109
-
110
- while (curclient != NULL ) {
111
- prevclient = curclient ;
112
- curclient = curclient -> next ;
113
- }
118
+ t_client * curclient ;
114
119
115
120
curclient = client_get_new ();
116
121
117
122
curclient -> ip = safe_strdup (ip );
118
123
curclient -> mac = safe_strdup (mac );
119
124
curclient -> token = safe_strdup (token );
120
- curclient -> counters .incoming = curclient -> counters .incoming_history = curclient -> counters .outgoing = curclient -> counters .outgoing_history = 0 ;
125
+ curclient -> counters .incoming = curclient -> counters .incoming_history = curclient -> counters .outgoing =
126
+ curclient -> counters .outgoing_history = 0 ;
121
127
curclient -> counters .last_updated = time (NULL );
122
128
123
- if (prevclient == NULL ) {
124
- firstclient = curclient ;
125
- } else {
126
- prevclient -> next = curclient ;
127
- }
129
+ client_list_insert_client (curclient );
128
130
129
- debug (LOG_INFO , "Added a new client to linked list: IP: %s Token: %s" ,
130
- ip , token );
131
+ debug (LOG_INFO , "Added a new client to linked list: IP: %s Token: %s" , ip , token );
131
132
132
133
return curclient ;
133
134
}
134
135
136
+ /** Duplicate the whole client list to process in a thread safe way
137
+ * MUTEX MUST BE HELD.
138
+ * @param dest pointer TO A POINTER to a t_client (i.e.: t_client **ptr)
139
+ * @return int Number of clients copied
140
+ */
141
+ int
142
+ client_list_dup (t_client * * dest )
143
+ {
144
+ t_client * new , * cur , * top , * prev ;
145
+ int copied = 0 ;
146
+
147
+ cur = firstclient ;
148
+ new = top = prev = NULL ;
149
+
150
+ if (NULL == cur ) {
151
+ * dest = new ; /* NULL */
152
+ return copied ;
153
+ }
154
+
155
+ while (NULL != cur ) {
156
+ new = client_dup (cur );
157
+ if (NULL == top ) {
158
+ /* first item */
159
+ top = new ;
160
+ } else {
161
+ prev -> next = new ;
162
+ }
163
+ prev = new ;
164
+ copied ++ ;
165
+ cur = cur -> next ;
166
+ }
167
+
168
+ * dest = top ;
169
+ return copied ;
170
+ }
171
+
172
+ /** Create a duplicate of a client.
173
+ * @param src Original client
174
+ * @return duplicate client object with next == NULL
175
+ */
176
+ t_client *
177
+ client_dup (const t_client * src )
178
+ {
179
+ t_client * new = client_get_new ();
180
+
181
+ new -> id = src -> id ;
182
+ new -> ip = safe_strdup (src -> ip );
183
+ new -> mac = safe_strdup (src -> mac );
184
+ new -> token = safe_strdup (src -> token );
185
+ new -> counters .incoming = src -> counters .incoming ;
186
+ new -> counters .incoming_history = src -> counters .incoming_history ;
187
+ new -> counters .outgoing = src -> counters .outgoing ;
188
+ new -> counters .outgoing_history = src -> counters .outgoing_history ;
189
+ new -> counters .last_updated = src -> counters .last_updated ;
190
+ new -> next = NULL ;
191
+
192
+ return new ;
193
+ }
194
+
195
+ /** Find a client in the list from a client struct, matching operates by id.
196
+ * This is useful from a copy of client to find the original.
197
+ * @param client Client to find
198
+ * @return pointer to the client in the list.
199
+ */
200
+ t_client *
201
+ client_list_find_by_client (t_client * client )
202
+ {
203
+ t_client * c = firstclient ;
204
+
205
+ while (NULL != c ) {
206
+ if (c -> id == client -> id ) {
207
+ return c ;
208
+ }
209
+ c = c -> next ;
210
+ }
211
+ return NULL ;
212
+ }
213
+
135
214
/** Finds a client by its IP and MAC, returns NULL if the client could not
136
215
* be found
137
216
* @param ip IP we are looking for in the linked list
138
217
* @param mac MAC we are looking for in the linked list
139
218
* @return Pointer to the client, or NULL if not found
140
219
*/
141
- t_client *
220
+ t_client *
142
221
client_list_find (const char * ip , const char * mac )
143
222
{
144
- t_client * ptr ;
223
+ t_client * ptr ;
145
224
146
225
ptr = firstclient ;
147
226
while (NULL != ptr ) {
@@ -159,10 +238,10 @@ client_list_find(const char *ip, const char *mac)
159
238
* @param ip IP we are looking for in the linked list
160
239
* @return Pointer to the client, or NULL if not found
161
240
*/
162
- t_client *
241
+ t_client *
163
242
client_list_find_by_ip (const char * ip )
164
243
{
165
- t_client * ptr ;
244
+ t_client * ptr ;
166
245
167
246
ptr = firstclient ;
168
247
while (NULL != ptr ) {
@@ -180,10 +259,10 @@ client_list_find_by_ip(const char *ip)
180
259
* @param mac Mac we are looking for in the linked list
181
260
* @return Pointer to the client, or NULL if not found
182
261
*/
183
- t_client *
262
+ t_client *
184
263
client_list_find_by_mac (const char * mac )
185
264
{
186
- t_client * ptr ;
265
+ t_client * ptr ;
187
266
188
267
ptr = firstclient ;
189
268
while (NULL != ptr ) {
@@ -202,7 +281,7 @@ client_list_find_by_mac(const char *mac)
202
281
t_client *
203
282
client_list_find_by_token (const char * token )
204
283
{
205
- t_client * ptr ;
284
+ t_client * ptr ;
206
285
207
286
ptr = firstclient ;
208
287
while (NULL != ptr ) {
@@ -214,6 +293,22 @@ client_list_find_by_token(const char *token)
214
293
return NULL ;
215
294
}
216
295
296
+ /** Destroy the client list. Including all free...
297
+ * DOES NOT UPDATE firstclient or anything else.
298
+ * @param list List to destroy (first item)
299
+ */
300
+ void
301
+ client_list_destroy (t_client * list )
302
+ {
303
+ t_client * next ;
304
+
305
+ while (NULL != list ) {
306
+ next = list -> next ;
307
+ client_free_node (list );
308
+ list = next ;
309
+ }
310
+ }
311
+
217
312
/** @internal
218
313
* @brief Frees the memory used by a t_client structure
219
314
* This function frees the memory used by the t_client structure in the
@@ -258,7 +353,7 @@ client_list_delete(t_client * client)
258
353
void
259
354
client_list_remove (t_client * client )
260
355
{
261
- t_client * ptr ;
356
+ t_client * ptr ;
262
357
263
358
ptr = firstclient ;
264
359
0 commit comments