blob: 37dee4bba604d0972064145dba0fcf961f174073 [file] [log] [blame]
Harald Welteb0d93602018-03-20 18:09:34 +01001module SIP_Templates {
2
3import from SIPmsg_Types all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02004import from TCCConversion_Functions all;
5import from TCCOpenSecurity_Functions all;
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02006import from TCCDateTime_Functions all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02007import from Native_Functions all;
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01008import from Osmocom_Types all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02009import from Misc_Helpers all;
Harald Welteb0d93602018-03-20 18:09:34 +010010
11/* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */
12type record SipAddr {
13 Addr_Union addr,
14 SemicolonParam_List params optional
15}
16
17const charstring c_SIP_VERSION := "SIP/2.0";
18
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020019template (value) GenericParam ts_Param(template (value) charstring id,
20 template (omit) charstring paramValue := omit) := {
21 id := id,
22 paramValue := paramValue
23}
24template (present) GenericParam tr_Param(template (present) charstring id := ?,
25 template charstring paramValue := *) := {
26 id := id,
27 paramValue := paramValue
28}
29function f_ts_Param_omit(template (value) charstring id,
30 template (omit) charstring paramValue := omit)
31 return template (omit) GenericParam
32{
33 if (istemplatekind(paramValue, "omit")) {
34 return omit;
35 }
36 return ts_Param(id, paramValue);
37}
38
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010039template (value) SipUrl ts_SipUrl(template (value) HostPort host_port,
40 template (omit) UserInfo user_info := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +010041 scheme := "sip",
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010042 userInfo := user_info,
43 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010044 urlParameters := omit,
45 headers := omit
46}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010047template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?,
48 template UserInfo user_info := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +010049 scheme := "sip",
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010050 userInfo := user_info,
51 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010052 urlParameters := *,
53 headers := *
54}
55
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +020056template (value) SipUrl ts_SipUrlHost(template (value) charstring host,
57 template (omit) integer portField := omit)
58 := ts_SipUrl(ts_HostPort(host, portField));
59
60function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au)
61return template (value) SipUrl {
62 if (ischosen(au.nameAddr)) {
63 return au.nameAddr.addrSpec;
64 } else { /* au.addrSpecUnion */
65 return au.addrSpecUnion;
66 }
67}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010068
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +020069// [20.5]
70template (present) Allow tr_Allow(template Method_List methods := *) := {
71 fieldName := ALLOW_E,
72 methods := methods
73}
74template (value) Allow ts_Allow(template (omit) Method_List methods := omit) := {
75 fieldName := ALLOW_E,
76 methods := methods
77}
78
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020079template (value) Credentials ts_Credentials_DigestResponse(template (value) CommaParam_List digestResponse) := {
80 digestResponse := digestResponse
81}
82
83template (value) Credentials ts_Credentials_DigestResponseMD5(
84 template (value) charstring username,
85 template (value) charstring realm,
86 template (value) charstring nonce,
87 template (value) charstring uri,
88 template (value) charstring response,
89 template (value) charstring opaque,
90 template (value) charstring algorithm := "MD5",
91 template (value) charstring qop := "auth",
92 template (omit) charstring cnonce := omit,
93 template (omit) charstring nc := omit
94 ) := {
95 digestResponse := {
96 // Already added by digestResponse automatically:
97 //ts_Param("Digest", omit),
98 ts_Param("username", f_sip_str_quote(username)),
99 ts_Param("realm", f_sip_str_quote(realm)),
100 ts_Param("nonce", f_sip_str_quote(nonce)),
101 ts_Param("uri", f_sip_str_quote(uri)),
102 ts_Param("response", f_sip_str_quote(response)),
103 ts_Param("opaque", f_sip_str_quote(opaque)),
104 ts_Param("algorithm", algorithm),
105 ts_Param("qop", qop),
106 // FIXME: If "omit" is passed, these below end up in;
107 // "Dynamic test case error: Performing a valueof or send operation on a non-specific template of type @SIPmsg_Types.GenericParam"
108 f_ts_Param_omit("cnonce", f_sip_str_quote(cnonce)),
109 f_ts_Param_omit("nc", nc)
110 }
111}
112
113template (value) Credentials ts_Credentials_OtherAuth(template (value) OtherAuth otherResponse) := {
114 otherResponse := otherResponse
115}
116
117template (value) Authorization ts_Authorization(template (value) Credentials body) := {
118 fieldName := AUTHORIZATION_E,
119 body := body
120}
121
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100122// [20.10]
123template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?,
124 template charstring displayName := *) := {
125 displayName := displayName,
126 addrSpec := addrSpec
Harald Welteb0d93602018-03-20 18:09:34 +0100127}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100128template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec,
129 template (omit) charstring displayName := omit) := {
130 displayName := displayName,
131 addrSpec := addrSpec
132}
133
134template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := {
135 nameAddr := nameAddr
136}
137template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := {
138 nameAddr := nameAddr
139}
140
141template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := {
142 addrSpecUnion := sipUrl
143}
144template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := {
145 addrSpecUnion := sipUrl
146}
147
148
149template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?,
150 template SemicolonParam_List contactParams := *) := {
151 addressField := addressField,
152 contactParams := contactParams
153}
154template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField,
155 template (omit) SemicolonParam_List contactParams := omit) := {
156 addressField := addressField,
157 contactParams := contactParams
158}
159
160template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := {
161 fieldName := CONTACT_E,
162 contactBody := {
163 contactAddresses := contactAddresses
164 }
165}
166template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := {
167 fieldName := CONTACT_E,
168 contactBody := {
169 contactAddresses := contactAddresses
170 }
171}
172
173template (value) Contact ts_ContactWildcard := {
174 fieldName := CONTACT_E,
175 contactBody := {
176 wildcard := "*"
177 }
178}
179
180template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?)
181 := tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) });
182
183private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact
184{
185 if (istemplatekind(contact_addr, "omit")) {
186 return omit;
187 } else if (istemplatekind(contact_addr, "*")) {
188 return *;
189 }
190 return tr_Contact_SipAddr(contact_addr);
191}
192
193template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr)
194 := ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) });
195private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact
196{
197 if (istemplatekind(contact_addr, "omit")) {
198 return omit;
199 }
200 return ts_Contact_SipAddr(contact_addr);
201}
202
203
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200204// [20.14]
205template (value) ContentLength ts_ContentLength(template (value) integer len := 0) := {
206 fieldName := CONTENT_LENGTH_E,
207 len := len
208}
209template (present) ContentLength tr_ContentLength(template (present) integer len := ?) := {
210 fieldName := CONTENT_LENGTH_E,
211 len := len
212}
213
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100214// [20.19]
215template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := {
216 fieldName := EXPIRES_E,
217 deltaSec := deltaSec
218}
219
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200220
221// [20.32]
222template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := {
223 fieldName := REQUIRE_E,
224 optionsTags := optionsTags
225}
226template (present) Require tr_Require(template (present) OptionTag_List optionsTags := ?) := {
227 fieldName := REQUIRE_E,
228 optionsTags := optionsTags
229}
230
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200231// [20.35 RFC2616 14.38]
232template (value) Server ts_Server(template (value) ServerVal_List serverBody := {}) := {
233 fieldName := SERVER_E,
234 serverBody := serverBody
235}
236template (present) Server tr_Server(template (present) ServerVal_List serverBody := ?) := {
237 fieldName := SERVER_E,
238 serverBody := serverBody
239}
240
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200241// [20.37]
242template (value) Supported ts_Supported(template (value) OptionTag_List optionsTags := {}) := {
243 fieldName := SUPPORTED_E,
244 optionsTags := optionsTags
245}
246template (present) Supported tr_Supported(template (present) OptionTag_List optionsTags := ?) := {
247 fieldName := SUPPORTED_E,
248 optionsTags := optionsTags
249}
250
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200251// [20.41 RFC2616 14.43]
252template (value) UserAgent ts_UserAgent(template (value) ServerVal_List userAgentBody := {}) := {
253 fieldName := USER_AGENT_E,
254 userAgentBody := userAgentBody
255}
256template (present) UserAgent tr_UserAgent(template (present) ServerVal_List userAgentBody := ?) := {
257 fieldName := USER_AGENT_E,
258 userAgentBody := userAgentBody
259}
260
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200261
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100262template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
263 template (omit) UserInfo user_info := omit,
264 template (omit) charstring displayName := omit,
265 template (omit) SemicolonParam_List params := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100266 addr := {
267 nameAddr := {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100268 displayName := displayName,
269 addrSpec := ts_SipUrl(host_port, user_info)
Harald Welteb0d93602018-03-20 18:09:34 +0100270 }
271 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100272 params := params
273}
274template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
275 template UserInfo user_info := *,
276 template charstring displayName := *,
277 template SemicolonParam_List params := *) := {
278 addr := {
279 nameAddr := {
280 displayName := displayName,
281 addrSpec := tr_SipUrl(host_port, user_info)
282 }
283 },
284 params := params
Harald Welteb0d93602018-03-20 18:09:34 +0100285}
286
287/* build a receive template from a value: substitute '*' for omit */
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200288function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl {
289 var template (present) SipUrl ret := tin;
290
291 /* if the port number is 5060, it may be omitted */
292 if (ispresent(tin.hostPort.portField) and
293 valueof(tin.hostPort.portField) == 5060) {
294 ret.hostPort.portField := 5060 ifpresent;
295 }
296 if (not ispresent(tin.userInfo.password)) {
297 ret.userInfo.password := *;
298 }
299
300 return ret;
301}
302function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100303 var template (present) SipAddr ret := tin;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200304
305 if (not ispresent(tin.addr.nameAddr.displayName)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100306 ret.addr.nameAddr.displayName := *;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200307 } else if (f_str_tolower(f_sip_str_unquote(tin.addr.nameAddr.displayName)) == "anonymous") {
308 /* if the user is Anonymous, it may be omitted */
309 ret.addr.nameAddr.displayName := tin.addr.nameAddr.displayName ifpresent;
Harald Welteb0d93602018-03-20 18:09:34 +0100310 }
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200311
312 ret.addr.nameAddr.addrSpec := tr_SipUrl_from_val(tin.addr.nameAddr.addrSpec);
313
314 if (not ispresent(tin.params)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100315 ret.params := *;
316 }
317 return ret;
318}
319
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200320function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
321 template (omit) SemicolonParam_List params := omit)
322return template (value) SipAddr {
323 var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
324 var template (omit) charstring displayName;
325
326 if (ischosen(au.nameAddr)) {
327 displayName := au.nameAddr.displayName;
328 } else { /* au.addrSpecUnion */
329 displayName := omit
330 }
331
332 return ts_SipAddr(addrSpec.hostPort,
333 addrSpec.userInfo,
334 displayName,
335 params);
336}
337
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100338template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
339 template (omit) integer portField := omit) := {
340 host := host,
341 portField := portField
342}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200343
344template (present) HostPort tr_HostPort(template charstring host := *,
345 template integer portField := *) := {
346 host := host,
347 portField := portField
348}
349function f_tr_HostPort(template charstring host := *,
350 template integer portField := *)
351return template (present) HostPort {
352 return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
353}
354function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort {
355 var template (present) HostPort hpout := hp;
Harald Welteb0d93602018-03-20 18:09:34 +0100356 /* if the port number is 5060, it may be omitted */
357 if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
358 hpout.portField := 5060 ifpresent;
359 }
360 return hpout;
361}
362
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200363function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl {
364 var template (present) SipUrl urlout := url;
365 urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
366 return urlout;
367}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100368
369template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
370 template (omit) charstring password := omit) := {
371 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
372 password := password
373}
374template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
375 template charstring password := *) := {
376 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
377 password := password
378}
379
380template (value) RequestLine ts_SIP_ReqLine(Method method,
381 template (value) SipUrl uri,
Harald Welteb0d93602018-03-20 18:09:34 +0100382 charstring ver := c_SIP_VERSION) := {
383 method := method,
384 requestUri := uri,
385 sipVersion := ver
386}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100387template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
388 template (present) SipUrl uri := ?,
389 template (present) charstring ver := c_SIP_VERSION) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100390 method := method,
391 requestUri := uri,
392 sipVersion := ver
393}
394
395template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
396 sipVersion := "SIP/2.0",
397 statusCode := status_code,
398 reasonPhrase := reason
399}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100400template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
401 template charstring reason) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100402 sipVersion := "SIP/2.0",
403 statusCode := status_code,
404 reasonPhrase := reason
405}
406
407
408template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
409 requestLine := rl,
410 msgHeader := c_SIP_msgHeader_empty,
411 messageBody := omit,
412 payload := omit
413}
414
415const Method_List c_SIP_defaultMethods := {
416 "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
417 "NOTIFY", "REFER", "UPDATE" };
418
419private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
420return template (omit) ContentType {
421 /* if user explicitly stated no content type */
422 if (istemplatekind(ct, "omit")) {
423 return omit;
424 }
425 /* if there's no body, then there's no content-type either */
426 if (istemplatekind(body, "omit")) {
427 return omit;
428 }
429 return ct;
430}
431
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200432private function f_ContentLength(template (omit) charstring body)
433return template (value) ContentLength {
434 /* rfc3261 20.14: "If no body is present in a message, then the
435 * Content-Length header field value MUST be set to zero." */
436 if (istemplatekind(body, "omit")) {
437 return ts_ContentLength(0);
438 }
439 return ts_ContentLength(lengthof(body));
440}
441
Harald Welteb0d93602018-03-20 18:09:34 +0100442template (value) ContentType ts_CT_SDP := {
443 fieldName := CONTENT_TYPE_E,
444 mediaType := "application/sdp"
445};
446
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200447template (value) Via ts_Via_from(template (value) HostPort addr,
448 template (value) charstring transport := "UDP") := {
Harald Welteb0d93602018-03-20 18:09:34 +0100449 fieldName := VIA_E,
450 viaBody := {
451 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200452 sentProtocol := { "SIP", "2.0", transport },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100453 sentBy := addr,
Harald Welteb0d93602018-03-20 18:09:34 +0100454 viaParams := omit
455 }
456 }
457}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100458template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200459 template (present) charstring transport := ?,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100460 template SemicolonParam_List viaParams := *) := {
461 fieldName := VIA_E,
462 viaBody := {
463 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200464 sentProtocol := { "SIP", "2.0", ? },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100465 sentBy := host_port,
466 viaParams := viaParams
467 }
468 }
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200469}
470
471template (present) OtherAuth
472tr_OtherAuth(template (present) charstring authScheme := ?,
473 template (present) CommaParam_List authParams := ?) := {
474 authScheme := authScheme,
475 authParams := authParams
476}
477
478template (value) OtherAuth
479ts_OtherAuth(template (value) charstring authScheme,
480 template (value) CommaParam_List authParams) := {
481 authScheme := authScheme,
482 authParams := authParams
483}
484
485template (present) Challenge
486tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := {
487 digestCln := digestCln
488}
489
490template (value) Challenge
491ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := {
492 digestCln := digestCln
493}
494
495template (present) Challenge
496tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := {
497 otherChallenge := otherChallenge
498}
499
500template (value) Challenge
501ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := {
502 otherChallenge := otherChallenge
503}
504
505template (present) WwwAuthenticate
506tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := {
507 fieldName := WWW_AUTHENTICATE_E,
508 challenge := challenge
509}
510
511template (value) WwwAuthenticate
512ts_WwwAuthenticate(template (value) Challenge_list challenge) := {
513 fieldName := WWW_AUTHENTICATE_E,
514 challenge := challenge
515}
Harald Welteb0d93602018-03-20 18:09:34 +0100516
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200517// RFC3329
518template (present) Security_client
519tr_Security_client(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
520 fieldName := SECURITY_CLIENT_E,
521 sec_mechanism_list := sec_mechanism_list
522}
523template (value) Security_client
524ts_Security_client(template (value) Security_mechanism_list sec_mechanism_list) := {
525 fieldName := SECURITY_CLIENT_E,
526 sec_mechanism_list := sec_mechanism_list
527}
528
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200529template (present) Security_server
530tr_Security_server(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
531 fieldName := SECURITY_SERVER_E,
532 sec_mechanism_list := sec_mechanism_list
533}
534template (value) Security_server
535ts_Security_server(template (value) Security_mechanism_list sec_mechanism_list) := {
536 fieldName := SECURITY_SERVER_E,
537 sec_mechanism_list := sec_mechanism_list
538}
539
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200540template (present) Security_mechanism
541tr_Security_mechanism(template (present) charstring name := ?,
542 template SemicolonParam_List params := *) := {
543 mechanism_name := name,
544 mechanism_params := params
545}
546template (value) Security_mechanism
547ts_Security_mechanism(template (value) charstring name,
548 template (omit) SemicolonParam_List params := omit) := {
549 mechanism_name := name,
550 mechanism_params := params
551}
552
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100553template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
554template (value) MessageHeader
555ts_SIP_msgh_std(template (value) CallidString call_id,
556 template (value) SipAddr from_addr,
557 template (value) SipAddr to_addr,
558 template (omit) Contact contact,
559 template (value) charstring method,
560 template (value) integer seq_nr,
561 template (value) Via via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200562 template (omit) ContentLength content_length := ts_ContentLength(0),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100563 template (omit) ContentType content_type := omit,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200564 template (omit)Authorization authorization := omit,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200565 template (omit) Allow allow := ts_Allow(c_SIP_defaultMethods),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200566 template (omit) Expires expires := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200567 template (omit) Require require := omit,
568 template (omit) Security_client security_client := omit,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200569 template (omit) Security_server security_server := omit,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200570 template (omit) Server server := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200571 template (omit) Supported supported := omit,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200572 template (omit) UserAgent userAgent := ts_UserAgent({ "osmo-ttcn3-hacks/0.23" }),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200573 template (omit) WwwAuthenticate wwwAuthenticate := omit
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100574 ) modifies ts_SIP_msgHeader_empty := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200575 allow := allow,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200576 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100577 callId := {
578 fieldName := CALL_ID_E,
579 callid := call_id
580 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100581 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200582 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100583 contentType := content_type,
584 cSeq := {
585 fieldName := CSEQ_E,
586 seqNumber := seq_nr,
587 method := method
588 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100589 expires := expires,
Harald Welteb0d93602018-03-20 18:09:34 +0100590 fromField := {
591 fieldName := FROM_E,
592 addressField := from_addr.addr,
593 fromParams := from_addr.params
594 },
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200595 require := require,
596 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200597 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200598 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200599 supported := supported,
Harald Welteb0d93602018-03-20 18:09:34 +0100600 toField := {
601 fieldName := TO_E,
602 addressField := to_addr.addr,
603 toParams := to_addr.params
604 },
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200605 userAgent := userAgent,
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200606 via := via,
607 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100608}
609
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100610template (present) MessageHeader
611tr_SIP_msgh_std(template CallidString call_id,
612 template SipAddr from_addr,
613 template SipAddr to_addr,
614 template Contact contact,
615 template (present) Via via := tr_Via_from(?),
616 template charstring method,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100617 template integer seq_nr := ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200618 template ContentLength content_length := *,
619 template ContentType content_type := *,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200620 template Allow allow := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200621 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200622 template Require require := *,
623 template Security_client security_client := *,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200624 template Security_server security_server := *,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200625 template Server server := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200626 template Supported supported := *,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200627 template UserAgent userAgent := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200628 template WwwAuthenticate wwwAuthenticate := *
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100629 ) modifies t_SIP_msgHeader_any := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200630 allow := allow,
Harald Welteb0d93602018-03-20 18:09:34 +0100631 callId := {
632 fieldName := CALL_ID_E,
633 callid := call_id
634 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100635 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200636 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100637 contentType := content_type,
638 cSeq := {
639 fieldName := CSEQ_E,
640 seqNumber := seq_nr,
641 method := method
642 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100643 expires := expires,
Harald Welteb0d93602018-03-20 18:09:34 +0100644 fromField := {
645 fieldName := FROM_E,
646 addressField := from_addr.addr,
647 fromParams := from_addr.params
648 },
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200649 require := require,
650 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200651 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200652 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200653 supported := supported,
Harald Welteb0d93602018-03-20 18:09:34 +0100654 toField := {
655 fieldName := TO_E,
656 addressField := to_addr.addr,
657 toParams := to_addr.params
658 },
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200659 userAgent := userAgent,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200660 via := via,
661 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100662}
663
664
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100665template (value) PDU_SIP_Request
666ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
667 template (value) CallidString call_id,
668 template (value) SipAddr from_addr,
669 template (value) SipAddr to_addr,
670 template (value) Via via,
671 integer seq_nr,
672 template (omit) Contact contact,
673 template (omit) Expires expires,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200674 template (omit) Authorization authorization := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200675 template (omit) Require require := omit,
676 template (omit) Security_client security_client := omit,
677 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100678 template (omit) charstring body := omit) := {
679 requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
680 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
681 "REGISTER", seq_nr, via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200682 content_length := f_ContentLength(body),
683 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200684 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200685 expires := expires,
686 require := require,
687 security_client := security_client,
688 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100689 messageBody := body,
690 payload := omit
691}
692template (present) PDU_SIP_Request
693tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
694 template (present) CallidString call_id := ?,
695 template (present) SipAddr from_addr := ?,
696 template (present) SipAddr to_addr := ?,
Pau Espin Pedrol0dd3f262024-04-25 17:04:43 +0200697 template (present) Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100698 template integer seq_nr := *,
699 template Contact contact := *,
700 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200701 template Require require := *,
702 template Security_client security_client := *,
703 template Supported supported := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100704 template charstring body := *) := {
705 requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
706 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200707 via, "REGISTER", seq_nr,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200708 expires := expires,
709 require := require,
710 security_client := security_client,
711 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100712 messageBody := body,
713 payload := omit
714}
715
716template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200717ts_SIP_INVITE(template (value) CallidString call_id,
718 template (value) SipAddr from_addr,
719 template (value) SipAddr to_addr,
720 template (value) Via via,
721 template (value) Contact contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100722 integer seq_nr,
723 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100724 requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200725 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100726 "INVITE", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200727 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200728 content_length := f_ContentLength(body),
729 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100730 messageBody := body,
731 payload := omit
732}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100733template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200734tr_SIP_INVITE(template (present) SipUrl uri,
735 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100736 template SipAddr from_addr,
737 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200738 template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100739 template integer seq_nr,
740 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200741 requestLine := tr_SIP_ReqLine(INVITE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100742 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200743 via, "INVITE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100744 messageBody := body,
745 payload := omit
746}
747
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100748template (value) PDU_SIP_Request
749ts_SIP_BYE(CallidString call_id,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200750 template (value) SipAddr from_addr,
751 template (value) SipAddr to_addr,
752 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100753 integer seq_nr,
754 template (omit) charstring body) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100755 requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
756 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200757 via,
758 content_length := f_ContentLength(body),
759 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100760 messageBody := body,
761 payload := omit
762}
763
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100764template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200765tr_SIP_BYE(template (present) SipUrl uri,
766 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100767 template SipAddr from_addr,
768 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200769 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100770 template integer seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200771 template charstring body := *) := {
772 requestLine := tr_SIP_ReqLine(BYE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100773 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200774 via, "BYE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100775 messageBody := body,
776 payload := omit
777}
778
779
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100780template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200781ts_SIP_ACK(template (value) CallidString call_id,
782 template (value) SipAddr from_addr,
783 template (value) SipAddr to_addr,
784 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100785 integer seq_nr,
786 template (omit) charstring body) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100787 requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100788 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
789 ts_Contact_SipAddr(from_addr),
790 "ACK", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200791 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200792 content_length := f_ContentLength(body),
793 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100794 messageBody := body,
795 payload := omit
796}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100797template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200798tr_SIP_ACK(template (present) SipUrl uri,
799 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100800 template SipAddr from_addr,
801 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200802 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100803 template integer seq_nr,
804 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200805 requestLine := tr_SIP_ReqLine(ACK_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100806 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200807 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200808 "ACK", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100809 messageBody := body,
810 payload := omit
811}
812
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200813template (present) PDU_SIP_Request
814tr_SIP_CANCEL(template (present) SipUrl uri,
815 template (present) CallidString call_id,
816 template (present) SipAddr from_addr,
817 template (present) SipAddr to_addr,
818 template (present) Via via,
819 template (present) integer seq_nr,
820 template charstring body := *) := {
821 requestLine := tr_SIP_ReqLine(CANCEL_E, uri),
822 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
823 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200824 "CANCEL", seq_nr),
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200825 messageBody := body,
826 payload := omit
827}
828
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100829template (value) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200830ts_SIP_Response(template (value) CallidString call_id,
831 template (value) SipAddr from_addr,
832 template (value) SipAddr to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100833 charstring method,
834 integer status_code,
835 integer seq_nr,
836 charstring reason,
837 Via via,
838 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100839 statusLine := ts_SIP_StatusLine(status_code, reason),
840 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200841 via,
842 content_length := f_ContentLength(body),
843 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100844 messageBody := body,
845 payload := omit
846}
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200847/* 100 Trying */
848template (value) PDU_SIP_Response
849ts_SIP_Response_Trying(
850 template (value) CallidString call_id,
851 template (value) SipAddr from_addr,
852 template (value) SipAddr to_addr,
853 Via via,
854 integer seq_nr,
855 charstring method := "INVITE",
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200856 template (omit) Allow allow := omit,
857 template (omit) Server server := omit,
858 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200859 template (omit) charstring body := omit) := {
860 statusLine := ts_SIP_StatusLine(100, "Trying"),
861 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200862 via,
863 content_length := f_ContentLength(body),
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200864 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
865 allow := allow,
866 server := server,
867 userAgent := userAgent),
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200868 messageBody := body,
869 payload := omit
870}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200871/* 180 Ringing */
872template (value) PDU_SIP_Response
873ts_SIP_Response_Ringing(
874 template (value) CallidString call_id,
875 template (value) SipAddr from_addr,
876 template (value) SipAddr to_addr,
877 Via via,
878 integer seq_nr,
879 charstring method := "INVITE",
880 template (omit) charstring body := omit) := {
881 statusLine := ts_SIP_StatusLine(180, "Ringing"),
882 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200883 via,
884 content_length := f_ContentLength(body),
885 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200886 messageBody := body,
887 payload := omit
888}
889
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200890/* 401 Unauthorized */
891template (value) PDU_SIP_Response
892ts_SIP_Response_Unauthorized(
893 template (value) CallidString call_id,
894 template (value) SipAddr from_addr,
895 template (value) SipAddr to_addr,
896 Via via,
897 template (value) WwwAuthenticate wwwAuthenticate,
898 integer seq_nr,
899 charstring method := "REGISTER",
900 template (omit) Allow allow := omit,
901 template (omit) Security_server security_server := omit,
902 template (omit) Server server := omit,
903 template (omit) Supported supported := omit,
904 template (omit) UserAgent userAgent := omit,
905 template (omit) charstring body := omit) := {
906 statusLine := ts_SIP_StatusLine(401, "Unauthorized"),
907 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
908 via,
909 content_length := f_ContentLength(body),
910 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
911 allow := allow,
912 security_server := security_server,
913 server := server,
914 supported := supported,
915 userAgent := userAgent,
916 wwwAuthenticate := wwwAuthenticate),
917 messageBody := body,
918 payload := omit
919}
920
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100921template (present) PDU_SIP_Response
922tr_SIP_Response(template CallidString call_id,
923 template SipAddr from_addr,
924 template SipAddr to_addr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200925 template (present) Via via := tr_Via_from(?),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100926 template Contact contact,
927 template charstring method,
928 template integer status_code,
929 template integer seq_nr := ?,
930 template charstring reason := ?,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200931 template charstring body := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100932 statusLine := tr_SIP_StatusLine(status_code, reason),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100933 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200934 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200935 method, seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100936 messageBody := body,
937 payload := omit
938}
939
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200940/* Expect during first REGISTER/INVITE/... when authorization is required: */
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100941template (present) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200942tr_SIP_Response_Unauthorized(
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100943 template CallidString call_id,
944 template SipAddr from_addr,
945 template SipAddr to_addr,
946 template (present) Via via := tr_Via_from(?),
947 template Contact contact := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200948 template (present) WwwAuthenticate wwwAuthenticate := ?,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100949 template integer seq_nr := ?,
950 template charstring method := "REGISTER",
951 template integer status_code := 401,
952 template charstring reason := "Unauthorized",
953 template charstring body := *) := {
954 statusLine := tr_SIP_StatusLine(status_code, reason),
955 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
956 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200957 method, seq_nr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200958 wwwAuthenticate := wwwAuthenticate),
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100959 messageBody := body,
960 payload := omit
961}
Harald Welteb0d93602018-03-20 18:09:34 +0100962
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200963/* 100 Trying */
964template (present) PDU_SIP_Response
965tr_SIP_Response_Trying(
966 template CallidString call_id,
967 template SipAddr from_addr,
968 template SipAddr to_addr,
969 template (present) Via via := tr_Via_from(?),
970 template integer seq_nr := ?,
971 template charstring method := "INVITE",
972 template integer status_code := 100,
973 template charstring reason := "Trying",
974 template charstring body := *) := {
975 statusLine := tr_SIP_StatusLine(status_code, reason),
976 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
977 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200978 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200979 messageBody := body,
980 payload := omit
981}
982
983/* 180 Ringing */
984template (present) PDU_SIP_Response
985tr_SIP_Response_Ringing(
986 template CallidString call_id,
987 template SipAddr from_addr,
988 template SipAddr to_addr,
989 template (present) Via via := tr_Via_from(?),
990 template integer seq_nr := ?,
991 template charstring method := "INVITE",
992 template integer status_code := 180,
993 template charstring reason := "Ringing",
994 template charstring body := *) := {
995 statusLine := tr_SIP_StatusLine(status_code, reason),
996 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
997 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200998 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200999 messageBody := body,
1000 payload := omit
1001}
1002
1003/****************
1004 * FUNCTIONS:
1005 ****************/
1006
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001007function f_sip_param_find(GenericParam_List li,
1008 template (present) charstring id := ?)
1009return template (omit) GenericParam {
1010 var integer i;
1011
1012 for (i := 0; i < lengthof(li); i := i + 1) {
1013 if (not ispresent(li[i])) {
1014 continue;
1015 }
1016 if (match(li[i].id, id)) {
1017 return li[i];
1018 }
1019 }
1020 return omit;
1021}
1022
1023function f_sip_param_find_or_fail(GenericParam_List li,
1024 template (present) charstring id := ?)
1025return GenericParam {
1026 var template (omit) GenericParam parameter;
1027 parameter := f_sip_param_find(li, id);
1028 if (istemplatekind(parameter, "omit")) {
1029 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1030 log2str("Param ", id, " not found in ", li));
1031 }
1032 return valueof(parameter);
1033}
1034
1035function f_sip_param_get_value(GenericParam_List li,
1036 template (present) charstring id := ?)
1037return template (omit) charstring {
1038 var template (omit) GenericParam parameter;
1039 parameter := f_sip_param_find(li, id);
1040 if (istemplatekind(parameter, "omit")) {
1041 return omit;
1042 }
1043 return parameter.paramValue;
1044}
1045
1046function f_sip_param_get_value_or_fail(GenericParam_List li,
1047 template (present) charstring id := ?)
1048return template (omit) charstring {
1049 var GenericParam parameter;
1050 parameter := f_sip_param_find_or_fail(li, id);
1051 return parameter.paramValue;
1052}
1053
1054function f_sip_param_get_value_present_or_fail(GenericParam_List li,
1055 template (present) charstring id := ?)
1056return charstring {
1057 var GenericParam parameter;
1058 parameter := f_sip_param_find_or_fail(li, id);
1059 if (not ispresent(parameter.paramValue)) {
1060 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1061 log2str("Param ", id, " value not present in ", li));
1062 }
1063 return parameter.paramValue;
1064}
1065
1066function f_sip_param_match_value(GenericParam_List li,
1067 template (present) charstring id := ?,
1068 template charstring exp_paramValue := *)
1069return boolean {
1070 var template (omit) charstring val;
1071 val := f_sip_param_get_value_or_fail(li, id);
1072 if (istemplatekind(val, "omit")) {
1073 return istemplatekind(val, "omit") or istemplatekind(val, "*");
1074 }
1075 return match(valueof(val), exp_paramValue);
1076}
1077
1078function f_sip_param_match_value_or_fail(GenericParam_List li,
1079 template (present) charstring id := ?,
1080 template charstring exp_paramValue := *)
1081{
1082 var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id);
1083 if (istemplatekind(val, "omit")) {
1084 if (istemplatekind(val, "omit") or istemplatekind(val, "*")) {
1085 return;
1086 } else {
1087 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1088 log2str("Param ", id, " match failed: val ", val,
1089 " vs exp ", exp_paramValue));
1090 }
1091 }
1092 if (not match(valueof(val), exp_paramValue)) {
1093 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1094 log2str("Param ", id, " match failed: val ", val,
1095 " vs exp ", exp_paramValue));
1096 }
1097}
1098
1099function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id)
1100return GenericParam_List {
1101 var integer i;
1102 var GenericParam_List li;
1103 var GenericParam_List new_li := {};
1104
1105 if (istemplatekind(li_tpl, "omit")) {
1106 return {};
1107 }
1108
1109 li := valueof(li_tpl);
1110 for (i := 0; i < lengthof(li); i := i + 1) {
1111 if (not ispresent(li[i]) or
1112 not match(li[i].id, id)) {
1113 new_li := new_li & {li[i]};
1114 }
1115 }
1116 return new_li;
1117}
1118
1119function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val)
1120return GenericParam_List {
1121 var integer i;
1122 var GenericParam_List li;
1123 var GenericParam_List new_li := {};
1124 var boolean found := false;
1125
1126 if (istemplatekind(li_tpl, "omit")) {
1127 return { valueof(ts_Param(id, val)) };
1128 }
1129
1130 li := valueof(li_tpl);
1131 for (i := 0; i < lengthof(li); i := i + 1) {
1132 if (not ispresent(li[i]) or
1133 not match(li[i].id, id)) {
1134 new_li := new_li & {li[i]};
1135 continue;
1136 }
1137 new_li := new_li & { valueof(ts_Param(li[i].id, val)) };
1138 found := true;
1139 }
1140
1141 if (not found) {
1142 new_li := new_li & { valueof(ts_Param(id, val)) };
1143 }
1144 return new_li;
1145}
1146
1147/* Make sure string is quoted. */
1148function f_sip_str_quote(template (value) charstring val) return charstring {
1149 var charstring str := valueof(val);
1150 if (lengthof(str) == 0) {
1151 return "";
1152 }
1153
1154 if (str[0] != "\"") {
1155 return "\"" & str & "\"";
1156 }
1157 return str;
1158}
1159
1160/* Make sure string is unquoted.
1161 * Similar to unq() in RFC 2617 */
1162function f_sip_str_unquote(template (value) charstring val) return charstring {
1163 var charstring str := valueof(val);
1164 var integer len := lengthof(str);
1165
1166 if (len <= 1) {
1167 return str;
1168 }
1169
1170 if (str[0] == "\"" and str[len - 1] == "\"") {
1171 return substr(str, 1, len - 2);
1172 }
1173 return str;
1174}
1175
1176/* RFC 2617 3.2.2.2 A1 */
1177function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring {
1178
1179 /* RFC 2617 3.2.2.2 A1 */
1180 var charstring A1 := f_sip_str_unquote(user) & ":" &
1181 f_sip_str_unquote(realm) & ":" &
1182 password;
1183 var charstring digestA1 := f_str_tolower(f_calculateMD5(A1));
1184 log("A1: md5('", A1, "') = ", digestA1);
1185 return digestA1;
1186}
1187
1188/* RFC 2617 3.2.2.2 A2 */
1189function f_sip_digest_A2(charstring method, charstring uri) return charstring {
1190
1191 var charstring A2 := method & ":" & uri
1192 var charstring digestA2 := f_str_tolower(f_calculateMD5(A2));
1193 log("A2: md5('", A2, "') = ", digestA2);
1194 return digestA2;
1195}
1196
1197/* RFC 2617 3.2.2.1 Request-Digest */
1198function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce,
1199 charstring nc, charstring cnonce,
1200 charstring qop, charstring digestA2) return charstring {
1201 var charstring digest_data := f_sip_str_unquote(nonce) & ":" &
1202 nc & ":" &
1203 cnonce & ":" &
1204 f_sip_str_unquote(qop) & ":" &
1205 digestA2;
1206 var charstring req_digest := f_sip_digest_KD(digestA1, digest_data);
1207 log("Request-Digest: md5('", digestA1, ":", digest_data ,"') = ", req_digest);
1208 return req_digest;
1209}
1210
1211/* RFC 2617 3.2.1 The WWW-Authenticate Response Header
1212 * KD(secret, data) = H(concat(secret, ":", data))
1213 */
1214function f_sip_digest_KD(charstring secret, charstring data) return charstring {
1215 return f_str_tolower(f_calculateMD5(secret & ":" & data));
1216}
1217
1218/* Digest Auth: RFC 2617 */
1219function f_sip_digest_gen_Authorization(WwwAuthenticate www_authenticate,
1220 charstring user, charstring password,
1221 charstring method, charstring uri,
1222 charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization {
1223 var CommaParam_List digestCln;
1224 var template (value) Authorization authorization;
1225 var template (value) Credentials cred;
1226 var template (omit) GenericParam rx_param;
1227
1228 digestCln := www_authenticate.challenge[0].digestCln;
1229
1230 var charstring algorithm;
1231 rx_param := f_sip_param_find(digestCln, "algorithm");
1232 if (istemplatekind(rx_param, "omit")) {
1233 /* Assume MD5 if not set */
1234 algorithm := "MD5"
1235 } else {
1236 algorithm := valueof(rx_param.paramValue);
1237 if (f_strstr(algorithm, "MD5") == -1) {
1238 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1239 log2str("Unexpected algorithm: ", algorithm));
1240 }
1241 }
1242
1243 var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
1244 var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
1245 var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque");
1246 var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop");
1247
1248 if (f_strstr(qop, "auth") == -1) {
1249 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1250 }
1251 var charstring selected_qop := "auth";
1252
1253 /* RFC 2617 3.2.2.2 A1 */
1254 var charstring digestA1 := f_sip_digest_A1(user, realm, password);
1255 /* RFC 2617 3.2.2.3 A2 */
1256 var charstring digestA2 := f_sip_digest_A2(method, uri);
1257
1258 /* RFC 2617 3.2.2.1 Request-Digest */
1259 var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8)));
1260 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1261 nc, cnonce,
1262 selected_qop, digestA2);
1263
1264 cred := ts_Credentials_DigestResponseMD5(user, realm, nonce,
1265 uri, req_digest,
1266 opaque, algorithm, selected_qop, cnonce, nc);
1267
1268 authorization := ts_Authorization(cred);
1269 return valueof(authorization);
1270}
1271
1272/* RFC 2617 3.5 Example */
1273function f_sip_digest_selftest() {
1274/*
1275The following example assumes that an access-protected document is
1276being requested from the server via a GET request. The URI of the
1277document is "http://www.nowhere.org/dir/index.html". Both client and
1278server know that the username for this document is "Mufasa", and the
1279password is "Circle Of Life" (with one space between each of the
1280three words).
1281
1282HTTP/1.1 401 Unauthorized
1283WWW-Authenticate: Digest
1284 realm="testrealm@host.com",
1285 qop="auth,auth-int",
1286 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1287 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1288
1289Authorization: Digest username="Mufasa",
1290 realm="testrealm@host.com",
1291 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1292 uri="/dir/index.html",
1293 qop=auth,
1294 nc=00000001,
1295 cnonce="0a4f113b",
1296 response="6629fae49393a05397450978507c4ef1",
1297 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1298*/
1299 var template (value) CommaParam_List digestCln := {
1300 ts_Param("realm", f_sip_str_quote("testrealm@host.com")),
1301 ts_Param("qop", f_sip_str_quote("auth,auth-int")),
1302 ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")),
1303 ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"))
1304 };
1305 var template (value) WwwAuthenticate www_authenticate :=
1306 ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
1307
1308 var Authorization authorization :=
1309 f_sip_digest_gen_Authorization(valueof(www_authenticate),
1310 "Mufasa",
1311 "Circle Of Life",
1312 "GET",
1313 "/dir/index.html",
1314 cnonce := "0a4f113b",
1315 nc_int := 1);
1316
1317 var CommaParam_List digestResp := authorization.body.digestResponse;
1318 f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com"));
1319 f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093"));
1320 f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html"));
1321 f_sip_param_match_value_or_fail(digestResp, "qop", "auth");
1322 f_sip_param_match_value_or_fail(digestResp, "nc", "00000001");
1323 f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b"));
1324 f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1"));
1325 f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"));
1326}
1327
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01001328/* RFC 3261 8.1.1.5:
1329 * "The sequence number value MUST be expressible as a 32-bit unsigned integer
1330 * and MUST be less than 2**31."
1331 */
1332function f_sip_rand_seq_nr() return integer {
1333 /* 2**31 = 2147483648 */
1334 return f_rnd_int(2147483648)
1335}
Harald Welteb0d93602018-03-20 18:09:34 +01001336
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001337function f_sip_next_seq_nr(integer seq_nr) return integer {
1338 return (seq_nr + 1) mod 2147483648;
1339}
1340
1341function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
1342 req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
1343}
1344
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001345function f_sip_rand_tag() return charstring {
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001346 /* Tags shall have at least 32 bit of randomness */
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001347 var integer rnd_int := f_rnd_int(4294967296);
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001348 /* Make collisions harder by appending time to the final string: */
1349 var integer ts_int := f_time_ms() mod 4294967296;
1350 return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8));
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001351}
1352
1353/* Generate a "branch" tag value.
1354 * RFC 3261 p.105 section 8:
1355 * "A common way to create this value is to compute a
1356 * cryptographic hash of the To tag, From tag, Call-ID header
1357 * field, the Request-URI of the request received (before
1358 * translation), the topmost Via header, and the sequence number
1359 * from the CSeq header field, in addition to any Proxy-Require
1360 * and Proxy-Authorization header fields that may be present. The
1361 * algorithm used to compute the hash is implementation-dependent,
1362 * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable
1363 * choice."
1364 * See also Section 8.1.1.7:
1365 * "The branch ID inserted by an element compliant with this
1366 * specification MUST always begin with the characters "z9hG4bK"."
1367 */
1368const charstring sip_magic_cookie := "z9hG4bK";
1369function f_sip_gen_branch(charstring tag_to,
1370 charstring tag_from,
1371 charstring tag_call_id,
1372 integer cseq) return charstring {
1373 var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq);
1374 var charstring hash := f_calculateMD5(str);
1375 var charstring branch := sip_magic_cookie & hash;
1376 return branch;
1377}
1378
1379function f_sip_HostPort_to_str(HostPort host_port) return charstring {
1380 var charstring str := "";
1381 if (ispresent(host_port.host)) {
1382 str := host_port.host;
1383 }
1384 if (ispresent(host_port.portField)) {
1385 str := str & ":" & int2str(host_port.portField);
1386 }
1387 return str;
1388}
1389
1390function f_sip_SipUrl_to_str(SipUrl uri) return charstring {
Pau Espin Pedrolad5e9962024-05-16 20:53:06 +02001391 var charstring str := uri.scheme & ":" & f_sip_HostPort_to_str(uri.hostPort);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001392 return str;
1393}
1394
1395function f_sip_NameAddr_to_str(NameAddr naddr) return charstring {
1396 if (ispresent(naddr.displayName)) {
1397 return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">";
1398 } else {
1399 return f_sip_SipUrl_to_str(naddr.addrSpec);
1400 }
1401}
1402
1403function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring {
1404 if (ischosen(sip_addr.addr.nameAddr)) {
1405 return f_sip_NameAddr_to_str(sip_addr.addr.nameAddr);
1406 } else {
1407 return f_sip_SipUrl_to_str(sip_addr.addr.addrSpecUnion);
1408 }
1409}
1410
Harald Welteb0d93602018-03-20 18:09:34 +01001411}