Files
@ 12d117f54ffe
Branch filter:
Location: libtransport.git/src/user.cpp - annotation
12d117f54ffe
12.7 KiB
text/x-c++hdr
Working setUser for postgres
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 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | 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 f035510e4798 c5edfd19b1aa 3f3c73988787 3f3c73988787 1ebe5535c4f3 8faecb5664c8 c00d5149d528 e2a992466e74 c7f2b6298073 c7f2b6298073 c00d5149d528 c00d5149d528 e2a992466e74 e2a992466e74 e2a992466e74 c5edfd19b1aa c5edfd19b1aa c5edfd19b1aa c00d5149d528 c00d5149d528 50bcfbf84cb1 2b836edd7985 c6224941ceab c5edfd19b1aa 2ae880ff94b5 c5edfd19b1aa c5edfd19b1aa 50bcfbf84cb1 2ae880ff94b5 5f017bd15dc7 5f017bd15dc7 c68479f86d5e 2b836edd7985 79d0e907bb27 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 6cabfd73ff78 6cabfd73ff78 6cabfd73ff78 6cabfd73ff78 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 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 2b836edd7985 36f4fb8870c9 36f4fb8870c9 2b836edd7985 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 79d0e907bb27 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 36f4fb8870c9 2ae880ff94b5 2b836edd7985 2b836edd7985 5b89dae8ca9a 5b89dae8ca9a 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 8c529dbabbbc 8c529dbabbbc 2c526db0f32e 2c526db0f32e 8e03fbec4701 8e03fbec4701 c00d5149d528 8e03fbec4701 8e03fbec4701 8e03fbec4701 c00d5149d528 8c529dbabbbc 04cbb3a90713 04cbb3a90713 04cbb3a90713 04cbb3a90713 196afcf3a36a 2c526db0f32e 1ebe5535c4f3 1ebe5535c4f3 5f017bd15dc7 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 8e1c2b43a6e3 2b836edd7985 2b836edd7985 2b836edd7985 2b836edd7985 8e1c2b43a6e3 8e1c2b43a6e3 9947946e3af1 2b836edd7985 2b836edd7985 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 8faecb5664c8 c68479f86d5e c68479f86d5e c68479f86d5e c68479f86d5e 808a9067c5f5 97a6609c8731 79d0e907bb27 79d0e907bb27 79d0e907bb27 79d0e907bb27 79d0e907bb27 79d0e907bb27 79d0e907bb27 79d0e907bb27 79d0e907bb27 97a6609c8731 97a6609c8731 c00d5149d528 c00d5149d528 c00d5149d528 c00d5149d528 c00d5149d528 c00d5149d528 50bcfbf84cb1 c7dd572625a2 c7dd572625a2 c7dd572625a2 c7dd572625a2 6a4fffdfe8c7 8faecb5664c8 c7dd572625a2 cdb464dd99d4 808a9067c5f5 d969b377433b d969b377433b 6a4fffdfe8c7 3450eb879607 3450eb879607 3450eb879607 e31c07794705 04cbb3a90713 3450eb879607 25f5516757ed 25f5516757ed 6a4fffdfe8c7 d969b377433b d969b377433b d969b377433b 50bcfbf84cb1 50bcfbf84cb1 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 "transport/presenceoracle.h"
#include "Swiften/Swiften.h"
#include "Swiften/Server/ServerStanzaChannel.h"
#include "Swiften/Elements/StreamError.h"
#include "Swiften/Elements/MUCPayload.h"
#include "Swiften/Elements/SpectrumErrorPayload.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.toBare();
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_resources = 0;
m_reconnectCounter = 0;
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;
}
if (!discoInfo) {
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;
}
std::vector<Swift::Presence::ref> presences = m_presenceOracle->getAllPresence(m_jid);
foreach(Swift::Presence::ref presence, presences) {
if (presence->getType() == Swift::Presence::Unavailable) {
continue;
}
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(presence->getFrom());
response->setFrom(m_component->getJID());
m_component->getStanzaChannel()->sendPresence(response);
}
else {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(presence->getFrom());
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(presence->getFrom());
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;
m_reconnectCounter = 0;
setIgnoreDisconnect(false);
updateLastActivity();
sendCurrentPresence();
}
void User::handlePresence(Swift::Presence::ref presence) {
int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
m_conversationManager->resetResources();
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());
std::string room = Buddy::JIDToLegacyName(presence->getTo());
onRoomLeft(room);
}
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());
std::string room = Buddy::JIDToLegacyName(presence->getTo());
std::string password = "";
if (presence->getPayload<Swift::MUCPayload>() != NULL) {
password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
}
onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password);
}
return;
}
// User wants to disconnect this resource
if (!m_component->inServerMode()) {
if (presence->getType() == Swift::Presence::Unavailable) {
// Send unavailable presences for online contacts
m_rosterManager->sendUnavailablePresences(presence->getFrom());
// Send unavailable presence for transport contact itself
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(presence->getFrom());
response->setFrom(m_component->getJID());
response->setType(Swift::Presence::Unavailable);
m_component->getStanzaChannel()->sendPresence(response);
}
else {
sendCurrentPresence();
// This resource is new, so we have to send buddies presences
if (currentResourcesCount != m_resources) {
m_rosterManager->sendCurrentPresences(presence->getFrom());
}
}
}
m_resources = currentResourcesCount;
// 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, Swift::SpectrumErrorPayload::Error e) {
if (m_ignoreDisconnect) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network ignored (probably moving between backends)");
return;
}
if (e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR || e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_NETWORK_ERROR) {
if (m_reconnectCounter < 3) {
m_reconnectCounter++;
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network for, trying to reconnect automatically.");
// Simulate destruction/resurrection :)
// TODO: If this stops working, create onReconnect signal
m_userManager->onUserDestroyed(this);
m_userManager->onUserCreated(this);
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());
msg->addPayload(boost::make_shared<Swift::SpectrumErrorPayload>(e));
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(Swift::StreamError::UndefinedCondition, error)));
if (m_userManager->getUser(jid) != NULL) {
m_userManager->removeUser(this);
}
}
else {
m_userManager->removeUser(this);
}
}
}
|