/src/rtpproxy/src/rtpp_pipe.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 | | #include <stddef.h> |
30 | | #include <stdint.h> |
31 | | #include <stdlib.h> |
32 | | |
33 | | #include "config.h" |
34 | | |
35 | | #include "rtpp_cfg.h" |
36 | | #include "rtpp_debug.h" |
37 | | #include "rtpp_log.h" |
38 | | #include "rtpp_types.h" |
39 | | #include "rtpp_genuid.h" |
40 | | #include "rtpp_mallocs.h" |
41 | | #include "rtpp_pcount.h" |
42 | | #include "rtpp_codeptr.h" |
43 | | #include "rtpp_refcnt.h" |
44 | | #include "rtpp_log_obj.h" |
45 | | #include "rtpp_weakref.h" |
46 | | #include "rtpp_time.h" |
47 | | #include "rtpp_stream.h" |
48 | | #include "rtpp_pipe.h" |
49 | | #include "rtpp_pipe_fin.h" |
50 | | #include "rtpp_ttl.h" |
51 | | #include "rtpp_math.h" |
52 | | #include "rtpp_acct_pipe.h" |
53 | | #include "rtpp_pcnt_strm.h" |
54 | | #include "rtpp_pcnts_strm.h" |
55 | | #include "rtpp_stats.h" |
56 | | #include "rtpp_refcnt.h" |
57 | | #include "rtpp_session.h" |
58 | | #include "advanced/pproc_manager.h" |
59 | | |
60 | | struct rtpp_pipe_priv |
61 | | { |
62 | | struct rtpp_pipe pub; |
63 | | struct rtpp_weakref *streams_wrt; |
64 | | int pipe_type; |
65 | | }; |
66 | | |
67 | | static void rtpp_pipe_dtor(struct rtpp_pipe_priv *); |
68 | | static int rtpp_pipe_get_ttl(struct rtpp_pipe *); |
69 | | static void rtpp_pipe_decr_ttl(struct rtpp_pipe *); |
70 | | static void rtpp_pipe_get_stats(struct rtpp_pipe *, struct rtpp_acct_pipe *); |
71 | | static void rtpp_pipe_upd_cntrs(struct rtpp_pipe *, struct rtpp_acct_pipe *); |
72 | | |
73 | 7.95k | #define NO_MED_NM(t) (((t) == PIPE_RTP) ? "nsess_nortp" : "nsess_nortcp") |
74 | 0 | #define OW_MED_NM(t) (((t) == PIPE_RTP) ? "nsess_owrtp" : "nsess_owrtcp") |
75 | | |
76 | 0 | #define MT2RT_NZ(mt) ((mt).wall) |
77 | 0 | #define DRTN_NZ(bmt, emt) ((emt).mono == 0.0 || (bmt).mono == 0.0 ? 0.0 : ((emt).mono - (bmt).mono)) |
78 | | |
79 | | DEFINE_SMETHODS(rtpp_pipe, |
80 | | .get_ttl = &rtpp_pipe_get_ttl, |
81 | | .decr_ttl = &rtpp_pipe_decr_ttl, |
82 | | .get_stats = &rtpp_pipe_get_stats, |
83 | | .upd_cntrs = &rtpp_pipe_upd_cntrs, |
84 | | ); |
85 | | |
86 | | struct rtpp_pipe * |
87 | | rtpp_pipe_ctor(const struct r_pipe_ctor_args *ap) |
88 | 78.8k | { |
89 | 78.8k | struct rtpp_pipe_priv *pvt; |
90 | 78.8k | const struct rtpp_cfg *cfs = ap->session_cap->cfs; |
91 | 78.8k | int i; |
92 | | |
93 | 78.8k | pvt = rtpp_rzmalloc(sizeof(struct rtpp_pipe_priv), PVT_RCOFFS(pvt)); |
94 | 78.8k | if (pvt == NULL) { |
95 | 0 | goto e0; |
96 | 0 | } |
97 | | |
98 | 78.8k | RTPP_OBJ_BORROW_s(&pvt->pub, ap->log); |
99 | 78.8k | if (ap->pipe_type == PIPE_RTP) { |
100 | 39.4k | pvt->streams_wrt = cfs->rtp_streams_wrt; |
101 | 39.4k | } else { |
102 | 39.4k | pvt->streams_wrt = cfs->rtcp_streams_wrt; |
103 | 39.4k | } |
104 | | |
105 | 78.8k | pvt->pub.ppuid = CALL_SMETHOD(cfs->guid, gen); |
106 | 78.8k | struct r_stream_ctor_args rsca = { |
107 | 78.8k | .pipe_cap = ap, |
108 | 78.8k | }; |
109 | 236k | for (i = 0; i < 2; i++) { |
110 | 157k | rsca.side = i; |
111 | 157k | pvt->pub.stream[i] = rtpp_stream_ctor(&rsca); |
112 | 157k | if (pvt->pub.stream[i] == NULL) { |
113 | 0 | goto e1; |
114 | 0 | } |
115 | 157k | RTPP_OBJ_DTOR_ATTACH_OBJ_s(&pvt->pub, pvt->pub.stream[i]); |
116 | 157k | if (CALL_SMETHOD(pvt->streams_wrt, reg, pvt->pub.stream[i]->rcnt, |
117 | 157k | pvt->pub.stream[i]->stuid) != 0) { |
118 | 0 | goto e1; |
119 | 0 | } |
120 | 157k | } |
121 | 78.8k | if (CALL_SMETHOD(pvt->pub.stream[0], link_sender, pvt->pub.stream[1]) != 0) |
122 | 0 | goto e1; |
123 | 78.8k | if (CALL_SMETHOD(pvt->pub.stream[1], link_sender, pvt->pub.stream[0]) != 0) |
124 | 0 | goto e1; |
125 | 78.8k | pvt->pub.pcount = rtpp_pcount_ctor(); |
126 | 78.8k | if (pvt->pub.pcount == NULL) { |
127 | 0 | goto e1; |
128 | 0 | } |
129 | 78.8k | RTPP_OBJ_DTOR_ATTACH_OBJ_s(&pvt->pub, pvt->pub.pcount); |
130 | 236k | for (i = 0; i < 2; i++) { |
131 | 157k | RTPP_OBJ_BORROW_s(pvt->pub.stream[i], pvt->pub.pcount); |
132 | 157k | pvt->pub.stream[i]->pcount = pvt->pub.pcount; |
133 | 157k | } |
134 | 78.8k | pvt->pub.stream[0]->pproc_manager->reverse = pvt->pub.stream[1]->pproc_manager; |
135 | 78.8k | RTPP_OBJ_BORROW_s(&pvt->pub, pvt->pub.stream[1]->pproc_manager); |
136 | 78.8k | pvt->pub.stream[1]->pproc_manager->reverse = pvt->pub.stream[0]->pproc_manager; |
137 | 78.8k | RTPP_OBJ_BORROW_s(&pvt->pub, pvt->pub.stream[0]->pproc_manager); |
138 | 78.8k | pvt->pipe_type = ap->pipe_type; |
139 | 78.8k | pvt->pub.rtpp_stats = cfs->rtpp_stats; |
140 | 78.8k | pvt->pub.log = ap->log; |
141 | 78.8k | PUBINST_FININIT(&pvt->pub, pvt, rtpp_pipe_dtor); |
142 | | #if defined(RTPP_DEBUG) |
143 | | RTPP_OBJ_DTOR_ATTACH_s(&pvt->pub, rtpp_pipe_fin, &(pvt->pub)); |
144 | | #endif |
145 | 78.8k | return (&pvt->pub); |
146 | | |
147 | 0 | e1: |
148 | 0 | for (i = 0; i < 2; i++) |
149 | 0 | if (pvt->pub.stream[i] != NULL) |
150 | 0 | CALL_SMETHOD(pvt->pub.stream[i], unreg); |
151 | 0 | RTPP_OBJ_DECREF(&(pvt->pub)); |
152 | 0 | e0: |
153 | 0 | return (NULL); |
154 | 0 | } |
155 | | |
156 | | static void |
157 | | rtpp_pipe_dtor(struct rtpp_pipe_priv *pvt) |
158 | 78.8k | { |
159 | 78.8k | int i; |
160 | | |
161 | 236k | for (i = 0; i < 2; i++) { |
162 | 157k | CALL_SMETHOD(pvt->pub.stream[i], unreg); |
163 | 157k | } |
164 | 78.8k | } |
165 | | |
166 | | static int |
167 | | rtpp_pipe_get_ttl(struct rtpp_pipe *self) |
168 | 4.00k | { |
169 | 4.00k | int ttls[2]; |
170 | | |
171 | 4.00k | ttls[0] = CALL_SMETHOD(self->stream[0]->ttl, get_remaining); |
172 | 4.00k | ttls[1] = CALL_SMETHOD(self->stream[1]->ttl, get_remaining); |
173 | 4.00k | return (MIN(ttls[0], ttls[1])); |
174 | 4.00k | } |
175 | | |
176 | | static void |
177 | | rtpp_pipe_decr_ttl(struct rtpp_pipe *self) |
178 | 46 | { |
179 | 46 | CALL_SMETHOD(self->stream[0]->ttl, decr); |
180 | 46 | if (self->stream[1]->ttl == self->stream[0]->ttl) |
181 | 46 | return; |
182 | 46 | CALL_SMETHOD(self->stream[1]->ttl, decr); |
183 | 0 | } |
184 | | |
185 | | static void |
186 | | rtpp_pipe_get_stats(struct rtpp_pipe *self, struct rtpp_acct_pipe *rapp) |
187 | 78.8k | { |
188 | 78.8k | struct rtpp_pipe_priv *pvt; |
189 | | |
190 | 78.8k | PUB2PVT(self, pvt); |
191 | | |
192 | 78.8k | CALL_SMETHOD(self->pcount, get_stats, rapp->pcnts); |
193 | 78.8k | CALL_SMETHOD(self->stream[0], get_stats, &rapp->o.hld_stat); |
194 | 78.8k | CALL_SMETHOD(self->stream[1], get_stats, &rapp->a.hld_stat); |
195 | 78.8k | CALL_SMETHOD(self->stream[0]->pcnt_strm, get_stats, rapp->o.ps); |
196 | 78.8k | CALL_SMETHOD(self->stream[1]->pcnt_strm, get_stats, rapp->a.ps); |
197 | 78.8k | rapp->o.rem_addr = CALL_SMETHOD(self->stream[0], get_rem_addr, 1); |
198 | 78.8k | rapp->a.rem_addr = CALL_SMETHOD(self->stream[1], get_rem_addr, 1); |
199 | 78.8k | RTPP_LOG(self->log, RTPP_LOG_INFO, "%s stats: %lu in from callee, %lu " |
200 | 78.8k | "in from caller, %lu relayed, %lu dropped, %lu ignored", |
201 | 78.8k | PP_NAME(pvt->pipe_type), rapp->o.ps->npkts_in, |
202 | 78.8k | rapp->a.ps->npkts_in, rapp->pcnts->nrelayed, rapp->pcnts->ndropped, |
203 | 78.8k | rapp->pcnts->nignored); |
204 | 78.8k | if (rapp->pcnts->ndropped > 0) { |
205 | 0 | CALL_SMETHOD(self->pcount, log_drops, self->log); |
206 | 0 | } |
207 | 78.8k | if (pvt->pipe_type != PIPE_RTP) { |
208 | 39.4k | return; |
209 | 39.4k | } |
210 | 39.4k | if (rapp->o.ps->first_pkt_rcv.mono > 0.0) { |
211 | 0 | RTPP_LOG(self->log, RTPP_LOG_INFO, "RTP times: caller: first in at %f, " |
212 | 0 | "duration %f, longest IPI %f", MT2RT_NZ(rapp->o.ps->first_pkt_rcv), |
213 | 0 | DRTN_NZ(rapp->o.ps->first_pkt_rcv, rapp->o.ps->last_pkt_rcv), |
214 | 0 | rapp->o.ps->longest_ipi); |
215 | 0 | } |
216 | 39.4k | if (rapp->a.ps->first_pkt_rcv.mono > 0.0) { |
217 | 0 | RTPP_LOG(self->log, RTPP_LOG_INFO, "RTP times: callee: first in at %f, " |
218 | 0 | "duration %f, longest IPI %f", MT2RT_NZ(rapp->a.ps->first_pkt_rcv), |
219 | 0 | DRTN_NZ(rapp->a.ps->first_pkt_rcv, rapp->a.ps->last_pkt_rcv), |
220 | 0 | rapp->a.ps->longest_ipi); |
221 | 0 | } |
222 | | |
223 | 39.4k | } |
224 | | |
225 | | static void |
226 | | rtpp_pipe_upd_cntrs(struct rtpp_pipe *self, struct rtpp_acct_pipe *rapp) |
227 | 7.95k | { |
228 | 7.95k | struct rtpp_pipe_priv *pvt; |
229 | | |
230 | 7.95k | PUB2PVT(self, pvt); |
231 | | |
232 | 7.95k | if (rapp->o.ps->npkts_in == 0 && rapp->a.ps->npkts_in == 0) { |
233 | 7.95k | CALL_SMETHOD(self->rtpp_stats, updatebyname, NO_MED_NM(pvt->pipe_type), |
234 | 7.95k | 1); |
235 | 7.95k | } else if (rapp->o.ps->npkts_in == 0 || rapp->a.ps->npkts_in == 0) { |
236 | 0 | CALL_SMETHOD(self->rtpp_stats, updatebyname, OW_MED_NM(pvt->pipe_type), |
237 | 0 | 1); |
238 | 0 | } |
239 | 7.95k | } |