rust_rcs_client/provisioning/
ims_application.rs

1// Copyright 2023 宋昊文
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use super::characteristic::{Characteristic, RuntimeCharacteristics};
16use super::wap_provisioning_doc::WapProvisioningDoc;
17
18pub const DEFAULT_TRANSPORT_PROTO: TransportProto = TransportProto {
19    ps_signalling: SignallingProtocol::SIPoUDP,
20    ps_media: MediaProtocol::MSRP,
21    ps_rt_media: RealTimeMediaProtocol::RTP,
22
23    ps_signalling_roaming: SignallingProtocol::SIPoUDP,
24    ps_media_roaming: MediaProtocol::MSRP,
25    ps_rt_media_roaming: RealTimeMediaProtocol::RTP,
26
27    wifi_signalling: SignallingProtocol::SIPoTLS,
28    wifi_media: MediaProtocol::MSRPoTLS,
29    wifi_rt_media: RealTimeMediaProtocol::SRTP,
30};
31
32pub struct ImsApplication<'a> {
33    root: &'a Characteristic,
34}
35
36impl<'a> ImsApplication<'a> {
37    pub fn new(e: &Characteristic) -> ImsApplication {
38        ImsApplication { root: e }
39    }
40
41    pub fn clone_characteristic(&self) -> Characteristic {
42        self.root.clone()
43    }
44
45    pub fn get_ims_gsma_extension(&self) -> Option<ImsGMSAExtension> {
46        if let Some(ext) = self.root.get_child_characteristic("Ext") {
47            if let Some(gsma) = ext.get_child_characteristic("GSMA") {
48                return Some(ImsGMSAExtension { root: gsma });
49            }
50        }
51
52        None
53    }
54
55    pub fn get_lbo_p_cscf_addresses(&self) -> PCscfAddresses {
56        if let Some(addresses) = self.root.get_child_characteristic("LBO_P-CSCF_Address") {
57            let nodes = addresses.get_runtime_characteristics();
58            return PCscfAddresses { root: Some(nodes) };
59        }
60
61        PCscfAddresses { root: None }
62    }
63
64    pub fn get_home_domain(&self) -> Option<&str> {
65        if let Some(home) = self.root.get_parameter("Home_network_domain_name") {
66            return Some(home);
67        }
68
69        None
70    }
71
72    pub fn get_private_user_identity(&self) -> Option<&str> {
73        if let Some(pvui) = self.root.get_parameter("Private_User_Identity") {
74            return Some(pvui);
75        }
76
77        None
78    }
79
80    pub fn get_public_user_identity_list(&self) -> IMPUList {
81        if let Some(pbui_list) = self
82            .root
83            .get_child_characteristic("Public_User_Identity_List")
84        {
85            let nodes = pbui_list.get_runtime_characteristics();
86            return IMPUList { root: Some(nodes) };
87        }
88
89        IMPUList { root: None }
90    }
91}
92
93pub struct PCscfAddresses<'a> {
94    root: Option<RuntimeCharacteristics<'a>>,
95}
96
97impl<'a> Iterator for PCscfAddresses<'a> {
98    type Item = (&'a str, &'a str);
99    fn next(&mut self) -> Option<(&'a str, &'a str)> {
100        if let Some(ref mut nodes) = self.root {
101            while let Some(node) = nodes.next() {
102                if let (Some(address), Some(address_type)) = (
103                    node.get_parameter("Address"),
104                    node.get_parameter("AddressType"),
105                ) {
106                    return Some((address, address_type));
107                }
108            }
109        }
110
111        None
112    }
113}
114
115pub struct IMPUList<'a> {
116    root: Option<RuntimeCharacteristics<'a>>,
117}
118
119impl<'a> Iterator for IMPUList<'a> {
120    type Item = &'a str;
121    fn next(&mut self) -> Option<&'a str> {
122        if let Some(ref mut nodes) = self.root {
123            while let Some(node) = nodes.next() {
124                if let Some(impu) = node.get_parameter("Public_User_Identity") {
125                    return Some(impu);
126                }
127            }
128        }
129
130        None
131    }
132}
133
134pub struct ImsGMSAExtension<'a> {
135    root: &'a Characteristic,
136}
137
138impl<'a> ImsGMSAExtension<'a> {
139    pub fn get_info(&self) -> ImsGSMAExtensionInfo {
140        ImsGSMAExtensionInfo {
141            app_ref: self.root.get_parameter("AppRef"),
142            auth_type: self.root.get_parameter("AuthType"),
143            realm: self.root.get_parameter("Realm"),
144            user_name: self.root.get_parameter("UserName"),
145            user_password: self.root.get_parameter("UserPwd"),
146            eucr_id: self.root.get_parameter("endUserConfReqId"),
147            transport_proto: self.root.get_child_characteristic("transportProto"),
148            uuid_value: self.root.get_parameter("uuid_Value"),
149        }
150    }
151}
152
153pub struct ImsGSMAExtensionInfo<'a> {
154    pub app_ref: Option<&'a str>,
155    pub auth_type: Option<&'a str>,
156    pub realm: Option<&'a str>,
157    pub user_name: Option<&'a str>,
158    pub user_password: Option<&'a str>,
159    pub eucr_id: Option<&'a str>,
160    transport_proto: Option<&'a Characteristic>,
161    pub uuid_value: Option<&'a str>,
162}
163
164impl<'a> ImsGSMAExtensionInfo<'a> {
165    pub fn get_transport_proto_info(&self) -> Option<TransportProto> {
166        if let Some(e) = self.transport_proto {
167            return Some(TransportProto {
168                ps_signalling: if let Some(proto) = e.get_parameter("psSignalling") {
169                    match proto {
170                        "SIPoTCP" => SignallingProtocol::SIPoTCP,
171                        "SIPoUDP" => SignallingProtocol::SIPoUDP,
172                        "SIPoTLS" => SignallingProtocol::SIPoTLS,
173                        _ => SignallingProtocol::SIPoUDP,
174                    }
175                } else {
176                    SignallingProtocol::SIPoUDP
177                },
178                ps_media: if let Some(proto) = e.get_parameter("psMedia") {
179                    match proto {
180                        "MSRP" => MediaProtocol::MSRP,
181                        "MSRPoTLS" => MediaProtocol::MSRPoTLS,
182                        _ => MediaProtocol::MSRP,
183                    }
184                } else {
185                    MediaProtocol::MSRP
186                },
187                ps_rt_media: if let Some(proto) = e.get_parameter("psRTMedia") {
188                    match proto {
189                        "RTP" => RealTimeMediaProtocol::RTP,
190                        "SRTP" => RealTimeMediaProtocol::SRTP,
191                        _ => RealTimeMediaProtocol::RTP,
192                    }
193                } else {
194                    RealTimeMediaProtocol::RTP
195                },
196                ps_signalling_roaming: if let Some(proto) = e.get_parameter("psSignallingRoaming") {
197                    match proto {
198                        "SIPoTCP" => SignallingProtocol::SIPoTCP,
199                        "SIPoUDP" => SignallingProtocol::SIPoUDP,
200                        "SIPoTLS" => SignallingProtocol::SIPoTLS,
201                        _ => SignallingProtocol::SIPoUDP,
202                    }
203                } else {
204                    SignallingProtocol::SIPoUDP
205                },
206                ps_media_roaming: if let Some(proto) = e.get_parameter("psMediaRoaming") {
207                    match proto {
208                        "MSRP" => MediaProtocol::MSRP,
209                        "MSRPoTLS" => MediaProtocol::MSRPoTLS,
210                        _ => MediaProtocol::MSRP,
211                    }
212                } else {
213                    MediaProtocol::MSRP
214                },
215                ps_rt_media_roaming: if let Some(proto) = e.get_parameter("psRTMediaRoaming") {
216                    match proto {
217                        "RTP" => RealTimeMediaProtocol::RTP,
218                        "SRTP" => RealTimeMediaProtocol::SRTP,
219                        _ => RealTimeMediaProtocol::RTP,
220                    }
221                } else {
222                    RealTimeMediaProtocol::RTP
223                },
224                wifi_signalling: if let Some(proto) = e.get_parameter("wifiSignalling") {
225                    match proto {
226                        "SIPoTCP" => SignallingProtocol::SIPoTCP,
227                        "SIPoUDP" => SignallingProtocol::SIPoUDP,
228                        "SIPoTLS" => SignallingProtocol::SIPoTLS,
229                        _ => SignallingProtocol::SIPoTLS,
230                    }
231                } else {
232                    SignallingProtocol::SIPoTLS
233                },
234                wifi_media: if let Some(proto) = e.get_parameter("wifiMedia") {
235                    match proto {
236                        "MSRP" => MediaProtocol::MSRP,
237                        "MSRPoTLS" => MediaProtocol::MSRPoTLS,
238                        _ => MediaProtocol::MSRPoTLS,
239                    }
240                } else {
241                    MediaProtocol::MSRPoTLS
242                },
243                wifi_rt_media: if let Some(proto) = e.get_parameter("wifiRTMedia") {
244                    match proto {
245                        "RTP" => RealTimeMediaProtocol::RTP,
246                        "SRTP" => RealTimeMediaProtocol::SRTP,
247                        _ => RealTimeMediaProtocol::SRTP,
248                    }
249                } else {
250                    RealTimeMediaProtocol::SRTP
251                },
252            });
253        }
254
255        None
256    }
257}
258
259pub enum SignallingProtocol {
260    SIPoTCP,
261    SIPoUDP,
262    SIPoTLS,
263}
264
265pub enum MediaProtocol {
266    MSRP,
267    MSRPoTLS,
268}
269
270pub enum RealTimeMediaProtocol {
271    RTP,
272    SRTP,
273}
274
275pub struct TransportProto {
276    pub ps_signalling: SignallingProtocol,
277    pub ps_media: MediaProtocol,
278    pub ps_rt_media: RealTimeMediaProtocol,
279
280    pub ps_signalling_roaming: SignallingProtocol,
281    pub ps_media_roaming: MediaProtocol,
282    pub ps_rt_media_roaming: RealTimeMediaProtocol,
283
284    pub wifi_signalling: SignallingProtocol,
285    pub wifi_media: MediaProtocol,
286    pub wifi_rt_media: RealTimeMediaProtocol,
287}
288
289impl TransportProto {
290    pub fn create_default() -> TransportProto {
291        TransportProto {
292            ps_signalling: SignallingProtocol::SIPoUDP,
293            ps_media: MediaProtocol::MSRP,
294            ps_rt_media: RealTimeMediaProtocol::RTP,
295            ps_signalling_roaming: SignallingProtocol::SIPoUDP,
296            ps_media_roaming: MediaProtocol::MSRP,
297            ps_rt_media_roaming: RealTimeMediaProtocol::RTP,
298            wifi_signalling: SignallingProtocol::SIPoTLS,
299            wifi_media: MediaProtocol::MSRPoTLS,
300            wifi_rt_media: RealTimeMediaProtocol::SRTP,
301        }
302    }
303}
304
305pub trait GetImsApplication {
306    fn get_ims_application(&self, app_ref: &str) -> Option<ImsApplication>;
307}
308
309impl<'a> GetImsApplication for &WapProvisioningDoc {
310    fn get_ims_application(&self, app_ref: &str) -> Option<ImsApplication> {
311        if let Some(ims_mo) = self.get_application_characteristic("urn:oma:mo:ext-3gpp-ims:1.0") {
312            for child in &ims_mo.child_characteristics {
313                if child.characteristic_type == "3GPP_IMS" {
314                    if let Some(ext) = child.get_child_characteristic("Ext") {
315                        if let Some(gsma) = ext.get_child_characteristic("GSMA") {
316                            if let Some(app_ref_parm) = gsma.get_parameter("AppRef") {
317                                if app_ref_parm == app_ref {
318                                    return Some(ImsApplication { root: &child });
319                                }
320                            }
321                        }
322                    }
323                }
324            }
325        }
326
327        None
328    }
329}