jingle: Wrap all supported and unknown transports in an enum.

This commit is contained in:
Emmanuel Gil Peyrot 2019-10-12 17:13:42 +02:00
parent b91e5bdc4e
commit 7665f7e5d8

View file

@ -6,6 +6,9 @@
use crate::util::error::Error;
use crate::iq::IqSetPayload;
use crate::jingle_ice_udp::Transport as IceUdpTransport;
use crate::jingle_ibb::Transport as IbbTransport;
use crate::jingle_s5b::Transport as Socks5Transport;
use crate::ns;
use jid::Jid;
use crate::Element;
@ -164,6 +167,78 @@ generate_id!(
ContentId
);
/// Enum wrapping all of the various supported transports of a Content.
#[derive(Debug, Clone)]
pub enum Transport {
/// Jingle ICE-UDP Bytestreams (XEP-0176) transport.
IceUdp(IceUdpTransport),
/// Jingle In-Band Bytestreams (XEP-0261) transport.
Ibb(IbbTransport),
/// Jingle SOCKS5 Bytestreams (XEP-0260) transport.
Socks5(Socks5Transport),
/// To be used for any transport that isnt known at compile-time.
Unknown(Element),
}
impl TryFrom<Element> for Transport {
type Error = Error;
fn try_from(elem: Element) -> Result<Transport, Error> {
Ok(if elem.is("transport", ns::JINGLE_ICE_UDP) {
Transport::IceUdp(IceUdpTransport::try_from(elem)?)
} else if elem.is("transport", ns::JINGLE_IBB) {
Transport::Ibb(IbbTransport::try_from(elem)?)
} else if elem.is("transport", ns::JINGLE_S5B) {
Transport::Socks5(Socks5Transport::try_from(elem)?)
} else {
Transport::Unknown(elem)
})
}
}
impl From<IceUdpTransport> for Transport {
fn from(transport: IceUdpTransport) -> Transport {
Transport::IceUdp(transport)
}
}
impl From<IbbTransport> for Transport {
fn from(transport: IbbTransport) -> Transport {
Transport::Ibb(transport)
}
}
impl From<Socks5Transport> for Transport {
fn from(transport: Socks5Transport) -> Transport {
Transport::Socks5(transport)
}
}
impl From<Transport> for Element {
fn from(transport: Transport) -> Element {
match transport {
Transport::IceUdp(transport) => transport.into(),
Transport::Ibb(transport) => transport.into(),
Transport::Socks5(transport) => transport.into(),
Transport::Unknown(elem) => elem,
}
}
}
impl Transport {
fn get_ns(&self) -> String {
match self {
Transport::IceUdp(_) => String::from(ns::JINGLE_ICE_UDP),
Transport::Ibb(_) => String::from(ns::JINGLE_IBB),
Transport::Socks5(_) => String::from(ns::JINGLE_S5B),
Transport::Unknown(elem) => elem.ns().unwrap_or_else(|| String::new()),
}
}
}
generate_element!(
/// Describes a sessions content, there can be multiple content in one
/// session.
@ -186,7 +261,7 @@ generate_element!(
description: Option<Element> = ("description", JINGLE) => Element,
/// How to send it.
transport: Option<Element> = ("transport", JINGLE) => Element,
transport: Option<Transport> = ("transport", *) => Transport,
/// With which security.
security: Option<Element> = ("security", JINGLE) => Element
@ -226,8 +301,8 @@ impl Content {
}
/// Set the transport of this content.
pub fn with_transport(mut self, transport: Element) -> Content {
self.transport = Some(transport);
pub fn with_transport<T: Into<Transport>>(mut self, transport: T) -> Content {
self.transport = Some(transport.into());
self
}
@ -575,7 +650,7 @@ mod tests {
assert_size!(Senders, 1);
assert_size!(Disposition, 1);
assert_size!(ContentId, 24);
assert_size!(Content, 344);
assert_size!(Content, 384);
assert_size!(Reason, 1);
assert_size!(ReasonElement, 32);
assert_size!(SessionId, 24);
@ -626,18 +701,18 @@ mod tests {
#[test]
fn test_content() {
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><content creator='initiator' name='coucou'><description/><transport/></content></jingle>".parse().unwrap();
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><content creator='initiator' name='coucou'><description/><transport xmlns='urn:xmpp:jingle:transports:stub:0'/></content></jingle>".parse().unwrap();
let jingle = Jingle::try_from(elem).unwrap();
assert_eq!(jingle.contents[0].creator, Creator::Initiator);
assert_eq!(jingle.contents[0].name, ContentId(String::from("coucou")));
assert_eq!(jingle.contents[0].senders, Senders::Both);
assert_eq!(jingle.contents[0].disposition, Disposition::Session);
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><content creator='initiator' name='coucou' senders='both'><description/><transport/></content></jingle>".parse().unwrap();
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><content creator='initiator' name='coucou' senders='both'><description/><transport xmlns='urn:xmpp:jingle:transports:stub:0'/></content></jingle>".parse().unwrap();
let jingle = Jingle::try_from(elem).unwrap();
assert_eq!(jingle.contents[0].senders, Senders::Both);
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><content creator='initiator' name='coucou' disposition='early-session'><description/><transport/></content></jingle>".parse().unwrap();
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><content creator='initiator' name='coucou' disposition='early-session'><description/><transport xmlns='urn:xmpp:jingle:transports:stub:0'/></content></jingle>".parse().unwrap();
let jingle = Jingle::try_from(elem).unwrap();
assert_eq!(jingle.contents[0].disposition, Disposition::EarlySession);
}