blob: 72746845f2f6a07d53702f88bfcd16059ed3ee04 [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*********************************************************************************************************
2* Software License Agreement (BSD License) *
3* Author: Sebastien Decugis <sdecugis@freediameter.net> *
4* *
5* Copyright (c) 2015, WIDE Project and NICT *
6* All rights reserved. *
7* *
8* Redistribution and use of this software in source and binary forms, with or without modification, are *
9* permitted provided that the following conditions are met: *
10* *
11* * Redistributions of source code must retain the above *
12* copyright notice, this list of conditions and the *
13* following disclaimer. *
14* *
15* * Redistributions in binary form must reproduce the above *
16* copyright notice, this list of conditions and the *
17* following disclaimer in the documentation and/or other *
18* materials provided with the distribution. *
19* *
20* * Neither the name of the WIDE Project or NICT nor the *
21* names of its contributors may be used to endorse or *
22* promote products derived from this software without *
23* specific prior written permission of WIDE Project and *
24* NICT. *
25* *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
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. *
34*********************************************************************************************************/
35
36#include "rt_redir.h"
37
38/* Expiration management */
39
40
41/* Entries by their ascending expiration date, to accelerate the work of the expire thread */
42static struct fd_list expire_list = FD_LIST_INITIALIZER(expire_list);
43static pthread_cond_t exp_cnd = PTHREAD_COND_INITIALIZER;
44
45pthread_mutex_t redir_exp_peer_lock = PTHREAD_MUTEX_INITIALIZER;
46
47/* The thread that handles expired entries cleanup. */
48void * redir_exp_thr_fct(void * arg)
49{
50 fd_log_threadname ( "Redirects/expire" );
51 TRACE_ENTRY( "" );
52
53 CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), goto fatal_error );
54 pthread_cleanup_push( fd_cleanup_mutex, &redir_exp_peer_lock );
55
56 do {
57 struct timespec now;
58 struct redir_entry * first;
59again:
60 /* Check if there are expiring entries available */
61 if (FD_IS_LIST_EMPTY(&expire_list)) {
62 /* Just wait for a change or cancelation */
63 CHECK_POSIX_DO( pthread_cond_wait( &exp_cnd, &redir_exp_peer_lock ), break /* this might not pop the cleanup handler, but since we ASSERT(0), it is not the big issue... */ );
64 /* Restart the loop on wakeup */
65 goto again;
66 }
67
68 /* Get the pointer to the entry that expires first */
69 first = (struct redir_entry *)(expire_list.next->o);
70
71 /* Get the current time */
72 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), break );
73
74 /* If first session is not expired, we just wait until it happens */
75 if ( TS_IS_INFERIOR( &now, &first->timeout ) ) {
76
77 CHECK_POSIX_DO2( pthread_cond_timedwait( &exp_cnd, &redir_exp_peer_lock, &first->timeout ),
78 ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */,
79 /* on other error, */ break );
80
81 /* on wakeup, loop */
82 goto again;
83 }
84
85 /* Now, the first entry in the list is expired; destroy it */
86
87 CHECK_FCT_DO( redir_entry_destroy( first ), break );
88
89 } while (1);
90
91 pthread_cleanup_pop( 0 );
92 CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), );
93
94fatal_error:
95 TRACE_DEBUG(INFO, "A system error occurred in redirect module! Expiry thread is terminating...");
96 ASSERT(0);
97 return NULL;
98}
99
100/* Sets the timeout value & link in expiry list. The mutex must be held on calling */
101int redir_exp_set(struct redir_entry * e, uint32_t duration)
102{
103 struct fd_list * li;
104 TRACE_ENTRY("%p %d", e, duration);
105 CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC) && duration );
106
107 /* Unlink in case it was already set before */
108 fd_list_unlink(&e->exp_list);
109
110 /* Get current time */
111 CHECK_SYS( clock_gettime(CLOCK_REALTIME, &e->timeout) );
112
113 /* Add the duration */
114 e->timeout.tv_sec += duration;
115
116 /* now search the next element in the list */
117 for (li = expire_list.next; li != &expire_list; li = li->next) {
118 struct redir_entry * n = li->o;
119
120 if ( TS_IS_INFERIOR( &e->timeout, &n->timeout ) )
121 break;
122
123 }
124
125 /* Insert before this element */
126 fd_list_insert_before(li, &e->exp_list);
127
128 /* Signal the expiry thread if needed */
129 if (e->exp_list.prev == &expire_list) { /* it is the first element */
130 CHECK_POSIX( pthread_cond_signal(&exp_cnd) );
131 }
132
133 /* Done */
134 return 0;
135}
136