1 /* 2 * libjingle 3 * Copyright 2011, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/xmpp/pubsubclient.h" 29 30 #include <string> 31 #include <vector> 32 33 #include "talk/xmpp/constants.h" 34 #include "talk/xmpp/jid.h" 35 #include "talk/xmpp/pubsubtasks.h" 36 37 namespace buzz { 38 39 void PubSubClient::RequestItems() { 40 PubSubRequestTask* request_task = 41 new PubSubRequestTask(parent_, pubsubjid_, node_); 42 request_task->SignalResult.connect(this, &PubSubClient::OnRequestResult); 43 request_task->SignalError.connect(this, &PubSubClient::OnRequestError); 44 45 PubSubReceiveTask* receive_task = 46 new PubSubReceiveTask(parent_, pubsubjid_, node_); 47 receive_task->SignalUpdate.connect(this, &PubSubClient::OnReceiveUpdate); 48 49 receive_task->Start(); 50 request_task->Start(); 51 } 52 53 void PubSubClient::PublishItem( 54 const std::string& itemid, XmlElement* payload, std::string* task_id_out) { 55 std::vector<XmlElement*> children; 56 children.push_back(payload); 57 PublishItem(itemid, children, task_id_out); 58 } 59 60 void PubSubClient::PublishItem( 61 const std::string& itemid, const std::vector<XmlElement*>& children, 62 std::string* task_id_out) { 63 PubSubPublishTask* publish_task = 64 new PubSubPublishTask(parent_, pubsubjid_, node_, itemid, children); 65 publish_task->SignalError.connect(this, &PubSubClient::OnPublishError); 66 publish_task->SignalResult.connect(this, &PubSubClient::OnPublishResult); 67 publish_task->Start(); 68 if (task_id_out) { 69 *task_id_out = publish_task->task_id(); 70 } 71 } 72 73 void PubSubClient::RetractItem( 74 const std::string& itemid, std::string* task_id_out) { 75 PubSubRetractTask* retract_task = 76 new PubSubRetractTask(parent_, pubsubjid_, node_, itemid); 77 retract_task->SignalError.connect(this, &PubSubClient::OnRetractError); 78 retract_task->SignalResult.connect(this, &PubSubClient::OnRetractResult); 79 retract_task->Start(); 80 if (task_id_out) { 81 *task_id_out = retract_task->task_id(); 82 } 83 } 84 85 void PubSubClient::OnRequestResult(PubSubRequestTask* task, 86 const std::vector<PubSubItem>& items) { 87 SignalItems(this, items); 88 } 89 90 void PubSubClient::OnRequestError(IqTask* task, 91 const XmlElement* stanza) { 92 SignalRequestError(this, stanza); 93 } 94 95 void PubSubClient::OnReceiveUpdate(PubSubReceiveTask* task, 96 const std::vector<PubSubItem>& items) { 97 SignalItems(this, items); 98 } 99 100 const XmlElement* GetItemFromStanza(const XmlElement* stanza) { 101 if (stanza != NULL) { 102 const XmlElement* pubsub = stanza->FirstNamed(QN_PUBSUB); 103 if (pubsub != NULL) { 104 const XmlElement* publish = pubsub->FirstNamed(QN_PUBSUB_PUBLISH); 105 if (publish != NULL) { 106 return publish->FirstNamed(QN_PUBSUB_ITEM); 107 } 108 } 109 } 110 return NULL; 111 } 112 113 void PubSubClient::OnPublishResult(PubSubPublishTask* task) { 114 const XmlElement* item = GetItemFromStanza(task->stanza()); 115 SignalPublishResult(this, task->task_id(), item); 116 } 117 118 void PubSubClient::OnPublishError(IqTask* task, 119 const XmlElement* error_stanza) { 120 PubSubPublishTask* publish_task = 121 static_cast<PubSubPublishTask*>(task); 122 const XmlElement* item = GetItemFromStanza(publish_task->stanza()); 123 SignalPublishError(this, publish_task->task_id(), item, error_stanza); 124 } 125 126 void PubSubClient::OnRetractResult(PubSubRetractTask* task) { 127 SignalRetractResult(this, task->task_id()); 128 } 129 130 void PubSubClient::OnRetractError(IqTask* task, 131 const XmlElement* stanza) { 132 PubSubRetractTask* retract_task = 133 static_cast<PubSubRetractTask*>(task); 134 SignalRetractError(this, retract_task->task_id(), stanza); 135 } 136 137 138 const std::string PubSubClient::GetPublisherNickFromPubSubItem( 139 const XmlElement* item_elem) { 140 if (item_elem == NULL) { 141 return ""; 142 } 143 144 return Jid(item_elem->Attr(QN_ATTR_PUBLISHER)).resource(); 145 } 146 } // namespace buzz 147