/src/rtpproxy/src/rtpp_proc_ttl.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org> |
3 | | * Copyright (c) 2006-2015 Sippy Software, Inc., http://www.sippysoft.com |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions |
8 | | * are met: |
9 | | * 1. Redistributions of source code must retain the above copyright |
10 | | * notice, this list of conditions and the following disclaimer. |
11 | | * 2. Redistributions in binary form must reproduce the above copyright |
12 | | * notice, this list of conditions and the following disclaimer in the |
13 | | * documentation and/or other materials provided with the distribution. |
14 | | * |
15 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 | | * SUCH DAMAGE. |
26 | | * |
27 | | */ |
28 | | |
29 | | #if defined(LINUX_XXX) && !defined(_GNU_SOURCE) |
30 | | #define _GNU_SOURCE /* pthread_setname_np() */ |
31 | | #endif |
32 | | |
33 | | #include <assert.h> |
34 | | #include <pthread.h> |
35 | | #include <stdatomic.h> |
36 | | #include <stddef.h> |
37 | | #include <stdint.h> |
38 | | #include <stdlib.h> |
39 | | |
40 | | #include <elperiodic.h> |
41 | | |
42 | | #include "config.h" |
43 | | |
44 | | #include "rtpp_cfg.h" |
45 | | #include "rtpp_log.h" |
46 | | #include "rtpp_types.h" |
47 | | #include "rtpp_log_obj.h" |
48 | | #include "rtpp_notify.h" |
49 | | #include "rtpp_session.h" |
50 | | #include "rtpp_stats.h" |
51 | | #include "rtpp_hash_table.h" |
52 | | #include "rtpp_weakref.h" |
53 | | #include "rtpp_proc_ttl.h" |
54 | | #include "rtpp_codeptr.h" |
55 | | #include "rtpp_refcnt.h" |
56 | | #include "rtpp_mallocs.h" |
57 | | #include "rtpp_pipe.h" |
58 | | #include "rtpp_timeout_data.h" |
59 | | #include "rtpp_locking.h" |
60 | | #include "rtpp_threads.h" |
61 | | |
62 | | struct foreach_args { |
63 | | struct rtpp_notify *rtpp_notify_cf; |
64 | | struct rtpp_stats *rtpp_stats; |
65 | | struct rtpp_weakref *sessions_wrt; |
66 | | }; |
67 | | |
68 | | struct rtpp_proc_ttl_pvt { |
69 | | struct rtpp_proc_ttl pub; |
70 | | pthread_t thread_id; |
71 | | struct rtpp_anetio_cf *op; |
72 | | _Atomic(int) tstate; |
73 | | void *elp; |
74 | | struct rtpp_hash_table *sessions_ht; |
75 | | struct foreach_args fa; |
76 | | }; |
77 | | |
78 | | static void rtpp_proc_ttl(struct rtpp_hash_table *, const struct foreach_args *); |
79 | | |
80 | | static const char *notyfy_type = "timeout"; |
81 | | |
82 | | static int |
83 | | rtpp_proc_ttl_foreach(void *dp, void *ap) |
84 | 14 | { |
85 | 14 | const struct foreach_args *fap; |
86 | 14 | const struct rtpp_session *sp; |
87 | | |
88 | 14 | fap = (const struct foreach_args *)ap; |
89 | | /* |
90 | | * This method does not need us to bump ref, since we are in the |
91 | | * locked context of the rtpp_hash_table, which holds its own ref. |
92 | | */ |
93 | 14 | sp = (const struct rtpp_session *)dp; |
94 | | |
95 | 14 | if (CALL_SMETHOD(sp->rtp, get_ttl) == 0) { |
96 | 0 | RTPP_LOG(sp->log, RTPP_LOG_INFO, "session timeout"); |
97 | 0 | if (sp->timeout_data != NULL) { |
98 | 0 | CALL_METHOD(fap->rtpp_notify_cf, schedule, |
99 | 0 | sp->timeout_data->notify_target, sp->timeout_data->notify_tag, |
100 | 0 | notyfy_type); |
101 | 0 | } |
102 | 0 | CALL_SMETHOD(fap->rtpp_stats, updatebyname, "nsess_timeout", 1); |
103 | 0 | CALL_SMETHOD(fap->sessions_wrt, unreg, sp->seuid); |
104 | 0 | return (RTPP_HT_MATCH_DEL); |
105 | 14 | } else { |
106 | 14 | CALL_SMETHOD(sp->rtp, decr_ttl); |
107 | 14 | } |
108 | 14 | return (RTPP_HT_MATCH_CONT); |
109 | 14 | } |
110 | | |
111 | | static void |
112 | | rtpp_proc_ttl(struct rtpp_hash_table *sessions_ht, const struct foreach_args *fap) |
113 | 20 | { |
114 | | |
115 | 20 | CALL_SMETHOD(sessions_ht, foreach, rtpp_proc_ttl_foreach, (void *)fap, NULL); |
116 | 20 | } |
117 | | |
118 | | static void |
119 | | rtpp_proc_ttl_run(void *arg) |
120 | 4 | { |
121 | 4 | struct rtpp_proc_ttl_pvt *proc_cf; |
122 | 4 | int tstate; |
123 | | |
124 | 4 | proc_cf = (struct rtpp_proc_ttl_pvt *)arg; |
125 | | |
126 | 24 | for (;;) { |
127 | 24 | tstate = atomic_load(&proc_cf->tstate); |
128 | 24 | if (tstate == TSTATE_CEASE) { |
129 | 4 | break; |
130 | 4 | } |
131 | 20 | prdic_procrastinate(proc_cf->elp); |
132 | 20 | rtpp_proc_ttl(proc_cf->sessions_ht, &proc_cf->fa); |
133 | 20 | } |
134 | 4 | } |
135 | | |
136 | | static void |
137 | | rtpp_proc_ttl_dtor(struct rtpp_proc_ttl *pub) |
138 | 4 | { |
139 | 4 | struct rtpp_proc_ttl_pvt *proc_cf; |
140 | 4 | int tstate; |
141 | | |
142 | 4 | PUB2PVT(pub, proc_cf); |
143 | 4 | tstate = atomic_load(&proc_cf->tstate); |
144 | 4 | assert(tstate == TSTATE_RUN); |
145 | 4 | atomic_store(&proc_cf->tstate, TSTATE_CEASE); |
146 | 4 | pthread_join(proc_cf->thread_id, NULL); |
147 | 4 | RTPP_OBJ_DECREF(proc_cf->sessions_ht); |
148 | 4 | RTPP_OBJ_DECREF(proc_cf->fa.sessions_wrt); |
149 | 4 | RTPP_OBJ_DECREF(proc_cf->fa.rtpp_notify_cf); |
150 | 4 | RTPP_OBJ_DECREF(proc_cf->fa.rtpp_stats); |
151 | 4 | prdic_free(proc_cf->elp); |
152 | 4 | free(proc_cf); |
153 | 4 | } |
154 | | |
155 | | struct rtpp_proc_ttl * |
156 | | rtpp_proc_ttl_ctor(const struct rtpp_cfg *cfsp) |
157 | 4 | { |
158 | 4 | struct rtpp_proc_ttl_pvt *proc_cf; |
159 | | |
160 | 4 | proc_cf = rtpp_zmalloc(sizeof(*proc_cf)); |
161 | 4 | if (proc_cf == NULL) |
162 | 0 | return (NULL); |
163 | | |
164 | 4 | proc_cf->elp = prdic_init(1.0, 0.0); |
165 | 4 | if (proc_cf->elp == NULL) { |
166 | 0 | goto e0; |
167 | 0 | } |
168 | | |
169 | 4 | proc_cf->fa.rtpp_notify_cf = cfsp->rtpp_notify_cf; |
170 | 4 | RTPP_OBJ_INCREF(cfsp->rtpp_notify_cf); |
171 | 4 | proc_cf->fa.rtpp_stats = cfsp->rtpp_stats; |
172 | 4 | RTPP_OBJ_INCREF(cfsp->rtpp_stats); |
173 | 4 | proc_cf->fa.sessions_wrt = cfsp->sessions_wrt; |
174 | 4 | RTPP_OBJ_INCREF(cfsp->sessions_wrt); |
175 | 4 | proc_cf->sessions_ht = cfsp->sessions_ht; |
176 | 4 | RTPP_OBJ_INCREF(cfsp->sessions_ht); |
177 | | |
178 | 4 | if (pthread_create(&proc_cf->thread_id, NULL, (void *(*)(void *))&rtpp_proc_ttl_run, proc_cf) != 0) { |
179 | 0 | goto e1; |
180 | 0 | } |
181 | 4 | #if HAVE_PTHREAD_SETNAME_NP |
182 | 4 | (void)pthread_setname_np(proc_cf->thread_id, "rtpp_proc_ttl"); |
183 | 4 | #endif |
184 | 4 | proc_cf->pub.dtor = &rtpp_proc_ttl_dtor; |
185 | 4 | return (&proc_cf->pub); |
186 | 0 | e1: |
187 | 0 | RTPP_OBJ_DECREF(cfsp->rtpp_stats); |
188 | 0 | RTPP_OBJ_DECREF(cfsp->sessions_ht); |
189 | 0 | RTPP_OBJ_DECREF(cfsp->sessions_wrt); |
190 | 0 | RTPP_OBJ_DECREF(cfsp->rtpp_notify_cf); |
191 | 0 | prdic_free(proc_cf->elp); |
192 | 0 | e0: |
193 | 0 | free(proc_cf); |
194 | | return (NULL); |
195 | 0 | } |