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 |