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}