Mercurial > hg > freeDiameter
comparison libfdproto/sessions.c @ 1369:f1bbcab403a6
Clean up trailing whitespace in sessions.c
author | Thomas Klausner <tk@giga.or.at> |
---|---|
date | Mon, 10 Jun 2019 16:27:54 +0200 |
parents | 44f3e48dfe27 |
children | 643883ec68ef |
comparison
equal
deleted
inserted
replaced
1368:a1571234c09b | 1369:f1bbcab403a6 |
---|---|
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * | 32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * |
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * | 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * |
34 *********************************************************************************************************/ | 34 *********************************************************************************************************/ |
35 | 35 |
36 /* Sessions module. | 36 /* Sessions module. |
37 * | 37 * |
38 * Basic functionalities to help implementing User sessions state machines from RFC3588. | 38 * Basic functionalities to help implementing User sessions state machines from RFC3588. |
39 */ | 39 */ |
40 | 40 |
41 #include "fdproto-internal.h" | 41 #include "fdproto-internal.h" |
42 | 42 |
89 }; | 89 }; |
90 | 90 |
91 /* Session object, one for each value of Session-Id AVP */ | 91 /* Session object, one for each value of Session-Id AVP */ |
92 struct session { | 92 struct session { |
93 int eyec; /* Eyecatcher, SI_EYEC */ | 93 int eyec; /* Eyecatcher, SI_EYEC */ |
94 | 94 |
95 os0_t sid; /* The \0-terminated Session-Id */ | 95 os0_t sid; /* The \0-terminated Session-Id */ |
96 size_t sidlen; /* cached length of sid */ | 96 size_t sidlen; /* cached length of sid */ |
97 uint32_t hash; /* computed hash of sid */ | 97 uint32_t hash; /* computed hash of sid */ |
98 struct fd_list chain_h;/* chaining in the hash table of sessions. */ | 98 struct fd_list chain_h;/* chaining in the hash table of sessions. */ |
99 | 99 |
100 struct timespec timeout;/* Timeout date for the session */ | 100 struct timespec timeout;/* Timeout date for the session */ |
101 struct fd_list expire; /* List of expiring sessions, ordered by timeouts. */ | 101 struct fd_list expire; /* List of expiring sessions, ordered by timeouts. */ |
102 | 102 |
103 pthread_mutex_t stlock; /* A lock to protect the list of states associated with this session */ | 103 pthread_mutex_t stlock; /* A lock to protect the list of states associated with this session */ |
104 struct fd_list states; /* Sentinel for the list of states of this session. */ | 104 struct fd_list states; /* Sentinel for the list of states of this session. */ |
105 int msg_cnt;/* Reference counter for the messages pointing to this session */ | 105 int msg_cnt;/* Reference counter for the messages pointing to this session */ |
106 int is_destroyed; /* boolean telling if fd_sess_detroy has been called on this */ | 106 int is_destroyed; /* boolean telling if fd_sess_detroy has been called on this */ |
107 }; | 107 }; |
123 static pthread_mutex_t sid_lock = PTHREAD_MUTEX_INITIALIZER; | 123 static pthread_mutex_t sid_lock = PTHREAD_MUTEX_INITIALIZER; |
124 | 124 |
125 /* Expiring sessions management */ | 125 /* Expiring sessions management */ |
126 static struct fd_list exp_sentinel = FD_LIST_INITIALIZER(exp_sentinel); /* list of sessions ordered by their timeout date */ | 126 static struct fd_list exp_sentinel = FD_LIST_INITIALIZER(exp_sentinel); /* list of sessions ordered by their timeout date */ |
127 static pthread_mutex_t exp_lock = PTHREAD_MUTEX_INITIALIZER; /* lock protecting the list. */ | 127 static pthread_mutex_t exp_lock = PTHREAD_MUTEX_INITIALIZER; /* lock protecting the list. */ |
128 static pthread_cond_t exp_cond = PTHREAD_COND_INITIALIZER; /* condvar used by the expiry mecahinsm. */ | 128 static pthread_cond_t exp_cond = PTHREAD_COND_INITIALIZER; /* condvar used by the expiry mechainsm. */ |
129 static pthread_t exp_thr = (pthread_t)NULL; /* The expiry thread that handles cleanup of expired sessions */ | 129 static pthread_t exp_thr = (pthread_t)NULL; /* The expiry thread that handles cleanup of expired sessions */ |
130 | 130 |
131 /* Hierarchy of the locks, to avoid deadlocks: | 131 /* Hierarchy of the locks, to avoid deadlocks: |
132 * hash lock > state lock > expiry lock | 132 * hash lock > state lock > expiry lock |
133 * i.e. state lock can be taken while holding the hash lock, but not while holding the expiry lock. | 133 * i.e. state lock can be taken while holding the hash lock, but not while holding the expiry lock. |
138 | 138 |
139 /* Initialize a session object. It is not linked now. sid must be already malloc'ed. The hash has already been computed. */ | 139 /* Initialize a session object. It is not linked now. sid must be already malloc'ed. The hash has already been computed. */ |
140 static struct session * new_session(os0_t sid, size_t sidlen, uint32_t hash) | 140 static struct session * new_session(os0_t sid, size_t sidlen, uint32_t hash) |
141 { | 141 { |
142 struct session * sess; | 142 struct session * sess; |
143 | 143 |
144 TRACE_ENTRY("%p %zd", sid, sidlen); | 144 TRACE_ENTRY("%p %zd", sid, sidlen); |
145 CHECK_PARAMS_DO( sid && sidlen, return NULL ); | 145 CHECK_PARAMS_DO( sid && sidlen, return NULL ); |
146 | 146 |
147 CHECK_MALLOC_DO( sess = malloc(sizeof(struct session)), return NULL ); | 147 CHECK_MALLOC_DO( sess = malloc(sizeof(struct session)), return NULL ); |
148 memset(sess, 0, sizeof(struct session)); | 148 memset(sess, 0, sizeof(struct session)); |
149 | 149 |
150 sess->eyec = SI_EYEC; | 150 sess->eyec = SI_EYEC; |
151 | 151 |
152 sess->sid = sid; | 152 sess->sid = sid; |
153 sess->sidlen = sidlen; | 153 sess->sidlen = sidlen; |
154 sess->hash = hash; | 154 sess->hash = hash; |
155 fd_list_init(&sess->chain_h, sess); | 155 fd_list_init(&sess->chain_h, sess); |
156 | 156 |
157 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), return NULL ); | 157 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), return NULL ); |
158 sess->timeout.tv_sec += SESS_DEFAULT_LIFETIME; | 158 sess->timeout.tv_sec += SESS_DEFAULT_LIFETIME; |
159 fd_list_init(&sess->expire, sess); | 159 fd_list_init(&sess->expire, sess); |
160 | 160 |
161 CHECK_POSIX_DO( pthread_mutex_init(&sess->stlock, NULL), return NULL ); | 161 CHECK_POSIX_DO( pthread_mutex_init(&sess->stlock, NULL), return NULL ); |
162 fd_list_init(&sess->states, sess); | 162 fd_list_init(&sess->states, sess); |
163 | 163 |
164 return sess; | 164 return sess; |
165 } | 165 } |
166 | 166 |
167 /* destroy the session object. It should really be already unlinked... */ | 167 /* destroy the session object. It should really be already unlinked... */ |
168 static void del_session(struct session * s) | 168 static void del_session(struct session * s) |
172 fd_list_unlink(&s->chain_h); | 172 fd_list_unlink(&s->chain_h); |
173 fd_list_unlink(&s->expire); | 173 fd_list_unlink(&s->expire); |
174 CHECK_POSIX_DO( pthread_mutex_destroy(&s->stlock), /* continue */ ); | 174 CHECK_POSIX_DO( pthread_mutex_destroy(&s->stlock), /* continue */ ); |
175 free(s); | 175 free(s); |
176 } | 176 } |
177 | 177 |
178 /* The expiry thread */ | 178 /* The expiry thread */ |
179 static void * exp_fct(void * arg) | 179 static void * exp_fct(void * arg) |
180 { | 180 { |
181 fd_log_threadname ( "Session/expire" ); | 181 fd_log_threadname ( "Session/expire" ); |
182 TRACE_ENTRY( "" ); | 182 TRACE_ENTRY( "" ); |
183 | 183 |
184 | 184 |
185 do { | 185 do { |
186 struct timespec now; | 186 struct timespec now; |
187 struct session * first; | 187 struct session * first; |
188 | 188 |
189 CHECK_POSIX_DO( pthread_mutex_lock(&exp_lock), break ); | 189 CHECK_POSIX_DO( pthread_mutex_lock(&exp_lock), break ); |
190 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); | 190 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); |
191 again: | 191 again: |
192 /* Check if there are expiring sessions available */ | 192 /* Check if there are expiring sessions available */ |
193 if (FD_IS_LIST_EMPTY(&exp_sentinel)) { | 193 if (FD_IS_LIST_EMPTY(&exp_sentinel)) { |
194 /* Just wait for a change or cancelation */ | 194 /* Just wait for a change or cancelation */ |
195 CHECK_POSIX_DO( pthread_cond_wait( &exp_cond, &exp_lock ), break /* this might not pop the cleanup handler, but since we ASSERT(0), it is not the big issue... */ ); | 195 CHECK_POSIX_DO( pthread_cond_wait( &exp_cond, &exp_lock ), break /* this might not pop the cleanup handler, but since we ASSERT(0), it is not the big issue... */ ); |
196 /* Restart the loop on wakeup */ | 196 /* Restart the loop on wakeup */ |
197 goto again; | 197 goto again; |
198 } | 198 } |
199 | 199 |
200 /* Get the pointer to the session that expires first */ | 200 /* Get the pointer to the session that expires first */ |
201 first = (struct session *)(exp_sentinel.next->o); | 201 first = (struct session *)(exp_sentinel.next->o); |
202 ASSERT( VALIDATE_SI(first) ); | 202 ASSERT( VALIDATE_SI(first) ); |
203 | 203 |
204 /* Get the current time */ | 204 /* Get the current time */ |
205 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), break ); | 205 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), break ); |
206 | 206 |
207 /* If first session is not expired, we just wait until it happens */ | 207 /* If first session is not expired, we just wait until it happens */ |
208 if ( TS_IS_INFERIOR( &now, &first->timeout ) ) { | 208 if ( TS_IS_INFERIOR( &now, &first->timeout ) ) { |
209 | 209 CHECK_POSIX_DO2( pthread_cond_timedwait( &exp_cond, &exp_lock, &first->timeout ), |
210 CHECK_POSIX_DO2( pthread_cond_timedwait( &exp_cond, &exp_lock, &first->timeout ), | |
211 ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */, | 210 ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */, |
212 /* on other error, */ break ); | 211 /* on other error, */ break ); |
213 | 212 |
214 /* on wakeup, loop */ | 213 /* on wakeup, loop */ |
215 goto again; | 214 goto again; |
216 } | 215 } |
217 | 216 |
218 /* Now, the first session in the list is expired; destroy it */ | 217 /* Now, the first session in the list is expired; destroy it */ |
219 pthread_cleanup_pop( 0 ); | 218 pthread_cleanup_pop( 0 ); |
220 CHECK_POSIX_DO( pthread_mutex_unlock(&exp_lock), break ); | 219 CHECK_POSIX_DO( pthread_mutex_unlock(&exp_lock), break ); |
221 | 220 |
222 CHECK_FCT_DO( fd_sess_destroy( &first ), break ); | 221 CHECK_FCT_DO( fd_sess_destroy( &first ), break ); |
223 | 222 |
224 } while (1); | 223 } while (1); |
225 | 224 |
226 TRACE_DEBUG(INFO, "A system error occurred in session module! Expiry thread is terminating..."); | 225 TRACE_DEBUG(INFO, "A system error occurred in session module! Expiry thread is terminating..."); |
227 ASSERT(0); | 226 ASSERT(0); |
228 return NULL; | 227 return NULL; |
229 } | 228 } |
230 | 229 |
231 | 230 |
232 | 231 |
233 /********************************************************************************************************/ | 232 /********************************************************************************************************/ |
234 | 233 |
235 /* Initialize the session module */ | 234 /* Initialize the session module */ |
236 int fd_sess_init(void) | 235 int fd_sess_init(void) |
237 { | 236 { |
238 int i; | 237 int i; |
239 | 238 |
240 TRACE_ENTRY( "" ); | 239 TRACE_ENTRY( "" ); |
241 | 240 |
242 /* Initialize the global counters */ | 241 /* Initialize the global counters */ |
243 sid_h = (uint32_t) time(NULL); | 242 sid_h = (uint32_t) time(NULL); |
244 sid_l = 0; | 243 sid_l = 0; |
245 | 244 |
246 /* Initialize the hash table */ | 245 /* Initialize the hash table */ |
247 for (i = 0; i < sizeof(sess_hash) / sizeof(sess_hash[0]); i++) { | 246 for (i = 0; i < sizeof(sess_hash) / sizeof(sess_hash[0]); i++) { |
248 fd_list_init( &sess_hash[i].sentinel, NULL ); | 247 fd_list_init( &sess_hash[i].sentinel, NULL ); |
249 CHECK_POSIX( pthread_mutex_init(&sess_hash[i].lock, NULL) ); | 248 CHECK_POSIX( pthread_mutex_init(&sess_hash[i].lock, NULL) ); |
250 } | 249 } |
251 | 250 |
252 return 0; | 251 return 0; |
253 } | 252 } |
254 | 253 |
255 /* Run this when initializations are complete. */ | 254 /* Run this when initializations are complete. */ |
256 int fd_sess_start(void) | 255 int fd_sess_start(void) |
257 { | 256 { |
258 /* Start session garbage collector (expiry) */ | 257 /* Start session garbage collector (expiry) */ |
259 CHECK_POSIX( pthread_create(&exp_thr, NULL, exp_fct, NULL) ); | 258 CHECK_POSIX( pthread_create(&exp_thr, NULL, exp_fct, NULL) ); |
260 | 259 |
261 return 0; | 260 return 0; |
262 } | 261 } |
263 | 262 |
264 /* Terminate */ | 263 /* Terminate */ |
265 void fd_sess_fini(void) | 264 void fd_sess_fini(void) |
266 { | 265 { |
267 TRACE_ENTRY(""); | 266 TRACE_ENTRY(""); |
268 CHECK_FCT_DO( fd_thr_term(&exp_thr), /* continue */ ); | 267 CHECK_FCT_DO( fd_thr_term(&exp_thr), /* continue */ ); |
269 | 268 |
270 /* Destroy all sessions in the hash table, and the hash table itself? -- How to do it without a race condition ? */ | 269 /* Destroy all sessions in the hash table, and the hash table itself? -- How to do it without a race condition ? */ |
271 | 270 |
272 return; | 271 return; |
273 } | 272 } |
274 | 273 |
275 /* Create a new handler */ | 274 /* Create a new handler */ |
276 int fd_sess_handler_create ( struct session_handler ** handler, void (*cleanup)(struct sess_state *, os0_t, void *), session_state_dump dumper, void * opaque ) | 275 int fd_sess_handler_create ( struct session_handler ** handler, void (*cleanup)(struct sess_state *, os0_t, void *), session_state_dump dumper, void * opaque ) |
277 { | 276 { |
278 struct session_handler *new; | 277 struct session_handler *new; |
279 | 278 |
280 TRACE_ENTRY("%p %p", handler, cleanup); | 279 TRACE_ENTRY("%p %p", handler, cleanup); |
281 | 280 |
282 CHECK_PARAMS( handler && cleanup ); | 281 CHECK_PARAMS( handler && cleanup ); |
283 | 282 |
284 CHECK_MALLOC( new = malloc(sizeof(struct session_handler)) ); | 283 CHECK_MALLOC( new = malloc(sizeof(struct session_handler)) ); |
285 memset(new, 0, sizeof(struct session_handler)); | 284 memset(new, 0, sizeof(struct session_handler)); |
286 | 285 |
287 CHECK_POSIX( pthread_mutex_lock(&hdl_lock) ); | 286 CHECK_POSIX( pthread_mutex_lock(&hdl_lock) ); |
288 new->id = ++hdl_id; | 287 new->id = ++hdl_id; |
289 CHECK_POSIX( pthread_mutex_unlock(&hdl_lock) ); | 288 CHECK_POSIX( pthread_mutex_unlock(&hdl_lock) ); |
290 | 289 |
291 new->eyec = SH_EYEC; | 290 new->eyec = SH_EYEC; |
292 new->cleanup = cleanup; | 291 new->cleanup = cleanup; |
293 new->state_dump = dumper; | 292 new->state_dump = dumper; |
294 new->opaque = opaque; | 293 new->opaque = opaque; |
295 | 294 |
296 *handler = new; | 295 *handler = new; |
297 return 0; | 296 return 0; |
298 } | 297 } |
299 | 298 |
300 /* Destroy a handler, and all states attached to this handler. This operation is very slow but we don't care since it's rarely used. | 299 /* Destroy a handler, and all states attached to this handler. This operation is very slow but we don't care since it's rarely used. |
301 * Note that it's better to call this function after all sessions have been deleted... */ | 300 * Note that it's better to call this function after all sessions have been deleted... */ |
302 int fd_sess_handler_destroy ( struct session_handler ** handler, void ** opaque ) | 301 int fd_sess_handler_destroy ( struct session_handler ** handler, void ** opaque ) |
303 { | 302 { |
304 struct session_handler * del; | 303 struct session_handler * del; |
305 /* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */ | 304 /* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */ |
306 struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states ); | 305 struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states ); |
307 int i; | 306 int i; |
308 | 307 |
309 TRACE_ENTRY("%p", handler); | 308 TRACE_ENTRY("%p", handler); |
310 CHECK_PARAMS( handler && VALIDATE_SH(*handler) ); | 309 CHECK_PARAMS( handler && VALIDATE_SH(*handler) ); |
311 | 310 |
312 del = *handler; | 311 del = *handler; |
313 *handler = NULL; | 312 *handler = NULL; |
314 | 313 |
315 del->eyec = 0xdead; /* The handler is not valid anymore for any other operation */ | 314 del->eyec = 0xdead; /* The handler is not valid anymore for any other operation */ |
316 | 315 |
317 /* Now find all sessions with data registered for this handler, and move this data to the deleted_states list. */ | 316 /* Now find all sessions with data registered for this handler, and move this data to the deleted_states list. */ |
318 for (i = 0; i < sizeof(sess_hash) / sizeof(sess_hash[0]); i++) { | 317 for (i = 0; i < sizeof(sess_hash) / sizeof(sess_hash[0]); i++) { |
319 struct fd_list * li_si; | 318 struct fd_list * li_si; |
320 CHECK_POSIX( pthread_mutex_lock(&sess_hash[i].lock) ); | 319 CHECK_POSIX( pthread_mutex_lock(&sess_hash[i].lock) ); |
321 | 320 |
322 for (li_si = sess_hash[i].sentinel.next; li_si != &sess_hash[i].sentinel; li_si = li_si->next) { /* for each session in the hash line */ | 321 for (li_si = sess_hash[i].sentinel.next; li_si != &sess_hash[i].sentinel; li_si = li_si->next) { /* for each session in the hash line */ |
323 struct fd_list * li_st; | 322 struct fd_list * li_st; |
324 struct session * sess = (struct session *)(li_si->o); | 323 struct session * sess = (struct session *)(li_si->o); |
325 CHECK_POSIX( pthread_mutex_lock(&sess->stlock) ); | 324 CHECK_POSIX( pthread_mutex_lock(&sess->stlock) ); |
326 for (li_st = sess->states.next; li_st != &sess->states; li_st = li_st->next) { /* for each state in this session */ | 325 for (li_st = sess->states.next; li_st != &sess->states; li_st = li_st->next) { /* for each state in this session */ |
338 } | 337 } |
339 CHECK_POSIX( pthread_mutex_unlock(&sess->stlock) ); | 338 CHECK_POSIX( pthread_mutex_unlock(&sess->stlock) ); |
340 } | 339 } |
341 CHECK_POSIX( pthread_mutex_unlock(&sess_hash[i].lock) ); | 340 CHECK_POSIX( pthread_mutex_unlock(&sess_hash[i].lock) ); |
342 } | 341 } |
343 | 342 |
344 /* Now, delete all states after calling their cleanup handler */ | 343 /* Now, delete all states after calling their cleanup handler */ |
345 while (!FD_IS_LIST_EMPTY(&deleted_states)) { | 344 while (!FD_IS_LIST_EMPTY(&deleted_states)) { |
346 struct state * st = (struct state *)(deleted_states.next->o); | 345 struct state * st = (struct state *)(deleted_states.next->o); |
347 TRACE_DEBUG(FULL, "Calling cleanup handler for session '%s' and data %p", st->sid, st->state); | 346 TRACE_DEBUG(FULL, "Calling cleanup handler for session '%s' and data %p", st->sid, st->state); |
348 (*del->cleanup)(st->state, st->sid, del->opaque); | 347 (*del->cleanup)(st->state, st->sid, del->opaque); |
349 fd_list_unlink(&st->chain); | 348 fd_list_unlink(&st->chain); |
350 free(st); | 349 free(st); |
351 } | 350 } |
352 | 351 |
353 if (opaque) | 352 if (opaque) |
354 *opaque = del->opaque; | 353 *opaque = del->opaque; |
355 | 354 |
356 /* Free the handler */ | 355 /* Free the handler */ |
357 free(del); | 356 free(del); |
358 | 357 |
359 return 0; | 358 return 0; |
360 } | 359 } |
361 | 360 |
362 | 361 |
363 | 362 |
369 uint32_t hash; | 368 uint32_t hash; |
370 struct session * sess; | 369 struct session * sess; |
371 struct fd_list * li; | 370 struct fd_list * li; |
372 int found = 0; | 371 int found = 0; |
373 int ret = 0; | 372 int ret = 0; |
374 | 373 |
375 TRACE_ENTRY("%p %p %zd %p %zd", session, diamid, diamidlen, opt, optlen); | 374 TRACE_ENTRY("%p %p %zd %p %zd", session, diamid, diamidlen, opt, optlen); |
376 CHECK_PARAMS( session && (diamid || opt) ); | 375 CHECK_PARAMS( session && (diamid || opt) ); |
377 | 376 |
378 if (diamid) { | 377 if (diamid) { |
379 if (!diamidlen) { | 378 if (!diamidlen) { |
380 diamidlen = strlen(diamid); | 379 diamidlen = strlen(diamid); |
381 } | 380 } |
382 /* We check if the string is a valid DiameterIdentity */ | 381 /* We check if the string is a valid DiameterIdentity */ |
383 CHECK_PARAMS( fd_os_is_valid_DiameterIdentity((uint8_t *)diamid, diamidlen) ); | 382 CHECK_PARAMS( fd_os_is_valid_DiameterIdentity((uint8_t *)diamid, diamidlen) ); |
384 } else { | 383 } else { |
385 diamidlen = 0; | 384 diamidlen = 0; |
386 } | 385 } |
387 if (opt) { | 386 if (opt) { |
388 if (!optlen) { | 387 if (!optlen) { |
389 optlen = strlen((char *)opt); | 388 optlen = strlen((char *)opt); |
390 } else { | 389 } else { |
391 CHECK_PARAMS( fd_os_is_valid_os0(opt, optlen) ); | 390 CHECK_PARAMS( fd_os_is_valid_os0(opt, optlen) ); |
392 } | 391 } |
393 } else { | 392 } else { |
394 optlen = 0; | 393 optlen = 0; |
395 } | 394 } |
396 | 395 |
397 /* Ok, first create the identifier for the string */ | 396 /* Ok, first create the identifier for the string */ |
398 if (diamid == NULL) { | 397 if (diamid == NULL) { |
399 /* opt is the full string */ | 398 /* opt is the full string */ |
400 CHECK_MALLOC( sid = os0dup(opt, optlen) ); | 399 CHECK_MALLOC( sid = os0dup(opt, optlen) ); |
401 sidlen = optlen; | 400 sidlen = optlen; |
407 sidlen += 22; /* max size of ';<high32>;<low32>' */ | 406 sidlen += 22; /* max size of ';<high32>;<low32>' */ |
408 if (opt) | 407 if (opt) |
409 sidlen += 1 + optlen; /* ';opt' */ | 408 sidlen += 1 + optlen; /* ';opt' */ |
410 sidlen++; /* space for the final \0 also */ | 409 sidlen++; /* space for the final \0 also */ |
411 CHECK_MALLOC( sid = malloc(sidlen) ); | 410 CHECK_MALLOC( sid = malloc(sidlen) ); |
412 | 411 |
413 CHECK_POSIX( pthread_mutex_lock(&sid_lock) ); | 412 CHECK_POSIX( pthread_mutex_lock(&sid_lock) ); |
414 if ( ++sid_l == 0 ) /* overflow */ | 413 if ( ++sid_l == 0 ) /* overflow */ |
415 ++sid_h; | 414 ++sid_h; |
416 sid_h_cpy = sid_h; | 415 sid_h_cpy = sid_h; |
417 sid_l_cpy = sid_l; | 416 sid_l_cpy = sid_l; |
418 CHECK_POSIX( pthread_mutex_unlock(&sid_lock) ); | 417 CHECK_POSIX( pthread_mutex_unlock(&sid_lock) ); |
419 | 418 |
420 if (opt) { | 419 if (opt) { |
421 sidlen = snprintf((char*)sid, sidlen, "%.*s;%u;%u;%.*s", (int)diamidlen, diamid, sid_h_cpy, sid_l_cpy, (int)optlen, opt); | 420 sidlen = snprintf((char*)sid, sidlen, "%.*s;%u;%u;%.*s", (int)diamidlen, diamid, sid_h_cpy, sid_l_cpy, (int)optlen, opt); |
422 } else { | 421 } else { |
423 sidlen = snprintf((char*)sid, sidlen, "%.*s;%u;%u", (int)diamidlen, diamid, sid_h_cpy, sid_l_cpy); | 422 sidlen = snprintf((char*)sid, sidlen, "%.*s;%u;%u", (int)diamidlen, diamid, sid_h_cpy, sid_l_cpy); |
424 } | 423 } |
425 } | 424 } |
426 | 425 |
427 hash = fd_os_hash(sid, sidlen); | 426 hash = fd_os_hash(sid, sidlen); |
428 | 427 |
429 /* Now find the place to add this object in the hash table. */ | 428 /* Now find the place to add this object in the hash table. */ |
430 CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash) ) ); | 429 CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash) ) ); |
431 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); | 430 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); |
432 | 431 |
433 for (li = H_LIST(hash)->next; li != H_LIST(hash); li = li->next) { | 432 for (li = H_LIST(hash)->next; li != H_LIST(hash); li = li->next) { |
434 int cmp; | 433 int cmp; |
435 struct session * s = (struct session *)(li->o); | 434 struct session * s = (struct session *)(li->o); |
436 | 435 |
437 /* The list is ordered by hash and sid (in case of collisions) */ | 436 /* The list is ordered by hash and sid (in case of collisions) */ |
438 if (s->hash < hash) | 437 if (s->hash < hash) |
439 continue; | 438 continue; |
440 if (s->hash > hash) | 439 if (s->hash > hash) |
441 break; | 440 break; |
442 | 441 |
443 cmp = fd_os_cmp(s->sid, s->sidlen, sid, sidlen); | 442 cmp = fd_os_cmp(s->sid, s->sidlen, sid, sidlen); |
444 if (cmp < 0) | 443 if (cmp < 0) |
445 continue; | 444 continue; |
446 if (cmp > 0) | 445 if (cmp > 0) |
447 break; | 446 break; |
448 | 447 |
449 /* A session with the same sid was already in the hash table */ | 448 /* A session with the same sid was already in the hash table */ |
450 found = 1; | 449 found = 1; |
451 *session = s; | 450 *session = s; |
452 break; | 451 break; |
453 } | 452 } |
454 | 453 |
455 /* If the session did not exist, we can create it & link it in global tables */ | 454 /* If the session did not exist, we can create it & link it in global tables */ |
456 if (!found) { | 455 if (!found) { |
457 CHECK_MALLOC_DO(sess = new_session(sid, sidlen, hash), | 456 CHECK_MALLOC_DO(sess = new_session(sid, sidlen, hash), |
458 { | 457 { |
459 ret = ENOMEM; | 458 ret = ENOMEM; |
460 free(sid); | 459 free(sid); |
461 goto out; | 460 goto out; |
462 } ); | 461 } ); |
463 | 462 |
464 fd_list_insert_before(li, &sess->chain_h); /* hash table */ | 463 fd_list_insert_before(li, &sess->chain_h); /* hash table */ |
465 sess->msg_cnt++; | 464 sess->msg_cnt++; |
466 } else { | 465 } else { |
467 free(sid); | 466 free(sid); |
468 | 467 |
469 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); | 468 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); |
470 (*session)->msg_cnt++; | 469 (*session)->msg_cnt++; |
471 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); | 470 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); |
472 | 471 |
473 /* it was found: was it previously destroyed? */ | 472 /* it was found: was it previously destroyed? */ |
474 if ((*session)->is_destroyed == 0) { | 473 if ((*session)->is_destroyed == 0) { |
475 ret = EALREADY; | 474 ret = EALREADY; |
476 goto out; | 475 goto out; |
477 } else { | 476 } else { |
478 /* the session was marked destroyed, let's re-activate it. */ | 477 /* the session was marked destroyed, let's re-activate it. */ |
479 sess = *session; | 478 sess = *session; |
480 sess->is_destroyed = 0; | 479 sess->is_destroyed = 0; |
481 | 480 |
482 /* update the expiry time */ | 481 /* update the expiry time */ |
483 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), { ASSERT(0); } ); | 482 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), { ASSERT(0); } ); |
484 sess->timeout.tv_sec += SESS_DEFAULT_LIFETIME; | 483 sess->timeout.tv_sec += SESS_DEFAULT_LIFETIME; |
485 } | 484 } |
486 } | 485 } |
487 | 486 |
488 /* We must insert in the expiry list */ | 487 /* We must insert in the expiry list */ |
489 CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); | 488 CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); |
490 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); | 489 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); |
491 | 490 |
492 /* Find the position in that list. We take it in reverse order */ | 491 /* Find the position in that list. We take it in reverse order */ |
509 | 508 |
510 out: | 509 out: |
511 ; | 510 ; |
512 pthread_cleanup_pop(0); | 511 pthread_cleanup_pop(0); |
513 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); | 512 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); |
514 | 513 |
515 if (ret) /* in case of error */ | 514 if (ret) /* in case of error */ |
516 return ret; | 515 return ret; |
517 | 516 |
518 *session = sess; | 517 *session = sess; |
519 return 0; | 518 return 0; |
520 } | 519 } |
521 | 520 |
522 /* Find or create a session -- the msg refcount is increased */ | 521 /* Find or create a session -- the msg refcount is increased */ |
523 int fd_sess_fromsid_msg ( uint8_t * sid, size_t len, struct session ** session, int * new) | 522 int fd_sess_fromsid_msg ( uint8_t * sid, size_t len, struct session ** session, int * new) |
524 { | 523 { |
525 int ret; | 524 int ret; |
526 | 525 |
527 TRACE_ENTRY("%p %zd %p %p", sid, len, session, new); | 526 TRACE_ENTRY("%p %zd %p %p", sid, len, session, new); |
528 CHECK_PARAMS( sid && session ); | 527 CHECK_PARAMS( sid && session ); |
529 | 528 |
530 if (!fd_os_is_valid_os0(sid,len)) { | 529 if (!fd_os_is_valid_os0(sid,len)) { |
531 TRACE_DEBUG(INFO, "Warning: a Session-Id value contains \\0 chars... (len:%zd, begin:'%.*s') => Debug messages may be truncated.", len, (int)len, sid); | 530 TRACE_DEBUG(INFO, "Warning: a Session-Id value contains \\0 chars... (len:%zd, begin:'%.*s') => Debug messages may be truncated.", len, (int)len, sid); |
532 } | 531 } |
533 | 532 |
534 /* All the work is done in sess_new */ | 533 /* All the work is done in sess_new */ |
535 ret = fd_sess_new ( session, NULL, 0, sid, len ); | 534 ret = fd_sess_new ( session, NULL, 0, sid, len ); |
536 switch (ret) { | 535 switch (ret) { |
537 case 0: | 536 case 0: |
538 case EALREADY: | 537 case EALREADY: |
539 break; | 538 break; |
540 | 539 |
541 default: | 540 default: |
542 CHECK_FCT(ret); | 541 CHECK_FCT(ret); |
543 } | 542 } |
544 | 543 |
545 if (new) | 544 if (new) |
546 *new = ret ? 0 : 1; | 545 *new = ret ? 0 : 1; |
547 | 546 |
548 return 0; | 547 return 0; |
549 } | 548 } |
550 | 549 |
551 /* Get the sid of a session */ | 550 /* Get the sid of a session */ |
552 int fd_sess_getsid ( struct session * session, os0_t * sid, size_t * sidlen ) | 551 int fd_sess_getsid ( struct session * session, os0_t * sid, size_t * sidlen ) |
553 { | 552 { |
554 TRACE_ENTRY("%p %p", session, sid); | 553 TRACE_ENTRY("%p %p", session, sid); |
555 | 554 |
556 CHECK_PARAMS( VALIDATE_SI(session) && sid ); | 555 CHECK_PARAMS( VALIDATE_SI(session) && sid ); |
557 | 556 |
558 *sid = session->sid; | 557 *sid = session->sid; |
559 if (sidlen) | 558 if (sidlen) |
560 *sidlen = session->sidlen; | 559 *sidlen = session->sidlen; |
561 | 560 |
562 return 0; | 561 return 0; |
563 } | 562 } |
564 | 563 |
565 /* Change the timeout value of a session */ | 564 /* Change the timeout value of a session */ |
566 int fd_sess_settimeout( struct session * session, const struct timespec * timeout ) | 565 int fd_sess_settimeout( struct session * session, const struct timespec * timeout ) |
567 { | 566 { |
568 struct fd_list * li; | 567 struct fd_list * li; |
569 | 568 |
570 TRACE_ENTRY("%p %p", session, timeout); | 569 TRACE_ENTRY("%p %p", session, timeout); |
571 CHECK_PARAMS( VALIDATE_SI(session) && timeout ); | 570 CHECK_PARAMS( VALIDATE_SI(session) && timeout ); |
572 | 571 |
573 /* Lock -- do we need to lock the hash table as well? I don't think so... */ | 572 /* Lock -- do we need to lock the hash table as well? I don't think so... */ |
574 CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); | 573 CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); |
575 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); | 574 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); |
576 | 575 |
577 /* Update the timeout */ | 576 /* Update the timeout */ |
578 fd_list_unlink(&session->expire); | 577 fd_list_unlink(&session->expire); |
579 memcpy(&session->timeout, timeout, sizeof(struct timespec)); | 578 memcpy(&session->timeout, timeout, sizeof(struct timespec)); |
580 | 579 |
581 /* Find the new position in expire list. We take it in normal order */ | 580 /* Find the new position in expire list. We take it in normal order */ |
582 for (li = exp_sentinel.next; li != &exp_sentinel; li = li->next) { | 581 for (li = exp_sentinel.next; li != &exp_sentinel; li = li->next) { |
583 struct session * s = (struct session *)(li->o); | 582 struct session * s = (struct session *)(li->o); |
584 | 583 |
585 if (TS_IS_INFERIOR( &s->timeout, &session->timeout ) ) | 584 if (TS_IS_INFERIOR( &s->timeout, &session->timeout ) ) |
595 } | 594 } |
596 | 595 |
597 /* We're done */ | 596 /* We're done */ |
598 pthread_cleanup_pop(0); | 597 pthread_cleanup_pop(0); |
599 CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) ); | 598 CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) ); |
600 | 599 |
601 return 0; | 600 return 0; |
602 } | 601 } |
603 | 602 |
604 /* Destroy the states associated to a session, and mark it destroyed. */ | 603 /* Destroy the states associated to a session, and mark it destroyed. */ |
605 int fd_sess_destroy ( struct session ** session ) | 604 int fd_sess_destroy ( struct session ** session ) |
606 { | 605 { |
607 struct session * sess; | 606 struct session * sess; |
608 int destroy_now; | 607 int destroy_now; |
609 os0_t sid; | 608 os0_t sid; |
610 int ret = 0; | 609 int ret = 0; |
611 | 610 |
612 /* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */ | 611 /* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */ |
613 struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states ); | 612 struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states ); |
614 | 613 |
615 TRACE_ENTRY("%p", session); | 614 TRACE_ENTRY("%p", session); |
616 CHECK_PARAMS( session && VALIDATE_SI(*session) ); | 615 CHECK_PARAMS( session && VALIDATE_SI(*session) ); |
617 | 616 |
618 sess = *session; | 617 sess = *session; |
619 *session = NULL; | 618 *session = NULL; |
620 | 619 |
621 /* Lock the hash line */ | 620 /* Lock the hash line */ |
622 CHECK_POSIX( pthread_mutex_lock( H_LOCK(sess->hash) ) ); | 621 CHECK_POSIX( pthread_mutex_lock( H_LOCK(sess->hash) ) ); |
623 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(sess->hash) ); | 622 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(sess->hash) ); |
624 | 623 |
625 /* Unlink from the expiry list */ | 624 /* Unlink from the expiry list */ |
626 CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); | 625 CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); |
626 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); | |
627 if (!FD_IS_LIST_EMPTY(&sess->expire)) { | 627 if (!FD_IS_LIST_EMPTY(&sess->expire)) { |
628 sess_cnt--; | 628 sess_cnt--; |
629 fd_list_unlink( &sess->expire ); /* no need to signal the condition here */ | 629 fd_list_unlink( &sess->expire ); /* no need to signal the condition here */ |
630 } | 630 } |
631 pthread_cleanup_pop(0); | |
631 CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); | 632 CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); |
632 | 633 |
633 /* Now move all states associated to this session into deleted_states */ | 634 /* Now move all states associated to this session into deleted_states */ |
634 CHECK_POSIX_DO( pthread_mutex_lock( &sess->stlock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); | 635 CHECK_POSIX_DO( pthread_mutex_lock( &sess->stlock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); |
635 while (!FD_IS_LIST_EMPTY(&sess->states)) { | 636 while (!FD_IS_LIST_EMPTY(&sess->states)) { |
636 struct state * st = (struct state *)(sess->states.next->o); | 637 struct state * st = (struct state *)(sess->states.next->o); |
637 fd_list_unlink(&st->chain); | 638 fd_list_unlink(&st->chain); |
638 fd_list_insert_before(&deleted_states, &st->chain); | 639 fd_list_insert_before(&deleted_states, &st->chain); |
639 } | 640 } |
640 CHECK_POSIX_DO( pthread_mutex_unlock( &sess->stlock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); | 641 CHECK_POSIX_DO( pthread_mutex_unlock( &sess->stlock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); |
641 | 642 |
642 /* Mark the session as destroyed */ | 643 /* Mark the session as destroyed */ |
643 destroy_now = (sess->msg_cnt == 0); | 644 destroy_now = (sess->msg_cnt == 0); |
644 if (destroy_now) { | 645 if (destroy_now) { |
645 fd_list_unlink( &sess->chain_h ); | 646 fd_list_unlink( &sess->chain_h ); |
646 sid = sess->sid; | 647 sid = sess->sid; |
648 sess->is_destroyed = 1; | 649 sess->is_destroyed = 1; |
649 CHECK_MALLOC_DO( sid = os0dup(sess->sid, sess->sidlen), ret = ENOMEM ); | 650 CHECK_MALLOC_DO( sid = os0dup(sess->sid, sess->sidlen), ret = ENOMEM ); |
650 } | 651 } |
651 pthread_cleanup_pop(0); | 652 pthread_cleanup_pop(0); |
652 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(sess->hash) ) ); | 653 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(sess->hash) ) ); |
653 | 654 |
654 if (ret) | 655 if (ret) |
655 return ret; | 656 return ret; |
656 | 657 |
657 /* Now, really delete the states */ | 658 /* Now, really delete the states */ |
658 while (!FD_IS_LIST_EMPTY(&deleted_states)) { | 659 while (!FD_IS_LIST_EMPTY(&deleted_states)) { |
659 struct state * st = (struct state *)(deleted_states.next->o); | 660 struct state * st = (struct state *)(deleted_states.next->o); |
660 fd_list_unlink(&st->chain); | 661 fd_list_unlink(&st->chain); |
661 TRACE_DEBUG(FULL, "Calling handler %p cleanup for state %p registered with session '%s'", st->hdl, st, sid); | 662 TRACE_DEBUG(FULL, "Calling handler %p cleanup for state %p registered with session '%s'", st->hdl, st, sid); |
662 (*st->hdl->cleanup)(st->state, sid, st->hdl->opaque); | 663 (*st->hdl->cleanup)(st->state, sid, st->hdl->opaque); |
663 free(st); | 664 free(st); |
664 } | 665 } |
665 | 666 |
666 /* Finally, destroy the session itself, if it is not referrenced by any message anymore */ | 667 /* Finally, destroy the session itself, if it is not referrenced by any message anymore */ |
667 if (destroy_now) { | 668 if (destroy_now) { |
668 del_session(sess); | 669 del_session(sess); |
669 } else { | 670 } else { |
670 free(sid); | 671 free(sid); |
671 } | 672 } |
672 | 673 |
673 return 0; | 674 return 0; |
674 } | 675 } |
675 | 676 |
676 /* Destroy a session if it is not used */ | 677 /* Destroy a session if it is not used */ |
677 int fd_sess_reclaim ( struct session ** session ) | 678 int fd_sess_reclaim ( struct session ** session ) |
678 { | 679 { |
679 struct session * sess; | 680 struct session * sess; |
680 uint32_t hash; | 681 uint32_t hash; |
681 int destroy_now = 0; | 682 int destroy_now = 0; |
682 | 683 |
683 TRACE_ENTRY("%p", session); | 684 TRACE_ENTRY("%p", session); |
684 CHECK_PARAMS( session && VALIDATE_SI(*session) ); | 685 CHECK_PARAMS( session && VALIDATE_SI(*session) ); |
685 | 686 |
686 sess = *session; | 687 sess = *session; |
687 hash = sess->hash; | 688 hash = sess->hash; |
688 *session = NULL; | 689 *session = NULL; |
689 | 690 |
690 CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash) ) ); | 691 CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash) ) ); |
691 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); | 692 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); |
692 CHECK_POSIX_DO( pthread_mutex_lock( &sess->stlock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); | 693 CHECK_POSIX_DO( pthread_mutex_lock( &sess->stlock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); |
693 pthread_cleanup_push( fd_cleanup_mutex, &sess->stlock ); | 694 pthread_cleanup_push( fd_cleanup_mutex, &sess->stlock ); |
694 CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); | 695 CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); |
695 | 696 pthread_cleanup_push( fd_cleanup_mutex, &exp_lock ); |
697 | |
696 /* We only do something if the states list is empty */ | 698 /* We only do something if the states list is empty */ |
697 if (FD_IS_LIST_EMPTY(&sess->states)) { | 699 if (FD_IS_LIST_EMPTY(&sess->states)) { |
698 /* In this case, we do as in destroy */ | 700 /* In this case, we do as in destroy */ |
699 fd_list_unlink( &sess->expire ); | 701 fd_list_unlink( &sess->expire ); |
700 destroy_now = (sess->msg_cnt == 0); | 702 destroy_now = (sess->msg_cnt == 0); |
703 } else { | 705 } else { |
704 /* just mark it as destroyed, it will be freed when the last message stops referencing it */ | 706 /* just mark it as destroyed, it will be freed when the last message stops referencing it */ |
705 sess->is_destroyed = 1; | 707 sess->is_destroyed = 1; |
706 } | 708 } |
707 } | 709 } |
708 | 710 |
711 pthread_cleanup_pop(0); | |
709 CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); | 712 CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); |
710 pthread_cleanup_pop(0); | 713 pthread_cleanup_pop(0); |
711 CHECK_POSIX_DO( pthread_mutex_unlock( &sess->stlock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); | 714 CHECK_POSIX_DO( pthread_mutex_unlock( &sess->stlock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } ); |
712 pthread_cleanup_pop(0); | 715 pthread_cleanup_pop(0); |
713 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); | 716 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); |
714 | 717 |
715 if (destroy_now) | 718 if (destroy_now) |
716 del_session(sess); | 719 del_session(sess); |
717 | 720 |
718 return 0; | 721 return 0; |
719 } | 722 } |
720 | 723 |
721 /* Save a state information with a session */ | 724 /* Save a state information with a session */ |
722 int fd_sess_state_store ( struct session_handler * handler, struct session * session, struct sess_state ** state ) | 725 int fd_sess_state_store ( struct session_handler * handler, struct session * session, struct sess_state ** state ) |
723 { | 726 { |
724 struct state *new; | 727 struct state *new; |
725 struct fd_list * li; | 728 struct fd_list * li; |
726 int already = 0; | 729 int already = 0; |
727 int ret = 0; | 730 int ret = 0; |
728 | 731 |
729 TRACE_ENTRY("%p %p %p", handler, session, state); | 732 TRACE_ENTRY("%p %p %p", handler, session, state); |
730 CHECK_PARAMS( handler && VALIDATE_SH(handler) && session && VALIDATE_SI(session) && (!session->is_destroyed) && state ); | 733 CHECK_PARAMS( handler && VALIDATE_SH(handler) && session && VALIDATE_SI(session) && (!session->is_destroyed) && state ); |
731 | 734 |
732 /* Lock the session state list */ | 735 /* Lock the session state list */ |
733 CHECK_POSIX( pthread_mutex_lock(&session->stlock) ); | 736 CHECK_POSIX( pthread_mutex_lock(&session->stlock) ); |
734 pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); | 737 pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); |
735 | 738 |
736 /* Create the new state object */ | 739 /* Create the new state object */ |
737 CHECK_MALLOC_DO(new = malloc(sizeof(struct state)), { ret = ENOMEM; goto out; } ); | 740 CHECK_MALLOC_DO(new = malloc(sizeof(struct state)), { ret = ENOMEM; goto out; } ); |
738 memset(new, 0, sizeof(struct state)); | 741 memset(new, 0, sizeof(struct state)); |
739 | 742 |
740 new->eyec = SD_EYEC; | 743 new->eyec = SD_EYEC; |
741 new->state= *state; | 744 new->state= *state; |
742 fd_list_init(&new->chain, new); | 745 fd_list_init(&new->chain, new); |
743 new->hdl = handler; | 746 new->hdl = handler; |
744 | 747 |
745 /* find place for this state in the list */ | 748 /* find place for this state in the list */ |
746 for (li = session->states.next; li != &session->states; li = li->next) { | 749 for (li = session->states.next; li != &session->states; li = li->next) { |
747 struct state * st = (struct state *)(li->o); | 750 struct state * st = (struct state *)(li->o); |
748 /* The list is ordered by handler's id */ | 751 /* The list is ordered by handler's id */ |
749 if (st->hdl->id < handler->id) | 752 if (st->hdl->id < handler->id) |
750 continue; | 753 continue; |
751 | 754 |
752 if (st->hdl->id == handler->id) { | 755 if (st->hdl->id == handler->id) { |
753 TRACE_DEBUG(INFO, "A state was already stored for session '%s' and handler '%p', at location %p", session->sid, st->hdl, st->state); | 756 TRACE_DEBUG(INFO, "A state was already stored for session '%s' and handler '%p', at location %p", session->sid, st->hdl, st->state); |
754 already = EALREADY; | 757 already = EALREADY; |
755 } | 758 } |
756 | 759 |
757 break; | 760 break; |
758 } | 761 } |
759 | 762 |
760 if (!already) { | 763 if (!already) { |
761 fd_list_insert_before(li, &new->chain); | 764 fd_list_insert_before(li, &new->chain); |
762 *state = NULL; | 765 *state = NULL; |
763 } else { | 766 } else { |
764 free(new); | 767 free(new); |
765 } | 768 } |
766 out: | 769 out: |
767 ; | 770 ; |
768 pthread_cleanup_pop(0); | 771 pthread_cleanup_pop(0); |
769 CHECK_POSIX( pthread_mutex_unlock(&session->stlock) ); | 772 CHECK_POSIX( pthread_mutex_unlock(&session->stlock) ); |
770 | 773 |
771 return ret ?: already; | 774 return ret ?: already; |
772 } | 775 } |
773 | 776 |
774 /* Get the data back */ | 777 /* Get the data back */ |
775 int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, struct sess_state ** state ) | 778 int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, struct sess_state ** state ) |
776 { | 779 { |
777 struct fd_list * li; | 780 struct fd_list * li; |
778 struct state * st = NULL; | 781 struct state * st = NULL; |
779 | 782 |
780 TRACE_ENTRY("%p %p %p", handler, session, state); | 783 TRACE_ENTRY("%p %p %p", handler, session, state); |
781 CHECK_PARAMS( handler && VALIDATE_SH(handler) && session && VALIDATE_SI(session) && state ); | 784 CHECK_PARAMS( handler && VALIDATE_SH(handler) && session && VALIDATE_SI(session) && state ); |
782 | 785 |
783 *state = NULL; | 786 *state = NULL; |
784 | 787 |
785 /* Lock the session state list */ | 788 /* Lock the session state list */ |
786 CHECK_POSIX( pthread_mutex_lock(&session->stlock) ); | 789 CHECK_POSIX( pthread_mutex_lock(&session->stlock) ); |
787 pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); | 790 pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); |
788 | 791 |
789 /* find the state in the list */ | 792 /* find the state in the list */ |
790 for (li = session->states.next; li != &session->states; li = li->next) { | 793 for (li = session->states.next; li != &session->states; li = li->next) { |
791 st = (struct state *)(li->o); | 794 st = (struct state *)(li->o); |
792 | 795 |
793 /* The list is ordered by handler's id */ | 796 /* The list is ordered by handler's id */ |
794 if (st->hdl->id > handler->id) | 797 if (st->hdl->id > handler->id) |
795 break; | 798 break; |
796 } | 799 } |
797 | 800 |
798 /* If we found the state */ | 801 /* If we found the state */ |
799 if (st && (st->hdl == handler)) { | 802 if (st && (st->hdl == handler)) { |
800 fd_list_unlink(&st->chain); | 803 fd_list_unlink(&st->chain); |
801 *state = st->state; | 804 *state = st->state; |
802 free(st); | 805 free(st); |
803 } | 806 } |
804 | 807 |
805 pthread_cleanup_pop(0); | 808 pthread_cleanup_pop(0); |
806 CHECK_POSIX( pthread_mutex_unlock(&session->stlock) ); | 809 CHECK_POSIX( pthread_mutex_unlock(&session->stlock) ); |
807 | 810 |
808 return 0; | 811 return 0; |
809 } | 812 } |
810 | 813 |
811 /* For the messages module */ | 814 /* For the messages module */ |
812 int fd_sess_fromsid ( uint8_t * sid, size_t len, struct session ** session, int * new) | 815 int fd_sess_fromsid ( uint8_t * sid, size_t len, struct session ** session, int * new) |
813 { | 816 { |
814 TRACE_ENTRY("%p %zd %p %p", sid, len, session, new); | 817 TRACE_ENTRY("%p %zd %p %p", sid, len, session, new); |
815 CHECK_PARAMS( sid && len && session ); | 818 CHECK_PARAMS( sid && len && session ); |
816 | 819 |
817 /* Get the session object */ | 820 /* Get the session object */ |
818 CHECK_FCT( fd_sess_fromsid_msg ( sid, len, session, new) ); | 821 CHECK_FCT( fd_sess_fromsid_msg ( sid, len, session, new) ); |
819 | 822 |
820 /* Decrease the refcount */ | 823 /* Decrease the refcount */ |
821 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); | 824 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); |
822 (*session)->msg_cnt--; /* was increased in fd_sess_new */ | 825 (*session)->msg_cnt--; /* was increased in fd_sess_new */ |
823 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); | 826 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); |
824 | 827 |
825 /* Done */ | 828 /* Done */ |
826 return 0; | 829 return 0; |
827 } | 830 } |
828 | 831 |
829 int fd_sess_ref_msg ( struct session * session ) | 832 int fd_sess_ref_msg ( struct session * session ) |
833 | 836 |
834 /* Update the msg refcount */ | 837 /* Update the msg refcount */ |
835 CHECK_POSIX( pthread_mutex_lock(&session->stlock) ); | 838 CHECK_POSIX( pthread_mutex_lock(&session->stlock) ); |
836 session->msg_cnt++; | 839 session->msg_cnt++; |
837 CHECK_POSIX( pthread_mutex_unlock(&session->stlock) ); | 840 CHECK_POSIX( pthread_mutex_unlock(&session->stlock) ); |
838 | 841 |
839 return 0; | 842 return 0; |
840 } | 843 } |
841 | 844 |
842 int fd_sess_reclaim_msg ( struct session ** session ) | 845 int fd_sess_reclaim_msg ( struct session ** session ) |
843 { | 846 { |
844 int reclaim; | 847 int reclaim; |
845 uint32_t hash; | 848 uint32_t hash; |
846 | 849 |
847 TRACE_ENTRY("%p", session); | 850 TRACE_ENTRY("%p", session); |
848 CHECK_PARAMS( session && VALIDATE_SI(*session) ); | 851 CHECK_PARAMS( session && VALIDATE_SI(*session) ); |
849 | 852 |
850 /* Lock the hash line to avoid possibility that session is freed while we are reclaiming */ | 853 /* Lock the hash line to avoid possibility that session is freed while we are reclaiming */ |
851 hash = (*session)->hash; | 854 hash = (*session)->hash; |
852 CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash)) ); | 855 CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash)) ); |
853 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); | 856 pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); |
854 | 857 |
855 /* Update the msg refcount */ | 858 /* Update the msg refcount */ |
856 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); | 859 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); |
857 reclaim = (*session)->msg_cnt; | 860 reclaim = (*session)->msg_cnt; |
858 (*session)->msg_cnt = reclaim - 1; | 861 (*session)->msg_cnt = reclaim - 1; |
859 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); | 862 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); |
860 | 863 |
861 /* Ok, now unlock the hash line */ | 864 /* Ok, now unlock the hash line */ |
862 pthread_cleanup_pop( 0 ); | 865 pthread_cleanup_pop( 0 ); |
863 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); | 866 CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); |
864 | 867 |
865 /* and reclaim if no message references the session anymore */ | 868 /* and reclaim if no message references the session anymore */ |
866 if (reclaim == 1) { | 869 if (reclaim == 1) { |
867 CHECK_FCT(fd_sess_reclaim ( session )); | 870 CHECK_FCT(fd_sess_reclaim ( session )); |
868 } else { | 871 } else { |
869 *session = NULL; | 872 *session = NULL; |
875 | 878 |
876 /* Dump functions */ | 879 /* Dump functions */ |
877 DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states) | 880 DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states) |
878 { | 881 { |
879 FD_DUMP_HANDLE_OFFSET(); | 882 FD_DUMP_HANDLE_OFFSET(); |
880 | 883 |
881 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{session}(@%p): ", session), return NULL); | 884 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{session}(@%p): ", session), return NULL); |
882 | 885 |
883 if (!VALIDATE_SI(session)) { | 886 if (!VALIDATE_SI(session)) { |
884 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); | 887 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); |
885 } else { | 888 } else { |
886 char timebuf[30]; | 889 char timebuf[30]; |
887 struct tm tm; | 890 struct tm tm; |
888 | 891 |
889 strftime(timebuf, sizeof(timebuf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); | 892 strftime(timebuf, sizeof(timebuf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); |
890 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%zd) h:%x m:%d d:%d to:%s.%06ld", | 893 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%zd) h:%x m:%d d:%d to:%s.%06ld", |
891 session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed, | 894 session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed, |
892 timebuf, session->timeout.tv_nsec/1000), | 895 timebuf, session->timeout.tv_nsec/1000), |
893 return NULL); | 896 return NULL); |
894 | 897 |
895 if (with_states) { | 898 if (with_states) { |
896 struct fd_list * li; | 899 struct fd_list * li; |
897 CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); | 900 CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); |
898 pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); | 901 pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); |
899 | 902 |
900 for (li = session->states.next; li != &session->states; li = li->next) { | 903 for (li = session->states.next; li != &session->states; li = li->next) { |
901 struct state * st = (struct state *)(li->o); | 904 struct state * st = (struct state *)(li->o); |
902 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {state i:%d}(@%p): ", st->hdl->id, st), return NULL); | 905 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {state i:%d}(@%p): ", st->hdl->id, st), return NULL); |
903 if (st->hdl->state_dump) { | 906 if (st->hdl->state_dump) { |
904 CHECK_MALLOC_DO( (*st->hdl->state_dump)( FD_DUMP_STD_PARAMS, st->state), | 907 CHECK_MALLOC_DO( (*st->hdl->state_dump)( FD_DUMP_STD_PARAMS, st->state), |
905 fd_dump_extend( FD_DUMP_STD_PARAMS, "[dumper error]")); | 908 fd_dump_extend( FD_DUMP_STD_PARAMS, "[dumper error]")); |
906 } else { | 909 } else { |
907 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<%p>", st->state), return NULL); | 910 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<%p>", st->state), return NULL); |
908 } | 911 } |
909 } | 912 } |
910 | 913 |
911 pthread_cleanup_pop(0); | 914 pthread_cleanup_pop(0); |
912 CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); | 915 CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); |
913 } | 916 } |
914 } | 917 } |
915 | 918 |
916 return *buf; | 919 return *buf; |
917 } | 920 } |
918 | 921 |
919 DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler) | 922 DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler) |
920 { | 923 { |
921 FD_DUMP_HANDLE_OFFSET(); | 924 FD_DUMP_HANDLE_OFFSET(); |
922 | 925 |
923 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{sesshdl}(@%p): ", handler), return NULL); | 926 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{sesshdl}(@%p): ", handler), return NULL); |
924 | 927 |
925 if (!VALIDATE_SH(handler)) { | 928 if (!VALIDATE_SH(handler)) { |
926 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); | 929 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); |
927 } else { | 930 } else { |
928 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "i:%d cl:%p d:%p o:%p", handler->id, handler->cleanup, handler->state_dump, handler->opaque), return NULL); | 931 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "i:%d cl:%p d:%p o:%p", handler->id, handler->cleanup, handler->state_dump, handler->opaque), return NULL); |
929 } | 932 } |
930 return *buf; | 933 return *buf; |
931 } | 934 } |
932 | 935 |
933 int fd_sess_getcount(uint32_t *cnt) | 936 int fd_sess_getcount(uint32_t *cnt) |
934 { | 937 { |
935 CHECK_PARAMS(cnt); | 938 CHECK_PARAMS(cnt); |
936 CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); | 939 CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); |