xmpp_parsers/
starttls.rs

1// Copyright (c) 2024 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use xso::{AsXml, FromXml};
8
9use crate::ns;
10
11/// Request to start TLS.
12#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
13#[xml(namespace = ns::TLS, name = "starttls")]
14pub struct Request;
15
16/// Information that TLS may now commence.
17#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
18#[xml(namespace = ns::TLS, name = "proceed")]
19pub struct Proceed;
20
21/// Information that the peer cannot do TLS after all.
22#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
23#[xml(namespace = ns::TLS, name = "failure")]
24pub struct Failure;
25
26/// Stream feature for StartTLS
27///
28/// Used in [`crate::stream_features::StreamFeatures`].
29#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
30#[xml(namespace = ns::TLS, name = "starttls")]
31pub struct StartTls {
32    /// Marker for mandatory StartTLS.
33    #[xml(flag)]
34    pub required: bool,
35}
36
37/// Enum which allows parsing/serialising any STARTTLS element.
38#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
39#[xml()]
40pub enum Nonza {
41    /// Request to start TLS
42    #[xml(transparent)]
43    Request(Request),
44
45    /// Information that TLS may now commence
46    #[xml(transparent)]
47    Proceed(Proceed),
48
49    /// Information that the peer cannot do TLS after all.
50    #[xml(transparent)]
51    Failure(Failure),
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use minidom::Element;
58
59    #[test]
60    fn test_size() {
61        assert_size!(Request, 0);
62        assert_size!(Proceed, 0);
63        assert_size!(StartTls, 1);
64        assert_size!(Nonza, 1);
65    }
66
67    #[test]
68    fn test_parsers() {
69        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
70            .parse()
71            .unwrap();
72        let request = Request::try_from(elem.clone()).unwrap();
73        let elem2 = Element::from(request);
74        assert_eq!(elem, elem2);
75
76        let elem: Element = "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
77            .parse()
78            .unwrap();
79        let proceed = Proceed::try_from(elem.clone()).unwrap();
80        let elem2 = Element::from(proceed);
81        assert_eq!(elem, elem2);
82
83        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
84            .parse()
85            .unwrap();
86        let starttls = StartTls::try_from(elem.clone()).unwrap();
87        assert_eq!(starttls.required, false);
88        let elem2 = Element::from(starttls);
89        assert_eq!(elem, elem2);
90
91        let elem: Element =
92            "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls>"
93                .parse()
94                .unwrap();
95        let starttls = StartTls::try_from(elem.clone()).unwrap();
96        assert_eq!(starttls.required, true);
97        let elem2 = Element::from(starttls);
98        assert_eq!(elem, elem2);
99
100        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
101            .parse()
102            .unwrap();
103        let nonza = Nonza::try_from(elem.clone()).unwrap();
104        assert_eq!(nonza, Nonza::Request(Request));
105        let elem2 = Element::from(nonza);
106        assert_eq!(elem, elem2);
107
108        let elem: Element = "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
109            .parse()
110            .unwrap();
111        let nonza = Nonza::try_from(elem.clone()).unwrap();
112        assert_eq!(nonza, Nonza::Proceed(Proceed));
113        let elem2 = Element::from(nonza);
114        assert_eq!(elem, elem2);
115    }
116}