blob: 7c89d102196027a1ade6b87d1af2f8f33095bed5 [file] [log] [blame]
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +01001/* MGCP Private Data */
2
3/*
Holger Hans Peter Freyther38e02c52012-10-22 18:09:35 +02004 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2009-2012 by On-Waves
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +01006 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010017 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010020 *
21 */
22
Holger Hans Peter Freytherf6b61e62014-05-22 17:06:14 +020023#pragma once
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010024
Holger Hans Peter Freythera611da82015-08-14 09:24:11 +020025#include <string.h>
26
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010027#include <osmocom/core/select.h>
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010028
29#define CI_UNUSED 0
30
Holger Hans Peter Freyther98a38772010-08-03 02:27:21 +080031enum mgcp_connection_mode {
32 MGCP_CONN_NONE = 0,
33 MGCP_CONN_RECV_ONLY = 1,
34 MGCP_CONN_SEND_ONLY = 2,
35 MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
Jacob Erlbecke35fd132014-01-16 16:50:40 +010036 MGCP_CONN_LOOPBACK = 4 | MGCP_CONN_RECV_SEND,
Holger Hans Peter Freyther98a38772010-08-03 02:27:21 +080037};
38
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +010039enum mgcp_trunk_type {
40 MGCP_TRUNK_VIRTUAL,
41 MGCP_TRUNK_E1,
42};
43
Jacob Erlbeck50079a12013-11-25 12:53:28 +010044struct mgcp_rtp_stream_state {
45 uint32_t ssrc;
46 uint16_t last_seq;
47 uint32_t last_timestamp;
48 uint32_t err_ts_counter;
49 int32_t last_tsdelta;
Jacob Erlbeckeacc9b92014-01-30 21:01:35 +010050 uint32_t last_arrival_time;
Jacob Erlbeck50079a12013-11-25 12:53:28 +010051};
52
Holger Hans Peter Freyther31868922010-08-03 11:59:04 +000053struct mgcp_rtp_state {
54 int initialized;
Jacob Erlbeck58340e52013-11-29 11:20:06 +010055 int patch_ssrc;
Holger Hans Peter Freyther31868922010-08-03 11:59:04 +000056
Holger Hans Peter Freyther6aa882b2010-08-03 14:35:50 +000057 uint32_t orig_ssrc;
Holger Hans Peter Freythered3a6612012-10-22 17:08:48 +020058
Holger Hans Peter Freyther6aa882b2010-08-03 14:35:50 +000059 int seq_offset;
Holger Hans Peter Freythered3a6612012-10-22 17:08:48 +020060
Holger Hans Peter Freyther6aa882b2010-08-03 14:35:50 +000061 int32_t timestamp_offset;
Jacob Erlbeck30ce4222013-12-05 12:02:15 +010062 uint32_t packet_duration;
Jacob Erlbeck50079a12013-11-25 12:53:28 +010063
64 struct mgcp_rtp_stream_state in_stream;
65 struct mgcp_rtp_stream_state out_stream;
Holger Hans Peter Freythera5a59c92014-10-06 20:04:42 +020066
67 /* jitter and packet loss calculation */
68 int stats_initialized;
69 uint16_t stats_base_seq;
70 uint16_t stats_max_seq;
71 uint32_t stats_ssrc;
72 uint32_t stats_jitter;
73 int32_t stats_transit;
74 int stats_cycles;
Holger Hans Peter Freyther31868922010-08-03 11:59:04 +000075};
Holger Hans Peter Freyther98a38772010-08-03 02:27:21 +080076
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +020077struct mgcp_rtp_codec {
78 uint32_t rate;
79 int channels;
80 uint32_t frame_duration_num;
81 uint32_t frame_duration_den;
82
83 int payload_type;
84 char *audio_name;
85 char *subtype_name;
86};
87
Holger Hans Peter Freythera17d7012010-08-05 01:34:51 +080088struct mgcp_rtp_end {
89 /* statistics */
90 unsigned int packets;
Holger Hans Peter Freyther952f7522012-09-12 11:38:37 +020091 unsigned int octets;
Jacob Erlbeck0970bab2013-12-19 12:13:32 +010092 unsigned int dropped_packets;
Holger Hans Peter Freythera17d7012010-08-05 01:34:51 +080093 struct in_addr addr;
94
95 /* in network byte order */
96 int rtp_port, rtcp_port;
97
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +020098 /* audio codec information */
99 struct mgcp_rtp_codec codec;
Holger Hans Peter Freythere46bc272014-09-01 10:50:22 +0200100 struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200101
Holger Hans Peter Freyther5ea1bc72012-09-03 00:07:39 +0200102 /* per endpoint data */
Jacob Erlbeck72c30902013-11-25 15:23:35 +0100103 int frames_per_packet;
Jacob Erlbeckf6ec0e92013-12-04 10:30:11 +0100104 uint32_t packet_duration_ms;
Holger Hans Peter Freyther5ea1bc72012-09-03 00:07:39 +0200105 char *fmtp_extra;
Jacob Erlbeck0970bab2013-12-19 12:13:32 +0100106 int output_enabled;
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200107 int force_output_ptime;
Holger Hans Peter Freyther58ff2192010-08-05 03:08:35 +0800108
Jacob Erlbeckdb2d4312013-12-03 14:43:34 +0100109 /* RTP patching */
Jacob Erlbecke2292f32013-12-03 15:13:12 +0100110 int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
Jacob Erlbeck4bbddc62013-12-18 12:54:51 +0100111 int force_aligned_timing;
Jacob Erlbecka0d64ce2014-03-13 14:24:52 +0100112 void *rtp_process_data;
Jacob Erlbeckdb2d4312013-12-03 14:43:34 +0100113
Holger Hans Peter Freytherc4921272010-08-05 03:37:22 +0800114 /*
115 * Each end has a socket...
116 */
Pablo Neira Ayuso4db92992011-05-06 12:11:23 +0200117 struct osmo_fd rtp;
118 struct osmo_fd rtcp;
Holger Hans Peter Freytherc4921272010-08-05 03:37:22 +0800119
Holger Hans Peter Freyther58ff2192010-08-05 03:08:35 +0800120 int local_port;
Holger Hans Peter Freytherf138f912010-08-05 08:08:17 +0800121 int local_alloc;
Holger Hans Peter Freythera17d7012010-08-05 01:34:51 +0800122};
123
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800124enum {
125 MGCP_TAP_BTS_IN,
126 MGCP_TAP_BTS_OUT,
127 MGCP_TAP_NET_IN,
128 MGCP_TAP_NET_OUT,
129
130 /* last element */
131 MGCP_TAP_COUNT
132};
133
134struct mgcp_rtp_tap {
135 int enabled;
136 struct sockaddr_in forward;
137};
138
Jacob Erlbeck2c2ca4d2013-12-09 14:32:03 +0100139struct mgcp_lco {
140 char *string;
Jacob Erlbeck452c1832014-05-09 19:42:17 +0200141 char *codec;
Jacob Erlbeck2c2ca4d2013-12-09 14:32:03 +0100142 int pkt_period_min; /* time in ms */
143 int pkt_period_max; /* time in ms */
144};
145
Pablo Neira Ayuso46bd4242013-07-08 05:09:46 +0200146enum mgcp_type {
147 MGCP_RTP_DEFAULT = 0,
148 MGCP_RTP_TRANSCODED,
Pablo Neira Ayusocab6e752014-02-05 18:56:17 +0100149 MGCP_OSMUX_BSC,
150 MGCP_OSMUX_BSC_NAT,
Pablo Neira Ayuso46bd4242013-07-08 05:09:46 +0200151};
152
Pablo Neira Ayusocab6e752014-02-05 18:56:17 +0100153#include <openbsc/osmux.h>
154
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100155struct mgcp_endpoint {
Holger Hans Peter Freyther39a97e22010-08-06 18:03:11 +0800156 int allocated;
Holger Hans Peter Freyther46340132010-08-06 08:26:54 +0800157 uint32_t ci;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100158 char *callid;
Jacob Erlbeck2c2ca4d2013-12-09 14:32:03 +0100159 struct mgcp_lco local_options;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100160 int conn_mode;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800161 int orig_mode;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100162
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100163 /* backpointer */
164 struct mgcp_config *cfg;
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100165 struct mgcp_trunk_config *tcfg;
Holger Hans Peter Freytherb4b135e2010-04-07 09:37:17 +0200166
Holger Hans Peter Freythera17d7012010-08-05 01:34:51 +0800167 /* port status for bts/net */
168 struct mgcp_rtp_end bts_end;
169 struct mgcp_rtp_end net_end;
Holger Hans Peter Freyther21262332010-11-01 20:53:31 +0100170
Holger Hans Peter Freytherbd7b3c52010-11-01 21:04:54 +0100171 /*
172 * For transcoding we will send from the local_port
173 * of trans_bts and it will arrive at trans_net from
174 * where we will forward it to the network.
175 */
176 struct mgcp_rtp_end trans_bts;
Holger Hans Peter Freyther21262332010-11-01 20:53:31 +0100177 struct mgcp_rtp_end trans_net;
Pablo Neira Ayuso46bd4242013-07-08 05:09:46 +0200178 enum mgcp_type type;
Holger Hans Peter Freyther380b8712010-07-29 02:38:39 +0800179
180 /* sequence bits */
Holger Hans Peter Freyther31868922010-08-03 11:59:04 +0000181 struct mgcp_rtp_state net_state;
182 struct mgcp_rtp_state bts_state;
Holger Hans Peter Freyther6357a8e2010-08-05 12:07:00 +0000183
Holger Hans Peter Freytherce553612012-12-07 15:04:07 +0100184 /* fields for re-transmission */
185 char *last_trans;
186 char *last_response;
187
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800188 /* tap for the endpoint */
189 struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
Pablo Neira Ayusocab6e752014-02-05 18:56:17 +0100190
Pablo Neira Ayuso63650bb2014-08-26 13:31:53 +0200191 struct {
Pablo Neira Ayusob769f3c2014-08-27 17:02:52 +0200192 /* Osmux state: disabled, activating, active */
193 enum osmux_state state;
194 /* Allocated Osmux circuit ID for this endpoint */
Holger Hans Peter Freyther1afe7c72015-10-04 11:11:11 +0200195 int allocated_cid;
196 /* Used Osmux circuit ID for this endpoint */
Pablo Neira Ayusob769f3c2014-08-27 17:02:52 +0200197 uint8_t cid;
198 /* handle to batch messages */
199 struct osmux_in_handle *in;
Pablo Neira Ayuso63650bb2014-08-26 13:31:53 +0200200 /* handle to unbatch messages */
201 struct osmux_out_handle out;
Pablo Neira Ayusoee11bc02014-09-17 12:33:09 +0200202 /* statistics */
203 struct {
204 uint32_t chunks;
205 uint32_t octets;
206 } stats;
Pablo Neira Ayuso63650bb2014-08-26 13:31:53 +0200207 } osmux;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100208};
209
Holger Hans Peter Freythera611da82015-08-14 09:24:11 +0200210#define for_each_line(line, save) \
211 for (line = strline_r(NULL, &save); line;\
212 line = strline_r(NULL, &save))
213
214static inline char *strline_r(char *str, char **saveptr)
215{
216 char *result;
217
218 if (str)
219 *saveptr = str;
220
221 result = *saveptr;
222
223 if (*saveptr != NULL) {
224 *saveptr = strpbrk(*saveptr, "\r\n");
225
226 if (*saveptr != NULL) {
227 char *eos = *saveptr;
228
229 if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
230 (*saveptr)++;
231 (*saveptr)++;
232 if ((*saveptr)[0] == '\0')
233 *saveptr = NULL;
234
235 *eos = '\0';
236 }
237 }
238
239 return result;
240}
241
242
243
Holger Hans Peter Freyther38159422015-05-02 10:02:38 +0200244#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100245
Holger Hans Peter Freythera611da82015-08-14 09:24:11 +0200246/**
247 * Internal structure while parsing a request
248 */
249struct mgcp_parse_data {
250 struct mgcp_config *cfg;
251 struct mgcp_endpoint *endp;
252 char *trans;
253 char *save;
254 int found;
Holger Hans Peter Freytherf2f15912010-04-01 03:27:04 +0200255};
256
Holger Hans Peter Freytherb844b872010-04-21 21:25:13 +0800257int mgcp_send_dummy(struct mgcp_endpoint *endp);
Holger Hans Peter Freytherbb89aa12010-08-05 03:29:33 +0800258int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800259int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
Holger Hans Peter Freytherbd7b3c52010-11-01 21:04:54 +0100260int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
261int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
Holger Hans Peter Freytherf138f912010-08-05 08:08:17 +0800262int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
Holger Hans Peter Freytherf2f15912010-04-01 03:27:04 +0200263
Holger Hans Peter Freytherbd7b3c52010-11-01 21:04:54 +0100264/* For transcoding we need to manage an in and an output that are connected */
265static inline int endp_back_channel(int endpoint)
266{
267 return endpoint + 60;
268}
269
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +0100270struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
271struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
272
Jacob Erlbeckdb2d4312013-12-03 14:43:34 +0100273void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
274 struct mgcp_rtp_end *rtp);
Jacob Erlbeckf6ec0e92013-12-04 10:30:11 +0100275uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
276 struct mgcp_rtp_end *rtp);
Jacob Erlbeckdb2d4312013-12-03 14:43:34 +0100277
Holger Hans Peter Freyther38e02c52012-10-22 18:09:35 +0200278void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
279 uint32_t *expected, int *loss);
Holger Hans Peter Freythercb306a62012-10-24 21:22:47 +0200280uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
Holger Hans Peter Freyther38e02c52012-10-22 18:09:35 +0200281
Jacob Erlbecka0d64ce2014-03-13 14:24:52 +0100282/* payload processing default functions */
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200283int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
Jacob Erlbecka0d64ce2014-03-13 14:24:52 +0100284 char *data, int *len, int buf_size);
285
286int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
287 struct mgcp_rtp_end *dst_end,
288 struct mgcp_rtp_end *src_end);
289
Jacob Erlbeck168ca002014-03-17 12:40:07 +0100290void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
291 int *payload_type,
292 const char**subtype_name,
293 const char**fmtp_extra);
294
Holger Hans Peter Freyther05d481a2014-10-06 21:01:26 +0200295/* internal RTP Annex A counting */
296void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
297 const uint16_t seq, const int32_t transit,
298 const uint32_t ssrc);
299
Holger Hans Peter Freyther9be675e2015-01-21 11:39:47 +0100300int mgcp_set_ip_tos(int fd, int tos);
301
Pablo Neira Ayusocab6e752014-02-05 18:56:17 +0100302enum {
303 MGCP_DEST_NET = 0,
304 MGCP_DEST_BTS,
305};
306
Holger Hans Peter Freythera611da82015-08-14 09:24:11 +0200307
Pablo Neira Ayusocab6e752014-02-05 18:56:17 +0100308#define MGCP_DUMMY_LOAD 0x23
Holger Hans Peter Freytherbd7b3c52010-11-01 21:04:54 +0100309
Holger Hans Peter Freythera611da82015-08-14 09:24:11 +0200310
311/**
312 * SDP related information
313 */
314/* Assume audio frame length of 20ms */
315#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
316#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
317#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
318#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000
319#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
320
321#define PTYPE_UNDEFINED (-1)
Holger Hans Peter Freytheraeadf262015-08-14 15:43:06 +0200322int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
Holger Hans Peter Freythera611da82015-08-14 09:24:11 +0200323int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
324 int payload_type, const char *audio_name);
Holger Hans Peter Freythere6ed0092015-08-20 14:58:19 +0200325
326
327/**
328 * Internal network related
329 */
330static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
331{
Holger Hans Peter Freytherf3316e32015-10-12 09:37:35 +0200332 if (endp->cfg->net_ports.bind_addr)
333 return endp->cfg->net_ports.bind_addr;
Holger Hans Peter Freythere6ed0092015-08-20 14:58:19 +0200334 return endp->cfg->source_addr;
335}
336
337static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
338{
Holger Hans Peter Freytherf3316e32015-10-12 09:37:35 +0200339 if (endp->cfg->bts_ports.bind_addr)
340 return endp->cfg->bts_ports.bind_addr;
Holger Hans Peter Freythere6ed0092015-08-20 14:58:19 +0200341 return endp->cfg->source_addr;
342}