1// Copyright (c) 2018 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 stanza_error::DefinedCondition;
8
9generate_element!(
10 /// Acknowledgement of the currently received stanzas.
11 A, "a", SM,
12 attributes: [
13 /// The last handled stanza.
14 h: u32 = "h" => required,
15 ]
16);
17
18impl A {
19 /// Generates a new `<a/>` element.
20 pub fn new(h: u32) -> A {
21 A { h }
22 }
23}
24
25generate_attribute!(
26 /// Whether to allow resumption of a previous stream.
27 ResumeAttr, "resume", bool
28);
29
30generate_element!(
31 /// Client request for enabling stream management.
32 Enable, "enable", SM,
33 attributes: [
34 /// The preferred resumption time in seconds by the client.
35 // TODO: should be the infinite integer set ≥ 1.
36 max: Option<u32> = "max" => optional,
37
38 /// Whether the client wants to be allowed to resume the stream.
39 resume: ResumeAttr = "resume" => default,
40 ]
41);
42
43impl Enable {
44 /// Generates a new `<enable/>` element.
45 pub fn new() -> Self {
46 Enable {
47 max: None,
48 resume: ResumeAttr::False,
49 }
50 }
51
52 /// Sets the preferred resumption time in seconds.
53 pub fn with_max(mut self, max: u32) -> Self {
54 self.max = Some(max);
55 self
56 }
57
58 /// Asks for resumption to be possible.
59 pub fn with_resume(mut self) -> Self {
60 self.resume = ResumeAttr::True;
61 self
62 }
63}
64
65generate_id!(
66 /// A random identifier used for stream resumption.
67 StreamId
68);
69
70generate_element!(
71 /// Server response once stream management is enabled.
72 Enabled, "enabled", SM,
73 attributes: [
74 /// A random identifier used for stream resumption.
75 id: Option<StreamId> = "id" => optional,
76
77 /// The preferred IP, domain, IP:port or domain:port location for
78 /// resumption.
79 location: Option<String> = "location" => optional,
80
81 /// The preferred resumption time in seconds by the server.
82 // TODO: should be the infinite integer set ≥ 1.
83 max: Option<u32> = "max" => optional,
84
85 /// Whether stream resumption is allowed.
86 resume: ResumeAttr = "resume" => default,
87 ]
88);
89
90generate_element!(
91 /// A stream management error happened.
92 Failed, "failed", SM,
93 attributes: [
94 /// The last handled stanza.
95 h: Option<u32> = "h" => optional,
96 ],
97 children: [
98 /// The error returned.
99 // XXX: implement the * handling.
100 error: Option<DefinedCondition> = ("*", XMPP_STANZAS) => DefinedCondition
101 ]
102);
103
104generate_empty_element!(
105 /// Requests the currently received stanzas by the other party.
106 R, "r", SM
107);
108
109generate_element!(
110 /// Requests a stream resumption.
111 Resume, "resume", SM,
112 attributes: [
113 /// The last handled stanza.
114 h: u32 = "h" => required,
115
116 /// The previous id given by the server on
117 /// [enabled](struct.Enabled.html).
118 previd: StreamId = "previd" => required,
119 ]
120);
121
122generate_element!(
123 /// The response by the server for a successfully resumed stream.
124 Resumed, "resumed", SM,
125 attributes: [
126 /// The last handled stanza.
127 h: u32 = "h" => required,
128
129 /// The previous id given by the server on
130 /// [enabled](struct.Enabled.html).
131 previd: StreamId = "previd" => required,
132 ]
133);
134
135// TODO: add support for optional and required.
136generate_empty_element!(
137 /// Represents availability of Stream Management in `<stream:features/>`.
138 StreamManagement, "sm", SM
139);
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use try_from::TryFrom;
145 use minidom::Element;
146
147 #[test]
148 fn test_size() {
149 assert_size!(A, 4);
150 assert_size!(ResumeAttr, 1);
151 assert_size!(Enable, 12);
152 assert_size!(StreamId, 24);
153 assert_size!(Enabled, 64);
154 assert_size!(Failed, 12);
155 assert_size!(R, 0);
156 assert_size!(Resume, 32);
157 assert_size!(Resumed, 32);
158 assert_size!(StreamManagement, 0);
159 }
160
161 #[test]
162 fn a() {
163 let elem: Element = "<a xmlns='urn:xmpp:sm:3' h='5'".parse().unwrap();
164 let a = A::try_from(elem).unwrap();
165 assert_eq!(a.h, 5);
166 }
167
168 #[test]
169 fn stream_feature() {
170 let elem: Element = "<sm xmlns='urn:xmpp:sm:3'/>".parse().unwrap();
171 StreamManagement::try_from(elem).unwrap();
172 }
173
174 #[test]
175 fn resume() {
176 let elem: Element = "<enable xmlns='urn:xmpp:sm:3' resume='true'/>".parse().unwrap();
177 let enable = Enable::try_from(elem).unwrap();
178 assert_eq!(enable.max, None);
179 assert_eq!(enable.resume, ResumeAttr::True);
180
181 let elem: Element = "<enabled xmlns='urn:xmpp:sm:3' resume='true' id='coucou' max='600'/>".parse().unwrap();
182 let enabled = Enabled::try_from(elem).unwrap();
183 let previd = enabled.id.unwrap();
184 assert_eq!(enabled.resume, ResumeAttr::True);
185 assert_eq!(previd, StreamId(String::from("coucou")));
186 assert_eq!(enabled.max, Some(600));
187 assert_eq!(enabled.location, None);
188
189 let elem: Element = "<resume xmlns='urn:xmpp:sm:3' h='5' previd='coucou'/>".parse().unwrap();
190 let resume = Resume::try_from(elem).unwrap();
191 assert_eq!(resume.h, 5);
192 assert_eq!(resume.previd, previd);
193
194 let elem: Element = "<resumed xmlns='urn:xmpp:sm:3' h='5' previd='coucou'/>".parse().unwrap();
195 let resumed = Resumed::try_from(elem).unwrap();
196 assert_eq!(resumed.h, 5);
197 assert_eq!(resumed.previd, previd);
198 }
199}