blob: f4c6e0fd94a5caa3aca2283d500f4b8d2e397c90 [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 Welte90029572017-11-24 23:39:50 +0100140 template MgcpCommand tr_DLCX := {
141 line := t_MgcpCmdLine("DLCX", ?, ?),
142 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 Welte90029572017-11-24 23:39:50 +0100156 template MgcpResponse ts_DLCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
157
Harald Weltee98bb2e2017-11-29 12:09:48 +0100158 template MgcpCommand tr_RSIP := {
159 line := t_MgcpCmdLine("RSIP", ?, ?),
160 params := *,
161 sdp := *
162 }
163
Harald Welte4029e8c2017-11-23 22:00:42 +0100164 /* SDP Templates */
165 template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
166 charstring session_version := "1",
167 charstring addr_type := "IP4",
168 charstring user_name := "-") := {
169 user_name := user_name,
170 session_id := session_id,
171 session_version := session_version,
172 net_type := "IN",
173 addr_type := addr_type,
174 addr := addr
175 }
176
177 template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
178 template integer ttl := omit,
179 template integer num_of_addr := omit) :={
180 net_type := "IN",
181 addr_type := addr_type,
182 conn_addr := {
183 addr := addr,
184 ttl := ttl,
185 num_of_addr := num_of_addr
186 }
187 }
188
189 template SDP_time ts_SDP_time(charstring beg, charstring end) := {
190 time_field := {
191 start_time := beg,
192 stop_time := end
193 },
194 time_repeat := omit
195 }
196
197 template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
198 SDP_attribute_list attributes) := {
199 media_field := {
200 media := "audio",
201 ports := {
202 port_number := port_number,
203 num_of_ports := omit
204 },
205 transport := "RTP/AVP",
206 fmts := fmts
207 },
208 information := omit,
209 connections := omit,
210 bandwidth := omit,
211 key := omit,
212 attributes := attributes
213 }
214
215 /* master template for generating SDP based in template arguments */
216 template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
217 charstring session_id, charstring session_version,
218 integer rtp_port, SDP_fmt_list fmts,
219 SDP_attribute_list attributes) := {
220 protocol_version := 0,
221 origin := ts_SDP_origin(local_addr, session_id, session_version),
222 session_name := "-",
223 information := omit,
224 uri := omit,
225 emails := omit,
226 phone_numbers := omit,
227 connection := ts_SDP_connection_IP(remote_addr),
228 bandwidth := omit,
229 times := { ts_SDP_time("0","0") },
230 timezone_adjustments := omit,
231 key := omit,
232 attributes := omit,
233 media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
234 }
235
236 template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
237 rtpmap := {
238 attr_value := int2str(fmt) & " " & val
239 }
240 }
241 template SDP_attribute ts_SDP_ptime(integer p) := {
242 ptime := {
243 attr_value := int2str(p)
244 }
245 }
246
Harald Welte4c11d562017-11-24 23:39:00 +0100247 function f_MgcpResp_extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
248 var integer i;
249 for (i := 0; i < lengthof(resp.params); i := i + 1) {
250 var MgcpParameter par := resp.params[i];
251 if (par.code == "I") {
252 return str2hex(par.val);
253 }
254 }
255 setverdict(fail);
256 return '00000000'H;
257 }
258
259 function f_mgcp_alloc_tid() return MgcpTransId {
260 return int2str(float2int(rnd()*2147483647.0));
261 }
262
263 function f_mgcp_alloc_call_id() return MgcpCallId {
264 return int2hex(float2int(rnd()*2147483647.0), 8);
265 }
266
267 function f_mgcp_alloc_conn_id() return MgcpConnectionId {
268 return int2hex(float2int(rnd()*2147483647.0), 8);
269 }
270
Harald Welte4029e8c2017-11-23 22:00:42 +0100271}