spectrum2/include/Swiften/Server/ServerStanzaChannel.cpp
Vladimir Matena 6d2f8c1927 Switch from boost shared pointers to stl shared pointers (#162)
* Swiften 4 support
* using standard shared pointers when compiling with Swiften 4
2016-09-12 19:20:58 +03:00

183 lines
6.7 KiB
C++

/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Swiften/Server/ServerStanzaChannel.h"
#include "Swiften/Base/Error.h"
#include <iostream>
#include <boost/bind.hpp>
namespace Swift {
namespace {
// struct PriorityLessThan {
// bool operator()(const ServerSession* s1, const ServerSession* s2) const {
// return s1->getPriority() < s2->getPriority();
// }
// };
struct HasJID {
HasJID(const JID& jid) : jid(jid) {}
bool operator()(const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> session) const {
return session->getRemoteJID().equals(jid, JID::WithResource);
}
JID jid;
};
}
void ServerStanzaChannel::addSession(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> session) {
sessions[session->getRemoteJID().toBare().toString()].push_back(session);
session->onSessionFinished.connect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
session->onElementReceived.connect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
session->onDataRead.connect(boost::bind(&ServerStanzaChannel::handleDataRead, this, _1, session));
}
void ServerStanzaChannel::removeSession(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> session) {
session->onSessionFinished.disconnect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
session->onElementReceived.disconnect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
session->onDataRead.disconnect(boost::bind(&ServerStanzaChannel::handleDataRead, this, _1, session));
std::list<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> > &lst = sessions[session->getRemoteJID().toBare().toString()];
lst.erase(std::remove(lst.begin(), lst.end(), session), lst.end());
}
void ServerStanzaChannel::sendIQ(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<IQ> iq) {
send(iq);
}
void ServerStanzaChannel::sendMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Message> message) {
send(message);
}
void ServerStanzaChannel::sendPresence(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Presence> presence) {
send(presence);
}
void ServerStanzaChannel::handleDataRead(const SafeByteArray &data, const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> &session) {
if (safeByteArrayToString(data).find("</stream:stream>") != std::string::npos) {
Swift::Presence::ref presence = Swift::Presence::create();
presence->setFrom(session->getRemoteJID());
presence->setType(Swift::Presence::Unavailable);
onPresenceReceived(presence);
}
}
#if HAVE_SWIFTEN_3
void ServerStanzaChannel::finishSession(const JID& to, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ToplevelElement> element, bool last) {
#else
void ServerStanzaChannel::finishSession(const JID& to, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Element> element, bool last) {
#endif
std::vector<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> > candidateSessions;
for (std::list<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[to.toBare().toString()].begin(); i != sessions[to.toBare().toString()].end(); ++i) {
candidateSessions.push_back(*i);
}
for (std::vector<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> >::const_iterator i = candidateSessions.begin(); i != candidateSessions.end(); ++i) {
removeSession(*i);
if (element) {
(*i)->sendElement(element);
}
if (last && (*i)->getRemoteJID().isValid()) {
Swift::Presence::ref presence = Swift::Presence::create();
presence->setFrom((*i)->getRemoteJID());
presence->setType(Swift::Presence::Unavailable);
onPresenceReceived(presence);
}
(*i)->finishSession();
// std::cout << "FINISH SESSION " << sessions[to.toBare().toString()].size() << "\n";
if (last) {
break;
}
}
}
std::string ServerStanzaChannel::getNewIQID() {
return idGenerator.generateID();
}
void ServerStanzaChannel::send(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Stanza> stanza) {
JID to = stanza->getTo();
assert(to.isValid());
if (!stanza->getFrom().isValid()) {
stanza->setFrom(m_jid);
}
// For a full JID, first try to route to a session with the full JID
if (!to.isBare()) {
std::list<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> >::const_iterator i = std::find_if(sessions[stanza->getTo().toBare().toString()].begin(), sessions[stanza->getTo().toBare().toString()].end(), HasJID(to));
if (i != sessions[stanza->getTo().toBare().toString()].end()) {
(*i)->sendElement(stanza);
return;
}
}
// Look for candidate sessions
to = to.toBare();
std::vector<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> > candidateSessions;
for (std::list<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[stanza->getTo().toBare().toString()].begin(); i != sessions[stanza->getTo().toBare().toString()].end(); ++i) {
if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) {
candidateSessions.push_back(*i);
(*i)->sendElement(stanza);
}
}
if (candidateSessions.empty()) {
return;
}
// Find the session with the highest priority
// std::vector<ServerSession*>::const_iterator i = std::max_element(sessions.begin(), sessions.end(), PriorityLessThan());
// (*i)->sendStanza(stanza);
return;
}
void ServerStanzaChannel::handleSessionFinished(const boost::optional<Session::SessionError>&, const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession>& session) {
removeSession(session);
// if (!session->initiatedFinish()) {
Swift::Presence::ref presence = Swift::Presence::create();
presence->setFrom(session->getRemoteJID());
presence->setType(Swift::Presence::Unavailable);
onPresenceReceived(presence);
// }
}
void ServerStanzaChannel::handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Element> element, const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession>& session) {
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Stanza> stanza = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Stanza>(element);
if (!stanza) {
return;
}
stanza->setFrom(session->getRemoteJID());
if (!stanza->getFrom().isValid())
return;
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Message> message = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Message>(stanza);
if (message) {
onMessageReceived(message);
return;
}
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Presence> presence = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Presence>(stanza);
if (presence) {
onPresenceReceived(presence);
return;
}
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<IQ> iq = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<IQ>(stanza);
if (iq) {
onIQReceived(iq);
return;
}
}
void ServerStanzaChannel::handleSessionInitialized() {
onAvailableChanged(true);
}
}