mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
Add alternate_address to StanzaError
[gone](https://datatracker.ietf.org/doc/html/rfc6120#section-8.3.3.5) and [redirect](https://datatracker.ietf.org/doc/html/rfc6120#section-8.3.3.14) errors may include an alternative address. > gone > > The recipient or server can no longer be contacted at this address, > typically on a permanent basis (as opposed to the <redirect/> error > condition, which is used for temporary addressing failures); the > associated error type SHOULD be "cancel" and the error stanza SHOULD > include a new address (if available) as the XML character data of the > <gone/> element (which MUST be a Uniform Resource Identifier [URI] or > Internationalized Resource Identifier [IRI] at which the entity can > be contacted, typically an XMPP IRI as specified in [XMPP-URI]). — > redirect > > The recipient or server is redirecting requests for this information > to another entity, typically in a temporary fashion (as opposed to > the <gone/> error condition, which is used for permanent addressing > failures); the associated error type SHOULD be "modify" and the error > stanza SHOULD contain the alternate address in the XML character data > of the <redirect/> element (which MUST be a URI or IRI with which the > sender can communicate, typically an XMPP IRI as specified in > [XMPP-URI](https://datatracker.ietf.org/doc/html/rfc6120#ref-XMPP-URI)).
This commit is contained in:
parent
ac0707e52d
commit
998d2825f8
2 changed files with 93 additions and 6 deletions
|
@ -232,15 +232,15 @@ mod tests {
|
|||
#[cfg(target_pointer_width = "32")]
|
||||
#[test]
|
||||
fn test_size() {
|
||||
assert_size!(IqType, 92);
|
||||
assert_size!(Iq, 156);
|
||||
assert_size!(IqType, 104);
|
||||
assert_size!(Iq, 168);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_size() {
|
||||
assert_size!(IqType, 184);
|
||||
assert_size!(Iq, 272);
|
||||
assert_size!(IqType, 208);
|
||||
assert_size!(Iq, 296);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -10,7 +10,9 @@ use crate::presence::PresencePayload;
|
|||
use crate::util::error::Error;
|
||||
use crate::Element;
|
||||
use jid::Jid;
|
||||
use minidom::Node;
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
generate_attribute!(
|
||||
/// The type of the error.
|
||||
|
@ -209,6 +211,11 @@ pub struct StanzaError {
|
|||
|
||||
/// A protocol-specific extension for this error.
|
||||
pub other: Option<Element>,
|
||||
|
||||
/// May include an alternate address if `defined_condition` is `Gone` or `Redirect`. It is
|
||||
/// a Uniform Resource Identifier [URI] or Internationalized Resource Identifier [IRI] at
|
||||
/// which the entity can be contacted, typically an XMPP IRI as specified in [XMPP‑URI]
|
||||
pub alternate_address: Option<String>,
|
||||
}
|
||||
|
||||
impl MessagePayload for StanzaError {}
|
||||
|
@ -236,6 +243,7 @@ impl StanzaError {
|
|||
map
|
||||
},
|
||||
other: None,
|
||||
alternate_address: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +263,7 @@ impl TryFrom<Element> for StanzaError {
|
|||
defined_condition: DefinedCondition::UndefinedCondition,
|
||||
texts: BTreeMap::new(),
|
||||
other: None,
|
||||
alternate_address: None,
|
||||
};
|
||||
let mut defined_condition = None;
|
||||
|
||||
|
@ -277,6 +286,14 @@ impl TryFrom<Element> for StanzaError {
|
|||
check_no_children!(child, "defined-condition");
|
||||
check_no_attributes!(child, "defined-condition");
|
||||
let condition = DefinedCondition::try_from(child.clone())?;
|
||||
|
||||
if condition == DefinedCondition::Gone || condition == DefinedCondition::Redirect {
|
||||
stanza_error.alternate_address = child.nodes().find_map(|node| {
|
||||
let Node::Text(text) = node else { return None };
|
||||
return Some(text.to_string());
|
||||
});
|
||||
}
|
||||
|
||||
defined_condition = Some(condition);
|
||||
} else {
|
||||
if stanza_error.other.is_some() {
|
||||
|
@ -319,7 +336,7 @@ mod tests {
|
|||
fn test_size() {
|
||||
assert_size!(ErrorType, 1);
|
||||
assert_size!(DefinedCondition, 1);
|
||||
assert_size!(StanzaError, 92);
|
||||
assert_size!(StanzaError, 104);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
|
@ -327,7 +344,7 @@ mod tests {
|
|||
fn test_size() {
|
||||
assert_size!(ErrorType, 1);
|
||||
assert_size!(DefinedCondition, 1);
|
||||
assert_size!(StanzaError, 184);
|
||||
assert_size!(StanzaError, 208);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -415,4 +432,74 @@ mod tests {
|
|||
let stanza_error = StanzaError::try_from(elem).unwrap();
|
||||
assert_eq!(stanza_error.type_, ErrorType::Cancel);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gone_with_new_address() {
|
||||
#[cfg(not(feature = "component"))]
|
||||
let elem: Element = "<error xmlns='jabber:client' type='cancel'><gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>xmpp:room@muc.example.org?join</gone></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
#[cfg(feature = "component")]
|
||||
let elem: Element = "<error xmlns='jabber:component:accept' type='cancel'><gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>xmpp:room@muc.example.org?join</gone></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
let error = StanzaError::try_from(elem).unwrap();
|
||||
assert_eq!(error.type_, ErrorType::Cancel);
|
||||
assert_eq!(error.defined_condition, DefinedCondition::Gone);
|
||||
assert_eq!(
|
||||
error.alternate_address,
|
||||
Some("xmpp:room@muc.example.org?join".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gone_without_new_address() {
|
||||
#[cfg(not(feature = "component"))]
|
||||
let elem: Element = "<error xmlns='jabber:client' type='cancel'><gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' /></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
#[cfg(feature = "component")]
|
||||
let elem: Element = "<error xmlns='jabber:component:accept' type='cancel'><gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' /></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
let error = StanzaError::try_from(elem).unwrap();
|
||||
assert_eq!(error.type_, ErrorType::Cancel);
|
||||
assert_eq!(error.defined_condition, DefinedCondition::Gone);
|
||||
assert_eq!(error.alternate_address, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_with_alternate_address() {
|
||||
#[cfg(not(feature = "component"))]
|
||||
let elem: Element = "<error xmlns='jabber:client' type='modify'><redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>xmpp:characters@conference.example.org</redirect></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
#[cfg(feature = "component")]
|
||||
let elem: Element = "<error xmlns='jabber:component:accept' type='modify'><redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>xmpp:characters@conference.example.org</redirect></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
let error = StanzaError::try_from(elem).unwrap();
|
||||
assert_eq!(error.type_, ErrorType::Modify);
|
||||
assert_eq!(error.defined_condition, DefinedCondition::Redirect);
|
||||
assert_eq!(
|
||||
error.alternate_address,
|
||||
Some("xmpp:characters@conference.example.org".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_without_alternate_address() {
|
||||
#[cfg(not(feature = "component"))]
|
||||
let elem: Element = "<error xmlns='jabber:client' type='modify'><redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' /></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
#[cfg(feature = "component")]
|
||||
let elem: Element = "<error xmlns='jabber:component:accept' type='modify'><redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' /></error>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
let error = StanzaError::try_from(elem).unwrap();
|
||||
assert_eq!(error.type_, ErrorType::Modify);
|
||||
assert_eq!(error.defined_condition, DefinedCondition::Redirect);
|
||||
assert_eq!(error.alternate_address, None);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue