Coverage Report

Created: 2026-06-16 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}