blob: 182868e40ded4b955dbd4680479efe1e4edd55db [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
37 /* 3.2.2.10: LocalConnectionOptions (codec, packetization, bandwidth, ToS, eco, gain, silence, ...) */
38 template MgcpParameter t_MgcpParLocConnOpt(template charstring lco) := { "L", lco };
39
40 /* 3.2.2.5: ConnectionId: maximum 32 hex chars */
41 template MgcpParameter ts_MgcpParConnectionId(MgcpConnectionId cid) := {
42 code := "I",
43 val := hex2str(cid)
44 };
45
46 /* osmo-bsc_mgcp implements L/C/M/X only, osmo-mgw adds 'I' */
47 /* SDP: osmo-bsc_mgcp implements Tx of v,o,s,c,t,m,a */
48
49 template MgcpResponse tr_MgcpResp_Err(template MgcpResponseCode code) := {
50 line := {
51 code := code,
52 trans_id := ?,
53 string := ?
54 },
55 params := {},
56 sdp := omit
57 }
58
59 template MgcpCommandLine t_MgcpCmdLine(template charstring verb, template MgcpTransId trans_id, template charstring ep) := {
60 verb := verb,
61 trans_id := trans_id,
62 ep := ep,
63 ver := "1.0"
64 };
65
66 template MgcpCommand ts_CRCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
67 line := t_MgcpCmdLine("CRCX", trans_id, ep),
68 params := {
69 t_MgcpParConnMode(mode),
70 ts_MgcpParCallId(call_id),
71 //t_MgcpParReqId(omit),
Daniel Willmannfbef7142017-11-30 13:16:14 +010072 t_MgcpParLocConnOpt("p:20, a:AMR")
Harald Welte4029e8c2017-11-23 22:00:42 +010073 },
74 sdp := sdp
75 }
76
Harald Welte90029572017-11-24 23:39:50 +010077 template MgcpCommand tr_CRCX := {
78 line := t_MgcpCmdLine("CRCX", ?, ?),
79 params := *,
80 sdp := *
81 }
82
Harald Welte4029e8c2017-11-23 22:00:42 +010083 template MgcpResponse tr_CRCX_ACK := {
84 line := {
85 code := "200",
Harald Welte51f34ad2017-11-24 20:40:43 +010086 trans_id := ?,
Harald Welte4029e8c2017-11-23 22:00:42 +010087 string := "OK"
88 },
89 params:= { { "I", ? }, *},
90 sdp := ?
91 }
92
Harald Welte90029572017-11-24 23:39:50 +010093 template MgcpResponse ts_CRCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
94 line := {
95 code := "200",
96 trans_id := trans_id,
97 string := "OK"
98 },
99 params:= { ts_MgcpParConnectionId(conn_id) },
100 sdp := sdp
101 }
102
Harald Welte4029e8c2017-11-23 22:00:42 +0100103 template MgcpCommand ts_MDCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
104 line := t_MgcpCmdLine("MDCX", trans_id, ep),
105 params := {
106 t_MgcpParConnMode(mode),
107 ts_MgcpParCallId(call_id),
108 ts_MgcpParConnectionId(conn_id),
109 //t_MgcpParReqId(omit),
Daniel Willmannfbef7142017-11-30 13:16:14 +0100110 t_MgcpParLocConnOpt("p:20, a:AMR")
Harald Welte4029e8c2017-11-23 22:00:42 +0100111 },
112 sdp := sdp
113 }
114
Harald Welte90029572017-11-24 23:39:50 +0100115 template MgcpCommand tr_MDCX := {
116 line := t_MgcpCmdLine("MDCX", ?, ?),
117 params := *,
118 sdp := *
119 }
120
121 template MgcpResponse ts_MDCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
122
Harald Welte4029e8c2017-11-23 22:00:42 +0100123 /* have a function that generates a template, rather than a template in order to handle
124 * optional parameters */
125 function ts_DLCX(MgcpTransId trans_id, charstring ep, template MgcpCallId call_id := omit,
126 template MgcpConnectionId conn_id := omit) return template MgcpCommand {
127 var template MgcpCommand cmd;
128 cmd.line := t_MgcpCmdLine("DLCX", trans_id, ep);
129 cmd.params := {};
130 cmd.sdp := omit;
131 if (isvalue(call_id)) {
132 f_mgcp_par_append(cmd.params, ts_MgcpParCallId(valueof(call_id)));
133 if (isvalue(conn_id)) {
134 f_mgcp_par_append(cmd.params, ts_MgcpParConnectionId(valueof(conn_id)));
135 }
136 }
137 return cmd;
138 }
139
Harald Welteb71901a2018-01-26 19:16:05 +0100140 template MgcpCommand tr_DLCX(template MgcpEndpoint ep := ?) := {
141 line := t_MgcpCmdLine("DLCX", ?, ep),
Harald Welte90029572017-11-24 23:39:50 +0100142 params := *,
143 sdp := *
144 }
145
Harald Weltec82eef42017-11-24 20:40:12 +0100146 template MgcpResponse tr_DLCX_ACK := {
147 line := {
Daniel Willmann961e5c92017-11-30 16:37:40 +0100148 code := ("200", "250"),
Harald Weltec82eef42017-11-24 20:40:12 +0100149 trans_id := ?,
150 string := "OK"
151 },
152 params:= *,
153 sdp := *
154 }
155
Harald Welteb71901a2018-01-26 19:16:05 +0100156 template MgcpResponse ts_DLCX_ACK2(MgcpTransId trans_id) := {
157 line := {
158 code := "250",
159 trans_id := trans_id,
160 string := "OK"
161 },
162 params:= { /* list of ConnectionIDs */ },
163 sdp := omit
164 }
165
166
167
Harald Welte90029572017-11-24 23:39:50 +0100168 template MgcpResponse ts_DLCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
169
Harald Weltee98bb2e2017-11-29 12:09:48 +0100170 template MgcpCommand tr_RSIP := {
171 line := t_MgcpCmdLine("RSIP", ?, ?),
172 params := *,
173 sdp := *
174 }
175
Harald Welte4029e8c2017-11-23 22:00:42 +0100176 /* SDP Templates */
177 template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
178 charstring session_version := "1",
179 charstring addr_type := "IP4",
180 charstring user_name := "-") := {
181 user_name := user_name,
182 session_id := session_id,
183 session_version := session_version,
184 net_type := "IN",
185 addr_type := addr_type,
186 addr := addr
187 }
188
189 template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
190 template integer ttl := omit,
191 template integer num_of_addr := omit) :={
192 net_type := "IN",
193 addr_type := addr_type,
194 conn_addr := {
195 addr := addr,
196 ttl := ttl,
197 num_of_addr := num_of_addr
198 }
199 }
200
201 template SDP_time ts_SDP_time(charstring beg, charstring end) := {
202 time_field := {
203 start_time := beg,
204 stop_time := end
205 },
206 time_repeat := omit
207 }
208
209 template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
210 SDP_attribute_list attributes) := {
211 media_field := {
212 media := "audio",
213 ports := {
214 port_number := port_number,
215 num_of_ports := omit
216 },
217 transport := "RTP/AVP",
218 fmts := fmts
219 },
220 information := omit,
221 connections := omit,
222 bandwidth := omit,
223 key := omit,
224 attributes := attributes
225 }
226
227 /* master template for generating SDP based in template arguments */
228 template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
229 charstring session_id, charstring session_version,
230 integer rtp_port, SDP_fmt_list fmts,
231 SDP_attribute_list attributes) := {
232 protocol_version := 0,
233 origin := ts_SDP_origin(local_addr, session_id, session_version),
234 session_name := "-",
235 information := omit,
236 uri := omit,
237 emails := omit,
238 phone_numbers := omit,
239 connection := ts_SDP_connection_IP(remote_addr),
240 bandwidth := omit,
241 times := { ts_SDP_time("0","0") },
242 timezone_adjustments := omit,
243 key := omit,
244 attributes := omit,
245 media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
246 }
247
248 template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
249 rtpmap := {
250 attr_value := int2str(fmt) & " " & val
251 }
252 }
253 template SDP_attribute ts_SDP_ptime(integer p) := {
254 ptime := {
255 attr_value := int2str(p)
256 }
257 }
258
Harald Welteb71901a2018-01-26 19:16:05 +0100259 function f_mgcp_extract_par(MgcpMessage msg, MgcpInfoCode code) return charstring {
260 var MgcpParameterList pars;
261 if (ischosen(msg.command)) {
262 pars := msg.command.params;
263 } else {
264 pars := msg.response.params;
265 }
266 for (var integer i := 0; i < lengthof(pars); i := i + 1) {
267 var MgcpParameter par := pars[i];
268 if (par.code == code) {
269 return par.val;
Harald Welte4c11d562017-11-24 23:39:00 +0100270 }
271 }
272 setverdict(fail);
Harald Welteb71901a2018-01-26 19:16:05 +0100273 return "";
274 }
275
276 function f_MgcpResp_extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
277 var MgcpMessage msg := {
278 response := resp
279 }
280 return str2hex(f_mgcp_extract_par(msg, "I"));
281 }
282
283 function f_MgcpCmd_extract_call_id(MgcpCommand cmd) return MgcpCallId {
284 var MgcpMessage msg := {
285 command := cmd
286 }
287 return str2hex(f_mgcp_extract_par(msg, "C"));
Harald Welte4c11d562017-11-24 23:39:00 +0100288 }
289
290 function f_mgcp_alloc_tid() return MgcpTransId {
291 return int2str(float2int(rnd()*2147483647.0));
292 }
293
294 function f_mgcp_alloc_call_id() return MgcpCallId {
295 return int2hex(float2int(rnd()*2147483647.0), 8);
296 }
297
298 function f_mgcp_alloc_conn_id() return MgcpConnectionId {
299 return int2hex(float2int(rnd()*2147483647.0), 8);
300 }
301
Harald Weltebb5a1212018-01-26 10:34:44 +0100302 /* those verbs that related to a connection (and hence have ConnectionId) */
303 template MgcpVerb tr_MgcpVerb_ConnectionOriented := ("CRCX", "MDCX", "DLCX", "AUCX");
304 /* entire command template matching only connection oriented verbs */
305 template MgcpCommand tr_MgcpCommand_CO := {
306 line := {
307 verb := tr_MgcpVerb_ConnectionOriented,
308 trans_id := ?,
309 ep := ?,
310 ver := ?
311 },
312 params := *,
313 sdp := *
314 }
315
Harald Welteb71901a2018-01-26 19:16:05 +0100316
Harald Welte4029e8c2017-11-23 22:00:42 +0100317}