OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/libjingle/xmpp/pubsubtasks.h" | |
12 | |
13 #include <string> | |
14 #include <vector> | |
15 | |
16 #include "webrtc/libjingle/xmpp/constants.h" | |
17 #include "webrtc/libjingle/xmpp/receivetask.h" | |
18 | |
19 // An implementation of the tasks for XEP-0060 | |
20 // (http://xmpp.org/extensions/xep-0060.html). | |
21 | |
22 namespace buzz { | |
23 | |
24 namespace { | |
25 | |
26 bool IsPubSubEventItemsElem(const XmlElement* stanza, | |
27 const std::string& expected_node) { | |
28 if (stanza->Name() != QN_MESSAGE) { | |
29 return false; | |
30 } | |
31 | |
32 const XmlElement* event_elem = stanza->FirstNamed(QN_PUBSUB_EVENT); | |
33 if (event_elem == NULL) { | |
34 return false; | |
35 } | |
36 | |
37 const XmlElement* items_elem = event_elem->FirstNamed(QN_PUBSUB_EVENT_ITEMS); | |
38 if (items_elem == NULL) { | |
39 return false; | |
40 } | |
41 | |
42 const std::string& actual_node = items_elem->Attr(QN_NODE); | |
43 return (actual_node == expected_node); | |
44 } | |
45 | |
46 | |
47 // Creates <pubsub node="node"><items></pubsub> | |
48 XmlElement* CreatePubSubItemsElem(const std::string& node) { | |
49 XmlElement* items_elem = new XmlElement(QN_PUBSUB_ITEMS, false); | |
50 items_elem->AddAttr(QN_NODE, node); | |
51 XmlElement* pubsub_elem = new XmlElement(QN_PUBSUB, false); | |
52 pubsub_elem->AddElement(items_elem); | |
53 return pubsub_elem; | |
54 } | |
55 | |
56 // Creates <pubsub node="node"><publish><item id="itemid">payload</item>... | |
57 // Takes ownership of payload. | |
58 XmlElement* CreatePubSubPublishItemElem( | |
59 const std::string& node, | |
60 const std::string& itemid, | |
61 const std::vector<XmlElement*>& children) { | |
62 XmlElement* pubsub_elem = new XmlElement(QN_PUBSUB, true); | |
63 XmlElement* publish_elem = new XmlElement(QN_PUBSUB_PUBLISH, false); | |
64 publish_elem->AddAttr(QN_NODE, node); | |
65 XmlElement* item_elem = new XmlElement(QN_PUBSUB_ITEM, false); | |
66 item_elem->AddAttr(QN_ID, itemid); | |
67 for (std::vector<XmlElement*>::const_iterator child = children.begin(); | |
68 child != children.end(); ++child) { | |
69 item_elem->AddElement(*child); | |
70 } | |
71 publish_elem->AddElement(item_elem); | |
72 pubsub_elem->AddElement(publish_elem); | |
73 return pubsub_elem; | |
74 } | |
75 | |
76 // Creates <pubsub node="node"><publish><item id="itemid">payload</item>... | |
77 // Takes ownership of payload. | |
78 XmlElement* CreatePubSubRetractItemElem(const std::string& node, | |
79 const std::string& itemid) { | |
80 XmlElement* pubsub_elem = new XmlElement(QN_PUBSUB, true); | |
81 XmlElement* retract_elem = new XmlElement(QN_PUBSUB_RETRACT, false); | |
82 retract_elem->AddAttr(QN_NODE, node); | |
83 retract_elem->AddAttr(QN_NOTIFY, "true"); | |
84 XmlElement* item_elem = new XmlElement(QN_PUBSUB_ITEM, false); | |
85 item_elem->AddAttr(QN_ID, itemid); | |
86 retract_elem->AddElement(item_elem); | |
87 pubsub_elem->AddElement(retract_elem); | |
88 return pubsub_elem; | |
89 } | |
90 | |
91 void ParseItem(const XmlElement* item_elem, | |
92 std::vector<PubSubItem>* items) { | |
93 PubSubItem item; | |
94 item.itemid = item_elem->Attr(QN_ID); | |
95 item.elem = item_elem; | |
96 items->push_back(item); | |
97 } | |
98 | |
99 // Right now, <retract>s are treated the same as items with empty | |
100 // payloads. We may want to change it in the future, but right now | |
101 // it's sufficient for our needs. | |
102 void ParseRetract(const XmlElement* retract_elem, | |
103 std::vector<PubSubItem>* items) { | |
104 ParseItem(retract_elem, items); | |
105 } | |
106 | |
107 void ParseEventItemsElem(const XmlElement* stanza, | |
108 std::vector<PubSubItem>* items) { | |
109 const XmlElement* event_elem = stanza->FirstNamed(QN_PUBSUB_EVENT); | |
110 if (event_elem != NULL) { | |
111 const XmlElement* items_elem = | |
112 event_elem->FirstNamed(QN_PUBSUB_EVENT_ITEMS); | |
113 if (items_elem != NULL) { | |
114 for (const XmlElement* item_elem = | |
115 items_elem->FirstNamed(QN_PUBSUB_EVENT_ITEM); | |
116 item_elem != NULL; | |
117 item_elem = item_elem->NextNamed(QN_PUBSUB_EVENT_ITEM)) { | |
118 ParseItem(item_elem, items); | |
119 } | |
120 for (const XmlElement* retract_elem = | |
121 items_elem->FirstNamed(QN_PUBSUB_EVENT_RETRACT); | |
122 retract_elem != NULL; | |
123 retract_elem = retract_elem->NextNamed(QN_PUBSUB_EVENT_RETRACT)) { | |
124 ParseRetract(retract_elem, items); | |
125 } | |
126 } | |
127 } | |
128 } | |
129 | |
130 void ParsePubSubItemsElem(const XmlElement* stanza, | |
131 std::vector<PubSubItem>* items) { | |
132 const XmlElement* pubsub_elem = stanza->FirstNamed(QN_PUBSUB); | |
133 if (pubsub_elem != NULL) { | |
134 const XmlElement* items_elem = pubsub_elem->FirstNamed(QN_PUBSUB_ITEMS); | |
135 if (items_elem != NULL) { | |
136 for (const XmlElement* item_elem = items_elem->FirstNamed(QN_PUBSUB_ITEM); | |
137 item_elem != NULL; | |
138 item_elem = item_elem->NextNamed(QN_PUBSUB_ITEM)) { | |
139 ParseItem(item_elem, items); | |
140 } | |
141 } | |
142 } | |
143 } | |
144 | |
145 } // namespace | |
146 | |
147 PubSubRequestTask::PubSubRequestTask(XmppTaskParentInterface* parent, | |
148 const Jid& pubsubjid, | |
149 const std::string& node) | |
150 : IqTask(parent, STR_GET, pubsubjid, CreatePubSubItemsElem(node)) { | |
151 } | |
152 | |
153 void PubSubRequestTask::HandleResult(const XmlElement* stanza) { | |
154 std::vector<PubSubItem> items; | |
155 ParsePubSubItemsElem(stanza, &items); | |
156 SignalResult(this, items); | |
157 } | |
158 | |
159 int PubSubReceiveTask::ProcessStart() { | |
160 if (SignalUpdate.is_empty()) { | |
161 return STATE_DONE; | |
162 } | |
163 return ReceiveTask::ProcessStart(); | |
164 } | |
165 | |
166 bool PubSubReceiveTask::WantsStanza(const XmlElement* stanza) { | |
167 return MatchStanzaFrom(stanza, pubsubjid_) && | |
168 IsPubSubEventItemsElem(stanza, node_) && !SignalUpdate.is_empty(); | |
169 } | |
170 | |
171 void PubSubReceiveTask::ReceiveStanza(const XmlElement* stanza) { | |
172 std::vector<PubSubItem> items; | |
173 ParseEventItemsElem(stanza, &items); | |
174 SignalUpdate(this, items); | |
175 } | |
176 | |
177 PubSubPublishTask::PubSubPublishTask(XmppTaskParentInterface* parent, | |
178 const Jid& pubsubjid, | |
179 const std::string& node, | |
180 const std::string& itemid, | |
181 const std::vector<XmlElement*>& children) | |
182 : IqTask(parent, STR_SET, pubsubjid, | |
183 CreatePubSubPublishItemElem(node, itemid, children)), | |
184 itemid_(itemid) { | |
185 } | |
186 | |
187 void PubSubPublishTask::HandleResult(const XmlElement* stanza) { | |
188 SignalResult(this); | |
189 } | |
190 | |
191 PubSubRetractTask::PubSubRetractTask(XmppTaskParentInterface* parent, | |
192 const Jid& pubsubjid, | |
193 const std::string& node, | |
194 const std::string& itemid) | |
195 : IqTask(parent, STR_SET, pubsubjid, | |
196 CreatePubSubRetractItemElem(node, itemid)), | |
197 itemid_(itemid) { | |
198 } | |
199 | |
200 void PubSubRetractTask::HandleResult(const XmlElement* stanza) { | |
201 SignalResult(this); | |
202 } | |
203 | |
204 } // namespace buzz | |
OLD | NEW |