blob: 26f7ea8b312ea91e2bdc5cf73cc0b310604bd531 [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,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +020040 template (omit) UserInfo user_info := omit,
41 template (value) charstring scheme := "sip") := {
42 scheme := scheme,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010043 userInfo := user_info,
44 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010045 urlParameters := omit,
46 headers := omit
47}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010048template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +020049 template UserInfo user_info := *,
50 template (present) charstring scheme := "sip") := {
51 scheme := scheme,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010052 userInfo := user_info,
53 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010054 urlParameters := *,
55 headers := *
56}
57
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +020058template (value) SipUrl ts_SipUrlHost(template (value) charstring host,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +020059 template (omit) integer portField := omit,
60 template (value) charstring scheme := "sip")
61 := ts_SipUrl(ts_HostPort(host, portField), scheme := scheme);
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +020062
63function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au)
64return template (value) SipUrl {
65 if (ischosen(au.nameAddr)) {
66 return au.nameAddr.addrSpec;
67 } else { /* au.addrSpecUnion */
68 return au.addrSpecUnion;
69 }
70}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010071
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +020072// [20.5]
73template (present) Allow tr_Allow(template Method_List methods := *) := {
74 fieldName := ALLOW_E,
75 methods := methods
76}
77template (value) Allow ts_Allow(template (omit) Method_List methods := omit) := {
78 fieldName := ALLOW_E,
79 methods := methods
80}
81
Pau Espin Pedrola674d612024-05-14 19:56:33 +020082template (present) Credentials tr_Credentials_DigestResponse(template (present) CommaParam_List digestResponse) := {
83 digestResponse := digestResponse
84}
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020085template (value) Credentials ts_Credentials_DigestResponse(template (value) CommaParam_List digestResponse) := {
86 digestResponse := digestResponse
87}
88
89template (value) Credentials ts_Credentials_DigestResponseMD5(
90 template (value) charstring username,
91 template (value) charstring realm,
92 template (value) charstring nonce,
93 template (value) charstring uri,
94 template (value) charstring response,
95 template (value) charstring opaque,
96 template (value) charstring algorithm := "MD5",
97 template (value) charstring qop := "auth",
98 template (omit) charstring cnonce := omit,
99 template (omit) charstring nc := omit
100 ) := {
101 digestResponse := {
102 // Already added by digestResponse automatically:
103 //ts_Param("Digest", omit),
104 ts_Param("username", f_sip_str_quote(username)),
105 ts_Param("realm", f_sip_str_quote(realm)),
106 ts_Param("nonce", f_sip_str_quote(nonce)),
107 ts_Param("uri", f_sip_str_quote(uri)),
108 ts_Param("response", f_sip_str_quote(response)),
109 ts_Param("opaque", f_sip_str_quote(opaque)),
110 ts_Param("algorithm", algorithm),
111 ts_Param("qop", qop),
112 // FIXME: If "omit" is passed, these below end up in;
113 // "Dynamic test case error: Performing a valueof or send operation on a non-specific template of type @SIPmsg_Types.GenericParam"
114 f_ts_Param_omit("cnonce", f_sip_str_quote(cnonce)),
115 f_ts_Param_omit("nc", nc)
116 }
117}
118
119template (value) Credentials ts_Credentials_OtherAuth(template (value) OtherAuth otherResponse) := {
120 otherResponse := otherResponse
121}
122
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200123template (present) Authorization tr_Authorization(template (present) Credentials body) := {
124 fieldName := AUTHORIZATION_E,
125 body := body
126}
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200127template (value) Authorization ts_Authorization(template (value) Credentials body) := {
128 fieldName := AUTHORIZATION_E,
129 body := body
130}
131
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100132// [20.10]
133template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?,
134 template charstring displayName := *) := {
135 displayName := displayName,
136 addrSpec := addrSpec
Harald Welteb0d93602018-03-20 18:09:34 +0100137}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100138template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec,
139 template (omit) charstring displayName := omit) := {
140 displayName := displayName,
141 addrSpec := addrSpec
142}
143
144template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := {
145 nameAddr := nameAddr
146}
147template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := {
148 nameAddr := nameAddr
149}
150
151template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := {
152 addrSpecUnion := sipUrl
153}
154template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := {
155 addrSpecUnion := sipUrl
156}
157
158
159template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?,
160 template SemicolonParam_List contactParams := *) := {
161 addressField := addressField,
162 contactParams := contactParams
163}
164template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField,
165 template (omit) SemicolonParam_List contactParams := omit) := {
166 addressField := addressField,
167 contactParams := contactParams
168}
169
170template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := {
171 fieldName := CONTACT_E,
172 contactBody := {
173 contactAddresses := contactAddresses
174 }
175}
176template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := {
177 fieldName := CONTACT_E,
178 contactBody := {
179 contactAddresses := contactAddresses
180 }
181}
182
183template (value) Contact ts_ContactWildcard := {
184 fieldName := CONTACT_E,
185 contactBody := {
186 wildcard := "*"
187 }
188}
189
190template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?)
191 := tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) });
192
193private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact
194{
195 if (istemplatekind(contact_addr, "omit")) {
196 return omit;
197 } else if (istemplatekind(contact_addr, "*")) {
198 return *;
199 }
200 return tr_Contact_SipAddr(contact_addr);
201}
202
203template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr)
204 := ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) });
205private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact
206{
207 if (istemplatekind(contact_addr, "omit")) {
208 return omit;
209 }
210 return ts_Contact_SipAddr(contact_addr);
211}
212
213
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200214// [20.14]
215template (value) ContentLength ts_ContentLength(template (value) integer len := 0) := {
216 fieldName := CONTENT_LENGTH_E,
217 len := len
218}
219template (present) ContentLength tr_ContentLength(template (present) integer len := ?) := {
220 fieldName := CONTENT_LENGTH_E,
221 len := len
222}
223
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100224// [20.19]
225template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := {
226 fieldName := EXPIRES_E,
227 deltaSec := deltaSec
228}
Pau Espin Pedrol586eec52024-06-04 19:07:33 +0200229template (present) Expires tr_Expires(template (present) DeltaSec deltaSec := ?) := {
230 fieldName := EXPIRES_E,
231 deltaSec := deltaSec
232}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100233
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200234// [20.20]
235template (value) From ts_From(template (value) Addr_Union addressField,
236 template (omit) SemicolonParam_List fromParams := omit) := {
237 fieldName := FROM_E,
238 addressField := addressField,
239 fromParams := fromParams
240}
241template (present) From tr_From(template (present) Addr_Union addressField := ?,
242 template SemicolonParam_List fromParams := *) := {
243 fieldName := FROM_E,
244 addressField := addressField,
245 fromParams := fromParams
246}
247
Pau Espin Pedrol27239402024-06-25 19:09:53 +0200248// [20.23]
249template (value) MinExpires ts_MinExpires(template (value) DeltaSec deltaSec := "800000") := {
250 fieldName := MIN_EXPIRES_E,
251 deltaSec := deltaSec
252}
253
Pau Espin Pedrol0c5c6472024-05-21 13:13:49 +0200254// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
255template (present) Access_net_spec tr_Access_net_spec(template (present) charstring access_type := ?,
256 template SemicolonParam_List access_info := *) := {
257 access_type := access_type,
258 access_info := access_info
259}
260template (present) Access_net_spec tr_Access_net_spec_EUTRAN(template (present) charstring uli_str := ?) := {
261 access_type := "3GPP-E-UTRAN-FDD",
262 access_info := {tr_Param("utran-cell-id-3gpp", uli_str)}
263}
264
265// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
266template (present) P_Access_Network_Info tr_P_Access_Network_Info(template (present) Access_net_spec_list access_net_specs := ?) := {
267 fieldName := P_ACCESS_NETWORK_INFO,
268 access_net_specs := access_net_specs
269}
270
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200271// [RFC3455 4.1]
272template (present) P_Assoc_uri_spec tr_P_Assoc_uri_spec(template (present) NameAddr p_asso_uri := ?,
273 template SemicolonParam_List ai_params := *) := {
274 p_asso_uri := p_asso_uri,
275 ai_params := ai_params
276}
277template (value) P_Assoc_uri_spec ts_P_Assoc_uri_spec(template (value) NameAddr p_asso_uri,
278 template (omit) SemicolonParam_List ai_params := omit) := {
279 p_asso_uri := p_asso_uri,
280 ai_params := ai_params
281}
282
283// [RFC3455 4.1]
284template (present) P_Associated_Uri tr_P_Associated_Uri(template (present) P_Assoc_uri_spec_list p_assoc_uris := ?) := {
285 fieldName := P_ASSOCIATED_URI,
286 p_assoc_uris := p_assoc_uris
287}
288template (value) P_Associated_Uri ts_P_Associated_Uri(template (value) P_Assoc_uri_spec_list p_assoc_uris := {}) := {
289 fieldName := P_ASSOCIATED_URI,
290 p_assoc_uris := p_assoc_uris
291}
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200292
Pau Espin Pedrol6088b892024-06-21 20:40:41 +0200293// [RFC6050]
294template (present) P_Preferred_Service tr_P_Preferred_Service(template (present) Service_ID_List p_ps := ?) := {
295 fieldName := P_PREFERRED_SERVICE_E,
296 p_ps := p_ps
297}
298
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200299// RFC 3262
300template (value) RAck ts_RAck(template (value) integer response_num,
301 template (value) integer seq_nr,
302 template (value) charstring method := "INVITE") := {
303 fieldName := RACK_E,
304 response_num := response_num,
305 seqNumber := seq_nr,
306 method := method
307}
308template (present) RAck tr_RAck(template (present) integer response_num := ?,
309 template (present) integer seq_nr := ?,
310 template (present) charstring method := ?) := {
311 fieldName := RACK_E,
312 response_num := response_num,
313 seqNumber := seq_nr,
314 method := method
315}
316
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200317// [20.32]
318template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := {
319 fieldName := REQUIRE_E,
320 optionsTags := optionsTags
321}
322template (present) Require tr_Require(template (present) OptionTag_List optionsTags := ?) := {
323 fieldName := REQUIRE_E,
324 optionsTags := optionsTags
325}
326
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200327// RFC 3262
328template (value) RSeq ts_RSeq(template (value) integer response_num) := {
329 fieldName := RSEQ_E,
330 response_num := response_num
331}
332template (present) RSeq tr_RSeq(template (present) integer response_num := ?) := {
333 fieldName := RSEQ_E,
334 response_num := response_num
335}
336
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200337// [20.35 RFC2616 14.38]
338template (value) Server ts_Server(template (value) ServerVal_List serverBody := {}) := {
339 fieldName := SERVER_E,
340 serverBody := serverBody
341}
342template (present) Server tr_Server(template (present) ServerVal_List serverBody := ?) := {
343 fieldName := SERVER_E,
344 serverBody := serverBody
345}
346
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200347// [20.37]
348template (value) Supported ts_Supported(template (value) OptionTag_List optionsTags := {}) := {
349 fieldName := SUPPORTED_E,
350 optionsTags := optionsTags
351}
352template (present) Supported tr_Supported(template (present) OptionTag_List optionsTags := ?) := {
353 fieldName := SUPPORTED_E,
354 optionsTags := optionsTags
355}
356
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200357// [20.39]
358template (value) To ts_To(template (value) Addr_Union addressField,
359 template (omit) SemicolonParam_List toParams := omit) := {
360 fieldName := TO_E,
361 addressField := addressField,
362 toParams := toParams
363}
364template (present) To tr_To(template (present) Addr_Union addressField := ?,
365 template SemicolonParam_List toParams := *) := {
366 fieldName := TO_E,
367 addressField := addressField,
368 toParams := toParams
369}
370
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200371// [20.41 RFC2616 14.43]
372template (value) UserAgent ts_UserAgent(template (value) ServerVal_List userAgentBody := {}) := {
373 fieldName := USER_AGENT_E,
374 userAgentBody := userAgentBody
375}
376template (present) UserAgent tr_UserAgent(template (present) ServerVal_List userAgentBody := ?) := {
377 fieldName := USER_AGENT_E,
378 userAgentBody := userAgentBody
379}
380
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200381
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100382template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
383 template (omit) UserInfo user_info := omit,
384 template (omit) charstring displayName := omit,
385 template (omit) SemicolonParam_List params := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100386 addr := {
387 nameAddr := {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100388 displayName := displayName,
389 addrSpec := ts_SipUrl(host_port, user_info)
Harald Welteb0d93602018-03-20 18:09:34 +0100390 }
391 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100392 params := params
393}
394template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
395 template UserInfo user_info := *,
396 template charstring displayName := *,
397 template SemicolonParam_List params := *) := {
398 addr := {
399 nameAddr := {
400 displayName := displayName,
401 addrSpec := tr_SipUrl(host_port, user_info)
402 }
403 },
404 params := params
Harald Welteb0d93602018-03-20 18:09:34 +0100405}
406
407/* build a receive template from a value: substitute '*' for omit */
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200408function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl {
409 var template (present) SipUrl ret := tin;
410
411 /* if the port number is 5060, it may be omitted */
412 if (ispresent(tin.hostPort.portField) and
413 valueof(tin.hostPort.portField) == 5060) {
414 ret.hostPort.portField := 5060 ifpresent;
415 }
416 if (not ispresent(tin.userInfo.password)) {
417 ret.userInfo.password := *;
418 }
419
420 return ret;
421}
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200422function tr_Addr_Union_from_val(template (value) Addr_Union tin) return template (present) Addr_Union {
423 var template (present) Addr_Union ret := tin;
424
425 if (not ispresent(tin.nameAddr.displayName)) {
426 ret.nameAddr.displayName := *;
427 } else if (f_str_tolower(f_sip_str_unquote(tin.nameAddr.displayName)) == "anonymous") {
428 /* if the user is Anonymous, it may be omitted */
429 ret.nameAddr.displayName := tin.nameAddr.displayName ifpresent;
430 }
431
432 ret.nameAddr.addrSpec := tr_SipUrl_from_val(tin.nameAddr.addrSpec);
433
434 return ret;
435}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200436function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100437 var template (present) SipAddr ret := tin;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200438
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200439 ret.addr := tr_Addr_Union_from_val(tin.addr);
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200440
441 if (not ispresent(tin.params)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100442 ret.params := *;
443 }
444 return ret;
445}
446
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200447function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
448 template (omit) SemicolonParam_List params := omit)
449return template (value) SipAddr {
450 var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
451 var template (omit) charstring displayName;
452
453 if (ischosen(au.nameAddr)) {
454 displayName := au.nameAddr.displayName;
455 } else { /* au.addrSpecUnion */
456 displayName := omit
457 }
458
459 return ts_SipAddr(addrSpec.hostPort,
460 addrSpec.userInfo,
461 displayName,
462 params);
463}
464
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100465template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
466 template (omit) integer portField := omit) := {
467 host := host,
468 portField := portField
469}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200470
471template (present) HostPort tr_HostPort(template charstring host := *,
472 template integer portField := *) := {
473 host := host,
474 portField := portField
475}
476function f_tr_HostPort(template charstring host := *,
477 template integer portField := *)
478return template (present) HostPort {
479 return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
480}
481function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort {
482 var template (present) HostPort hpout := hp;
Harald Welteb0d93602018-03-20 18:09:34 +0100483 /* if the port number is 5060, it may be omitted */
484 if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
485 hpout.portField := 5060 ifpresent;
486 }
487 return hpout;
488}
489
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200490function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl {
491 var template (present) SipUrl urlout := url;
492 urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
493 return urlout;
494}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100495
496template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
497 template (omit) charstring password := omit) := {
498 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
499 password := password
500}
501template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
502 template charstring password := *) := {
503 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
504 password := password
505}
506
507template (value) RequestLine ts_SIP_ReqLine(Method method,
508 template (value) SipUrl uri,
Harald Welteb0d93602018-03-20 18:09:34 +0100509 charstring ver := c_SIP_VERSION) := {
510 method := method,
511 requestUri := uri,
512 sipVersion := ver
513}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100514template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
515 template (present) SipUrl uri := ?,
516 template (present) charstring ver := c_SIP_VERSION) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100517 method := method,
518 requestUri := uri,
519 sipVersion := ver
520}
521
522template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
523 sipVersion := "SIP/2.0",
524 statusCode := status_code,
525 reasonPhrase := reason
526}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100527template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
528 template charstring reason) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100529 sipVersion := "SIP/2.0",
530 statusCode := status_code,
531 reasonPhrase := reason
532}
533
534
535template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
536 requestLine := rl,
537 msgHeader := c_SIP_msgHeader_empty,
538 messageBody := omit,
539 payload := omit
540}
541
542const Method_List c_SIP_defaultMethods := {
543 "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
544 "NOTIFY", "REFER", "UPDATE" };
545
546private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
547return template (omit) ContentType {
548 /* if user explicitly stated no content type */
549 if (istemplatekind(ct, "omit")) {
550 return omit;
551 }
552 /* if there's no body, then there's no content-type either */
553 if (istemplatekind(body, "omit")) {
554 return omit;
555 }
556 return ct;
557}
558
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200559private function f_ContentLength(template (omit) charstring body)
560return template (value) ContentLength {
561 /* rfc3261 20.14: "If no body is present in a message, then the
562 * Content-Length header field value MUST be set to zero." */
563 if (istemplatekind(body, "omit")) {
564 return ts_ContentLength(0);
565 }
566 return ts_ContentLength(lengthof(body));
567}
568
Harald Welteb0d93602018-03-20 18:09:34 +0100569template (value) ContentType ts_CT_SDP := {
570 fieldName := CONTENT_TYPE_E,
571 mediaType := "application/sdp"
572};
573
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200574template (value) Via ts_Via_from(template (value) HostPort addr,
575 template (value) charstring transport := "UDP") := {
Harald Welteb0d93602018-03-20 18:09:34 +0100576 fieldName := VIA_E,
577 viaBody := {
578 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200579 sentProtocol := { "SIP", "2.0", transport },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100580 sentBy := addr,
Harald Welteb0d93602018-03-20 18:09:34 +0100581 viaParams := omit
582 }
583 }
584}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100585template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200586 template (present) charstring transport := ?,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100587 template SemicolonParam_List viaParams := *) := {
588 fieldName := VIA_E,
589 viaBody := {
590 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200591 sentProtocol := { "SIP", "2.0", ? },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100592 sentBy := host_port,
593 viaParams := viaParams
594 }
595 }
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200596}
597
598template (present) OtherAuth
599tr_OtherAuth(template (present) charstring authScheme := ?,
600 template (present) CommaParam_List authParams := ?) := {
601 authScheme := authScheme,
602 authParams := authParams
603}
604
605template (value) OtherAuth
606ts_OtherAuth(template (value) charstring authScheme,
607 template (value) CommaParam_List authParams) := {
608 authScheme := authScheme,
609 authParams := authParams
610}
611
612template (present) Challenge
613tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := {
614 digestCln := digestCln
615}
616
617template (value) Challenge
618ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := {
619 digestCln := digestCln
620}
621
622template (present) Challenge
623tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := {
624 otherChallenge := otherChallenge
625}
626
627template (value) Challenge
628ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := {
629 otherChallenge := otherChallenge
630}
631
632template (present) WwwAuthenticate
633tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := {
634 fieldName := WWW_AUTHENTICATE_E,
635 challenge := challenge
636}
637
638template (value) WwwAuthenticate
639ts_WwwAuthenticate(template (value) Challenge_list challenge) := {
640 fieldName := WWW_AUTHENTICATE_E,
641 challenge := challenge
642}
Harald Welteb0d93602018-03-20 18:09:34 +0100643
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200644// RFC3329
645template (present) Security_client
646tr_Security_client(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
647 fieldName := SECURITY_CLIENT_E,
648 sec_mechanism_list := sec_mechanism_list
649}
650template (value) Security_client
651ts_Security_client(template (value) Security_mechanism_list sec_mechanism_list) := {
652 fieldName := SECURITY_CLIENT_E,
653 sec_mechanism_list := sec_mechanism_list
654}
655
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200656template (present) Security_server
657tr_Security_server(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
658 fieldName := SECURITY_SERVER_E,
659 sec_mechanism_list := sec_mechanism_list
660}
661template (value) Security_server
662ts_Security_server(template (value) Security_mechanism_list sec_mechanism_list) := {
663 fieldName := SECURITY_SERVER_E,
664 sec_mechanism_list := sec_mechanism_list
665}
666
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200667template (present) Security_mechanism
668tr_Security_mechanism(template (present) charstring name := ?,
669 template SemicolonParam_List params := *) := {
670 mechanism_name := name,
671 mechanism_params := params
672}
673template (value) Security_mechanism
674ts_Security_mechanism(template (value) charstring name,
675 template (omit) SemicolonParam_List params := omit) := {
676 mechanism_name := name,
677 mechanism_params := params
678}
679
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100680template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
681template (value) MessageHeader
682ts_SIP_msgh_std(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200683 template (value) From from_addr,
684 template (value) To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100685 template (omit) Contact contact,
686 template (value) charstring method,
687 template (value) integer seq_nr,
688 template (value) Via via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200689 template (omit) ContentLength content_length := ts_ContentLength(0),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100690 template (omit) ContentType content_type := omit,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200691 template (omit)Authorization authorization := omit,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200692 template (omit) Allow allow := ts_Allow(c_SIP_defaultMethods),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200693 template (omit) Expires expires := omit,
Pau Espin Pedrol27239402024-06-25 19:09:53 +0200694 template (omit) MinExpires minExpires := omit,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200695 template (omit) P_Associated_Uri p_associated_uri := omit,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200696 template (omit) RAck rack := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200697 template (omit) Require require := omit,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200698 template (omit) RSeq rseq := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200699 template (omit) Security_client security_client := omit,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200700 template (omit) Security_server security_server := omit,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200701 template (omit) Server server := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200702 template (omit) Supported supported := omit,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200703 template (omit) UserAgent userAgent := ts_UserAgent({ "osmo-ttcn3-hacks/0.23" }),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200704 template (omit) WwwAuthenticate wwwAuthenticate := omit
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100705 ) modifies ts_SIP_msgHeader_empty := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200706 allow := allow,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200707 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100708 callId := {
709 fieldName := CALL_ID_E,
710 callid := call_id
711 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100712 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200713 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100714 contentType := content_type,
715 cSeq := {
716 fieldName := CSEQ_E,
717 seqNumber := seq_nr,
718 method := method
719 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100720 expires := expires,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200721 fromField := from_addr,
Pau Espin Pedrol27239402024-06-25 19:09:53 +0200722 minExpires := minExpires,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200723 p_associated_uri := p_associated_uri,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200724 rack := rack,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200725 require := require,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200726 rseq := rseq,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200727 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200728 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200729 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200730 supported := supported,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200731 toField := to_addr,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200732 userAgent := userAgent,
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200733 via := via,
734 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100735}
736
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100737template (present) MessageHeader
738tr_SIP_msgh_std(template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200739 template From from_addr,
740 template To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100741 template Contact contact,
742 template (present) Via via := tr_Via_from(?),
743 template charstring method,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100744 template integer seq_nr := ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200745 template ContentLength content_length := *,
746 template ContentType content_type := *,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200747 template Allow allow := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200748 template Authorization authorization := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200749 template Expires expires := *,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200750 template P_Associated_Uri p_associated_uri := *,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200751 template RAck rack := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200752 template Require require := *,
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200753 template RSeq rseq := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200754 template Security_client security_client := *,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200755 template Security_server security_server := *,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200756 template Server server := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200757 template Supported supported := *,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200758 template UserAgent userAgent := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200759 template WwwAuthenticate wwwAuthenticate := *
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100760 ) modifies t_SIP_msgHeader_any := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200761 allow := allow,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200762 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100763 callId := {
764 fieldName := CALL_ID_E,
765 callid := call_id
766 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100767 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200768 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100769 contentType := content_type,
770 cSeq := {
771 fieldName := CSEQ_E,
772 seqNumber := seq_nr,
773 method := method
774 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100775 expires := expires,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200776 fromField := from_addr,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200777 p_associated_uri := p_associated_uri,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200778 rack := rack,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200779 require := require,
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200780 rseq := rseq,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200781 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200782 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200783 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200784 supported := supported,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200785 toField := to_addr,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200786 userAgent := userAgent,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200787 via := via,
788 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100789}
790
791
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100792template (value) PDU_SIP_Request
793ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
794 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200795 template (value) From from_addr,
796 template (value) To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100797 template (value) Via via,
798 integer seq_nr,
799 template (omit) Contact contact,
800 template (omit) Expires expires,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200801 template (omit) Authorization authorization := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200802 template (omit) Require require := omit,
803 template (omit) Security_client security_client := omit,
804 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100805 template (omit) charstring body := omit) := {
806 requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
807 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
808 "REGISTER", seq_nr, via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200809 content_length := f_ContentLength(body),
810 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200811 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200812 expires := expires,
813 require := require,
814 security_client := security_client,
815 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100816 messageBody := body,
817 payload := omit
818}
819template (present) PDU_SIP_Request
820tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
821 template (present) CallidString call_id := ?,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200822 template (present) From from_addr := ?,
823 template (present) To to_addr := ?,
Pau Espin Pedrol0dd3f262024-04-25 17:04:43 +0200824 template (present) Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100825 template integer seq_nr := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200826 template Authorization authorization := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100827 template Contact contact := *,
828 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200829 template Require require := *,
830 template Security_client security_client := *,
831 template Supported supported := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100832 template charstring body := *) := {
833 requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
834 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200835 via, "REGISTER", seq_nr,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200836 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200837 expires := expires,
838 require := require,
839 security_client := security_client,
840 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100841 messageBody := body,
842 payload := omit
843}
844
845template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200846ts_SIP_INVITE(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200847 template (value) From from_addr,
848 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200849 template (value) Via via,
850 template (value) Contact contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100851 integer seq_nr,
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200852 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100853 template (omit) charstring body := omit) := {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200854 requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addressField.nameAddr.addrSpec),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200855 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100856 "INVITE", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200857 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200858 content_length := f_ContentLength(body),
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200859 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
860 supported := supported),
Harald Welteb0d93602018-03-20 18:09:34 +0100861 messageBody := body,
862 payload := omit
863}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100864template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200865tr_SIP_INVITE(template (present) SipUrl uri,
866 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200867 template From from_addr,
868 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200869 template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100870 template integer seq_nr,
871 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200872 requestLine := tr_SIP_ReqLine(INVITE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100873 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200874 via, "INVITE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100875 messageBody := body,
876 payload := omit
877}
878
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100879template (value) PDU_SIP_Request
880ts_SIP_BYE(CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200881 template (value) From from_addr,
882 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200883 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100884 integer seq_nr,
885 template (omit) charstring body) := {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200886 requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addressField.nameAddr.addrSpec),
Harald Welteb0d93602018-03-20 18:09:34 +0100887 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200888 via,
889 content_length := f_ContentLength(body),
890 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100891 messageBody := body,
892 payload := omit
893}
894
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100895template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200896tr_SIP_BYE(template (present) SipUrl uri,
897 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200898 template From from_addr,
899 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200900 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100901 template integer seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200902 template charstring body := *) := {
903 requestLine := tr_SIP_ReqLine(BYE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100904 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200905 via, "BYE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100906 messageBody := body,
907 payload := omit
908}
909
910
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100911template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200912ts_SIP_ACK(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200913 template (value) From from_addr,
914 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200915 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100916 integer seq_nr,
917 template (omit) charstring body) := {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200918 requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addressField.nameAddr.addrSpec),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100919 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200920 ts_Contact({ ts_ContactAddress(from_addr.addressField, from_addr.fromParams) }),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100921 "ACK", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200922 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200923 content_length := f_ContentLength(body),
924 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100925 messageBody := body,
926 payload := omit
927}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100928template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200929tr_SIP_ACK(template (present) SipUrl uri,
930 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200931 template From from_addr,
932 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200933 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100934 template integer seq_nr,
935 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200936 requestLine := tr_SIP_ReqLine(ACK_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100937 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200938 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200939 "ACK", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100940 messageBody := body,
941 payload := omit
942}
943
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200944template (present) PDU_SIP_Request
945tr_SIP_CANCEL(template (present) SipUrl uri,
946 template (present) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200947 template (present) From from_addr,
948 template (present) To to_addr,
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200949 template (present) Via via,
950 template (present) integer seq_nr,
951 template charstring body := *) := {
952 requestLine := tr_SIP_ReqLine(CANCEL_E, uri),
953 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
954 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200955 "CANCEL", seq_nr),
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200956 messageBody := body,
957 payload := omit
958}
959
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200960template (value) PDU_SIP_Request
961ts_SIP_PRACK(template (value) SipUrl uri,
962 template (value) CallidString call_id,
963 template (value) From from_addr,
964 template (value) To to_addr,
965 template (value) Via via,
966 integer seq_nr,
967 template (value) RAck rack,
968 template (omit) charstring body := omit) := {
969 requestLine := ts_SIP_ReqLine(PRACK_E, uri),
970 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit,
971 "PRACK", seq_nr,
972 via,
973 content_length := f_ContentLength(body),
974 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
975 rack := rack),
976 messageBody := body,
977 payload := omit
978}
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200979template (present) PDU_SIP_Request
980tr_SIP_PRACK(template (present) SipUrl uri,
981 template CallidString call_id,
982 template From from_addr,
983 template To to_addr,
984 template Via via,
985 template integer seq_nr,
986 template RAck rack := tr_RAck(?, ?, ?),
987 template charstring body := *) := {
988 requestLine := tr_SIP_ReqLine(PRACK_E, uri),
989 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
990 via,
991 "PRACK", seq_nr,
992 rack := rack),
993 messageBody := body,
994 payload := omit
995}
996
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200997template (value) PDU_SIP_Request
998ts_SIP_UPDATE(template (value) SipUrl uri,
999 template (value) CallidString call_id,
1000 template (value) From from_addr,
1001 template (value) To to_addr,
1002 template (value) Via via,
1003 integer seq_nr,
1004 template (omit) Contact contact,
1005 template (value) Require require := ts_Require({"sec-agree", "precondition"}),
1006 template (value) charstring body) := {
1007 requestLine := ts_SIP_ReqLine(UPDATE_E, uri),
1008 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
1009 "UPDATE", seq_nr,
1010 via,
1011 require := require),
1012 messageBody := body,
1013 payload := omit
1014}
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +02001015template (present) PDU_SIP_Request
1016tr_SIP_UPDATE(template (present) SipUrl uri,
1017 template CallidString call_id,
1018 template From from_addr,
1019 template To to_addr,
1020 template Via via,
1021 template integer seq_nr,
1022 template Require require := *,
1023 template charstring body) := {
1024 requestLine := tr_SIP_ReqLine(UPDATE_E, uri),
1025 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1026 via,
1027 "UPDATE", seq_nr,
1028 require := require),
1029 messageBody := body,
1030 payload := omit
1031}
1032
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001033template (value) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001034ts_SIP_Response(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001035 template (value) From from_addr,
1036 template (value) To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001037 charstring method,
1038 integer status_code,
1039 integer seq_nr,
1040 charstring reason,
1041 Via via,
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001042 template (omit) Allow allow := omit,
Pau Espin Pedrol586eec52024-06-04 19:07:33 +02001043 template (omit) Contact contact := omit,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001044 template (omit) P_Associated_Uri p_associated_uri := omit,
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001045 template (omit) Require require := omit,
1046 template (omit) Server server := omit,
1047 template (omit) Supported supported := omit,
1048 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001049 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +01001050 statusLine := ts_SIP_StatusLine(status_code, reason),
Pau Espin Pedrol586eec52024-06-04 19:07:33 +02001051 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001052 via,
1053 content_length := f_ContentLength(body),
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001054 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1055 allow := allow,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001056 p_associated_uri := p_associated_uri,
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001057 require := require,
1058 server := server,
1059 supported := supported,
1060 userAgent := userAgent),
Harald Welteb0d93602018-03-20 18:09:34 +01001061 messageBody := body,
1062 payload := omit
1063}
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001064/* 100 Trying */
1065template (value) PDU_SIP_Response
1066ts_SIP_Response_Trying(
1067 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001068 template (value) From from_addr,
1069 template (value) To to_addr,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001070 Via via,
1071 integer seq_nr,
1072 charstring method := "INVITE",
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001073 template (omit) Allow allow := omit,
1074 template (omit) Server server := omit,
1075 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001076 template (omit) charstring body := omit) := {
1077 statusLine := ts_SIP_StatusLine(100, "Trying"),
1078 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001079 via,
1080 content_length := f_ContentLength(body),
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001081 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1082 allow := allow,
1083 server := server,
1084 userAgent := userAgent),
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001085 messageBody := body,
1086 payload := omit
1087}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001088/* 180 Ringing */
1089template (value) PDU_SIP_Response
1090ts_SIP_Response_Ringing(
1091 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001092 template (value) From from_addr,
1093 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001094 Via via,
1095 integer seq_nr,
1096 charstring method := "INVITE",
1097 template (omit) charstring body := omit) := {
1098 statusLine := ts_SIP_StatusLine(180, "Ringing"),
1099 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001100 via,
1101 content_length := f_ContentLength(body),
1102 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001103 messageBody := body,
1104 payload := omit
1105}
1106
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +02001107/* 183 Session Progress */
1108template (value) PDU_SIP_Response
1109ts_SIP_Response_SessionProgress(
1110 template (value) CallidString call_id,
1111 template (value) From from_addr,
1112 template (value) To to_addr,
1113 Via via,
1114 integer seq_nr,
1115 charstring method := "INVITE",
1116 template (omit) Require require := ts_Require({"100rel", "precondition"}),
1117 template (omit) RSeq rseq := ts_RSeq(1),
1118 template (omit) charstring body := omit) := {
1119 statusLine := ts_SIP_StatusLine(183, "Session Progress"),
1120 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
1121 via,
1122 content_length := f_ContentLength(body),
1123 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1124 require := require,
1125 rseq := rseq),
1126 messageBody := body,
1127 payload := omit
1128}
1129
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001130/* 401 Unauthorized */
1131template (value) PDU_SIP_Response
1132ts_SIP_Response_Unauthorized(
1133 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001134 template (value) From from_addr,
1135 template (value) To to_addr,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001136 Via via,
1137 template (value) WwwAuthenticate wwwAuthenticate,
1138 integer seq_nr,
1139 charstring method := "REGISTER",
1140 template (omit) Allow allow := omit,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001141 template (omit) P_Associated_Uri p_associated_uri := omit,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001142 template (omit) Security_server security_server := omit,
1143 template (omit) Server server := omit,
1144 template (omit) Supported supported := omit,
1145 template (omit) UserAgent userAgent := omit,
1146 template (omit) charstring body := omit) := {
1147 statusLine := ts_SIP_StatusLine(401, "Unauthorized"),
1148 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
1149 via,
1150 content_length := f_ContentLength(body),
1151 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1152 allow := allow,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001153 p_associated_uri := p_associated_uri,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001154 security_server := security_server,
1155 server := server,
1156 supported := supported,
1157 userAgent := userAgent,
1158 wwwAuthenticate := wwwAuthenticate),
1159 messageBody := body,
1160 payload := omit
1161}
1162
Pau Espin Pedrol27239402024-06-25 19:09:53 +02001163/* Tx 423 Interval Too Brief */
1164template (value) PDU_SIP_Response
1165ts_SIP_Response_423_Interval_Too_Brief(
1166 template (value) CallidString call_id,
1167 template (value) From from_addr,
1168 template (value) To to_addr,
1169 Via via,
1170 integer seq_nr,
1171 charstring method := "REGISTER",
1172 template (omit) Allow allow := omit,
1173 template (value) MinExpires minExpires := ts_MinExpires(),
1174 template (omit) Server server := omit,
1175 template (omit) Supported supported := omit,
1176 template (omit) UserAgent userAgent := omit) := {
1177 statusLine := ts_SIP_StatusLine(423, "Interval Too Brief"),
1178 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
1179 via,
1180 content_length := f_ContentLength(omit),
1181 content_type := f_ContentTypeOrOmit(ts_CT_SDP, omit),
1182 allow := allow,
1183 minExpires := minExpires,
1184 server := server,
1185 supported := supported,
1186 userAgent := userAgent),
1187 messageBody := omit,
1188 payload := omit
1189}
1190
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001191template (present) PDU_SIP_Response
1192tr_SIP_Response(template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001193 template From from_addr,
1194 template To to_addr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001195 template (present) Via via := tr_Via_from(?),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001196 template Contact contact,
1197 template charstring method,
1198 template integer status_code,
1199 template integer seq_nr := ?,
1200 template charstring reason := ?,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001201 template charstring body := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +01001202 statusLine := tr_SIP_StatusLine(status_code, reason),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001203 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001204 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001205 method, seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +01001206 messageBody := body,
1207 payload := omit
1208}
1209
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001210/* Expect during first REGISTER/INVITE/... when authorization is required: */
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001211template (present) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001212tr_SIP_Response_Unauthorized(
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001213 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001214 template From from_addr,
1215 template To to_addr,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001216 template (present) Via via := tr_Via_from(?),
1217 template Contact contact := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001218 template (present) WwwAuthenticate wwwAuthenticate := ?,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001219 template integer seq_nr := ?,
1220 template charstring method := "REGISTER",
1221 template integer status_code := 401,
1222 template charstring reason := "Unauthorized",
1223 template charstring body := *) := {
1224 statusLine := tr_SIP_StatusLine(status_code, reason),
1225 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
1226 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001227 method, seq_nr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001228 wwwAuthenticate := wwwAuthenticate),
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001229 messageBody := body,
1230 payload := omit
1231}
Harald Welteb0d93602018-03-20 18:09:34 +01001232
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001233/* 100 Trying */
1234template (present) PDU_SIP_Response
1235tr_SIP_Response_Trying(
1236 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001237 template From from_addr,
1238 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001239 template (present) Via via := tr_Via_from(?),
1240 template integer seq_nr := ?,
1241 template charstring method := "INVITE",
1242 template integer status_code := 100,
1243 template charstring reason := "Trying",
1244 template charstring body := *) := {
1245 statusLine := tr_SIP_StatusLine(status_code, reason),
1246 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
1247 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001248 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001249 messageBody := body,
1250 payload := omit
1251}
1252
1253/* 180 Ringing */
1254template (present) PDU_SIP_Response
1255tr_SIP_Response_Ringing(
1256 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001257 template From from_addr,
1258 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001259 template (present) Via via := tr_Via_from(?),
1260 template integer seq_nr := ?,
1261 template charstring method := "INVITE",
1262 template integer status_code := 180,
1263 template charstring reason := "Ringing",
1264 template charstring body := *) := {
1265 statusLine := tr_SIP_StatusLine(status_code, reason),
1266 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1267 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001268 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001269 messageBody := body,
1270 payload := omit
1271}
1272
Pau Espin Pedrolce370df2024-06-18 13:45:53 +02001273/* 183 Session Progress */
1274template (present) PDU_SIP_Response
1275tr_SIP_Response_SessionProgress(
1276 template (present) CallidString call_id,
1277 template (present) From from_addr,
1278 template (present) To to_addr,
1279 template (present) Via via,
1280 template (present) integer seq_nr := ?,
1281 template (present) charstring method := "INVITE",
1282 template Require require := *,
1283 template RSeq rseq := *,
1284 template (omit) charstring body := omit) := {
1285 statusLine := tr_SIP_StatusLine(183, "Session Progress"),
1286 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1287 via,
1288 method, seq_nr,
1289 require := require,
1290 rseq := rseq),
1291 messageBody := body,
1292 payload := omit
1293}
1294
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001295/****************
1296 * FUNCTIONS:
1297 ****************/
1298
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001299function f_sip_param_find(GenericParam_List li,
1300 template (present) charstring id := ?)
1301return template (omit) GenericParam {
1302 var integer i;
1303
1304 for (i := 0; i < lengthof(li); i := i + 1) {
1305 if (not ispresent(li[i])) {
1306 continue;
1307 }
1308 if (match(li[i].id, id)) {
1309 return li[i];
1310 }
1311 }
1312 return omit;
1313}
1314
1315function f_sip_param_find_or_fail(GenericParam_List li,
1316 template (present) charstring id := ?)
1317return GenericParam {
1318 var template (omit) GenericParam parameter;
1319 parameter := f_sip_param_find(li, id);
1320 if (istemplatekind(parameter, "omit")) {
1321 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1322 log2str("Param ", id, " not found in ", li));
1323 }
1324 return valueof(parameter);
1325}
1326
1327function f_sip_param_get_value(GenericParam_List li,
1328 template (present) charstring id := ?)
1329return template (omit) charstring {
1330 var template (omit) GenericParam parameter;
1331 parameter := f_sip_param_find(li, id);
1332 if (istemplatekind(parameter, "omit")) {
1333 return omit;
1334 }
1335 return parameter.paramValue;
1336}
1337
1338function f_sip_param_get_value_or_fail(GenericParam_List li,
1339 template (present) charstring id := ?)
1340return template (omit) charstring {
1341 var GenericParam parameter;
1342 parameter := f_sip_param_find_or_fail(li, id);
1343 return parameter.paramValue;
1344}
1345
1346function f_sip_param_get_value_present_or_fail(GenericParam_List li,
1347 template (present) charstring id := ?)
1348return charstring {
1349 var GenericParam parameter;
1350 parameter := f_sip_param_find_or_fail(li, id);
1351 if (not ispresent(parameter.paramValue)) {
1352 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1353 log2str("Param ", id, " value not present in ", li));
1354 }
1355 return parameter.paramValue;
1356}
1357
1358function f_sip_param_match_value(GenericParam_List li,
1359 template (present) charstring id := ?,
1360 template charstring exp_paramValue := *)
1361return boolean {
1362 var template (omit) charstring val;
1363 val := f_sip_param_get_value_or_fail(li, id);
1364 if (istemplatekind(val, "omit")) {
1365 return istemplatekind(val, "omit") or istemplatekind(val, "*");
1366 }
1367 return match(valueof(val), exp_paramValue);
1368}
1369
1370function f_sip_param_match_value_or_fail(GenericParam_List li,
1371 template (present) charstring id := ?,
1372 template charstring exp_paramValue := *)
1373{
1374 var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id);
1375 if (istemplatekind(val, "omit")) {
1376 if (istemplatekind(val, "omit") or istemplatekind(val, "*")) {
1377 return;
1378 } else {
1379 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1380 log2str("Param ", id, " match failed: val ", val,
1381 " vs exp ", exp_paramValue));
1382 }
1383 }
1384 if (not match(valueof(val), exp_paramValue)) {
1385 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1386 log2str("Param ", id, " match failed: val ", val,
1387 " vs exp ", exp_paramValue));
1388 }
1389}
1390
1391function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id)
1392return GenericParam_List {
1393 var integer i;
1394 var GenericParam_List li;
1395 var GenericParam_List new_li := {};
1396
1397 if (istemplatekind(li_tpl, "omit")) {
1398 return {};
1399 }
1400
1401 li := valueof(li_tpl);
1402 for (i := 0; i < lengthof(li); i := i + 1) {
1403 if (not ispresent(li[i]) or
1404 not match(li[i].id, id)) {
1405 new_li := new_li & {li[i]};
1406 }
1407 }
1408 return new_li;
1409}
1410
1411function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val)
1412return GenericParam_List {
1413 var integer i;
1414 var GenericParam_List li;
1415 var GenericParam_List new_li := {};
1416 var boolean found := false;
1417
1418 if (istemplatekind(li_tpl, "omit")) {
1419 return { valueof(ts_Param(id, val)) };
1420 }
1421
1422 li := valueof(li_tpl);
1423 for (i := 0; i < lengthof(li); i := i + 1) {
1424 if (not ispresent(li[i]) or
1425 not match(li[i].id, id)) {
1426 new_li := new_li & {li[i]};
1427 continue;
1428 }
1429 new_li := new_li & { valueof(ts_Param(li[i].id, val)) };
1430 found := true;
1431 }
1432
1433 if (not found) {
1434 new_li := new_li & { valueof(ts_Param(id, val)) };
1435 }
1436 return new_li;
1437}
1438
1439/* Make sure string is quoted. */
1440function f_sip_str_quote(template (value) charstring val) return charstring {
1441 var charstring str := valueof(val);
1442 if (lengthof(str) == 0) {
1443 return "";
1444 }
1445
1446 if (str[0] != "\"") {
1447 return "\"" & str & "\"";
1448 }
1449 return str;
1450}
1451
1452/* Make sure string is unquoted.
1453 * Similar to unq() in RFC 2617 */
1454function f_sip_str_unquote(template (value) charstring val) return charstring {
1455 var charstring str := valueof(val);
1456 var integer len := lengthof(str);
1457
1458 if (len <= 1) {
1459 return str;
1460 }
1461
1462 if (str[0] == "\"" and str[len - 1] == "\"") {
1463 return substr(str, 1, len - 2);
1464 }
1465 return str;
1466}
1467
1468/* RFC 2617 3.2.2.2 A1 */
1469function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring {
1470
1471 /* RFC 2617 3.2.2.2 A1 */
1472 var charstring A1 := f_sip_str_unquote(user) & ":" &
1473 f_sip_str_unquote(realm) & ":" &
1474 password;
1475 var charstring digestA1 := f_str_tolower(f_calculateMD5(A1));
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001476 log("A1: md5(", A1, ") = ", digestA1);
1477 return digestA1;
1478}
1479
1480/* RFC 3310: Same as f_sip_digest_A1(), but using an octet buffer as password (AKAv1-MD5, pwd=RES) */
1481function f_sip_digest_A1_octpwd(charstring user, charstring realm, octetstring password) return charstring {
1482 var charstring A1pre := f_sip_str_unquote(user) & ":" &
1483 f_sip_str_unquote(realm) & ":";
1484 var octetstring A1 := char2oct(A1pre) & password;
1485 var charstring digestA1 := f_str_tolower(oct2str(f_calculateMD5_oct(A1)));
1486 log("A1-octpwd: md5(", A1, ") = ", digestA1);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001487 return digestA1;
1488}
1489
1490/* RFC 2617 3.2.2.2 A2 */
1491function f_sip_digest_A2(charstring method, charstring uri) return charstring {
1492
1493 var charstring A2 := method & ":" & uri
1494 var charstring digestA2 := f_str_tolower(f_calculateMD5(A2));
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001495 log("A2: md5(", A2, ") = ", digestA2);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001496 return digestA2;
1497}
1498
1499/* RFC 2617 3.2.2.1 Request-Digest */
1500function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce,
1501 charstring nc, charstring cnonce,
1502 charstring qop, charstring digestA2) return charstring {
1503 var charstring digest_data := f_sip_str_unquote(nonce) & ":" &
1504 nc & ":" &
1505 cnonce & ":" &
1506 f_sip_str_unquote(qop) & ":" &
1507 digestA2;
1508 var charstring req_digest := f_sip_digest_KD(digestA1, digest_data);
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001509 log("Request-Digest: md5(\"" & digestA1 & ":" & digest_data & "\") = " & "\"" & req_digest & "\"");
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001510 return req_digest;
1511}
1512
1513/* RFC 2617 3.2.1 The WWW-Authenticate Response Header
1514 * KD(secret, data) = H(concat(secret, ":", data))
1515 */
1516function f_sip_digest_KD(charstring secret, charstring data) return charstring {
1517 return f_str_tolower(f_calculateMD5(secret & ":" & data));
1518}
1519
1520/* Digest Auth: RFC 2617 */
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001521function f_sip_digest_gen_Authorization_Response_MD5(charstring user, charstring realm, charstring password,
1522 charstring method, charstring uri, charstring qop,
1523 charstring nonce, charstring cnonce, charstring nc)
1524return charstring {
1525 /* RFC 2617 3.2.2.2 A1 */
1526 var charstring digestA1 := f_sip_digest_A1(user, realm, password);
1527
1528 /* RFC 2617 3.2.2.3 A2 */
1529 var charstring digestA2 := f_sip_digest_A2(method, uri);
1530
1531 /* RFC 2617 3.2.2.1 Request-Digest */
1532 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1533 nc, cnonce,
1534 qop, digestA2);
1535 return req_digest;
1536}
1537
1538/* Digest Auth: RFC 2617 */
1539function f_sip_digest_gen_Authorization_Response_AKAv1MD5(charstring user, charstring realm, octetstring password,
1540 charstring method, charstring uri, charstring qop,
1541 charstring nonce, charstring cnonce, charstring nc)
1542return charstring {
1543 /* RFC 2617 3.2.2.2 A1 */
1544 var charstring digestA1 := f_sip_digest_A1_octpwd(user, realm, password);
1545 /* RFC 2617 3.2.2.3 A2 */
1546 var charstring digestA2 := f_sip_digest_A2(method, uri);
1547
1548 /* RFC 2617 3.2.2.1 Request-Digest */
1549 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1550 nc, cnonce,
1551 qop, digestA2);
1552 return req_digest;
1553}
1554
1555function f_sip_digest_gen_Authorization_MD5(WwwAuthenticate www_authenticate,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001556 charstring user, charstring password,
1557 charstring method, charstring uri,
1558 charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization {
1559 var CommaParam_List digestCln;
1560 var template (value) Authorization authorization;
1561 var template (value) Credentials cred;
1562 var template (omit) GenericParam rx_param;
1563
1564 digestCln := www_authenticate.challenge[0].digestCln;
1565
1566 var charstring algorithm;
1567 rx_param := f_sip_param_find(digestCln, "algorithm");
1568 if (istemplatekind(rx_param, "omit")) {
1569 /* Assume MD5 if not set */
1570 algorithm := "MD5"
1571 } else {
1572 algorithm := valueof(rx_param.paramValue);
1573 if (f_strstr(algorithm, "MD5") == -1) {
1574 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1575 log2str("Unexpected algorithm: ", algorithm));
1576 }
1577 }
1578
1579 var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
1580 var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
1581 var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque");
1582 var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop");
1583
1584 if (f_strstr(qop, "auth") == -1) {
1585 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1586 }
1587 var charstring selected_qop := "auth";
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001588 var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8)));
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001589
1590 var charstring req_digest;
1591 req_digest :=
1592 f_sip_digest_gen_Authorization_Response_MD5(user, realm, password,
1593 method, uri, selected_qop,
1594 nonce, cnonce, nc);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001595
1596 cred := ts_Credentials_DigestResponseMD5(user, realm, nonce,
1597 uri, req_digest,
1598 opaque, algorithm, selected_qop, cnonce, nc);
1599
1600 authorization := ts_Authorization(cred);
1601 return valueof(authorization);
1602}
1603
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001604/* RFC 3310: Same as f_sip_digest_validate_Authorization_MD5(), but using an octet buffer as password (AKAv1-MD5, pwd=RES) */
1605function f_sip_digest_validate_Authorization_AKAv1MD5(Authorization authorization, charstring method, octetstring password) {
1606 var CommaParam_List auth_pars := authorization.body.digestResponse;
1607 var template (omit) GenericParam rx_param;
1608
1609 rx_param := f_sip_param_find(auth_pars, "algorithm");
1610 if (istemplatekind(rx_param, "omit")) {
1611 /* Assume MD5 if not set */
1612 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Algorithm param not present");
1613 } else {
1614 var charstring algorithm := valueof(rx_param.paramValue);
1615 if (f_strstr(algorithm, "AKAv1-MD5") == -1) {
1616 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1617 log2str("Unexpected algorithm: ", algorithm));
1618 }
1619 }
1620
1621 var charstring user := f_sip_param_get_value_present_or_fail(auth_pars, "username");
1622 var charstring realm := f_sip_param_get_value_present_or_fail(auth_pars, "realm");
1623 var charstring uri := f_sip_param_get_value_present_or_fail(auth_pars, "uri");
1624 var charstring nonce := f_sip_param_get_value_present_or_fail(auth_pars, "nonce");
1625 var charstring qop := f_sip_param_get_value_present_or_fail(auth_pars, "qop");
1626 var charstring response := f_sip_param_get_value_present_or_fail(auth_pars, "response");
1627 var charstring cnonce := f_sip_param_get_value_present_or_fail(auth_pars, "cnonce");
1628 var charstring nc := f_sip_param_get_value_present_or_fail(auth_pars, "nc");
1629
1630 if (f_strstr(qop, "auth") == -1) {
1631 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1632 }
1633
1634 var charstring exp_response :=
1635 f_sip_digest_gen_Authorization_Response_AKAv1MD5(f_sip_str_unquote(user),
1636 f_sip_str_unquote(realm),
1637 password,
1638 method,
1639 f_sip_str_unquote(uri),
1640 qop,
1641 f_sip_str_unquote(nonce),
1642 f_sip_str_unquote(cnonce),
1643 nc);
1644
1645 response := f_sip_str_unquote(response);
1646 if (response != exp_response) {
1647 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1648 log2str("Wrong digest response: ", response,
1649 " vs exp: ", exp_response, ". Params: ", auth_pars));
1650 }
1651}
1652
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001653/* RFC 2617 3.5 Example */
1654function f_sip_digest_selftest() {
1655/*
1656The following example assumes that an access-protected document is
1657being requested from the server via a GET request. The URI of the
1658document is "http://www.nowhere.org/dir/index.html". Both client and
1659server know that the username for this document is "Mufasa", and the
1660password is "Circle Of Life" (with one space between each of the
1661three words).
1662
1663HTTP/1.1 401 Unauthorized
1664WWW-Authenticate: Digest
1665 realm="testrealm@host.com",
1666 qop="auth,auth-int",
1667 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1668 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1669
1670Authorization: Digest username="Mufasa",
1671 realm="testrealm@host.com",
1672 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1673 uri="/dir/index.html",
1674 qop=auth,
1675 nc=00000001,
1676 cnonce="0a4f113b",
1677 response="6629fae49393a05397450978507c4ef1",
1678 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1679*/
1680 var template (value) CommaParam_List digestCln := {
1681 ts_Param("realm", f_sip_str_quote("testrealm@host.com")),
1682 ts_Param("qop", f_sip_str_quote("auth,auth-int")),
1683 ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")),
1684 ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"))
1685 };
1686 var template (value) WwwAuthenticate www_authenticate :=
1687 ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
1688
1689 var Authorization authorization :=
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001690 f_sip_digest_gen_Authorization_MD5(valueof(www_authenticate),
1691 "Mufasa",
1692 "Circle Of Life",
1693 "GET",
1694 "/dir/index.html",
1695 cnonce := "0a4f113b",
1696 nc_int := 1);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001697
1698 var CommaParam_List digestResp := authorization.body.digestResponse;
1699 f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com"));
1700 f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093"));
1701 f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html"));
1702 f_sip_param_match_value_or_fail(digestResp, "qop", "auth");
1703 f_sip_param_match_value_or_fail(digestResp, "nc", "00000001");
1704 f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b"));
1705 f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1"));
1706 f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"));
1707}
1708
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01001709/* RFC 3261 8.1.1.5:
1710 * "The sequence number value MUST be expressible as a 32-bit unsigned integer
1711 * and MUST be less than 2**31."
1712 */
1713function f_sip_rand_seq_nr() return integer {
1714 /* 2**31 = 2147483648 */
1715 return f_rnd_int(2147483648)
1716}
Harald Welteb0d93602018-03-20 18:09:34 +01001717
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001718function f_sip_next_seq_nr(integer seq_nr) return integer {
1719 return (seq_nr + 1) mod 2147483648;
1720}
1721
1722function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
1723 req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
1724}
1725
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001726function f_sip_rand_tag() return charstring {
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001727 /* Tags shall have at least 32 bit of randomness */
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001728 var integer rnd_int := f_rnd_int(4294967296);
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001729 /* Make collisions harder by appending time to the final string: */
1730 var integer ts_int := f_time_ms() mod 4294967296;
1731 return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8));
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001732}
1733
1734/* Generate a "branch" tag value.
1735 * RFC 3261 p.105 section 8:
1736 * "A common way to create this value is to compute a
1737 * cryptographic hash of the To tag, From tag, Call-ID header
1738 * field, the Request-URI of the request received (before
1739 * translation), the topmost Via header, and the sequence number
1740 * from the CSeq header field, in addition to any Proxy-Require
1741 * and Proxy-Authorization header fields that may be present. The
1742 * algorithm used to compute the hash is implementation-dependent,
1743 * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable
1744 * choice."
1745 * See also Section 8.1.1.7:
1746 * "The branch ID inserted by an element compliant with this
1747 * specification MUST always begin with the characters "z9hG4bK"."
1748 */
1749const charstring sip_magic_cookie := "z9hG4bK";
1750function f_sip_gen_branch(charstring tag_to,
1751 charstring tag_from,
1752 charstring tag_call_id,
1753 integer cseq) return charstring {
1754 var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq);
1755 var charstring hash := f_calculateMD5(str);
1756 var charstring branch := sip_magic_cookie & hash;
1757 return branch;
1758}
1759
1760function f_sip_HostPort_to_str(HostPort host_port) return charstring {
1761 var charstring str := "";
1762 if (ispresent(host_port.host)) {
1763 str := host_port.host;
1764 }
1765 if (ispresent(host_port.portField)) {
1766 str := str & ":" & int2str(host_port.portField);
1767 }
1768 return str;
1769}
1770
1771function f_sip_SipUrl_to_str(SipUrl uri) return charstring {
Pau Espin Pedrolb0dbf7a2024-05-22 18:12:15 +02001772 var charstring str := uri.scheme & ":";
1773 if (ispresent(uri.userInfo)) {
1774 str := str & uri.userInfo.userOrTelephoneSubscriber & "@";
1775 }
1776 str := str & f_sip_HostPort_to_str(uri.hostPort);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001777 return str;
1778}
1779
1780function f_sip_NameAddr_to_str(NameAddr naddr) return charstring {
1781 if (ispresent(naddr.displayName)) {
1782 return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">";
1783 } else {
1784 return f_sip_SipUrl_to_str(naddr.addrSpec);
1785 }
1786}
1787
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001788function f_sip_Addr_Union_to_str(Addr_Union addru) return charstring {
1789 if (ischosen(addru.nameAddr)) {
1790 return f_sip_NameAddr_to_str(addru.nameAddr);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001791 } else {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001792 return f_sip_SipUrl_to_str(addru.addrSpecUnion);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001793 }
1794}
1795
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001796function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring {
1797 return f_sip_Addr_Union_to_str(sip_addr.addr);
1798}
1799
Harald Welteb0d93602018-03-20 18:09:34 +01001800}