blob: 7ef49cf87e1423c608f54f8300a11d8bc681b195 [file] [log] [blame]
Harald Welteb0d93602018-03-20 18:09:34 +01001module SIP_Templates {
2
3import from SIPmsg_Types all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02004import from TCCConversion_Functions all;
5import from TCCOpenSecurity_Functions all;
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02006import from TCCDateTime_Functions all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02007import from Native_Functions all;
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01008import from Osmocom_Types all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02009import from Misc_Helpers all;
Harald Welteb0d93602018-03-20 18:09:34 +010010
11/* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */
12type record SipAddr {
13 Addr_Union addr,
14 SemicolonParam_List params optional
15}
16
17const charstring c_SIP_VERSION := "SIP/2.0";
18
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020019template (value) GenericParam ts_Param(template (value) charstring id,
20 template (omit) charstring paramValue := omit) := {
21 id := id,
22 paramValue := paramValue
23}
24template (present) GenericParam tr_Param(template (present) charstring id := ?,
25 template charstring paramValue := *) := {
26 id := id,
27 paramValue := paramValue
28}
29function f_ts_Param_omit(template (value) charstring id,
30 template (omit) charstring paramValue := omit)
31 return template (omit) GenericParam
32{
33 if (istemplatekind(paramValue, "omit")) {
34 return omit;
35 }
36 return ts_Param(id, paramValue);
37}
38
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010039template (value) SipUrl ts_SipUrl(template (value) HostPort host_port,
40 template (omit) UserInfo user_info := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +010041 scheme := "sip",
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010042 userInfo := user_info,
43 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010044 urlParameters := omit,
45 headers := omit
46}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010047template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?,
48 template UserInfo user_info := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +010049 scheme := "sip",
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010050 userInfo := user_info,
51 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010052 urlParameters := *,
53 headers := *
54}
55
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +020056template (value) SipUrl ts_SipUrlHost(template (value) charstring host,
57 template (omit) integer portField := omit)
58 := ts_SipUrl(ts_HostPort(host, portField));
59
60function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au)
61return template (value) SipUrl {
62 if (ischosen(au.nameAddr)) {
63 return au.nameAddr.addrSpec;
64 } else { /* au.addrSpecUnion */
65 return au.addrSpecUnion;
66 }
67}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010068
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +020069// [20.5]
70template (present) Allow tr_Allow(template Method_List methods := *) := {
71 fieldName := ALLOW_E,
72 methods := methods
73}
74template (value) Allow ts_Allow(template (omit) Method_List methods := omit) := {
75 fieldName := ALLOW_E,
76 methods := methods
77}
78
Pau Espin Pedrola674d612024-05-14 19:56:33 +020079template (present) Credentials tr_Credentials_DigestResponse(template (present) CommaParam_List digestResponse) := {
80 digestResponse := digestResponse
81}
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020082template (value) Credentials ts_Credentials_DigestResponse(template (value) CommaParam_List digestResponse) := {
83 digestResponse := digestResponse
84}
85
86template (value) Credentials ts_Credentials_DigestResponseMD5(
87 template (value) charstring username,
88 template (value) charstring realm,
89 template (value) charstring nonce,
90 template (value) charstring uri,
91 template (value) charstring response,
92 template (value) charstring opaque,
93 template (value) charstring algorithm := "MD5",
94 template (value) charstring qop := "auth",
95 template (omit) charstring cnonce := omit,
96 template (omit) charstring nc := omit
97 ) := {
98 digestResponse := {
99 // Already added by digestResponse automatically:
100 //ts_Param("Digest", omit),
101 ts_Param("username", f_sip_str_quote(username)),
102 ts_Param("realm", f_sip_str_quote(realm)),
103 ts_Param("nonce", f_sip_str_quote(nonce)),
104 ts_Param("uri", f_sip_str_quote(uri)),
105 ts_Param("response", f_sip_str_quote(response)),
106 ts_Param("opaque", f_sip_str_quote(opaque)),
107 ts_Param("algorithm", algorithm),
108 ts_Param("qop", qop),
109 // FIXME: If "omit" is passed, these below end up in;
110 // "Dynamic test case error: Performing a valueof or send operation on a non-specific template of type @SIPmsg_Types.GenericParam"
111 f_ts_Param_omit("cnonce", f_sip_str_quote(cnonce)),
112 f_ts_Param_omit("nc", nc)
113 }
114}
115
116template (value) Credentials ts_Credentials_OtherAuth(template (value) OtherAuth otherResponse) := {
117 otherResponse := otherResponse
118}
119
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200120template (present) Authorization tr_Authorization(template (present) Credentials body) := {
121 fieldName := AUTHORIZATION_E,
122 body := body
123}
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200124template (value) Authorization ts_Authorization(template (value) Credentials body) := {
125 fieldName := AUTHORIZATION_E,
126 body := body
127}
128
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100129// [20.10]
130template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?,
131 template charstring displayName := *) := {
132 displayName := displayName,
133 addrSpec := addrSpec
Harald Welteb0d93602018-03-20 18:09:34 +0100134}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100135template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec,
136 template (omit) charstring displayName := omit) := {
137 displayName := displayName,
138 addrSpec := addrSpec
139}
140
141template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := {
142 nameAddr := nameAddr
143}
144template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := {
145 nameAddr := nameAddr
146}
147
148template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := {
149 addrSpecUnion := sipUrl
150}
151template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := {
152 addrSpecUnion := sipUrl
153}
154
155
156template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?,
157 template SemicolonParam_List contactParams := *) := {
158 addressField := addressField,
159 contactParams := contactParams
160}
161template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField,
162 template (omit) SemicolonParam_List contactParams := omit) := {
163 addressField := addressField,
164 contactParams := contactParams
165}
166
167template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := {
168 fieldName := CONTACT_E,
169 contactBody := {
170 contactAddresses := contactAddresses
171 }
172}
173template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := {
174 fieldName := CONTACT_E,
175 contactBody := {
176 contactAddresses := contactAddresses
177 }
178}
179
180template (value) Contact ts_ContactWildcard := {
181 fieldName := CONTACT_E,
182 contactBody := {
183 wildcard := "*"
184 }
185}
186
187template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?)
188 := tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) });
189
190private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact
191{
192 if (istemplatekind(contact_addr, "omit")) {
193 return omit;
194 } else if (istemplatekind(contact_addr, "*")) {
195 return *;
196 }
197 return tr_Contact_SipAddr(contact_addr);
198}
199
200template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr)
201 := ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) });
202private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact
203{
204 if (istemplatekind(contact_addr, "omit")) {
205 return omit;
206 }
207 return ts_Contact_SipAddr(contact_addr);
208}
209
210
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200211// [20.14]
212template (value) ContentLength ts_ContentLength(template (value) integer len := 0) := {
213 fieldName := CONTENT_LENGTH_E,
214 len := len
215}
216template (present) ContentLength tr_ContentLength(template (present) integer len := ?) := {
217 fieldName := CONTENT_LENGTH_E,
218 len := len
219}
220
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100221// [20.19]
222template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := {
223 fieldName := EXPIRES_E,
224 deltaSec := deltaSec
225}
226
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200227
228// [20.32]
229template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := {
230 fieldName := REQUIRE_E,
231 optionsTags := optionsTags
232}
233template (present) Require tr_Require(template (present) OptionTag_List optionsTags := ?) := {
234 fieldName := REQUIRE_E,
235 optionsTags := optionsTags
236}
237
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200238// [20.35 RFC2616 14.38]
239template (value) Server ts_Server(template (value) ServerVal_List serverBody := {}) := {
240 fieldName := SERVER_E,
241 serverBody := serverBody
242}
243template (present) Server tr_Server(template (present) ServerVal_List serverBody := ?) := {
244 fieldName := SERVER_E,
245 serverBody := serverBody
246}
247
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200248// [20.37]
249template (value) Supported ts_Supported(template (value) OptionTag_List optionsTags := {}) := {
250 fieldName := SUPPORTED_E,
251 optionsTags := optionsTags
252}
253template (present) Supported tr_Supported(template (present) OptionTag_List optionsTags := ?) := {
254 fieldName := SUPPORTED_E,
255 optionsTags := optionsTags
256}
257
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200258// [20.41 RFC2616 14.43]
259template (value) UserAgent ts_UserAgent(template (value) ServerVal_List userAgentBody := {}) := {
260 fieldName := USER_AGENT_E,
261 userAgentBody := userAgentBody
262}
263template (present) UserAgent tr_UserAgent(template (present) ServerVal_List userAgentBody := ?) := {
264 fieldName := USER_AGENT_E,
265 userAgentBody := userAgentBody
266}
267
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200268
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100269template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
270 template (omit) UserInfo user_info := omit,
271 template (omit) charstring displayName := omit,
272 template (omit) SemicolonParam_List params := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100273 addr := {
274 nameAddr := {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100275 displayName := displayName,
276 addrSpec := ts_SipUrl(host_port, user_info)
Harald Welteb0d93602018-03-20 18:09:34 +0100277 }
278 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100279 params := params
280}
281template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
282 template UserInfo user_info := *,
283 template charstring displayName := *,
284 template SemicolonParam_List params := *) := {
285 addr := {
286 nameAddr := {
287 displayName := displayName,
288 addrSpec := tr_SipUrl(host_port, user_info)
289 }
290 },
291 params := params
Harald Welteb0d93602018-03-20 18:09:34 +0100292}
293
294/* build a receive template from a value: substitute '*' for omit */
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200295function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl {
296 var template (present) SipUrl ret := tin;
297
298 /* if the port number is 5060, it may be omitted */
299 if (ispresent(tin.hostPort.portField) and
300 valueof(tin.hostPort.portField) == 5060) {
301 ret.hostPort.portField := 5060 ifpresent;
302 }
303 if (not ispresent(tin.userInfo.password)) {
304 ret.userInfo.password := *;
305 }
306
307 return ret;
308}
309function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100310 var template (present) SipAddr ret := tin;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200311
312 if (not ispresent(tin.addr.nameAddr.displayName)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100313 ret.addr.nameAddr.displayName := *;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200314 } else if (f_str_tolower(f_sip_str_unquote(tin.addr.nameAddr.displayName)) == "anonymous") {
315 /* if the user is Anonymous, it may be omitted */
316 ret.addr.nameAddr.displayName := tin.addr.nameAddr.displayName ifpresent;
Harald Welteb0d93602018-03-20 18:09:34 +0100317 }
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200318
319 ret.addr.nameAddr.addrSpec := tr_SipUrl_from_val(tin.addr.nameAddr.addrSpec);
320
321 if (not ispresent(tin.params)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100322 ret.params := *;
323 }
324 return ret;
325}
326
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200327function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
328 template (omit) SemicolonParam_List params := omit)
329return template (value) SipAddr {
330 var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
331 var template (omit) charstring displayName;
332
333 if (ischosen(au.nameAddr)) {
334 displayName := au.nameAddr.displayName;
335 } else { /* au.addrSpecUnion */
336 displayName := omit
337 }
338
339 return ts_SipAddr(addrSpec.hostPort,
340 addrSpec.userInfo,
341 displayName,
342 params);
343}
344
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100345template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
346 template (omit) integer portField := omit) := {
347 host := host,
348 portField := portField
349}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200350
351template (present) HostPort tr_HostPort(template charstring host := *,
352 template integer portField := *) := {
353 host := host,
354 portField := portField
355}
356function f_tr_HostPort(template charstring host := *,
357 template integer portField := *)
358return template (present) HostPort {
359 return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
360}
361function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort {
362 var template (present) HostPort hpout := hp;
Harald Welteb0d93602018-03-20 18:09:34 +0100363 /* if the port number is 5060, it may be omitted */
364 if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
365 hpout.portField := 5060 ifpresent;
366 }
367 return hpout;
368}
369
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200370function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl {
371 var template (present) SipUrl urlout := url;
372 urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
373 return urlout;
374}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100375
376template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
377 template (omit) charstring password := omit) := {
378 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
379 password := password
380}
381template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
382 template charstring password := *) := {
383 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
384 password := password
385}
386
387template (value) RequestLine ts_SIP_ReqLine(Method method,
388 template (value) SipUrl uri,
Harald Welteb0d93602018-03-20 18:09:34 +0100389 charstring ver := c_SIP_VERSION) := {
390 method := method,
391 requestUri := uri,
392 sipVersion := ver
393}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100394template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
395 template (present) SipUrl uri := ?,
396 template (present) charstring ver := c_SIP_VERSION) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100397 method := method,
398 requestUri := uri,
399 sipVersion := ver
400}
401
402template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
403 sipVersion := "SIP/2.0",
404 statusCode := status_code,
405 reasonPhrase := reason
406}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100407template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
408 template charstring reason) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100409 sipVersion := "SIP/2.0",
410 statusCode := status_code,
411 reasonPhrase := reason
412}
413
414
415template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
416 requestLine := rl,
417 msgHeader := c_SIP_msgHeader_empty,
418 messageBody := omit,
419 payload := omit
420}
421
422const Method_List c_SIP_defaultMethods := {
423 "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
424 "NOTIFY", "REFER", "UPDATE" };
425
426private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
427return template (omit) ContentType {
428 /* if user explicitly stated no content type */
429 if (istemplatekind(ct, "omit")) {
430 return omit;
431 }
432 /* if there's no body, then there's no content-type either */
433 if (istemplatekind(body, "omit")) {
434 return omit;
435 }
436 return ct;
437}
438
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200439private function f_ContentLength(template (omit) charstring body)
440return template (value) ContentLength {
441 /* rfc3261 20.14: "If no body is present in a message, then the
442 * Content-Length header field value MUST be set to zero." */
443 if (istemplatekind(body, "omit")) {
444 return ts_ContentLength(0);
445 }
446 return ts_ContentLength(lengthof(body));
447}
448
Harald Welteb0d93602018-03-20 18:09:34 +0100449template (value) ContentType ts_CT_SDP := {
450 fieldName := CONTENT_TYPE_E,
451 mediaType := "application/sdp"
452};
453
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200454template (value) Via ts_Via_from(template (value) HostPort addr,
455 template (value) charstring transport := "UDP") := {
Harald Welteb0d93602018-03-20 18:09:34 +0100456 fieldName := VIA_E,
457 viaBody := {
458 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200459 sentProtocol := { "SIP", "2.0", transport },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100460 sentBy := addr,
Harald Welteb0d93602018-03-20 18:09:34 +0100461 viaParams := omit
462 }
463 }
464}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100465template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200466 template (present) charstring transport := ?,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100467 template SemicolonParam_List viaParams := *) := {
468 fieldName := VIA_E,
469 viaBody := {
470 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200471 sentProtocol := { "SIP", "2.0", ? },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100472 sentBy := host_port,
473 viaParams := viaParams
474 }
475 }
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200476}
477
478template (present) OtherAuth
479tr_OtherAuth(template (present) charstring authScheme := ?,
480 template (present) CommaParam_List authParams := ?) := {
481 authScheme := authScheme,
482 authParams := authParams
483}
484
485template (value) OtherAuth
486ts_OtherAuth(template (value) charstring authScheme,
487 template (value) CommaParam_List authParams) := {
488 authScheme := authScheme,
489 authParams := authParams
490}
491
492template (present) Challenge
493tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := {
494 digestCln := digestCln
495}
496
497template (value) Challenge
498ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := {
499 digestCln := digestCln
500}
501
502template (present) Challenge
503tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := {
504 otherChallenge := otherChallenge
505}
506
507template (value) Challenge
508ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := {
509 otherChallenge := otherChallenge
510}
511
512template (present) WwwAuthenticate
513tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := {
514 fieldName := WWW_AUTHENTICATE_E,
515 challenge := challenge
516}
517
518template (value) WwwAuthenticate
519ts_WwwAuthenticate(template (value) Challenge_list challenge) := {
520 fieldName := WWW_AUTHENTICATE_E,
521 challenge := challenge
522}
Harald Welteb0d93602018-03-20 18:09:34 +0100523
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200524// RFC3329
525template (present) Security_client
526tr_Security_client(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
527 fieldName := SECURITY_CLIENT_E,
528 sec_mechanism_list := sec_mechanism_list
529}
530template (value) Security_client
531ts_Security_client(template (value) Security_mechanism_list sec_mechanism_list) := {
532 fieldName := SECURITY_CLIENT_E,
533 sec_mechanism_list := sec_mechanism_list
534}
535
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200536template (present) Security_server
537tr_Security_server(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
538 fieldName := SECURITY_SERVER_E,
539 sec_mechanism_list := sec_mechanism_list
540}
541template (value) Security_server
542ts_Security_server(template (value) Security_mechanism_list sec_mechanism_list) := {
543 fieldName := SECURITY_SERVER_E,
544 sec_mechanism_list := sec_mechanism_list
545}
546
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200547template (present) Security_mechanism
548tr_Security_mechanism(template (present) charstring name := ?,
549 template SemicolonParam_List params := *) := {
550 mechanism_name := name,
551 mechanism_params := params
552}
553template (value) Security_mechanism
554ts_Security_mechanism(template (value) charstring name,
555 template (omit) SemicolonParam_List params := omit) := {
556 mechanism_name := name,
557 mechanism_params := params
558}
559
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100560template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
561template (value) MessageHeader
562ts_SIP_msgh_std(template (value) CallidString call_id,
563 template (value) SipAddr from_addr,
564 template (value) SipAddr to_addr,
565 template (omit) Contact contact,
566 template (value) charstring method,
567 template (value) integer seq_nr,
568 template (value) Via via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200569 template (omit) ContentLength content_length := ts_ContentLength(0),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100570 template (omit) ContentType content_type := omit,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200571 template (omit)Authorization authorization := omit,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200572 template (omit) Allow allow := ts_Allow(c_SIP_defaultMethods),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200573 template (omit) Expires expires := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200574 template (omit) Require require := omit,
575 template (omit) Security_client security_client := omit,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200576 template (omit) Security_server security_server := omit,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200577 template (omit) Server server := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200578 template (omit) Supported supported := omit,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200579 template (omit) UserAgent userAgent := ts_UserAgent({ "osmo-ttcn3-hacks/0.23" }),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200580 template (omit) WwwAuthenticate wwwAuthenticate := omit
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100581 ) modifies ts_SIP_msgHeader_empty := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200582 allow := allow,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200583 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100584 callId := {
585 fieldName := CALL_ID_E,
586 callid := call_id
587 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100588 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200589 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100590 contentType := content_type,
591 cSeq := {
592 fieldName := CSEQ_E,
593 seqNumber := seq_nr,
594 method := method
595 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100596 expires := expires,
Harald Welteb0d93602018-03-20 18:09:34 +0100597 fromField := {
598 fieldName := FROM_E,
599 addressField := from_addr.addr,
600 fromParams := from_addr.params
601 },
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200602 require := require,
603 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200604 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200605 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200606 supported := supported,
Harald Welteb0d93602018-03-20 18:09:34 +0100607 toField := {
608 fieldName := TO_E,
609 addressField := to_addr.addr,
610 toParams := to_addr.params
611 },
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200612 userAgent := userAgent,
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200613 via := via,
614 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100615}
616
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100617template (present) MessageHeader
618tr_SIP_msgh_std(template CallidString call_id,
619 template SipAddr from_addr,
620 template SipAddr to_addr,
621 template Contact contact,
622 template (present) Via via := tr_Via_from(?),
623 template charstring method,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100624 template integer seq_nr := ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200625 template ContentLength content_length := *,
626 template ContentType content_type := *,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200627 template Allow allow := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200628 template Authorization authorization := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200629 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200630 template Require require := *,
631 template Security_client security_client := *,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200632 template Security_server security_server := *,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200633 template Server server := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200634 template Supported supported := *,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200635 template UserAgent userAgent := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200636 template WwwAuthenticate wwwAuthenticate := *
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100637 ) modifies t_SIP_msgHeader_any := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200638 allow := allow,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200639 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100640 callId := {
641 fieldName := CALL_ID_E,
642 callid := call_id
643 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100644 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200645 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100646 contentType := content_type,
647 cSeq := {
648 fieldName := CSEQ_E,
649 seqNumber := seq_nr,
650 method := method
651 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100652 expires := expires,
Harald Welteb0d93602018-03-20 18:09:34 +0100653 fromField := {
654 fieldName := FROM_E,
655 addressField := from_addr.addr,
656 fromParams := from_addr.params
657 },
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200658 require := require,
659 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200660 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200661 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200662 supported := supported,
Harald Welteb0d93602018-03-20 18:09:34 +0100663 toField := {
664 fieldName := TO_E,
665 addressField := to_addr.addr,
666 toParams := to_addr.params
667 },
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200668 userAgent := userAgent,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200669 via := via,
670 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100671}
672
673
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100674template (value) PDU_SIP_Request
675ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
676 template (value) CallidString call_id,
677 template (value) SipAddr from_addr,
678 template (value) SipAddr to_addr,
679 template (value) Via via,
680 integer seq_nr,
681 template (omit) Contact contact,
682 template (omit) Expires expires,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200683 template (omit) Authorization authorization := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200684 template (omit) Require require := omit,
685 template (omit) Security_client security_client := omit,
686 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100687 template (omit) charstring body := omit) := {
688 requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
689 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
690 "REGISTER", seq_nr, via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200691 content_length := f_ContentLength(body),
692 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200693 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200694 expires := expires,
695 require := require,
696 security_client := security_client,
697 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100698 messageBody := body,
699 payload := omit
700}
701template (present) PDU_SIP_Request
702tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
703 template (present) CallidString call_id := ?,
704 template (present) SipAddr from_addr := ?,
705 template (present) SipAddr to_addr := ?,
Pau Espin Pedrol0dd3f262024-04-25 17:04:43 +0200706 template (present) Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100707 template integer seq_nr := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200708 template Authorization authorization := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100709 template Contact contact := *,
710 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200711 template Require require := *,
712 template Security_client security_client := *,
713 template Supported supported := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100714 template charstring body := *) := {
715 requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
716 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200717 via, "REGISTER", seq_nr,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200718 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200719 expires := expires,
720 require := require,
721 security_client := security_client,
722 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100723 messageBody := body,
724 payload := omit
725}
726
727template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200728ts_SIP_INVITE(template (value) CallidString call_id,
729 template (value) SipAddr from_addr,
730 template (value) SipAddr to_addr,
731 template (value) Via via,
732 template (value) Contact contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100733 integer seq_nr,
734 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100735 requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200736 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100737 "INVITE", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200738 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200739 content_length := f_ContentLength(body),
740 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100741 messageBody := body,
742 payload := omit
743}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100744template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200745tr_SIP_INVITE(template (present) SipUrl uri,
746 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100747 template SipAddr from_addr,
748 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200749 template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100750 template integer seq_nr,
751 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200752 requestLine := tr_SIP_ReqLine(INVITE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100753 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200754 via, "INVITE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100755 messageBody := body,
756 payload := omit
757}
758
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100759template (value) PDU_SIP_Request
760ts_SIP_BYE(CallidString call_id,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200761 template (value) SipAddr from_addr,
762 template (value) SipAddr to_addr,
763 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100764 integer seq_nr,
765 template (omit) charstring body) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100766 requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
767 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200768 via,
769 content_length := f_ContentLength(body),
770 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100771 messageBody := body,
772 payload := omit
773}
774
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100775template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200776tr_SIP_BYE(template (present) SipUrl uri,
777 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100778 template SipAddr from_addr,
779 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200780 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100781 template integer seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200782 template charstring body := *) := {
783 requestLine := tr_SIP_ReqLine(BYE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100784 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200785 via, "BYE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100786 messageBody := body,
787 payload := omit
788}
789
790
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100791template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200792ts_SIP_ACK(template (value) CallidString call_id,
793 template (value) SipAddr from_addr,
794 template (value) SipAddr to_addr,
795 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100796 integer seq_nr,
797 template (omit) charstring body) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100798 requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100799 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
800 ts_Contact_SipAddr(from_addr),
801 "ACK", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200802 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200803 content_length := f_ContentLength(body),
804 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100805 messageBody := body,
806 payload := omit
807}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100808template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200809tr_SIP_ACK(template (present) SipUrl uri,
810 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100811 template SipAddr from_addr,
812 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200813 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100814 template integer seq_nr,
815 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200816 requestLine := tr_SIP_ReqLine(ACK_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100817 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200818 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200819 "ACK", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100820 messageBody := body,
821 payload := omit
822}
823
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200824template (present) PDU_SIP_Request
825tr_SIP_CANCEL(template (present) SipUrl uri,
826 template (present) CallidString call_id,
827 template (present) SipAddr from_addr,
828 template (present) SipAddr to_addr,
829 template (present) Via via,
830 template (present) integer seq_nr,
831 template charstring body := *) := {
832 requestLine := tr_SIP_ReqLine(CANCEL_E, uri),
833 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
834 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200835 "CANCEL", seq_nr),
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200836 messageBody := body,
837 payload := omit
838}
839
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100840template (value) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200841ts_SIP_Response(template (value) CallidString call_id,
842 template (value) SipAddr from_addr,
843 template (value) SipAddr to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100844 charstring method,
845 integer status_code,
846 integer seq_nr,
847 charstring reason,
848 Via via,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200849 template (omit) Allow allow := omit,
850 template (omit) Require require := omit,
851 template (omit) Server server := omit,
852 template (omit) Supported supported := omit,
853 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100854 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100855 statusLine := ts_SIP_StatusLine(status_code, reason),
856 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200857 via,
858 content_length := f_ContentLength(body),
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200859 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
860 allow := allow,
861 require := require,
862 server := server,
863 supported := supported,
864 userAgent := userAgent),
Harald Welteb0d93602018-03-20 18:09:34 +0100865 messageBody := body,
866 payload := omit
867}
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200868/* 100 Trying */
869template (value) PDU_SIP_Response
870ts_SIP_Response_Trying(
871 template (value) CallidString call_id,
872 template (value) SipAddr from_addr,
873 template (value) SipAddr to_addr,
874 Via via,
875 integer seq_nr,
876 charstring method := "INVITE",
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200877 template (omit) Allow allow := omit,
878 template (omit) Server server := omit,
879 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200880 template (omit) charstring body := omit) := {
881 statusLine := ts_SIP_StatusLine(100, "Trying"),
882 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200883 via,
884 content_length := f_ContentLength(body),
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200885 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
886 allow := allow,
887 server := server,
888 userAgent := userAgent),
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200889 messageBody := body,
890 payload := omit
891}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200892/* 180 Ringing */
893template (value) PDU_SIP_Response
894ts_SIP_Response_Ringing(
895 template (value) CallidString call_id,
896 template (value) SipAddr from_addr,
897 template (value) SipAddr to_addr,
898 Via via,
899 integer seq_nr,
900 charstring method := "INVITE",
901 template (omit) charstring body := omit) := {
902 statusLine := ts_SIP_StatusLine(180, "Ringing"),
903 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200904 via,
905 content_length := f_ContentLength(body),
906 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200907 messageBody := body,
908 payload := omit
909}
910
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200911/* 401 Unauthorized */
912template (value) PDU_SIP_Response
913ts_SIP_Response_Unauthorized(
914 template (value) CallidString call_id,
915 template (value) SipAddr from_addr,
916 template (value) SipAddr to_addr,
917 Via via,
918 template (value) WwwAuthenticate wwwAuthenticate,
919 integer seq_nr,
920 charstring method := "REGISTER",
921 template (omit) Allow allow := omit,
922 template (omit) Security_server security_server := omit,
923 template (omit) Server server := omit,
924 template (omit) Supported supported := omit,
925 template (omit) UserAgent userAgent := omit,
926 template (omit) charstring body := omit) := {
927 statusLine := ts_SIP_StatusLine(401, "Unauthorized"),
928 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
929 via,
930 content_length := f_ContentLength(body),
931 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
932 allow := allow,
933 security_server := security_server,
934 server := server,
935 supported := supported,
936 userAgent := userAgent,
937 wwwAuthenticate := wwwAuthenticate),
938 messageBody := body,
939 payload := omit
940}
941
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100942template (present) PDU_SIP_Response
943tr_SIP_Response(template CallidString call_id,
944 template SipAddr from_addr,
945 template SipAddr to_addr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200946 template (present) Via via := tr_Via_from(?),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100947 template Contact contact,
948 template charstring method,
949 template integer status_code,
950 template integer seq_nr := ?,
951 template charstring reason := ?,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200952 template charstring body := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100953 statusLine := tr_SIP_StatusLine(status_code, reason),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100954 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200955 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200956 method, seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100957 messageBody := body,
958 payload := omit
959}
960
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200961/* Expect during first REGISTER/INVITE/... when authorization is required: */
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100962template (present) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200963tr_SIP_Response_Unauthorized(
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100964 template CallidString call_id,
965 template SipAddr from_addr,
966 template SipAddr to_addr,
967 template (present) Via via := tr_Via_from(?),
968 template Contact contact := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200969 template (present) WwwAuthenticate wwwAuthenticate := ?,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100970 template integer seq_nr := ?,
971 template charstring method := "REGISTER",
972 template integer status_code := 401,
973 template charstring reason := "Unauthorized",
974 template charstring body := *) := {
975 statusLine := tr_SIP_StatusLine(status_code, reason),
976 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
977 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200978 method, seq_nr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200979 wwwAuthenticate := wwwAuthenticate),
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100980 messageBody := body,
981 payload := omit
982}
Harald Welteb0d93602018-03-20 18:09:34 +0100983
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200984/* 100 Trying */
985template (present) PDU_SIP_Response
986tr_SIP_Response_Trying(
987 template CallidString call_id,
988 template SipAddr from_addr,
989 template SipAddr to_addr,
990 template (present) Via via := tr_Via_from(?),
991 template integer seq_nr := ?,
992 template charstring method := "INVITE",
993 template integer status_code := 100,
994 template charstring reason := "Trying",
995 template charstring body := *) := {
996 statusLine := tr_SIP_StatusLine(status_code, reason),
997 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
998 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200999 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001000 messageBody := body,
1001 payload := omit
1002}
1003
1004/* 180 Ringing */
1005template (present) PDU_SIP_Response
1006tr_SIP_Response_Ringing(
1007 template CallidString call_id,
1008 template SipAddr from_addr,
1009 template SipAddr to_addr,
1010 template (present) Via via := tr_Via_from(?),
1011 template integer seq_nr := ?,
1012 template charstring method := "INVITE",
1013 template integer status_code := 180,
1014 template charstring reason := "Ringing",
1015 template charstring body := *) := {
1016 statusLine := tr_SIP_StatusLine(status_code, reason),
1017 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1018 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001019 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001020 messageBody := body,
1021 payload := omit
1022}
1023
1024/****************
1025 * FUNCTIONS:
1026 ****************/
1027
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001028function f_sip_param_find(GenericParam_List li,
1029 template (present) charstring id := ?)
1030return template (omit) GenericParam {
1031 var integer i;
1032
1033 for (i := 0; i < lengthof(li); i := i + 1) {
1034 if (not ispresent(li[i])) {
1035 continue;
1036 }
1037 if (match(li[i].id, id)) {
1038 return li[i];
1039 }
1040 }
1041 return omit;
1042}
1043
1044function f_sip_param_find_or_fail(GenericParam_List li,
1045 template (present) charstring id := ?)
1046return GenericParam {
1047 var template (omit) GenericParam parameter;
1048 parameter := f_sip_param_find(li, id);
1049 if (istemplatekind(parameter, "omit")) {
1050 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1051 log2str("Param ", id, " not found in ", li));
1052 }
1053 return valueof(parameter);
1054}
1055
1056function f_sip_param_get_value(GenericParam_List li,
1057 template (present) charstring id := ?)
1058return template (omit) charstring {
1059 var template (omit) GenericParam parameter;
1060 parameter := f_sip_param_find(li, id);
1061 if (istemplatekind(parameter, "omit")) {
1062 return omit;
1063 }
1064 return parameter.paramValue;
1065}
1066
1067function f_sip_param_get_value_or_fail(GenericParam_List li,
1068 template (present) charstring id := ?)
1069return template (omit) charstring {
1070 var GenericParam parameter;
1071 parameter := f_sip_param_find_or_fail(li, id);
1072 return parameter.paramValue;
1073}
1074
1075function f_sip_param_get_value_present_or_fail(GenericParam_List li,
1076 template (present) charstring id := ?)
1077return charstring {
1078 var GenericParam parameter;
1079 parameter := f_sip_param_find_or_fail(li, id);
1080 if (not ispresent(parameter.paramValue)) {
1081 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1082 log2str("Param ", id, " value not present in ", li));
1083 }
1084 return parameter.paramValue;
1085}
1086
1087function f_sip_param_match_value(GenericParam_List li,
1088 template (present) charstring id := ?,
1089 template charstring exp_paramValue := *)
1090return boolean {
1091 var template (omit) charstring val;
1092 val := f_sip_param_get_value_or_fail(li, id);
1093 if (istemplatekind(val, "omit")) {
1094 return istemplatekind(val, "omit") or istemplatekind(val, "*");
1095 }
1096 return match(valueof(val), exp_paramValue);
1097}
1098
1099function f_sip_param_match_value_or_fail(GenericParam_List li,
1100 template (present) charstring id := ?,
1101 template charstring exp_paramValue := *)
1102{
1103 var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id);
1104 if (istemplatekind(val, "omit")) {
1105 if (istemplatekind(val, "omit") or istemplatekind(val, "*")) {
1106 return;
1107 } else {
1108 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1109 log2str("Param ", id, " match failed: val ", val,
1110 " vs exp ", exp_paramValue));
1111 }
1112 }
1113 if (not match(valueof(val), exp_paramValue)) {
1114 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1115 log2str("Param ", id, " match failed: val ", val,
1116 " vs exp ", exp_paramValue));
1117 }
1118}
1119
1120function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id)
1121return GenericParam_List {
1122 var integer i;
1123 var GenericParam_List li;
1124 var GenericParam_List new_li := {};
1125
1126 if (istemplatekind(li_tpl, "omit")) {
1127 return {};
1128 }
1129
1130 li := valueof(li_tpl);
1131 for (i := 0; i < lengthof(li); i := i + 1) {
1132 if (not ispresent(li[i]) or
1133 not match(li[i].id, id)) {
1134 new_li := new_li & {li[i]};
1135 }
1136 }
1137 return new_li;
1138}
1139
1140function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val)
1141return GenericParam_List {
1142 var integer i;
1143 var GenericParam_List li;
1144 var GenericParam_List new_li := {};
1145 var boolean found := false;
1146
1147 if (istemplatekind(li_tpl, "omit")) {
1148 return { valueof(ts_Param(id, val)) };
1149 }
1150
1151 li := valueof(li_tpl);
1152 for (i := 0; i < lengthof(li); i := i + 1) {
1153 if (not ispresent(li[i]) or
1154 not match(li[i].id, id)) {
1155 new_li := new_li & {li[i]};
1156 continue;
1157 }
1158 new_li := new_li & { valueof(ts_Param(li[i].id, val)) };
1159 found := true;
1160 }
1161
1162 if (not found) {
1163 new_li := new_li & { valueof(ts_Param(id, val)) };
1164 }
1165 return new_li;
1166}
1167
1168/* Make sure string is quoted. */
1169function f_sip_str_quote(template (value) charstring val) return charstring {
1170 var charstring str := valueof(val);
1171 if (lengthof(str) == 0) {
1172 return "";
1173 }
1174
1175 if (str[0] != "\"") {
1176 return "\"" & str & "\"";
1177 }
1178 return str;
1179}
1180
1181/* Make sure string is unquoted.
1182 * Similar to unq() in RFC 2617 */
1183function f_sip_str_unquote(template (value) charstring val) return charstring {
1184 var charstring str := valueof(val);
1185 var integer len := lengthof(str);
1186
1187 if (len <= 1) {
1188 return str;
1189 }
1190
1191 if (str[0] == "\"" and str[len - 1] == "\"") {
1192 return substr(str, 1, len - 2);
1193 }
1194 return str;
1195}
1196
1197/* RFC 2617 3.2.2.2 A1 */
1198function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring {
1199
1200 /* RFC 2617 3.2.2.2 A1 */
1201 var charstring A1 := f_sip_str_unquote(user) & ":" &
1202 f_sip_str_unquote(realm) & ":" &
1203 password;
1204 var charstring digestA1 := f_str_tolower(f_calculateMD5(A1));
1205 log("A1: md5('", A1, "') = ", digestA1);
1206 return digestA1;
1207}
1208
1209/* RFC 2617 3.2.2.2 A2 */
1210function f_sip_digest_A2(charstring method, charstring uri) return charstring {
1211
1212 var charstring A2 := method & ":" & uri
1213 var charstring digestA2 := f_str_tolower(f_calculateMD5(A2));
1214 log("A2: md5('", A2, "') = ", digestA2);
1215 return digestA2;
1216}
1217
1218/* RFC 2617 3.2.2.1 Request-Digest */
1219function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce,
1220 charstring nc, charstring cnonce,
1221 charstring qop, charstring digestA2) return charstring {
1222 var charstring digest_data := f_sip_str_unquote(nonce) & ":" &
1223 nc & ":" &
1224 cnonce & ":" &
1225 f_sip_str_unquote(qop) & ":" &
1226 digestA2;
1227 var charstring req_digest := f_sip_digest_KD(digestA1, digest_data);
1228 log("Request-Digest: md5('", digestA1, ":", digest_data ,"') = ", req_digest);
1229 return req_digest;
1230}
1231
1232/* RFC 2617 3.2.1 The WWW-Authenticate Response Header
1233 * KD(secret, data) = H(concat(secret, ":", data))
1234 */
1235function f_sip_digest_KD(charstring secret, charstring data) return charstring {
1236 return f_str_tolower(f_calculateMD5(secret & ":" & data));
1237}
1238
1239/* Digest Auth: RFC 2617 */
1240function f_sip_digest_gen_Authorization(WwwAuthenticate www_authenticate,
1241 charstring user, charstring password,
1242 charstring method, charstring uri,
1243 charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization {
1244 var CommaParam_List digestCln;
1245 var template (value) Authorization authorization;
1246 var template (value) Credentials cred;
1247 var template (omit) GenericParam rx_param;
1248
1249 digestCln := www_authenticate.challenge[0].digestCln;
1250
1251 var charstring algorithm;
1252 rx_param := f_sip_param_find(digestCln, "algorithm");
1253 if (istemplatekind(rx_param, "omit")) {
1254 /* Assume MD5 if not set */
1255 algorithm := "MD5"
1256 } else {
1257 algorithm := valueof(rx_param.paramValue);
1258 if (f_strstr(algorithm, "MD5") == -1) {
1259 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1260 log2str("Unexpected algorithm: ", algorithm));
1261 }
1262 }
1263
1264 var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
1265 var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
1266 var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque");
1267 var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop");
1268
1269 if (f_strstr(qop, "auth") == -1) {
1270 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1271 }
1272 var charstring selected_qop := "auth";
1273
1274 /* RFC 2617 3.2.2.2 A1 */
1275 var charstring digestA1 := f_sip_digest_A1(user, realm, password);
1276 /* RFC 2617 3.2.2.3 A2 */
1277 var charstring digestA2 := f_sip_digest_A2(method, uri);
1278
1279 /* RFC 2617 3.2.2.1 Request-Digest */
1280 var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8)));
1281 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1282 nc, cnonce,
1283 selected_qop, digestA2);
1284
1285 cred := ts_Credentials_DigestResponseMD5(user, realm, nonce,
1286 uri, req_digest,
1287 opaque, algorithm, selected_qop, cnonce, nc);
1288
1289 authorization := ts_Authorization(cred);
1290 return valueof(authorization);
1291}
1292
1293/* RFC 2617 3.5 Example */
1294function f_sip_digest_selftest() {
1295/*
1296The following example assumes that an access-protected document is
1297being requested from the server via a GET request. The URI of the
1298document is "http://www.nowhere.org/dir/index.html". Both client and
1299server know that the username for this document is "Mufasa", and the
1300password is "Circle Of Life" (with one space between each of the
1301three words).
1302
1303HTTP/1.1 401 Unauthorized
1304WWW-Authenticate: Digest
1305 realm="testrealm@host.com",
1306 qop="auth,auth-int",
1307 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1308 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1309
1310Authorization: Digest username="Mufasa",
1311 realm="testrealm@host.com",
1312 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1313 uri="/dir/index.html",
1314 qop=auth,
1315 nc=00000001,
1316 cnonce="0a4f113b",
1317 response="6629fae49393a05397450978507c4ef1",
1318 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1319*/
1320 var template (value) CommaParam_List digestCln := {
1321 ts_Param("realm", f_sip_str_quote("testrealm@host.com")),
1322 ts_Param("qop", f_sip_str_quote("auth,auth-int")),
1323 ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")),
1324 ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"))
1325 };
1326 var template (value) WwwAuthenticate www_authenticate :=
1327 ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
1328
1329 var Authorization authorization :=
1330 f_sip_digest_gen_Authorization(valueof(www_authenticate),
1331 "Mufasa",
1332 "Circle Of Life",
1333 "GET",
1334 "/dir/index.html",
1335 cnonce := "0a4f113b",
1336 nc_int := 1);
1337
1338 var CommaParam_List digestResp := authorization.body.digestResponse;
1339 f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com"));
1340 f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093"));
1341 f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html"));
1342 f_sip_param_match_value_or_fail(digestResp, "qop", "auth");
1343 f_sip_param_match_value_or_fail(digestResp, "nc", "00000001");
1344 f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b"));
1345 f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1"));
1346 f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"));
1347}
1348
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01001349/* RFC 3261 8.1.1.5:
1350 * "The sequence number value MUST be expressible as a 32-bit unsigned integer
1351 * and MUST be less than 2**31."
1352 */
1353function f_sip_rand_seq_nr() return integer {
1354 /* 2**31 = 2147483648 */
1355 return f_rnd_int(2147483648)
1356}
Harald Welteb0d93602018-03-20 18:09:34 +01001357
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001358function f_sip_next_seq_nr(integer seq_nr) return integer {
1359 return (seq_nr + 1) mod 2147483648;
1360}
1361
1362function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
1363 req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
1364}
1365
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001366function f_sip_rand_tag() return charstring {
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001367 /* Tags shall have at least 32 bit of randomness */
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001368 var integer rnd_int := f_rnd_int(4294967296);
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001369 /* Make collisions harder by appending time to the final string: */
1370 var integer ts_int := f_time_ms() mod 4294967296;
1371 return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8));
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001372}
1373
1374/* Generate a "branch" tag value.
1375 * RFC 3261 p.105 section 8:
1376 * "A common way to create this value is to compute a
1377 * cryptographic hash of the To tag, From tag, Call-ID header
1378 * field, the Request-URI of the request received (before
1379 * translation), the topmost Via header, and the sequence number
1380 * from the CSeq header field, in addition to any Proxy-Require
1381 * and Proxy-Authorization header fields that may be present. The
1382 * algorithm used to compute the hash is implementation-dependent,
1383 * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable
1384 * choice."
1385 * See also Section 8.1.1.7:
1386 * "The branch ID inserted by an element compliant with this
1387 * specification MUST always begin with the characters "z9hG4bK"."
1388 */
1389const charstring sip_magic_cookie := "z9hG4bK";
1390function f_sip_gen_branch(charstring tag_to,
1391 charstring tag_from,
1392 charstring tag_call_id,
1393 integer cseq) return charstring {
1394 var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq);
1395 var charstring hash := f_calculateMD5(str);
1396 var charstring branch := sip_magic_cookie & hash;
1397 return branch;
1398}
1399
1400function f_sip_HostPort_to_str(HostPort host_port) return charstring {
1401 var charstring str := "";
1402 if (ispresent(host_port.host)) {
1403 str := host_port.host;
1404 }
1405 if (ispresent(host_port.portField)) {
1406 str := str & ":" & int2str(host_port.portField);
1407 }
1408 return str;
1409}
1410
1411function f_sip_SipUrl_to_str(SipUrl uri) return charstring {
Pau Espin Pedrolad5e9962024-05-16 20:53:06 +02001412 var charstring str := uri.scheme & ":" & f_sip_HostPort_to_str(uri.hostPort);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001413 return str;
1414}
1415
1416function f_sip_NameAddr_to_str(NameAddr naddr) return charstring {
1417 if (ispresent(naddr.displayName)) {
1418 return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">";
1419 } else {
1420 return f_sip_SipUrl_to_str(naddr.addrSpec);
1421 }
1422}
1423
1424function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring {
1425 if (ischosen(sip_addr.addr.nameAddr)) {
1426 return f_sip_NameAddr_to_str(sip_addr.addr.nameAddr);
1427 } else {
1428 return f_sip_SipUrl_to_str(sip_addr.addr.addrSpecUnion);
1429 }
1430}
1431
Harald Welteb0d93602018-03-20 18:09:34 +01001432}