blob: 75681a912d52016cee369afb32b26268d1e147ff [file] [log] [blame]
Harald Welteb0d93602018-03-20 18:09:34 +01001module SIP_Templates {
2
3import from SIPmsg_Types all;
4
5/* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */
6type record SipAddr {
7 Addr_Union addr,
8 SemicolonParam_List params optional
9}
10
11const charstring c_SIP_VERSION := "SIP/2.0";
12
13template (value) SipUrl ts_SipUrl(charstring user_or_tel, charstring host, integer portnr) := {
14 scheme := "sip",
15 userInfo := {
16 userOrTelephoneSubscriber := user_or_tel,
17 password := omit
18 },
19 hostPort := {
20 host := host,
21 portField := portnr
22 },
23 urlParameters := omit,
24 headers := omit
25}
26template SipUrl tr_SipUrl(template charstring user_or_tel,
27 template charstring host,
28 template integer portnr) := {
29 scheme := "sip",
30 userInfo := {
31 userOrTelephoneSubscriber := user_or_tel,
32 password := *
33 },
34 hostPort := {
35 host := host,
36 portField := portnr
37 },
38 urlParameters := *,
39 headers := *
40}
41
42template (value) SipAddr ts_SipAddr(charstring user_or_tel, charstring host, integer portnr) := {
43 addr := {
44 nameAddr := {
45 displayName := omit,
46 addrSpec := ts_SipUrl(user_or_tel, host, portnr)
47 }
48 },
49 params := omit
50}
51template SipAddr tr_SipAddr(template charstring user_or_tel,
52 template charstring host,
53 template integer portnr) := {
54 addr := {
55 nameAddr := {
56 displayName := *,
57 addrSpec := tr_SipUrl(user_or_tel, host, portnr)
58 }
59 },
60 params := *
61}
62
63/* build a receive template from a value: substitute '*' for omit */
64function tr_SipAddr_from_val(SipAddr tin) return template SipAddr {
65 var template SipAddr ret := tin;
66 if (tin.addr.nameAddr.displayName == omit) {
67 ret.addr.nameAddr.displayName := *;
68 }
69 if (tin.addr.nameAddr.addrSpec.userInfo.password == omit) {
70 ret.addr.nameAddr.addrSpec.userInfo.password := *;
71 }
72 if (tin.params == omit) {
73 ret.params := *;
74 }
75 return ret;
76}
77
78
79function tr_HostPort(template HostPort hp) return template HostPort {
80 var template HostPort hpout := hp;
81 /* if the port number is 5060, it may be omitted */
82 if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
83 hpout.portField := 5060 ifpresent;
84 }
85 return hpout;
86}
87
88template (value) RequestLine ts_SIP_ReqLine(Method method, template (value) SipUrl uri,
89 charstring ver := c_SIP_VERSION) := {
90 method := method,
91 requestUri := uri,
92 sipVersion := ver
93}
94template RequestLine tr_SIP_ReqLine(template Method method,
95 template SipUrl uri,
96 template charstring ver := c_SIP_VERSION) := {
97 method := method,
98 requestUri := uri,
99 sipVersion := ver
100}
101
102template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
103 sipVersion := "SIP/2.0",
104 statusCode := status_code,
105 reasonPhrase := reason
106}
107template StatusLine tr_SIP_StatusLine(template integer status_code, template charstring reason) := {
108 sipVersion := "SIP/2.0",
109 statusCode := status_code,
110 reasonPhrase := reason
111}
112
113
114template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
115 requestLine := rl,
116 msgHeader := c_SIP_msgHeader_empty,
117 messageBody := omit,
118 payload := omit
119}
120
121const Method_List c_SIP_defaultMethods := {
122 "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
123 "NOTIFY", "REFER", "UPDATE" };
124
125private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
126return template (omit) ContentType {
127 /* if user explicitly stated no content type */
128 if (istemplatekind(ct, "omit")) {
129 return omit;
130 }
131 /* if there's no body, then there's no content-type either */
132 if (istemplatekind(body, "omit")) {
133 return omit;
134 }
135 return ct;
136}
137
138template (value) ContentType ts_CT_SDP := {
139 fieldName := CONTENT_TYPE_E,
140 mediaType := "application/sdp"
141};
142
143template (value) Via ts_Via_from(SipAddr from_addr) := {
144 fieldName := VIA_E,
145 viaBody := {
146 {
147 sentProtocol := { "SIP", "2.0", "UDP" },
148 sentBy := from_addr.addr.nameAddr.addrSpec.hostPort,
149 viaParams := omit
150 }
151 }
152}
153
154template (value) MessageHeader ts_SIP_msgHeader_empty :=c_SIP_msgHeader_empty;
155template (value) MessageHeader ts_SIP_msgh_std( CallidString call_id,
156 SipAddr from_addr,
157 SipAddr to_addr,
158 template (omit) SipAddr contact_addr,
159 charstring method,
160 integer seq_nr,
161 template (value) Via via,
162 template (omit) ContentType content_type := omit,
163 Method_List allow_methods := c_SIP_defaultMethods
164 ) modifies ts_SIP_msgHeader_empty := {
165 allow := {
166 fieldName := ALLOW_E,
167 methods := allow_methods
168 },
169 callId := {
170 fieldName := CALL_ID_E,
171 callid := call_id
172 },
173 contact := ts_Contact(contact_addr),
174 contentType := content_type,
175 cSeq := {
176 fieldName := CSEQ_E,
177 seqNumber := seq_nr,
178 method := method
179 },
180 fromField := {
181 fieldName := FROM_E,
182 addressField := from_addr.addr,
183 fromParams := from_addr.params
184 },
185 toField := {
186 fieldName := TO_E,
187 addressField := to_addr.addr,
188 toParams := to_addr.params
189 },
190 userAgent := {
191 fieldName := USER_AGENT_E,
192 userAgentBody := {
193 "osmo-ttcn3-hacks/0.23"
194 }
195 },
196 via := via
197}
198
199private function tr_Contact(template SipAddr contact_addr) return template Contact
200{
201 if (istemplatekind(contact_addr, "omit")) {
202 return omit;
203 } else if (istemplatekind(contact_addr, "*")) {
204 return *;
205 } else if (istemplatekind(contact_addr, "?")) {
206 return ?;
207 }
208 var template Contact ret := {
209 fieldName := CONTACT_E,
210 contactBody := {
211 contactAddresses := {
212 {
213 addressField := contact_addr.addr,
214 contactParams := contact_addr.params
215 }
216 }
217 }
218 };
219 return ret;
220}
221
222private function ts_Contact(template (omit) SipAddr contact_addr) return template (omit) Contact
223{
224 if (istemplatekind(contact_addr, "omit")) {
225 return omit;
226 }
227 var template (omit) Contact ret := {
228 fieldName := CONTACT_E,
229 contactBody := {
230 contactAddresses := {
231 {
232 addressField := contact_addr.addr,
233 contactParams := contact_addr.params
234 }
235 }
236 }
237 };
238 return ret;
239}
240
241
242function tr_AllowMethods(template Method_List allow_methods) return template Allow {
243 if (istemplatekind(allow_methods, "omit")) {
244 return omit;
245 } else if (istemplatekind(allow_methods, "*")) {
246 return *;
247 } else if (istemplatekind(allow_methods, "?")) {
248 return ?;
249 }
250 var template Allow ret := {
251 fieldName := ALLOW_E,
252 methods := allow_methods
253 }
254 return ret
255}
256
257template MessageHeader tr_SIP_msgh_std( template CallidString call_id,
258 template SipAddr from_addr,
259 template SipAddr to_addr,
260 template SipAddr contact_addr,
261 template charstring method,
262 template ContentType content_type := *,
263 template integer seq_nr := ?,
264 template Method_List allow_methods := *
265 ) modifies t_SIP_msgHeader_any := {
266 allow := tr_AllowMethods(allow_methods),
267 callId := {
268 fieldName := CALL_ID_E,
269 callid := call_id
270 },
271 contact := tr_Contact(contact_addr),
272 contentType := content_type,
273 cSeq := {
274 fieldName := CSEQ_E,
275 seqNumber := seq_nr,
276 method := method
277 },
278 fromField := {
279 fieldName := FROM_E,
280 addressField := from_addr.addr,
281 fromParams := from_addr.params
282 },
283 toField := {
284 fieldName := TO_E,
285 addressField := to_addr.addr,
286 toParams := to_addr.params
287 },
288 userAgent := *,
289 via := {
290 fieldName := VIA_E,
291 viaBody := {
292 {
293 sentProtocol := { "SIP", "2.0", "UDP" },
294 sentBy := tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort),
295 viaParams := *
296 }
297 }
298 }
299}
300
301
302template (value) PDU_SIP_Request ts_SIP_INVITE( CallidString call_id,
303 SipAddr from_addr,
304 SipAddr to_addr,
305 integer seq_nr,
306 template (omit) charstring body
307 ) := {
308 requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
309 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, from_addr, "INVITE", seq_nr,
310 ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)),
311 messageBody := body,
312 payload := omit
313}
314template PDU_SIP_Request tr_SIP_INVITE( template CallidString call_id,
315 template SipAddr from_addr,
316 template SipAddr to_addr,
317 template integer seq_nr,
318 template charstring body
319 ) := {
320 requestLine := tr_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
321 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?, "INVITE", *, seq_nr),
322 messageBody := body,
323 payload := omit
324}
325
326template (value) PDU_SIP_Request ts_SIP_BYE( CallidString call_id,
327 SipAddr from_addr,
328 SipAddr to_addr,
329 integer seq_nr,
330 template (omit) charstring body
331 ) := {
332 requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
333 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
334 ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)),
335 messageBody := body,
336 payload := omit
337}
338
339template PDU_SIP_Request tr_SIP_BYE( template CallidString call_id,
340 template SipAddr from_addr,
341 template SipAddr to_addr,
342 template integer seq_nr,
343 template charstring body
344 ) := {
345 requestLine := tr_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
346 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", *, seq_nr),
347 messageBody := body,
348 payload := omit
349}
350
351
352template (value) PDU_SIP_Request ts_SIP_ACK( CallidString call_id,
353 SipAddr from_addr,
354 SipAddr to_addr,
355 integer seq_nr,
356 template (omit) charstring body
357 ) := {
358 requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
359 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, from_addr, "ACK", seq_nr,
360 ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)),
361 messageBody := body,
362 payload := omit
363}
364template PDU_SIP_Request tr_SIP_ACK( template CallidString call_id,
365 template SipAddr from_addr,
366 template SipAddr to_addr,
367 template integer seq_nr,
368 template charstring body
369 ) := {
370 requestLine := tr_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
371 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *, "ACK", *, seq_nr),
372 messageBody := body,
373 payload := omit
374}
375
376
377
378template (value) PDU_SIP_Response ts_SIP_Response( CallidString call_id,
379 SipAddr from_addr,
380 SipAddr to_addr,
381 charstring method,
382 integer status_code,
383 integer seq_nr,
384 charstring reason,
385 Via via,
386 template (omit) charstring body := omit
387 ) := {
388 statusLine := ts_SIP_StatusLine(status_code, reason),
389 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
390 via, f_ContentTypeOrOmit(ts_CT_SDP, body)),
391 messageBody := body,
392 payload := omit
393}
394
395template PDU_SIP_Response tr_SIP_Response( template CallidString call_id,
396 template SipAddr from_addr,
397 template SipAddr to_addr,
398 template SipAddr contact_addr,
399 template charstring method,
400 template integer status_code,
401 template integer seq_nr := ?,
402 template charstring reason := ?,
403 template charstring body := ?
404 ) := {
405 statusLine := tr_SIP_StatusLine(status_code, reason),
406 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact_addr, method, *, seq_nr),
407 messageBody := body,
408 payload := omit
409}
410
411
412
413}