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!(Failure, 0);
64        assert_size!(StartTls, 1);
65        assert_size!(Nonza, 1);
66    }
67
68    #[test]
69    fn test_parsers() {
70        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
71            .parse()
72            .unwrap();
73        let request = Request::try_from(elem.clone()).unwrap();
74        let elem2 = Element::from(request);
75        assert_eq!(elem, elem2);
76
77        let elem: Element = "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
78            .parse()
79            .unwrap();
80        let proceed = Proceed::try_from(elem.clone()).unwrap();
81        let elem2 = Element::from(proceed);
82        assert_eq!(elem, elem2);
83
84        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
85            .parse()
86            .unwrap();
87        let starttls = StartTls::try_from(elem.clone()).unwrap();
88        assert_eq!(starttls.required, false);
89        let elem2 = Element::from(starttls);
90        assert_eq!(elem, elem2);
91
92        let elem: Element =
93            "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls>"
94                .parse()
95                .unwrap();
96        let starttls = StartTls::try_from(elem.clone()).unwrap();
97        assert_eq!(starttls.required, true);
98        let elem2 = Element::from(starttls);
99        assert_eq!(elem, elem2);
100
101        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
102            .parse()
103            .unwrap();
104        let nonza = Nonza::try_from(elem.clone()).unwrap();
105        assert_eq!(nonza, Nonza::Request(Request));
106        let elem2 = Element::from(nonza);
107        assert_eq!(elem, elem2);
108
109        let elem: Element = "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
110            .parse()
111            .unwrap();
112        let nonza = Nonza::try_from(elem.clone()).unwrap();
113        assert_eq!(nonza, Nonza::Proceed(Proceed));
114        let elem2 = Element::from(nonza);
115        assert_eq!(elem, elem2);
116    }
117}