blob: 7307f3c81ca5a624b71dfbcab5f8aa62287949c2 [file] [log] [blame]
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2
3/*
4 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2009-2012 by On-Waves
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * 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
11 * (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
16 * GNU Affero General Public License for more details.
17 *
18 * 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/>.
20 *
21 */
22
Philipp Maier87bd9be2017-08-22 16:35:41 +020023#pragma once
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020024
25#include <osmocom/core/msgb.h>
26#include <osmocom/core/write_queue.h>
27#include <osmocom/core/timer.h>
28#include <osmocom/core/logging.h>
29
Neels Hofmeyr67793542017-09-08 04:25:16 +020030#include <osmocom/mgcp/mgcp_common.h>
31
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020032#include <arpa/inet.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36
Philipp Maier87bd9be2017-08-22 16:35:41 +020037#define RTP_PORT_DEFAULT_RANGE_START 16002
38#define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020039
40/**
41 * Calculate the RTP audio port for the given multiplex
42 * and the direction. This allows a semi static endpoint
43 * to port calculation removing the need for the BSC
44 * and the MediaGateway to communicate.
45 *
46 * Port usage explained:
47 * base + (multiplex * 2) + 0 == local port to wait for network packets
48 * base + (multiplex * 2) + 1 == local port for rtcp
49 *
50 * The above port will receive packets from the BTS that need
51 * to be patched and forwarded to the network.
52 * The above port will receive packets from the network that
53 * need to be patched and forwarded to the BTS.
54 *
55 * We assume to have a static BTS IP address so we can differentiate
56 * network and BTS.
57 *
58 */
59static inline int rtp_calculate_port(int multiplex, int base)
60{
61 return base + (multiplex * 2);
62}
63
64
65/*
66 * Handling of MGCP Endpoints and the MGCP Config
67 */
68struct mgcp_endpoint;
69struct mgcp_config;
70struct mgcp_trunk_config;
71struct mgcp_rtp_end;
72
73#define MGCP_ENDP_CRCX 1
74#define MGCP_ENDP_DLCX 2
75#define MGCP_ENDP_MDCX 3
76
77/*
78 * what to do with the msg?
79 * - continue as usual?
80 * - reject and send a failure code?
81 * - defer? do not send anything
82 */
83#define MGCP_POLICY_CONT 4
84#define MGCP_POLICY_REJECT 5
85#define MGCP_POLICY_DEFER 6
86
87typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
88typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
89typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
90typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
91typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
92
93/**
94 * Return:
95 * < 0 in case no audio was processed
96 * >= 0 in case audio was processed. The remaining payload
97 * length will be returned.
98 */
99typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
100 struct mgcp_rtp_end *dst_end,
101 char *data, int *len, int buf_size);
102typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
103 struct mgcp_rtp_end *dst_end,
104 struct mgcp_rtp_end *src_end);
105
Philipp Maier87bd9be2017-08-22 16:35:41 +0200106struct mgcp_conn_rtp;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200107typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
108 int *payload_type,
109 const char**subtype_name,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200110 const char**fmtp_extra,
111 struct mgcp_conn_rtp *conn);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200112
113/**
114 * This holds information on how to allocate ports
115 */
116struct mgcp_port_range {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200117 /* addr or NULL to fall-back to default */
118 char *bind_addr;
119
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200120 /* dynamically allocated */
121 int range_start;
122 int range_end;
123 int last_port;
124};
125
126#define MGCP_KEEPALIVE_ONCE (-1)
127
128struct mgcp_trunk_config {
129 struct llist_head entry;
130
131 struct mgcp_config *cfg;
132
133 int trunk_nr;
134 int trunk_type;
135
136 char *audio_fmtp_extra;
137 char *audio_name;
138 int audio_payload;
139 int audio_send_ptime;
140 int audio_send_name;
141 int audio_loop;
142
143 int no_audio_transcoding;
144
145 int omit_rtcp;
146 int keepalive_interval;
147
148 /* RTP patching */
149 int force_constant_ssrc; /* 0: don't, 1: once */
150 int force_aligned_timing;
151
152 /* spec handling */
153 int force_realloc;
154
155 /* timer */
156 struct osmo_timer_list keepalive_timer;
157
Philipp Maier87bd9be2017-08-22 16:35:41 +0200158 /* When set, incoming RTP packets are not filtered
159 * when ports and ip-address do not match (debug) */
160 int rtp_accept_all;
161
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200162 unsigned int number_endpoints;
163 struct mgcp_endpoint *endpoints;
164};
165
166enum mgcp_role {
167 MGCP_BSC = 0,
168 MGCP_BSC_NAT,
169};
170
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200171struct mgcp_config {
172 int source_port;
173 char *local_ip;
174 char *source_addr;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200175 char *call_agent_addr;
176
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200177 /* RTP processing */
178 mgcp_processing rtp_processing_cb;
179 mgcp_processing_setup setup_rtp_processing_cb;
180
181 mgcp_get_format get_net_downlink_format_cb;
182
183 struct osmo_wqueue gw_fd;
184
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200185 struct mgcp_port_range net_ports;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200186 int endp_dscp;
187
Philipp Maier87bd9be2017-08-22 16:35:41 +0200188 int force_ptime;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200189
190 mgcp_change change_cb;
191 mgcp_policy policy_cb;
192 mgcp_reset reset_cb;
193 mgcp_realloc realloc_cb;
194 mgcp_rqnt rqnt_cb;
195 void *data;
196
197 uint32_t last_call_id;
198
199 /* trunk handling */
200 struct mgcp_trunk_config trunk;
201 struct llist_head trunks;
202
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200203 enum mgcp_role role;
204
205 /* osmux translator: 0 means disabled, 1 means enabled */
206 int osmux;
207 /* addr to bind the server to */
208 char *osmux_addr;
209 /* The BSC-NAT may ask for enabling osmux on demand. This tells us if
210 * the osmux socket is already initialized.
211 */
212 int osmux_init;
213 /* osmux batch factor: from 1 to 4 maximum */
214 int osmux_batch;
215 /* osmux batch size (in bytes) */
216 int osmux_batch_size;
217 /* osmux port */
218 uint16_t osmux_port;
219 /* Pad circuit with dummy messages until we see the first voice
220 * message.
221 */
222 uint16_t osmux_dummy;
223};
224
225/* config management */
226struct mgcp_config *mgcp_config_alloc(void);
227int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
228 enum mgcp_role role);
229int mgcp_vty_init(void);
230int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
231void mgcp_release_endp(struct mgcp_endpoint *endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200232void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
233
234/*
235 * format helper functions
236 */
237struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
238
239/* adc helper */
240static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
241{
242 if (timeslot == 0) {
243 LOGP(DLMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
244 timeslot = 255;
245 }
246
247 return timeslot + (32 * multiplex);
248}
249
250static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
251{
252 *multiplex = endpoint / 32;
253 *timeslot = endpoint % 32;
254}
255
256int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
257int mgcp_send_reset_all(struct mgcp_config *cfg);
258
259
260int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200261int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);