jingle_raw_udp.rs

  1// Copyright (c) 2020 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 core::net::IpAddr;
  8
  9use xso::{AsXml, FromXml};
 10
 11use crate::jingle_ice_udp::Type;
 12use crate::ns;
 13
 14/// Wrapper element for an raw UDP transport.
 15#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)]
 16#[xml(namespace = ns::JINGLE_RAW_UDP, name = "transport")]
 17pub struct Transport {
 18    /// List of candidates for this raw UDP session.
 19    #[xml(child(n = ..))]
 20    pub candidates: Vec<Candidate>,
 21}
 22
 23impl Transport {
 24    /// Create a new ICE-UDP transport.
 25    pub fn new() -> Transport {
 26        Transport::default()
 27    }
 28
 29    /// Add a candidate to this transport.
 30    pub fn add_candidate(mut self, candidate: Candidate) -> Self {
 31        self.candidates.push(candidate);
 32        self
 33    }
 34}
 35
 36/// A candidate for an ICE-UDP session.
 37#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 38#[xml(namespace = ns::JINGLE_RAW_UDP, name = "candidate")]
 39pub struct Candidate {
 40    /// A Component ID as defined in ICE-CORE.
 41    #[xml(attribute)]
 42    pub component: u8,
 43
 44    /// An index, starting at 0, that enables the parties to keep track of updates to the
 45    /// candidate throughout the life of the session.
 46    #[xml(attribute)]
 47    pub generation: u8,
 48
 49    /// A unique identifier for the candidate.
 50    #[xml(attribute)]
 51    pub id: String,
 52
 53    /// The Internet Protocol (IP) address for the candidate transport mechanism; this can be
 54    /// either an IPv4 address or an IPv6 address.
 55    #[xml(attribute)]
 56    pub ip: IpAddr,
 57
 58    /// The port at the candidate IP address.
 59    #[xml(attribute)]
 60    pub port: u16,
 61
 62    /// A Candidate Type as defined in ICE-CORE.
 63    #[xml(attribute(default, name = "type"))]
 64    pub type_: Option<Type>,
 65}
 66
 67#[cfg(test)]
 68mod tests {
 69    use super::*;
 70    use minidom::Element;
 71
 72    #[cfg(target_pointer_width = "32")]
 73    #[test]
 74    fn test_size() {
 75        assert_size!(Transport, 12);
 76        assert_size!(Candidate, 36);
 77    }
 78
 79    #[cfg(target_pointer_width = "64")]
 80    #[test]
 81    fn test_size() {
 82        assert_size!(Transport, 24);
 83        assert_size!(Candidate, 48);
 84    }
 85
 86    #[test]
 87    fn example_1() {
 88        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:raw-udp:1'>
 89    <candidate component='1'
 90               generation='0'
 91               id='a9j3mnbtu1'
 92               ip='10.1.1.104'
 93               port='13540'/>
 94</transport>"
 95            .parse()
 96            .unwrap();
 97        let mut transport = Transport::try_from(elem).unwrap();
 98        assert_eq!(transport.candidates.len(), 1);
 99        let candidate = transport.candidates.pop().unwrap();
100        assert_eq!(candidate.component, 1);
101        assert_eq!(candidate.generation, 0);
102        assert_eq!(candidate.id, "a9j3mnbtu1");
103        assert_eq!(candidate.ip, "10.1.1.104".parse::<IpAddr>().unwrap());
104        assert_eq!(candidate.port, 13540u16);
105        assert!(candidate.type_.is_none());
106    }
107}