blob: 9e32a34d4265c018680e3f9a9db2d6d0d9b8a71b [file] [log] [blame]
Harald Welte4029e8c2017-11-23 22:00:42 +01001module MGCP_Templates {
2
Harald Welte35bb7162018-01-03 21:07:52 +01003/* MGCP Templates, building on top of MGCP_Types (Osmocom) and SDP_Types from Ericsson.
4 *
5 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
6 * All rights reserved.
7 *
8 * Released under the terms of GNU General Public License, Version 2 or
9 * (at your option) any later version.
10 */
11
12
Harald Welte4029e8c2017-11-23 22:00:42 +010013 import from MGCP_Types all;
14 import from SDP_Types all;
15
16 function f_mgcp_par_append(inout template MgcpParameterList list, template MgcpParameter par) {
17 var integer len := lengthof(list);
18 list[len] := par;
19 }
20
21 /* 3.2.2.6 Connection Mode (sendonly, recvonly, sendrecv, confrnce, inactive, loopback,
22 * conttest, netwloop, netwtest) */
23 template MgcpParameter t_MgcpParConnMode(template MgcpConnectionMode mode) := { "M", mode };
24
25 /* 3.2.2.2 CallId: maximum 32 hex chars */
26 template MgcpParameter ts_MgcpParCallId(MgcpCallId cid) := {
27 code := "C",
28 val := hex2str(cid)
29 };
30
31 /* 3.2.2.18 RequestIdentifier: Maximum 32 hex chars */
32 template MgcpParameter ts_MgcpParReqId(MgcpRequestId rid) := {
33 code := "X",
34 val := hex2str(rid)
35 };
36
Harald Welte363cb0a2018-01-30 19:35:53 +010037 /* 3.2.1.3 SpecificEndpointId */
38 template MgcpParameter ts_MgcpParSpecEP(MgcpEndpoint ep) := {
39 code := "Z",
40 val := ep
41 };
42
Harald Welte4029e8c2017-11-23 22:00:42 +010043 /* 3.2.2.10: LocalConnectionOptions (codec, packetization, bandwidth, ToS, eco, gain, silence, ...) */
44 template MgcpParameter t_MgcpParLocConnOpt(template charstring lco) := { "L", lco };
45
46 /* 3.2.2.5: ConnectionId: maximum 32 hex chars */
47 template MgcpParameter ts_MgcpParConnectionId(MgcpConnectionId cid) := {
48 code := "I",
49 val := hex2str(cid)
50 };
51
52 /* osmo-bsc_mgcp implements L/C/M/X only, osmo-mgw adds 'I' */
53 /* SDP: osmo-bsc_mgcp implements Tx of v,o,s,c,t,m,a */
54
55 template MgcpResponse tr_MgcpResp_Err(template MgcpResponseCode code) := {
56 line := {
57 code := code,
58 trans_id := ?,
59 string := ?
60 },
61 params := {},
62 sdp := omit
63 }
64
65 template MgcpCommandLine t_MgcpCmdLine(template charstring verb, template MgcpTransId trans_id, template charstring ep) := {
66 verb := verb,
67 trans_id := trans_id,
68 ep := ep,
69 ver := "1.0"
70 };
71
72 template MgcpCommand ts_CRCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
73 line := t_MgcpCmdLine("CRCX", trans_id, ep),
74 params := {
75 t_MgcpParConnMode(mode),
76 ts_MgcpParCallId(call_id),
77 //t_MgcpParReqId(omit),
Daniel Willmannfbef7142017-11-30 13:16:14 +010078 t_MgcpParLocConnOpt("p:20, a:AMR")
Harald Welte4029e8c2017-11-23 22:00:42 +010079 },
80 sdp := sdp
81 }
82
Harald Welte4017d552018-01-26 21:40:05 +010083 template MgcpCommand tr_CRCX(template MgcpEndpoint ep := ?) := {
84 line := t_MgcpCmdLine("CRCX", ?, ep),
Harald Welte90029572017-11-24 23:39:50 +010085 params := *,
86 sdp := *
87 }
88
Harald Welte4029e8c2017-11-23 22:00:42 +010089 template MgcpResponse tr_CRCX_ACK := {
90 line := {
91 code := "200",
Harald Welte51f34ad2017-11-24 20:40:43 +010092 trans_id := ?,
Harald Welte4029e8c2017-11-23 22:00:42 +010093 string := "OK"
94 },
95 params:= { { "I", ? }, *},
96 sdp := ?
97 }
98
Harald Welte90029572017-11-24 23:39:50 +010099 template MgcpResponse ts_CRCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
100 line := {
101 code := "200",
102 trans_id := trans_id,
103 string := "OK"
104 },
105 params:= { ts_MgcpParConnectionId(conn_id) },
106 sdp := sdp
107 }
108
Harald Welte4029e8c2017-11-23 22:00:42 +0100109 template MgcpCommand ts_MDCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
110 line := t_MgcpCmdLine("MDCX", trans_id, ep),
111 params := {
112 t_MgcpParConnMode(mode),
113 ts_MgcpParCallId(call_id),
114 ts_MgcpParConnectionId(conn_id),
115 //t_MgcpParReqId(omit),
Daniel Willmannfbef7142017-11-30 13:16:14 +0100116 t_MgcpParLocConnOpt("p:20, a:AMR")
Harald Welte4029e8c2017-11-23 22:00:42 +0100117 },
118 sdp := sdp
119 }
120
Harald Welte90029572017-11-24 23:39:50 +0100121 template MgcpCommand tr_MDCX := {
122 line := t_MgcpCmdLine("MDCX", ?, ?),
123 params := *,
124 sdp := *
125 }
126
127 template MgcpResponse ts_MDCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
128
Harald Welte4029e8c2017-11-23 22:00:42 +0100129 /* have a function that generates a template, rather than a template in order to handle
130 * optional parameters */
131 function ts_DLCX(MgcpTransId trans_id, charstring ep, template MgcpCallId call_id := omit,
132 template MgcpConnectionId conn_id := omit) return template MgcpCommand {
133 var template MgcpCommand cmd;
134 cmd.line := t_MgcpCmdLine("DLCX", trans_id, ep);
135 cmd.params := {};
136 cmd.sdp := omit;
137 if (isvalue(call_id)) {
138 f_mgcp_par_append(cmd.params, ts_MgcpParCallId(valueof(call_id)));
139 if (isvalue(conn_id)) {
140 f_mgcp_par_append(cmd.params, ts_MgcpParConnectionId(valueof(conn_id)));
141 }
142 }
143 return cmd;
144 }
145
Harald Welteb71901a2018-01-26 19:16:05 +0100146 template MgcpCommand tr_DLCX(template MgcpEndpoint ep := ?) := {
147 line := t_MgcpCmdLine("DLCX", ?, ep),
Harald Welte90029572017-11-24 23:39:50 +0100148 params := *,
149 sdp := *
150 }
151
Harald Weltec82eef42017-11-24 20:40:12 +0100152 template MgcpResponse tr_DLCX_ACK := {
153 line := {
Daniel Willmann961e5c92017-11-30 16:37:40 +0100154 code := ("200", "250"),
Harald Weltec82eef42017-11-24 20:40:12 +0100155 trans_id := ?,
156 string := "OK"
157 },
158 params:= *,
159 sdp := *
160 }
161
Harald Welteb71901a2018-01-26 19:16:05 +0100162 template MgcpResponse ts_DLCX_ACK2(MgcpTransId trans_id) := {
163 line := {
164 code := "250",
165 trans_id := trans_id,
166 string := "OK"
167 },
168 params:= { /* list of ConnectionIDs */ },
169 sdp := omit
170 }
171
172
173
Harald Welte90029572017-11-24 23:39:50 +0100174 template MgcpResponse ts_DLCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
175
Harald Weltee98bb2e2017-11-29 12:09:48 +0100176 template MgcpCommand tr_RSIP := {
177 line := t_MgcpCmdLine("RSIP", ?, ?),
178 params := *,
179 sdp := *
180 }
181
Harald Welte4029e8c2017-11-23 22:00:42 +0100182 /* SDP Templates */
183 template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
184 charstring session_version := "1",
185 charstring addr_type := "IP4",
186 charstring user_name := "-") := {
187 user_name := user_name,
188 session_id := session_id,
189 session_version := session_version,
190 net_type := "IN",
191 addr_type := addr_type,
192 addr := addr
193 }
194
195 template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
196 template integer ttl := omit,
197 template integer num_of_addr := omit) :={
198 net_type := "IN",
199 addr_type := addr_type,
200 conn_addr := {
201 addr := addr,
202 ttl := ttl,
203 num_of_addr := num_of_addr
204 }
205 }
206
207 template SDP_time ts_SDP_time(charstring beg, charstring end) := {
208 time_field := {
209 start_time := beg,
210 stop_time := end
211 },
212 time_repeat := omit
213 }
214
215 template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
216 SDP_attribute_list attributes) := {
217 media_field := {
218 media := "audio",
219 ports := {
220 port_number := port_number,
221 num_of_ports := omit
222 },
223 transport := "RTP/AVP",
224 fmts := fmts
225 },
226 information := omit,
227 connections := omit,
228 bandwidth := omit,
229 key := omit,
230 attributes := attributes
231 }
232
233 /* master template for generating SDP based in template arguments */
234 template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
235 charstring session_id, charstring session_version,
236 integer rtp_port, SDP_fmt_list fmts,
237 SDP_attribute_list attributes) := {
238 protocol_version := 0,
239 origin := ts_SDP_origin(local_addr, session_id, session_version),
240 session_name := "-",
241 information := omit,
242 uri := omit,
243 emails := omit,
244 phone_numbers := omit,
245 connection := ts_SDP_connection_IP(remote_addr),
246 bandwidth := omit,
247 times := { ts_SDP_time("0","0") },
248 timezone_adjustments := omit,
249 key := omit,
250 attributes := omit,
251 media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
252 }
253
254 template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
255 rtpmap := {
256 attr_value := int2str(fmt) & " " & val
257 }
258 }
259 template SDP_attribute ts_SDP_ptime(integer p) := {
260 ptime := {
261 attr_value := int2str(p)
262 }
263 }
264
Harald Welteb71901a2018-01-26 19:16:05 +0100265 function f_mgcp_extract_par(MgcpMessage msg, MgcpInfoCode code) return charstring {
266 var MgcpParameterList pars;
267 if (ischosen(msg.command)) {
268 pars := msg.command.params;
269 } else {
270 pars := msg.response.params;
271 }
272 for (var integer i := 0; i < lengthof(pars); i := i + 1) {
273 var MgcpParameter par := pars[i];
274 if (par.code == code) {
275 return par.val;
Harald Welte4c11d562017-11-24 23:39:00 +0100276 }
277 }
278 setverdict(fail);
Harald Welteb71901a2018-01-26 19:16:05 +0100279 return "";
280 }
281
Harald Welte1fe74812018-01-29 21:57:26 +0100282 function f_MgcpResp_extract_par(MgcpResponse resp, MgcpInfoCode code) return charstring {
Harald Welteb71901a2018-01-26 19:16:05 +0100283 var MgcpMessage msg := {
284 response := resp
285 }
Harald Welte1fe74812018-01-29 21:57:26 +0100286 return f_mgcp_extract_par(msg, code);
Harald Welteb71901a2018-01-26 19:16:05 +0100287 }
288
Harald Welte1fe74812018-01-29 21:57:26 +0100289 function f_MgcpCmd_extract_par(MgcpCommand cmd, MgcpInfoCode code) return charstring {
Harald Welteb71901a2018-01-26 19:16:05 +0100290 var MgcpMessage msg := {
291 command := cmd
292 }
Harald Welte1fe74812018-01-29 21:57:26 +0100293 return f_mgcp_extract_par(msg, code);
Harald Welte4c11d562017-11-24 23:39:00 +0100294 }
295
Harald Welte1fe74812018-01-29 21:57:26 +0100296 function f_MgcpResp_extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
297 return str2hex(f_MgcpResp_extract_par(resp, "I"));
298 }
299
300 function f_MgcpCmd_extract_call_id(MgcpCommand cmd) return MgcpCallId {
301 return str2hex(f_MgcpCmd_extract_par(cmd, "C"));
302 }
303
304 function f_MgcpCmd_extract_conn_id(MgcpCommand cmd) return MgcpConnectionId {
305 return str2hex(f_MgcpCmd_extract_par(cmd, "I"));
306 }
307
308
Harald Welte4c11d562017-11-24 23:39:00 +0100309 function f_mgcp_alloc_tid() return MgcpTransId {
310 return int2str(float2int(rnd()*2147483647.0));
311 }
312
313 function f_mgcp_alloc_call_id() return MgcpCallId {
314 return int2hex(float2int(rnd()*2147483647.0), 8);
315 }
316
317 function f_mgcp_alloc_conn_id() return MgcpConnectionId {
318 return int2hex(float2int(rnd()*2147483647.0), 8);
319 }
320
Harald Weltebb5a1212018-01-26 10:34:44 +0100321 /* those verbs that related to a connection (and hence have ConnectionId) */
322 template MgcpVerb tr_MgcpVerb_ConnectionOriented := ("CRCX", "MDCX", "DLCX", "AUCX");
323 /* entire command template matching only connection oriented verbs */
324 template MgcpCommand tr_MgcpCommand_CO := {
325 line := {
326 verb := tr_MgcpVerb_ConnectionOriented,
327 trans_id := ?,
328 ep := ?,
329 ver := ?
330 },
331 params := *,
332 sdp := *
333 }
334
Harald Welte363cb0a2018-01-30 19:35:53 +0100335 function f_mgcp_find_param(MgcpMessage msg, MgcpInfoCode code, out charstring ret)
336 return boolean {
337 var MgcpParameterList pars;
338 if (ischosen(msg.command)) {
339 pars := msg.command.params;
340 } else {
341 pars := msg.response.params;
342 }
343 for (var integer i := 0; i < sizeof(pars); i := i+1) {
344 if (pars[i].code == code) {
345 ret := pars[i].val;
346 return true;
347 }
348 }
349 return false;
350 }
351
352 /* template to determine if a MGCP endpoint is a wildcard endpoint */
353 template charstring t_MGCP_EP_wildcard := (pattern "\*@*", pattern "rtpbridge/\*@*");
354
Harald Welteb71901a2018-01-26 19:16:05 +0100355
Harald Welte4029e8c2017-11-23 22:00:42 +0100356}