10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2005, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <algorithm>
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <iostream>
30cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include <map>
31cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include <sstream>
32cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include <string>
33cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include <vector>
34cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/xmpp/chatroommodule.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/constants.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/moduleimpl.h"
37cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/common.h"
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace buzz {
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// forward declarations
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass XmppChatroomImpl;
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass XmppChatroomMemberImpl;
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//! Module that encapsulates multiple chatrooms.
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//! Each chatroom is represented by an XmppChatroomImpl instance
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass XmppChatroomModuleImpl : public XmppChatroomModule,
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  public XmppModuleImpl, public XmppIqHandler {
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgpublic:
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  IMPLEMENT_XMPPMODULE
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org   // Creates a chatroom with specified Jid
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomModuleImpl();
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~XmppChatroomModuleImpl();
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // XmppChatroomModule
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus set_chatroom_handler(XmppChatroomHandler* handler);
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppChatroomHandler* chatroom_handler();
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus set_chatroom_jid(const Jid& chatroom_jid);
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual const Jid& chatroom_jid() const;
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus set_nickname(const std::string& nickname);
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual const std::string& nickname() const;
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual const Jid member_jid() const;
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus RequestEnterChatroom(const std::string& password,
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      const std::string& client_version,
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      const std::string& locale);
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus RequestExitChatroom();
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus RequestConnectionStatusChange(
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      XmppPresenceConnectionStatus connection_status);
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual size_t GetChatroomMemberCount();
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus CreateMemberEnumerator(XmppChatroomMemberEnumerator** enumerator);
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual const std::string subject();
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppChatroomState state() { return chatroom_state_; }
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppReturnStatus SendMessage(const XmlElement& message);
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // XmppModule
772a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  virtual void IqResponse(XmppIqCookie cookie, const XmlElement * pelStanza) {RTC_UNUSED2(cookie, pelStanza);}
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool HandleStanza(const XmlElement *);
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgprivate:
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  friend class XmppChatroomMemberEnumeratorImpl;
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus ServerChangeMyPresence(const XmlElement& presence);
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus ClientChangeMyPresence(XmppChatroomState new_state);
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus ChangePresence(XmppChatroomState new_state, const XmlElement* presence, bool isServer);
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus ServerChangedOtherPresence(const XmlElement& presence_element);
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomEnteredStatus GetEnterFailureFromXml(const XmlElement* presence);
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomExitedStatus GetExitFailureFromXml(const XmlElement* presence);
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool CheckEnterChatroomStateOk();
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void FireEnteredStatus(const XmlElement* presence,
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         XmppChatroomEnteredStatus status);
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void FireExitStatus(XmppChatroomExitedStatus status);
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void FireMessageReceived(const XmlElement& message);
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void FireMemberEntered(const XmppChatroomMember* entered_member);
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void FireMemberChanged(const XmppChatroomMember* changed_member);
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void FireMemberExited(const XmppChatroomMember* exited_member);
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef std::map<Jid, XmppChatroomMemberImpl*> JidMemberMap;
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomHandler*              chatroom_handler_;
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Jid                               chatroom_jid_;
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string                       nickname_;
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomState                 chatroom_state_;
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  JidMemberMap                      chatroom_jid_members_;
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int                               chatroom_jid_members_version_;
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass XmppChatroomMemberImpl : public XmppChatroomMember {
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgpublic:
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~XmppChatroomMemberImpl() {}
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus SetPresence(const XmppPresence* presence);
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // XmppChatroomMember
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const Jid member_jid() const;
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const Jid full_jid() const;
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::string name() const;
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const XmppPresence* presence() const;
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgprivate:
1242a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_ptr<XmppPresence>  presence_;
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass XmppChatroomMemberEnumeratorImpl :
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        public XmppChatroomMemberEnumerator  {
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgpublic:
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomMemberEnumeratorImpl(XmppChatroomModuleImpl::JidMemberMap* chatroom_jid_members,
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        int* map_version);
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // XmppChatroomMemberEnumerator
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual XmppChatroomMember* current();
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool Next();
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool Prev();
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool IsValid();
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool IsBeforeBeginning();
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool IsAfterEnd();
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgprivate:
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomModuleImpl::JidMemberMap*           map_;
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int                                             map_version_created_;
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int*                                            map_version_;
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomModuleImpl::JidMemberMap::iterator  iterator_;
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool                                            before_beginning_;
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// XmppChatroomModuleImpl ------------------------------------------------
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModule *
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModule::Create() {
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return new XmppChatroomModuleImpl();
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::XmppChatroomModuleImpl() :
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_handler_(NULL),
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_jid_(STR_EMPTY),
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_state_(XMPP_CHATROOM_STATE_NOT_IN_ROOM),
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_jid_members_version_(0) {
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::~XmppChatroomModuleImpl() {
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  JidMemberMap::iterator iterator = chatroom_jid_members_.begin();
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (iterator != chatroom_jid_members_.end()) {
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete iterator->second;
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iterator++;
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::HandleStanza(const XmlElement* stanza) {
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(engine() != NULL);
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // we handle stanzas that are for one of our chatrooms
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Jid from_jid = Jid(stanza->Attr(QN_FROM));
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // see if it's one of our chatrooms
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_jid_ != from_jid.BareJid()) {
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false; // not one of our chatrooms
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // handle presence stanza
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (stanza->Name() == QN_PRESENCE) {
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (from_jid == member_jid()) {
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ServerChangeMyPresence(*stanza);
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ServerChangedOtherPresence(*stanza);
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (stanza->Name() == QN_MESSAGE) {
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireMessageReceived(*stanza);
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::set_chatroom_handler(XmppChatroomHandler* handler) {
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Calling with NULL removes the handler.
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_handler_ = handler;
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return XMPP_RETURN_OK;
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomHandler*
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::chatroom_handler() {
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return chatroom_handler_;
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::set_chatroom_jid(const Jid& chatroom_jid) {
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_state_ != XMPP_CHATROOM_STATE_NOT_IN_ROOM) {
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE; // $TODO - this isn't a bad state, it's a bad call,  diff error code?
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_jid != chatroom_jid.BareJid()) {
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // chatroom_jid must be a bare jid
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADARGUMENT;
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_jid_ = chatroom_jid;
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return XMPP_RETURN_OK;
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst Jid&
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::chatroom_jid() const {
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return chatroom_jid_;
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org XmppReturnStatus
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org XmppChatroomModuleImpl::set_nickname(const std::string& nickname) {
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_state_ != XMPP_CHATROOM_STATE_NOT_IN_ROOM) {
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE; // $TODO - this isn't a bad state, it's a bad call,  diff error code?
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  nickname_ = nickname;
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return XMPP_RETURN_OK;
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org }
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string&
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org XmppChatroomModuleImpl::nickname() const {
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return nickname_;
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org }
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst Jid
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::member_jid() const {
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return Jid(chatroom_jid_.node(), chatroom_jid_.domain(), nickname_);
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::CheckEnterChatroomStateOk() {
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_jid_.IsValid() == false) {
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(0);
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (nickname_ == STR_EMPTY) {
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(0);
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string GetAttrValueFor(XmppPresenceConnectionStatus connection_status) {
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (connection_status) {
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case XMPP_CONNECTION_STATUS_UNKNOWN:
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "";
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case XMPP_CONNECTION_STATUS_CONNECTING:
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return STR_PSTN_CONFERENCE_STATUS_CONNECTING;
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case XMPP_CONNECTION_STATUS_CONNECTED:
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return STR_PSTN_CONFERENCE_STATUS_CONNECTED;
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::RequestEnterChatroom(
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& password,
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& client_version,
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& locale) {
2792a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  RTC_UNUSED(password);
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!engine())
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_state_ != XMPP_CHATROOM_STATE_NOT_IN_ROOM)
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE; // $TODO - this isn't a bad state, it's a bad call,  diff error code?
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (CheckEnterChatroomStateOk() == false) {
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // entering a chatroom is a presence request to the server
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmlElement element(QN_PRESENCE);
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  element.AddAttr(QN_TO, member_jid().Str());
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmlElement* muc_x = new XmlElement(QN_MUC_X);
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  element.AddElement(muc_x);
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!client_version.empty()) {
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElement* client_version_element = new XmlElement(QN_CLIENT_VERSION,
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                        false);
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    client_version_element->SetBodyText(client_version);
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    muc_x->AddElement(client_version_element);
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!locale.empty()) {
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElement* locale_element = new XmlElement(QN_LOCALE, false);
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    locale_element->SetBodyText(locale);
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    muc_x->AddElement(locale_element);
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus status = engine()->SendStanza(&element);
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (status == XMPP_RETURN_OK) {
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ClientChangeMyPresence(XMPP_CHATROOM_STATE_REQUESTED_ENTER);
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return status;
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::RequestExitChatroom() {
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!engine())
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // exiting a chatroom is a presence request to the server
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmlElement element(QN_PRESENCE);
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  element.AddAttr(QN_TO, member_jid().Str());
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  element.AddAttr(QN_TYPE, "unavailable");
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus status = engine()->SendStanza(&element);
328afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  if (status == XMPP_RETURN_OK &&
329afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      chatroom_state_ == XMPP_CHATROOM_STATE_IN_ROOM) {
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ClientChangeMyPresence(XMPP_CHATROOM_STATE_REQUESTED_EXIT);
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return status;
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::RequestConnectionStatusChange(
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmppPresenceConnectionStatus connection_status) {
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!engine())
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_state_ != XMPP_CHATROOM_STATE_IN_ROOM) {
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // $TODO - this isn't a bad state, it's a bad call,  diff error code?
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (CheckEnterChatroomStateOk() == false) {
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // entering a chatroom is a presence request to the server
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmlElement element(QN_PRESENCE);
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  element.AddAttr(QN_TO, member_jid().Str());
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  element.AddElement(new XmlElement(QN_MUC_X));
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connection_status != XMPP_CONNECTION_STATUS_UNKNOWN) {
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElement* con_status_element =
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        new XmlElement(QN_GOOGLE_PSTN_CONFERENCE_STATUS);
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    con_status_element->AddAttr(QN_STATUS, GetAttrValueFor(connection_status));
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    element.AddElement(con_status_element);
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus status = engine()->SendStanza(&element);
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return status;
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgsize_t
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::GetChatroomMemberCount() {
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return chatroom_jid_members_.size();
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::CreateMemberEnumerator(XmppChatroomMemberEnumerator** enumerator) {
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *enumerator = new XmppChatroomMemberEnumeratorImpl(&chatroom_jid_members_, &chatroom_jid_members_version_);
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return XMPP_RETURN_OK;
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::string
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::subject() {
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ""; //NYI
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::SendMessage(const XmlElement& message) {
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus xmpp_status = XMPP_RETURN_OK;
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // can only send a message if we're in the room
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_state_ != XMPP_CHATROOM_STATE_IN_ROOM) {
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE; // $TODO - this isn't a bad state, it's a bad call,  diff error code?
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (message.Name() != QN_MESSAGE) {
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    IFR(XMPP_RETURN_BADARGUMENT);
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::string& type = message.Attr(QN_TYPE);
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type != "groupchat") {
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    IFR(XMPP_RETURN_BADARGUMENT);
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (message.HasAttr(QN_FROM)) {
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    IFR(XMPP_RETURN_BADARGUMENT);
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (message.Attr(QN_TO) != chatroom_jid_.Str()) {
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    IFR(XMPP_RETURN_BADARGUMENT);
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  IFR(engine()->SendStanza(&message));
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return xmpp_status;
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum TransitionType {
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TRANSITION_TYPE_NONE                 = 0,
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TRANSITION_TYPE_ENTER_SUCCESS        = 1,
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TRANSITION_TYPE_ENTER_FAILURE        = 2,
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TRANSITION_TYPE_EXIT_VOLUNTARILY     = 3,
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TRANSITION_TYPE_EXIT_INVOLUNTARILY   = 4,
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct StateTransitionDescription {
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomState old_state;
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomState new_state;
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool              is_valid_server_transition;
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool              is_valid_client_transition;
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransitionType    transition_type;
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStateTransitionDescription Transitions[] = {
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_NOT_IN_ROOM,     XMPP_CHATROOM_STATE_REQUESTED_ENTER, false, true,  TRANSITION_TYPE_NONE, },
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_NOT_IN_ROOM,     XMPP_CHATROOM_STATE_IN_ROOM,         false, false, TRANSITION_TYPE_ENTER_SUCCESS, },
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_NOT_IN_ROOM,     XMPP_CHATROOM_STATE_REQUESTED_EXIT,  false, false, TRANSITION_TYPE_NONE, },
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_REQUESTED_ENTER, XMPP_CHATROOM_STATE_NOT_IN_ROOM,     true,  false, TRANSITION_TYPE_ENTER_FAILURE, },
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_REQUESTED_ENTER, XMPP_CHATROOM_STATE_IN_ROOM,         true,  false, TRANSITION_TYPE_ENTER_SUCCESS, },
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_REQUESTED_ENTER, XMPP_CHATROOM_STATE_REQUESTED_EXIT,  false, false, TRANSITION_TYPE_NONE, },
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_IN_ROOM,         XMPP_CHATROOM_STATE_NOT_IN_ROOM,     true,  false, TRANSITION_TYPE_EXIT_INVOLUNTARILY,  },
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_IN_ROOM,         XMPP_CHATROOM_STATE_REQUESTED_ENTER, false, false, TRANSITION_TYPE_NONE, },
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_IN_ROOM,         XMPP_CHATROOM_STATE_REQUESTED_EXIT,  false, true,  TRANSITION_TYPE_NONE, },
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_REQUESTED_EXIT,  XMPP_CHATROOM_STATE_NOT_IN_ROOM,     true,  false, TRANSITION_TYPE_EXIT_VOLUNTARILY, },
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_REQUESTED_EXIT,  XMPP_CHATROOM_STATE_REQUESTED_ENTER, false, false, TRANSITION_TYPE_NONE, },
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { XMPP_CHATROOM_STATE_REQUESTED_EXIT,  XMPP_CHATROOM_STATE_IN_ROOM,         false, false, TRANSITION_TYPE_NONE, },
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::FireEnteredStatus(const XmlElement* presence,
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                          XmppChatroomEnteredStatus status) {
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_handler_) {
4492a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::scoped_ptr<XmppPresence> xmpp_presence(XmppPresence::Create());
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    xmpp_presence->set_raw_xml(presence);
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    chatroom_handler_->ChatroomEnteredStatus(this, xmpp_presence.get(), status);
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::FireExitStatus(XmppChatroomExitedStatus status) {
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_handler_)
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    chatroom_handler_->ChatroomExitedStatus(this, status);
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::FireMessageReceived(const XmlElement& message) {
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_handler_)
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    chatroom_handler_->MessageReceived(this, message);
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::FireMemberEntered(const XmppChatroomMember* entered_member) {
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_handler_)
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    chatroom_handler_->MemberEntered(this, entered_member);
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::FireMemberChanged(
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const XmppChatroomMember* changed_member) {
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_handler_)
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    chatroom_handler_->MemberChanged(this, changed_member);
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::FireMemberExited(const XmppChatroomMember* exited_member) {
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (chatroom_handler_)
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    chatroom_handler_->MemberExited(this, exited_member);
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::ServerChangedOtherPresence(const XmlElement&
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                   presence_element) {
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppReturnStatus xmpp_status = XMPP_RETURN_OK;
4912a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_ptr<XmppPresence> presence(XmppPresence::Create());
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  IFR(presence->set_raw_xml(&presence_element));
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  JidMemberMap::iterator pos = chatroom_jid_members_.find(presence->jid());
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (pos == chatroom_jid_members_.end()) {
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (presence->available() == XMPP_PRESENCE_AVAILABLE) {
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      XmppChatroomMemberImpl* member = new XmppChatroomMemberImpl();
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      member->SetPresence(presence.get());
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      chatroom_jid_members_.insert(std::make_pair(member->member_jid(), member));
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      chatroom_jid_members_version_++;
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireMemberEntered(member);
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmppChatroomMemberImpl* member = pos->second;
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (presence->available() == XMPP_PRESENCE_AVAILABLE) {
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      member->SetPresence(presence.get());
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      chatroom_jid_members_version_++;
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireMemberChanged(member);
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    else if (presence->available() == XMPP_PRESENCE_UNAVAILABLE) {
512afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      member->SetPresence(presence.get());
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      chatroom_jid_members_.erase(pos);
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      chatroom_jid_members_version_++;
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireMemberExited(member);
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      delete member;
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return xmpp_status;
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::ClientChangeMyPresence(XmppChatroomState new_state) {
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangePresence(new_state, NULL, false);
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::ServerChangeMyPresence(const XmlElement& presence) {
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org   XmppChatroomState new_state;
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org   if (presence.HasAttr(QN_TYPE) == false) {
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      new_state = XMPP_CHATROOM_STATE_IN_ROOM;
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org   } else {
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     new_state = XMPP_CHATROOM_STATE_NOT_IN_ROOM;
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org   }
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangePresence(new_state, &presence, true);
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::ChangePresence(XmppChatroomState new_state,
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       const XmlElement* presence,
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       bool isServer) {
5452a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  RTC_UNUSED(presence);
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomState old_state = chatroom_state_;
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // do nothing if state hasn't changed
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (old_state == new_state)
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_OK;
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // find the right transition description
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StateTransitionDescription* transition_desc = NULL;
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (int i=0; i < ARRAY_SIZE(Transitions); i++) {
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (Transitions[i].old_state == old_state &&
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        Transitions[i].new_state == new_state) {
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        transition_desc = &Transitions[i];
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        break;
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (transition_desc == NULL) {
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(0);
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return XMPP_RETURN_BADSTATE;
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // we assert for any invalid transition states, and we'll
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (isServer) {
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // $TODO send original stanza back to server and log an error?
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Disable the assert because of b/6133072
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // ASSERT(transition_desc->is_valid_server_transition);
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!transition_desc->is_valid_server_transition) {
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return XMPP_RETURN_BADSTATE;
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (transition_desc->is_valid_client_transition == false) {
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(0);
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return XMPP_RETURN_BADARGUMENT;
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // set the new state and then fire any notifications to the handler
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  chatroom_state_ = new_state;
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (transition_desc->transition_type) {
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case TRANSITION_TYPE_ENTER_SUCCESS:
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireEnteredStatus(presence, XMPP_CHATROOM_ENTERED_SUCCESS);
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case TRANSITION_TYPE_ENTER_FAILURE:
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireEnteredStatus(presence, GetEnterFailureFromXml(presence));
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case TRANSITION_TYPE_EXIT_INVOLUNTARILY:
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireExitStatus(GetExitFailureFromXml(presence));
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case TRANSITION_TYPE_EXIT_VOLUNTARILY:
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      FireExitStatus(XMPP_CHATROOM_EXITED_REQUESTED);
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case TRANSITION_TYPE_NONE:
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return XMPP_RETURN_OK;
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomEnteredStatus
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::GetEnterFailureFromXml(const XmlElement* presence) {
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomEnteredStatus status = XMPP_CHATROOM_ENTERED_FAILURE_UNSPECIFIED;
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const XmlElement* error = presence->FirstNamed(QN_ERROR);
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (error != NULL && error->HasAttr(QN_CODE)) {
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int code = atoi(error->Attr(QN_CODE).c_str());
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    switch (code) {
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 401: status = XMPP_CHATROOM_ENTERED_FAILURE_PASSWORD_REQUIRED; break;
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 403: {
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        status = XMPP_CHATROOM_ENTERED_FAILURE_MEMBER_BANNED;
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (error->FirstNamed(QN_GOOGLE_SESSION_BLOCKED)) {
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          status = XMPP_CHATROOM_ENTERED_FAILURE_MEMBER_BLOCKED;
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        } else if (error->FirstNamed(QN_GOOGLE_SESSION_BLOCKING)) {
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          status = XMPP_CHATROOM_ENTERED_FAILURE_MEMBER_BLOCKING;
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        break;
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 405: status = XMPP_CHATROOM_ENTERED_FAILURE_ROOM_LOCKED; break;
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 406: status = XMPP_CHATROOM_ENTERED_FAILURE_OUTDATED_CLIENT; break;
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 407: status = XMPP_CHATROOM_ENTERED_FAILURE_NOT_A_MEMBER; break;
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 409: status = XMPP_CHATROOM_ENTERED_FAILURE_NICKNAME_CONFLICT; break;
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // http://xmpp.org/extensions/xep-0045.html#enter-maxusers
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      case 503: status = XMPP_CHATROOM_ENTERED_FAILURE_MAX_USERS; break;
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return status;
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomExitedStatus
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomModuleImpl::GetExitFailureFromXml(const XmlElement* presence) {
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  XmppChatroomExitedStatus status = XMPP_CHATROOM_EXITED_UNSPECIFIED;
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const XmlElement* muc_user = presence->FirstNamed(QN_MUC_USER_X);
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (muc_user != NULL) {
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const XmlElement* user_status = muc_user->FirstNamed(QN_MUC_USER_STATUS);
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (user_status != NULL && user_status->HasAttr(QN_CODE)) {
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int code = atoi(user_status->Attr(QN_CODE).c_str());
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      switch (code) {
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        case 307: status = XMPP_CHATROOM_EXITED_KICKED; break;
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        case 322: status = XMPP_CHATROOM_EXITED_NOT_A_MEMBER; break;
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        case 332: status = XMPP_CHATROOM_EXITED_SYSTEM_SHUTDOWN; break;
6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return status;
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppReturnStatus
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberImpl::SetPresence(const XmppPresence* presence) {
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(presence != NULL);
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // copy presence
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_.reset(XmppPresence::Create());
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_->set_raw_xml(presence->raw_xml());
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return XMPP_RETURN_OK;
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst Jid
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberImpl::member_jid() const {
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return presence_->jid();
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst Jid
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberImpl::full_jid() const {
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return Jid("");
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::string
6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberImpl::name() const {
6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return member_jid().resource();
6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst XmppPresence*
6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberImpl::presence() const {
6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return presence_.get();
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// XmppChatroomMemberEnumeratorImpl --------------------------------------
6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::XmppChatroomMemberEnumeratorImpl(
6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        XmppChatroomModuleImpl::JidMemberMap* map, int* map_version) {
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  map_ = map;
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  map_version_ = map_version;
6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  map_version_created_ = *map_version_;
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  iterator_ = map->begin();
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  before_beginning_ = true;
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMember*
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::current() {
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsValid() == false) {
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsBeforeBeginning() || IsAfterEnd()) {
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return iterator_->second;
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::Prev() {
7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsValid() == false) {
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsBeforeBeginning()) {
7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (iterator_ == map_->begin()) {
7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    before_beginning_ = true;
7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iterator_--;
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return current() != NULL;
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::Next() {
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsValid() == false) {
7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsBeforeBeginning()) {
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    before_beginning_ = false;
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iterator_ = map_->begin();
7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return current() != NULL;
7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsAfterEnd()) {
7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iterator_++;
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return current() != NULL;
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::IsValid() {
7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return map_version_created_ == *map_version_;
7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::IsBeforeBeginning() {
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return before_beginning_;
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgXmppChatroomMemberEnumeratorImpl::IsAfterEnd() {
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (iterator_ == map_->end());
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace buzz
753