| Index: webrtc/libjingle/xmpp/rostermoduleimpl.cc
|
| diff --git a/webrtc/libjingle/xmpp/rostermoduleimpl.cc b/webrtc/libjingle/xmpp/rostermoduleimpl.cc
|
| deleted file mode 100644
|
| index b9752896efad84b0d4970be44f3e125b4260b452..0000000000000000000000000000000000000000
|
| --- a/webrtc/libjingle/xmpp/rostermoduleimpl.cc
|
| +++ /dev/null
|
| @@ -1,1064 +0,0 @@
|
| -/*
|
| - * Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include <algorithm>
|
| -#include <iostream>
|
| -#include <map>
|
| -#include <sstream>
|
| -#include <string>
|
| -#include <vector>
|
| -#include "webrtc/libjingle/xmpp/constants.h"
|
| -#include "webrtc/libjingle/xmpp/rostermoduleimpl.h"
|
| -#include "webrtc/base/common.h"
|
| -#include "webrtc/base/stringencode.h"
|
| -
|
| -namespace buzz {
|
| -
|
| -// enum prase and persist helpers ----------------------------------------------
|
| -static bool
|
| -StringToPresenceShow(const std::string& input, XmppPresenceShow* show) {
|
| - // If this becomes a perf issue we can use a hash or a map here
|
| - if (STR_SHOW_AWAY == input)
|
| - *show = XMPP_PRESENCE_AWAY;
|
| - else if (STR_SHOW_DND == input)
|
| - *show = XMPP_PRESENCE_DND;
|
| - else if (STR_SHOW_XA == input)
|
| - *show = XMPP_PRESENCE_XA;
|
| - else if (STR_SHOW_CHAT == input)
|
| - *show = XMPP_PRESENCE_CHAT;
|
| - else if (STR_EMPTY == input)
|
| - *show = XMPP_PRESENCE_DEFAULT;
|
| - else
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -static bool
|
| -PresenceShowToString(XmppPresenceShow show, const char** output) {
|
| - switch(show) {
|
| - case XMPP_PRESENCE_AWAY:
|
| - *output = STR_SHOW_AWAY;
|
| - return true;
|
| - case XMPP_PRESENCE_CHAT:
|
| - *output = STR_SHOW_CHAT;
|
| - return true;
|
| - case XMPP_PRESENCE_XA:
|
| - *output = STR_SHOW_XA;
|
| - return true;
|
| - case XMPP_PRESENCE_DND:
|
| - *output = STR_SHOW_DND;
|
| - return true;
|
| - case XMPP_PRESENCE_DEFAULT:
|
| - *output = STR_EMPTY;
|
| - return true;
|
| - }
|
| -
|
| - *output = STR_EMPTY;
|
| - return false;
|
| -}
|
| -
|
| -static bool
|
| -StringToSubscriptionState(const std::string& subscription,
|
| - const std::string& ask,
|
| - XmppSubscriptionState* state)
|
| -{
|
| - if (ask == "subscribe")
|
| - {
|
| - if (subscription == "none") {
|
| - *state = XMPP_SUBSCRIPTION_NONE_ASKED;
|
| - return true;
|
| - }
|
| - if (subscription == "from") {
|
| - *state = XMPP_SUBSCRIPTION_FROM_ASKED;
|
| - return true;
|
| - }
|
| - } else if (ask == STR_EMPTY)
|
| - {
|
| - if (subscription == "none") {
|
| - *state = XMPP_SUBSCRIPTION_NONE;
|
| - return true;
|
| - }
|
| - if (subscription == "from") {
|
| - *state = XMPP_SUBSCRIPTION_FROM;
|
| - return true;
|
| - }
|
| - if (subscription == "to") {
|
| - *state = XMPP_SUBSCRIPTION_TO;
|
| - return true;
|
| - }
|
| - if (subscription == "both") {
|
| - *state = XMPP_SUBSCRIPTION_BOTH;
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -static bool
|
| -StringToSubscriptionRequestType(const std::string& string,
|
| - XmppSubscriptionRequestType* type)
|
| -{
|
| - if (string == "subscribe")
|
| - *type = XMPP_REQUEST_SUBSCRIBE;
|
| - else if (string == "unsubscribe")
|
| - *type = XMPP_REQUEST_UNSUBSCRIBE;
|
| - else if (string == "subscribed")
|
| - *type = XMPP_REQUEST_SUBSCRIBED;
|
| - else if (string == "unsubscribed")
|
| - *type = XMPP_REQUEST_UNSUBSCRIBED;
|
| - else
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -// XmppPresenceImpl class ------------------------------------------------------
|
| -XmppPresence*
|
| -XmppPresence::Create() {
|
| - return new XmppPresenceImpl();
|
| -}
|
| -
|
| -XmppPresenceImpl::XmppPresenceImpl() {
|
| -}
|
| -
|
| -const Jid
|
| -XmppPresenceImpl::jid() const {
|
| - if (!raw_xml_)
|
| - return Jid();
|
| -
|
| - return Jid(raw_xml_->Attr(QN_FROM));
|
| -}
|
| -
|
| -XmppPresenceAvailable
|
| -XmppPresenceImpl::available() const {
|
| - if (!raw_xml_)
|
| - return XMPP_PRESENCE_UNAVAILABLE;
|
| -
|
| - if (raw_xml_->Attr(QN_TYPE) == "unavailable")
|
| - return XMPP_PRESENCE_UNAVAILABLE;
|
| - else if (raw_xml_->Attr(QN_TYPE) == "error")
|
| - return XMPP_PRESENCE_ERROR;
|
| - else
|
| - return XMPP_PRESENCE_AVAILABLE;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppPresenceImpl::set_available(XmppPresenceAvailable available) {
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - if (available == XMPP_PRESENCE_AVAILABLE)
|
| - raw_xml_->ClearAttr(QN_TYPE);
|
| - else if (available == XMPP_PRESENCE_UNAVAILABLE)
|
| - raw_xml_->SetAttr(QN_TYPE, "unavailable");
|
| - else if (available == XMPP_PRESENCE_ERROR)
|
| - raw_xml_->SetAttr(QN_TYPE, "error");
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -XmppPresenceShow
|
| -XmppPresenceImpl::presence_show() const {
|
| - if (!raw_xml_)
|
| - return XMPP_PRESENCE_DEFAULT;
|
| -
|
| - XmppPresenceShow show = XMPP_PRESENCE_DEFAULT;
|
| - StringToPresenceShow(raw_xml_->TextNamed(QN_SHOW), &show);
|
| - return show;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppPresenceImpl::set_presence_show(XmppPresenceShow show) {
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - const char* show_string;
|
| -
|
| - if(!PresenceShowToString(show, &show_string))
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - raw_xml_->ClearNamedChildren(QN_SHOW);
|
| -
|
| - if (show!=XMPP_PRESENCE_DEFAULT) {
|
| - raw_xml_->AddElement(new XmlElement(QN_SHOW));
|
| - raw_xml_->AddText(show_string, 1);
|
| - }
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -int
|
| -XmppPresenceImpl::priority() const {
|
| - if (!raw_xml_)
|
| - return 0;
|
| -
|
| - int raw_priority = 0;
|
| - if (!rtc::FromString(raw_xml_->TextNamed(QN_PRIORITY), &raw_priority))
|
| - raw_priority = 0;
|
| - if (raw_priority < -128)
|
| - raw_priority = -128;
|
| - if (raw_priority > 127)
|
| - raw_priority = 127;
|
| -
|
| - return raw_priority;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppPresenceImpl::set_priority(int priority) {
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - if (priority < -128 || priority > 127)
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - raw_xml_->ClearNamedChildren(QN_PRIORITY);
|
| - if (0 != priority) {
|
| - std::string priority_string;
|
| - if (rtc::ToString(priority, &priority_string)) {
|
| - raw_xml_->AddElement(new XmlElement(QN_PRIORITY));
|
| - raw_xml_->AddText(priority_string, 1);
|
| - }
|
| - }
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -const std::string
|
| -XmppPresenceImpl::status() const {
|
| - if (!raw_xml_)
|
| - return STR_EMPTY;
|
| -
|
| - XmlElement* status_element;
|
| - XmlElement* element;
|
| -
|
| - // Search for a status element with no xml:lang attribute on it. if we can't
|
| - // find that then just return the first status element in the stanza.
|
| - for (status_element = element = raw_xml_->FirstNamed(QN_STATUS);
|
| - element;
|
| - element = element->NextNamed(QN_STATUS)) {
|
| - if (!element->HasAttr(QN_XML_LANG)) {
|
| - status_element = element;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (status_element) {
|
| - return status_element->BodyText();
|
| - }
|
| -
|
| - return STR_EMPTY;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppPresenceImpl::set_status(const std::string& status) {
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - raw_xml_->ClearNamedChildren(QN_STATUS);
|
| -
|
| - if (status != STR_EMPTY) {
|
| - raw_xml_->AddElement(new XmlElement(QN_STATUS));
|
| - raw_xml_->AddText(status, 1);
|
| - }
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -XmppPresenceConnectionStatus
|
| -XmppPresenceImpl::connection_status() const {
|
| - if (!raw_xml_)
|
| - return XMPP_CONNECTION_STATUS_UNKNOWN;
|
| -
|
| - XmlElement* con = raw_xml_->FirstNamed(QN_GOOGLE_PSTN_CONFERENCE_STATUS);
|
| - if (con) {
|
| - std::string status = con->Attr(QN_ATTR_STATUS);
|
| - if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTING)
|
| - return XMPP_CONNECTION_STATUS_CONNECTING;
|
| - else if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTED)
|
| - return XMPP_CONNECTION_STATUS_CONNECTED;
|
| - else if (status == STR_PSTN_CONFERENCE_STATUS_JOINING)
|
| - return XMPP_CONNECTION_STATUS_JOINING;
|
| - else if (status == STR_PSTN_CONFERENCE_STATUS_HANGUP)
|
| - return XMPP_CONNECTION_STATUS_HANGUP;
|
| - }
|
| -
|
| - return XMPP_CONNECTION_STATUS_CONNECTED;
|
| -}
|
| -
|
| -const std::string
|
| -XmppPresenceImpl::google_user_id() const {
|
| - if (!raw_xml_)
|
| - return std::string();
|
| -
|
| - XmlElement* muc_user_x = raw_xml_->FirstNamed(QN_MUC_USER_X);
|
| - if (muc_user_x) {
|
| - XmlElement* muc_user_item = muc_user_x->FirstNamed(QN_MUC_USER_ITEM);
|
| - if (muc_user_item) {
|
| - return muc_user_item->Attr(QN_GOOGLE_USER_ID);
|
| - }
|
| - }
|
| -
|
| - return std::string();
|
| -}
|
| -
|
| -const std::string
|
| -XmppPresenceImpl::nickname() const {
|
| - if (!raw_xml_)
|
| - return std::string();
|
| -
|
| - XmlElement* nickname = raw_xml_->FirstNamed(QN_NICKNAME);
|
| - if (nickname) {
|
| - return nickname->BodyText();
|
| - }
|
| -
|
| - return std::string();
|
| -}
|
| -
|
| -const XmlElement*
|
| -XmppPresenceImpl::raw_xml() const {
|
| - if (!raw_xml_)
|
| - const_cast<XmppPresenceImpl*>(this)->CreateRawXmlSkeleton();
|
| - return raw_xml_.get();
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppPresenceImpl::set_raw_xml(const XmlElement * xml) {
|
| - if (!xml ||
|
| - xml->Name() != QN_PRESENCE)
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - raw_xml_.reset(new XmlElement(*xml));
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -void
|
| -XmppPresenceImpl::CreateRawXmlSkeleton() {
|
| - raw_xml_.reset(new XmlElement(QN_PRESENCE));
|
| -}
|
| -
|
| -// XmppRosterContactImpl -------------------------------------------------------
|
| -XmppRosterContact*
|
| -XmppRosterContact::Create() {
|
| - return new XmppRosterContactImpl();
|
| -}
|
| -
|
| -XmppRosterContactImpl::XmppRosterContactImpl() {
|
| - ResetGroupCache();
|
| -}
|
| -
|
| -void
|
| -XmppRosterContactImpl::SetXmlFromWire(const XmlElement* xml) {
|
| - ResetGroupCache();
|
| - if (xml)
|
| - raw_xml_.reset(new XmlElement(*xml));
|
| - else
|
| - raw_xml_.reset(NULL);
|
| -}
|
| -
|
| -void
|
| -XmppRosterContactImpl::ResetGroupCache() {
|
| - group_count_ = -1;
|
| - group_index_returned_ = -1;
|
| - group_returned_ = NULL;
|
| -}
|
| -
|
| -const Jid
|
| -XmppRosterContactImpl::jid() const {
|
| - return Jid(raw_xml_->Attr(QN_JID));
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterContactImpl::set_jid(const Jid& jid)
|
| -{
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - if (!jid.IsValid())
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - raw_xml_->SetAttr(QN_JID, jid.Str());
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -const std::string
|
| -XmppRosterContactImpl::name() const {
|
| - return raw_xml_->Attr(QN_NAME);
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterContactImpl::set_name(const std::string& name) {
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - if (name == STR_EMPTY)
|
| - raw_xml_->ClearAttr(QN_NAME);
|
| - else
|
| - raw_xml_->SetAttr(QN_NAME, name);
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -XmppSubscriptionState
|
| -XmppRosterContactImpl::subscription_state() const {
|
| - if (!raw_xml_)
|
| - return XMPP_SUBSCRIPTION_NONE;
|
| -
|
| - XmppSubscriptionState state = XMPP_SUBSCRIPTION_NONE;
|
| -
|
| - if (StringToSubscriptionState(raw_xml_->Attr(QN_SUBSCRIPTION),
|
| - raw_xml_->Attr(QN_ASK),
|
| - &state))
|
| - return state;
|
| -
|
| - return XMPP_SUBSCRIPTION_NONE;
|
| -}
|
| -
|
| -size_t
|
| -XmppRosterContactImpl::GetGroupCount() const {
|
| - if (!raw_xml_)
|
| - return 0;
|
| -
|
| - if (-1 == group_count_) {
|
| - XmlElement *group_element = raw_xml_->FirstNamed(QN_ROSTER_GROUP);
|
| - int group_count = 0;
|
| - while(group_element) {
|
| - group_count++;
|
| - group_element = group_element->NextNamed(QN_ROSTER_GROUP);
|
| - }
|
| -
|
| - ASSERT(group_count > 0); // protect the cast
|
| - XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
|
| - me->group_count_ = group_count;
|
| - }
|
| -
|
| - return group_count_;
|
| -}
|
| -
|
| -const std::string
|
| -XmppRosterContactImpl::GetGroup(size_t index) const {
|
| - if (index >= GetGroupCount())
|
| - return STR_EMPTY;
|
| -
|
| - // We cache the last group index and element that we returned. This way
|
| - // going through the groups in order is order n and not n^2. This could be
|
| - // enhanced if necessary by starting at the cached value if the index asked
|
| - // is after the cached one.
|
| - if (group_index_returned_ >= 0 &&
|
| - index == static_cast<size_t>(group_index_returned_) + 1)
|
| - {
|
| - XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
|
| - me->group_returned_ = group_returned_->NextNamed(QN_ROSTER_GROUP);
|
| - ASSERT(group_returned_ != NULL);
|
| - me->group_index_returned_++;
|
| - } else if (group_index_returned_ < 0 ||
|
| - static_cast<size_t>(group_index_returned_) != index) {
|
| - XmlElement * group_element = raw_xml_->FirstNamed(QN_ROSTER_GROUP);
|
| - size_t group_index = 0;
|
| - while(group_index < index) {
|
| - ASSERT(group_element != NULL);
|
| - group_index++;
|
| - group_element = group_element->NextNamed(QN_ROSTER_GROUP);
|
| - }
|
| -
|
| - XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
|
| - me->group_index_returned_ = static_cast<int>(group_index);
|
| - me->group_returned_ = group_element;
|
| - }
|
| -
|
| - return group_returned_->BodyText();
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterContactImpl::AddGroup(const std::string& group) {
|
| - if (group == STR_EMPTY)
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (!raw_xml_)
|
| - CreateRawXmlSkeleton();
|
| -
|
| - if (FindGroup(group, NULL, NULL))
|
| - return XMPP_RETURN_OK;
|
| -
|
| - raw_xml_->AddElement(new XmlElement(QN_ROSTER_GROUP));
|
| - raw_xml_->AddText(group, 1);
|
| - ++group_count_;
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterContactImpl::RemoveGroup(const std::string& group) {
|
| - if (group == STR_EMPTY)
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (!raw_xml_)
|
| - return XMPP_RETURN_OK;
|
| -
|
| - XmlChild * child_before;
|
| - if (FindGroup(group, NULL, &child_before)) {
|
| - raw_xml_->RemoveChildAfter(child_before);
|
| - ResetGroupCache();
|
| - }
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -bool
|
| -XmppRosterContactImpl::FindGroup(const std::string& group,
|
| - XmlElement** element,
|
| - XmlChild** child_before) {
|
| - XmlChild * prev_child = NULL;
|
| - XmlChild * next_child;
|
| - XmlChild * child;
|
| - for (child = raw_xml_->FirstChild(); child; child = next_child) {
|
| - next_child = child->NextChild();
|
| - if (!child->IsText() &&
|
| - child->AsElement()->Name() == QN_ROSTER_GROUP &&
|
| - child->AsElement()->BodyText() == group) {
|
| - if (element)
|
| - *element = child->AsElement();
|
| - if (child_before)
|
| - *child_before = prev_child;
|
| - return true;
|
| - }
|
| - prev_child = child;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -const XmlElement*
|
| -XmppRosterContactImpl::raw_xml() const {
|
| - if (!raw_xml_)
|
| - const_cast<XmppRosterContactImpl*>(this)->CreateRawXmlSkeleton();
|
| - return raw_xml_.get();
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterContactImpl::set_raw_xml(const XmlElement* xml) {
|
| - if (!xml ||
|
| - xml->Name() != QN_ROSTER_ITEM ||
|
| - xml->HasAttr(QN_SUBSCRIPTION) ||
|
| - xml->HasAttr(QN_ASK))
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - ResetGroupCache();
|
| -
|
| - raw_xml_.reset(new XmlElement(*xml));
|
| -
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -void
|
| -XmppRosterContactImpl::CreateRawXmlSkeleton() {
|
| - raw_xml_.reset(new XmlElement(QN_ROSTER_ITEM));
|
| -}
|
| -
|
| -// XmppRosterModuleImpl --------------------------------------------------------
|
| -XmppRosterModule *
|
| -XmppRosterModule::Create() {
|
| - return new XmppRosterModuleImpl();
|
| -}
|
| -
|
| -XmppRosterModuleImpl::XmppRosterModuleImpl() :
|
| - roster_handler_(NULL),
|
| - incoming_presence_map_(new JidPresenceVectorMap()),
|
| - incoming_presence_vector_(new PresenceVector()),
|
| - contacts_(new ContactVector()) {
|
| -
|
| -}
|
| -
|
| -XmppRosterModuleImpl::~XmppRosterModuleImpl() {
|
| - DeleteIncomingPresence();
|
| - DeleteContacts();
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::set_roster_handler(XmppRosterHandler * handler) {
|
| - roster_handler_ = handler;
|
| - return XMPP_RETURN_OK;
|
| -}
|
| -
|
| -XmppRosterHandler*
|
| -XmppRosterModuleImpl::roster_handler() {
|
| - return roster_handler_;
|
| -}
|
| -
|
| -XmppPresence*
|
| -XmppRosterModuleImpl::outgoing_presence() {
|
| - return &outgoing_presence_;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::BroadcastPresence() {
|
| - // Scrub the outgoing presence
|
| - const XmlElement* element = outgoing_presence_.raw_xml();
|
| -
|
| - ASSERT(!element->HasAttr(QN_TO) &&
|
| - !element->HasAttr(QN_FROM) &&
|
| - (element->Attr(QN_TYPE) == STR_EMPTY ||
|
| - element->Attr(QN_TYPE) == "unavailable"));
|
| -
|
| - if (!engine())
|
| - return XMPP_RETURN_BADSTATE;
|
| -
|
| - return engine()->SendStanza(element);
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::SendDirectedPresence(const XmppPresence* presence,
|
| - const Jid& to_jid) {
|
| - if (!presence)
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (!engine())
|
| - return XMPP_RETURN_BADSTATE;
|
| -
|
| - XmlElement element(*(presence->raw_xml()));
|
| -
|
| - if (element.Name() != QN_PRESENCE ||
|
| - element.HasAttr(QN_TO) ||
|
| - element.HasAttr(QN_FROM))
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (element.HasAttr(QN_TYPE)) {
|
| - if (element.Attr(QN_TYPE) != STR_EMPTY &&
|
| - element.Attr(QN_TYPE) != "unavailable") {
|
| - return XMPP_RETURN_BADARGUMENT;
|
| - }
|
| - }
|
| -
|
| - element.SetAttr(QN_TO, to_jid.Str());
|
| -
|
| - return engine()->SendStanza(&element);
|
| -}
|
| -
|
| -size_t
|
| -XmppRosterModuleImpl::GetIncomingPresenceCount() {
|
| - return incoming_presence_vector_->size();
|
| -}
|
| -
|
| -const XmppPresence*
|
| -XmppRosterModuleImpl::GetIncomingPresence(size_t index) {
|
| - if (index >= incoming_presence_vector_->size())
|
| - return NULL;
|
| - return (*incoming_presence_vector_)[index];
|
| -}
|
| -
|
| -size_t
|
| -XmppRosterModuleImpl::GetIncomingPresenceForJidCount(const Jid& jid)
|
| -{
|
| - // find the vector in the map
|
| - JidPresenceVectorMap::iterator pos;
|
| - pos = incoming_presence_map_->find(jid);
|
| - if (pos == incoming_presence_map_->end())
|
| - return 0;
|
| -
|
| - ASSERT(pos->second != NULL);
|
| -
|
| - return pos->second->size();
|
| -}
|
| -
|
| -const XmppPresence*
|
| -XmppRosterModuleImpl::GetIncomingPresenceForJid(const Jid& jid,
|
| - size_t index) {
|
| - JidPresenceVectorMap::iterator pos;
|
| - pos = incoming_presence_map_->find(jid);
|
| - if (pos == incoming_presence_map_->end())
|
| - return NULL;
|
| -
|
| - ASSERT(pos->second != NULL);
|
| -
|
| - if (index >= pos->second->size())
|
| - return NULL;
|
| -
|
| - return (*pos->second)[index];
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::RequestRosterUpdate() {
|
| - if (!engine())
|
| - return XMPP_RETURN_BADSTATE;
|
| -
|
| - XmlElement roster_get(QN_IQ);
|
| - roster_get.AddAttr(QN_TYPE, "get");
|
| - roster_get.AddAttr(QN_ID, engine()->NextId());
|
| - roster_get.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
|
| - return engine()->SendIq(&roster_get, this, NULL);
|
| -}
|
| -
|
| -size_t
|
| -XmppRosterModuleImpl::GetRosterContactCount() {
|
| - return contacts_->size();
|
| -}
|
| -
|
| -const XmppRosterContact*
|
| -XmppRosterModuleImpl::GetRosterContact(size_t index) {
|
| - if (index >= contacts_->size())
|
| - return NULL;
|
| - return (*contacts_)[index];
|
| -}
|
| -
|
| -class RosterPredicate {
|
| -public:
|
| - explicit RosterPredicate(const Jid& jid) : jid_(jid) {
|
| - }
|
| -
|
| - bool operator() (XmppRosterContactImpl *& contact) {
|
| - return contact->jid() == jid_;
|
| - }
|
| -
|
| -private:
|
| - Jid jid_;
|
| -};
|
| -
|
| -const XmppRosterContact*
|
| -XmppRosterModuleImpl::FindRosterContact(const Jid& jid) {
|
| - ContactVector::iterator pos;
|
| -
|
| - pos = std::find_if(contacts_->begin(),
|
| - contacts_->end(),
|
| - RosterPredicate(jid));
|
| - if (pos == contacts_->end())
|
| - return NULL;
|
| -
|
| - return *pos;
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::RequestRosterChange(
|
| - const XmppRosterContact* contact) {
|
| - if (!contact)
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - Jid jid = contact->jid();
|
| -
|
| - if (!jid.IsValid())
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (!engine())
|
| - return XMPP_RETURN_BADSTATE;
|
| -
|
| - const XmlElement* contact_xml = contact->raw_xml();
|
| - if (contact_xml->Name() != QN_ROSTER_ITEM ||
|
| - contact_xml->HasAttr(QN_SUBSCRIPTION) ||
|
| - contact_xml->HasAttr(QN_ASK))
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - XmlElement roster_add(QN_IQ);
|
| - roster_add.AddAttr(QN_TYPE, "set");
|
| - roster_add.AddAttr(QN_ID, engine()->NextId());
|
| - roster_add.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
|
| - roster_add.AddElement(new XmlElement(*contact_xml), 1);
|
| -
|
| - return engine()->SendIq(&roster_add, this, NULL);
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::RequestRosterRemove(const Jid& jid) {
|
| - if (!jid.IsValid())
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (!engine())
|
| - return XMPP_RETURN_BADSTATE;
|
| -
|
| - XmlElement roster_add(QN_IQ);
|
| - roster_add.AddAttr(QN_TYPE, "set");
|
| - roster_add.AddAttr(QN_ID, engine()->NextId());
|
| - roster_add.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
|
| - roster_add.AddAttr(QN_JID, jid.Str(), 1);
|
| - roster_add.AddAttr(QN_SUBSCRIPTION, "remove", 1);
|
| -
|
| - return engine()->SendIq(&roster_add, this, NULL);
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::RequestSubscription(const Jid& jid) {
|
| - return SendSubscriptionRequest(jid, "subscribe");
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::CancelSubscription(const Jid& jid) {
|
| - return SendSubscriptionRequest(jid, "unsubscribe");
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::ApproveSubscriber(const Jid& jid) {
|
| - return SendSubscriptionRequest(jid, "subscribed");
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::CancelSubscriber(const Jid& jid) {
|
| - return SendSubscriptionRequest(jid, "unsubscribed");
|
| -}
|
| -
|
| -void
|
| -XmppRosterModuleImpl::IqResponse(XmppIqCookie, const XmlElement * stanza) {
|
| - // The only real Iq response that we expect to recieve are initial roster
|
| - // population
|
| - if (stanza->Attr(QN_TYPE) == "error")
|
| - {
|
| - if (roster_handler_)
|
| - roster_handler_->RosterError(this, stanza);
|
| -
|
| - return;
|
| - }
|
| -
|
| - ASSERT(stanza->Attr(QN_TYPE) == "result");
|
| -
|
| - InternalRosterItems(stanza);
|
| -}
|
| -
|
| -bool
|
| -XmppRosterModuleImpl::HandleStanza(const XmlElement * stanza)
|
| -{
|
| - ASSERT(engine() != NULL);
|
| -
|
| - // There are two types of stanzas that we care about: presence and roster push
|
| - // Iqs
|
| - if (stanza->Name() == QN_PRESENCE) {
|
| - const std::string& jid_string = stanza->Attr(QN_FROM);
|
| - Jid jid(jid_string);
|
| -
|
| - if (!jid.IsValid())
|
| - return false; // if the Jid isn't valid, don't process
|
| -
|
| - const std::string& type = stanza->Attr(QN_TYPE);
|
| - XmppSubscriptionRequestType request_type;
|
| - if (StringToSubscriptionRequestType(type, &request_type))
|
| - InternalSubscriptionRequest(jid, stanza, request_type);
|
| - else if (type == "unavailable" || type == STR_EMPTY)
|
| - InternalIncomingPresence(jid, stanza);
|
| - else if (type == "error")
|
| - InternalIncomingPresenceError(jid, stanza);
|
| - else
|
| - return false;
|
| -
|
| - return true;
|
| - } else if (stanza->Name() == QN_IQ) {
|
| - const XmlElement * roster_query = stanza->FirstNamed(QN_ROSTER_QUERY);
|
| - if (!roster_query || stanza->Attr(QN_TYPE) != "set")
|
| - return false;
|
| -
|
| - InternalRosterItems(stanza);
|
| -
|
| - // respond to the IQ
|
| - XmlElement result(QN_IQ);
|
| - result.AddAttr(QN_TYPE, "result");
|
| - result.AddAttr(QN_TO, stanza->Attr(QN_FROM));
|
| - result.AddAttr(QN_ID, stanza->Attr(QN_ID));
|
| -
|
| - engine()->SendStanza(&result);
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void
|
| -XmppRosterModuleImpl::DeleteIncomingPresence() {
|
| - // Clear out the vector of all presence notifications
|
| - {
|
| - PresenceVector::iterator pos;
|
| - for (pos = incoming_presence_vector_->begin();
|
| - pos < incoming_presence_vector_->end();
|
| - ++pos) {
|
| - XmppPresenceImpl * presence = *pos;
|
| - *pos = NULL;
|
| - delete presence;
|
| - }
|
| - incoming_presence_vector_->clear();
|
| - }
|
| -
|
| - // Clear out all of the small presence vectors per Jid
|
| - {
|
| - JidPresenceVectorMap::iterator pos;
|
| - for (pos = incoming_presence_map_->begin();
|
| - pos != incoming_presence_map_->end();
|
| - ++pos) {
|
| - PresenceVector* presence_vector = pos->second;
|
| - pos->second = NULL;
|
| - delete presence_vector;
|
| - }
|
| - incoming_presence_map_->clear();
|
| - }
|
| -}
|
| -
|
| -void
|
| -XmppRosterModuleImpl::DeleteContacts() {
|
| - ContactVector::iterator pos;
|
| - for (pos = contacts_->begin();
|
| - pos < contacts_->end();
|
| - ++pos) {
|
| - XmppRosterContact* contact = *pos;
|
| - *pos = NULL;
|
| - delete contact;
|
| - }
|
| - contacts_->clear();
|
| -}
|
| -
|
| -XmppReturnStatus
|
| -XmppRosterModuleImpl::SendSubscriptionRequest(const Jid& jid,
|
| - const std::string& type) {
|
| - if (!jid.IsValid())
|
| - return XMPP_RETURN_BADARGUMENT;
|
| -
|
| - if (!engine())
|
| - return XMPP_RETURN_BADSTATE;
|
| -
|
| - XmlElement presence_request(QN_PRESENCE);
|
| - presence_request.AddAttr(QN_TO, jid.Str());
|
| - presence_request.AddAttr(QN_TYPE, type);
|
| -
|
| - return engine()->SendStanza(&presence_request);
|
| -}
|
| -
|
| -
|
| -void
|
| -XmppRosterModuleImpl::InternalSubscriptionRequest(const Jid& jid,
|
| - const XmlElement* stanza,
|
| - XmppSubscriptionRequestType
|
| - request_type) {
|
| - if (roster_handler_)
|
| - roster_handler_->SubscriptionRequest(this, jid, request_type, stanza);
|
| -}
|
| -
|
| -class PresencePredicate {
|
| -public:
|
| - explicit PresencePredicate(const Jid& jid) : jid_(jid) {
|
| - }
|
| -
|
| - bool operator() (XmppPresenceImpl *& contact) {
|
| - return contact->jid() == jid_;
|
| - }
|
| -
|
| -private:
|
| - Jid jid_;
|
| -};
|
| -
|
| -void
|
| -XmppRosterModuleImpl::InternalIncomingPresence(const Jid& jid,
|
| - const XmlElement* stanza) {
|
| - bool added = false;
|
| - Jid bare_jid = jid.BareJid();
|
| -
|
| - // First add the presence to the map
|
| - JidPresenceVectorMap::iterator pos;
|
| - pos = incoming_presence_map_->find(jid.BareJid());
|
| - if (pos == incoming_presence_map_->end()) {
|
| - // Insert a new entry into the map. Get the position of this new entry
|
| - pos = (incoming_presence_map_->insert(
|
| - std::make_pair(bare_jid, new PresenceVector()))).first;
|
| - }
|
| -
|
| - PresenceVector * presence_vector = pos->second;
|
| - ASSERT(presence_vector != NULL);
|
| -
|
| - // Try to find this jid in the bare jid bucket
|
| - PresenceVector::iterator presence_pos;
|
| - XmppPresenceImpl* presence;
|
| - presence_pos = std::find_if(presence_vector->begin(),
|
| - presence_vector->end(),
|
| - PresencePredicate(jid));
|
| -
|
| - // Update/add it to the bucket
|
| - if (presence_pos == presence_vector->end()) {
|
| - presence = new XmppPresenceImpl();
|
| - if (XMPP_RETURN_OK == presence->set_raw_xml(stanza)) {
|
| - added = true;
|
| - presence_vector->push_back(presence);
|
| - } else {
|
| - delete presence;
|
| - presence = NULL;
|
| - }
|
| - } else {
|
| - presence = *presence_pos;
|
| - presence->set_raw_xml(stanza);
|
| - }
|
| -
|
| - // now add to the comprehensive vector
|
| - if (added)
|
| - incoming_presence_vector_->push_back(presence);
|
| -
|
| - // Call back to the user with the changed presence information
|
| - if (roster_handler_)
|
| - roster_handler_->IncomingPresenceChanged(this, presence);
|
| -}
|
| -
|
| -
|
| -void
|
| -XmppRosterModuleImpl::InternalIncomingPresenceError(const Jid& jid,
|
| - const XmlElement* stanza) {
|
| - if (roster_handler_)
|
| - roster_handler_->SubscriptionError(this, jid, stanza);
|
| -}
|
| -
|
| -void
|
| -XmppRosterModuleImpl::InternalRosterItems(const XmlElement* stanza) {
|
| - const XmlElement* result_data = stanza->FirstNamed(QN_ROSTER_QUERY);
|
| - if (!result_data)
|
| - return; // unknown stuff in result!
|
| -
|
| - bool all_new = contacts_->empty();
|
| -
|
| - for (const XmlElement* roster_item = result_data->FirstNamed(QN_ROSTER_ITEM);
|
| - roster_item;
|
| - roster_item = roster_item->NextNamed(QN_ROSTER_ITEM))
|
| - {
|
| - const std::string& jid_string = roster_item->Attr(QN_JID);
|
| - Jid jid(jid_string);
|
| - if (!jid.IsValid())
|
| - continue;
|
| -
|
| - // This algorithm is N^2 on the number of incoming contacts after the
|
| - // initial load. There is no way to do this faster without allowing
|
| - // duplicates, introducing more data structures or write a custom data
|
| - // structure. We'll see if this becomes a perf problem and fix it if it
|
| - // does.
|
| - ContactVector::iterator pos = contacts_->end();
|
| -
|
| - if (!all_new) {
|
| - pos = std::find_if(contacts_->begin(),
|
| - contacts_->end(),
|
| - RosterPredicate(jid));
|
| - }
|
| -
|
| - if (pos != contacts_->end()) { // Update/remove a current contact
|
| - if (roster_item->Attr(QN_SUBSCRIPTION) == "remove") {
|
| - XmppRosterContact* contact = *pos;
|
| - contacts_->erase(pos);
|
| - if (roster_handler_)
|
| - roster_handler_->ContactRemoved(this, contact,
|
| - std::distance(contacts_->begin(), pos));
|
| - delete contact;
|
| - } else {
|
| - XmppRosterContact* old_contact = *pos;
|
| - *pos = new XmppRosterContactImpl();
|
| - (*pos)->SetXmlFromWire(roster_item);
|
| - if (roster_handler_)
|
| - roster_handler_->ContactChanged(this, old_contact,
|
| - std::distance(contacts_->begin(), pos));
|
| - delete old_contact;
|
| - }
|
| - } else { // Add a new contact
|
| - XmppRosterContactImpl* contact = new XmppRosterContactImpl();
|
| - contact->SetXmlFromWire(roster_item);
|
| - contacts_->push_back(contact);
|
| - if (roster_handler_ && !all_new)
|
| - roster_handler_->ContactsAdded(this, contacts_->size() - 1, 1);
|
| - }
|
| - }
|
| -
|
| - // Send a consolidated update if all contacts are new
|
| - if (roster_handler_ && all_new)
|
| - roster_handler_->ContactsAdded(this, 0, contacts_->size());
|
| -}
|
| -
|
| -}
|
|
|