blob: 33738bc6e1509c86412bbcf779457138ef16688b [file] [log] [blame]
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The protocol implementation */
3
4/*
5 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2012 by On-Waves
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <string.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <errno.h>
28#include <time.h>
29#include <limits.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020030#include <arpa/inet.h>
31
32#include <osmocom/core/msgb.h>
33#include <osmocom/core/select.h>
Philipp Maier1cb1e382017-11-02 17:16:04 +010034#include <osmocom/core/socket.h>
Philipp Maier4dba7692018-08-03 12:20:52 +020035#include <osmocom/core/byteswap.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020036#include <osmocom/netif/rtp.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020037#include <osmocom/mgcp/mgcp.h>
Neels Hofmeyr67793542017-09-08 04:25:16 +020038#include <osmocom/mgcp/mgcp_common.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020039#include <osmocom/mgcp/mgcp_internal.h>
40#include <osmocom/mgcp/mgcp_stat.h>
41#include <osmocom/mgcp/osmux.h>
42#include <osmocom/mgcp/mgcp_conn.h>
Philipp Maier37d11c82018-02-01 14:38:12 +010043#include <osmocom/mgcp/mgcp_endp.h>
Philipp Maier6931f9a2018-07-26 09:29:31 +020044#include <osmocom/mgcp/mgcp_codec.h>
Philipp Maierc3413882017-10-27 12:26:54 +020045#include <osmocom/mgcp/debug.h>
Philipp Maier9fc8a022019-02-20 12:26:52 +010046#include <osmocom/codec/codec.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020047
Philipp Maier6931f9a2018-07-26 09:29:31 +020048
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020049#define RTP_SEQ_MOD (1 << 16)
50#define RTP_MAX_DROPOUT 3000
51#define RTP_MAX_MISORDER 100
52#define RTP_BUF_SIZE 4096
53
54enum {
55 MGCP_PROTO_RTP,
56 MGCP_PROTO_RTCP,
57};
58
Philipp Maier1cb1e382017-11-02 17:16:04 +010059/*! Determine the local rtp bind IP-address.
60 * \param[out] addr caller provided memory to store the resulting IP-Address
61 * \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters
62 *
63 * The local bind IP-address is automatically selected by probing the
64 * IP-Address of the interface that is pointing towards the remote IP-Address,
65 * if no remote IP-Address is known yet, the statically configured
66 * IP-Addresses are used as fallback. */
67void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
68{
69
70 struct mgcp_endpoint *endp;
71 int rc;
72 endp = conn->conn->endp;
73
74 /* Try probing the local IP-Address */
75 if (endp->cfg->net_ports.bind_addr_probe && conn->end.addr.s_addr != 0) {
76 rc = osmo_sock_local_ip(addr, inet_ntoa(conn->end.addr));
77 if (rc < 0)
78 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +010079 "endpoint:0x%x CI:%s local interface auto detection failed, using configured addresses...\n",
Philipp Maier1cb1e382017-11-02 17:16:04 +010080 ENDPOINT_NUMBER(endp), conn->conn->id);
81 else {
82 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +010083 "endpoint:0x%x CI:%s selected local rtp bind ip %s by probing using remote ip %s\n",
Philipp Maier1cb1e382017-11-02 17:16:04 +010084 ENDPOINT_NUMBER(endp), conn->conn->id, addr,
85 inet_ntoa(conn->end.addr));
86 return;
87 }
88 }
89
90 /* Select from preconfigured IP-Addresses */
91 if (endp->cfg->net_ports.bind_addr) {
92 /* Check there is a bind IP for the RTP traffic configured,
93 * if so, use that IP-Address */
Philipp Maierf8bfbe82017-11-23 19:32:31 +010094 osmo_strlcpy(addr, endp->cfg->net_ports.bind_addr, INET_ADDRSTRLEN);
Philipp Maier1cb1e382017-11-02 17:16:04 +010095 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +010096 "endpoint:0x%x CI:%s using configured rtp bind ip as local bind ip %s\n",
Philipp Maier1cb1e382017-11-02 17:16:04 +010097 ENDPOINT_NUMBER(endp), conn->conn->id, addr);
98 } else {
99 /* No specific bind IP is configured for the RTP traffic, so
100 * assume the IP where we listen for incoming MGCP messages
101 * as bind IP */
Philipp Maierf8bfbe82017-11-23 19:32:31 +0100102 osmo_strlcpy(addr, endp->cfg->source_addr, INET_ADDRSTRLEN);
Philipp Maier1cb1e382017-11-02 17:16:04 +0100103 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100104 "endpoint:0x%x CI:%s using mgcp bind ip as local rtp bind ip: %s\n",
Philipp Maier1cb1e382017-11-02 17:16:04 +0100105 ENDPOINT_NUMBER(endp), conn->conn->id, addr);
106 }
107}
108
Philipp Maier87bd9be2017-08-22 16:35:41 +0200109/* This does not need to be a precision timestamp and
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200110 * is allowed to wrap quite fast. The returned value is
Philipp Maier87bd9be2017-08-22 16:35:41 +0200111 * 1/codec_rate seconds. */
112static uint32_t get_current_ts(unsigned codec_rate)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200113{
114 struct timespec tp;
115 uint64_t ret;
116
Philipp Maier87bd9be2017-08-22 16:35:41 +0200117 if (!codec_rate)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200118 return 0;
119
120 memset(&tp, 0, sizeof(tp));
121 if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0)
Philipp Maierc3413882017-10-27 12:26:54 +0200122 LOGP(DRTP, LOGL_NOTICE, "Getting the clock failed.\n");
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200123
124 /* convert it to 1/unit seconds */
125 ret = tp.tv_sec;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200126 ret *= codec_rate;
127 ret += (int64_t) tp.tv_nsec * codec_rate / 1000 / 1000 / 1000;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200128
129 return ret;
130}
131
Philipp Maier87bd9be2017-08-22 16:35:41 +0200132/*! send udp packet.
133 * \param[in] fd associated file descriptor
134 * \param[in] addr destination ip-address
135 * \param[in] port destination UDP port
136 * \param[in] buf buffer that holds the data to be send
137 * \param[in] len length of the data to be sent
138 * \returns bytes sent, -1 on error */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200139int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
140{
141 struct sockaddr_in out;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200142
Philipp Maierc3413882017-10-27 12:26:54 +0200143 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200144 "sending %i bytes length packet to %s:%u ...\n",
145 len, inet_ntoa(*addr), ntohs(port));
146
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200147 out.sin_family = AF_INET;
148 out.sin_port = port;
149 memcpy(&out.sin_addr, addr, sizeof(*addr));
150
151 return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
152}
153
Philipp Maier87bd9be2017-08-22 16:35:41 +0200154/*! send RTP dummy packet (to keep NAT connection open).
155 * \param[in] endp mcgp endpoint that holds the RTP connection
156 * \param[in] conn associated RTP connection
157 * \returns bytes sent, -1 on error */
158int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200159{
160 static char buf[] = { MGCP_DUMMY_LOAD };
161 int rc;
162 int was_rtcp = 0;
163
Philipp Maier87bd9be2017-08-22 16:35:41 +0200164 OSMO_ASSERT(endp);
165 OSMO_ASSERT(conn);
166
Philipp Maierc3413882017-10-27 12:26:54 +0200167 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100168 "endpoint:0x%x sending dummy packet...\n", ENDPOINT_NUMBER(endp));
169 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x conn:%s\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200170 ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
171
172 rc = mgcp_udp_send(conn->end.rtp.fd, &conn->end.addr,
173 conn->end.rtp_port, buf, 1);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200174
175 if (rc == -1)
176 goto failed;
177
178 if (endp->tcfg->omit_rtcp)
179 return rc;
180
181 was_rtcp = 1;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200182 rc = mgcp_udp_send(conn->end.rtcp.fd, &conn->end.addr,
183 conn->end.rtcp_port, buf, 1);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200184
185 if (rc >= 0)
186 return rc;
187
188failed:
Philipp Maierc3413882017-10-27 12:26:54 +0200189 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100190 "endpoint:0x%x Failed to send dummy %s packet.\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200191 ENDPOINT_NUMBER(endp), was_rtcp ? "RTCP" : "RTP");
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200192
193 return -1;
194}
195
Philipp Maier87bd9be2017-08-22 16:35:41 +0200196/* Compute timestamp alignment error */
197static int32_t ts_alignment_error(struct mgcp_rtp_stream_state *sstate,
198 int ptime, uint32_t timestamp)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200199{
200 int32_t timestamp_delta;
201
202 if (ptime == 0)
203 return 0;
204
205 /* Align according to: T - Tlast = k * Tptime */
206 timestamp_delta = timestamp - sstate->last_timestamp;
207
208 return timestamp_delta % ptime;
209}
210
Philipp Maier87bd9be2017-08-22 16:35:41 +0200211/* Check timestamp and sequence number for plausibility */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200212static int check_rtp_timestamp(struct mgcp_endpoint *endp,
213 struct mgcp_rtp_state *state,
214 struct mgcp_rtp_stream_state *sstate,
215 struct mgcp_rtp_end *rtp_end,
216 struct sockaddr_in *addr,
217 uint16_t seq, uint32_t timestamp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200218 const char *text, int32_t * tsdelta_out)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200219{
220 int32_t tsdelta;
221 int32_t timestamp_error;
222
223 /* Not fully intialized, skip */
224 if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp)
225 return 0;
226
227 if (seq == sstate->last_seq) {
228 if (timestamp != sstate->last_timestamp) {
Philipp Maier9e1d1642018-05-09 16:26:34 +0200229 rate_ctr_inc(sstate->err_ts_ctr);
Philipp Maierc3413882017-10-27 12:26:54 +0200230 LOGP(DRTP, LOGL_ERROR,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200231 "The %s timestamp delta is != 0 but the sequence "
232 "number %d is the same, "
233 "TS offset: %d, SeqNo offset: %d "
234 "on 0x%x SSRC: %u timestamp: %u "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200235 "from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200236 text, seq,
Harald Welte33381352017-12-25 09:44:26 +0100237 state->patch.timestamp_offset, state->patch.seq_offset,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200238 ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200239 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200240 }
241 return 0;
242 }
243
244 tsdelta =
Philipp Maier87bd9be2017-08-22 16:35:41 +0200245 (int32_t)(timestamp - sstate->last_timestamp) /
246 (int16_t)(seq - sstate->last_seq);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200247
248 if (tsdelta == 0) {
249 /* Don't update *tsdelta_out */
Philipp Maierc3413882017-10-27 12:26:54 +0200250 LOGP(DRTP, LOGL_NOTICE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200251 "The %s timestamp delta is %d "
252 "on 0x%x SSRC: %u timestamp: %u "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200253 "from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200254 text, tsdelta,
255 ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200256 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200257
258 return 0;
259 }
260
261 if (sstate->last_tsdelta != tsdelta) {
262 if (sstate->last_tsdelta) {
Philipp Maierc3413882017-10-27 12:26:54 +0200263 LOGP(DRTP, LOGL_INFO,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200264 "The %s timestamp delta changes from %d to %d "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200265 "on 0x%x SSRC: %u timestamp: %u from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200266 text, sstate->last_tsdelta, tsdelta,
267 ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200268 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200269 }
270 }
271
272 if (tsdelta_out)
273 *tsdelta_out = tsdelta;
274
275 timestamp_error =
Philipp Maier87bd9be2017-08-22 16:35:41 +0200276 ts_alignment_error(sstate, state->packet_duration, timestamp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200277
278 if (timestamp_error) {
Philipp Maier9e1d1642018-05-09 16:26:34 +0200279 rate_ctr_inc(sstate->err_ts_ctr);
Philipp Maierc3413882017-10-27 12:26:54 +0200280 LOGP(DRTP, LOGL_NOTICE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200281 "The %s timestamp has an alignment error of %d "
282 "on 0x%x SSRC: %u "
283 "SeqNo delta: %d, TS delta: %d, dTS/dSeq: %d "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200284 "from %s:%d. ptime: %d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200285 text, timestamp_error,
286 ENDPOINT_NUMBER(endp), sstate->ssrc,
287 (int16_t)(seq - sstate->last_seq),
288 (int32_t)(timestamp - sstate->last_timestamp),
289 tsdelta,
290 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200291 state->packet_duration);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200292 }
293 return 1;
294}
295
296/* Set the timestamp offset according to the packet duration. */
297static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
298 struct mgcp_rtp_state *state,
299 struct mgcp_rtp_end *rtp_end,
300 struct sockaddr_in *addr,
301 int16_t delta_seq, uint32_t in_timestamp)
302{
303 int32_t tsdelta = state->packet_duration;
304 int timestamp_offset;
305 uint32_t out_timestamp;
306
307 if (tsdelta == 0) {
308 tsdelta = state->out_stream.last_tsdelta;
309 if (tsdelta != 0) {
Philipp Maierc3413882017-10-27 12:26:54 +0200310 LOGP(DRTP, LOGL_NOTICE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200311 "A fixed packet duration is not available on 0x%x, "
312 "using last output timestamp delta instead: %d "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200313 "from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200314 ENDPOINT_NUMBER(endp), tsdelta,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200315 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200316 } else {
Philipp Maierbc0346e2018-06-07 09:52:16 +0200317 tsdelta = rtp_end->codec->rate * 20 / 1000;
Philipp Maierc3413882017-10-27 12:26:54 +0200318 LOGP(DRTP, LOGL_NOTICE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200319 "Fixed packet duration and last timestamp delta "
320 "are not available on 0x%x, "
321 "using fixed 20ms instead: %d "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200322 "from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200323 ENDPOINT_NUMBER(endp), tsdelta,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200324 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200325 }
326 }
327
328 out_timestamp = state->out_stream.last_timestamp + delta_seq * tsdelta;
329 timestamp_offset = out_timestamp - in_timestamp;
330
Harald Welte33381352017-12-25 09:44:26 +0100331 if (state->patch.timestamp_offset != timestamp_offset) {
332 state->patch.timestamp_offset = timestamp_offset;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200333
Philipp Maierc3413882017-10-27 12:26:54 +0200334 LOGP(DRTP, LOGL_NOTICE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200335 "Timestamp offset change on 0x%x SSRC: %u "
336 "SeqNo delta: %d, TS offset: %d, "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200337 "from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200338 ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
Harald Welte33381352017-12-25 09:44:26 +0100339 delta_seq, state->patch.timestamp_offset,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200340 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200341 }
342
343 return timestamp_offset;
344}
345
346/* Set the timestamp offset according to the packet duration. */
347static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
348 struct mgcp_rtp_state *state,
349 struct mgcp_rtp_end *rtp_end,
350 struct sockaddr_in *addr,
351 uint32_t timestamp)
352{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200353 int ts_error = 0;
354 int ts_check = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200355 int ptime = state->packet_duration;
356
357 /* Align according to: T + Toffs - Tlast = k * Tptime */
358
Philipp Maier87bd9be2017-08-22 16:35:41 +0200359 ts_error = ts_alignment_error(&state->out_stream, ptime,
Harald Welte33381352017-12-25 09:44:26 +0100360 timestamp + state->patch.timestamp_offset);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200361
Philipp Maier87bd9be2017-08-22 16:35:41 +0200362 /* If there is an alignment error, we have to compensate it */
363 if (ts_error) {
Harald Welte33381352017-12-25 09:44:26 +0100364 state->patch.timestamp_offset += ptime - ts_error;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200365
Philipp Maierc3413882017-10-27 12:26:54 +0200366 LOGP(DRTP, LOGL_NOTICE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200367 "Corrected timestamp alignment error of %d on 0x%x SSRC: %u "
368 "new TS offset: %d, "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200369 "from %s:%d\n",
370 ts_error,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200371 ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
Harald Welte33381352017-12-25 09:44:26 +0100372 state->patch.timestamp_offset, inet_ntoa(addr->sin_addr),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200373 ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200374 }
375
Philipp Maier87bd9be2017-08-22 16:35:41 +0200376 /* Check we really managed to compensate the timestamp
377 * offset. There should not be any remaining error, failing
Harald Welte1d1b98f2017-12-25 10:03:40 +0100378 * here would point to a serous problem with the alignment
379 * error computation function */
Philipp Maier87bd9be2017-08-22 16:35:41 +0200380 ts_check = ts_alignment_error(&state->out_stream, ptime,
Harald Welte33381352017-12-25 09:44:26 +0100381 timestamp + state->patch.timestamp_offset);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200382 OSMO_ASSERT(ts_check == 0);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200383
Philipp Maier87bd9be2017-08-22 16:35:41 +0200384 /* Return alignment error before compensation */
385 return ts_error;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200386}
387
Philipp Maier87bd9be2017-08-22 16:35:41 +0200388/*! dummy callback to disable transcoding (see also cfg->rtp_processing_cb).
389 * \param[in] associated endpoint
390 * \param[in] destination RTP end
391 * \param[in,out] pointer to buffer with voice data
392 * \param[in] voice data length
Harald Welte1d1b98f2017-12-25 10:03:40 +0100393 * \param[in] maximum size of caller provided voice data buffer
Philipp Maier87bd9be2017-08-22 16:35:41 +0200394 * \returns ignores input parameters, return always 0 */
395int mgcp_rtp_processing_default(struct mgcp_endpoint *endp,
396 struct mgcp_rtp_end *dst_end,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200397 char *data, int *len, int buf_size)
398{
Philipp Maier230e4fc2017-11-28 09:38:45 +0100399 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x transcoding disabled\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200400 ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200401 return 0;
402}
403
Philipp Maier87bd9be2017-08-22 16:35:41 +0200404/*! dummy callback to disable transcoding (see also cfg->setup_rtp_processing_cb).
405 * \param[in] associated endpoint
Philipp Maieracc10352018-07-19 18:07:57 +0200406 * \param[in] destination RTP connnection
407 * \param[in] source RTP connection
Philipp Maier87bd9be2017-08-22 16:35:41 +0200408 * \returns ignores input parameters, return always 0 */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200409int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
Philipp Maieracc10352018-07-19 18:07:57 +0200410 struct mgcp_conn_rtp *conn_dst,
411 struct mgcp_conn_rtp *conn_src)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200412{
Philipp Maier230e4fc2017-11-28 09:38:45 +0100413 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x transcoding disabled\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200414 ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200415 return 0;
416}
417
418void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
419 int *payload_type,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200420 const char **audio_name,
421 const char **fmtp_extra,
422 struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200423{
Philipp Maierc3413882017-10-27 12:26:54 +0200424 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100425 "endpoint:0x%x conn:%s using format defaults\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200426 ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
427
Philipp Maierbc0346e2018-06-07 09:52:16 +0200428 *payload_type = conn->end.codec->payload_type;
429 *audio_name = conn->end.codec->audio_name;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200430 *fmtp_extra = conn->end.fmtp_extra;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200431}
432
Philipp Maier87bd9be2017-08-22 16:35:41 +0200433void mgcp_rtp_annex_count(struct mgcp_endpoint *endp,
434 struct mgcp_rtp_state *state, const uint16_t seq,
435 const int32_t transit, const uint32_t ssrc)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200436{
437 int32_t d;
438
439 /* initialize or re-initialize */
Harald Welte49e3d5a2017-12-25 09:47:57 +0100440 if (!state->stats.initialized || state->stats.ssrc != ssrc) {
441 state->stats.initialized = 1;
442 state->stats.base_seq = seq;
443 state->stats.max_seq = seq - 1;
444 state->stats.ssrc = ssrc;
445 state->stats.jitter = 0;
446 state->stats.transit = transit;
447 state->stats.cycles = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200448 } else {
449 uint16_t udelta;
450
Philipp Maier87bd9be2017-08-22 16:35:41 +0200451 /* The below takes the shape of the validation of
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200452 * Appendix A. Check if there is something weird with
453 * the sequence number, otherwise check for a wrap
454 * around in the sequence number.
455 * It can't wrap during the initialization so let's
456 * skip it here. The Appendix A probably doesn't have
Philipp Maier87bd9be2017-08-22 16:35:41 +0200457 * this issue because of the probation. */
Harald Welte49e3d5a2017-12-25 09:47:57 +0100458 udelta = seq - state->stats.max_seq;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200459 if (udelta < RTP_MAX_DROPOUT) {
Harald Welte49e3d5a2017-12-25 09:47:57 +0100460 if (seq < state->stats.max_seq)
461 state->stats.cycles += RTP_SEQ_MOD;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200462 } else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
Philipp Maierc3413882017-10-27 12:26:54 +0200463 LOGP(DRTP, LOGL_NOTICE,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200464 "RTP seqno made a very large jump on 0x%x delta: %u\n",
465 ENDPOINT_NUMBER(endp), udelta);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200466 }
467 }
468
Philipp Maier87bd9be2017-08-22 16:35:41 +0200469 /* Calculate the jitter between the two packages. The TS should be
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200470 * taken closer to the read function. This was taken from the
471 * Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate
Philipp Maier87bd9be2017-08-22 16:35:41 +0200472 * resolution. */
Harald Welte49e3d5a2017-12-25 09:47:57 +0100473 d = transit - state->stats.transit;
474 state->stats.transit = transit;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200475 if (d < 0)
476 d = -d;
Harald Welte49e3d5a2017-12-25 09:47:57 +0100477 state->stats.jitter += d - ((state->stats.jitter + 8) >> 4);
478 state->stats.max_seq = seq;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200479}
480
Philipp Maier6931f9a2018-07-26 09:29:31 +0200481/* There may be different payload type numbers negotiated for two connections.
482 * Patch the payload type of an RTP packet so that it uses the payload type
483 * that is valid for the destination connection (conn_dst) */
484static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_src,
485 struct mgcp_conn_rtp *conn_dst, char *data, int len)
486{
487 struct rtp_hdr *rtp_hdr;
488 uint8_t pt_in;
489 int pt_out;
490
491 OSMO_ASSERT(len >= sizeof(struct rtp_hdr));
492 rtp_hdr = (struct rtp_hdr *)data;
493
494 pt_in = rtp_hdr->payload_type;
495 pt_out = mgcp_codec_pt_translate(conn_src, conn_dst, pt_in);
496 if (pt_out < 0)
497 return -EINVAL;
498
499 rtp_hdr->payload_type = (uint8_t) pt_out;
500 return 0;
501}
502
Philipp Maier87bd9be2017-08-22 16:35:41 +0200503/* The RFC 3550 Appendix A assumes there are multiple sources but
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200504 * some of the supported endpoints (e.g. the nanoBTS) can only handle
505 * one source and this code will patch RTP header to appear as if there
506 * is only one source.
507 * There is also no probation period for new sources. Every RTP header
Philipp Maier87bd9be2017-08-22 16:35:41 +0200508 * we receive will be seen as a switch in streams. */
509void mgcp_patch_and_count(struct mgcp_endpoint *endp,
510 struct mgcp_rtp_state *state,
511 struct mgcp_rtp_end *rtp_end,
512 struct sockaddr_in *addr, char *data, int len)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200513{
514 uint32_t arrival_time;
515 int32_t transit;
516 uint16_t seq;
517 uint32_t timestamp, ssrc;
518 struct rtp_hdr *rtp_hdr;
Philipp Maierbc0346e2018-06-07 09:52:16 +0200519 int payload = rtp_end->codec->payload_type;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200520
521 if (len < sizeof(*rtp_hdr))
522 return;
523
Philipp Maier87bd9be2017-08-22 16:35:41 +0200524 rtp_hdr = (struct rtp_hdr *)data;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200525 seq = ntohs(rtp_hdr->sequence);
526 timestamp = ntohl(rtp_hdr->timestamp);
Philipp Maierbc0346e2018-06-07 09:52:16 +0200527 arrival_time = get_current_ts(rtp_end->codec->rate);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200528 ssrc = ntohl(rtp_hdr->ssrc);
529 transit = arrival_time - timestamp;
530
531 mgcp_rtp_annex_count(endp, state, seq, transit, ssrc);
532
533 if (!state->initialized) {
534 state->initialized = 1;
535 state->in_stream.last_seq = seq - 1;
Harald Welte33381352017-12-25 09:44:26 +0100536 state->in_stream.ssrc = state->patch.orig_ssrc = ssrc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200537 state->in_stream.last_tsdelta = 0;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200538 state->packet_duration =
539 mgcp_rtp_packet_duration(endp, rtp_end);
Philipp Maier0ec1d4e2018-05-16 11:09:42 +0200540 state->out_stream.last_seq = seq - 1;
541 state->out_stream.ssrc = state->patch.orig_ssrc = ssrc;
542 state->out_stream.last_tsdelta = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200543 state->out_stream.last_timestamp = timestamp;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200544 state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */
Philipp Maierc3413882017-10-27 12:26:54 +0200545 LOGP(DRTP, LOGL_INFO,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100546 "endpoint:0x%x initializing stream, SSRC: %u timestamp: %u "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200547 "pkt-duration: %d, from %s:%d\n",
548 ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
Harald Welte33381352017-12-25 09:44:26 +0100549 state->patch.seq_offset, state->packet_duration,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200550 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200551 if (state->packet_duration == 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +0200552 state->packet_duration =
Philipp Maierbc0346e2018-06-07 09:52:16 +0200553 rtp_end->codec->rate * 20 / 1000;
Philipp Maierc3413882017-10-27 12:26:54 +0200554 LOGP(DRTP, LOGL_NOTICE,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100555 "endpoint:0x%x fixed packet duration is not available, "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200556 "using fixed 20ms instead: %d from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200557 ENDPOINT_NUMBER(endp), state->packet_duration,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200558 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200559 }
560 } else if (state->in_stream.ssrc != ssrc) {
Philipp Maierc3413882017-10-27 12:26:54 +0200561 LOGP(DRTP, LOGL_NOTICE,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100562 "endpoint:0x%x SSRC changed: %u -> %u "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200563 "from %s:%d\n",
564 ENDPOINT_NUMBER(endp),
565 state->in_stream.ssrc, rtp_hdr->ssrc,
566 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200567
568 state->in_stream.ssrc = ssrc;
569 if (rtp_end->force_constant_ssrc) {
570 int16_t delta_seq;
571
572 /* Always increment seqno by 1 */
Harald Welte33381352017-12-25 09:44:26 +0100573 state->patch.seq_offset =
Philipp Maier87bd9be2017-08-22 16:35:41 +0200574 (state->out_stream.last_seq + 1) - seq;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200575
576 /* Estimate number of packets that would have been sent */
577 delta_seq =
Philipp Maier87bd9be2017-08-22 16:35:41 +0200578 (arrival_time - state->in_stream.last_arrival_time
579 + state->packet_duration / 2) /
580 state->packet_duration;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200581
582 adjust_rtp_timestamp_offset(endp, state, rtp_end, addr,
583 delta_seq, timestamp);
584
Harald Welte33381352017-12-25 09:44:26 +0100585 state->patch.patch_ssrc = 1;
586 ssrc = state->patch.orig_ssrc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200587 if (rtp_end->force_constant_ssrc != -1)
588 rtp_end->force_constant_ssrc -= 1;
589
Philipp Maierc3413882017-10-27 12:26:54 +0200590 LOGP(DRTP, LOGL_NOTICE,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100591 "endpoint:0x%x SSRC patching enabled, SSRC: %u "
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200592 "SeqNo offset: %d, TS offset: %d "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200593 "from %s:%d\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200594 ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
Harald Welte33381352017-12-25 09:44:26 +0100595 state->patch.seq_offset, state->patch.timestamp_offset,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200596 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200597 }
598
599 state->in_stream.last_tsdelta = 0;
600 } else {
601 /* Compute current per-packet timestamp delta */
Philipp Maier87bd9be2017-08-22 16:35:41 +0200602 check_rtp_timestamp(endp, state, &state->in_stream, rtp_end,
603 addr, seq, timestamp, "input",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200604 &state->in_stream.last_tsdelta);
605
Harald Welte33381352017-12-25 09:44:26 +0100606 if (state->patch.patch_ssrc)
607 ssrc = state->patch.orig_ssrc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200608 }
609
610 /* Save before patching */
611 state->in_stream.last_timestamp = timestamp;
612 state->in_stream.last_seq = seq;
613 state->in_stream.last_arrival_time = arrival_time;
614
615 if (rtp_end->force_aligned_timing &&
616 state->out_stream.ssrc == ssrc && state->packet_duration)
617 /* Align the timestamp offset */
Philipp Maier87bd9be2017-08-22 16:35:41 +0200618 align_rtp_timestamp_offset(endp, state, rtp_end, addr,
619 timestamp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200620
621 /* Store the updated SSRC back to the packet */
Harald Welte33381352017-12-25 09:44:26 +0100622 if (state->patch.patch_ssrc)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200623 rtp_hdr->ssrc = htonl(ssrc);
624
625 /* Apply the offset and store it back to the packet.
626 * This won't change anything if the offset is 0, so the conditional is
627 * omitted. */
Harald Welte33381352017-12-25 09:44:26 +0100628 seq += state->patch.seq_offset;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200629 rtp_hdr->sequence = htons(seq);
Harald Welte33381352017-12-25 09:44:26 +0100630 timestamp += state->patch.timestamp_offset;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200631 rtp_hdr->timestamp = htonl(timestamp);
632
633 /* Check again, whether the timestamps are still valid */
634 if (state->out_stream.ssrc == ssrc)
635 check_rtp_timestamp(endp, state, &state->out_stream, rtp_end,
636 addr, seq, timestamp, "output",
637 &state->out_stream.last_tsdelta);
638
639 /* Save output values */
640 state->out_stream.last_seq = seq;
641 state->out_stream.last_timestamp = timestamp;
642 state->out_stream.ssrc = ssrc;
643
644 if (payload < 0)
645 return;
646
647#if 0
Philipp Maierc3413882017-10-27 12:26:54 +0200648 DEBUGP(DRTP,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100649 "endpoint:0x%x payload hdr payload %u -> endp payload %u\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200650 ENDPOINT_NUMBER(endp), rtp_hdr->payload_type, payload);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200651 rtp_hdr->payload_type = payload;
652#endif
653}
654
Philipp Maier9fc8a022019-02-20 12:26:52 +0100655/* There are different dialects used to format and transfer voice data. When
656 * the receiving end expects GSM-HR data to be formated after RFC 5993, this
657 * function is used to convert between RFC 5993 and TS 101318, which we normally
658 * use. */
659static void rfc5993_hr_convert(struct mgcp_endpoint *endp, char *data, int *len)
660{
661 /* NOTE: *data has an overall length of RTP_BUF_SIZE, so there is
662 * plenty of space available to store the slightly larger, converted
663 * data */
664
665 struct rtp_hdr *rtp_hdr;
666
667 OSMO_ASSERT(*len >= sizeof(struct rtp_hdr));
668 rtp_hdr = (struct rtp_hdr *)data;
669
670 if (*len == GSM_HR_BYTES + sizeof(struct rtp_hdr)) {
671 /* TS 101318 encoding => RFC 5993 encoding */
672 memmove(rtp_hdr->data + 1, rtp_hdr->data, GSM_HR_BYTES);
673 rtp_hdr->data[0] = 0x00;
674 (*len) += 1;
675
676 } else if (*len == GSM_HR_BYTES + sizeof(struct rtp_hdr) + 1) {
677 /* RFC 5993 encoding => TS 101318 encoding */
678 memmove(rtp_hdr->data, rtp_hdr->data + 1, GSM_HR_BYTES);
679 (*len) -= 1;
680 } else {
681 /* It is possible that multiple payloads occur in one RTP
682 * packet. This is not supported yet. */
683 LOGP(DRTP, LOGL_ERROR,
684 "endpoint:0x%x cannot figure out how to convert RTP packet\n",
685 ENDPOINT_NUMBER(endp));
686 }
687}
688
Philipp Maier87bd9be2017-08-22 16:35:41 +0200689/* Forward data to a debug tap. This is debug function that is intended for
690 * debugging the voice traffic with tools like gstreamer */
Philipp Maiere6f172d2017-11-07 12:00:01 +0100691static void forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf,
692 int len)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200693{
Philipp Maiere6f172d2017-11-07 12:00:01 +0100694 int rc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200695
Philipp Maiere6f172d2017-11-07 12:00:01 +0100696 if (!tap->enabled)
697 return;
698
699 rc = sendto(fd, buf, len, 0, (struct sockaddr *)&tap->forward,
700 sizeof(tap->forward));
701
702 if (rc < 0)
703 LOGP(DRTP, LOGL_ERROR,
704 "Forwarding tapped (debug) voice data failed.\n");
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200705}
706
Philipp Maier87bd9be2017-08-22 16:35:41 +0200707/*! Send RTP/RTCP data to a specified destination connection.
708 * \param[in] endp associated endpoint (for configuration, logging)
709 * \param[in] is_rtp flag to specify if the packet is of type RTP or RTCP
710 * \param[in] spoofed source address (set to NULL to disable)
711 * \param[in] buf buffer that contains the RTP/RTCP data
712 * \param[in] len length of the buffer that contains the RTP/RTCP data
713 * \param[in] conn_src associated source connection
714 * \param[in] conn_dst associated destination connection
715 * \returns 0 on success, -1 on ERROR */
716int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
717 char *buf, int len, struct mgcp_conn_rtp *conn_src,
718 struct mgcp_conn_rtp *conn_dst)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200719{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200720 /*! When no destination connection is available (e.g. when only one
721 * connection in loopback mode exists), then the source connection
722 * shall be specified as destination connection */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200723
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200724 struct mgcp_trunk_config *tcfg = endp->tcfg;
725 struct mgcp_rtp_end *rtp_end;
726 struct mgcp_rtp_state *rtp_state;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200727 char *dest_name;
Philipp Maier6931f9a2018-07-26 09:29:31 +0200728 int rc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200729
Philipp Maier87bd9be2017-08-22 16:35:41 +0200730 OSMO_ASSERT(conn_src);
731 OSMO_ASSERT(conn_dst);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200732
Philipp Maier87bd9be2017-08-22 16:35:41 +0200733 if (is_rtp) {
Philipp Maierc3413882017-10-27 12:26:54 +0200734 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100735 "endpoint:0x%x delivering RTP packet...\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200736 ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200737 } else {
Philipp Maierc3413882017-10-27 12:26:54 +0200738 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100739 "endpoint:0x%x delivering RTCP packet...\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200740 ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200741 }
Philipp Maier87bd9be2017-08-22 16:35:41 +0200742
Philipp Maierc3413882017-10-27 12:26:54 +0200743 LOGP(DRTP, LOGL_DEBUG,
Neels Hofmeyr7066af82018-07-23 18:28:36 +0200744 "endpoint:0x%x loop:%d, mode:%d%s\n",
745 ENDPOINT_NUMBER(endp), tcfg->audio_loop, conn_src->conn->mode,
746 conn_src->conn->mode == MGCP_CONN_LOOPBACK ? " (loopback)" : "");
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200747
Philipp Maier6931f9a2018-07-26 09:29:31 +0200748 /* FIXME: It is legal that the payload type on the egress connection is
749 * different from the payload type that has been negotiated on the
750 * ingress connection. Essentially the codecs are the same so we can
751 * match them and patch the payload type. However, if we can not find
752 * the codec pendant (everything ist equal except the PT), we are of
753 * course unable to patch the payload type. A situation like this
754 * should not occur if transcoding is consequently avoided. Until
755 * we have transcoding support in osmo-mgw we can not resolve this. */
Philipp Maierda895b12018-08-03 12:16:37 +0200756 if (is_rtp) {
757 rc = mgcp_patch_pt(conn_src, conn_dst, buf, len);
758 if (rc < 0) {
759 LOGP(DRTP, LOGL_ERROR,
760 "endpoint:0x%x can not patch PT because no suitable egress codec was found.\n",
761 ENDPOINT_NUMBER(endp));
762 }
Philipp Maier6931f9a2018-07-26 09:29:31 +0200763 }
764
Philipp Maier87bd9be2017-08-22 16:35:41 +0200765 /* Note: In case of loopback configuration, both, the source and the
766 * destination will point to the same connection. */
767 rtp_end = &conn_dst->end;
768 rtp_state = &conn_src->state;
769 dest_name = conn_dst->conn->name;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200770
771 if (!rtp_end->output_enabled) {
Philipp Maiercede2a42018-07-03 14:14:21 +0200772 rate_ctr_inc(&conn_dst->rate_ctr_group->ctr[RTP_DROPPED_PACKETS_CTR]);
Philipp Maierc3413882017-10-27 12:26:54 +0200773 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100774 "endpoint:0x%x output disabled, drop to %s %s "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200775 "rtp_port:%u rtcp_port:%u\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200776 ENDPOINT_NUMBER(endp),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200777 dest_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200778 inet_ntoa(rtp_end->addr),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200779 ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200780 );
781 } else if (is_rtp) {
782 int cont;
783 int nbytes = 0;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200784 int buflen = len;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200785 do {
Philipp Maier87bd9be2017-08-22 16:35:41 +0200786 /* Run transcoder */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200787 cont = endp->cfg->rtp_processing_cb(endp, rtp_end,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200788 buf, &buflen,
789 RTP_BUF_SIZE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200790 if (cont < 0)
791 break;
792
Philipp Maier87bd9be2017-08-22 16:35:41 +0200793 if (addr)
794 mgcp_patch_and_count(endp, rtp_state, rtp_end,
795 addr, buf, buflen);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100796
797 if (rtp_end->rfc5993_hr_convert
798 && strcmp(conn_src->end.codec->subtype_name,
799 "GSM-HR-08") == 0)
800 rfc5993_hr_convert(endp, buf, &buflen);
801
Philipp Maierc3413882017-10-27 12:26:54 +0200802 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100803 "endpoint:0x%x process/send to %s %s "
Philipp Maier87bd9be2017-08-22 16:35:41 +0200804 "rtp_port:%u rtcp_port:%u\n",
805 ENDPOINT_NUMBER(endp), dest_name,
806 inet_ntoa(rtp_end->addr), ntohs(rtp_end->rtp_port),
807 ntohs(rtp_end->rtcp_port)
808 );
809
810 /* Forward a copy of the RTP data to a debug ip/port */
811 forward_data(rtp_end->rtp.fd, &conn_src->tap_out,
812 buf, buflen);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200813
814 /* FIXME: HACK HACK HACK. See OS#2459.
815 * The ip.access nano3G needs the first RTP payload's first two bytes to read hex
816 * 'e400', or it will reject the RAB assignment. It seems to not harm other femto
817 * cells (as long as we patch only the first RTP payload in each stream).
818 */
Neels Hofmeyr35a38292018-07-23 18:29:04 +0200819 if (!rtp_state->patched_first_rtp_payload
820 && conn_src->conn->mode == MGCP_CONN_LOOPBACK) {
Philipp Maier87bd9be2017-08-22 16:35:41 +0200821 uint8_t *data = (uint8_t *) & buf[12];
Neels Hofmeyr35a38292018-07-23 18:29:04 +0200822 if (data[0] == 0xe0) {
823 data[0] = 0xe4;
824 data[1] = 0x00;
825 rtp_state->patched_first_rtp_payload = true;
826 LOGP(DRTP, LOGL_DEBUG,
827 "endpoint:0x%x Patching over first two bytes"
828 " to fake an IuUP Initialization Ack\n",
829 ENDPOINT_NUMBER(endp));
830 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200831 }
832
Philipp Maier87bd9be2017-08-22 16:35:41 +0200833 len = mgcp_udp_send(rtp_end->rtp.fd,
834 &rtp_end->addr,
835 rtp_end->rtp_port, buf, buflen);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200836
Philipp Maier87bd9be2017-08-22 16:35:41 +0200837 if (len <= 0)
838 return len;
839
Philipp Maiercede2a42018-07-03 14:14:21 +0200840 rate_ctr_inc(&conn_dst->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR]);
841 rate_ctr_add(&conn_dst->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR], len);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200842
843 nbytes += len;
844 buflen = cont;
845 } while (buflen > 0);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200846 return nbytes;
847 } else if (!tcfg->omit_rtcp) {
Philipp Maierc3413882017-10-27 12:26:54 +0200848 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100849 "endpoint:0x%x send to %s %s rtp_port:%u rtcp_port:%u\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200850 ENDPOINT_NUMBER(endp),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200851 dest_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200852 inet_ntoa(rtp_end->addr),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200853 ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200854 );
855
Philipp Maier87bd9be2017-08-22 16:35:41 +0200856 len = mgcp_udp_send(rtp_end->rtcp.fd,
857 &rtp_end->addr,
858 rtp_end->rtcp_port, buf, len);
859
Philipp Maiercede2a42018-07-03 14:14:21 +0200860 rate_ctr_inc(&conn_dst->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR]);
861 rate_ctr_add(&conn_dst->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR], len);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200862
863 return len;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200864 }
865
866 return 0;
867}
868
Philipp Maier87bd9be2017-08-22 16:35:41 +0200869/* Helper function for mgcp_recv(),
870 Receive one RTP Packet + Originating address from file descriptor */
871static int receive_from(struct mgcp_endpoint *endp, int fd,
872 struct sockaddr_in *addr, char *buf, int bufsize)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200873{
874 int rc;
875 socklen_t slen = sizeof(*addr);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200876 struct sockaddr_in addr_sink;
877 char buf_sink[RTP_BUF_SIZE];
878 bool tossed = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200879
Philipp Maier87bd9be2017-08-22 16:35:41 +0200880 if (!addr)
881 addr = &addr_sink;
882 if (!buf) {
883 tossed = true;
884 buf = buf_sink;
885 bufsize = sizeof(buf_sink);
886 }
887
888 rc = recvfrom(fd, buf, bufsize, 0, (struct sockaddr *)addr, &slen);
889
Philipp Maierc3413882017-10-27 12:26:54 +0200890 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200891 "receiving %u bytes length packet from %s:%u ...\n",
892 rc, inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
893
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200894 if (rc < 0) {
Philipp Maierc3413882017-10-27 12:26:54 +0200895 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100896 "endpoint:0x%x failed to receive packet, errno: %d/%s\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200897 ENDPOINT_NUMBER(endp), errno, strerror(errno));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200898 return -1;
899 }
900
Philipp Maier87bd9be2017-08-22 16:35:41 +0200901 if (tossed) {
Philipp Maier230e4fc2017-11-28 09:38:45 +0100902 LOGP(DRTP, LOGL_ERROR, "endpoint:0x%x packet tossed\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200903 ENDPOINT_NUMBER(endp));
904 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200905
906 return rc;
907}
908
Philipp Maier87bd9be2017-08-22 16:35:41 +0200909/* Check if the origin (addr) matches the address/port data of the RTP
910 * connections. */
911static int check_rtp_origin(struct mgcp_conn_rtp *conn,
912 struct sockaddr_in *addr)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200913{
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200914 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200915 endp = conn->conn->endp;
Neels Hofmeyr0063ca22018-07-23 18:12:16 +0200916
Harald Weltec26b6652018-10-21 12:01:04 +0200917 if (conn->end.addr.s_addr == 0) {
Neels Hofmeyrefd645e2018-09-10 13:14:50 +0200918 switch (conn->conn->mode) {
919 case MGCP_CONN_LOOPBACK:
920 /* HACK: for IuUP, we want to reply with an IuUP Initialization ACK upon the first RTP
921 * message received. We currently hackishly accomplish that by putting the endpoint in
922 * loopback mode and patching over the looped back RTP message to make it look like an
923 * ack. We don't know the femto cell's IP address and port until the RAB Assignment
924 * Response is received, but the nano3G expects an IuUP Initialization Ack before it even
925 * sends the RAB Assignment Response. Hence, if the remote address is 0.0.0.0 and the
926 * MGCP port is in loopback mode, allow looping back the packet to any source. */
927 LOGP(DRTP, LOGL_ERROR,
928 "endpoint:0x%x In loopback mode and remote address not set:"
929 " allowing data from address: %s\n",
930 ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr));
931 return 0;
932
933 default:
934 /* Receiving early media before the endpoint is configured. Instead of logging
935 * this as an error that occurs on every call, keep it more low profile to not
936 * confuse humans with expected errors. */
937 LOGP(DRTP, LOGL_INFO,
938 "endpoint:0x%x I:%s Rx RTP from %s, but remote address not set:"
939 " dropping early media\n",
940 ENDPOINT_NUMBER(endp), conn->conn->id, inet_ntoa(addr->sin_addr));
941 return -1;
942 }
Neels Hofmeyr0063ca22018-07-23 18:12:16 +0200943 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200944
Philipp Maier87bd9be2017-08-22 16:35:41 +0200945 /* Note: Check if the inbound RTP data comes from the same host to
946 * which we send our outgoing RTP traffic. */
Harald Weltec26b6652018-10-21 12:01:04 +0200947 if (conn->end.addr.s_addr != addr->sin_addr.s_addr) {
Philipp Maierc3413882017-10-27 12:26:54 +0200948 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100949 "endpoint:0x%x data from wrong address: %s, ",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200950 ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr));
Philipp Maierc3413882017-10-27 12:26:54 +0200951 LOGPC(DRTP, LOGL_ERROR, "expected: %s\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200952 inet_ntoa(conn->end.addr));
Philipp Maier230e4fc2017-11-28 09:38:45 +0100953 LOGP(DRTP, LOGL_ERROR, "endpoint:0x%x packet tossed\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200954 ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200955 return -1;
956 }
957
Philipp Maier87bd9be2017-08-22 16:35:41 +0200958 /* Note: Usually the remote remote port of the data we receive will be
959 * the same as the remote port where we transmit outgoing RTP traffic
960 * to (set by MDCX). We use this to check the origin of the data for
961 * plausibility. */
962 if (conn->end.rtp_port != addr->sin_port &&
963 conn->end.rtcp_port != addr->sin_port) {
Philipp Maierc3413882017-10-27 12:26:54 +0200964 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +0100965 "endpoint:0x%x data from wrong source port: %d, ",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200966 ENDPOINT_NUMBER(endp), ntohs(addr->sin_port));
Philipp Maierc3413882017-10-27 12:26:54 +0200967 LOGPC(DRTP, LOGL_ERROR,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200968 "expected: %d for RTP or %d for RTCP\n",
969 ntohs(conn->end.rtp_port), ntohs(conn->end.rtcp_port));
Philipp Maier230e4fc2017-11-28 09:38:45 +0100970 LOGP(DRTP, LOGL_ERROR, "endpoint:0x%x packet tossed\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200971 ENDPOINT_NUMBER(endp));
972 return -1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200973 }
974
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200975 return 0;
976}
977
Philipp Maier87bd9be2017-08-22 16:35:41 +0200978/* Check the if the destination address configuration of an RTP connection
979 * makes sense */
980static int check_rtp_destin(struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200981{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200982 struct mgcp_endpoint *endp;
983 endp = conn->conn->endp;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200984
Philipp Maiere6df0e42018-05-29 14:03:06 +0200985 /* Note: it is legal to create a connection but never setting a port
986 * and IP-address for outgoing data. */
987 if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0 && conn->end.rtp_port == 0) {
988 LOGP(DRTP, LOGL_DEBUG,
Neels Hofmeyrad21a0e2018-12-12 01:16:42 +0100989 "endpoint:0x%x destination IP-address and rtp port is (not yet) known (%s:%u)\n",
990 ENDPOINT_NUMBER(endp), inet_ntoa(conn->end.addr), conn->end.rtp_port);
Philipp Maiere6df0e42018-05-29 14:03:06 +0200991 return -1;
992 }
993
Philipp Maier87bd9be2017-08-22 16:35:41 +0200994 if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0) {
Philipp Maierc3413882017-10-27 12:26:54 +0200995 LOGP(DRTP, LOGL_ERROR,
Neels Hofmeyrad21a0e2018-12-12 01:16:42 +0100996 "endpoint:0x%x destination IP-address is invalid (%s:%u)\n",
997 ENDPOINT_NUMBER(endp), inet_ntoa(conn->end.addr), conn->end.rtp_port);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200998 return -1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200999 }
Philipp Maier87bd9be2017-08-22 16:35:41 +02001000
1001 if (conn->end.rtp_port == 0) {
Philipp Maierc3413882017-10-27 12:26:54 +02001002 LOGP(DRTP, LOGL_ERROR,
Neels Hofmeyrad21a0e2018-12-12 01:16:42 +01001003 "endpoint:0x%x destination rtp port is invalid (%s:%u)\n",
1004 ENDPOINT_NUMBER(endp), inet_ntoa(conn->end.addr), conn->end.rtp_port);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001005 return -1;
1006 }
1007
1008 return 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001009}
1010
Philipp Maier4dba7692018-08-03 12:20:52 +02001011/* Do some basic checks to make sure that the RTCP packets we are going to
1012 * process are not complete garbage */
1013static int check_rtcp(char *buf, unsigned int buf_size)
1014{
1015 struct rtcp_hdr *hdr;
1016 unsigned int len;
1017 uint8_t type;
1018
1019 /* RTPC packets that are just a header without data do not make
1020 * any sense. */
1021 if (buf_size < sizeof(struct rtcp_hdr))
1022 return -EINVAL;
1023
1024 /* Make sure that the length of the received packet does not exceed
1025 * the available buffer size */
1026 hdr = (struct rtcp_hdr *)buf;
1027 len = (osmo_ntohs(hdr->length) + 1) * 4;
1028 if (len > buf_size)
1029 return -EINVAL;
1030
1031 /* Make sure we accept only packets that have a proper packet type set
1032 * See also: http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
1033 type = hdr->type;
1034 if ((type < 192 || type > 195) && (type < 200 || type > 213))
1035 return -EINVAL;
1036
1037 return 0;
1038}
1039
1040/* Do some basic checks to make sure that the RTP packets we are going to
1041 * process are not complete garbage */
1042static int check_rtp(char *buf, unsigned int buf_size)
1043{
1044 /* RTP packets that are just a header without data do not make
1045 * any sense. */
1046 if (buf_size < sizeof(struct rtp_hdr))
1047 return -EINVAL;
1048
1049 /* FIXME: Add more checks, the reason why we do not check more than
1050 * the length is because we currently handle IUUP packets as RTP
1051 * packets, so they must pass this check, if we weould be more
1052 * strict here, we would possibly break 3G. (see also FIXME note
1053 * below */
1054
1055 return 0;
1056}
1057
Philipp Maier87bd9be2017-08-22 16:35:41 +02001058/* Receive RTP data from a specified source connection and dispatch it to a
1059 * destination connection. */
1060static int mgcp_recv(int *proto, struct sockaddr_in *addr, char *buf,
1061 unsigned int buf_size, struct osmo_fd *fd)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001062{
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001063 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001064 struct mgcp_conn_rtp *conn;
1065 struct mgcp_trunk_config *tcfg;
1066 int rc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001067
Philipp Maier87bd9be2017-08-22 16:35:41 +02001068 conn = (struct mgcp_conn_rtp*) fd->data;
1069 endp = conn->conn->endp;
1070 tcfg = endp->tcfg;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001071
Philipp Maier230e4fc2017-11-28 09:38:45 +01001072 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x receiving RTP/RTCP packet...\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001073 ENDPOINT_NUMBER(endp));
1074
1075 rc = receive_from(endp, fd->fd, addr, buf, buf_size);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001076 if (rc <= 0)
1077 return -1;
Philipp Maier4dba7692018-08-03 12:20:52 +02001078
1079 /* FIXME: The way how we detect the protocol looks odd. We should look
1080 * into the packet header. Also we should introduce a packet type
1081 * MGCP_PROTO_IUUP because currently we handle IUUP packets like RTP
1082 * packets which is problematic. */
Philipp Maier87bd9be2017-08-22 16:35:41 +02001083 *proto = fd == &conn->end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001084
Philipp Maier4dba7692018-08-03 12:20:52 +02001085 if (*proto == MGCP_PROTO_RTP) {
1086 if (check_rtp(buf, rc) < 0) {
1087 LOGP(DRTP, LOGL_ERROR,
1088 "endpoint:0x%x invalid RTP packet received -- packet tossed\n",
1089 ENDPOINT_NUMBER(endp));
1090 return -1;
1091 }
1092 } else if (*proto == MGCP_PROTO_RTCP) {
1093 if (check_rtcp(buf, rc) < 0) {
1094 LOGP(DRTP, LOGL_ERROR,
1095 "endpoint:0x%x invalid RTCP packet received -- packet tossed\n",
1096 ENDPOINT_NUMBER(endp));
1097 return -1;
1098 }
1099 }
1100
Philipp Maier230e4fc2017-11-28 09:38:45 +01001101 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x ", ENDPOINT_NUMBER(endp));
Neels Hofmeyr56725632018-01-15 15:15:07 +01001102 LOGPC(DRTP, LOGL_DEBUG, "receiving from %s %s %d\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001103 conn->conn->name, inet_ntoa(addr->sin_addr),
1104 ntohs(addr->sin_port));
Philipp Maier230e4fc2017-11-28 09:38:45 +01001105 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x conn:%s\n", ENDPOINT_NUMBER(endp),
Philipp Maier87bd9be2017-08-22 16:35:41 +02001106 mgcp_conn_dump(conn->conn));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001107
Philipp Maier87bd9be2017-08-22 16:35:41 +02001108 /* Check if the origin of the RTP packet seems plausible */
1109 if (tcfg->rtp_accept_all == 0) {
1110 if (check_rtp_origin(conn, addr) != 0)
1111 return -1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001112 }
1113
Philipp Maier87bd9be2017-08-22 16:35:41 +02001114 /* Filter out dummy message */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001115 if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
Philipp Maierc3413882017-10-27 12:26:54 +02001116 LOGP(DRTP, LOGL_NOTICE,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001117 "endpoint:0x%x dummy message received\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001118 ENDPOINT_NUMBER(endp));
Philipp Maierc3413882017-10-27 12:26:54 +02001119 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001120 "endpoint:0x%x packet tossed\n", ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001121 return 0;
1122 }
1123
Philipp Maier87bd9be2017-08-22 16:35:41 +02001124 /* Increment RX statistics */
Philipp Maiercede2a42018-07-03 14:14:21 +02001125 rate_ctr_inc(&conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR]);
1126 rate_ctr_add(&conn->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR], rc);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001127
Philipp Maier87bd9be2017-08-22 16:35:41 +02001128 /* Forward a copy of the RTP data to a debug ip/port */
1129 forward_data(fd->fd, &conn->tap_in, buf, rc);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001130
Philipp Maier87bd9be2017-08-22 16:35:41 +02001131 return rc;
1132}
1133
1134/* Send RTP data. Possible options are standard RTP packet
1135 * transmission or trsmission via an osmux connection */
1136static int mgcp_send_rtp(int proto, struct sockaddr_in *addr, char *buf,
1137 unsigned int buf_size,
1138 struct mgcp_conn_rtp *conn_src,
1139 struct mgcp_conn_rtp *conn_dst)
1140{
1141 struct mgcp_endpoint *endp;
1142 endp = conn_src->conn->endp;
1143
Philipp Maier230e4fc2017-11-28 09:38:45 +01001144 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x destin conn:%s\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001145 ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn_dst->conn));
1146
1147 /* Before we try to deliver the packet, we check if the destination
1148 * port and IP-Address make sense at all. If not, we will be unable
1149 * to deliver the packet. */
1150 if (check_rtp_destin(conn_dst) != 0)
1151 return -1;
1152
1153 /* Depending on the RTP connection type, deliver the RTP packet to the
1154 * destination connection. */
1155 switch (conn_dst->type) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001156 case MGCP_RTP_DEFAULT:
Philipp Maierc3413882017-10-27 12:26:54 +02001157 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001158 "endpoint:0x%x endpoint type is MGCP_RTP_DEFAULT, "
Philipp Maier87bd9be2017-08-22 16:35:41 +02001159 "using mgcp_send() to forward data directly\n",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001160 ENDPOINT_NUMBER(endp));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001161 return mgcp_send(endp, proto == MGCP_PROTO_RTP,
1162 addr, buf, buf_size, conn_src, conn_dst);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001163 case MGCP_OSMUX_BSC_NAT:
Philipp Maier87bd9be2017-08-22 16:35:41 +02001164 case MGCP_OSMUX_BSC:
Philipp Maierc3413882017-10-27 12:26:54 +02001165 LOGP(DRTP, LOGL_DEBUG,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001166 "endpoint:0x%x endpoint type is MGCP_OSMUX_BSC_NAT, "
Philipp Maier87bd9be2017-08-22 16:35:41 +02001167 "using osmux_xfrm_to_osmux() to forward data through OSMUX\n",
1168 ENDPOINT_NUMBER(endp));
1169 return osmux_xfrm_to_osmux(buf, buf_size, conn_dst);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001170 }
1171
Philipp Maier87bd9be2017-08-22 16:35:41 +02001172 /* If the data has not been handled/forwarded until here, it will
1173 * be discarded, this should not happen, normally the MGCP type
1174 * should be properly set */
Philipp Maierc3413882017-10-27 12:26:54 +02001175 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001176 "endpoint:0x%x bad MGCP type -- data discarded!\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001177 ENDPOINT_NUMBER(endp));
1178
1179 return -1;
1180}
1181
1182/*! dispatch incoming RTP packet to opposite RTP connection.
1183 * \param[in] proto protocol (MGCP_CONN_TYPE_RTP or MGCP_CONN_TYPE_RTCP)
1184 * \param[in] addr socket address where the RTP packet has been received from
1185 * \param[in] buf buffer that hold the RTP payload
1186 * \param[in] buf_size size data length of buf
1187 * \param[in] conn originating connection
1188 * \returns 0 on success, -1 on ERROR */
1189int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
1190 unsigned int buf_size, struct mgcp_conn *conn)
1191{
1192 struct mgcp_conn *conn_dst;
1193 struct mgcp_endpoint *endp;
1194 endp = conn->endp;
1195
1196 /*! NOTE: This callback function implements the endpoint specific
1197 * dispatch bahviour of an rtp bridge/proxy endpoint. It is assumed
1198 * that the endpoint will hold only two connections. This premise
1199 * is used to determine the opposite connection (it is always the
1200 * connection that is not the originating connection). Once the
1201 * destination connection is known the RTP packet is sent via
1202 * the destination connection. */
1203
1204 /* Find a destination connection. */
1205 /* NOTE: This code path runs every time an RTP packet is received. The
1206 * function mgcp_find_dst_conn() we use to determine the detination
1207 * connection will iterate the connection list inside the endpoint.
1208 * Since list iterations are quite costly, we will figure out the
1209 * destination only once and use the optional private data pointer of
1210 * the connection to cache the destination connection pointer. */
1211 if (!conn->priv) {
1212 conn_dst = mgcp_find_dst_conn(conn);
1213 conn->priv = conn_dst;
1214 } else {
1215 conn_dst = (struct mgcp_conn *)conn->priv;
1216 }
1217
1218 /* There is no destination conn, stop here */
1219 if (!conn_dst) {
Philipp Maierc3413882017-10-27 12:26:54 +02001220 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001221 "endpoint:0x%x unable to find destination conn\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001222 ENDPOINT_NUMBER(endp));
1223 return -1;
1224 }
1225
1226 /* The destination conn is not an RTP connection */
1227 if (conn_dst->type != MGCP_CONN_TYPE_RTP) {
Philipp Maierc3413882017-10-27 12:26:54 +02001228 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001229 "endpoint:0x%x unable to find suitable destination conn\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001230 ENDPOINT_NUMBER(endp));
1231 return -1;
1232 }
1233
1234 /* Dispatch RTP packet to destination RTP connection */
1235 return mgcp_send_rtp(proto, addr, buf,
1236 buf_size, &conn->u.rtp, &conn_dst->u.rtp);
1237
1238}
1239
Philipp Maierdf5d2192018-01-24 11:39:32 +01001240/*! cleanup an endpoint when a connection on an RTP bridge endpoint is removed.
1241 * \param[in] endp Endpoint on which the connection resides.
1242 * \param[in] conn Connection that is about to be removed (ignored).
1243 * \returns 0 on success, -1 on ERROR. */
1244void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *conn)
1245{
1246 struct mgcp_conn *conn_cleanup;
1247
1248 /* In mgcp_dispatch_rtp_bridge_cb() we use conn->priv to cache the
1249 * pointer to the destination connection, so that we do not have
1250 * to go through the list every time an RTP packet arrives. To prevent
1251 * a use-after-free situation we invalidate this information for all
1252 * connections present when one connection is removed from the
1253 * endpoint. */
1254 llist_for_each_entry(conn_cleanup, &endp->conns, entry) {
1255 conn_cleanup->priv = NULL;
1256 }
1257}
1258
Philipp Maier87bd9be2017-08-22 16:35:41 +02001259/* Handle incoming RTP data from NET */
1260static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
1261{
1262 /* NOTE: This is a generic implementation. RTP data is received. In
1263 * case of loopback the data is just sent back to its origin. All
1264 * other cases implement endpoint specific behaviour (e.g. how is the
1265 * destination connection determined?). That specific behaviour is
1266 * implemented by the callback function that is called at the end of
1267 * the function */
1268
1269 struct mgcp_conn_rtp *conn_src;
1270 struct mgcp_endpoint *endp;
1271 struct sockaddr_in addr;
1272
1273 char buf[RTP_BUF_SIZE];
1274 int proto;
Philipp Maierb9694552017-11-08 16:53:57 +01001275 int len;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001276
1277 conn_src = (struct mgcp_conn_rtp *)fd->data;
1278 OSMO_ASSERT(conn_src);
1279 endp = conn_src->conn->endp;
1280 OSMO_ASSERT(endp);
1281
Philipp Maier230e4fc2017-11-28 09:38:45 +01001282 LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x source conn:%s\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001283 ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn_src->conn));
1284
1285 /* Receive packet */
Philipp Maierb9694552017-11-08 16:53:57 +01001286 len = mgcp_recv(&proto, &addr, buf, sizeof(buf), fd);
1287 if (len < 0)
Philipp Maier87bd9be2017-08-22 16:35:41 +02001288 return -1;
1289
Oliver Smithe36b7752019-01-22 16:31:36 +01001290 mgcp_conn_watchdog_kick(conn_src->conn);
1291
Philipp Maier87bd9be2017-08-22 16:35:41 +02001292 /* Check if the connection is in loopback mode, if yes, just send the
1293 * incoming data back to the origin */
1294 if (conn_src->conn->mode == MGCP_CONN_LOOPBACK) {
Philipp Maier5dbfc782017-12-12 16:20:25 +01001295 /* When we are in loopback mode, we loop back all incoming
1296 * packets back to their origin. We will use the originating
1297 * address data from the UDP packet header to patch the
1298 * outgoing address in connection on the fly */
1299 if (conn_src->end.rtp_port == 0) {
1300 conn_src->end.addr = addr.sin_addr;
1301 conn_src->end.rtp_port = addr.sin_port;
1302 }
Philipp Maier87bd9be2017-08-22 16:35:41 +02001303 return mgcp_send_rtp(proto, &addr, buf,
Philipp Maierb9694552017-11-08 16:53:57 +01001304 len, conn_src, conn_src);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001305 }
1306
1307 /* Execute endpoint specific implementation that handles the
1308 * dispatching of the RTP data */
Philipp Maierb9694552017-11-08 16:53:57 +01001309 return endp->type->dispatch_rtp_cb(proto, &addr, buf, len,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001310 conn_src->conn);
1311}
1312
1313/*! set IP Type of Service parameter.
1314 * \param[in] fd associated file descriptor
1315 * \param[in] tos dscp value
1316 * \returns 0 on success, -1 on ERROR */
1317int mgcp_set_ip_tos(int fd, int tos)
1318{
1319 int ret;
1320 ret = setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
1321
1322 if (ret < 0)
1323 return -1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001324 return 0;
1325}
1326
Philipp Maier87bd9be2017-08-22 16:35:41 +02001327/*! bind RTP port to osmo_fd.
1328 * \param[in] source_addr source (local) address to bind on
1329 * \param[in] fd associated file descriptor
1330 * \param[in] port to bind on
1331 * \returns 0 on success, -1 on ERROR */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001332int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port)
1333{
Harald Welte8890dfa2017-11-17 15:09:30 +01001334 int rc;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001335
Harald Welte8890dfa2017-11-17 15:09:30 +01001336 rc = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
1337 NULL, 0, OSMO_SOCK_F_BIND);
1338 if (rc < 0) {
Philipp Maierc3413882017-10-27 12:26:54 +02001339 LOGP(DRTP, LOGL_ERROR, "failed to bind UDP port (%s:%i).\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001340 source_addr, port);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001341 return -1;
1342 }
Harald Welte8890dfa2017-11-17 15:09:30 +01001343 fd->fd = rc;
1344 LOGP(DRTP, LOGL_DEBUG, "created socket + bound UDP port (%s:%i).\n", source_addr, port);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001345
1346 return 0;
1347}
1348
Philipp Maier87bd9be2017-08-22 16:35:41 +02001349/* Bind RTP and RTCP port (helper function for mgcp_bind_net_rtp_port()) */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001350static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001351 struct mgcp_rtp_end *rtp_end, int endpno)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001352{
Philipp Maier87bd9be2017-08-22 16:35:41 +02001353 /* NOTE: The port that is used for RTCP is the RTP port incremented by one
1354 * (e.g. RTP-Port = 16000 ==> RTCP-Port = 16001) */
1355
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001356 if (mgcp_create_bind(source_addr, &rtp_end->rtp,
1357 rtp_end->local_port) != 0) {
Philipp Maierc3413882017-10-27 12:26:54 +02001358 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001359 "endpoint:0x%x failed to create RTP port: %s:%d\n", endpno,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001360 source_addr, rtp_end->local_port);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001361 goto cleanup0;
1362 }
1363
1364 if (mgcp_create_bind(source_addr, &rtp_end->rtcp,
1365 rtp_end->local_port + 1) != 0) {
Philipp Maierc3413882017-10-27 12:26:54 +02001366 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001367 "endpoint:0x%x failed to create RTCP port: %s:%d\n", endpno,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001368 source_addr, rtp_end->local_port + 1);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001369 goto cleanup1;
1370 }
1371
Philipp Maier87bd9be2017-08-22 16:35:41 +02001372 /* Set Type of Service (DSCP-Value) as configured via VTY */
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001373 mgcp_set_ip_tos(rtp_end->rtp.fd, cfg->endp_dscp);
1374 mgcp_set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp);
1375
1376 rtp_end->rtp.when = BSC_FD_READ;
1377 if (osmo_fd_register(&rtp_end->rtp) != 0) {
Philipp Maierc3413882017-10-27 12:26:54 +02001378 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001379 "endpoint:0x%x failed to register RTP port %d\n", endpno,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001380 rtp_end->local_port);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001381 goto cleanup2;
1382 }
1383
1384 rtp_end->rtcp.when = BSC_FD_READ;
1385 if (osmo_fd_register(&rtp_end->rtcp) != 0) {
Philipp Maierc3413882017-10-27 12:26:54 +02001386 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001387 "endpoint:0x%x failed to register RTCP port %d\n", endpno,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001388 rtp_end->local_port + 1);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001389 goto cleanup3;
1390 }
1391
1392 return 0;
1393
1394cleanup3:
1395 osmo_fd_unregister(&rtp_end->rtp);
1396cleanup2:
1397 close(rtp_end->rtcp.fd);
1398 rtp_end->rtcp.fd = -1;
1399cleanup1:
1400 close(rtp_end->rtp.fd);
1401 rtp_end->rtp.fd = -1;
1402cleanup0:
1403 return -1;
1404}
1405
Philipp Maier87bd9be2017-08-22 16:35:41 +02001406/*! bind RTP port to endpoint/connection.
1407 * \param[in] endp endpoint that holds the RTP connection
1408 * \param[in] rtp_port port number to bind on
1409 * \param[in] conn associated RTP connection
1410 * \returns 0 on success, -1 on ERROR */
1411int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
1412 struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001413{
Philipp Maier87bd9be2017-08-22 16:35:41 +02001414 char name[512];
1415 struct mgcp_rtp_end *end;
Philipp Maier1cb1e382017-11-02 17:16:04 +01001416 char local_ip_addr[INET_ADDRSTRLEN];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001417
Philipp Maier01d24a32017-11-21 17:26:09 +01001418 snprintf(name, sizeof(name), "%s-%s", conn->conn->name, conn->conn->id);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001419 end = &conn->end;
1420
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001421 if (end->rtp.fd != -1 || end->rtcp.fd != -1) {
Philipp Maierc3413882017-10-27 12:26:54 +02001422 LOGP(DRTP, LOGL_ERROR,
Philipp Maier230e4fc2017-11-28 09:38:45 +01001423 "endpoint:0x%x %u was already bound on conn:%s\n",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001424 ENDPOINT_NUMBER(endp), rtp_port,
1425 mgcp_conn_dump(conn->conn));
1426
1427 /* Double bindings should never occour! Since we always allocate
1428 * connections dynamically and free them when they are not
1429 * needed anymore, there must be no previous binding leftover.
1430 * Should there be a connection bound twice, we have a serious
1431 * problem and must exit immediately! */
1432 OSMO_ASSERT(false);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001433 }
1434
1435 end->local_port = rtp_port;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001436 end->rtp.cb = rtp_data_net;
1437 end->rtp.data = conn;
1438 end->rtcp.data = conn;
1439 end->rtcp.cb = rtp_data_net;
1440
Philipp Maier1cb1e382017-11-02 17:16:04 +01001441 mgcp_get_local_addr(local_ip_addr, conn);
1442
1443 return bind_rtp(endp->cfg, local_ip_addr, end,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001444 ENDPOINT_NUMBER(endp));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001445}
1446
Philipp Maier87bd9be2017-08-22 16:35:41 +02001447/*! free allocated RTP and RTCP ports.
1448 * \param[in] end RTP end */
1449void mgcp_free_rtp_port(struct mgcp_rtp_end *end)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001450{
1451 if (end->rtp.fd != -1) {
1452 close(end->rtp.fd);
1453 end->rtp.fd = -1;
1454 osmo_fd_unregister(&end->rtp);
1455 }
1456
1457 if (end->rtcp.fd != -1) {
1458 close(end->rtcp.fd);
1459 end->rtcp.fd = -1;
1460 osmo_fd_unregister(&end->rtcp);
1461 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001462}