Coverage Report

Created: 2026-04-12 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rtpproxy/src/rtpp_server.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3
 * Copyright (c) 2006-2016 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 <sys/types.h>
30
#include <netinet/in.h>
31
#include <fcntl.h>
32
#include <limits.h>
33
#include <stddef.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
#include <unistd.h>
38
39
#include "rtpp_types.h"
40
#include "rtp.h"
41
#include "rtpp_time.h"
42
#include "rtp_packet.h"
43
#include "rtpp_mallocs.h"
44
#include "rtpp_codeptr.h"
45
#include "rtpp_refcnt.h"
46
#include "rtpp_server.h"
47
#include "rtpp_server_fin.h"
48
#include "rtpp_genuid.h"
49
#include "rtpp_debug.h"
50
51
/*
52
 * Minimum length of each RTP packet in ms.
53
 * Actual length may differ due to codec's framing constrains.
54
 */
55
0
#define RTPS_TICKS_MIN  10
56
57
#define RTPS_SRATE      8000
58
59
struct rtpp_server_priv {
60
    struct rtpp_server pub;
61
    double btime;
62
    unsigned char buf[1024];
63
    rtp_hdr_t *rtp;
64
    unsigned char *pload;
65
    int fd;
66
    int loop;
67
    uint64_t dts;
68
    int ptime;
69
    int started;
70
};
71
72
static void rtpp_server_dtor(struct rtpp_server_priv *);
73
static struct rtp_packet *rtpp_server_get(struct rtpp_server *, double, int *);
74
static uint32_t rtpp_server_get_ssrc(struct rtpp_server *);
75
static void rtpp_server_set_ssrc(struct rtpp_server *, uint32_t);
76
static uint16_t rtpp_server_get_seq(struct rtpp_server *);
77
static void rtpp_server_set_seq(struct rtpp_server *, uint16_t);
78
static void rtpp_server_start(struct rtpp_server *, double);
79
80
DEFINE_SMETHODS(rtpp_server,
81
    .get = &rtpp_server_get,
82
    .get_ssrc = &rtpp_server_get_ssrc,
83
    .set_ssrc = &rtpp_server_set_ssrc,
84
    .get_seq = &rtpp_server_get_seq,
85
    .set_seq = &rtpp_server_set_seq,
86
    .start = &rtpp_server_start
87
);
88
89
struct rtpp_server *
90
rtpp_server_ctor(struct rtpp_server_ctor_args *ap)
91
0
{
92
0
    struct rtpp_server_priv *rp;
93
0
    int fd;
94
0
    char path[PATH_MAX + 1];
95
0
    size_t len;
96
97
0
    len = snprintf(path, sizeof(path), "%s.%d", ap->name, ap->codec);
98
0
    if (len >= sizeof(path)) {
99
0
        ap->result = RTPP_SERV_BADARG;
100
0
        goto e0;
101
0
    }
102
0
    fd = open(path, O_RDONLY);
103
0
    if (fd == -1) {
104
0
        ap->result = RTPP_SERV_NOENT;
105
0
  goto e0;
106
0
    }
107
108
0
    rp = rtpp_rzmalloc(sizeof(struct rtpp_server_priv), PVT_RCOFFS(rp));
109
0
    if (rp == NULL) {
110
0
        ap->result = RTPP_SERV_NOMEM;
111
0
  goto e1;
112
0
    }
113
114
0
    rp->dts = 0;
115
0
    rp->fd = fd;
116
0
    rp->loop = (ap->loop > 0) ? ap->loop - 1 : ap->loop;
117
0
    rp->ptime = (ap->ptime > 0) ? ap->ptime : RTPS_TICKS_MIN;
118
119
0
    rp->rtp = (rtp_hdr_t *)rp->buf;
120
0
    rp->rtp->version = 2;
121
0
    rp->rtp->p = 0;
122
0
    rp->rtp->x = 0;
123
0
    rp->rtp->cc = 0;
124
0
    rp->rtp->mbt = 1;
125
0
    rp->rtp->pt = ap->codec;
126
0
    rp->rtp->ts = random() & 0xfffffffe;
127
0
    rp->rtp->seq = random() & 0xffff;
128
0
    rp->rtp->ssrc = random();
129
0
    rp->pload = rp->buf + RTP_HDR_LEN(rp->rtp);
130
131
0
    rp->pub.sruid = CALL_SMETHOD(ap->guid, gen);
132
133
0
    PUBINST_FININIT(&rp->pub, rp, rtpp_server_dtor);
134
0
    ap->result = RTPP_SERV_OK;
135
0
    return (&rp->pub);
136
0
e1:
137
0
    close(fd);
138
0
e0:
139
0
    return (NULL);
140
0
}
141
142
static void
143
rtpp_server_dtor(struct rtpp_server_priv *rp)
144
0
{
145
146
0
    rtpp_server_fin(&rp->pub);
147
0
    close(rp->fd);
148
0
}
149
150
static struct rtp_packet *
151
rtpp_server_get(struct rtpp_server *self, double dtime, int *rval)
152
0
{
153
0
    struct rtp_packet *pkt;
154
0
    uint32_t ts;
155
0
    int rlen, rticks, bytes_per_frame, ticks_per_frame, number_of_frames;
156
0
    int hlen;
157
0
    struct rtpp_server_priv *rp;
158
159
0
    PUB2PVT(self, rp);
160
161
0
    if (rp->started == 0 || (rp->btime + ((double)rp->dts / 1000.0) > dtime)) {
162
0
        *rval = RTPS_LATER;
163
0
  return (NULL);
164
0
    }
165
166
0
    switch (rp->rtp->pt) {
167
0
    case RTP_PCMU:
168
0
    case RTP_PCMA:
169
0
  bytes_per_frame = 8;
170
0
  ticks_per_frame = 1;
171
0
  break;
172
173
0
    case RTP_G729:
174
  /* 10 ms per 8 kbps G.729 frame */
175
0
  bytes_per_frame = 10;
176
0
  ticks_per_frame = 10;
177
0
  break;
178
179
0
    case RTP_G723:
180
  /* 30 ms per 6.3 kbps G.723 frame */
181
0
  bytes_per_frame = 24;
182
0
  ticks_per_frame = 30;
183
0
  break;
184
185
0
    case RTP_GSM:
186
  /* 20 ms per 13 kbps GSM frame */
187
0
  bytes_per_frame = 33;
188
0
  ticks_per_frame = 20;
189
0
  break;
190
191
0
    case RTP_G722:
192
0
  bytes_per_frame = 8;
193
0
  ticks_per_frame = 1;
194
0
  break;
195
196
0
    default:
197
0
  *rval = RTPS_ERROR;
198
0
        return (NULL);
199
0
    }
200
201
0
    number_of_frames = rp->ptime / ticks_per_frame;
202
0
    if (rp->ptime % ticks_per_frame != 0)
203
0
  number_of_frames++;
204
205
0
    rlen = bytes_per_frame * number_of_frames;
206
0
    rticks = ticks_per_frame * number_of_frames;
207
0
    rp->dts += rticks;
208
209
0
    pkt = rtp_packet_alloc();
210
0
    if (pkt == NULL) {
211
0
        *rval = RTPS_ENOMEM;
212
0
        return (NULL);
213
0
    }
214
0
    hlen = RTP_HDR_LEN(rp->rtp);
215
216
0
    if (read(rp->fd, pkt->data.buf + hlen, rlen) != rlen) {
217
0
  if (rp->loop == 0 || lseek(rp->fd, 0, SEEK_SET) == -1 ||
218
0
    read(rp->fd, pkt->data.buf + hlen, rlen) != rlen) {
219
0
      *rval = RTPS_EOF;
220
0
            RTPP_OBJ_DECREF(pkt);
221
0
            return (NULL);
222
0
        }
223
0
  if (rp->loop != -1)
224
0
      rp->loop -= 1;
225
0
    }
226
227
0
    memcpy(&pkt->data.header, rp->rtp, hlen);
228
229
0
    if (rp->rtp->mbt != 0) {
230
0
        rp->rtp->mbt = 0;
231
0
    }
232
233
0
    ts = ntohl(rp->rtp->ts);
234
0
    rp->rtp->ts = htonl(ts + (RTPS_SRATE * rticks / 1000));
235
0
    rp->rtp->seq = htons(ntohs(rp->rtp->seq) + 1);
236
237
0
    pkt->size = hlen + rlen;
238
0
    return (pkt);
239
0
}
240
241
static uint32_t
242
rtpp_server_get_ssrc(struct rtpp_server *self)
243
0
{
244
0
    struct rtpp_server_priv *rp;
245
246
0
    PUB2PVT(self, rp);
247
0
    return (ntohl(rp->rtp->ssrc));
248
0
}
249
250
static void
251
rtpp_server_set_ssrc(struct rtpp_server *self, uint32_t ssrc)
252
0
{
253
0
    struct rtpp_server_priv *rp;
254
255
0
    PUB2PVT(self, rp);
256
0
    rp->rtp->ssrc = htonl(ssrc);
257
0
}
258
259
static uint16_t
260
rtpp_server_get_seq(struct rtpp_server *self)
261
0
{
262
0
    struct rtpp_server_priv *rp;
263
264
0
    PUB2PVT(self, rp);
265
0
    return (ntohs(rp->rtp->seq));
266
0
}
267
268
static void
269
rtpp_server_set_seq(struct rtpp_server *self, uint16_t seq)
270
0
{
271
0
    struct rtpp_server_priv *rp;
272
273
0
    PUB2PVT(self, rp);
274
0
    rp->rtp->seq = htons(seq);
275
0
}
276
277
static void
278
rtpp_server_start(struct rtpp_server *self, double dtime)
279
0
{
280
0
    struct rtpp_server_priv *rp;
281
282
    PUB2PVT(self, rp);
283
0
    RTPP_DBG_ASSERT(rp->started == 0);
284
0
    rp->btime = dtime;
285
0
    rp->started = 1;
286
0
}