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/pubsubclient.h"
12
13#include <string>
14#include <vector>
15
16#include "webrtc/libjingle/xmpp/constants.h"
17#include "webrtc/libjingle/xmpp/jid.h"
18#include "webrtc/libjingle/xmpp/pubsubtasks.h"
19
20namespace buzz {
21
22void PubSubClient::RequestItems() {
23  PubSubRequestTask* request_task =
24      new PubSubRequestTask(parent_, pubsubjid_, node_);
25  request_task->SignalResult.connect(this, &PubSubClient::OnRequestResult);
26  request_task->SignalError.connect(this, &PubSubClient::OnRequestError);
27
28  PubSubReceiveTask* receive_task =
29      new PubSubReceiveTask(parent_, pubsubjid_, node_);
30  receive_task->SignalUpdate.connect(this, &PubSubClient::OnReceiveUpdate);
31
32  receive_task->Start();
33  request_task->Start();
34}
35
36void PubSubClient::PublishItem(
37    const std::string& itemid, XmlElement* payload, std::string* task_id_out) {
38  std::vector<XmlElement*> children;
39  children.push_back(payload);
40  PublishItem(itemid, children, task_id_out);
41}
42
43void PubSubClient::PublishItem(
44    const std::string& itemid, const std::vector<XmlElement*>& children,
45    std::string* task_id_out) {
46  PubSubPublishTask* publish_task =
47      new PubSubPublishTask(parent_, pubsubjid_, node_, itemid, children);
48  publish_task->SignalError.connect(this, &PubSubClient::OnPublishError);
49  publish_task->SignalResult.connect(this, &PubSubClient::OnPublishResult);
50  publish_task->Start();
51  if (task_id_out) {
52    *task_id_out = publish_task->task_id();
53  }
54}
55
56void PubSubClient::RetractItem(
57    const std::string& itemid, std::string* task_id_out) {
58  PubSubRetractTask* retract_task =
59      new PubSubRetractTask(parent_, pubsubjid_, node_, itemid);
60  retract_task->SignalError.connect(this, &PubSubClient::OnRetractError);
61  retract_task->SignalResult.connect(this, &PubSubClient::OnRetractResult);
62  retract_task->Start();
63  if (task_id_out) {
64    *task_id_out = retract_task->task_id();
65  }
66}
67
68void PubSubClient::OnRequestResult(PubSubRequestTask* task,
69                                   const std::vector<PubSubItem>& items) {
70  SignalItems(this, items);
71}
72
73void PubSubClient::OnRequestError(IqTask* task,
74                                  const XmlElement* stanza) {
75  SignalRequestError(this, stanza);
76}
77
78void PubSubClient::OnReceiveUpdate(PubSubReceiveTask* task,
79                                   const std::vector<PubSubItem>& items) {
80  SignalItems(this, items);
81}
82
83const XmlElement* GetItemFromStanza(const XmlElement* stanza) {
84  if (stanza != NULL) {
85    const XmlElement* pubsub = stanza->FirstNamed(QN_PUBSUB);
86    if (pubsub != NULL) {
87      const XmlElement* publish = pubsub->FirstNamed(QN_PUBSUB_PUBLISH);
88      if (publish != NULL) {
89        return publish->FirstNamed(QN_PUBSUB_ITEM);
90      }
91    }
92  }
93  return NULL;
94}
95
96void PubSubClient::OnPublishResult(PubSubPublishTask* task) {
97  const XmlElement* item = GetItemFromStanza(task->stanza());
98  SignalPublishResult(this, task->task_id(), item);
99}
100
101void PubSubClient::OnPublishError(IqTask* task,
102                                  const XmlElement* error_stanza) {
103  PubSubPublishTask* publish_task =
104      static_cast<PubSubPublishTask*>(task);
105  const XmlElement* item = GetItemFromStanza(publish_task->stanza());
106  SignalPublishError(this, publish_task->task_id(), item, error_stanza);
107}
108
109void PubSubClient::OnRetractResult(PubSubRetractTask* task) {
110  SignalRetractResult(this, task->task_id());
111}
112
113void PubSubClient::OnRetractError(IqTask* task,
114                                  const XmlElement* stanza) {
115  PubSubRetractTask* retract_task =
116      static_cast<PubSubRetractTask*>(task);
117  SignalRetractError(this, retract_task->task_id(), stanza);
118}
119
120
121const std::string PubSubClient::GetPublisherNickFromPubSubItem(
122    const XmlElement* item_elem) {
123  if (item_elem == NULL) {
124    return "";
125  }
126
127  return Jid(item_elem->Attr(QN_ATTR_PUBLISHER)).resource();
128}
129}  // namespace buzz
130