blob: ce5998b61b3a445551b323e0ee4228b6fefa54a5 [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 Pedrol0c5c6472024-05-21 13:13:49 +0200248// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
249template (present) Access_net_spec tr_Access_net_spec(template (present) charstring access_type := ?,
250 template SemicolonParam_List access_info := *) := {
251 access_type := access_type,
252 access_info := access_info
253}
254template (present) Access_net_spec tr_Access_net_spec_EUTRAN(template (present) charstring uli_str := ?) := {
255 access_type := "3GPP-E-UTRAN-FDD",
256 access_info := {tr_Param("utran-cell-id-3gpp", uli_str)}
257}
258
259// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
260template (present) P_Access_Network_Info tr_P_Access_Network_Info(template (present) Access_net_spec_list access_net_specs := ?) := {
261 fieldName := P_ACCESS_NETWORK_INFO,
262 access_net_specs := access_net_specs
263}
264
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200265// [RFC3455 4.1]
266template (present) P_Assoc_uri_spec tr_P_Assoc_uri_spec(template (present) NameAddr p_asso_uri := ?,
267 template SemicolonParam_List ai_params := *) := {
268 p_asso_uri := p_asso_uri,
269 ai_params := ai_params
270}
271template (value) P_Assoc_uri_spec ts_P_Assoc_uri_spec(template (value) NameAddr p_asso_uri,
272 template (omit) SemicolonParam_List ai_params := omit) := {
273 p_asso_uri := p_asso_uri,
274 ai_params := ai_params
275}
276
277// [RFC3455 4.1]
278template (present) P_Associated_Uri tr_P_Associated_Uri(template (present) P_Assoc_uri_spec_list p_assoc_uris := ?) := {
279 fieldName := P_ASSOCIATED_URI,
280 p_assoc_uris := p_assoc_uris
281}
282template (value) P_Associated_Uri ts_P_Associated_Uri(template (value) P_Assoc_uri_spec_list p_assoc_uris := {}) := {
283 fieldName := P_ASSOCIATED_URI,
284 p_assoc_uris := p_assoc_uris
285}
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200286
Pau Espin Pedrol6088b892024-06-21 20:40:41 +0200287// [RFC6050]
288template (present) P_Preferred_Service tr_P_Preferred_Service(template (present) Service_ID_List p_ps := ?) := {
289 fieldName := P_PREFERRED_SERVICE_E,
290 p_ps := p_ps
291}
292
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200293// RFC 3262
294template (value) RAck ts_RAck(template (value) integer response_num,
295 template (value) integer seq_nr,
296 template (value) charstring method := "INVITE") := {
297 fieldName := RACK_E,
298 response_num := response_num,
299 seqNumber := seq_nr,
300 method := method
301}
302template (present) RAck tr_RAck(template (present) integer response_num := ?,
303 template (present) integer seq_nr := ?,
304 template (present) charstring method := ?) := {
305 fieldName := RACK_E,
306 response_num := response_num,
307 seqNumber := seq_nr,
308 method := method
309}
310
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200311// [20.32]
312template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := {
313 fieldName := REQUIRE_E,
314 optionsTags := optionsTags
315}
316template (present) Require tr_Require(template (present) OptionTag_List optionsTags := ?) := {
317 fieldName := REQUIRE_E,
318 optionsTags := optionsTags
319}
320
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200321// RFC 3262
322template (value) RSeq ts_RSeq(template (value) integer response_num) := {
323 fieldName := RSEQ_E,
324 response_num := response_num
325}
326template (present) RSeq tr_RSeq(template (present) integer response_num := ?) := {
327 fieldName := RSEQ_E,
328 response_num := response_num
329}
330
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200331// [20.35 RFC2616 14.38]
332template (value) Server ts_Server(template (value) ServerVal_List serverBody := {}) := {
333 fieldName := SERVER_E,
334 serverBody := serverBody
335}
336template (present) Server tr_Server(template (present) ServerVal_List serverBody := ?) := {
337 fieldName := SERVER_E,
338 serverBody := serverBody
339}
340
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200341// [20.37]
342template (value) Supported ts_Supported(template (value) OptionTag_List optionsTags := {}) := {
343 fieldName := SUPPORTED_E,
344 optionsTags := optionsTags
345}
346template (present) Supported tr_Supported(template (present) OptionTag_List optionsTags := ?) := {
347 fieldName := SUPPORTED_E,
348 optionsTags := optionsTags
349}
350
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200351// [20.39]
352template (value) To ts_To(template (value) Addr_Union addressField,
353 template (omit) SemicolonParam_List toParams := omit) := {
354 fieldName := TO_E,
355 addressField := addressField,
356 toParams := toParams
357}
358template (present) To tr_To(template (present) Addr_Union addressField := ?,
359 template SemicolonParam_List toParams := *) := {
360 fieldName := TO_E,
361 addressField := addressField,
362 toParams := toParams
363}
364
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200365// [20.41 RFC2616 14.43]
366template (value) UserAgent ts_UserAgent(template (value) ServerVal_List userAgentBody := {}) := {
367 fieldName := USER_AGENT_E,
368 userAgentBody := userAgentBody
369}
370template (present) UserAgent tr_UserAgent(template (present) ServerVal_List userAgentBody := ?) := {
371 fieldName := USER_AGENT_E,
372 userAgentBody := userAgentBody
373}
374
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200375
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100376template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
377 template (omit) UserInfo user_info := omit,
378 template (omit) charstring displayName := omit,
379 template (omit) SemicolonParam_List params := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100380 addr := {
381 nameAddr := {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100382 displayName := displayName,
383 addrSpec := ts_SipUrl(host_port, user_info)
Harald Welteb0d93602018-03-20 18:09:34 +0100384 }
385 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100386 params := params
387}
388template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
389 template UserInfo user_info := *,
390 template charstring displayName := *,
391 template SemicolonParam_List params := *) := {
392 addr := {
393 nameAddr := {
394 displayName := displayName,
395 addrSpec := tr_SipUrl(host_port, user_info)
396 }
397 },
398 params := params
Harald Welteb0d93602018-03-20 18:09:34 +0100399}
400
401/* build a receive template from a value: substitute '*' for omit */
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200402function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl {
403 var template (present) SipUrl ret := tin;
404
405 /* if the port number is 5060, it may be omitted */
406 if (ispresent(tin.hostPort.portField) and
407 valueof(tin.hostPort.portField) == 5060) {
408 ret.hostPort.portField := 5060 ifpresent;
409 }
410 if (not ispresent(tin.userInfo.password)) {
411 ret.userInfo.password := *;
412 }
413
414 return ret;
415}
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200416function tr_Addr_Union_from_val(template (value) Addr_Union tin) return template (present) Addr_Union {
417 var template (present) Addr_Union ret := tin;
418
419 if (not ispresent(tin.nameAddr.displayName)) {
420 ret.nameAddr.displayName := *;
421 } else if (f_str_tolower(f_sip_str_unquote(tin.nameAddr.displayName)) == "anonymous") {
422 /* if the user is Anonymous, it may be omitted */
423 ret.nameAddr.displayName := tin.nameAddr.displayName ifpresent;
424 }
425
426 ret.nameAddr.addrSpec := tr_SipUrl_from_val(tin.nameAddr.addrSpec);
427
428 return ret;
429}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200430function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100431 var template (present) SipAddr ret := tin;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200432
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200433 ret.addr := tr_Addr_Union_from_val(tin.addr);
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200434
435 if (not ispresent(tin.params)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100436 ret.params := *;
437 }
438 return ret;
439}
440
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200441function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
442 template (omit) SemicolonParam_List params := omit)
443return template (value) SipAddr {
444 var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
445 var template (omit) charstring displayName;
446
447 if (ischosen(au.nameAddr)) {
448 displayName := au.nameAddr.displayName;
449 } else { /* au.addrSpecUnion */
450 displayName := omit
451 }
452
453 return ts_SipAddr(addrSpec.hostPort,
454 addrSpec.userInfo,
455 displayName,
456 params);
457}
458
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100459template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
460 template (omit) integer portField := omit) := {
461 host := host,
462 portField := portField
463}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200464
465template (present) HostPort tr_HostPort(template charstring host := *,
466 template integer portField := *) := {
467 host := host,
468 portField := portField
469}
470function f_tr_HostPort(template charstring host := *,
471 template integer portField := *)
472return template (present) HostPort {
473 return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
474}
475function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort {
476 var template (present) HostPort hpout := hp;
Harald Welteb0d93602018-03-20 18:09:34 +0100477 /* if the port number is 5060, it may be omitted */
478 if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
479 hpout.portField := 5060 ifpresent;
480 }
481 return hpout;
482}
483
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200484function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl {
485 var template (present) SipUrl urlout := url;
486 urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
487 return urlout;
488}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100489
490template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
491 template (omit) charstring password := omit) := {
492 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
493 password := password
494}
495template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
496 template charstring password := *) := {
497 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
498 password := password
499}
500
501template (value) RequestLine ts_SIP_ReqLine(Method method,
502 template (value) SipUrl uri,
Harald Welteb0d93602018-03-20 18:09:34 +0100503 charstring ver := c_SIP_VERSION) := {
504 method := method,
505 requestUri := uri,
506 sipVersion := ver
507}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100508template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
509 template (present) SipUrl uri := ?,
510 template (present) charstring ver := c_SIP_VERSION) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100511 method := method,
512 requestUri := uri,
513 sipVersion := ver
514}
515
516template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
517 sipVersion := "SIP/2.0",
518 statusCode := status_code,
519 reasonPhrase := reason
520}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100521template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
522 template charstring reason) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100523 sipVersion := "SIP/2.0",
524 statusCode := status_code,
525 reasonPhrase := reason
526}
527
528
529template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
530 requestLine := rl,
531 msgHeader := c_SIP_msgHeader_empty,
532 messageBody := omit,
533 payload := omit
534}
535
536const Method_List c_SIP_defaultMethods := {
537 "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
538 "NOTIFY", "REFER", "UPDATE" };
539
540private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
541return template (omit) ContentType {
542 /* if user explicitly stated no content type */
543 if (istemplatekind(ct, "omit")) {
544 return omit;
545 }
546 /* if there's no body, then there's no content-type either */
547 if (istemplatekind(body, "omit")) {
548 return omit;
549 }
550 return ct;
551}
552
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200553private function f_ContentLength(template (omit) charstring body)
554return template (value) ContentLength {
555 /* rfc3261 20.14: "If no body is present in a message, then the
556 * Content-Length header field value MUST be set to zero." */
557 if (istemplatekind(body, "omit")) {
558 return ts_ContentLength(0);
559 }
560 return ts_ContentLength(lengthof(body));
561}
562
Harald Welteb0d93602018-03-20 18:09:34 +0100563template (value) ContentType ts_CT_SDP := {
564 fieldName := CONTENT_TYPE_E,
565 mediaType := "application/sdp"
566};
567
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200568template (value) Via ts_Via_from(template (value) HostPort addr,
569 template (value) charstring transport := "UDP") := {
Harald Welteb0d93602018-03-20 18:09:34 +0100570 fieldName := VIA_E,
571 viaBody := {
572 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200573 sentProtocol := { "SIP", "2.0", transport },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100574 sentBy := addr,
Harald Welteb0d93602018-03-20 18:09:34 +0100575 viaParams := omit
576 }
577 }
578}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100579template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200580 template (present) charstring transport := ?,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100581 template SemicolonParam_List viaParams := *) := {
582 fieldName := VIA_E,
583 viaBody := {
584 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200585 sentProtocol := { "SIP", "2.0", ? },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100586 sentBy := host_port,
587 viaParams := viaParams
588 }
589 }
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200590}
591
592template (present) OtherAuth
593tr_OtherAuth(template (present) charstring authScheme := ?,
594 template (present) CommaParam_List authParams := ?) := {
595 authScheme := authScheme,
596 authParams := authParams
597}
598
599template (value) OtherAuth
600ts_OtherAuth(template (value) charstring authScheme,
601 template (value) CommaParam_List authParams) := {
602 authScheme := authScheme,
603 authParams := authParams
604}
605
606template (present) Challenge
607tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := {
608 digestCln := digestCln
609}
610
611template (value) Challenge
612ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := {
613 digestCln := digestCln
614}
615
616template (present) Challenge
617tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := {
618 otherChallenge := otherChallenge
619}
620
621template (value) Challenge
622ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := {
623 otherChallenge := otherChallenge
624}
625
626template (present) WwwAuthenticate
627tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := {
628 fieldName := WWW_AUTHENTICATE_E,
629 challenge := challenge
630}
631
632template (value) WwwAuthenticate
633ts_WwwAuthenticate(template (value) Challenge_list challenge) := {
634 fieldName := WWW_AUTHENTICATE_E,
635 challenge := challenge
636}
Harald Welteb0d93602018-03-20 18:09:34 +0100637
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200638// RFC3329
639template (present) Security_client
640tr_Security_client(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
641 fieldName := SECURITY_CLIENT_E,
642 sec_mechanism_list := sec_mechanism_list
643}
644template (value) Security_client
645ts_Security_client(template (value) Security_mechanism_list sec_mechanism_list) := {
646 fieldName := SECURITY_CLIENT_E,
647 sec_mechanism_list := sec_mechanism_list
648}
649
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200650template (present) Security_server
651tr_Security_server(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
652 fieldName := SECURITY_SERVER_E,
653 sec_mechanism_list := sec_mechanism_list
654}
655template (value) Security_server
656ts_Security_server(template (value) Security_mechanism_list sec_mechanism_list) := {
657 fieldName := SECURITY_SERVER_E,
658 sec_mechanism_list := sec_mechanism_list
659}
660
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200661template (present) Security_mechanism
662tr_Security_mechanism(template (present) charstring name := ?,
663 template SemicolonParam_List params := *) := {
664 mechanism_name := name,
665 mechanism_params := params
666}
667template (value) Security_mechanism
668ts_Security_mechanism(template (value) charstring name,
669 template (omit) SemicolonParam_List params := omit) := {
670 mechanism_name := name,
671 mechanism_params := params
672}
673
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100674template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
675template (value) MessageHeader
676ts_SIP_msgh_std(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200677 template (value) From from_addr,
678 template (value) To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100679 template (omit) Contact contact,
680 template (value) charstring method,
681 template (value) integer seq_nr,
682 template (value) Via via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200683 template (omit) ContentLength content_length := ts_ContentLength(0),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100684 template (omit) ContentType content_type := omit,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200685 template (omit)Authorization authorization := omit,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200686 template (omit) Allow allow := ts_Allow(c_SIP_defaultMethods),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200687 template (omit) Expires expires := omit,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200688 template (omit) P_Associated_Uri p_associated_uri := omit,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200689 template (omit) RAck rack := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200690 template (omit) Require require := omit,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200691 template (omit) RSeq rseq := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200692 template (omit) Security_client security_client := omit,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200693 template (omit) Security_server security_server := omit,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200694 template (omit) Server server := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200695 template (omit) Supported supported := omit,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200696 template (omit) UserAgent userAgent := ts_UserAgent({ "osmo-ttcn3-hacks/0.23" }),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200697 template (omit) WwwAuthenticate wwwAuthenticate := omit
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100698 ) modifies ts_SIP_msgHeader_empty := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200699 allow := allow,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200700 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100701 callId := {
702 fieldName := CALL_ID_E,
703 callid := call_id
704 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100705 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200706 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100707 contentType := content_type,
708 cSeq := {
709 fieldName := CSEQ_E,
710 seqNumber := seq_nr,
711 method := method
712 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100713 expires := expires,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200714 fromField := from_addr,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200715 p_associated_uri := p_associated_uri,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200716 rack := rack,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200717 require := require,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200718 rseq := rseq,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200719 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200720 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200721 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200722 supported := supported,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200723 toField := to_addr,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200724 userAgent := userAgent,
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200725 via := via,
726 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100727}
728
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100729template (present) MessageHeader
730tr_SIP_msgh_std(template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200731 template From from_addr,
732 template To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100733 template Contact contact,
734 template (present) Via via := tr_Via_from(?),
735 template charstring method,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100736 template integer seq_nr := ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200737 template ContentLength content_length := *,
738 template ContentType content_type := *,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200739 template Allow allow := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200740 template Authorization authorization := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200741 template Expires expires := *,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200742 template P_Associated_Uri p_associated_uri := *,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200743 template RAck rack := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200744 template Require require := *,
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200745 template RSeq rseq := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200746 template Security_client security_client := *,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200747 template Security_server security_server := *,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200748 template Server server := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200749 template Supported supported := *,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200750 template UserAgent userAgent := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200751 template WwwAuthenticate wwwAuthenticate := *
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100752 ) modifies t_SIP_msgHeader_any := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200753 allow := allow,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200754 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100755 callId := {
756 fieldName := CALL_ID_E,
757 callid := call_id
758 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100759 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200760 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100761 contentType := content_type,
762 cSeq := {
763 fieldName := CSEQ_E,
764 seqNumber := seq_nr,
765 method := method
766 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100767 expires := expires,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200768 fromField := from_addr,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +0200769 p_associated_uri := p_associated_uri,
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200770 rack := rack,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200771 require := require,
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200772 rseq := rseq,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200773 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200774 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200775 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200776 supported := supported,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200777 toField := to_addr,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200778 userAgent := userAgent,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200779 via := via,
780 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100781}
782
783
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100784template (value) PDU_SIP_Request
785ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
786 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200787 template (value) From from_addr,
788 template (value) To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100789 template (value) Via via,
790 integer seq_nr,
791 template (omit) Contact contact,
792 template (omit) Expires expires,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200793 template (omit) Authorization authorization := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200794 template (omit) Require require := omit,
795 template (omit) Security_client security_client := omit,
796 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100797 template (omit) charstring body := omit) := {
798 requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
799 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
800 "REGISTER", seq_nr, via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200801 content_length := f_ContentLength(body),
802 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200803 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200804 expires := expires,
805 require := require,
806 security_client := security_client,
807 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100808 messageBody := body,
809 payload := omit
810}
811template (present) PDU_SIP_Request
812tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
813 template (present) CallidString call_id := ?,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200814 template (present) From from_addr := ?,
815 template (present) To to_addr := ?,
Pau Espin Pedrol0dd3f262024-04-25 17:04:43 +0200816 template (present) Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100817 template integer seq_nr := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200818 template Authorization authorization := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100819 template Contact contact := *,
820 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200821 template Require require := *,
822 template Security_client security_client := *,
823 template Supported supported := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100824 template charstring body := *) := {
825 requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
826 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200827 via, "REGISTER", seq_nr,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200828 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200829 expires := expires,
830 require := require,
831 security_client := security_client,
832 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100833 messageBody := body,
834 payload := omit
835}
836
837template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200838ts_SIP_INVITE(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200839 template (value) From from_addr,
840 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200841 template (value) Via via,
842 template (value) Contact contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100843 integer seq_nr,
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200844 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100845 template (omit) charstring body := omit) := {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200846 requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addressField.nameAddr.addrSpec),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200847 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100848 "INVITE", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200849 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200850 content_length := f_ContentLength(body),
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200851 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
852 supported := supported),
Harald Welteb0d93602018-03-20 18:09:34 +0100853 messageBody := body,
854 payload := omit
855}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100856template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200857tr_SIP_INVITE(template (present) SipUrl uri,
858 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200859 template From from_addr,
860 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200861 template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100862 template integer seq_nr,
863 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200864 requestLine := tr_SIP_ReqLine(INVITE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100865 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200866 via, "INVITE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100867 messageBody := body,
868 payload := omit
869}
870
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100871template (value) PDU_SIP_Request
872ts_SIP_BYE(CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200873 template (value) From from_addr,
874 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200875 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100876 integer seq_nr,
877 template (omit) charstring body) := {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200878 requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addressField.nameAddr.addrSpec),
Harald Welteb0d93602018-03-20 18:09:34 +0100879 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200880 via,
881 content_length := f_ContentLength(body),
882 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100883 messageBody := body,
884 payload := omit
885}
886
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100887template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200888tr_SIP_BYE(template (present) SipUrl uri,
889 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200890 template From from_addr,
891 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200892 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100893 template integer seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200894 template charstring body := *) := {
895 requestLine := tr_SIP_ReqLine(BYE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100896 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200897 via, "BYE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100898 messageBody := body,
899 payload := omit
900}
901
902
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100903template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200904ts_SIP_ACK(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200905 template (value) From from_addr,
906 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200907 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100908 integer seq_nr,
909 template (omit) charstring body) := {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200910 requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addressField.nameAddr.addrSpec),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100911 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200912 ts_Contact({ ts_ContactAddress(from_addr.addressField, from_addr.fromParams) }),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100913 "ACK", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200914 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200915 content_length := f_ContentLength(body),
916 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100917 messageBody := body,
918 payload := omit
919}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100920template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200921tr_SIP_ACK(template (present) SipUrl uri,
922 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200923 template From from_addr,
924 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200925 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100926 template integer seq_nr,
927 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200928 requestLine := tr_SIP_ReqLine(ACK_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100929 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200930 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200931 "ACK", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100932 messageBody := body,
933 payload := omit
934}
935
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200936template (present) PDU_SIP_Request
937tr_SIP_CANCEL(template (present) SipUrl uri,
938 template (present) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +0200939 template (present) From from_addr,
940 template (present) To to_addr,
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200941 template (present) Via via,
942 template (present) integer seq_nr,
943 template charstring body := *) := {
944 requestLine := tr_SIP_ReqLine(CANCEL_E, uri),
945 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
946 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200947 "CANCEL", seq_nr),
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200948 messageBody := body,
949 payload := omit
950}
951
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200952template (value) PDU_SIP_Request
953ts_SIP_PRACK(template (value) SipUrl uri,
954 template (value) CallidString call_id,
955 template (value) From from_addr,
956 template (value) To to_addr,
957 template (value) Via via,
958 integer seq_nr,
959 template (value) RAck rack,
960 template (omit) charstring body := omit) := {
961 requestLine := ts_SIP_ReqLine(PRACK_E, uri),
962 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit,
963 "PRACK", seq_nr,
964 via,
965 content_length := f_ContentLength(body),
966 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
967 rack := rack),
968 messageBody := body,
969 payload := omit
970}
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +0200971template (present) PDU_SIP_Request
972tr_SIP_PRACK(template (present) SipUrl uri,
973 template CallidString call_id,
974 template From from_addr,
975 template To to_addr,
976 template Via via,
977 template integer seq_nr,
978 template RAck rack := tr_RAck(?, ?, ?),
979 template charstring body := *) := {
980 requestLine := tr_SIP_ReqLine(PRACK_E, uri),
981 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
982 via,
983 "PRACK", seq_nr,
984 rack := rack),
985 messageBody := body,
986 payload := omit
987}
988
Pau Espin Pedrolce370df2024-06-18 13:45:53 +0200989template (value) PDU_SIP_Request
990ts_SIP_UPDATE(template (value) SipUrl uri,
991 template (value) CallidString call_id,
992 template (value) From from_addr,
993 template (value) To to_addr,
994 template (value) Via via,
995 integer seq_nr,
996 template (omit) Contact contact,
997 template (value) Require require := ts_Require({"sec-agree", "precondition"}),
998 template (value) charstring body) := {
999 requestLine := ts_SIP_ReqLine(UPDATE_E, uri),
1000 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
1001 "UPDATE", seq_nr,
1002 via,
1003 require := require),
1004 messageBody := body,
1005 payload := omit
1006}
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +02001007template (present) PDU_SIP_Request
1008tr_SIP_UPDATE(template (present) SipUrl uri,
1009 template CallidString call_id,
1010 template From from_addr,
1011 template To to_addr,
1012 template Via via,
1013 template integer seq_nr,
1014 template Require require := *,
1015 template charstring body) := {
1016 requestLine := tr_SIP_ReqLine(UPDATE_E, uri),
1017 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1018 via,
1019 "UPDATE", seq_nr,
1020 require := require),
1021 messageBody := body,
1022 payload := omit
1023}
1024
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001025template (value) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001026ts_SIP_Response(template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001027 template (value) From from_addr,
1028 template (value) To to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001029 charstring method,
1030 integer status_code,
1031 integer seq_nr,
1032 charstring reason,
1033 Via via,
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001034 template (omit) Allow allow := omit,
Pau Espin Pedrol586eec52024-06-04 19:07:33 +02001035 template (omit) Contact contact := omit,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001036 template (omit) P_Associated_Uri p_associated_uri := omit,
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001037 template (omit) Require require := omit,
1038 template (omit) Server server := omit,
1039 template (omit) Supported supported := omit,
1040 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001041 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +01001042 statusLine := ts_SIP_StatusLine(status_code, reason),
Pau Espin Pedrol586eec52024-06-04 19:07:33 +02001043 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001044 via,
1045 content_length := f_ContentLength(body),
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001046 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1047 allow := allow,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001048 p_associated_uri := p_associated_uri,
Pau Espin Pedrola674d612024-05-14 19:56:33 +02001049 require := require,
1050 server := server,
1051 supported := supported,
1052 userAgent := userAgent),
Harald Welteb0d93602018-03-20 18:09:34 +01001053 messageBody := body,
1054 payload := omit
1055}
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001056/* 100 Trying */
1057template (value) PDU_SIP_Response
1058ts_SIP_Response_Trying(
1059 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001060 template (value) From from_addr,
1061 template (value) To to_addr,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001062 Via via,
1063 integer seq_nr,
1064 charstring method := "INVITE",
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001065 template (omit) Allow allow := omit,
1066 template (omit) Server server := omit,
1067 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001068 template (omit) charstring body := omit) := {
1069 statusLine := ts_SIP_StatusLine(100, "Trying"),
1070 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001071 via,
1072 content_length := f_ContentLength(body),
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001073 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1074 allow := allow,
1075 server := server,
1076 userAgent := userAgent),
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +02001077 messageBody := body,
1078 payload := omit
1079}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001080/* 180 Ringing */
1081template (value) PDU_SIP_Response
1082ts_SIP_Response_Ringing(
1083 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001084 template (value) From from_addr,
1085 template (value) To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001086 Via via,
1087 integer seq_nr,
1088 charstring method := "INVITE",
1089 template (omit) charstring body := omit) := {
1090 statusLine := ts_SIP_StatusLine(180, "Ringing"),
1091 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001092 via,
1093 content_length := f_ContentLength(body),
1094 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001095 messageBody := body,
1096 payload := omit
1097}
1098
Pau Espin Pedrolfaf21be2024-06-12 16:42:00 +02001099/* 183 Session Progress */
1100template (value) PDU_SIP_Response
1101ts_SIP_Response_SessionProgress(
1102 template (value) CallidString call_id,
1103 template (value) From from_addr,
1104 template (value) To to_addr,
1105 Via via,
1106 integer seq_nr,
1107 charstring method := "INVITE",
1108 template (omit) Require require := ts_Require({"100rel", "precondition"}),
1109 template (omit) RSeq rseq := ts_RSeq(1),
1110 template (omit) charstring body := omit) := {
1111 statusLine := ts_SIP_StatusLine(183, "Session Progress"),
1112 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
1113 via,
1114 content_length := f_ContentLength(body),
1115 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1116 require := require,
1117 rseq := rseq),
1118 messageBody := body,
1119 payload := omit
1120}
1121
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001122/* 401 Unauthorized */
1123template (value) PDU_SIP_Response
1124ts_SIP_Response_Unauthorized(
1125 template (value) CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001126 template (value) From from_addr,
1127 template (value) To to_addr,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001128 Via via,
1129 template (value) WwwAuthenticate wwwAuthenticate,
1130 integer seq_nr,
1131 charstring method := "REGISTER",
1132 template (omit) Allow allow := omit,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001133 template (omit) P_Associated_Uri p_associated_uri := omit,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001134 template (omit) Security_server security_server := omit,
1135 template (omit) Server server := omit,
1136 template (omit) Supported supported := omit,
1137 template (omit) UserAgent userAgent := omit,
1138 template (omit) charstring body := omit) := {
1139 statusLine := ts_SIP_StatusLine(401, "Unauthorized"),
1140 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
1141 via,
1142 content_length := f_ContentLength(body),
1143 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
1144 allow := allow,
Pau Espin Pedrol4e6672c2024-05-22 17:03:53 +02001145 p_associated_uri := p_associated_uri,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +02001146 security_server := security_server,
1147 server := server,
1148 supported := supported,
1149 userAgent := userAgent,
1150 wwwAuthenticate := wwwAuthenticate),
1151 messageBody := body,
1152 payload := omit
1153}
1154
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001155template (present) PDU_SIP_Response
1156tr_SIP_Response(template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001157 template From from_addr,
1158 template To to_addr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001159 template (present) Via via := tr_Via_from(?),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001160 template Contact contact,
1161 template charstring method,
1162 template integer status_code,
1163 template integer seq_nr := ?,
1164 template charstring reason := ?,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001165 template charstring body := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +01001166 statusLine := tr_SIP_StatusLine(status_code, reason),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +01001167 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001168 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001169 method, seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +01001170 messageBody := body,
1171 payload := omit
1172}
1173
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001174/* Expect during first REGISTER/INVITE/... when authorization is required: */
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001175template (present) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001176tr_SIP_Response_Unauthorized(
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001177 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001178 template From from_addr,
1179 template To to_addr,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001180 template (present) Via via := tr_Via_from(?),
1181 template Contact contact := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001182 template (present) WwwAuthenticate wwwAuthenticate := ?,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001183 template integer seq_nr := ?,
1184 template charstring method := "REGISTER",
1185 template integer status_code := 401,
1186 template charstring reason := "Unauthorized",
1187 template charstring body := *) := {
1188 statusLine := tr_SIP_StatusLine(status_code, reason),
1189 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
1190 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001191 method, seq_nr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001192 wwwAuthenticate := wwwAuthenticate),
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +01001193 messageBody := body,
1194 payload := omit
1195}
Harald Welteb0d93602018-03-20 18:09:34 +01001196
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001197/* 100 Trying */
1198template (present) PDU_SIP_Response
1199tr_SIP_Response_Trying(
1200 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001201 template From from_addr,
1202 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001203 template (present) Via via := tr_Via_from(?),
1204 template integer seq_nr := ?,
1205 template charstring method := "INVITE",
1206 template integer status_code := 100,
1207 template charstring reason := "Trying",
1208 template charstring body := *) := {
1209 statusLine := tr_SIP_StatusLine(status_code, reason),
1210 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
1211 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001212 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001213 messageBody := body,
1214 payload := omit
1215}
1216
1217/* 180 Ringing */
1218template (present) PDU_SIP_Response
1219tr_SIP_Response_Ringing(
1220 template CallidString call_id,
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001221 template From from_addr,
1222 template To to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001223 template (present) Via via := tr_Via_from(?),
1224 template integer seq_nr := ?,
1225 template charstring method := "INVITE",
1226 template integer status_code := 180,
1227 template charstring reason := "Ringing",
1228 template charstring body := *) := {
1229 statusLine := tr_SIP_StatusLine(status_code, reason),
1230 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1231 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001232 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001233 messageBody := body,
1234 payload := omit
1235}
1236
Pau Espin Pedrolce370df2024-06-18 13:45:53 +02001237/* 183 Session Progress */
1238template (present) PDU_SIP_Response
1239tr_SIP_Response_SessionProgress(
1240 template (present) CallidString call_id,
1241 template (present) From from_addr,
1242 template (present) To to_addr,
1243 template (present) Via via,
1244 template (present) integer seq_nr := ?,
1245 template (present) charstring method := "INVITE",
1246 template Require require := *,
1247 template RSeq rseq := *,
1248 template (omit) charstring body := omit) := {
1249 statusLine := tr_SIP_StatusLine(183, "Session Progress"),
1250 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1251 via,
1252 method, seq_nr,
1253 require := require,
1254 rseq := rseq),
1255 messageBody := body,
1256 payload := omit
1257}
1258
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001259/****************
1260 * FUNCTIONS:
1261 ****************/
1262
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001263function f_sip_param_find(GenericParam_List li,
1264 template (present) charstring id := ?)
1265return template (omit) GenericParam {
1266 var integer i;
1267
1268 for (i := 0; i < lengthof(li); i := i + 1) {
1269 if (not ispresent(li[i])) {
1270 continue;
1271 }
1272 if (match(li[i].id, id)) {
1273 return li[i];
1274 }
1275 }
1276 return omit;
1277}
1278
1279function f_sip_param_find_or_fail(GenericParam_List li,
1280 template (present) charstring id := ?)
1281return GenericParam {
1282 var template (omit) GenericParam parameter;
1283 parameter := f_sip_param_find(li, id);
1284 if (istemplatekind(parameter, "omit")) {
1285 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1286 log2str("Param ", id, " not found in ", li));
1287 }
1288 return valueof(parameter);
1289}
1290
1291function f_sip_param_get_value(GenericParam_List li,
1292 template (present) charstring id := ?)
1293return template (omit) charstring {
1294 var template (omit) GenericParam parameter;
1295 parameter := f_sip_param_find(li, id);
1296 if (istemplatekind(parameter, "omit")) {
1297 return omit;
1298 }
1299 return parameter.paramValue;
1300}
1301
1302function f_sip_param_get_value_or_fail(GenericParam_List li,
1303 template (present) charstring id := ?)
1304return template (omit) charstring {
1305 var GenericParam parameter;
1306 parameter := f_sip_param_find_or_fail(li, id);
1307 return parameter.paramValue;
1308}
1309
1310function f_sip_param_get_value_present_or_fail(GenericParam_List li,
1311 template (present) charstring id := ?)
1312return charstring {
1313 var GenericParam parameter;
1314 parameter := f_sip_param_find_or_fail(li, id);
1315 if (not ispresent(parameter.paramValue)) {
1316 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1317 log2str("Param ", id, " value not present in ", li));
1318 }
1319 return parameter.paramValue;
1320}
1321
1322function f_sip_param_match_value(GenericParam_List li,
1323 template (present) charstring id := ?,
1324 template charstring exp_paramValue := *)
1325return boolean {
1326 var template (omit) charstring val;
1327 val := f_sip_param_get_value_or_fail(li, id);
1328 if (istemplatekind(val, "omit")) {
1329 return istemplatekind(val, "omit") or istemplatekind(val, "*");
1330 }
1331 return match(valueof(val), exp_paramValue);
1332}
1333
1334function f_sip_param_match_value_or_fail(GenericParam_List li,
1335 template (present) charstring id := ?,
1336 template charstring exp_paramValue := *)
1337{
1338 var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id);
1339 if (istemplatekind(val, "omit")) {
1340 if (istemplatekind(val, "omit") or istemplatekind(val, "*")) {
1341 return;
1342 } else {
1343 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1344 log2str("Param ", id, " match failed: val ", val,
1345 " vs exp ", exp_paramValue));
1346 }
1347 }
1348 if (not match(valueof(val), exp_paramValue)) {
1349 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1350 log2str("Param ", id, " match failed: val ", val,
1351 " vs exp ", exp_paramValue));
1352 }
1353}
1354
1355function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id)
1356return GenericParam_List {
1357 var integer i;
1358 var GenericParam_List li;
1359 var GenericParam_List new_li := {};
1360
1361 if (istemplatekind(li_tpl, "omit")) {
1362 return {};
1363 }
1364
1365 li := valueof(li_tpl);
1366 for (i := 0; i < lengthof(li); i := i + 1) {
1367 if (not ispresent(li[i]) or
1368 not match(li[i].id, id)) {
1369 new_li := new_li & {li[i]};
1370 }
1371 }
1372 return new_li;
1373}
1374
1375function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val)
1376return GenericParam_List {
1377 var integer i;
1378 var GenericParam_List li;
1379 var GenericParam_List new_li := {};
1380 var boolean found := false;
1381
1382 if (istemplatekind(li_tpl, "omit")) {
1383 return { valueof(ts_Param(id, val)) };
1384 }
1385
1386 li := valueof(li_tpl);
1387 for (i := 0; i < lengthof(li); i := i + 1) {
1388 if (not ispresent(li[i]) or
1389 not match(li[i].id, id)) {
1390 new_li := new_li & {li[i]};
1391 continue;
1392 }
1393 new_li := new_li & { valueof(ts_Param(li[i].id, val)) };
1394 found := true;
1395 }
1396
1397 if (not found) {
1398 new_li := new_li & { valueof(ts_Param(id, val)) };
1399 }
1400 return new_li;
1401}
1402
1403/* Make sure string is quoted. */
1404function f_sip_str_quote(template (value) charstring val) return charstring {
1405 var charstring str := valueof(val);
1406 if (lengthof(str) == 0) {
1407 return "";
1408 }
1409
1410 if (str[0] != "\"") {
1411 return "\"" & str & "\"";
1412 }
1413 return str;
1414}
1415
1416/* Make sure string is unquoted.
1417 * Similar to unq() in RFC 2617 */
1418function f_sip_str_unquote(template (value) charstring val) return charstring {
1419 var charstring str := valueof(val);
1420 var integer len := lengthof(str);
1421
1422 if (len <= 1) {
1423 return str;
1424 }
1425
1426 if (str[0] == "\"" and str[len - 1] == "\"") {
1427 return substr(str, 1, len - 2);
1428 }
1429 return str;
1430}
1431
1432/* RFC 2617 3.2.2.2 A1 */
1433function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring {
1434
1435 /* RFC 2617 3.2.2.2 A1 */
1436 var charstring A1 := f_sip_str_unquote(user) & ":" &
1437 f_sip_str_unquote(realm) & ":" &
1438 password;
1439 var charstring digestA1 := f_str_tolower(f_calculateMD5(A1));
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001440 log("A1: md5(", A1, ") = ", digestA1);
1441 return digestA1;
1442}
1443
1444/* RFC 3310: Same as f_sip_digest_A1(), but using an octet buffer as password (AKAv1-MD5, pwd=RES) */
1445function f_sip_digest_A1_octpwd(charstring user, charstring realm, octetstring password) return charstring {
1446 var charstring A1pre := f_sip_str_unquote(user) & ":" &
1447 f_sip_str_unquote(realm) & ":";
1448 var octetstring A1 := char2oct(A1pre) & password;
1449 var charstring digestA1 := f_str_tolower(oct2str(f_calculateMD5_oct(A1)));
1450 log("A1-octpwd: md5(", A1, ") = ", digestA1);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001451 return digestA1;
1452}
1453
1454/* RFC 2617 3.2.2.2 A2 */
1455function f_sip_digest_A2(charstring method, charstring uri) return charstring {
1456
1457 var charstring A2 := method & ":" & uri
1458 var charstring digestA2 := f_str_tolower(f_calculateMD5(A2));
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001459 log("A2: md5(", A2, ") = ", digestA2);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001460 return digestA2;
1461}
1462
1463/* RFC 2617 3.2.2.1 Request-Digest */
1464function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce,
1465 charstring nc, charstring cnonce,
1466 charstring qop, charstring digestA2) return charstring {
1467 var charstring digest_data := f_sip_str_unquote(nonce) & ":" &
1468 nc & ":" &
1469 cnonce & ":" &
1470 f_sip_str_unquote(qop) & ":" &
1471 digestA2;
1472 var charstring req_digest := f_sip_digest_KD(digestA1, digest_data);
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001473 log("Request-Digest: md5(\"" & digestA1 & ":" & digest_data & "\") = " & "\"" & req_digest & "\"");
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001474 return req_digest;
1475}
1476
1477/* RFC 2617 3.2.1 The WWW-Authenticate Response Header
1478 * KD(secret, data) = H(concat(secret, ":", data))
1479 */
1480function f_sip_digest_KD(charstring secret, charstring data) return charstring {
1481 return f_str_tolower(f_calculateMD5(secret & ":" & data));
1482}
1483
1484/* Digest Auth: RFC 2617 */
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001485function f_sip_digest_gen_Authorization_Response_MD5(charstring user, charstring realm, charstring password,
1486 charstring method, charstring uri, charstring qop,
1487 charstring nonce, charstring cnonce, charstring nc)
1488return charstring {
1489 /* RFC 2617 3.2.2.2 A1 */
1490 var charstring digestA1 := f_sip_digest_A1(user, realm, password);
1491
1492 /* RFC 2617 3.2.2.3 A2 */
1493 var charstring digestA2 := f_sip_digest_A2(method, uri);
1494
1495 /* RFC 2617 3.2.2.1 Request-Digest */
1496 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1497 nc, cnonce,
1498 qop, digestA2);
1499 return req_digest;
1500}
1501
1502/* Digest Auth: RFC 2617 */
1503function f_sip_digest_gen_Authorization_Response_AKAv1MD5(charstring user, charstring realm, octetstring password,
1504 charstring method, charstring uri, charstring qop,
1505 charstring nonce, charstring cnonce, charstring nc)
1506return charstring {
1507 /* RFC 2617 3.2.2.2 A1 */
1508 var charstring digestA1 := f_sip_digest_A1_octpwd(user, realm, password);
1509 /* RFC 2617 3.2.2.3 A2 */
1510 var charstring digestA2 := f_sip_digest_A2(method, uri);
1511
1512 /* RFC 2617 3.2.2.1 Request-Digest */
1513 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1514 nc, cnonce,
1515 qop, digestA2);
1516 return req_digest;
1517}
1518
1519function f_sip_digest_gen_Authorization_MD5(WwwAuthenticate www_authenticate,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001520 charstring user, charstring password,
1521 charstring method, charstring uri,
1522 charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization {
1523 var CommaParam_List digestCln;
1524 var template (value) Authorization authorization;
1525 var template (value) Credentials cred;
1526 var template (omit) GenericParam rx_param;
1527
1528 digestCln := www_authenticate.challenge[0].digestCln;
1529
1530 var charstring algorithm;
1531 rx_param := f_sip_param_find(digestCln, "algorithm");
1532 if (istemplatekind(rx_param, "omit")) {
1533 /* Assume MD5 if not set */
1534 algorithm := "MD5"
1535 } else {
1536 algorithm := valueof(rx_param.paramValue);
1537 if (f_strstr(algorithm, "MD5") == -1) {
1538 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1539 log2str("Unexpected algorithm: ", algorithm));
1540 }
1541 }
1542
1543 var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
1544 var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
1545 var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque");
1546 var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop");
1547
1548 if (f_strstr(qop, "auth") == -1) {
1549 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1550 }
1551 var charstring selected_qop := "auth";
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001552 var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8)));
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001553
1554 var charstring req_digest;
1555 req_digest :=
1556 f_sip_digest_gen_Authorization_Response_MD5(user, realm, password,
1557 method, uri, selected_qop,
1558 nonce, cnonce, nc);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001559
1560 cred := ts_Credentials_DigestResponseMD5(user, realm, nonce,
1561 uri, req_digest,
1562 opaque, algorithm, selected_qop, cnonce, nc);
1563
1564 authorization := ts_Authorization(cred);
1565 return valueof(authorization);
1566}
1567
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001568/* RFC 3310: Same as f_sip_digest_validate_Authorization_MD5(), but using an octet buffer as password (AKAv1-MD5, pwd=RES) */
1569function f_sip_digest_validate_Authorization_AKAv1MD5(Authorization authorization, charstring method, octetstring password) {
1570 var CommaParam_List auth_pars := authorization.body.digestResponse;
1571 var template (omit) GenericParam rx_param;
1572
1573 rx_param := f_sip_param_find(auth_pars, "algorithm");
1574 if (istemplatekind(rx_param, "omit")) {
1575 /* Assume MD5 if not set */
1576 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Algorithm param not present");
1577 } else {
1578 var charstring algorithm := valueof(rx_param.paramValue);
1579 if (f_strstr(algorithm, "AKAv1-MD5") == -1) {
1580 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1581 log2str("Unexpected algorithm: ", algorithm));
1582 }
1583 }
1584
1585 var charstring user := f_sip_param_get_value_present_or_fail(auth_pars, "username");
1586 var charstring realm := f_sip_param_get_value_present_or_fail(auth_pars, "realm");
1587 var charstring uri := f_sip_param_get_value_present_or_fail(auth_pars, "uri");
1588 var charstring nonce := f_sip_param_get_value_present_or_fail(auth_pars, "nonce");
1589 var charstring qop := f_sip_param_get_value_present_or_fail(auth_pars, "qop");
1590 var charstring response := f_sip_param_get_value_present_or_fail(auth_pars, "response");
1591 var charstring cnonce := f_sip_param_get_value_present_or_fail(auth_pars, "cnonce");
1592 var charstring nc := f_sip_param_get_value_present_or_fail(auth_pars, "nc");
1593
1594 if (f_strstr(qop, "auth") == -1) {
1595 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1596 }
1597
1598 var charstring exp_response :=
1599 f_sip_digest_gen_Authorization_Response_AKAv1MD5(f_sip_str_unquote(user),
1600 f_sip_str_unquote(realm),
1601 password,
1602 method,
1603 f_sip_str_unquote(uri),
1604 qop,
1605 f_sip_str_unquote(nonce),
1606 f_sip_str_unquote(cnonce),
1607 nc);
1608
1609 response := f_sip_str_unquote(response);
1610 if (response != exp_response) {
1611 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1612 log2str("Wrong digest response: ", response,
1613 " vs exp: ", exp_response, ". Params: ", auth_pars));
1614 }
1615}
1616
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001617/* RFC 2617 3.5 Example */
1618function f_sip_digest_selftest() {
1619/*
1620The following example assumes that an access-protected document is
1621being requested from the server via a GET request. The URI of the
1622document is "http://www.nowhere.org/dir/index.html". Both client and
1623server know that the username for this document is "Mufasa", and the
1624password is "Circle Of Life" (with one space between each of the
1625three words).
1626
1627HTTP/1.1 401 Unauthorized
1628WWW-Authenticate: Digest
1629 realm="testrealm@host.com",
1630 qop="auth,auth-int",
1631 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1632 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1633
1634Authorization: Digest username="Mufasa",
1635 realm="testrealm@host.com",
1636 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1637 uri="/dir/index.html",
1638 qop=auth,
1639 nc=00000001,
1640 cnonce="0a4f113b",
1641 response="6629fae49393a05397450978507c4ef1",
1642 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1643*/
1644 var template (value) CommaParam_List digestCln := {
1645 ts_Param("realm", f_sip_str_quote("testrealm@host.com")),
1646 ts_Param("qop", f_sip_str_quote("auth,auth-int")),
1647 ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")),
1648 ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"))
1649 };
1650 var template (value) WwwAuthenticate www_authenticate :=
1651 ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
1652
1653 var Authorization authorization :=
Pau Espin Pedrol80b981a2024-06-04 18:37:22 +02001654 f_sip_digest_gen_Authorization_MD5(valueof(www_authenticate),
1655 "Mufasa",
1656 "Circle Of Life",
1657 "GET",
1658 "/dir/index.html",
1659 cnonce := "0a4f113b",
1660 nc_int := 1);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001661
1662 var CommaParam_List digestResp := authorization.body.digestResponse;
1663 f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com"));
1664 f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093"));
1665 f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html"));
1666 f_sip_param_match_value_or_fail(digestResp, "qop", "auth");
1667 f_sip_param_match_value_or_fail(digestResp, "nc", "00000001");
1668 f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b"));
1669 f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1"));
1670 f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"));
1671}
1672
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01001673/* RFC 3261 8.1.1.5:
1674 * "The sequence number value MUST be expressible as a 32-bit unsigned integer
1675 * and MUST be less than 2**31."
1676 */
1677function f_sip_rand_seq_nr() return integer {
1678 /* 2**31 = 2147483648 */
1679 return f_rnd_int(2147483648)
1680}
Harald Welteb0d93602018-03-20 18:09:34 +01001681
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001682function f_sip_next_seq_nr(integer seq_nr) return integer {
1683 return (seq_nr + 1) mod 2147483648;
1684}
1685
1686function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
1687 req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
1688}
1689
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001690function f_sip_rand_tag() return charstring {
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001691 /* Tags shall have at least 32 bit of randomness */
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001692 var integer rnd_int := f_rnd_int(4294967296);
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001693 /* Make collisions harder by appending time to the final string: */
1694 var integer ts_int := f_time_ms() mod 4294967296;
1695 return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8));
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001696}
1697
1698/* Generate a "branch" tag value.
1699 * RFC 3261 p.105 section 8:
1700 * "A common way to create this value is to compute a
1701 * cryptographic hash of the To tag, From tag, Call-ID header
1702 * field, the Request-URI of the request received (before
1703 * translation), the topmost Via header, and the sequence number
1704 * from the CSeq header field, in addition to any Proxy-Require
1705 * and Proxy-Authorization header fields that may be present. The
1706 * algorithm used to compute the hash is implementation-dependent,
1707 * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable
1708 * choice."
1709 * See also Section 8.1.1.7:
1710 * "The branch ID inserted by an element compliant with this
1711 * specification MUST always begin with the characters "z9hG4bK"."
1712 */
1713const charstring sip_magic_cookie := "z9hG4bK";
1714function f_sip_gen_branch(charstring tag_to,
1715 charstring tag_from,
1716 charstring tag_call_id,
1717 integer cseq) return charstring {
1718 var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq);
1719 var charstring hash := f_calculateMD5(str);
1720 var charstring branch := sip_magic_cookie & hash;
1721 return branch;
1722}
1723
1724function f_sip_HostPort_to_str(HostPort host_port) return charstring {
1725 var charstring str := "";
1726 if (ispresent(host_port.host)) {
1727 str := host_port.host;
1728 }
1729 if (ispresent(host_port.portField)) {
1730 str := str & ":" & int2str(host_port.portField);
1731 }
1732 return str;
1733}
1734
1735function f_sip_SipUrl_to_str(SipUrl uri) return charstring {
Pau Espin Pedrolb0dbf7a2024-05-22 18:12:15 +02001736 var charstring str := uri.scheme & ":";
1737 if (ispresent(uri.userInfo)) {
1738 str := str & uri.userInfo.userOrTelephoneSubscriber & "@";
1739 }
1740 str := str & f_sip_HostPort_to_str(uri.hostPort);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001741 return str;
1742}
1743
1744function f_sip_NameAddr_to_str(NameAddr naddr) return charstring {
1745 if (ispresent(naddr.displayName)) {
1746 return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">";
1747 } else {
1748 return f_sip_SipUrl_to_str(naddr.addrSpec);
1749 }
1750}
1751
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001752function f_sip_Addr_Union_to_str(Addr_Union addru) return charstring {
1753 if (ischosen(addru.nameAddr)) {
1754 return f_sip_NameAddr_to_str(addru.nameAddr);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001755 } else {
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001756 return f_sip_SipUrl_to_str(addru.addrSpecUnion);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001757 }
1758}
1759
Pau Espin Pedrol41b0e072024-05-29 18:25:51 +02001760function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring {
1761 return f_sip_Addr_Union_to_str(sip_addr.addr);
1762}
1763
Harald Welteb0d93602018-03-20 18:09:34 +01001764}