Files
@ 88b7dd86b2be
Branch filter:
Location: libtransport.git/src/user.cpp - annotation
88b7dd86b2be
11.2 KiB
text/x-c++hdr
Added missing files
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa 2ae880ff94b5 88865c1234e3 50bcfbf84cb1 76c678dd6f1d c5edfd19b1aa 3f3c73988787 3f3c73988787 1ebe5535c4f3 c00d5149d528 e2a992466e74 c7f2b6298073 c7f2b6298073 c00d5149d528 c00d5149d528 e2a992466e74 e2a992466e74 e2a992466e74 c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c00d5149d528 c00d5149d528 50bcfbf84cb1 c5edfd19b1aa c6224941ceab c5edfd19b1aa 2ae880ff94b5 c5edfd19b1aa c5edfd19b1aa 50bcfbf84cb1 2ae880ff94b5 5f017bd15dc7 5f017bd15dc7 c68479f86d5e 5f017bd15dc7 d39705842a2a 5f017bd15dc7 88865c1234e3 88865c1234e3 76c678dd6f1d c00d5149d528 c68479f86d5e c5edfd19b1aa 2ae880ff94b5 c5edfd19b1aa c00d5149d528 e31c07794705 e31c07794705 e31c07794705 e31c07794705 50bcfbf84cb1 88865c1234e3 76c678dd6f1d c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e2a992466e74 e23f8e3c7f9d e23f8e3c7f9d e2a992466e74 e2a992466e74 16340590b496 e2a992466e74 e2a992466e74 e2a992466e74 e2a992466e74 e23f8e3c7f9d e2a992466e74 e2a992466e74 e2a992466e74 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 02b2f22f3e96 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 2ae880ff94b5 1e8eb7076f17 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 c00d5149d528 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 62fcb141926d c00d5149d528 c00d5149d528 c00d5149d528 62fcb141926d 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 1ebe5535c4f3 1ebe5535c4f3 2c526db0f32e c00d5149d528 2c526db0f32e 2c526db0f32e 2c526db0f32e 8e03fbec4701 8e03fbec4701 c00d5149d528 8e03fbec4701 8e03fbec4701 8e03fbec4701 c00d5149d528 2c526db0f32e 2c526db0f32e 1ebe5535c4f3 1ebe5535c4f3 5f017bd15dc7 36f4fb8870c9 9947946e3af1 e23f8e3c7f9d 9947946e3af1 e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d 9947946e3af1 2ae880ff94b5 2ae880ff94b5 5797b554ea69 5797b554ea69 5797b554ea69 5797b554ea69 e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 5f017bd15dc7 e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d e23f8e3c7f9d 5f017bd15dc7 5f017bd15dc7 c68479f86d5e c68479f86d5e c68479f86d5e c68479f86d5e c68479f86d5e 50bcfbf84cb1 c68479f86d5e c68479f86d5e c68479f86d5e c68479f86d5e 808a9067c5f5 c00d5149d528 c00d5149d528 c00d5149d528 c00d5149d528 c00d5149d528 c00d5149d528 50bcfbf84cb1 c7dd572625a2 c7dd572625a2 c7dd572625a2 c7dd572625a2 6a4fffdfe8c7 c7dd572625a2 cdb464dd99d4 808a9067c5f5 d969b377433b d969b377433b 6a4fffdfe8c7 3450eb879607 3450eb879607 3450eb879607 e31c07794705 cdb464dd99d4 3450eb879607 25f5516757ed 25f5516757ed 6a4fffdfe8c7 d969b377433b d969b377433b d969b377433b 50bcfbf84cb1 50bcfbf84cb1 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe 941bba0427fe c5edfd19b1aa | /**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "transport/user.h"
#include "transport/transport.h"
#include "transport/storagebackend.h"
#include "transport/rostermanager.h"
#include "transport/usermanager.h"
#include "transport/conversationmanager.h"
#include "Swiften/Swiften.h"
#include "Swiften/Server/ServerStanzaChannel.h"
#include "Swiften/Elements/StreamError.h"
#include "Swiften/Elements/MUCPayload.h"
#include "log4cxx/logger.h"
#include <boost/foreach.hpp>
#include <stdio.h>
#include <stdlib.h>
using namespace log4cxx;
using namespace boost;
#define foreach BOOST_FOREACH
namespace Transport {
static LoggerPtr logger = Logger::getLogger("User");
User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
m_jid = jid;
m_data = NULL;
m_component = component;
m_presenceOracle = component->m_presenceOracle;
m_entityCapsManager = component->m_entityCapsManager;
m_userManager = userManager;
m_userInfo = userInfo;
m_connected = false;
m_readyForConnect = false;
m_ignoreDisconnect = false;
m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(10000);
m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this));
m_rosterManager = new RosterManager(this, m_component);
m_conversationManager = new ConversationManager(this, m_component);
LOG4CXX_INFO(logger, m_jid.toString() << ": Created");
updateLastActivity();
}
User::~User(){
LOG4CXX_INFO(logger, m_jid.toString() << ": Destroying");
if (m_component->inServerMode()) {
dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>());
}
m_reconnectTimer->stop();
delete m_rosterManager;
delete m_conversationManager;
}
const Swift::JID &User::getJID() {
return m_jid;
}
Swift::JID User::getJIDWithFeature(const std::string &feature) {
Swift::JID jid;
std::vector<Swift::Presence::ref> presences = m_presenceOracle->getAllPresence(m_jid);
foreach(Swift::Presence::ref presence, presences) {
if (presence->getType() == Swift::Presence::Unavailable)
continue;
Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(presence->getFrom());
if (!discoInfo) {
#ifdef SUPPORT_LEGACY_CAPS
if (m_legacyCaps.find(presence->getFrom()) != m_legacyCaps.end()) {
discoInfo = m_legacyCaps[presence->getFrom()];
}
else {
continue;
}
#else
continue;
#endif
}
if (discoInfo->hasFeature(feature)) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Found JID with " << feature << " feature: " << presence->getFrom().toString());
return presence->getFrom();
}
}
LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << " feature " << m_legacyCaps.size());
return jid;
}
Swift::DiscoInfo::ref User::getCaps(const Swift::JID &jid) const {
Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid);
#ifdef SUPPORT_LEGACY_CAPS
if (!discoInfo) {
std::map<Swift::JID, Swift::DiscoInfo::ref>::const_iterator it = m_legacyCaps.find(jid);
if (it != m_legacyCaps.end()) {
discoInfo = it->second;
}
}
#endif
return discoInfo;
}
void User::sendCurrentPresence() {
if (m_component->inServerMode()) {
return;
}
if (m_connected) {
Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
if (highest) {
Swift::Presence::ref response = Swift::Presence::create(highest);
response->setTo(m_jid);
response->setFrom(m_component->getJID());
m_component->getStanzaChannel()->sendPresence(response);
}
else {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(m_jid.toBare());
response->setFrom(m_component->getJID());
response->setType(Swift::Presence::Unavailable);
m_component->getStanzaChannel()->sendPresence(response);
}
}
else {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(m_jid.toBare());
response->setFrom(m_component->getJID());
response->setType(Swift::Presence::Unavailable);
response->setStatus("Connecting");
m_component->getStanzaChannel()->sendPresence(response);
}
}
void User::setConnected(bool connected) {
m_connected = connected;
setIgnoreDisconnect(false);
updateLastActivity();
sendCurrentPresence();
}
void User::handlePresence(Swift::Presence::ref presence) {
std::cout << "PRESENCE " << presence->getFrom().toString() << "\n";
if (!m_connected) {
// we are not connected to legacy network, so we should do it when disco#info arrive :)
if (m_readyForConnect == false) {
// Forward status message to legacy network, but only if it's sent from active resource
// if (m_activeResource == presence->getFrom().getResource().getUTF8String()) {
// forwardStatus(presenceShow, stanzaStatus);
// }
boost::shared_ptr<Swift::CapsInfo> capsInfo = presence->getPayload<Swift::CapsInfo>();
if (capsInfo && capsInfo->getHash() == "sha-1") {
if (m_entityCapsManager->getCaps(presence->getFrom()) != Swift::DiscoInfo::ref()) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
m_readyForConnect = true;
onReadyToConnect();
}
}
else if (m_component->inServerMode()) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
m_readyForConnect = true;
onReadyToConnect();
}
else {
m_reconnectTimer->start();
}
}
}
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
if (isMUC) {
if (presence->getType() == Swift::Presence::Unavailable) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << presence->getTo().getNode());
onRoomLeft(presence->getTo().getNode());
}
else {
// force connection to legacy network to let backend to handle auto-join on connect.
if (!m_readyForConnect) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
m_readyForConnect = true;
onReadyToConnect();
}
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << presence->getTo().getNode() << " as " << presence->getTo().getResource());
onRoomJoined(presence->getTo().getNode(), presence->getTo().getResource(), "");
}
return;
}
sendCurrentPresence();
// Change legacy network presence
if (m_readyForConnect) {
Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
if (highest) {
Swift::Presence::ref response = Swift::Presence::create(highest);
response->setTo(m_jid);
response->setFrom(m_component->getJID());
LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType());
onPresenceChanged(highest);
}
else {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(m_jid.toBare());
response->setFrom(m_component->getJID());
response->setType(Swift::Presence::Unavailable);
onPresenceChanged(response);
}
}
}
void User::handleSubscription(Swift::Presence::ref presence) {
m_rosterManager->handleSubscription(presence);
}
void User::handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info) {
LOG4CXX_INFO(logger, jid.toString() << ": got disco#info");
#ifdef SUPPORT_LEGACY_CAPS
Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid);
// This is old legacy cap which is not stored in entityCapsManager,
// we have to store it in our user class.
if (!discoInfo) {
LOG4CXX_INFO(logger, jid.toString() << ": LEGACY");
m_legacyCaps[jid] = info;
}
#endif
onConnectingTimeout();
}
void User::onConnectingTimeout() {
if (m_connected || m_readyForConnect)
return;
m_reconnectTimer->stop();
m_readyForConnect = true;
onReadyToConnect();
Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
if (highest) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << highest->getType());
onPresenceChanged(highest);
}
}
void User::setIgnoreDisconnect(bool ignoreDisconnect) {
m_ignoreDisconnect = ignoreDisconnect;
LOG4CXX_INFO(logger, m_jid.toString() << ": Setting ignoreDisconnect=" << m_ignoreDisconnect);
}
void User::handleDisconnected(const std::string &error) {
if (m_ignoreDisconnect) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network ignored (probably moving between backends)");
return;
}
if (error.empty()) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network");
}
else {
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network with error " << error);
}
onDisconnected();
boost::shared_ptr<Swift::Message> msg(new Swift::Message());
msg->setBody(error);
msg->setTo(m_jid.toBare());
msg->setFrom(m_component->getJID());
m_component->getStanzaChannel()->sendMessage(msg);
// In server mode, server finishes the session and pass unavailable session to userManager if we're connected to legacy network,
// so we can't removeUser() in server mode, because it would be removed twice.
// Once in finishSession and once in m_userManager->removeUser.
if (m_component->inServerMode()) {
// Remove user later just to be sure there won't be double-free.
// We can't be sure finishSession sends unavailable presence everytime, so check if user gets removed
// in finishSession(...) call and if not, remove it here.
std::string jid = m_jid.toBare().toString();
dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>(new Swift::StreamError()));
if (m_userManager->getUser(jid) != NULL) {
m_userManager->removeUser(this);
}
}
else {
m_userManager->removeUser(this);
}
}
void User::handleFTStateChanged(Swift::FileTransfer::State state, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long id) {
if (state.state == Swift::FileTransfer::State::Transferring) {
onFTAccepted(buddyName, fileName, size, id);
}
}
void User::sendFile(const Swift::JID& from, boost::shared_ptr<Swift::ReadBytestream> byteStream, const Swift::StreamInitiationFileInfo &info, unsigned long id) {
boost::shared_ptr<Swift::OutgoingFileTransfer> ft = m_userManager->getOutgoingFileTransferManager()->createOutgoingFileTransfer(from, m_jid, byteStream, info);
if (ft) {
m_filetransfers.push_back(ft);
ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id));
ft->start();
}
}
}
|