Initial swiften 3 support
This commit is contained in:
parent
bc4450cfca
commit
0d99e8c85d
65 changed files with 8152 additions and 8960 deletions
1044
CMakeLists.txt
1044
CMakeLists.txt
File diff suppressed because it is too large
Load diff
|
@ -1,447 +1,455 @@
|
|||
// Transport includes
|
||||
#include "transport/config.h"
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/logging.h"
|
||||
|
||||
#include "boost/date_time/posix_time/posix_time.hpp"
|
||||
|
||||
// Swiften
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
#ifndef WIN32
|
||||
// for signal handler
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#endif
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#ifndef __MACH__
|
||||
// malloc_trim
|
||||
#include "malloc.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
DEFINE_LOGGER(logger, "Swiften");
|
||||
DEFINE_LOGGER(logger_xml, "backend.xml");
|
||||
|
||||
// eventloop
|
||||
Swift::SimpleEventLoop *loop_;
|
||||
|
||||
// Plugins
|
||||
class SwiftenPlugin;
|
||||
NetworkPlugin *np = NULL;
|
||||
Swift::XMPPSerializer *serializer;
|
||||
|
||||
class ForwardIQHandler : public Swift::IQHandler {
|
||||
public:
|
||||
std::map <std::string, std::string> m_id2resource;
|
||||
|
||||
ForwardIQHandler(NetworkPlugin *np, const std::string &user) {
|
||||
m_np = np;
|
||||
m_user = user;
|
||||
}
|
||||
|
||||
bool handleIQ(boost::shared_ptr<Swift::IQ> iq) {
|
||||
if (iq->getPayload<Swift::RosterPayload>() != NULL) {
|
||||
return false;
|
||||
}
|
||||
if (iq->getType() == Swift::IQ::Get) {
|
||||
m_id2resource[iq->getID()] = iq->getFrom().getResource();
|
||||
}
|
||||
|
||||
iq->setTo(m_user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(iq));
|
||||
m_np->sendRawXML(xml);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
NetworkPlugin *m_np;
|
||||
std::string m_user;
|
||||
|
||||
};
|
||||
|
||||
class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
boost::shared_ptr<Swift::Connection> m_conn;
|
||||
bool m_firstPing;
|
||||
|
||||
Swift::FullPayloadSerializerCollection collection;
|
||||
Swift::XMPPParser *m_xmppParser;
|
||||
Swift::FullPayloadParserFactoryCollection m_collection2;
|
||||
|
||||
SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
|
||||
this->config = config;
|
||||
m_firstPing = true;
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1));
|
||||
m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
|
||||
|
||||
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType);
|
||||
m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory());
|
||||
m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting the plugin.");
|
||||
}
|
||||
|
||||
// NetworkPlugin uses this method to send the data to networkplugin server
|
||||
void sendData(const std::string &string) {
|
||||
m_conn->write(Swift::createSafeByteArray(string));
|
||||
}
|
||||
|
||||
// This method has to call handleDataRead with all received data from network plugin server
|
||||
void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
|
||||
if (m_firstPing) {
|
||||
m_firstPing = false;
|
||||
NetworkPlugin::PluginConfig cfg;
|
||||
cfg.setRawXML(true);
|
||||
sendConfig(cfg);
|
||||
}
|
||||
std::string d(data->begin(), data->end());
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void handleStreamStart(const Swift::ProtocolHeader&) {}
|
||||
|
||||
void handleElement(boost::shared_ptr<Swift::Element> element) {
|
||||
boost::shared_ptr<Swift::Stanza> stanza = boost::dynamic_pointer_cast<Swift::Stanza>(element);
|
||||
if (!stanza) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string user = stanza->getFrom().toBare();
|
||||
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
stanza->setFrom(client->getJID());
|
||||
|
||||
boost::shared_ptr<Swift::Message> message = boost::dynamic_pointer_cast<Swift::Message>(stanza);
|
||||
if (message) {
|
||||
client->sendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Presence> presence = boost::dynamic_pointer_cast<Swift::Presence>(stanza);
|
||||
if (presence) {
|
||||
client->sendPresence(presence);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::IQ> iq = boost::dynamic_pointer_cast<Swift::IQ>(stanza);
|
||||
if (iq) {
|
||||
if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) {
|
||||
std::string resource = m_handlers[user]->m_id2resource[stanza->getID()];
|
||||
if (resource.empty()) {
|
||||
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain()));
|
||||
} else {
|
||||
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), resource));
|
||||
}
|
||||
|
||||
m_handlers[user]->m_id2resource.erase(stanza->getID());
|
||||
}
|
||||
client->getIQRouter()->sendIQ(iq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void handleStreamEnd() {}
|
||||
|
||||
void handleRawXML(const std::string &xml) {
|
||||
m_xmppParser->parse(xml);
|
||||
}
|
||||
|
||||
void handleSwiftDisconnected(const std::string &user, const boost::optional<Swift::ClientError> &error) {
|
||||
std::string message = "";
|
||||
bool reconnect = false;
|
||||
if (error) {
|
||||
switch(error->getType()) {
|
||||
case Swift::ClientError::UnknownError: message = ("Unknown Error"); reconnect = true; break;
|
||||
case Swift::ClientError::DomainNameResolveError: message = ("Unable to find server"); break;
|
||||
case Swift::ClientError::ConnectionError: message = ("Error connecting to server"); break;
|
||||
case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); reconnect = true; break;
|
||||
case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); reconnect = true; break;
|
||||
case Swift::ClientError::XMLError: message = ("Error parsing server data"); reconnect = true; break;
|
||||
case Swift::ClientError::AuthenticationFailedError: message = ("Login/password invalid"); break;
|
||||
case Swift::ClientError::CompressionFailedError: message = ("Error while compressing stream"); break;
|
||||
case Swift::ClientError::ServerVerificationFailedError: message = ("Server verification failed"); break;
|
||||
case Swift::ClientError::NoSupportedAuthMechanismsError: message = ("Authentication mechanisms not supported"); break;
|
||||
case Swift::ClientError::UnexpectedElementError: message = ("Unexpected response"); break;
|
||||
case Swift::ClientError::ResourceBindError: message = ("Error binding resource"); break;
|
||||
case Swift::ClientError::SessionStartError: message = ("Error starting session"); break;
|
||||
case Swift::ClientError::StreamError: message = ("Stream error"); break;
|
||||
case Swift::ClientError::TLSError: message = ("Encryption error"); break;
|
||||
case Swift::ClientError::ClientCertificateLoadError: message = ("Error loading certificate (Invalid password?)"); break;
|
||||
case Swift::ClientError::ClientCertificateError: message = ("Certificate not authorized"); break;
|
||||
|
||||
case Swift::ClientError::UnknownCertificateError: message = ("Unknown certificate"); break;
|
||||
case Swift::ClientError::CertificateExpiredError: message = ("Certificate has expired"); break;
|
||||
case Swift::ClientError::CertificateNotYetValidError: message = ("Certificate is not yet valid"); break;
|
||||
case Swift::ClientError::CertificateSelfSignedError: message = ("Certificate is self-signed"); break;
|
||||
case Swift::ClientError::CertificateRejectedError: message = ("Certificate has been rejected"); break;
|
||||
case Swift::ClientError::CertificateUntrustedError: message = ("Certificate is not trusted"); break;
|
||||
case Swift::ClientError::InvalidCertificatePurposeError: message = ("Certificate cannot be used for encrypting your connection"); break;
|
||||
case Swift::ClientError::CertificatePathLengthExceededError: message = ("Certificate path length constraint exceeded"); break;
|
||||
case Swift::ClientError::InvalidCertificateSignatureError: message = ("Invalid certificate signature"); break;
|
||||
case Swift::ClientError::InvalidCAError: message = ("Invalid Certificate Authority"); break;
|
||||
case Swift::ClientError::InvalidServerIdentityError: message = ("Certificate does not match the host identity"); break;
|
||||
}
|
||||
}
|
||||
LOG4CXX_INFO(logger, user << ": Disconnected " << message);
|
||||
handleDisconnected(user, reconnect ? 0 : 3, message);
|
||||
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
m_users.erase(user);
|
||||
m_handlers.erase(user);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
#ifndef __FreeBSD__
|
||||
#ifndef __MACH__
|
||||
// force returning of memory chunks allocated by libxml2 to kernel
|
||||
malloc_trim(0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void handleSwiftConnected(const std::string &user) {
|
||||
LOG4CXX_INFO(logger, user << ": Connected to XMPP server.");
|
||||
handleConnected(user);
|
||||
m_users[user]->requestRoster();
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setFrom(m_users[user]->getJID());
|
||||
m_users[user]->sendPresence(response);
|
||||
}
|
||||
|
||||
void handleSwiftRosterReceived(const std::string &user) {
|
||||
Swift::PresenceOracle *oracle = m_users[user]->getPresenceOracle();
|
||||
BOOST_FOREACH(const Swift::XMPPRosterItem &item, m_users[user]->getRoster()->getItems()) {
|
||||
Swift::Presence::ref lastPresence = oracle->getLastPresence(item.getJID());
|
||||
pbnetwork::StatusType status = lastPresence ? ((pbnetwork::StatusType) lastPresence->getShow()) : pbnetwork::STATUS_NONE;
|
||||
handleBuddyChanged(user, item.getJID().toBare().toString(),
|
||||
item.getName(), item.getGroups(), status);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) {
|
||||
// boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
// if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (presence->getPayload<Swift::MUCUserPayload>() != NULL || presence->getPayload<Swift::MUCPayload>() != NULL) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed");
|
||||
//
|
||||
// std::string message = presence->getStatus();
|
||||
// std::string photo = "";
|
||||
//
|
||||
// boost::shared_ptr<Swift::VCardUpdate> update = presence->getPayload<Swift::VCardUpdate>();
|
||||
// if (update) {
|
||||
// photo = update->getPhotoHash();
|
||||
// }
|
||||
//
|
||||
// boost::optional<Swift::XMPPRosterItem> item = m_users[user]->getRoster()->getItem(presence->getFrom());
|
||||
// if (item) {
|
||||
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo);
|
||||
// }
|
||||
// else {
|
||||
// std::vector<std::string> groups;
|
||||
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo);
|
||||
// }
|
||||
presence->setTo(user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(presence));
|
||||
sendRawXML(xml);
|
||||
}
|
||||
|
||||
void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) {
|
||||
message->setTo(user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(message));
|
||||
sendRawXML(xml);
|
||||
}
|
||||
|
||||
void handleSwiftenDataRead(const Swift::SafeByteArray &data) {
|
||||
std::string d = safeByteArrayToString(data);
|
||||
if (!boost::starts_with(d, "<auth")) {
|
||||
LOG4CXX_INFO(logger_xml, "XML IN " << d);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSwiftenDataWritten(const Swift::SafeByteArray &data) {
|
||||
LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
|
||||
}
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
LOG4CXX_INFO(logger, user << ": connecting as " << legacyName);
|
||||
boost::shared_ptr<Swift::Client> client = boost::make_shared<Swift::Client>(Swift::JID(legacyName + "/Spectrum"), password, m_factories);
|
||||
m_users[user] = client;
|
||||
client->setAlwaysTrustCertificates();
|
||||
client->onConnected.connect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
client->onDisconnected.connect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
|
||||
client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
|
||||
client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1));
|
||||
client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1));
|
||||
client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3));
|
||||
client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2));
|
||||
Swift::ClientOptions opt;
|
||||
opt.allowPLAINWithoutTLS = true;
|
||||
client->connect(opt);
|
||||
|
||||
boost::shared_ptr<ForwardIQHandler> handler = boost::make_shared<ForwardIQHandler>(this, user);
|
||||
client->getIQRouter()->addHandler(handler);
|
||||
m_handlers[user] = handler;
|
||||
}
|
||||
|
||||
void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) {
|
||||
handleSwiftPresenceChanged(user, presence);
|
||||
}
|
||||
|
||||
void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) {
|
||||
Swift::Presence::ref presence = Swift::Presence::create();
|
||||
presence->setTo(user);
|
||||
presence->setFrom(jid);
|
||||
presence->setType(Swift::Presence::Unsubscribe);
|
||||
handleSwiftPresenceChanged(user, presence);
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
// client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
|
||||
client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
|
||||
client->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") {
|
||||
}
|
||||
|
||||
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
|
||||
}
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << ".");
|
||||
if (!client->getRoster()->containsJID(buddyName) || client->getRoster()->getSubscriptionStateForJID(buddyName) != Swift::RosterItemPayload::Both) {
|
||||
Swift::RosterItemPayload item;
|
||||
item.setName(alias);
|
||||
item.setJID(buddyName);
|
||||
item.setGroups(groups);
|
||||
boost::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
client->getSubscriptionManager()->requestSubscription(buddyName);
|
||||
}
|
||||
else {
|
||||
Swift::JID contact(buddyName);
|
||||
Swift::RosterItemPayload item(contact, alias, client->getRoster()->getSubscriptionStateForJID(contact));
|
||||
item.setGroups(groups);
|
||||
boost::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
Swift::RosterItemPayload item(buddyName, "", Swift::RosterItemPayload::Remove);
|
||||
boost::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
}
|
||||
}
|
||||
|
||||
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||
|
||||
}
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
Config *config;
|
||||
std::map<std::string, boost::shared_ptr<Swift::Client> > m_users;
|
||||
std::map<std::string, boost::shared_ptr<ForwardIQHandler> > m_handlers;
|
||||
};
|
||||
|
||||
#ifndef WIN32
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
#ifndef WIN32
|
||||
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
|
||||
std::cout << "SIGCHLD handler can't be set\n";
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logging::initBackendLogging(cfg);
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
loop_ = &eventLoop;
|
||||
np = new SwiftenPlugin(cfg, &eventLoop, host, port);
|
||||
loop_->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
// Transport includes
|
||||
#include "transport/config.h"
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/logging.h"
|
||||
|
||||
#include "boost/date_time/posix_time/posix_time.hpp"
|
||||
|
||||
// Swiften
|
||||
#include "Swiften/Swiften.h"
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
#ifndef WIN32
|
||||
// for signal handler
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#endif
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#ifndef __MACH__
|
||||
// malloc_trim
|
||||
#include "malloc.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
DEFINE_LOGGER(logger, "Swiften");
|
||||
DEFINE_LOGGER(logger_xml, "backend.xml");
|
||||
|
||||
// eventloop
|
||||
Swift::SimpleEventLoop *loop_;
|
||||
|
||||
// Plugins
|
||||
class SwiftenPlugin;
|
||||
NetworkPlugin *np = NULL;
|
||||
Swift::XMPPSerializer *serializer;
|
||||
|
||||
class ForwardIQHandler : public Swift::IQHandler {
|
||||
public:
|
||||
std::map <std::string, std::string> m_id2resource;
|
||||
|
||||
ForwardIQHandler(NetworkPlugin *np, const std::string &user) {
|
||||
m_np = np;
|
||||
m_user = user;
|
||||
}
|
||||
|
||||
bool handleIQ(boost::shared_ptr<Swift::IQ> iq) {
|
||||
if (iq->getPayload<Swift::RosterPayload>() != NULL) {
|
||||
return false;
|
||||
}
|
||||
if (iq->getType() == Swift::IQ::Get) {
|
||||
m_id2resource[iq->getID()] = iq->getFrom().getResource();
|
||||
}
|
||||
|
||||
iq->setTo(m_user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(iq));
|
||||
m_np->sendRawXML(xml);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
NetworkPlugin *m_np;
|
||||
std::string m_user;
|
||||
|
||||
};
|
||||
|
||||
class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
boost::shared_ptr<Swift::Connection> m_conn;
|
||||
bool m_firstPing;
|
||||
|
||||
Swift::FullPayloadSerializerCollection collection;
|
||||
Swift::XMPPParser *m_xmppParser;
|
||||
Swift::FullPayloadParserFactoryCollection m_collection2;
|
||||
|
||||
SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
|
||||
this->config = config;
|
||||
m_firstPing = true;
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1));
|
||||
m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
|
||||
#if HAVE_SWIFTEN_3
|
||||
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType, false);
|
||||
#else
|
||||
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType);
|
||||
#endif
|
||||
m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory());
|
||||
m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting the plugin.");
|
||||
}
|
||||
|
||||
// NetworkPlugin uses this method to send the data to networkplugin server
|
||||
void sendData(const std::string &string) {
|
||||
m_conn->write(Swift::createSafeByteArray(string));
|
||||
}
|
||||
|
||||
// This method has to call handleDataRead with all received data from network plugin server
|
||||
void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
|
||||
if (m_firstPing) {
|
||||
m_firstPing = false;
|
||||
NetworkPlugin::PluginConfig cfg;
|
||||
cfg.setRawXML(true);
|
||||
sendConfig(cfg);
|
||||
}
|
||||
std::string d(data->begin(), data->end());
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void handleStreamStart(const Swift::ProtocolHeader&) {}
|
||||
#if HAVE_SWIFTEN_3
|
||||
void handleElement(boost::shared_ptr<Swift::ToplevelElement> element) {
|
||||
#else
|
||||
void handleElement(boost::shared_ptr<Swift::Element> element) {
|
||||
#endif
|
||||
boost::shared_ptr<Swift::Stanza> stanza = boost::dynamic_pointer_cast<Swift::Stanza>(element);
|
||||
if (!stanza) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string user = stanza->getFrom().toBare();
|
||||
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
stanza->setFrom(client->getJID());
|
||||
|
||||
boost::shared_ptr<Swift::Message> message = boost::dynamic_pointer_cast<Swift::Message>(stanza);
|
||||
if (message) {
|
||||
client->sendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Presence> presence = boost::dynamic_pointer_cast<Swift::Presence>(stanza);
|
||||
if (presence) {
|
||||
client->sendPresence(presence);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::IQ> iq = boost::dynamic_pointer_cast<Swift::IQ>(stanza);
|
||||
if (iq) {
|
||||
if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) {
|
||||
std::string resource = m_handlers[user]->m_id2resource[stanza->getID()];
|
||||
if (resource.empty()) {
|
||||
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain()));
|
||||
} else {
|
||||
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), resource));
|
||||
}
|
||||
|
||||
m_handlers[user]->m_id2resource.erase(stanza->getID());
|
||||
}
|
||||
client->getIQRouter()->sendIQ(iq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void handleStreamEnd() {}
|
||||
|
||||
void handleRawXML(const std::string &xml) {
|
||||
m_xmppParser->parse(xml);
|
||||
}
|
||||
|
||||
void handleSwiftDisconnected(const std::string &user, const boost::optional<Swift::ClientError> &error) {
|
||||
std::string message = "";
|
||||
bool reconnect = false;
|
||||
if (error) {
|
||||
switch(error->getType()) {
|
||||
case Swift::ClientError::UnknownError: message = ("Unknown Error"); reconnect = true; break;
|
||||
case Swift::ClientError::DomainNameResolveError: message = ("Unable to find server"); break;
|
||||
case Swift::ClientError::ConnectionError: message = ("Error connecting to server"); break;
|
||||
case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); reconnect = true; break;
|
||||
case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); reconnect = true; break;
|
||||
case Swift::ClientError::XMLError: message = ("Error parsing server data"); reconnect = true; break;
|
||||
case Swift::ClientError::AuthenticationFailedError: message = ("Login/password invalid"); break;
|
||||
case Swift::ClientError::CompressionFailedError: message = ("Error while compressing stream"); break;
|
||||
case Swift::ClientError::ServerVerificationFailedError: message = ("Server verification failed"); break;
|
||||
case Swift::ClientError::NoSupportedAuthMechanismsError: message = ("Authentication mechanisms not supported"); break;
|
||||
case Swift::ClientError::UnexpectedElementError: message = ("Unexpected response"); break;
|
||||
case Swift::ClientError::ResourceBindError: message = ("Error binding resource"); break;
|
||||
case Swift::ClientError::SessionStartError: message = ("Error starting session"); break;
|
||||
case Swift::ClientError::StreamError: message = ("Stream error"); break;
|
||||
case Swift::ClientError::TLSError: message = ("Encryption error"); break;
|
||||
case Swift::ClientError::ClientCertificateLoadError: message = ("Error loading certificate (Invalid password?)"); break;
|
||||
case Swift::ClientError::ClientCertificateError: message = ("Certificate not authorized"); break;
|
||||
|
||||
case Swift::ClientError::UnknownCertificateError: message = ("Unknown certificate"); break;
|
||||
case Swift::ClientError::CertificateExpiredError: message = ("Certificate has expired"); break;
|
||||
case Swift::ClientError::CertificateNotYetValidError: message = ("Certificate is not yet valid"); break;
|
||||
case Swift::ClientError::CertificateSelfSignedError: message = ("Certificate is self-signed"); break;
|
||||
case Swift::ClientError::CertificateRejectedError: message = ("Certificate has been rejected"); break;
|
||||
case Swift::ClientError::CertificateUntrustedError: message = ("Certificate is not trusted"); break;
|
||||
case Swift::ClientError::InvalidCertificatePurposeError: message = ("Certificate cannot be used for encrypting your connection"); break;
|
||||
case Swift::ClientError::CertificatePathLengthExceededError: message = ("Certificate path length constraint exceeded"); break;
|
||||
case Swift::ClientError::InvalidCertificateSignatureError: message = ("Invalid certificate signature"); break;
|
||||
case Swift::ClientError::InvalidCAError: message = ("Invalid Certificate Authority"); break;
|
||||
case Swift::ClientError::InvalidServerIdentityError: message = ("Certificate does not match the host identity"); break;
|
||||
}
|
||||
}
|
||||
LOG4CXX_INFO(logger, user << ": Disconnected " << message);
|
||||
handleDisconnected(user, reconnect ? 0 : 3, message);
|
||||
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
m_users.erase(user);
|
||||
m_handlers.erase(user);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
#ifndef __FreeBSD__
|
||||
#ifndef __MACH__
|
||||
// force returning of memory chunks allocated by libxml2 to kernel
|
||||
malloc_trim(0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void handleSwiftConnected(const std::string &user) {
|
||||
LOG4CXX_INFO(logger, user << ": Connected to XMPP server.");
|
||||
handleConnected(user);
|
||||
m_users[user]->requestRoster();
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setFrom(m_users[user]->getJID());
|
||||
m_users[user]->sendPresence(response);
|
||||
}
|
||||
|
||||
void handleSwiftRosterReceived(const std::string &user) {
|
||||
Swift::PresenceOracle *oracle = m_users[user]->getPresenceOracle();
|
||||
BOOST_FOREACH(const Swift::XMPPRosterItem &item, m_users[user]->getRoster()->getItems()) {
|
||||
Swift::Presence::ref lastPresence = oracle->getLastPresence(item.getJID());
|
||||
pbnetwork::StatusType status = lastPresence ? ((pbnetwork::StatusType) lastPresence->getShow()) : pbnetwork::STATUS_NONE;
|
||||
handleBuddyChanged(user, item.getJID().toBare().toString(),
|
||||
item.getName(), item.getGroups(), status);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) {
|
||||
// boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
// if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (presence->getPayload<Swift::MUCUserPayload>() != NULL || presence->getPayload<Swift::MUCPayload>() != NULL) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed");
|
||||
//
|
||||
// std::string message = presence->getStatus();
|
||||
// std::string photo = "";
|
||||
//
|
||||
// boost::shared_ptr<Swift::VCardUpdate> update = presence->getPayload<Swift::VCardUpdate>();
|
||||
// if (update) {
|
||||
// photo = update->getPhotoHash();
|
||||
// }
|
||||
//
|
||||
// boost::optional<Swift::XMPPRosterItem> item = m_users[user]->getRoster()->getItem(presence->getFrom());
|
||||
// if (item) {
|
||||
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo);
|
||||
// }
|
||||
// else {
|
||||
// std::vector<std::string> groups;
|
||||
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo);
|
||||
// }
|
||||
presence->setTo(user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(presence));
|
||||
sendRawXML(xml);
|
||||
}
|
||||
|
||||
void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) {
|
||||
message->setTo(user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(message));
|
||||
sendRawXML(xml);
|
||||
}
|
||||
|
||||
void handleSwiftenDataRead(const Swift::SafeByteArray &data) {
|
||||
std::string d = safeByteArrayToString(data);
|
||||
if (!boost::starts_with(d, "<auth")) {
|
||||
LOG4CXX_INFO(logger_xml, "XML IN " << d);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSwiftenDataWritten(const Swift::SafeByteArray &data) {
|
||||
LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
|
||||
}
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
LOG4CXX_INFO(logger, user << ": connecting as " << legacyName);
|
||||
boost::shared_ptr<Swift::Client> client = boost::make_shared<Swift::Client>(Swift::JID(legacyName + "/Spectrum"), password, m_factories);
|
||||
m_users[user] = client;
|
||||
client->setAlwaysTrustCertificates();
|
||||
client->onConnected.connect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
client->onDisconnected.connect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
|
||||
client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
|
||||
client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1));
|
||||
client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1));
|
||||
client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3));
|
||||
client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2));
|
||||
Swift::ClientOptions opt;
|
||||
opt.allowPLAINWithoutTLS = true;
|
||||
client->connect(opt);
|
||||
|
||||
boost::shared_ptr<ForwardIQHandler> handler = boost::make_shared<ForwardIQHandler>(this, user);
|
||||
client->getIQRouter()->addHandler(handler);
|
||||
m_handlers[user] = handler;
|
||||
}
|
||||
|
||||
void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) {
|
||||
handleSwiftPresenceChanged(user, presence);
|
||||
}
|
||||
|
||||
void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) {
|
||||
Swift::Presence::ref presence = Swift::Presence::create();
|
||||
presence->setTo(user);
|
||||
presence->setFrom(jid);
|
||||
presence->setType(Swift::Presence::Unsubscribe);
|
||||
handleSwiftPresenceChanged(user, presence);
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
// client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
|
||||
client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
|
||||
client->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") {
|
||||
}
|
||||
|
||||
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
|
||||
}
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << ".");
|
||||
if (!client->getRoster()->containsJID(buddyName) || client->getRoster()->getSubscriptionStateForJID(buddyName) != Swift::RosterItemPayload::Both) {
|
||||
Swift::RosterItemPayload item;
|
||||
item.setName(alias);
|
||||
item.setJID(buddyName);
|
||||
item.setGroups(groups);
|
||||
boost::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
client->getSubscriptionManager()->requestSubscription(buddyName);
|
||||
}
|
||||
else {
|
||||
Swift::JID contact(buddyName);
|
||||
Swift::RosterItemPayload item(contact, alias, client->getRoster()->getSubscriptionStateForJID(contact));
|
||||
item.setGroups(groups);
|
||||
boost::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
boost::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
Swift::RosterItemPayload item(buddyName, "", Swift::RosterItemPayload::Remove);
|
||||
boost::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
}
|
||||
}
|
||||
|
||||
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||
|
||||
}
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
Config *config;
|
||||
std::map<std::string, boost::shared_ptr<Swift::Client> > m_users;
|
||||
std::map<std::string, boost::shared_ptr<ForwardIQHandler> > m_handlers;
|
||||
};
|
||||
|
||||
#ifndef WIN32
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
#ifndef WIN32
|
||||
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
|
||||
std::cout << "SIGCHLD handler can't be set\n";
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logging::initBackendLogging(cfg);
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
loop_ = &eventLoop;
|
||||
np = new SwiftenPlugin(cfg, &eventLoop, host, port);
|
||||
loop_->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,14 @@ include_directories (${libtransport_SOURCE_DIR}/backends/twitter/libtwitcurl)
|
|||
FILE(GLOB SRC *.cpp libtwitcurl/*.cpp Requests/*.cpp)
|
||||
add_executable(spectrum2_twitter_backend ${SRC})
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(spectrum2_twitter_backend curl transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
else ()
|
||||
include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/curl/include")
|
||||
target_link_libraries(spectrum2_twitter_backend libcurl transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
find_package(curl)
|
||||
|
||||
if(CURL_FOUND)
|
||||
message(STATUS "Using curl ${CURL_VERSION_STRING}: ${CURL_INCLUDE_DIRS} ${CURL_LIBRARIES}")
|
||||
include_directories (${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(spectrum2_twitter_backend transport ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "curl not found")
|
||||
endif()
|
||||
|
||||
INSTALL(TARGETS spectrum2_twitter_backend RUNTIME DESTINATION bin)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,181 +1,189 @@
|
|||
#ifndef TWITTER_PLUGIN
|
||||
#define TWITTER_PLUGIN
|
||||
|
||||
#include "transport/config.h"
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/logging.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/mysqlbackend.h"
|
||||
#include "transport/pqxxbackend.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/threadpool.h"
|
||||
|
||||
#include "Swiften/Swiften.h"
|
||||
#ifndef _WIN32
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#endif
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/signal.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "twitcurl.h"
|
||||
#include "TwitterResponseParser.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <cstdio>
|
||||
|
||||
#include "Swiften/StringCodecs/SHA1.h"
|
||||
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
#define STR(x) (std::string("(") + x.from + ", " + x.to + ", " + x.message + ")")
|
||||
|
||||
class TwitterPlugin;
|
||||
extern TwitterPlugin *np;
|
||||
extern Swift::SimpleEventLoop *loop_; // Event Loop
|
||||
|
||||
|
||||
class TwitterPlugin : public NetworkPlugin {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
boost::shared_ptr<Swift::Connection> m_conn;
|
||||
Swift::Timer::ref tweet_timer;
|
||||
Swift::Timer::ref message_timer;
|
||||
StorageBackend *storagebackend;
|
||||
|
||||
TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port);
|
||||
~TwitterPlugin();
|
||||
|
||||
// Send data to NetworkPlugin server
|
||||
void sendData(const std::string &string);
|
||||
|
||||
// Receive date from the NetworkPlugin server and invoke the appropirate payload handler (implement in the NetworkPlugin class)
|
||||
void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data);
|
||||
|
||||
// User trying to login into his twitter account
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
|
||||
|
||||
// User logging out
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
|
||||
|
||||
void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/);
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/);
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "");
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups);
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
|
||||
|
||||
void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/);
|
||||
|
||||
void pollForTweets();
|
||||
|
||||
void pollForDirectMessages();
|
||||
|
||||
bool getUserOAuthKeyAndSecret(const std::string user, std::string &key, std::string &secret);
|
||||
|
||||
bool checkSpectrum1User(const std::string user);
|
||||
|
||||
bool storeUserOAuthKeyAndSecret(const std::string user, const std::string OAuthKey, const std::string OAuthSecret);
|
||||
|
||||
void initUserSession(const std::string user, const std::string legacyName, const std::string password);
|
||||
|
||||
void OAuthFlowComplete(const std::string user, twitCurl *obj);
|
||||
|
||||
void pinExchangeComplete(const std::string user, const std::string OAuthAccessTokenKey, const std::string OAuthAccessTokenSecret);
|
||||
|
||||
void updateLastTweetID(const std::string user, const std::string ID);
|
||||
|
||||
std::string getMostRecentTweetID(const std::string user);
|
||||
|
||||
void updateLastDMID(const std::string user, const std::string ID);
|
||||
|
||||
std::string getMostRecentDMID(const std::string user);
|
||||
|
||||
void clearRoster(const std::string user);
|
||||
|
||||
int getTwitterMode(const std::string user);
|
||||
|
||||
bool setTwitterMode(const std::string user, int m);
|
||||
|
||||
/****************** Twitter response handlers **************************************/
|
||||
void statusUpdateResponse(std::string &user, Error &errMsg);
|
||||
|
||||
void helpMessageResponse(std::string &user, std::string &msg);
|
||||
|
||||
void populateRoster(std::string &user, std::vector<User> &friends, std::vector<std::string> &friendAvatars, Error &errMsg);
|
||||
|
||||
void displayFriendlist(std::string &user, std::vector<User> &friends, std::vector<std::string> &friendAvatars, Error &errMsg);
|
||||
|
||||
void displayTweets(std::string &user, std::string &userRequested, std::vector<Status> &tweets , Error &errMsg);
|
||||
|
||||
void directMessageResponse(std::string &user, std::string &username, std::vector<DirectMessage> &messages, Error &errMsg);
|
||||
|
||||
void createFriendResponse(std::string &user, User &frnd, std::string &img, Error &errMsg);
|
||||
|
||||
void deleteFriendResponse(std::string &user, User &frnd, Error &errMsg);
|
||||
|
||||
void RetweetResponse(std::string &user, Error &errMsg);
|
||||
|
||||
void profileImageResponse(std::string &user, std::string &buddy, std::string &img, unsigned int reqID, Error &errMsg);
|
||||
/***********************************************************************************/
|
||||
|
||||
private:
|
||||
std::string getMostRecentTweetIDUnsafe(const std::string user);
|
||||
std::string getMostRecentDMIDUnsafe(const std::string user);
|
||||
|
||||
enum status {NEW, WAITING_FOR_PIN, CONNECTED, DISCONNECTED};
|
||||
enum mode {SINGLECONTACT, MULTIPLECONTACT, CHATROOM};
|
||||
|
||||
Config *config;
|
||||
std::string adminLegacyName;
|
||||
std::string adminChatRoom;
|
||||
std::string adminNickName;
|
||||
std::string adminAlias;
|
||||
|
||||
std::string consumerKey;
|
||||
std::string consumerSecret;
|
||||
std::string OAUTH_KEY;
|
||||
std::string OAUTH_SECRET;
|
||||
std::string MODE;
|
||||
|
||||
boost::mutex dblock, userlock;
|
||||
|
||||
ThreadPool *tp;
|
||||
std::set<std::string> onlineUsers;
|
||||
struct UserData
|
||||
{
|
||||
std::string legacyName;
|
||||
bool spectrum1User; //Legacy support
|
||||
User userTwitterObj;
|
||||
std::string userImg;
|
||||
twitCurl* sessions;
|
||||
status connectionState;
|
||||
std::string mostRecentTweetID;
|
||||
std::string mostRecentDirectMessageID;
|
||||
std::string nickName;
|
||||
std::set<std::string> buddies;
|
||||
std::map<std::string, User> buddiesInfo;
|
||||
std::map<std::string, std::string> buddiesImgs;
|
||||
mode twitterMode;
|
||||
|
||||
UserData() { sessions = NULL; }
|
||||
};
|
||||
std::map<std::string, UserData> userdb;
|
||||
bool m_firstPing;
|
||||
};
|
||||
#endif
|
||||
#ifndef TWITTER_PLUGIN
|
||||
#define TWITTER_PLUGIN
|
||||
|
||||
#include "transport/config.h"
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/logging.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/mysqlbackend.h"
|
||||
#include "transport/pqxxbackend.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/threadpool.h"
|
||||
|
||||
#include "Swiften/Swiften.h"
|
||||
#ifndef _WIN32
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#endif
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/signal.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "twitcurl.h"
|
||||
#include "TwitterResponseParser.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <cstdio>
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
#if HAVE_SWIFTEN_3
|
||||
#include <Swiften/Crypto/CryptoProvider.h>
|
||||
#include <Swiften/Crypto/PlatformCryptoProvider.h>
|
||||
#else
|
||||
#include "Swiften/StringCodecs/SHA1.h"
|
||||
#endif
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
#define STR(x) (std::string("(") + x.from + ", " + x.to + ", " + x.message + ")")
|
||||
|
||||
class TwitterPlugin;
|
||||
extern TwitterPlugin *np;
|
||||
extern Swift::SimpleEventLoop *loop_; // Event Loop
|
||||
|
||||
|
||||
class TwitterPlugin : public NetworkPlugin {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
boost::shared_ptr<Swift::Connection> m_conn;
|
||||
#if HAVE_SWIFTEN_3
|
||||
boost::shared_ptr<Swift::CryptoProvider> cryptoProvider;
|
||||
#endif
|
||||
Swift::Timer::ref tweet_timer;
|
||||
Swift::Timer::ref message_timer;
|
||||
StorageBackend *storagebackend;
|
||||
|
||||
TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port);
|
||||
~TwitterPlugin();
|
||||
|
||||
// Send data to NetworkPlugin server
|
||||
void sendData(const std::string &string);
|
||||
|
||||
// Receive date from the NetworkPlugin server and invoke the appropirate payload handler (implement in the NetworkPlugin class)
|
||||
void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data);
|
||||
|
||||
// User trying to login into his twitter account
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
|
||||
|
||||
// User logging out
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
|
||||
|
||||
void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/);
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/);
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "");
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups);
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
|
||||
|
||||
void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/);
|
||||
|
||||
void pollForTweets();
|
||||
|
||||
void pollForDirectMessages();
|
||||
|
||||
bool getUserOAuthKeyAndSecret(const std::string user, std::string &key, std::string &secret);
|
||||
|
||||
bool checkSpectrum1User(const std::string user);
|
||||
|
||||
bool storeUserOAuthKeyAndSecret(const std::string user, const std::string OAuthKey, const std::string OAuthSecret);
|
||||
|
||||
void initUserSession(const std::string user, const std::string legacyName, const std::string password);
|
||||
|
||||
void OAuthFlowComplete(const std::string user, twitCurl *obj);
|
||||
|
||||
void pinExchangeComplete(const std::string user, const std::string OAuthAccessTokenKey, const std::string OAuthAccessTokenSecret);
|
||||
|
||||
void updateLastTweetID(const std::string user, const std::string ID);
|
||||
|
||||
std::string getMostRecentTweetID(const std::string user);
|
||||
|
||||
void updateLastDMID(const std::string user, const std::string ID);
|
||||
|
||||
std::string getMostRecentDMID(const std::string user);
|
||||
|
||||
void clearRoster(const std::string user);
|
||||
|
||||
int getTwitterMode(const std::string user);
|
||||
|
||||
bool setTwitterMode(const std::string user, int m);
|
||||
|
||||
/****************** Twitter response handlers **************************************/
|
||||
void statusUpdateResponse(std::string &user, Error &errMsg);
|
||||
|
||||
void helpMessageResponse(std::string &user, std::string &msg);
|
||||
|
||||
void populateRoster(std::string &user, std::vector<User> &friends, std::vector<std::string> &friendAvatars, Error &errMsg);
|
||||
|
||||
void displayFriendlist(std::string &user, std::vector<User> &friends, std::vector<std::string> &friendAvatars, Error &errMsg);
|
||||
|
||||
void displayTweets(std::string &user, std::string &userRequested, std::vector<Status> &tweets , Error &errMsg);
|
||||
|
||||
void directMessageResponse(std::string &user, std::string &username, std::vector<DirectMessage> &messages, Error &errMsg);
|
||||
|
||||
void createFriendResponse(std::string &user, User &frnd, std::string &img, Error &errMsg);
|
||||
|
||||
void deleteFriendResponse(std::string &user, User &frnd, Error &errMsg);
|
||||
|
||||
void RetweetResponse(std::string &user, Error &errMsg);
|
||||
|
||||
void profileImageResponse(std::string &user, std::string &buddy, std::string &img, unsigned int reqID, Error &errMsg);
|
||||
/***********************************************************************************/
|
||||
|
||||
private:
|
||||
std::string getMostRecentTweetIDUnsafe(const std::string user);
|
||||
std::string getMostRecentDMIDUnsafe(const std::string user);
|
||||
|
||||
enum status {NEW, WAITING_FOR_PIN, CONNECTED, DISCONNECTED};
|
||||
enum mode {SINGLECONTACT, MULTIPLECONTACT, CHATROOM};
|
||||
|
||||
Config *config;
|
||||
std::string adminLegacyName;
|
||||
std::string adminChatRoom;
|
||||
std::string adminNickName;
|
||||
std::string adminAlias;
|
||||
|
||||
std::string consumerKey;
|
||||
std::string consumerSecret;
|
||||
std::string OAUTH_KEY;
|
||||
std::string OAUTH_SECRET;
|
||||
std::string MODE;
|
||||
|
||||
boost::mutex dblock, userlock;
|
||||
|
||||
ThreadPool *tp;
|
||||
std::set<std::string> onlineUsers;
|
||||
struct UserData
|
||||
{
|
||||
std::string legacyName;
|
||||
bool spectrum1User; //Legacy support
|
||||
User userTwitterObj;
|
||||
std::string userImg;
|
||||
twitCurl* sessions;
|
||||
status connectionState;
|
||||
std::string mostRecentTweetID;
|
||||
std::string mostRecentDirectMessageID;
|
||||
std::string nickName;
|
||||
std::set<std::string> buddies;
|
||||
std::map<std::string, User> buddiesInfo;
|
||||
std::map<std::string, std::string> buddiesImgs;
|
||||
mode twitterMode;
|
||||
|
||||
UserData() { sessions = NULL; }
|
||||
};
|
||||
std::map<std::string, UserData> userdb;
|
||||
bool m_firstPing;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#define NOMINMAX
|
||||
#include <algorithm>
|
||||
#include <memory.h>
|
||||
#include "twitcurlurls.h"
|
||||
#include "twitcurl.h"
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
FIND_LIBRARY(SWIFTEN_LIBRARY NAMES Swiften HINTS ../lib)
|
||||
FIND_PATH(SWIFTEN_INCLUDE_DIR NAMES "Swiften/Swiften.h" PATH_SUFFIXES libSwiften Swiften HINTS ../include)
|
||||
|
||||
if( SWIFTEN_LIBRARY AND SWIFTEN_INCLUDE_DIR )
|
||||
find_program(SWIFTEN_CONFIG_EXECUTABLE NAMES swiften-config DOC "swiften-config executable" HINTS ../bin)
|
||||
set( SWIFTEN_CFLAGS "" )
|
||||
if (SWIFTEN_CONFIG_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${SWIFTEN_CONFIG_EXECUTABLE} --libs
|
||||
OUTPUT_VARIABLE SWIFTEN_LIB)
|
||||
string(REGEX REPLACE "[\r\n]" " " SWIFTEN_LIB ${SWIFTEN_LIB})
|
||||
string(REGEX REPLACE " +$" "" SWIFTEN_LIB ${SWIFTEN_LIB})
|
||||
string(REGEX REPLACE " " ";" SWIFTEN_LIB ${SWIFTEN_LIB})
|
||||
set(SWIFTEN_LIBRARY "")
|
||||
foreach(f ${SWIFTEN_LIB})
|
||||
STRING(SUBSTRING ${f} 0 2 f_out)
|
||||
STRING(COMPARE EQUAL ${f_out} "/L" IS_PATH)
|
||||
if(${IS_PATH})
|
||||
string(REGEX REPLACE "/LIBPATH:" "" f_replaced "${f}")
|
||||
message("Added link directory: ${f_replaced}")
|
||||
link_directories(${f_replaced})
|
||||
else()
|
||||
list(APPEND SWIFTEN_LIBRARY ${f})
|
||||
endif()
|
||||
endforeach(f)
|
||||
set( SWIFTEN_FOUND 1 )
|
||||
else()
|
||||
message( STATUS "Could NOT find swiften-config" )
|
||||
endif()
|
||||
|
||||
if (SWIFTEN_FOUND)
|
||||
set( SWIFTEN_INCLUDE_DIR ${SWIFTEN_INCLUDE_DIR} )
|
||||
message( STATUS "Found libSwiften: ${SWIFTEN_LIBRARY}, ${SWIFTEN_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
else( SWIFTEN_LIBRARY AND SWIFTEN_INCLUDE_DIR )
|
||||
message( STATUS "Could NOT find libSwiften" )
|
||||
endif( SWIFTEN_LIBRARY AND SWIFTEN_INCLUDE_DIR )
|
||||
FIND_LIBRARY(SWIFTEN_LIBRARY NAMES Swiften Swiften3 HINTS ../lib)
|
||||
FIND_PATH(SWIFTEN_INCLUDE_DIR NAMES "Swiften/Swiften.h" PATH_SUFFIXES libSwiften Swiften HINTS ../include)
|
||||
|
||||
if( SWIFTEN_LIBRARY AND SWIFTEN_INCLUDE_DIR )
|
||||
find_program(SWIFTEN_CONFIG_EXECUTABLE NAMES swiften-config DOC "swiften-config executable" HINTS ../bin)
|
||||
set( SWIFTEN_CFLAGS "" )
|
||||
if (SWIFTEN_CONFIG_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${SWIFTEN_CONFIG_EXECUTABLE} --libs
|
||||
OUTPUT_VARIABLE SWIFTEN_LIB)
|
||||
string(REGEX REPLACE "[\r\n]" " " SWIFTEN_LIB ${SWIFTEN_LIB})
|
||||
string(REGEX REPLACE " +$" "" SWIFTEN_LIB ${SWIFTEN_LIB})
|
||||
string(REGEX REPLACE " " ";" SWIFTEN_LIB ${SWIFTEN_LIB})
|
||||
set(SWIFTEN_LIBRARY "")
|
||||
foreach(f ${SWIFTEN_LIB})
|
||||
STRING(SUBSTRING ${f} 0 2 f_out)
|
||||
STRING(COMPARE EQUAL ${f_out} "/L" IS_PATH)
|
||||
if(${IS_PATH})
|
||||
string(REGEX REPLACE "/LIBPATH:" "" f_replaced "${f}")
|
||||
message("Added link directory: ${f_replaced}")
|
||||
link_directories(${f_replaced})
|
||||
else()
|
||||
list(APPEND SWIFTEN_LIBRARY ${f})
|
||||
endif()
|
||||
endforeach(f)
|
||||
set( SWIFTEN_FOUND 1 )
|
||||
else()
|
||||
message( STATUS "Could NOT find swiften-config" )
|
||||
endif()
|
||||
|
||||
if (SWIFTEN_FOUND)
|
||||
set( SWIFTEN_INCLUDE_DIR ${SWIFTEN_INCLUDE_DIR} )
|
||||
message( STATUS "Found libSwiften: ${SWIFTEN_LIBRARY}, ${SWIFTEN_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
else( SWIFTEN_LIBRARY AND SWIFTEN_INCLUDE_DIR )
|
||||
message( STATUS "Could NOT find libSwiften" )
|
||||
endif( SWIFTEN_LIBRARY AND SWIFTEN_INCLUDE_DIR )
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Elements/PubSubItem.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubItem::PubSubItem() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Elements/Payload.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubItem : public Payload {
|
||||
public:
|
||||
PubSubItem();
|
||||
|
||||
void addPayload(boost::shared_ptr<Payload> payload) {
|
||||
payloads.push_back(payload);
|
||||
}
|
||||
|
||||
const std::vector<boost::shared_ptr<Payload> > getPayloads() const {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const std::vector<boost::shared_ptr<T> > getPayloads() const {
|
||||
std::vector<boost::shared_ptr<T> > matched_payloads;
|
||||
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
|
||||
boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i);
|
||||
if (result) {
|
||||
matched_payloads.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
return matched_payloads;
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const boost::shared_ptr<T> getPayload() const {
|
||||
boost::shared_ptr<T> result;
|
||||
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
|
||||
result = boost::dynamic_pointer_cast<T>(*i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string& getId() const { return id; }
|
||||
|
||||
void setId(const std::string& id) {
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<boost::shared_ptr<Payload> > payloads;
|
||||
std::string id;
|
||||
};
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Elements/PubSubPayload.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubPayload::PubSubPayload() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Elements/Payload.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubPayload : public Payload {
|
||||
public:
|
||||
PubSubPayload();
|
||||
|
||||
void addPayload(boost::shared_ptr<Payload> payload) {
|
||||
payloads.push_back(payload);
|
||||
}
|
||||
|
||||
const std::vector<boost::shared_ptr<Payload> > getPayloads() const {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const std::vector<boost::shared_ptr<T> > getPayloads() const {
|
||||
std::vector<boost::shared_ptr<T> > matched_payloads;
|
||||
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
|
||||
boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i);
|
||||
if (result) {
|
||||
matched_payloads.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
return matched_payloads;
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const boost::shared_ptr<T> getPayload() const {
|
||||
boost::shared_ptr<T> result;
|
||||
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
|
||||
result = boost::dynamic_pointer_cast<T>(*i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<boost::shared_ptr<Payload> > payloads;
|
||||
};
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Elements/PubSubPublishPayload.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubPublishPayload::PubSubPublishPayload(const std::string &node) :
|
||||
node(node) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Elements/Payload.h>
|
||||
#include <Swiften/Elements/PubSubItem.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubPublishPayload : public Payload {
|
||||
public:
|
||||
enum Type { None, Pending, Subscribed, Unconfigured };
|
||||
|
||||
PubSubPublishPayload(const std::string &node = "");
|
||||
|
||||
void setNode(const std::string &node) {
|
||||
this->node = node;
|
||||
}
|
||||
|
||||
const std::string &getNode() const {
|
||||
return node;
|
||||
}
|
||||
|
||||
void addItem(const boost::shared_ptr<Payload> &item) {
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
const std::vector<boost::shared_ptr<Payload> > &getItems() const {
|
||||
return items;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string node;
|
||||
std::vector<boost::shared_ptr<Payload> > items;
|
||||
};
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Elements/PubSubSubscribePayload.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubSubscribePayload::PubSubSubscribePayload(const JID &jid, const std::string &node) :
|
||||
jid(jid), node(node) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Elements/Payload.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubSubscribePayload : public Payload {
|
||||
public:
|
||||
PubSubSubscribePayload(const JID &jid = JID(), const std::string &node = "");
|
||||
|
||||
void setJID(const JID &jid) {
|
||||
this->jid = jid;
|
||||
}
|
||||
|
||||
const JID &getJID() const {
|
||||
return jid;
|
||||
}
|
||||
|
||||
void setNode(const std::string &node) {
|
||||
this->node = node;
|
||||
}
|
||||
|
||||
const std::string &getNode() const {
|
||||
return node;
|
||||
}
|
||||
|
||||
private:
|
||||
JID jid;
|
||||
std::string node;
|
||||
};
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Elements/PubSubSubscriptionPayload.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubSubscriptionPayload::PubSubSubscriptionPayload(const JID &jid, const std::string &node) :
|
||||
jid(jid), node(node), type(None) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Elements/Payload.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubSubscriptionPayload : public Payload {
|
||||
public:
|
||||
enum Type { None, Pending, Subscribed, Unconfigured };
|
||||
|
||||
PubSubSubscriptionPayload(const JID &jid = JID(), const std::string &node = "");
|
||||
|
||||
void setJID(const JID &jid) {
|
||||
this->jid = jid;
|
||||
}
|
||||
|
||||
const JID &getJID() const {
|
||||
return jid;
|
||||
}
|
||||
|
||||
void setNode(const std::string &node) {
|
||||
this->node = node;
|
||||
}
|
||||
|
||||
const std::string &getNode() const {
|
||||
return node;
|
||||
}
|
||||
|
||||
void setId(const std::string &id) {
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
const std::string &getId() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
void setType(const Type &type) {
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
const Type &getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
JID jid;
|
||||
std::string node;
|
||||
std::string id;
|
||||
Type type;
|
||||
};
|
||||
}
|
|
@ -1,108 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Tobias Markmann
|
||||
* Licensed under the simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include "CombinedOutgoingFileTransferManager.h"
|
||||
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
#include <Swiften/JID/JID.h>
|
||||
#include "Swiften/Disco/EntityCapsProvider.h"
|
||||
#include <Swiften/Jingle/JingleSessionManager.h>
|
||||
#include <Swiften/Jingle/JingleSessionImpl.h>
|
||||
#include <Swiften/Jingle/JingleContentID.h>
|
||||
#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h>
|
||||
#include <Swiften/FileTransfer/MyOutgoingSIFileTransfer.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/Base/IDGenerator.h>
|
||||
#include <Swiften/Elements/Presence.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
|
||||
|
||||
namespace Swift {
|
||||
|
||||
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
|
||||
idGenerator = new IDGenerator();
|
||||
}
|
||||
|
||||
CombinedOutgoingFileTransferManager::~CombinedOutgoingFileTransferManager() {
|
||||
delete idGenerator;
|
||||
}
|
||||
|
||||
boost::shared_ptr<OutgoingFileTransfer> CombinedOutgoingFileTransferManager::createOutgoingFileTransfer(const JID& from, const JID& receipient, boost::shared_ptr<ReadBytestream> readBytestream, const StreamInitiationFileInfo& fileInfo) {
|
||||
// check if receipient support Jingle FT
|
||||
boost::optional<JID> fullJID = highestPriorityJIDSupportingJingle(receipient);
|
||||
if (!fullJID.is_initialized()) {
|
||||
fullJID = highestPriorityJIDSupportingSI(receipient);
|
||||
}
|
||||
else {
|
||||
JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>(from, receipient, idGenerator->generateID(), iqRouter);
|
||||
|
||||
//jsManager->getSession(receipient, idGenerator->generateID());
|
||||
assert(jingleSession);
|
||||
jsManager->registerOutgoingSession(from, jingleSession);
|
||||
boost::shared_ptr<OutgoingJingleFileTransfer> jingleFT = boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy));
|
||||
return jingleFT;
|
||||
}
|
||||
|
||||
if (!fullJID.is_initialized()) {
|
||||
return boost::shared_ptr<OutgoingFileTransfer>();
|
||||
}
|
||||
|
||||
// otherwise try SI
|
||||
boost::shared_ptr<MyOutgoingSIFileTransfer> jingleFT = boost::shared_ptr<MyOutgoingSIFileTransfer>(new MyOutgoingSIFileTransfer(idGenerator->generateID(), from, fullJID.get(), fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription(), readBytestream, iqRouter, bytestreamServer, bytestreamRegistry));
|
||||
// else fail
|
||||
|
||||
return jingleFT;
|
||||
}
|
||||
|
||||
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingJingle(const JID& bareJID) {
|
||||
JID fullReceipientJID;
|
||||
int priority = INT_MIN;
|
||||
|
||||
//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
|
||||
std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
|
||||
|
||||
//iterate over them
|
||||
foreach(Presence::ref pres, presences) {
|
||||
if (pres->getPriority() > priority) {
|
||||
// look up caps from the jid
|
||||
DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
|
||||
if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) &&
|
||||
info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
|
||||
|
||||
priority = pres->getPriority();
|
||||
fullReceipientJID = pres->getFrom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
|
||||
}
|
||||
|
||||
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingSI(const JID& bareJID) {
|
||||
JID fullReceipientJID;
|
||||
int priority = INT_MIN;
|
||||
|
||||
//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
|
||||
std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
|
||||
|
||||
//iterate over them
|
||||
foreach(Presence::ref pres, presences) {
|
||||
if (pres->getPriority() > priority) {
|
||||
// look up caps from the jid
|
||||
DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
|
||||
if (info && info->hasFeature("http://jabber.org/protocol/si/profile/file-transfer")) {
|
||||
|
||||
priority = pres->getPriority();
|
||||
fullReceipientJID = pres->getFrom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2011 Tobias Markmann
|
||||
* Licensed under the simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include "CombinedOutgoingFileTransferManager.h"
|
||||
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
#include <Swiften/JID/JID.h>
|
||||
#include "Swiften/Disco/EntityCapsProvider.h"
|
||||
#include <Swiften/Jingle/JingleSessionManager.h>
|
||||
#include <Swiften/Jingle/JingleSessionImpl.h>
|
||||
#include <Swiften/Jingle/JingleContentID.h>
|
||||
#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h>
|
||||
#include <Swiften/FileTransfer/MyOutgoingSIFileTransfer.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/Base/IDGenerator.h>
|
||||
#include <Swiften/Elements/Presence.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
|
||||
|
||||
namespace Swift {
|
||||
|
||||
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
|
||||
idGenerator = new IDGenerator();
|
||||
}
|
||||
|
||||
CombinedOutgoingFileTransferManager::~CombinedOutgoingFileTransferManager() {
|
||||
delete idGenerator;
|
||||
}
|
||||
|
||||
boost::shared_ptr<OutgoingFileTransfer> CombinedOutgoingFileTransferManager::createOutgoingFileTransfer(const JID& from, const JID& receipient, boost::shared_ptr<ReadBytestream> readBytestream, const StreamInitiationFileInfo& fileInfo) {
|
||||
// check if receipient support Jingle FT
|
||||
boost::optional<JID> fullJID = highestPriorityJIDSupportingJingle(receipient);
|
||||
if (!fullJID.is_initialized()) {
|
||||
fullJID = highestPriorityJIDSupportingSI(receipient);
|
||||
}
|
||||
else {
|
||||
JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>(from, receipient, idGenerator->generateID(), iqRouter);
|
||||
|
||||
//jsManager->getSession(receipient, idGenerator->generateID());
|
||||
assert(jingleSession);
|
||||
jsManager->registerOutgoingSession(from, jingleSession);
|
||||
#if !HAVE_SWIFTEN_3
|
||||
boost::shared_ptr<OutgoingJingleFileTransfer> jingleFT = boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy));
|
||||
return jingleFT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!fullJID.is_initialized()) {
|
||||
return boost::shared_ptr<OutgoingFileTransfer>();
|
||||
}
|
||||
|
||||
// otherwise try SI
|
||||
boost::shared_ptr<MyOutgoingSIFileTransfer> jingleFT = boost::shared_ptr<MyOutgoingSIFileTransfer>(new MyOutgoingSIFileTransfer(idGenerator->generateID(), from, fullJID.get(), fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription(), readBytestream, iqRouter, bytestreamServer, bytestreamRegistry));
|
||||
// else fail
|
||||
|
||||
return jingleFT;
|
||||
}
|
||||
|
||||
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingJingle(const JID& bareJID) {
|
||||
JID fullReceipientJID;
|
||||
int priority = INT_MIN;
|
||||
|
||||
//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
|
||||
std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
|
||||
|
||||
//iterate over them
|
||||
foreach(Presence::ref pres, presences) {
|
||||
if (pres->getPriority() > priority) {
|
||||
// look up caps from the jid
|
||||
DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
|
||||
if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) &&
|
||||
info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
|
||||
|
||||
priority = pres->getPriority();
|
||||
fullReceipientJID = pres->getFrom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
|
||||
}
|
||||
|
||||
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingSI(const JID& bareJID) {
|
||||
JID fullReceipientJID;
|
||||
int priority = INT_MIN;
|
||||
|
||||
//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
|
||||
std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
|
||||
|
||||
//iterate over them
|
||||
foreach(Presence::ref pres, presences) {
|
||||
if (pres->getPriority() > priority) {
|
||||
// look up caps from the jid
|
||||
DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
|
||||
if (info && info->hasFeature("http://jabber.org/protocol/si/profile/file-transfer")) {
|
||||
|
||||
priority = pres->getPriority();
|
||||
fullReceipientJID = pres->getFrom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,55 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Tobias Markmann
|
||||
* Licensed under the simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
#include "transport/presenceoracle.h"
|
||||
|
||||
namespace Swift {
|
||||
|
||||
class JingleSessionManager;
|
||||
class IQRouter;
|
||||
class EntityCapsProvider;
|
||||
class RemoteJingleTransportCandidateSelectorFactory;
|
||||
class LocalJingleTransportCandidateGeneratorFactory;
|
||||
class OutgoingFileTransfer;
|
||||
class JID;
|
||||
class IDGenerator;
|
||||
class ReadBytestream;
|
||||
class StreamInitiationFileInfo;
|
||||
class SOCKS5BytestreamRegistry;
|
||||
class SOCKS5BytestreamProxy;
|
||||
class SOCKS5BytestreamServer;
|
||||
class PresenceOracle;
|
||||
|
||||
class CombinedOutgoingFileTransferManager {
|
||||
public:
|
||||
CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle* presOracle, SOCKS5BytestreamServer *server);
|
||||
~CombinedOutgoingFileTransferManager();
|
||||
|
||||
boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr<ReadBytestream>, const StreamInitiationFileInfo&);
|
||||
|
||||
private:
|
||||
boost::optional<JID> highestPriorityJIDSupportingJingle(const JID& bareJID);
|
||||
boost::optional<JID> highestPriorityJIDSupportingSI(const JID& bareJID);
|
||||
JingleSessionManager* jsManager;
|
||||
IQRouter* iqRouter;
|
||||
EntityCapsProvider* capsProvider;
|
||||
RemoteJingleTransportCandidateSelectorFactory* remoteFactory;
|
||||
LocalJingleTransportCandidateGeneratorFactory* localFactory;
|
||||
IDGenerator *idGenerator;
|
||||
SOCKS5BytestreamRegistry* bytestreamRegistry;
|
||||
SOCKS5BytestreamProxy* bytestreamProxy;
|
||||
Transport::PresenceOracle* presenceOracle;
|
||||
SOCKS5BytestreamServer *bytestreamServer;
|
||||
};
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2011 Tobias Markmann
|
||||
* Licensed under the simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
#include "transport/presenceoracle.h"
|
||||
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
namespace Swift {
|
||||
|
||||
class JingleSessionManager;
|
||||
class IQRouter;
|
||||
class EntityCapsProvider;
|
||||
class RemoteJingleTransportCandidateSelectorFactory;
|
||||
class LocalJingleTransportCandidateGeneratorFactory;
|
||||
class OutgoingFileTransfer;
|
||||
class JID;
|
||||
class IDGenerator;
|
||||
class ReadBytestream;
|
||||
class StreamInitiationFileInfo;
|
||||
class SOCKS5BytestreamRegistry;
|
||||
class SOCKS5BytestreamProxy;
|
||||
class SOCKS5BytestreamServer;
|
||||
class PresenceOracle;
|
||||
|
||||
class CombinedOutgoingFileTransferManager {
|
||||
public:
|
||||
CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle* presOracle, SOCKS5BytestreamServer *server);
|
||||
~CombinedOutgoingFileTransferManager();
|
||||
|
||||
boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr<ReadBytestream>, const StreamInitiationFileInfo&);
|
||||
|
||||
private:
|
||||
boost::optional<JID> highestPriorityJIDSupportingJingle(const JID& bareJID);
|
||||
boost::optional<JID> highestPriorityJIDSupportingSI(const JID& bareJID);
|
||||
JingleSessionManager* jsManager;
|
||||
IQRouter* iqRouter;
|
||||
EntityCapsProvider* capsProvider;
|
||||
RemoteJingleTransportCandidateSelectorFactory* remoteFactory;
|
||||
LocalJingleTransportCandidateGeneratorFactory* localFactory;
|
||||
IDGenerator *idGenerator;
|
||||
SOCKS5BytestreamRegistry* bytestreamRegistry;
|
||||
SOCKS5BytestreamProxy* bytestreamProxy;
|
||||
Transport::PresenceOracle* presenceOracle;
|
||||
SOCKS5BytestreamServer *bytestreamServer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,111 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/FileTransfer/MyOutgoingSIFileTransfer.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <Swiften/FileTransfer/StreamInitiationRequest.h>
|
||||
#include <Swiften/FileTransfer/BytestreamsRequest.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
|
||||
#include <Swiften/FileTransfer/IBBSendSession.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
MyOutgoingSIFileTransfer::MyOutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer, SOCKS5BytestreamRegistry* registry) : id(id), from(from), to(to), name(name), size(size), description(description), bytestream(bytestream), iqRouter(iqRouter), socksServer(socksServer), registry(registry) {
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::start() {
|
||||
StreamInitiation::ref streamInitiation(new StreamInitiation());
|
||||
streamInitiation->setID(id);
|
||||
streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size));
|
||||
streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams");
|
||||
streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb");
|
||||
StreamInitiationRequest::ref request = StreamInitiationRequest::create(from, to, streamInitiation, iqRouter);
|
||||
request->onResponse.connect(boost::bind(&MyOutgoingSIFileTransfer::handleStreamInitiationRequestResponse, this, _1, _2));
|
||||
request->send();
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::stop() {
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::cancel() {
|
||||
// TODO
|
||||
// session->sendTerminate(JinglePayload::Reason::Cancel);
|
||||
|
||||
if (ibbSession) {
|
||||
ibbSession->stop();
|
||||
}
|
||||
SOCKS5BytestreamServerSession *serverSession = registry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(id, from, to));
|
||||
if (serverSession) {
|
||||
serverSession->stop();
|
||||
}
|
||||
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Canceled));
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::handleStreamInitiationRequestResponse(StreamInitiation::ref response, ErrorPayload::ref error) {
|
||||
if (error) {
|
||||
finish(FileTransferError());
|
||||
}
|
||||
else {
|
||||
if (response->getRequestedMethod() == "http://jabber.org/protocol/bytestreams") {
|
||||
registry->addReadBytestream(SOCKS5BytestreamRegistry::getHostname(id, from, to), bytestream);
|
||||
socksServer->addReadBytestream(id, from, to, bytestream);
|
||||
Bytestreams::ref bytestreams(new Bytestreams());
|
||||
bytestreams->setStreamID(id);
|
||||
HostAddressPort addressPort = socksServer->getAddressPort();
|
||||
bytestreams->addStreamHost(Bytestreams::StreamHost(addressPort.getAddress().toString(), from, addressPort.getPort()));
|
||||
BytestreamsRequest::ref request = BytestreamsRequest::create(from, to, bytestreams, iqRouter);
|
||||
request->onResponse.connect(boost::bind(&MyOutgoingSIFileTransfer::handleBytestreamsRequestResponse, this, _1, _2));
|
||||
request->send();
|
||||
}
|
||||
else if (response->getRequestedMethod() == "http://jabber.org/protocol/ibb") {
|
||||
ibbSession = boost::shared_ptr<IBBSendSession>(new IBBSendSession(id, from, to, bytestream, iqRouter));
|
||||
ibbSession->onFinished.connect(boost::bind(&MyOutgoingSIFileTransfer::handleIBBSessionFinished, this, _1));
|
||||
ibbSession->start();
|
||||
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Transferring));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref error) {
|
||||
if (error) {
|
||||
finish(FileTransferError());
|
||||
return;
|
||||
}
|
||||
|
||||
SOCKS5BytestreamServerSession *serverSession = registry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(id, from, to));
|
||||
// serverSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1));
|
||||
// serverSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1));
|
||||
serverSession->startTransfer();
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Transferring));
|
||||
|
||||
//socksServer->onTransferFinished.connect();
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::finish(boost::optional<FileTransferError> error) {
|
||||
if (ibbSession) {
|
||||
ibbSession->onFinished.disconnect(boost::bind(&MyOutgoingSIFileTransfer::handleIBBSessionFinished, this, _1));
|
||||
ibbSession.reset();
|
||||
}
|
||||
socksServer->removeReadBytestream(id, from, to);
|
||||
if(error) {
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Canceled));
|
||||
}
|
||||
else {
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Finished));
|
||||
}
|
||||
onFinished(error);
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::handleIBBSessionFinished(boost::optional<FileTransferError> error) {
|
||||
finish(error);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/FileTransfer/MyOutgoingSIFileTransfer.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <Swiften/FileTransfer/StreamInitiationRequest.h>
|
||||
#include <Swiften/FileTransfer/BytestreamsRequest.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
|
||||
#include <Swiften/FileTransfer/IBBSendSession.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
MyOutgoingSIFileTransfer::MyOutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer, SOCKS5BytestreamRegistry* registry) : id(id), from(from), to(to), name(name), size(size), description(description), bytestream(bytestream), iqRouter(iqRouter), socksServer(socksServer), registry(registry) {
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::start() {
|
||||
StreamInitiation::ref streamInitiation(new StreamInitiation());
|
||||
streamInitiation->setID(id);
|
||||
streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size));
|
||||
streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams");
|
||||
streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb");
|
||||
StreamInitiationRequest::ref request = StreamInitiationRequest::create(from, to, streamInitiation, iqRouter);
|
||||
request->onResponse.connect(boost::bind(&MyOutgoingSIFileTransfer::handleStreamInitiationRequestResponse, this, _1, _2));
|
||||
request->send();
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::stop() {
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::cancel() {
|
||||
// TODO
|
||||
// session->sendTerminate(JinglePayload::Reason::Cancel);
|
||||
|
||||
if (ibbSession) {
|
||||
ibbSession->stop();
|
||||
}
|
||||
#if !HAVE_SWIFTEN_3
|
||||
SOCKS5BytestreamServerSession *serverSession = registry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(id, from, to));
|
||||
if (serverSession) {
|
||||
serverSession->stop();
|
||||
}
|
||||
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Canceled));
|
||||
#endif
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::handleStreamInitiationRequestResponse(StreamInitiation::ref response, ErrorPayload::ref error) {
|
||||
if (error) {
|
||||
finish(FileTransferError());
|
||||
}
|
||||
else {
|
||||
if (response->getRequestedMethod() == "http://jabber.org/protocol/bytestreams") {
|
||||
#if !HAVE_SWIFTEN_3
|
||||
registry->addReadBytestream(SOCKS5BytestreamRegistry::getHostname(id, from, to), bytestream);
|
||||
socksServer->addReadBytestream(id, from, to, bytestream);
|
||||
#endif
|
||||
Bytestreams::ref bytestreams(new Bytestreams());
|
||||
bytestreams->setStreamID(id);
|
||||
HostAddressPort addressPort = socksServer->getAddressPort();
|
||||
bytestreams->addStreamHost(Bytestreams::StreamHost(addressPort.getAddress().toString(), from, addressPort.getPort()));
|
||||
BytestreamsRequest::ref request = BytestreamsRequest::create(from, to, bytestreams, iqRouter);
|
||||
request->onResponse.connect(boost::bind(&MyOutgoingSIFileTransfer::handleBytestreamsRequestResponse, this, _1, _2));
|
||||
request->send();
|
||||
}
|
||||
else if (response->getRequestedMethod() == "http://jabber.org/protocol/ibb") {
|
||||
ibbSession = boost::shared_ptr<IBBSendSession>(new IBBSendSession(id, from, to, bytestream, iqRouter));
|
||||
ibbSession->onFinished.connect(boost::bind(&MyOutgoingSIFileTransfer::handleIBBSessionFinished, this, _1));
|
||||
ibbSession->start();
|
||||
#if !HAVE_SWIFTEN_3
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Transferring));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref error) {
|
||||
if (error) {
|
||||
finish(FileTransferError());
|
||||
return;
|
||||
}
|
||||
#if !HAVE_SWIFTEN_3
|
||||
SOCKS5BytestreamServerSession *serverSession = registry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(id, from, to));
|
||||
// serverSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1));
|
||||
// serverSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1));
|
||||
serverSession->startTransfer();
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Transferring));
|
||||
#endif
|
||||
//socksServer->onTransferFinished.connect();
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::finish(boost::optional<FileTransferError> error) {
|
||||
if (ibbSession) {
|
||||
ibbSession->onFinished.disconnect(boost::bind(&MyOutgoingSIFileTransfer::handleIBBSessionFinished, this, _1));
|
||||
ibbSession.reset();
|
||||
}
|
||||
#if !HAVE_SWIFTEN_3
|
||||
socksServer->removeReadBytestream(id, from, to);
|
||||
if(error) {
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Canceled));
|
||||
}
|
||||
else {
|
||||
onStateChange(FileTransfer::State(FileTransfer::State::Finished));
|
||||
}
|
||||
#endif
|
||||
onFinished(error);
|
||||
}
|
||||
|
||||
void MyOutgoingSIFileTransfer::handleIBBSessionFinished(boost::optional<FileTransferError> error) {
|
||||
finish(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,56 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
|
||||
#include <Swiften/FileTransfer/ReadBytestream.h>
|
||||
#include <Swiften/Base/boost_bsignals.h>
|
||||
#include <Swiften/FileTransfer/FileTransferError.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
#include <Swiften/Elements/StreamInitiation.h>
|
||||
#include <Swiften/Elements/Bytestreams.h>
|
||||
#include <Swiften/Elements/ErrorPayload.h>
|
||||
#include <Swiften/FileTransfer/IBBSendSession.h>
|
||||
|
||||
namespace Swift {
|
||||
class IQRouter;
|
||||
class SOCKS5BytestreamServer;
|
||||
class SOCKS5BytestreamRegistry;
|
||||
|
||||
class MyOutgoingSIFileTransfer : public OutgoingFileTransfer {
|
||||
public:
|
||||
MyOutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer, SOCKS5BytestreamRegistry* registry);
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void cancel();
|
||||
|
||||
boost::signal<void (const boost::optional<FileTransferError>&)> onFinished;
|
||||
|
||||
private:
|
||||
void handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref);
|
||||
void handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref);
|
||||
void finish(boost::optional<FileTransferError> error);
|
||||
void handleIBBSessionFinished(boost::optional<FileTransferError> error);
|
||||
|
||||
private:
|
||||
std::string id;
|
||||
JID from;
|
||||
JID to;
|
||||
std::string name;
|
||||
int size;
|
||||
std::string description;
|
||||
boost::shared_ptr<ReadBytestream> bytestream;
|
||||
IQRouter* iqRouter;
|
||||
SOCKS5BytestreamServer* socksServer;
|
||||
boost::shared_ptr<IBBSendSession> ibbSession;
|
||||
SOCKS5BytestreamRegistry *registry;
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
|
||||
#include <Swiften/FileTransfer/ReadBytestream.h>
|
||||
#include <Swiften/Base/boost_bsignals.h>
|
||||
#include <Swiften/FileTransfer/FileTransferError.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
#include <Swiften/Elements/StreamInitiation.h>
|
||||
#include <Swiften/Elements/Bytestreams.h>
|
||||
#include <Swiften/Elements/ErrorPayload.h>
|
||||
#include <Swiften/FileTransfer/IBBSendSession.h>
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
namespace Swift {
|
||||
class IQRouter;
|
||||
class SOCKS5BytestreamServer;
|
||||
class SOCKS5BytestreamRegistry;
|
||||
|
||||
class MyOutgoingSIFileTransfer : public OutgoingFileTransfer {
|
||||
public:
|
||||
MyOutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer, SOCKS5BytestreamRegistry* registry);
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void cancel();
|
||||
|
||||
boost::signal<void (const boost::optional<FileTransferError>&)> onFinished;
|
||||
|
||||
private:
|
||||
void handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref);
|
||||
void handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref);
|
||||
void finish(boost::optional<FileTransferError> error);
|
||||
void handleIBBSessionFinished(boost::optional<FileTransferError> error);
|
||||
|
||||
private:
|
||||
std::string id;
|
||||
JID from;
|
||||
JID to;
|
||||
std::string name;
|
||||
int size;
|
||||
std::string description;
|
||||
boost::shared_ptr<ReadBytestream> bytestream;
|
||||
IQRouter* iqRouter;
|
||||
SOCKS5BytestreamServer* socksServer;
|
||||
boost::shared_ptr<IBBSendSession> ibbSession;
|
||||
SOCKS5BytestreamRegistry *registry;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Network/DummyConnectionServer.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/asio/placeholders.hpp>
|
||||
|
||||
#include <Swiften/EventLoop/EventLoop.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
DummyConnectionServer::DummyConnectionServer(EventLoop* eventLoop) : eventLoop(eventLoop) {
|
||||
}
|
||||
|
||||
void DummyConnectionServer::start() {
|
||||
}
|
||||
|
||||
|
||||
void DummyConnectionServer::stop() {
|
||||
|
||||
}
|
||||
|
||||
void DummyConnectionServer::acceptConnection(boost::shared_ptr<Connection> connection) {
|
||||
eventLoop->postEvent(
|
||||
boost::bind(boost::ref(onNewConnection), connection),
|
||||
shared_from_this());
|
||||
// connection->listen();
|
||||
}
|
||||
|
||||
|
||||
HostAddressPort DummyConnectionServer::getAddressPort() const {
|
||||
return HostAddressPort();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <Swiften/Base/boost_bsignals.h>
|
||||
|
||||
#include <Swiften/Network/DummyConnection.h>
|
||||
#include <Swiften/Network/ConnectionServer.h>
|
||||
#include <Swiften/EventLoop/EventOwner.h>
|
||||
|
||||
namespace Swift {
|
||||
class DummyConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<DummyConnectionServer> {
|
||||
public:
|
||||
typedef boost::shared_ptr<DummyConnectionServer> ref;
|
||||
|
||||
enum Error {
|
||||
Conflict,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
static ref create(EventLoop* eventLoop) {
|
||||
return ref(new DummyConnectionServer(eventLoop));
|
||||
}
|
||||
|
||||
void acceptConnection(boost::shared_ptr<Connection> connection);
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
||||
virtual HostAddressPort getAddressPort() const;
|
||||
|
||||
|
||||
private:
|
||||
DummyConnectionServer(EventLoop* eventLoop);
|
||||
|
||||
|
||||
private:
|
||||
HostAddress address_;
|
||||
EventLoop* eventLoop;
|
||||
};
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Network/DummyConnectionServerFactory.h>
|
||||
#include <Swiften/Network/DummyConnectionServer.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
DummyConnectionServerFactory::DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
|
||||
}
|
||||
|
||||
boost::shared_ptr<ConnectionServer> DummyConnectionServerFactory::createConnectionServer(int port) {
|
||||
return DummyConnectionServer::create(eventLoop);
|
||||
}
|
||||
|
||||
boost::shared_ptr<ConnectionServer> DummyConnectionServerFactory::createConnectionServer(const Swift::HostAddress &hostAddress, int port) {
|
||||
return DummyConnectionServer::create(eventLoop);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include <Swiften/Network/ConnectionServerFactory.h>
|
||||
#include <Swiften/Network/DummyConnectionServer.h>
|
||||
|
||||
namespace Swift {
|
||||
class ConnectionServer;
|
||||
|
||||
class DummyConnectionServerFactory : public ConnectionServerFactory {
|
||||
public:
|
||||
DummyConnectionServerFactory(EventLoop* eventLoop);
|
||||
|
||||
virtual boost::shared_ptr<ConnectionServer> createConnectionServer(int port);
|
||||
|
||||
virtual boost::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress &hostAddress, int port);
|
||||
|
||||
private:
|
||||
EventLoop* eventLoop;
|
||||
};
|
||||
}
|
|
@ -1,82 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Version.h>
|
||||
//#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
// Swiften 3 was not released yet and these changes are not in 3.0alpha
|
||||
#define HAVE_SWIFTEN_3 0
|
||||
|
||||
#include <Swiften/Network/NetworkFactories.h>
|
||||
#include <Swiften/Parser/PlatformXMLParserFactory.h>
|
||||
#if HAVE_SWIFTEN_3
|
||||
#include <Swiften/IDN/IDNConverter.h>
|
||||
#include <Swiften/IDN/PlatformIDNConverter.h>
|
||||
#endif
|
||||
|
||||
namespace Swift {
|
||||
class EventLoop;
|
||||
|
||||
class DummyNetworkFactories : public NetworkFactories {
|
||||
public:
|
||||
DummyNetworkFactories(EventLoop *eventLoop);
|
||||
~DummyNetworkFactories();
|
||||
|
||||
virtual TimerFactory* getTimerFactory() const {
|
||||
return timerFactory;
|
||||
}
|
||||
|
||||
virtual ConnectionFactory* getConnectionFactory() const {
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
#if HAVE_SWIFTEN_3
|
||||
IDNConverter* getIDNConverter() const {
|
||||
return idnConverter.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
DomainNameResolver* getDomainNameResolver() const {
|
||||
return domainNameResolver;
|
||||
}
|
||||
|
||||
ConnectionServerFactory* getConnectionServerFactory() const {
|
||||
return connectionServerFactory;
|
||||
}
|
||||
|
||||
virtual Swift::NATTraverser* getNATTraverser() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Swift::XMLParserFactory* getXMLParserFactory() const {
|
||||
return m_platformXMLParserFactory;
|
||||
}
|
||||
|
||||
EventLoop *getEventLoop() const {
|
||||
return eventLoop;
|
||||
}
|
||||
|
||||
Swift::TLSContextFactory* getTLSContextFactory() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Swift::ProxyProvider* getProxyProvider() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
PlatformXMLParserFactory *m_platformXMLParserFactory;
|
||||
TimerFactory* timerFactory;
|
||||
ConnectionFactory* connectionFactory;
|
||||
#if HAVE_SWIFTEN_3
|
||||
boost::shared_ptr<IDNConverter> idnConverter;
|
||||
#endif
|
||||
DomainNameResolver* domainNameResolver;
|
||||
ConnectionServerFactory* connectionServerFactory;
|
||||
EventLoop *eventLoop;
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
#include <Swiften/Network/NetworkFactories.h>
|
||||
#include <Swiften/Parser/PlatformXMLParserFactory.h>
|
||||
#if HAVE_SWIFTEN_3
|
||||
#include <Swiften/IDN/IDNConverter.h>
|
||||
#include <Swiften/IDN/PlatformIDNConverter.h>
|
||||
#endif
|
||||
|
||||
namespace Swift {
|
||||
class EventLoop;
|
||||
|
||||
class DummyNetworkFactories : public NetworkFactories {
|
||||
public:
|
||||
DummyNetworkFactories(EventLoop *eventLoop);
|
||||
~DummyNetworkFactories();
|
||||
|
||||
virtual TimerFactory* getTimerFactory() const {
|
||||
return timerFactory;
|
||||
}
|
||||
|
||||
virtual ConnectionFactory* getConnectionFactory() const {
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
#if HAVE_SWIFTEN_3
|
||||
IDNConverter* getIDNConverter() const {
|
||||
return idnConverter.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
DomainNameResolver* getDomainNameResolver() const {
|
||||
return domainNameResolver;
|
||||
}
|
||||
|
||||
ConnectionServerFactory* getConnectionServerFactory() const {
|
||||
return connectionServerFactory;
|
||||
}
|
||||
|
||||
virtual Swift::NATTraverser* getNATTraverser() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Swift::XMLParserFactory* getXMLParserFactory() const {
|
||||
return m_platformXMLParserFactory;
|
||||
}
|
||||
|
||||
EventLoop *getEventLoop() const {
|
||||
return eventLoop;
|
||||
}
|
||||
|
||||
Swift::TLSContextFactory* getTLSContextFactory() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Swift::ProxyProvider* getProxyProvider() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
PlatformXMLParserFactory *m_platformXMLParserFactory;
|
||||
TimerFactory* timerFactory;
|
||||
ConnectionFactory* connectionFactory;
|
||||
#if HAVE_SWIFTEN_3
|
||||
boost::shared_ptr<IDNConverter> idnConverter;
|
||||
#endif
|
||||
DomainNameResolver* domainNameResolver;
|
||||
ConnectionServerFactory* connectionServerFactory;
|
||||
EventLoop *eventLoop;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Parser/PayloadParsers/PubSubItemParser.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
|
||||
#include <Swiften/Parser/PayloadParserFactory.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Elements/MUCOccupant.h>
|
||||
#include <Swiften/Parser/Tree/TreeReparser.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
void PubSubItemParser::handleTree(ParserElement::ref root) {
|
||||
std::string id = root->getAttributes().getAttribute("id");
|
||||
if (!id.empty()) {
|
||||
getPayloadInternal()->setId(id);
|
||||
}
|
||||
|
||||
foreach (ParserElement::ref child, root->getAllChildren()) {
|
||||
getPayloadInternal()->addPayload(TreeReparser::parseTree(child, factories));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/Elements/PubSubItem.h>
|
||||
#include <Swiften/Parser/GenericPayloadTreeParser.h>
|
||||
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadParserFactoryCollection;
|
||||
class PubSubItemParser : public GenericPayloadTreeParser<PubSubItem> {
|
||||
public:
|
||||
PubSubItemParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
|
||||
virtual void handleTree(ParserElement::ref root);
|
||||
private:
|
||||
PayloadParserFactoryCollection* factories;
|
||||
};
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Parser/PayloadParsers/PubSubPayloadParser.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
|
||||
#include <Swiften/Parser/PayloadParserFactory.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Elements/MUCOccupant.h>
|
||||
#include <Swiften/Parser/Tree/TreeReparser.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
void PubSubPayloadParser::handleTree(ParserElement::ref root) {
|
||||
foreach (ParserElement::ref child, root->getAllChildren()) {
|
||||
getPayloadInternal()->addPayload(TreeReparser::parseTree(child, factories));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/Elements/PubSubPayload.h>
|
||||
#include <Swiften/Parser/GenericPayloadTreeParser.h>
|
||||
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadParserFactoryCollection;
|
||||
class PubSubPayloadParser : public GenericPayloadTreeParser<PubSubPayload> {
|
||||
public:
|
||||
PubSubPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
|
||||
virtual void handleTree(ParserElement::ref root);
|
||||
private:
|
||||
PayloadParserFactoryCollection* factories;
|
||||
};
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Parser/PayloadParsers/PubSubPublishPayloadParser.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
|
||||
#include <Swiften/Parser/PayloadParserFactory.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Elements/MUCOccupant.h>
|
||||
#include <Swiften/Parser/Tree/TreeReparser.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
void PubSubPublishPayloadParser::handleTree(ParserElement::ref root) {
|
||||
std::string node = root->getAttributes().getAttribute("node");
|
||||
if (!node.empty()) {
|
||||
getPayloadInternal()->setNode(node);
|
||||
}
|
||||
|
||||
foreach (ParserElement::ref child, root->getAllChildren()) {
|
||||
getPayloadInternal()->addItem(TreeReparser::parseTree(child, factories));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/Elements/PubSubPublishPayload.h>
|
||||
#include <Swiften/Parser/GenericPayloadTreeParser.h>
|
||||
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadParserFactoryCollection;
|
||||
class PubSubPublishPayloadParser : public GenericPayloadTreeParser<PubSubPublishPayload> {
|
||||
public:
|
||||
PubSubPublishPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
|
||||
virtual void handleTree(ParserElement::ref root);
|
||||
private:
|
||||
PayloadParserFactoryCollection* factories;
|
||||
};
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Parser/PayloadParsers/PubSubSubscribePayloadParser.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
|
||||
#include <Swiften/Parser/PayloadParserFactory.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Elements/MUCOccupant.h>
|
||||
#include <Swiften/Parser/Tree/TreeReparser.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
void PubSubSubscribePayloadParser::handleTree(ParserElement::ref root) {
|
||||
std::string node = root->getAttributes().getAttribute("node");
|
||||
if (!node.empty()) {
|
||||
getPayloadInternal()->setNode(node);
|
||||
}
|
||||
|
||||
std::string jid = root->getAttributes().getAttribute("jid");
|
||||
if (!jid.empty()) {
|
||||
getPayloadInternal()->setJID(jid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/Elements/PubSubSubscribePayload.h>
|
||||
#include <Swiften/Parser/GenericPayloadTreeParser.h>
|
||||
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadParserFactoryCollection;
|
||||
class PubSubSubscribePayloadParser : public GenericPayloadTreeParser<PubSubSubscribePayload> {
|
||||
public:
|
||||
PubSubSubscribePayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
|
||||
virtual void handleTree(ParserElement::ref root);
|
||||
private:
|
||||
PayloadParserFactoryCollection* factories;
|
||||
};
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Parser/PayloadParsers/PubSubSubscriptionPayloadParser.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
|
||||
#include <Swiften/Parser/PayloadParserFactory.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Elements/MUCOccupant.h>
|
||||
#include <Swiften/Parser/Tree/TreeReparser.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
void PubSubSubscriptionPayloadParser::handleTree(ParserElement::ref root) {
|
||||
std::string node = root->getAttributes().getAttribute("node");
|
||||
if (!node.empty()) {
|
||||
getPayloadInternal()->setNode(node);
|
||||
}
|
||||
|
||||
std::string jid = root->getAttributes().getAttribute("jid");
|
||||
if (!jid.empty()) {
|
||||
getPayloadInternal()->setJID(jid);
|
||||
}
|
||||
|
||||
std::string id = root->getAttributes().getAttribute("subid");
|
||||
if (!id.empty()) {
|
||||
getPayloadInternal()->setId(id);
|
||||
}
|
||||
|
||||
std::string type = root->getAttributes().getAttribute("subscription");
|
||||
if (type == "none") {
|
||||
getPayloadInternal()->setType(PubSubSubscriptionPayload::None);
|
||||
}
|
||||
else if (type == "subscribed") {
|
||||
getPayloadInternal()->setType(PubSubSubscriptionPayload::Subscribed);
|
||||
}
|
||||
else if (type == "pending") {
|
||||
getPayloadInternal()->setType(PubSubSubscriptionPayload::Pending);
|
||||
}
|
||||
else if (type == "unconfigured") {
|
||||
getPayloadInternal()->setType(PubSubSubscriptionPayload::Unconfigured);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Swiften/Elements/PubSubSubscriptionPayload.h>
|
||||
#include <Swiften/Parser/GenericPayloadTreeParser.h>
|
||||
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadParserFactoryCollection;
|
||||
class PubSubSubscriptionPayloadParser : public GenericPayloadTreeParser<PubSubSubscriptionPayload> {
|
||||
public:
|
||||
PubSubSubscriptionPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
|
||||
virtual void handleTree(ParserElement::ref root);
|
||||
private:
|
||||
PayloadParserFactoryCollection* factories;
|
||||
};
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLElement.h>
|
||||
#include <Swiften/Serializer/PayloadSerializerCollection.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubItemSerializer::PubSubItemSerializer(PayloadSerializerCollection *serializers) :
|
||||
GenericPayloadSerializer<PubSubItem>(), serializers(serializers) {
|
||||
}
|
||||
|
||||
std::string PubSubItemSerializer::serializePayload(boost::shared_ptr<PubSubItem> payload) const {
|
||||
XMLElement item("item");
|
||||
if (!payload->getId().empty()) {
|
||||
item.setAttribute("id", payload->getId());
|
||||
}
|
||||
|
||||
if (!payload->getPayloads().empty()) {
|
||||
foreach(boost::shared_ptr<Payload> subPayload, payload->getPayloads()) {
|
||||
PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
|
||||
if (serializer) {
|
||||
item.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return item.serialize();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Serializer/GenericPayloadSerializer.h>
|
||||
#include <Swiften/Elements/PubSubItem.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadSerializerCollection;
|
||||
class PubSubItemSerializer : public GenericPayloadSerializer<PubSubItem> {
|
||||
public:
|
||||
PubSubItemSerializer(PayloadSerializerCollection *serializers);
|
||||
|
||||
virtual std::string serializePayload(boost::shared_ptr<PubSubItem> item) const;
|
||||
private:
|
||||
PayloadSerializerCollection *serializers;
|
||||
};
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Serializer/PayloadSerializers/PubSubPayloadSerializer.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLElement.h>
|
||||
#include <Swiften/Serializer/PayloadSerializerCollection.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubPayloadSerializer::PubSubPayloadSerializer(PayloadSerializerCollection *serializers)
|
||||
: GenericPayloadSerializer<PubSubPayload>(),
|
||||
serializers(serializers) {
|
||||
}
|
||||
|
||||
std::string PubSubPayloadSerializer::serializePayload(boost::shared_ptr<PubSubPayload> payload) const {
|
||||
XMLElement pubsub("pubsub", "http://jabber.org/protocol/pubsub");
|
||||
|
||||
if (!payload->getPayloads().empty()) {
|
||||
foreach(boost::shared_ptr<Payload> subPayload, payload->getPayloads()) {
|
||||
PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
|
||||
if (serializer) {
|
||||
pubsub.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pubsub.serialize();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Serializer/GenericPayloadSerializer.h>
|
||||
#include <Swiften/Elements/PubSubPayload.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadSerializerCollection;
|
||||
|
||||
class PubSubPayloadSerializer : public GenericPayloadSerializer<PubSubPayload> {
|
||||
public:
|
||||
PubSubPayloadSerializer(PayloadSerializerCollection *serializers);
|
||||
|
||||
virtual std::string serializePayload(boost::shared_ptr<PubSubPayload> item) const;
|
||||
private:
|
||||
PayloadSerializerCollection *serializers;
|
||||
};
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Serializer/PayloadSerializers/PubSubPublishPayloadSerializer.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLElement.h>
|
||||
#include <Swiften/Serializer/PayloadSerializerCollection.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubPublishPayloadSerializer::PubSubPublishPayloadSerializer(PayloadSerializerCollection *serializers)
|
||||
: GenericPayloadSerializer<PubSubPublishPayload>(),
|
||||
serializers(serializers) {
|
||||
}
|
||||
|
||||
std::string PubSubPublishPayloadSerializer::serializePayload(boost::shared_ptr<PubSubPublishPayload> payload) const {
|
||||
XMLElement publish("publish");
|
||||
|
||||
if (!payload->getNode().empty()) {
|
||||
publish.setAttribute("node", payload->getNode());
|
||||
}
|
||||
|
||||
if (!payload->getItems().empty()) {
|
||||
foreach(boost::shared_ptr<Payload> subPayload, payload->getItems()) {
|
||||
PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
|
||||
if (serializer) {
|
||||
publish.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return publish.serialize();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Serializer/GenericPayloadSerializer.h>
|
||||
#include <Swiften/Elements/PubSubPublishPayload.h>
|
||||
|
||||
namespace Swift {
|
||||
class PayloadSerializerCollection;
|
||||
|
||||
class PubSubPublishPayloadSerializer : public GenericPayloadSerializer<PubSubPublishPayload> {
|
||||
public:
|
||||
PubSubPublishPayloadSerializer(PayloadSerializerCollection *serializers);
|
||||
|
||||
virtual std::string serializePayload(boost::shared_ptr<PubSubPublishPayload> item) const;
|
||||
private:
|
||||
PayloadSerializerCollection *serializers;
|
||||
};
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Serializer/PayloadSerializers/PubSubSubscribePayloadSerializer.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLElement.h>
|
||||
#include <Swiften/Serializer/PayloadSerializerCollection.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubSubscribePayloadSerializer::PubSubSubscribePayloadSerializer()
|
||||
: GenericPayloadSerializer<PubSubSubscribePayload>() {
|
||||
}
|
||||
|
||||
std::string PubSubSubscribePayloadSerializer::serializePayload(boost::shared_ptr<PubSubSubscribePayload> payload) const {
|
||||
XMLElement subscribe("subscribe");
|
||||
|
||||
if (!payload->getJID().isValid()) {
|
||||
subscribe.setAttribute("jid", payload->getJID().toBare().toString());
|
||||
}
|
||||
|
||||
if (!payload->getNode().empty()) {
|
||||
subscribe.setAttribute("node", payload->getNode());
|
||||
}
|
||||
|
||||
return subscribe.serialize();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Serializer/GenericPayloadSerializer.h>
|
||||
#include <Swiften/Elements/PubSubSubscribePayload.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubSubscribePayloadSerializer : public GenericPayloadSerializer<PubSubSubscribePayload> {
|
||||
public:
|
||||
PubSubSubscribePayloadSerializer();
|
||||
|
||||
virtual std::string serializePayload(boost::shared_ptr<PubSubSubscribePayload> item) const;
|
||||
};
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionPayloadSerializer.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLTextNode.h>
|
||||
#include <Swiften/Serializer/XML/XMLElement.h>
|
||||
#include <Swiften/Serializer/PayloadSerializerCollection.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
PubSubSubscriptionPayloadSerializer::PubSubSubscriptionPayloadSerializer()
|
||||
: GenericPayloadSerializer<PubSubSubscriptionPayload>() {
|
||||
}
|
||||
|
||||
std::string PubSubSubscriptionPayloadSerializer::serializePayload(boost::shared_ptr<PubSubSubscriptionPayload> payload) const {
|
||||
XMLElement subscription("subscription");
|
||||
|
||||
if (!payload->getJID().isValid()) {
|
||||
subscription.setAttribute("jid", payload->getJID().toBare().toString());
|
||||
}
|
||||
|
||||
if (!payload->getNode().empty()) {
|
||||
subscription.setAttribute("node", payload->getNode());
|
||||
}
|
||||
|
||||
switch (payload->getType()) {
|
||||
case PubSubSubscriptionPayload::None:
|
||||
subscription.setAttribute("subscription", "none");
|
||||
break;
|
||||
case PubSubSubscriptionPayload::Subscribed:
|
||||
subscription.setAttribute("subscription", "subscribed");
|
||||
break;
|
||||
case PubSubSubscriptionPayload::Unconfigured:
|
||||
subscription.setAttribute("subscription", "unconfigured");
|
||||
break;
|
||||
case PubSubSubscriptionPayload::Pending:
|
||||
subscription.setAttribute("subscription", "pending");
|
||||
break;
|
||||
}
|
||||
|
||||
return subscription.serialize();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jan Kaluza
|
||||
* Licensed under the Simplified BSD license.
|
||||
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Serializer/GenericPayloadSerializer.h>
|
||||
#include <Swiften/Elements/PubSubSubscriptionPayload.h>
|
||||
|
||||
namespace Swift {
|
||||
class PubSubSubscriptionPayloadSerializer : public GenericPayloadSerializer<PubSubSubscriptionPayload> {
|
||||
public:
|
||||
PubSubSubscriptionPayloadSerializer();
|
||||
|
||||
virtual std::string serializePayload(boost::shared_ptr<PubSubSubscriptionPayload> item) const;
|
||||
};
|
||||
}
|
|
@ -1,183 +1,183 @@
|
|||
/*
|
||||
* 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/ServerFromClientSession.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <Swiften/Elements/ProtocolHeader.h>
|
||||
#include <Swiften/Elements/StreamError.h>
|
||||
#include <Swiften/Elements/Message.h>
|
||||
#include <Swiften/Server/UserRegistry.h>
|
||||
#include <Swiften/Network/Connection.h>
|
||||
#include <Swiften/StreamStack/XMPPLayer.h>
|
||||
#include <Swiften/Elements/StreamFeatures.h>
|
||||
#include <Swiften/Elements/ResourceBind.h>
|
||||
#include <Swiften/Elements/StartSession.h>
|
||||
#include <Swiften/Elements/IQ.h>
|
||||
#include <Swiften/Elements/AuthSuccess.h>
|
||||
#include <Swiften/Elements/AuthFailure.h>
|
||||
#include <Swiften/Elements/AuthRequest.h>
|
||||
#include <Swiften/SASL/PLAINMessage.h>
|
||||
#include <Swiften/StreamStack/StreamStack.h>
|
||||
#include <Swiften/StreamStack/TLSServerLayer.h>
|
||||
#include <Swiften/Elements/StartTLSRequest.h>
|
||||
#include <Swiften/Elements/TLSProceed.h>
|
||||
#include <iostream>
|
||||
#include <Swiften/TLS/CertificateWithKey.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
ServerFromClientSession::ServerFromClientSession(
|
||||
const std::string& id,
|
||||
boost::shared_ptr<Connection> connection,
|
||||
PayloadParserFactoryCollection* payloadParserFactories,
|
||||
PayloadSerializerCollection* payloadSerializers,
|
||||
UserRegistry* userRegistry,
|
||||
XMLParserFactory* factory,
|
||||
Swift::JID remoteJID) :
|
||||
Session(connection, payloadParserFactories, payloadSerializers, factory),
|
||||
id_(id),
|
||||
userRegistry_(userRegistry),
|
||||
authenticated_(false),
|
||||
initialized(false),
|
||||
allowSASLEXTERNAL(false),
|
||||
tlsLayer(0),
|
||||
tlsConnected(false) {
|
||||
setRemoteJID(remoteJID);
|
||||
}
|
||||
|
||||
ServerFromClientSession::~ServerFromClientSession() {
|
||||
if (tlsLayer) {
|
||||
delete tlsLayer;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handlePasswordValid() {
|
||||
if (!isInitialized()) {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
|
||||
authenticated_ = true;
|
||||
getXMPPLayer()->resetParser();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handlePasswordInvalid(const std::string &error) {
|
||||
if (!isInitialized()) {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
|
||||
if (!error.empty()) {
|
||||
boost::shared_ptr<StreamError> msg(new StreamError(StreamError::UndefinedCondition, error));
|
||||
getXMPPLayer()->writeElement(msg);
|
||||
}
|
||||
|
||||
finishSession(AuthenticationFailedError);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element) {
|
||||
if (isInitialized()) {
|
||||
onElementReceived(element);
|
||||
}
|
||||
else {
|
||||
if (AuthRequest* authRequest = dynamic_cast<AuthRequest*>(element.get())) {
|
||||
if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) {
|
||||
if (authRequest->getMechanism() == "EXTERNAL") {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
|
||||
authenticated_ = true;
|
||||
getXMPPLayer()->resetParser();
|
||||
}
|
||||
else {
|
||||
PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : createSafeByteArray(""));
|
||||
user_ = plainMessage.getAuthenticationID();
|
||||
userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), this, plainMessage.getPassword());
|
||||
}
|
||||
}
|
||||
else {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
|
||||
finishSession(NoSupportedAuthMechanismsError);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<StartTLSRequest*>(element.get()) != NULL) {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<TLSProceed>(new TLSProceed));
|
||||
getStreamStack()->addLayer(tlsLayer);
|
||||
tlsLayer->connect();
|
||||
getXMPPLayer()->resetParser();
|
||||
}
|
||||
else if (IQ* iq = dynamic_cast<IQ*>(element.get())) {
|
||||
if (boost::shared_ptr<ResourceBind> resourceBind = iq->getPayload<ResourceBind>()) {
|
||||
std::string bucket = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string uuid;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
uuid += bucket[rand() % bucket.size()];
|
||||
}
|
||||
setRemoteJID(JID(user_, getLocalJID().getDomain(), uuid));
|
||||
boost::shared_ptr<ResourceBind> resultResourceBind(new ResourceBind());
|
||||
resultResourceBind->setJID(getRemoteJID());
|
||||
getXMPPLayer()->writeElement(IQ::createResult(JID(), iq->getID(), resultResourceBind));
|
||||
}
|
||||
else if (iq->getPayload<StartSession>()) {
|
||||
getXMPPLayer()->writeElement(IQ::createResult(getRemoteJID(), iq->getID()));
|
||||
setInitialized();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) {
|
||||
setLocalJID(JID("", incomingHeader.getTo()));
|
||||
ProtocolHeader header;
|
||||
header.setFrom(incomingHeader.getTo());
|
||||
header.setID(id_);
|
||||
getXMPPLayer()->writeHeader(header);
|
||||
|
||||
boost::shared_ptr<StreamFeatures> features(new StreamFeatures());
|
||||
|
||||
if (!authenticated_) {
|
||||
if (tlsLayer && !tlsConnected) {
|
||||
features->setHasStartTLS();
|
||||
}
|
||||
features->addAuthenticationMechanism("PLAIN");
|
||||
if (allowSASLEXTERNAL) {
|
||||
features->addAuthenticationMechanism("EXTERNAL");
|
||||
}
|
||||
}
|
||||
else {
|
||||
features->setHasResourceBind();
|
||||
features->setHasSession();
|
||||
}
|
||||
getXMPPLayer()->writeElement(features);
|
||||
}
|
||||
|
||||
void ServerFromClientSession::setInitialized() {
|
||||
initialized = true;
|
||||
onSessionStarted();
|
||||
}
|
||||
|
||||
void ServerFromClientSession::setAllowSASLEXTERNAL() {
|
||||
allowSASLEXTERNAL = true;
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handleSessionFinished(const boost::optional<SessionError>&) {
|
||||
userRegistry_->stopLogin(JID(user_, getLocalJID().getDomain()), this);
|
||||
}
|
||||
|
||||
void ServerFromClientSession::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert) {
|
||||
tlsLayer = new TLSServerLayer(tlsContextFactory);
|
||||
if (!tlsLayer->setServerCertificate(cert)) {
|
||||
// std::cout << "error\n";
|
||||
// TODO:
|
||||
// onClosed(boost::shared_ptr<Error>(new Error(Error::InvalidTLSCertificateError)));
|
||||
}
|
||||
else {
|
||||
tlsLayer->onError.connect(boost::bind(&ServerFromClientSession::handleTLSError, this));
|
||||
tlsLayer->onConnected.connect(boost::bind(&ServerFromClientSession::handleTLSConnected, this));
|
||||
// getStreamStack()->addLayer(tlsLayer);
|
||||
// tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this));
|
||||
// tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this));
|
||||
// tlsLayer->connect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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/ServerFromClientSession.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <Swiften/Elements/ProtocolHeader.h>
|
||||
#include <Swiften/Elements/StreamError.h>
|
||||
#include <Swiften/Elements/Message.h>
|
||||
#include <Swiften/Server/UserRegistry.h>
|
||||
#include <Swiften/Network/Connection.h>
|
||||
#include <Swiften/StreamStack/XMPPLayer.h>
|
||||
#include <Swiften/Elements/StreamFeatures.h>
|
||||
#include <Swiften/Elements/ResourceBind.h>
|
||||
#include <Swiften/Elements/StartSession.h>
|
||||
#include <Swiften/Elements/IQ.h>
|
||||
#include <Swiften/Elements/AuthSuccess.h>
|
||||
#include <Swiften/Elements/AuthFailure.h>
|
||||
#include <Swiften/Elements/AuthRequest.h>
|
||||
#include <Swiften/SASL/PLAINMessage.h>
|
||||
#include <Swiften/StreamStack/StreamStack.h>
|
||||
#include <Swiften/StreamStack/TLSServerLayer.h>
|
||||
#include <Swiften/Elements/StartTLSRequest.h>
|
||||
#include <Swiften/Elements/TLSProceed.h>
|
||||
#include <iostream>
|
||||
#include <Swiften/TLS/CertificateWithKey.h>
|
||||
|
||||
namespace Swift {
|
||||
|
||||
ServerFromClientSession::ServerFromClientSession(
|
||||
const std::string& id,
|
||||
boost::shared_ptr<Connection> connection,
|
||||
PayloadParserFactoryCollection* payloadParserFactories,
|
||||
PayloadSerializerCollection* payloadSerializers,
|
||||
UserRegistry* userRegistry,
|
||||
XMLParserFactory* factory,
|
||||
Swift::JID remoteJID) :
|
||||
Session(connection, payloadParserFactories, payloadSerializers, factory),
|
||||
id_(id),
|
||||
userRegistry_(userRegistry),
|
||||
authenticated_(false),
|
||||
initialized(false),
|
||||
allowSASLEXTERNAL(false),
|
||||
tlsLayer(0),
|
||||
tlsConnected(false) {
|
||||
setRemoteJID(remoteJID);
|
||||
}
|
||||
|
||||
ServerFromClientSession::~ServerFromClientSession() {
|
||||
if (tlsLayer) {
|
||||
delete tlsLayer;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handlePasswordValid() {
|
||||
if (!isInitialized()) {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
|
||||
authenticated_ = true;
|
||||
getXMPPLayer()->resetParser();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handlePasswordInvalid(const std::string &error) {
|
||||
if (!isInitialized()) {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
|
||||
if (!error.empty()) {
|
||||
boost::shared_ptr<StreamError> msg(new StreamError(StreamError::UndefinedCondition, error));
|
||||
getXMPPLayer()->writeElement(msg);
|
||||
}
|
||||
|
||||
finishSession(AuthenticationFailedError);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
|
||||
if (isInitialized()) {
|
||||
onElementReceived(element);
|
||||
}
|
||||
else {
|
||||
if (AuthRequest* authRequest = dynamic_cast<AuthRequest*>(element.get())) {
|
||||
if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) {
|
||||
if (authRequest->getMechanism() == "EXTERNAL") {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
|
||||
authenticated_ = true;
|
||||
getXMPPLayer()->resetParser();
|
||||
}
|
||||
else {
|
||||
PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : createSafeByteArray(""));
|
||||
user_ = plainMessage.getAuthenticationID();
|
||||
userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), this, plainMessage.getPassword());
|
||||
}
|
||||
}
|
||||
else {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
|
||||
finishSession(NoSupportedAuthMechanismsError);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<StartTLSRequest*>(element.get()) != NULL) {
|
||||
getXMPPLayer()->writeElement(boost::shared_ptr<TLSProceed>(new TLSProceed));
|
||||
getStreamStack()->addLayer(tlsLayer);
|
||||
tlsLayer->connect();
|
||||
getXMPPLayer()->resetParser();
|
||||
}
|
||||
else if (IQ* iq = dynamic_cast<IQ*>(element.get())) {
|
||||
if (boost::shared_ptr<ResourceBind> resourceBind = iq->getPayload<ResourceBind>()) {
|
||||
std::string bucket = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string uuid;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
uuid += bucket[rand() % bucket.size()];
|
||||
}
|
||||
setRemoteJID(JID(user_, getLocalJID().getDomain(), uuid));
|
||||
boost::shared_ptr<ResourceBind> resultResourceBind(new ResourceBind());
|
||||
resultResourceBind->setJID(getRemoteJID());
|
||||
getXMPPLayer()->writeElement(IQ::createResult(JID(), iq->getID(), resultResourceBind));
|
||||
}
|
||||
else if (iq->getPayload<StartSession>()) {
|
||||
getXMPPLayer()->writeElement(IQ::createResult(getRemoteJID(), iq->getID()));
|
||||
setInitialized();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) {
|
||||
setLocalJID(JID("", incomingHeader.getTo()));
|
||||
ProtocolHeader header;
|
||||
header.setFrom(incomingHeader.getTo());
|
||||
header.setID(id_);
|
||||
getXMPPLayer()->writeHeader(header);
|
||||
|
||||
boost::shared_ptr<StreamFeatures> features(new StreamFeatures());
|
||||
|
||||
if (!authenticated_) {
|
||||
if (tlsLayer && !tlsConnected) {
|
||||
features->setHasStartTLS();
|
||||
}
|
||||
features->addAuthenticationMechanism("PLAIN");
|
||||
if (allowSASLEXTERNAL) {
|
||||
features->addAuthenticationMechanism("EXTERNAL");
|
||||
}
|
||||
}
|
||||
else {
|
||||
features->setHasResourceBind();
|
||||
features->setHasSession();
|
||||
}
|
||||
getXMPPLayer()->writeElement(features);
|
||||
}
|
||||
|
||||
void ServerFromClientSession::setInitialized() {
|
||||
initialized = true;
|
||||
onSessionStarted();
|
||||
}
|
||||
|
||||
void ServerFromClientSession::setAllowSASLEXTERNAL() {
|
||||
allowSASLEXTERNAL = true;
|
||||
}
|
||||
|
||||
void ServerFromClientSession::handleSessionFinished(const boost::optional<SessionError>&) {
|
||||
userRegistry_->stopLogin(JID(user_, getLocalJID().getDomain()), this);
|
||||
}
|
||||
|
||||
void ServerFromClientSession::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert) {
|
||||
tlsLayer = new TLSServerLayer(tlsContextFactory);
|
||||
if (!tlsLayer->setServerCertificate(cert)) {
|
||||
// std::cout << "error\n";
|
||||
// TODO:
|
||||
// onClosed(boost::shared_ptr<Error>(new Error(Error::InvalidTLSCertificateError)));
|
||||
}
|
||||
else {
|
||||
tlsLayer->onError.connect(boost::bind(&ServerFromClientSession::handleTLSError, this));
|
||||
tlsLayer->onConnected.connect(boost::bind(&ServerFromClientSession::handleTLSConnected, this));
|
||||
// getStreamStack()->addLayer(tlsLayer);
|
||||
// tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this));
|
||||
// tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this));
|
||||
// tlsLayer->connect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,85 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <Swiften/Base/boost_bsignals.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Session/Session.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
#include <Swiften/Network/Connection.h>
|
||||
#include <Swiften/Base/ByteArray.h>
|
||||
#include <Swiften/TLS/CertificateWithKey.h>
|
||||
|
||||
namespace Swift {
|
||||
class ProtocolHeader;
|
||||
class Element;
|
||||
class Stanza;
|
||||
class PayloadParserFactoryCollection;
|
||||
class PayloadSerializerCollection;
|
||||
class StreamStack;
|
||||
class UserRegistry;
|
||||
class XMPPLayer;
|
||||
class ConnectionLayer;
|
||||
class Connection;
|
||||
class TLSServerLayer;
|
||||
class TLSServerContextFactory;
|
||||
class PKCS12Certificate;
|
||||
|
||||
class ServerFromClientSession : public Session {
|
||||
public:
|
||||
ServerFromClientSession(
|
||||
const std::string& id,
|
||||
boost::shared_ptr<Connection> connection,
|
||||
PayloadParserFactoryCollection* payloadParserFactories,
|
||||
PayloadSerializerCollection* payloadSerializers,
|
||||
UserRegistry* userRegistry,
|
||||
XMLParserFactory* factory,
|
||||
Swift::JID remoteJID = Swift::JID());
|
||||
~ServerFromClientSession();
|
||||
|
||||
boost::signal<void ()> onSessionStarted;
|
||||
void setAllowSASLEXTERNAL();
|
||||
const std::string &getUser() {
|
||||
return user_;
|
||||
}
|
||||
|
||||
void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert);
|
||||
|
||||
Swift::JID getBareJID() {
|
||||
return Swift::JID(user_, getLocalJID().getDomain());
|
||||
}
|
||||
|
||||
void handlePasswordValid();
|
||||
void handlePasswordInvalid(const std::string &error = "");
|
||||
|
||||
private:
|
||||
void handleElement(boost::shared_ptr<Element>);
|
||||
void handleStreamStart(const ProtocolHeader& header);
|
||||
void handleSessionFinished(const boost::optional<SessionError>&);
|
||||
|
||||
void setInitialized();
|
||||
bool isInitialized() const {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void handleTLSError() { }
|
||||
void handleTLSConnected() { tlsConnected = true; }
|
||||
|
||||
private:
|
||||
std::string id_;
|
||||
UserRegistry* userRegistry_;
|
||||
bool authenticated_;
|
||||
bool initialized;
|
||||
bool allowSASLEXTERNAL;
|
||||
std::string user_;
|
||||
TLSServerLayer* tlsLayer;
|
||||
bool tlsConnected;
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <Swiften/Base/boost_bsignals.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Session/Session.h>
|
||||
#include <Swiften/JID/JID.h>
|
||||
#include <Swiften/Network/Connection.h>
|
||||
#include <Swiften/Base/ByteArray.h>
|
||||
#include <Swiften/TLS/CertificateWithKey.h>
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
namespace Swift {
|
||||
class ProtocolHeader;
|
||||
class Element;
|
||||
class Stanza;
|
||||
class PayloadParserFactoryCollection;
|
||||
class PayloadSerializerCollection;
|
||||
class StreamStack;
|
||||
class UserRegistry;
|
||||
class XMPPLayer;
|
||||
class ConnectionLayer;
|
||||
class Connection;
|
||||
class TLSServerLayer;
|
||||
class TLSServerContextFactory;
|
||||
class PKCS12Certificate;
|
||||
|
||||
class ServerFromClientSession : public Session {
|
||||
public:
|
||||
ServerFromClientSession(
|
||||
const std::string& id,
|
||||
boost::shared_ptr<Connection> connection,
|
||||
PayloadParserFactoryCollection* payloadParserFactories,
|
||||
PayloadSerializerCollection* payloadSerializers,
|
||||
UserRegistry* userRegistry,
|
||||
XMLParserFactory* factory,
|
||||
Swift::JID remoteJID = Swift::JID());
|
||||
~ServerFromClientSession();
|
||||
|
||||
boost::signal<void ()> onSessionStarted;
|
||||
void setAllowSASLEXTERNAL();
|
||||
const std::string &getUser() {
|
||||
return user_;
|
||||
}
|
||||
|
||||
void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert);
|
||||
|
||||
Swift::JID getBareJID() {
|
||||
return Swift::JID(user_, getLocalJID().getDomain());
|
||||
}
|
||||
|
||||
void handlePasswordValid();
|
||||
void handlePasswordInvalid(const std::string &error = "");
|
||||
|
||||
private:
|
||||
#if HAVE_SWIFTEN_3
|
||||
void handleElement(boost::shared_ptr<ToplevelElement>);
|
||||
#else
|
||||
void handleElement(boost::shared_ptr<Element>);
|
||||
#endif
|
||||
void handleStreamStart(const ProtocolHeader& header);
|
||||
void handleSessionFinished(const boost::optional<SessionError>&);
|
||||
|
||||
void setInitialized();
|
||||
bool isInitialized() const {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void handleTLSError() { }
|
||||
void handleTLSConnected() { tlsConnected = true; }
|
||||
|
||||
private:
|
||||
std::string id_;
|
||||
UserRegistry* userRegistry_;
|
||||
bool authenticated_;
|
||||
bool initialized;
|
||||
bool allowSASLEXTERNAL;
|
||||
std::string user_;
|
||||
TLSServerLayer* tlsLayer;
|
||||
bool tlsConnected;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,176 +1,179 @@
|
|||
/*
|
||||
* 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 boost::shared_ptr<ServerFromClientSession> session) const {
|
||||
return session->getRemoteJID().equals(jid, JID::WithResource);
|
||||
}
|
||||
JID jid;
|
||||
};
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::addSession(boost::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(boost::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<boost::shared_ptr<ServerFromClientSession> > &lst = sessions[session->getRemoteJID().toBare().toString()];
|
||||
lst.erase(std::remove(lst.begin(), lst.end(), session), lst.end());
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
|
||||
send(iq);
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
|
||||
send(message);
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
|
||||
send(presence);
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::handleDataRead(const SafeByteArray &data, const boost::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);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element> element, bool last) {
|
||||
std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
|
||||
for (std::list<boost::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<boost::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(boost::shared_ptr<Stanza> stanza) {
|
||||
JID to = stanza->getTo();
|
||||
assert(to.isValid());
|
||||
|
||||
// For a full JID, first try to route to a session with the full JID
|
||||
if (!to.isBare()) {
|
||||
std::list<boost::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<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
|
||||
for (std::list<boost::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 boost::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(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession>& session) {
|
||||
boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
|
||||
if (!stanza) {
|
||||
return;
|
||||
}
|
||||
|
||||
stanza->setFrom(session->getRemoteJID());
|
||||
|
||||
if (!stanza->getFrom().isValid())
|
||||
return;
|
||||
|
||||
|
||||
boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza);
|
||||
if (message) {
|
||||
onMessageReceived(message);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza);
|
||||
if (presence) {
|
||||
onPresenceReceived(presence);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza);
|
||||
if (iq) {
|
||||
onIQReceived(iq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::handleSessionInitialized() {
|
||||
onAvailableChanged(true);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 boost::shared_ptr<ServerFromClientSession> session) const {
|
||||
return session->getRemoteJID().equals(jid, JID::WithResource);
|
||||
}
|
||||
JID jid;
|
||||
};
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::addSession(boost::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(boost::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<boost::shared_ptr<ServerFromClientSession> > &lst = sessions[session->getRemoteJID().toBare().toString()];
|
||||
lst.erase(std::remove(lst.begin(), lst.end(), session), lst.end());
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
|
||||
send(iq);
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
|
||||
send(message);
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
|
||||
send(presence);
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::handleDataRead(const SafeByteArray &data, const boost::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, boost::shared_ptr<ToplevelElement> element, bool last) {
|
||||
#else
|
||||
void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element> element, bool last) {
|
||||
#endif
|
||||
std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
|
||||
for (std::list<boost::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<boost::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(boost::shared_ptr<Stanza> stanza) {
|
||||
JID to = stanza->getTo();
|
||||
assert(to.isValid());
|
||||
|
||||
// For a full JID, first try to route to a session with the full JID
|
||||
if (!to.isBare()) {
|
||||
std::list<boost::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<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
|
||||
for (std::list<boost::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 boost::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(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession>& session) {
|
||||
boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
|
||||
if (!stanza) {
|
||||
return;
|
||||
}
|
||||
|
||||
stanza->setFrom(session->getRemoteJID());
|
||||
|
||||
if (!stanza->getFrom().isValid())
|
||||
return;
|
||||
|
||||
|
||||
boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza);
|
||||
if (message) {
|
||||
onMessageReceived(message);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza);
|
||||
if (presence) {
|
||||
onPresenceReceived(presence);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza);
|
||||
if (iq) {
|
||||
onIQReceived(iq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerStanzaChannel::handleSessionInitialized() {
|
||||
onAvailableChanged(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,58 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "Swiften/Base/IDGenerator.h"
|
||||
#include "Swiften/Server/ServerFromClientSession.h"
|
||||
#include "Swiften/Client/StanzaChannel.h"
|
||||
#include "Swiften/Elements/Message.h"
|
||||
#include "Swiften/Elements/IQ.h"
|
||||
#include "Swiften/Elements/Presence.h"
|
||||
#include "Swiften/TLS/Certificate.h"
|
||||
|
||||
namespace Swift {
|
||||
class Error;
|
||||
class ServerStanzaChannel : public StanzaChannel {
|
||||
public:
|
||||
void addSession(boost::shared_ptr<ServerFromClientSession> session);
|
||||
void removeSession(boost::shared_ptr<ServerFromClientSession> session);
|
||||
|
||||
void sendIQ(boost::shared_ptr<IQ> iq);
|
||||
void sendMessage(boost::shared_ptr<Message> message);
|
||||
void sendPresence(boost::shared_ptr<Presence> presence);
|
||||
|
||||
void finishSession(const JID& to, boost::shared_ptr<Element> element, bool last = false);
|
||||
|
||||
bool getStreamManagementEnabled() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isAvailable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Certificate::ref> getPeerCertificateChain() const {
|
||||
return std::vector<Certificate::ref>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string getNewIQID();
|
||||
void send(boost::shared_ptr<Stanza> stanza);
|
||||
void handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession> &session);
|
||||
void handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession> &session);
|
||||
void handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session);
|
||||
void handleSessionInitialized();
|
||||
|
||||
private:
|
||||
IDGenerator idGenerator;
|
||||
// [JID][resources][ServerFromClientSession]
|
||||
std::map<std::string, std::list<boost::shared_ptr<ServerFromClientSession> > > sessions;
|
||||
};
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2010 Remko Tronçon
|
||||
* Licensed under the GNU General Public License v3.
|
||||
* See Documentation/Licenses/GPLv3.txt for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "Swiften/Base/IDGenerator.h"
|
||||
#include "Swiften/Server/ServerFromClientSession.h"
|
||||
#include "Swiften/Client/StanzaChannel.h"
|
||||
#include "Swiften/Elements/Message.h"
|
||||
#include "Swiften/Elements/IQ.h"
|
||||
#include "Swiften/Elements/Presence.h"
|
||||
#include "Swiften/TLS/Certificate.h"
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
namespace Swift {
|
||||
class Error;
|
||||
class ServerStanzaChannel : public StanzaChannel {
|
||||
public:
|
||||
void addSession(boost::shared_ptr<ServerFromClientSession> session);
|
||||
void removeSession(boost::shared_ptr<ServerFromClientSession> session);
|
||||
|
||||
void sendIQ(boost::shared_ptr<IQ> iq);
|
||||
void sendMessage(boost::shared_ptr<Message> message);
|
||||
void sendPresence(boost::shared_ptr<Presence> presence);
|
||||
#if HAVE_SWIFTEN_3
|
||||
void finishSession(const JID& to, boost::shared_ptr<ToplevelElement> element, bool last = false);
|
||||
#else
|
||||
void finishSession(const JID& to, boost::shared_ptr<Element> element, bool last = false);
|
||||
#endif
|
||||
bool getStreamManagementEnabled() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isAvailable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Certificate::ref> getPeerCertificateChain() const {
|
||||
return std::vector<Certificate::ref>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string getNewIQID();
|
||||
void send(boost::shared_ptr<Stanza> stanza);
|
||||
void handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession> &session);
|
||||
void handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession> &session);
|
||||
void handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session);
|
||||
void handleSessionInitialized();
|
||||
|
||||
private:
|
||||
IDGenerator idGenerator;
|
||||
// [JID][resources][ServerFromClientSession]
|
||||
std::map<std::string, std::list<boost::shared_ptr<ServerFromClientSession> > > sessions;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,68 +1,83 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Swiften/Elements/StreamInitiationFileInfo.h>
|
||||
#include <Swiften/FileTransfer/ConnectivityManager.h>
|
||||
#include <Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h>
|
||||
#include <Swiften/FileTransfer/IncomingFileTransferManager.h>
|
||||
#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h>
|
||||
#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class UserManager;
|
||||
class User;
|
||||
class Component;
|
||||
class Buddy;
|
||||
|
||||
class FileTransferManager {
|
||||
public:
|
||||
typedef struct Transfer {
|
||||
boost::shared_ptr<Swift::OutgoingFileTransfer> ft;
|
||||
Swift::JID from;
|
||||
Swift::JID to;
|
||||
boost::shared_ptr<Swift::ReadBytestream> readByteStream;
|
||||
} Transfer;
|
||||
|
||||
FileTransferManager(Component *component, UserManager *userManager);
|
||||
virtual ~FileTransferManager();
|
||||
|
||||
FileTransferManager::Transfer sendFile(User *user, Buddy *buddy, boost::shared_ptr<Swift::ReadBytestream> byteStream, const Swift::StreamInitiationFileInfo &info);
|
||||
|
||||
private:
|
||||
Component *m_component;
|
||||
UserManager *m_userManager;
|
||||
Swift::CombinedOutgoingFileTransferManager* m_outgoingFTManager;
|
||||
Swift::RemoteJingleTransportCandidateSelectorFactory* m_remoteCandidateSelectorFactory;
|
||||
Swift::LocalJingleTransportCandidateGeneratorFactory* m_localCandidateGeneratorFactory;
|
||||
Swift::JingleSessionManager *m_jingleSessionManager;
|
||||
Swift::SOCKS5BytestreamRegistry* m_bytestreamRegistry;
|
||||
Swift::SOCKS5BytestreamServer* m_bytestreamServer;
|
||||
Swift::SOCKS5BytestreamProxy* m_bytestreamProxy;
|
||||
Swift::SOCKS5BytestreamServer *bytestreamServer;
|
||||
Swift::ConnectivityManager* m_connectivityManager;
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
#include <Swiften/Elements/StreamInitiationFileInfo.h>
|
||||
#if !HAVE_SWIFTEN_3
|
||||
#include <Swiften/FileTransfer/ConnectivityManager.h>
|
||||
#endif
|
||||
#include <Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h>
|
||||
#include <Swiften/FileTransfer/IncomingFileTransferManager.h>
|
||||
#if !HAVE_SWIFTEN_3
|
||||
#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h>
|
||||
#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h>
|
||||
#else
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h>
|
||||
#endif
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#if !HAVE_SWIFTEN_3
|
||||
#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h>
|
||||
#endif
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class UserManager;
|
||||
class User;
|
||||
class Component;
|
||||
class Buddy;
|
||||
|
||||
class FileTransferManager {
|
||||
public:
|
||||
typedef struct Transfer {
|
||||
boost::shared_ptr<Swift::OutgoingFileTransfer> ft;
|
||||
Swift::JID from;
|
||||
Swift::JID to;
|
||||
boost::shared_ptr<Swift::ReadBytestream> readByteStream;
|
||||
} Transfer;
|
||||
|
||||
FileTransferManager(Component *component, UserManager *userManager);
|
||||
virtual ~FileTransferManager();
|
||||
|
||||
FileTransferManager::Transfer sendFile(User *user, Buddy *buddy, boost::shared_ptr<Swift::ReadBytestream> byteStream, const Swift::StreamInitiationFileInfo &info);
|
||||
|
||||
private:
|
||||
Component *m_component;
|
||||
UserManager *m_userManager;
|
||||
Swift::CombinedOutgoingFileTransferManager* m_outgoingFTManager;
|
||||
Swift::RemoteJingleTransportCandidateSelectorFactory* m_remoteCandidateSelectorFactory;
|
||||
Swift::LocalJingleTransportCandidateGeneratorFactory* m_localCandidateGeneratorFactory;
|
||||
Swift::JingleSessionManager *m_jingleSessionManager;
|
||||
Swift::SOCKS5BytestreamRegistry* m_bytestreamRegistry;
|
||||
#if HAVE_SWIFTEN_3
|
||||
Swift::SOCKS5BytestreamServerManager* m_proxyServerManager;
|
||||
Swift::SOCKS5BytestreamProxiesManager *m_proxyManager;
|
||||
#else
|
||||
Swift::SOCKS5BytestreamServer* m_bytestreamServer;
|
||||
Swift::SOCKS5BytestreamProxy* m_bytestreamProxy;
|
||||
Swift::SOCKS5BytestreamServer *bytestreamServer;
|
||||
Swift::ConnectivityManager* m_connectivityManager;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,195 +1,199 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
#include "Swiften/Network/BoostConnectionServer.h"
|
||||
#include "Swiften/Network/Connection.h"
|
||||
#include "Swiften/Elements/ChatState.h"
|
||||
#include "Swiften/Elements/RosterItemPayload.h"
|
||||
#include "Swiften/Elements/VCard.h"
|
||||
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
|
||||
#include "Swiften/Parser/XMPPParser.h"
|
||||
#include "Swiften/Parser/XMPPParserClient.h"
|
||||
#include "Swiften/Serializer/XMPPSerializer.h"
|
||||
#include "storagebackend.h"
|
||||
#include "transport/filetransfermanager.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class UserManager;
|
||||
class User;
|
||||
class Component;
|
||||
class Buddy;
|
||||
class LocalBuddy;
|
||||
class Config;
|
||||
class NetworkConversation;
|
||||
class VCardResponder;
|
||||
class RosterResponder;
|
||||
class BlockResponder;
|
||||
class DummyReadBytestream;
|
||||
class AdminInterface;
|
||||
class DiscoItemsResponder;
|
||||
|
||||
class NetworkPluginServer : Swift::XMPPParserClient {
|
||||
public:
|
||||
struct Backend {
|
||||
int pongReceived;
|
||||
std::list<User *> users;
|
||||
Swift::SafeByteArray data;
|
||||
boost::shared_ptr<Swift::Connection> connection;
|
||||
unsigned long res;
|
||||
unsigned long init_res;
|
||||
unsigned long shared;
|
||||
bool acceptUsers;
|
||||
bool longRun;
|
||||
bool willDie;
|
||||
std::string id;
|
||||
};
|
||||
|
||||
NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder);
|
||||
|
||||
virtual ~NetworkPluginServer();
|
||||
|
||||
void start();
|
||||
|
||||
void setAdminInterface(AdminInterface *adminInterface) {
|
||||
m_adminInterface = adminInterface;
|
||||
}
|
||||
|
||||
int getBackendCount() {
|
||||
return m_clients.size();
|
||||
}
|
||||
|
||||
const std::list<Backend *> &getBackends() {
|
||||
return m_clients;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &getCrashedBackends() {
|
||||
return m_crashedBackends;
|
||||
}
|
||||
|
||||
void collectBackend();
|
||||
|
||||
bool moveToLongRunBackend(User *user);
|
||||
|
||||
void handleMessageReceived(NetworkConversation *conv, boost::shared_ptr<Swift::Message> &message);
|
||||
|
||||
public:
|
||||
void handleNewClientConnection(boost::shared_ptr<Swift::Connection> c);
|
||||
void handleSessionFinished(Backend *c);
|
||||
void handlePongReceived(Backend *c);
|
||||
void handleDataRead(Backend *c, boost::shared_ptr<Swift::SafeByteArray> data);
|
||||
|
||||
void handleConnectedPayload(const std::string &payload);
|
||||
void handleDisconnectedPayload(const std::string &payload);
|
||||
void handleBuddyChangedPayload(const std::string &payload);
|
||||
void handleBuddyRemovedPayload(const std::string &payload);
|
||||
void handleConvMessagePayload(const std::string &payload, bool subject = false);
|
||||
void handleConvMessageAckPayload(const std::string &payload);
|
||||
void handleParticipantChangedPayload(const std::string &payload);
|
||||
void handleRoomChangedPayload(const std::string &payload);
|
||||
void handleVCardPayload(const std::string &payload);
|
||||
void handleChatStatePayload(const std::string &payload, Swift::ChatState::ChatStateType type);
|
||||
void handleAuthorizationPayload(const std::string &payload);
|
||||
void handleAttentionPayload(const std::string &payload);
|
||||
void handleStatsPayload(Backend *c, const std::string &payload);
|
||||
void handleFTStartPayload(const std::string &payload);
|
||||
void handleFTFinishPayload(const std::string &payload);
|
||||
void handleFTDataPayload(Backend *b, const std::string &payload);
|
||||
void handleQueryPayload(Backend *b, const std::string &payload);
|
||||
void handleBackendConfigPayload(const std::string &payload);
|
||||
void handleRoomListPayload(const std::string &payload);
|
||||
void handleRawXML(const std::string &xml);
|
||||
|
||||
void handleUserCreated(User *user);
|
||||
void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password);
|
||||
void handleRoomLeft(User *user, const std::string &room);
|
||||
void handleUserReadyToConnect(User *user);
|
||||
void handleUserPresenceChanged(User *user, Swift::Presence::ref presence);
|
||||
void handleUserDestroyed(User *user);
|
||||
|
||||
void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item);
|
||||
void handleBuddyRemoved(Buddy *buddy);
|
||||
void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item);
|
||||
void handleUserBuddyAdded(User *user, Buddy *buddy);
|
||||
void handleUserBuddyRemoved(User *user, Buddy *buddy);
|
||||
|
||||
void handleBlockToggled(Buddy *buddy);
|
||||
|
||||
void handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> vcard);
|
||||
void handleVCardRequired(User *user, const std::string &name, unsigned int id);
|
||||
|
||||
void handleFTStateChanged(Swift::FileTransfer::State state, const std::string &userName, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long id);
|
||||
void handleFTAccepted(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID);
|
||||
void handleFTRejected(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size);
|
||||
void handleFTDataNeeded(Backend *b, unsigned long ftid);
|
||||
|
||||
void handlePIDTerminated(unsigned long pid);
|
||||
private:
|
||||
void send(boost::shared_ptr<Swift::Connection> &, const std::string &data);
|
||||
|
||||
void pingTimeout();
|
||||
void sendPing(Backend *c);
|
||||
Backend *getFreeClient(bool acceptUsers = true, bool longRun = false, bool check = false);
|
||||
void connectWaitingUsers();
|
||||
void loginDelayFinished();
|
||||
void handleRawIQReceived(boost::shared_ptr<Swift::IQ> iq);
|
||||
void handleRawPresenceReceived(boost::shared_ptr<Swift::Presence> presence);
|
||||
|
||||
void handleStreamStart(const Swift::ProtocolHeader&) {}
|
||||
|
||||
void handleElement(boost::shared_ptr<Swift::Element> element);
|
||||
|
||||
void handleStreamEnd() {}
|
||||
|
||||
UserManager *m_userManager;
|
||||
VCardResponder *m_vcardResponder;
|
||||
RosterResponder *m_rosterResponder;
|
||||
BlockResponder *m_blockResponder;
|
||||
Config *m_config;
|
||||
boost::shared_ptr<Swift::ConnectionServer> m_server;
|
||||
std::list<Backend *> m_clients;
|
||||
std::vector<unsigned long> m_pids;
|
||||
Swift::Timer::ref m_pingTimer;
|
||||
Swift::Timer::ref m_collectTimer;
|
||||
Swift::Timer::ref m_loginTimer;
|
||||
Component *m_component;
|
||||
std::list<User *> m_waitingUsers;
|
||||
bool m_isNextLongRun;
|
||||
std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
|
||||
FileTransferManager *m_ftManager;
|
||||
std::vector<std::string> m_crashedBackends;
|
||||
AdminInterface *m_adminInterface;
|
||||
bool m_startingBackend;
|
||||
DiscoItemsResponder *m_discoItemsResponder;
|
||||
time_t m_lastLogin;
|
||||
Swift::XMPPParser *m_xmppParser;
|
||||
Swift::FullPayloadParserFactoryCollection m_collection;
|
||||
Swift::XMPPSerializer *m_serializer;
|
||||
Swift::FullPayloadSerializerCollection m_collection2;
|
||||
std::map <std::string, std::string> m_id2resource;
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
#include "Swiften/Network/BoostConnectionServer.h"
|
||||
#include "Swiften/Network/Connection.h"
|
||||
#include "Swiften/Elements/ChatState.h"
|
||||
#include "Swiften/Elements/RosterItemPayload.h"
|
||||
#include "Swiften/Elements/VCard.h"
|
||||
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
|
||||
#include "Swiften/Parser/XMPPParser.h"
|
||||
#include "Swiften/Parser/XMPPParserClient.h"
|
||||
#include "Swiften/Serializer/XMPPSerializer.h"
|
||||
#include "storagebackend.h"
|
||||
#include "transport/filetransfermanager.h"
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class UserManager;
|
||||
class User;
|
||||
class Component;
|
||||
class Buddy;
|
||||
class LocalBuddy;
|
||||
class Config;
|
||||
class NetworkConversation;
|
||||
class VCardResponder;
|
||||
class RosterResponder;
|
||||
class BlockResponder;
|
||||
class DummyReadBytestream;
|
||||
class AdminInterface;
|
||||
class DiscoItemsResponder;
|
||||
|
||||
class NetworkPluginServer : Swift::XMPPParserClient {
|
||||
public:
|
||||
struct Backend {
|
||||
int pongReceived;
|
||||
std::list<User *> users;
|
||||
Swift::SafeByteArray data;
|
||||
boost::shared_ptr<Swift::Connection> connection;
|
||||
unsigned long res;
|
||||
unsigned long init_res;
|
||||
unsigned long shared;
|
||||
bool acceptUsers;
|
||||
bool longRun;
|
||||
bool willDie;
|
||||
std::string id;
|
||||
};
|
||||
|
||||
NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder);
|
||||
|
||||
virtual ~NetworkPluginServer();
|
||||
|
||||
void start();
|
||||
|
||||
void setAdminInterface(AdminInterface *adminInterface) {
|
||||
m_adminInterface = adminInterface;
|
||||
}
|
||||
|
||||
int getBackendCount() {
|
||||
return m_clients.size();
|
||||
}
|
||||
|
||||
const std::list<Backend *> &getBackends() {
|
||||
return m_clients;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &getCrashedBackends() {
|
||||
return m_crashedBackends;
|
||||
}
|
||||
|
||||
void collectBackend();
|
||||
|
||||
bool moveToLongRunBackend(User *user);
|
||||
|
||||
void handleMessageReceived(NetworkConversation *conv, boost::shared_ptr<Swift::Message> &message);
|
||||
|
||||
public:
|
||||
void handleNewClientConnection(boost::shared_ptr<Swift::Connection> c);
|
||||
void handleSessionFinished(Backend *c);
|
||||
void handlePongReceived(Backend *c);
|
||||
void handleDataRead(Backend *c, boost::shared_ptr<Swift::SafeByteArray> data);
|
||||
|
||||
void handleConnectedPayload(const std::string &payload);
|
||||
void handleDisconnectedPayload(const std::string &payload);
|
||||
void handleBuddyChangedPayload(const std::string &payload);
|
||||
void handleBuddyRemovedPayload(const std::string &payload);
|
||||
void handleConvMessagePayload(const std::string &payload, bool subject = false);
|
||||
void handleConvMessageAckPayload(const std::string &payload);
|
||||
void handleParticipantChangedPayload(const std::string &payload);
|
||||
void handleRoomChangedPayload(const std::string &payload);
|
||||
void handleVCardPayload(const std::string &payload);
|
||||
void handleChatStatePayload(const std::string &payload, Swift::ChatState::ChatStateType type);
|
||||
void handleAuthorizationPayload(const std::string &payload);
|
||||
void handleAttentionPayload(const std::string &payload);
|
||||
void handleStatsPayload(Backend *c, const std::string &payload);
|
||||
void handleFTStartPayload(const std::string &payload);
|
||||
void handleFTFinishPayload(const std::string &payload);
|
||||
void handleFTDataPayload(Backend *b, const std::string &payload);
|
||||
void handleQueryPayload(Backend *b, const std::string &payload);
|
||||
void handleBackendConfigPayload(const std::string &payload);
|
||||
void handleRoomListPayload(const std::string &payload);
|
||||
void handleRawXML(const std::string &xml);
|
||||
|
||||
void handleUserCreated(User *user);
|
||||
void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password);
|
||||
void handleRoomLeft(User *user, const std::string &room);
|
||||
void handleUserReadyToConnect(User *user);
|
||||
void handleUserPresenceChanged(User *user, Swift::Presence::ref presence);
|
||||
void handleUserDestroyed(User *user);
|
||||
|
||||
void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item);
|
||||
void handleBuddyRemoved(Buddy *buddy);
|
||||
void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item);
|
||||
void handleUserBuddyAdded(User *user, Buddy *buddy);
|
||||
void handleUserBuddyRemoved(User *user, Buddy *buddy);
|
||||
|
||||
void handleBlockToggled(Buddy *buddy);
|
||||
|
||||
void handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> vcard);
|
||||
void handleVCardRequired(User *user, const std::string &name, unsigned int id);
|
||||
|
||||
void handleFTStateChanged(Swift::FileTransfer::State state, const std::string &userName, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long id);
|
||||
void handleFTAccepted(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID);
|
||||
void handleFTRejected(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size);
|
||||
void handleFTDataNeeded(Backend *b, unsigned long ftid);
|
||||
|
||||
void handlePIDTerminated(unsigned long pid);
|
||||
private:
|
||||
void send(boost::shared_ptr<Swift::Connection> &, const std::string &data);
|
||||
|
||||
void pingTimeout();
|
||||
void sendPing(Backend *c);
|
||||
Backend *getFreeClient(bool acceptUsers = true, bool longRun = false, bool check = false);
|
||||
void connectWaitingUsers();
|
||||
void loginDelayFinished();
|
||||
void handleRawIQReceived(boost::shared_ptr<Swift::IQ> iq);
|
||||
void handleRawPresenceReceived(boost::shared_ptr<Swift::Presence> presence);
|
||||
|
||||
void handleStreamStart(const Swift::ProtocolHeader&) {}
|
||||
#if HAVE_SWIFTEN_3
|
||||
void handleElement(boost::shared_ptr<Swift::ToplevelElement> element);
|
||||
#else
|
||||
void handleElement(boost::shared_ptr<Swift::Element> element);
|
||||
#endif
|
||||
void handleStreamEnd() {}
|
||||
|
||||
UserManager *m_userManager;
|
||||
VCardResponder *m_vcardResponder;
|
||||
RosterResponder *m_rosterResponder;
|
||||
BlockResponder *m_blockResponder;
|
||||
Config *m_config;
|
||||
boost::shared_ptr<Swift::ConnectionServer> m_server;
|
||||
std::list<Backend *> m_clients;
|
||||
std::vector<unsigned long> m_pids;
|
||||
Swift::Timer::ref m_pingTimer;
|
||||
Swift::Timer::ref m_collectTimer;
|
||||
Swift::Timer::ref m_loginTimer;
|
||||
Component *m_component;
|
||||
std::list<User *> m_waitingUsers;
|
||||
bool m_isNextLongRun;
|
||||
std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
|
||||
FileTransferManager *m_ftManager;
|
||||
std::vector<std::string> m_crashedBackends;
|
||||
AdminInterface *m_adminInterface;
|
||||
bool m_startingBackend;
|
||||
DiscoItemsResponder *m_discoItemsResponder;
|
||||
time_t m_lastLogin;
|
||||
Swift::XMPPParser *m_xmppParser;
|
||||
Swift::FullPayloadParserFactoryCollection m_collection;
|
||||
Swift::XMPPSerializer *m_serializer;
|
||||
Swift::FullPayloadSerializerCollection m_collection2;
|
||||
std::map <std::string, std::string> m_id2resource;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,75 +1,77 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include "transport/adhoccommand.h"
|
||||
#include "transport/adhoccommandfactory.h"
|
||||
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class Component;
|
||||
class UserManager;
|
||||
class StorageBackend;
|
||||
|
||||
class SettingsAdHocCommand : public AdHocCommand {
|
||||
public:
|
||||
typedef enum { Init, WaitingForResponse } State;
|
||||
|
||||
SettingsAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~SettingsAdHocCommand();
|
||||
|
||||
virtual boost::shared_ptr<Swift::Command> handleRequest(boost::shared_ptr<Swift::Command> payload);
|
||||
|
||||
private:
|
||||
boost::shared_ptr<Swift::Command> getForm();
|
||||
boost::shared_ptr<Swift::Command> handleResponse(boost::shared_ptr<Swift::Command> payload);
|
||||
State m_state;
|
||||
};
|
||||
|
||||
class SettingsAdHocCommandFactory : public AdHocCommandFactory {
|
||||
public:
|
||||
SettingsAdHocCommandFactory() {
|
||||
m_userSettings["send_headlines"] = "0";
|
||||
m_userSettings["stay_connected"] = "0";
|
||||
}
|
||||
|
||||
virtual ~SettingsAdHocCommandFactory() {}
|
||||
|
||||
AdHocCommand *createAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) {
|
||||
return new SettingsAdHocCommand(component, userManager, storageBackend, initiator, to);
|
||||
}
|
||||
|
||||
std::string getNode() {
|
||||
return "settings";
|
||||
}
|
||||
|
||||
std::string getName() {
|
||||
return "Transport settings";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include "transport/adhoccommand.h"
|
||||
#include "transport/adhoccommandfactory.h"
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class Component;
|
||||
class UserManager;
|
||||
class StorageBackend;
|
||||
|
||||
class SettingsAdHocCommand : public AdHocCommand {
|
||||
public:
|
||||
typedef enum { Init, WaitingForResponse } State;
|
||||
|
||||
SettingsAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~SettingsAdHocCommand();
|
||||
|
||||
virtual boost::shared_ptr<Swift::Command> handleRequest(boost::shared_ptr<Swift::Command> payload);
|
||||
|
||||
private:
|
||||
boost::shared_ptr<Swift::Command> getForm();
|
||||
boost::shared_ptr<Swift::Command> handleResponse(boost::shared_ptr<Swift::Command> payload);
|
||||
State m_state;
|
||||
};
|
||||
|
||||
class SettingsAdHocCommandFactory : public AdHocCommandFactory {
|
||||
public:
|
||||
SettingsAdHocCommandFactory() {
|
||||
m_userSettings["send_headlines"] = "0";
|
||||
m_userSettings["stay_connected"] = "0";
|
||||
}
|
||||
|
||||
virtual ~SettingsAdHocCommandFactory() {}
|
||||
|
||||
AdHocCommand *createAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) {
|
||||
return new SettingsAdHocCommand(component, userManager, storageBackend, initiator, to);
|
||||
}
|
||||
|
||||
std::string getNode() {
|
||||
return "settings";
|
||||
}
|
||||
|
||||
std::string getName() {
|
||||
return "Transport settings";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,85 +1,87 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Swiften/Queries/Responder.h"
|
||||
#include "Swiften/Elements/InBandRegistrationPayload.h"
|
||||
#include "Swiften/Elements/RosterPayload.h"
|
||||
#include <boost/signal.hpp>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
struct UserInfo;
|
||||
class Component;
|
||||
class StorageBackend;
|
||||
class UserManager;
|
||||
class Config;
|
||||
|
||||
/// Allows users to register the transport using service discovery.
|
||||
class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayload> {
|
||||
public:
|
||||
/// Creates new UserRegistration handler.
|
||||
/// \param component Component associated with this class
|
||||
/// \param userManager UserManager associated with this class
|
||||
/// \param storageBackend StorageBackend where the registered users will be stored
|
||||
UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend);
|
||||
|
||||
/// Destroys UserRegistration.
|
||||
~UserRegistration();
|
||||
|
||||
/// Registers new user. This function stores user into database and subscribe user to transport.
|
||||
/// \param userInfo UserInfo struct with informations about registered user
|
||||
/// \return false if user is already registered
|
||||
bool registerUser(const UserInfo &userInfo);
|
||||
|
||||
/// Unregisters user. This function removes all data about user from databa, unsubscribe all buddies
|
||||
/// managed by this transport and disconnects user if he's connected.
|
||||
/// \param barejid bare JID of user to unregister
|
||||
/// \return false if there is no such user registered
|
||||
bool unregisterUser(const std::string &barejid);
|
||||
|
||||
/// Called when new user has been registered.
|
||||
/// \param userInfo UserInfo struct with informations about user
|
||||
boost::signal<void (const UserInfo &userInfo)> onUserRegistered;
|
||||
|
||||
/// Called when user has been unregistered.
|
||||
/// \param userInfo UserInfo struct with informations about user
|
||||
boost::signal<void (const UserInfo &userInfo)> onUserUnregistered;
|
||||
|
||||
/// Called when user's registration has been updated.
|
||||
/// \param userInfo UserInfo struct with informations about user
|
||||
boost::signal<void (const UserInfo &userInfo)> onUserUpdated;
|
||||
|
||||
private:
|
||||
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
|
||||
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
|
||||
|
||||
void handleRegisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const UserInfo &row);
|
||||
void handleUnregisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const std::string &barejid);
|
||||
|
||||
Component *m_component;
|
||||
StorageBackend *m_storageBackend;
|
||||
UserManager *m_userManager;
|
||||
Config *m_config;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Swiften/Queries/Responder.h"
|
||||
#include "Swiften/Elements/InBandRegistrationPayload.h"
|
||||
#include "Swiften/Elements/RosterPayload.h"
|
||||
#include <boost/signal.hpp>
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
|
||||
namespace Transport {
|
||||
|
||||
struct UserInfo;
|
||||
class Component;
|
||||
class StorageBackend;
|
||||
class UserManager;
|
||||
class Config;
|
||||
|
||||
/// Allows users to register the transport using service discovery.
|
||||
class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayload> {
|
||||
public:
|
||||
/// Creates new UserRegistration handler.
|
||||
/// \param component Component associated with this class
|
||||
/// \param userManager UserManager associated with this class
|
||||
/// \param storageBackend StorageBackend where the registered users will be stored
|
||||
UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend);
|
||||
|
||||
/// Destroys UserRegistration.
|
||||
~UserRegistration();
|
||||
|
||||
/// Registers new user. This function stores user into database and subscribe user to transport.
|
||||
/// \param userInfo UserInfo struct with informations about registered user
|
||||
/// \return false if user is already registered
|
||||
bool registerUser(const UserInfo &userInfo);
|
||||
|
||||
/// Unregisters user. This function removes all data about user from databa, unsubscribe all buddies
|
||||
/// managed by this transport and disconnects user if he's connected.
|
||||
/// \param barejid bare JID of user to unregister
|
||||
/// \return false if there is no such user registered
|
||||
bool unregisterUser(const std::string &barejid);
|
||||
|
||||
/// Called when new user has been registered.
|
||||
/// \param userInfo UserInfo struct with informations about user
|
||||
boost::signal<void (const UserInfo &userInfo)> onUserRegistered;
|
||||
|
||||
/// Called when user has been unregistered.
|
||||
/// \param userInfo UserInfo struct with informations about user
|
||||
boost::signal<void (const UserInfo &userInfo)> onUserUnregistered;
|
||||
|
||||
/// Called when user's registration has been updated.
|
||||
/// \param userInfo UserInfo struct with informations about user
|
||||
boost::signal<void (const UserInfo &userInfo)> onUserUpdated;
|
||||
|
||||
private:
|
||||
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
|
||||
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
|
||||
|
||||
void handleRegisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const UserInfo &row);
|
||||
void handleUnregisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const std::string &barejid);
|
||||
|
||||
Component *m_component;
|
||||
StorageBackend *m_storageBackend;
|
||||
UserManager *m_userManager;
|
||||
Config *m_config;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
ADD_SUBDIRECTORY(sqlite3)
|
||||
ADD_SUBDIRECTORY(curl)
|
||||
ADD_SUBDIRECTORY(sqlite3)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9ce2d7001939b795b45a8ce7700d1a3dcde0475d
|
||||
Subproject commit f39b1c080129c01c8204d3a5a40aad038c7a57f3
|
|
@ -1,161 +1,167 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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 "discoinforesponder.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "Swiften/Disco/DiscoInfoResponder.h"
|
||||
#include "Swiften/Queries/IQRouter.h"
|
||||
#include "Swiften/Elements/DiscoInfo.h"
|
||||
#include "transport/config.h"
|
||||
#include "transport/logging.h"
|
||||
#include "Swiften/Disco/CapsInfoGenerator.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
||||
DEFINE_LOGGER(logger, "DiscoInfoResponder");
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder<DiscoInfo>(router) {
|
||||
m_config = config;
|
||||
m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateFeatures, this));
|
||||
m_buddyInfo = NULL;
|
||||
m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"),
|
||||
CONFIG_STRING(m_config, "identity.category"),
|
||||
CONFIG_STRING(m_config, "identity.type")));
|
||||
|
||||
updateFeatures();
|
||||
}
|
||||
|
||||
DiscoInfoResponder::~DiscoInfoResponder() {
|
||||
delete m_buddyInfo;
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::updateFeatures() {
|
||||
std::list<std::string> features2;
|
||||
features2.push_back("jabber:iq:register");
|
||||
features2.push_back("jabber:iq:gateway");
|
||||
features2.push_back("jabber:iq:private");
|
||||
features2.push_back("http://jabber.org/protocol/disco#info");
|
||||
features2.push_back("http://jabber.org/protocol/commands");
|
||||
if (CONFIG_BOOL_DEFAULTED(m_config, "features.muc", false)) {
|
||||
features2.push_back("http://jabber.org/protocol/muc");
|
||||
}
|
||||
setTransportFeatures(features2);
|
||||
|
||||
std::list<std::string> features;
|
||||
features.push_back("http://jabber.org/protocol/disco#items");
|
||||
features.push_back("http://jabber.org/protocol/disco#info");
|
||||
features.push_back("http://jabber.org/protocol/chatstates");
|
||||
features.push_back("http://jabber.org/protocol/xhtml-im");
|
||||
if (CONFIG_BOOL_DEFAULTED(m_config, "features.receipts", false)) {
|
||||
features.push_back("urn:xmpp:receipts");
|
||||
}
|
||||
setBuddyFeatures(features);
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::setTransportFeatures(std::list<std::string> &features) {
|
||||
for (std::list<std::string>::iterator it = features.begin(); it != features.end(); it++) {
|
||||
if (!m_transportInfo.hasFeature(*it)) {
|
||||
m_transportInfo.addFeature(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::setBuddyFeatures(std::list<std::string> &f) {
|
||||
delete m_buddyInfo;
|
||||
m_buddyInfo = new Swift::DiscoInfo;
|
||||
m_buddyInfo->addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), "client", "pc"));
|
||||
|
||||
for (std::list<std::string>::iterator it = f.begin(); it != f.end(); it++) {
|
||||
if (!m_buddyInfo->hasFeature(*it)) {
|
||||
m_buddyInfo->addFeature(*it);
|
||||
}
|
||||
}
|
||||
|
||||
CapsInfoGenerator caps("spectrum");
|
||||
m_capsInfo = caps.generateCapsInfo(*m_buddyInfo);
|
||||
onBuddyCapsInfoChanged(m_capsInfo);
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::addRoom(const std::string &jid, const std::string &name) {
|
||||
std::string j = jid;
|
||||
boost::algorithm::to_lower(j);
|
||||
m_rooms[j] = name;
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::clearRooms() {
|
||||
m_rooms.clear();
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::addAdHocCommand(const std::string &node, const std::string &name) {
|
||||
m_commands[node] = node;
|
||||
}
|
||||
|
||||
bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> info) {
|
||||
// disco#info for transport
|
||||
if (to.getNode().empty()) {
|
||||
// Adhoc command
|
||||
if (m_commands.find(info->getNode()) != m_commands.end()) {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
|
||||
res->addFeature("http://jabber.org/protocol/commands");
|
||||
res->addFeature("jabber:x:data");
|
||||
res->addIdentity(DiscoInfo::Identity(m_commands[info->getNode()], "automation", "command-node"));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
else if (info->getNode() == "http://jabber.org/protocol/commands") {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
|
||||
res->addIdentity(DiscoInfo::Identity("Commands", "automation", "command-list"));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
else {
|
||||
if (!info->getNode().empty()) {
|
||||
sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_transportInfo));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, id, res);
|
||||
}
|
||||
}
|
||||
// disco#info for room
|
||||
else if (m_rooms.find(to.toBare().toString()) != m_rooms.end()) {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
|
||||
res->addIdentity(DiscoInfo::Identity(m_rooms[to.toBare().toString()], "conference", "text"));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
// disco#info for buddy
|
||||
else {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(*m_buddyInfo));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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 "discoinforesponder.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "Swiften/Disco/DiscoInfoResponder.h"
|
||||
#include "Swiften/Queries/IQRouter.h"
|
||||
#include "Swiften/Elements/DiscoInfo.h"
|
||||
#include "transport/config.h"
|
||||
#include "transport/logging.h"
|
||||
#include "Swiften/Disco/CapsInfoGenerator.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
||||
DEFINE_LOGGER(logger, "DiscoInfoResponder");
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder<DiscoInfo>(router) {
|
||||
m_config = config;
|
||||
m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateFeatures, this));
|
||||
m_buddyInfo = NULL;
|
||||
m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"),
|
||||
CONFIG_STRING(m_config, "identity.category"),
|
||||
CONFIG_STRING(m_config, "identity.type")));
|
||||
#if HAVE_SWIFTEN_3
|
||||
crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
|
||||
#endif
|
||||
|
||||
updateFeatures();
|
||||
}
|
||||
|
||||
DiscoInfoResponder::~DiscoInfoResponder() {
|
||||
delete m_buddyInfo;
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::updateFeatures() {
|
||||
std::list<std::string> features2;
|
||||
features2.push_back("jabber:iq:register");
|
||||
features2.push_back("jabber:iq:gateway");
|
||||
features2.push_back("jabber:iq:private");
|
||||
features2.push_back("http://jabber.org/protocol/disco#info");
|
||||
features2.push_back("http://jabber.org/protocol/commands");
|
||||
if (CONFIG_BOOL_DEFAULTED(m_config, "features.muc", false)) {
|
||||
features2.push_back("http://jabber.org/protocol/muc");
|
||||
}
|
||||
setTransportFeatures(features2);
|
||||
|
||||
std::list<std::string> features;
|
||||
features.push_back("http://jabber.org/protocol/disco#items");
|
||||
features.push_back("http://jabber.org/protocol/disco#info");
|
||||
features.push_back("http://jabber.org/protocol/chatstates");
|
||||
features.push_back("http://jabber.org/protocol/xhtml-im");
|
||||
if (CONFIG_BOOL_DEFAULTED(m_config, "features.receipts", false)) {
|
||||
features.push_back("urn:xmpp:receipts");
|
||||
}
|
||||
setBuddyFeatures(features);
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::setTransportFeatures(std::list<std::string> &features) {
|
||||
for (std::list<std::string>::iterator it = features.begin(); it != features.end(); it++) {
|
||||
if (!m_transportInfo.hasFeature(*it)) {
|
||||
m_transportInfo.addFeature(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::setBuddyFeatures(std::list<std::string> &f) {
|
||||
delete m_buddyInfo;
|
||||
m_buddyInfo = new Swift::DiscoInfo;
|
||||
m_buddyInfo->addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), "client", "pc"));
|
||||
|
||||
for (std::list<std::string>::iterator it = f.begin(); it != f.end(); it++) {
|
||||
if (!m_buddyInfo->hasFeature(*it)) {
|
||||
m_buddyInfo->addFeature(*it);
|
||||
}
|
||||
}
|
||||
#if HAVE_SWIFTEN_3
|
||||
CapsInfoGenerator caps("spectrum", crypto.get());
|
||||
#else
|
||||
CapsInfoGenerator caps("spectrum");
|
||||
#endif
|
||||
m_capsInfo = caps.generateCapsInfo(*m_buddyInfo);
|
||||
onBuddyCapsInfoChanged(m_capsInfo);
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::addRoom(const std::string &jid, const std::string &name) {
|
||||
std::string j = jid;
|
||||
boost::algorithm::to_lower(j);
|
||||
m_rooms[j] = name;
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::clearRooms() {
|
||||
m_rooms.clear();
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::addAdHocCommand(const std::string &node, const std::string &name) {
|
||||
m_commands[node] = node;
|
||||
}
|
||||
|
||||
bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> info) {
|
||||
// disco#info for transport
|
||||
if (to.getNode().empty()) {
|
||||
// Adhoc command
|
||||
if (m_commands.find(info->getNode()) != m_commands.end()) {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
|
||||
res->addFeature("http://jabber.org/protocol/commands");
|
||||
res->addFeature("jabber:x:data");
|
||||
res->addIdentity(DiscoInfo::Identity(m_commands[info->getNode()], "automation", "command-node"));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
else if (info->getNode() == "http://jabber.org/protocol/commands") {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
|
||||
res->addIdentity(DiscoInfo::Identity("Commands", "automation", "command-list"));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
else {
|
||||
if (!info->getNode().empty()) {
|
||||
sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_transportInfo));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, id, res);
|
||||
}
|
||||
}
|
||||
// disco#info for room
|
||||
else if (m_rooms.find(to.toBare().toString()) != m_rooms.end()) {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
|
||||
res->addIdentity(DiscoInfo::Identity(m_rooms[to.toBare().toString()], "conference", "text"));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
// disco#info for buddy
|
||||
else {
|
||||
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(*m_buddyInfo));
|
||||
res->setNode(info->getNode());
|
||||
sendResponse(from, to, id, res);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,65 +1,75 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/signal.hpp>
|
||||
#include "Swiften/Queries/GetResponder.h"
|
||||
#include "Swiften/Elements/DiscoInfo.h"
|
||||
#include "Swiften/Elements/CapsInfo.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class Config;
|
||||
|
||||
class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
|
||||
public:
|
||||
DiscoInfoResponder(Swift::IQRouter *router, Config *config);
|
||||
~DiscoInfoResponder();
|
||||
|
||||
void setTransportFeatures(std::list<std::string> &features);
|
||||
void setBuddyFeatures(std::list<std::string> &features);
|
||||
|
||||
void addRoom(const std::string &jid, const std::string &name);
|
||||
void clearRooms();
|
||||
|
||||
void addAdHocCommand(const std::string &node, const std::string &name);
|
||||
|
||||
boost::signal<void (const Swift::CapsInfo &capsInfo)> onBuddyCapsInfoChanged;
|
||||
|
||||
Swift::CapsInfo &getBuddyCapsInfo() {
|
||||
return m_capsInfo;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> payload);
|
||||
void updateFeatures();
|
||||
|
||||
Swift::DiscoInfo m_transportInfo;
|
||||
Swift::DiscoInfo *m_buddyInfo;
|
||||
Config *m_config;
|
||||
Swift::CapsInfo m_capsInfo;
|
||||
std::map<std::string, std::string> m_rooms;
|
||||
std::map<std::string, std::string> m_commands;
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/signal.hpp>
|
||||
#include "Swiften/Queries/GetResponder.h"
|
||||
#include "Swiften/Elements/DiscoInfo.h"
|
||||
#include "Swiften/Elements/CapsInfo.h"
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 SWIFTEN_VERSION >= 0x030000
|
||||
#if HAVE_SWIFTEN_3
|
||||
#include <Swiften/Crypto/CryptoProvider.h>
|
||||
#include <Swiften/Crypto/PlatformCryptoProvider.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class Config;
|
||||
|
||||
class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
|
||||
public:
|
||||
DiscoInfoResponder(Swift::IQRouter *router, Config *config);
|
||||
~DiscoInfoResponder();
|
||||
|
||||
void setTransportFeatures(std::list<std::string> &features);
|
||||
void setBuddyFeatures(std::list<std::string> &features);
|
||||
|
||||
void addRoom(const std::string &jid, const std::string &name);
|
||||
void clearRooms();
|
||||
|
||||
void addAdHocCommand(const std::string &node, const std::string &name);
|
||||
|
||||
boost::signal<void (const Swift::CapsInfo &capsInfo)> onBuddyCapsInfoChanged;
|
||||
|
||||
Swift::CapsInfo &getBuddyCapsInfo() {
|
||||
return m_capsInfo;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> payload);
|
||||
void updateFeatures();
|
||||
|
||||
Swift::DiscoInfo m_transportInfo;
|
||||
Swift::DiscoInfo *m_buddyInfo;
|
||||
Config *m_config;
|
||||
Swift::CapsInfo m_capsInfo;
|
||||
std::map<std::string, std::string> m_rooms;
|
||||
std::map<std::string, std::string> m_commands;
|
||||
#if HAVE_SWIFTEN_3
|
||||
boost::shared_ptr<Swift::CryptoProvider> crypto;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,89 +1,102 @@
|
|||
/**
|
||||
* 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/filetransfermanager.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/buddy.h"
|
||||
#include "transport/logging.h"
|
||||
#include "Swiften/Network/ConnectionServerFactory.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DEFINE_LOGGER(logger, "FileTransferManager");
|
||||
|
||||
FileTransferManager::FileTransferManager(Component *component, UserManager *userManager) {
|
||||
m_component = component;
|
||||
m_userManager = userManager;
|
||||
|
||||
m_jingleSessionManager = new Swift::JingleSessionManager(m_component->getIQRouter());
|
||||
m_connectivityManager = new Swift::ConnectivityManager(m_component->getNetworkFactories()->getNATTraverser());
|
||||
m_bytestreamRegistry = new Swift::SOCKS5BytestreamRegistry();
|
||||
m_bytestreamProxy = new Swift::SOCKS5BytestreamProxy(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
|
||||
|
||||
m_localCandidateGeneratorFactory = new Swift::DefaultLocalJingleTransportCandidateGeneratorFactory(m_connectivityManager, m_bytestreamRegistry, m_bytestreamProxy, "thishouldnotbeused");
|
||||
m_remoteCandidateSelectorFactory = new Swift::DefaultRemoteJingleTransportCandidateSelectorFactory(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
|
||||
|
||||
boost::shared_ptr<Swift::ConnectionServer> server = m_component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(19645);
|
||||
server->start();
|
||||
m_bytestreamServer = new Swift::SOCKS5BytestreamServer(server, m_bytestreamRegistry);
|
||||
m_bytestreamServer->start();
|
||||
|
||||
m_outgoingFTManager = new Swift::CombinedOutgoingFileTransferManager(m_jingleSessionManager, m_component->getIQRouter(),
|
||||
m_userManager, m_remoteCandidateSelectorFactory,
|
||||
m_localCandidateGeneratorFactory, m_bytestreamRegistry,
|
||||
m_bytestreamProxy, m_component->getPresenceOracle(),
|
||||
m_bytestreamServer);
|
||||
|
||||
// WARNING: Swiften crashes when this is uncommented... But we probably need it for working Jingle FT
|
||||
// m_connectivityManager->addListeningPort(19645);
|
||||
}
|
||||
|
||||
FileTransferManager::~FileTransferManager() {
|
||||
m_bytestreamServer->stop();
|
||||
delete m_outgoingFTManager;
|
||||
delete m_remoteCandidateSelectorFactory;
|
||||
delete m_localCandidateGeneratorFactory;
|
||||
delete m_jingleSessionManager;
|
||||
delete m_bytestreamRegistry;
|
||||
delete m_bytestreamServer;
|
||||
delete m_bytestreamProxy;
|
||||
delete m_connectivityManager;
|
||||
}
|
||||
|
||||
FileTransferManager::Transfer FileTransferManager::sendFile(User *user, Buddy *buddy, boost::shared_ptr<Swift::ReadBytestream> byteStream, const Swift::StreamInitiationFileInfo &info) {
|
||||
FileTransferManager::Transfer transfer;
|
||||
transfer.from = buddy->getJID();
|
||||
transfer.to = user->getJID();
|
||||
transfer.readByteStream = byteStream;
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting FT from '" << transfer.from << "' to '" << transfer.to << "'")
|
||||
|
||||
transfer.ft = m_outgoingFTManager->createOutgoingFileTransfer(transfer.from, transfer.to, transfer.readByteStream, info);
|
||||
// if (transfer.ft) {
|
||||
// m_filetransfers.push_back(ft);
|
||||
// ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id));
|
||||
// transfer.ft->start();
|
||||
// }
|
||||
return transfer;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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/filetransfermanager.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/buddy.h"
|
||||
#include "transport/logging.h"
|
||||
#include "Swiften/Network/ConnectionServerFactory.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DEFINE_LOGGER(logger, "FileTransferManager");
|
||||
|
||||
FileTransferManager::FileTransferManager(Component *component, UserManager *userManager) {
|
||||
m_component = component;
|
||||
m_userManager = userManager;
|
||||
|
||||
m_jingleSessionManager = new Swift::JingleSessionManager(m_component->getIQRouter());
|
||||
#if !HAVE_SWIFTEN_3
|
||||
m_connectivityManager = new Swift::ConnectivityManager(m_component->getNetworkFactories()->getNATTraverser());
|
||||
#endif
|
||||
m_bytestreamRegistry = new Swift::SOCKS5BytestreamRegistry();
|
||||
#if !HAVE_SWIFTEN_3
|
||||
m_bytestreamProxy = new Swift::SOCKS5BytestreamProxy(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
|
||||
m_localCandidateGeneratorFactory = new Swift::DefaultLocalJingleTransportCandidateGeneratorFactory(m_connectivityManager, m_bytestreamRegistry, m_bytestreamProxy, "thishouldnotbeused");
|
||||
m_remoteCandidateSelectorFactory = new Swift::DefaultRemoteJingleTransportCandidateSelectorFactory(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
|
||||
#else
|
||||
m_proxyManager = new Swift::SOCKS5BytestreamProxiesManager(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory(), m_component->getNetworkFactories()->getDomainNameResolver(), m_component->getIQRouter(), "bar.com");
|
||||
#endif
|
||||
boost::shared_ptr<Swift::ConnectionServer> server = m_component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(19645);
|
||||
server->start();
|
||||
#if HAVE_SWIFTEN_3
|
||||
m_proxyServerManager = new Swift::SOCKS5BytestreamServerManager(m_bytestreamRegistry, m_component->getNetworkFactories()->getConnectionServerFactory(), m_component->getNetworkFactories()->getNetworkEnvironment(), m_component->getNetworkFactories()->getNATTraverser());
|
||||
#else
|
||||
m_bytestreamServer = new Swift::SOCKS5BytestreamServer(server, m_bytestreamRegistry);
|
||||
m_bytestreamServer->start();
|
||||
m_outgoingFTManager = new Swift::CombinedOutgoingFileTransferManager(m_jingleSessionManager, m_component->getIQRouter(),
|
||||
m_userManager, m_remoteCandidateSelectorFactory,
|
||||
m_localCandidateGeneratorFactory, m_bytestreamRegistry,
|
||||
m_bytestreamProxy, m_component->getPresenceOracle(),
|
||||
m_bytestreamServer);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// WARNING: Swiften crashes when this is uncommented... But we probably need it for working Jingle FT
|
||||
// m_connectivityManager->addListeningPort(19645);
|
||||
}
|
||||
|
||||
FileTransferManager::~FileTransferManager() {
|
||||
#if !HAVE_SWIFTEN_3
|
||||
m_bytestreamServer->stop();
|
||||
delete m_remoteCandidateSelectorFactory;
|
||||
delete m_localCandidateGeneratorFactory;
|
||||
#endif
|
||||
delete m_outgoingFTManager;
|
||||
delete m_jingleSessionManager;
|
||||
delete m_bytestreamRegistry;
|
||||
#if !HAVE_SWIFTEN_3
|
||||
delete m_bytestreamServer;
|
||||
delete m_bytestreamProxy;
|
||||
delete m_connectivityManager;
|
||||
#endif
|
||||
}
|
||||
|
||||
FileTransferManager::Transfer FileTransferManager::sendFile(User *user, Buddy *buddy, boost::shared_ptr<Swift::ReadBytestream> byteStream, const Swift::StreamInitiationFileInfo &info) {
|
||||
FileTransferManager::Transfer transfer;
|
||||
transfer.from = buddy->getJID();
|
||||
transfer.to = user->getJID();
|
||||
transfer.readByteStream = byteStream;
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting FT from '" << transfer.from << "' to '" << transfer.to << "'")
|
||||
|
||||
transfer.ft = m_outgoingFTManager->createOutgoingFileTransfer(transfer.from, transfer.to, transfer.readByteStream, info);
|
||||
// if (transfer.ft) {
|
||||
// m_filetransfers.push_back(ft);
|
||||
// ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id));
|
||||
// transfer.ft->start();
|
||||
// }
|
||||
return transfer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,146 +1,181 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2012, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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/settingsadhoccommand.h"
|
||||
#include "transport/conversation.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/buddy.h"
|
||||
#include "transport/factory.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/logging.h"
|
||||
#include "transport/storagebackend.h"
|
||||
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DEFINE_LOGGER(logger, "SettingsAdHocCommand");
|
||||
|
||||
SettingsAdHocCommand::SettingsAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) : AdHocCommand(component, userManager, storageBackend, initiator, to) {
|
||||
m_state = Init;
|
||||
Swift::BooleanFormField::ref field;
|
||||
|
||||
field = Swift::BooleanFormField::create(true);
|
||||
field->setName("enable_transport");
|
||||
field->setLabel("Enable transport");
|
||||
addFormField(field);
|
||||
|
||||
field = Swift::BooleanFormField::create(CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.send_headlines", "0") == "1");
|
||||
field->setName("send_headlines");
|
||||
field->setLabel("Allow sending messages as headlines");
|
||||
addFormField(field);
|
||||
|
||||
field = Swift::BooleanFormField::create(CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.stay_connected", "0") == "1");
|
||||
field->setName("stay_connected");
|
||||
field->setLabel("Stay connected to legacy network when offline on XMPP");
|
||||
addFormField(field);
|
||||
}
|
||||
|
||||
SettingsAdHocCommand::~SettingsAdHocCommand() {
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::getForm() {
|
||||
if (!m_storageBackend) {
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
|
||||
boost::shared_ptr<Swift::Form> form(new Swift::Form());
|
||||
form->addField(Swift::FixedFormField::create("This server does not support transport settings. There is no storage backend configured"));
|
||||
response->setForm(form);
|
||||
return response;
|
||||
}
|
||||
|
||||
UserInfo user;
|
||||
if (m_storageBackend->getUser(m_initiator.toBare().toString(), user) == false) {
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
|
||||
boost::shared_ptr<Swift::Form> form(new Swift::Form());
|
||||
form->addField(Swift::FixedFormField::create("You are not registered."));
|
||||
response->setForm(form);
|
||||
return response;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Executing));
|
||||
boost::shared_ptr<Swift::Form> form(new Swift::Form());
|
||||
|
||||
BOOST_FOREACH(Swift::FormField::ref field, m_fields) {
|
||||
// FIXME: Support for more types than boolean
|
||||
if (boost::dynamic_pointer_cast<Swift::BooleanFormField>(field)) {
|
||||
Swift::BooleanFormField::ref f(boost::dynamic_pointer_cast<Swift::BooleanFormField>(field));
|
||||
std::string value = f->getValue() ? "1" : "0";
|
||||
int type = (int) TYPE_BOOLEAN;
|
||||
m_storageBackend->getUserSetting(user.id, f->getName(), type, value);
|
||||
f->setValue(value == "1");
|
||||
}
|
||||
|
||||
form->addField(field);
|
||||
}
|
||||
|
||||
response->setForm(form);
|
||||
return response;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::handleResponse(boost::shared_ptr<Swift::Command> payload) {
|
||||
UserInfo user;
|
||||
bool registered = m_storageBackend->getUser(m_initiator.toBare().toString(), user);
|
||||
|
||||
if (registered && payload->getForm()) {
|
||||
BOOST_FOREACH(Swift::FormField::ref field, m_fields) {
|
||||
Swift::FormField::ref received = payload->getForm()->getField(field->getName());
|
||||
if (!received) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: Support for more types than boolean
|
||||
if (boost::dynamic_pointer_cast<Swift::BooleanFormField>(received)) {
|
||||
Swift::BooleanFormField::ref f(boost::dynamic_pointer_cast<Swift::BooleanFormField>(received));
|
||||
std::string value = f->getValue() ? "1" : "0";
|
||||
m_storageBackend->updateUserSetting(user.id, f->getName(), value);
|
||||
}
|
||||
else if (boost::dynamic_pointer_cast<Swift::TextSingleFormField>(received)) {
|
||||
Swift::TextSingleFormField::ref f(boost::dynamic_pointer_cast<Swift::TextSingleFormField>(received));
|
||||
m_storageBackend->updateUserSetting(user.id, f->getName(), f->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
|
||||
return response;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::handleRequest(boost::shared_ptr<Swift::Command> payload) {
|
||||
boost::shared_ptr<Swift::Command> response;
|
||||
if (payload->getAction() == Swift::Command::Cancel) {
|
||||
response = boost::shared_ptr<Swift::Command>(new Swift::Command("settings", m_id, Swift::Command::Canceled));
|
||||
return response;
|
||||
}
|
||||
|
||||
switch (m_state) {
|
||||
case Init:
|
||||
response = getForm();
|
||||
m_state = WaitingForResponse;
|
||||
break;
|
||||
case WaitingForResponse:
|
||||
response = handleResponse(payload);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2012, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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/settingsadhoccommand.h"
|
||||
#include "transport/conversation.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/buddy.h"
|
||||
#include "transport/factory.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/logging.h"
|
||||
#include "transport/storagebackend.h"
|
||||
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DEFINE_LOGGER(logger, "SettingsAdHocCommand");
|
||||
|
||||
SettingsAdHocCommand::SettingsAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) : AdHocCommand(component, userManager, storageBackend, initiator, to) {
|
||||
m_state = Init;
|
||||
#if HAVE_SWIFTEN_3
|
||||
Swift::FormField::ref field = boost::make_shared<Swift::FormField>(Swift::FormField::BooleanType, "1");
|
||||
#else
|
||||
Swift::BooleanFormField::ref field;
|
||||
|
||||
field = Swift::BooleanFormField::create(true);
|
||||
#endif
|
||||
field->setName("enable_transport");
|
||||
field->setLabel("Enable transport");
|
||||
addFormField(field);
|
||||
#if HAVE_SWIFTEN_3
|
||||
field = boost::make_shared<Swift::FormField>(Swift::FormField::BooleanType, CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.send_headlines", "0"));
|
||||
#else
|
||||
field = Swift::BooleanFormField::create(CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.send_headlines", "0") == "1");
|
||||
#endif
|
||||
field->setName("send_headlines");
|
||||
field->setLabel("Allow sending messages as headlines");
|
||||
addFormField(field);
|
||||
#if HAVE_SWIFTEN_3
|
||||
field = boost::make_shared<Swift::FormField>(Swift::FormField::BooleanType, CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.stay_connected", "0"));
|
||||
#else
|
||||
field = Swift::BooleanFormField::create(CONFIG_STRING_DEFAULTED(component->getConfig(), "settings.stay_connected", "0") == "1");
|
||||
#endif
|
||||
field->setName("stay_connected");
|
||||
field->setLabel("Stay connected to legacy network when offline on XMPP");
|
||||
addFormField(field);
|
||||
}
|
||||
|
||||
SettingsAdHocCommand::~SettingsAdHocCommand() {
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::getForm() {
|
||||
if (!m_storageBackend) {
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
|
||||
boost::shared_ptr<Swift::Form> form(new Swift::Form());
|
||||
#if HAVE_SWIFTEN_3
|
||||
form->addField(boost::make_shared<Swift::FormField>(Swift::FormField::FixedType, "This server does not support transport settings. There is no storage backend configured"));
|
||||
#else
|
||||
form->addField(Swift::FixedFormField::create("This server does not support transport settings. There is no storage backend configured"));
|
||||
#endif
|
||||
response->setForm(form);
|
||||
return response;
|
||||
}
|
||||
|
||||
UserInfo user;
|
||||
if (m_storageBackend->getUser(m_initiator.toBare().toString(), user) == false) {
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
|
||||
boost::shared_ptr<Swift::Form> form(new Swift::Form());
|
||||
#if HAVE_SWIFTEN_3
|
||||
form->addField(boost::make_shared<Swift::FormField>(Swift::FormField::FixedType, "You are not registered."));
|
||||
#else
|
||||
form->addField(Swift::FixedFormField::create("You are not registered."));
|
||||
#endif
|
||||
response->setForm(form);
|
||||
return response;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Executing));
|
||||
boost::shared_ptr<Swift::Form> form(new Swift::Form());
|
||||
|
||||
BOOST_FOREACH(Swift::FormField::ref field, m_fields) {
|
||||
// FIXME: Support for more types than boolean
|
||||
#if HAVE_SWIFTEN_3
|
||||
if (field->getType() == Swift::FormField::BooleanType) {
|
||||
std::string value = field->getBoolValue() ? "1" : "0";
|
||||
int type = (int) TYPE_BOOLEAN;
|
||||
m_storageBackend->getUserSetting(user.id, field->getName(), type, value);
|
||||
field->setBoolValue(value == "1");
|
||||
}
|
||||
#else
|
||||
if (boost::dynamic_pointer_cast<Swift::BooleanFormField>(field)) {
|
||||
Swift::BooleanFormField::ref f(boost::dynamic_pointer_cast<Swift::BooleanFormField>(field));
|
||||
std::string value = f->getValue() ? "1" : "0";
|
||||
int type = (int)TYPE_BOOLEAN;
|
||||
m_storageBackend->getUserSetting(user.id, f->getName(), type, value);
|
||||
f->setValue(value == "1");
|
||||
}
|
||||
#endif
|
||||
|
||||
form->addField(field);
|
||||
}
|
||||
|
||||
response->setForm(form);
|
||||
return response;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::handleResponse(boost::shared_ptr<Swift::Command> payload) {
|
||||
UserInfo user;
|
||||
bool registered = m_storageBackend->getUser(m_initiator.toBare().toString(), user);
|
||||
|
||||
if (registered && payload->getForm()) {
|
||||
BOOST_FOREACH(Swift::FormField::ref field, m_fields) {
|
||||
Swift::FormField::ref received = payload->getForm()->getField(field->getName());
|
||||
if (!received) {
|
||||
continue;
|
||||
}
|
||||
#if HAVE_SWIFTEN_3
|
||||
if (received->getType() == Swift::FormField::BooleanType) {
|
||||
std::string value = received->getBoolValue() ? "1" : "0";
|
||||
m_storageBackend->updateUserSetting(user.id, received->getName(), value);
|
||||
} else if (received->getType() == Swift::FormField::TextSingleType) {
|
||||
m_storageBackend->updateUserSetting(user.id, received->getName(), received->getTextSingleValue());
|
||||
}
|
||||
#else
|
||||
// FIXME: Support for more types than boolean
|
||||
if (boost::dynamic_pointer_cast<Swift::BooleanFormField>(received)) {
|
||||
Swift::BooleanFormField::ref f(boost::dynamic_pointer_cast<Swift::BooleanFormField>(received));
|
||||
std::string value = f->getValue() ? "1" : "0";
|
||||
m_storageBackend->updateUserSetting(user.id, f->getName(), value);
|
||||
}
|
||||
else if (boost::dynamic_pointer_cast<Swift::TextSingleFormField>(received)) {
|
||||
Swift::TextSingleFormField::ref f(boost::dynamic_pointer_cast<Swift::TextSingleFormField>(received));
|
||||
m_storageBackend->updateUserSetting(user.id, f->getName(), f->getValue());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
|
||||
return response;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::handleRequest(boost::shared_ptr<Swift::Command> payload) {
|
||||
boost::shared_ptr<Swift::Command> response;
|
||||
if (payload->getAction() == Swift::Command::Cancel) {
|
||||
response = boost::shared_ptr<Swift::Command>(new Swift::Command("settings", m_id, Swift::Command::Canceled));
|
||||
return response;
|
||||
}
|
||||
|
||||
switch (m_state) {
|
||||
case Init:
|
||||
response = getForm();
|
||||
m_state = WaitingForResponse;
|
||||
break;
|
||||
case WaitingForResponse:
|
||||
response = handleResponse(payload);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,355 +1,363 @@
|
|||
/**
|
||||
* 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/transport.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/factory.h"
|
||||
#include "transport/userregistry.h"
|
||||
#include "transport/logging.h"
|
||||
#include "storageparser.h"
|
||||
#ifdef _WIN32
|
||||
#include <Swiften/TLS/CAPICertificate.h>
|
||||
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
|
||||
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
|
||||
#else
|
||||
#include "Swiften/TLS/PKCS12Certificate.h"
|
||||
#include "Swiften/TLS/CertificateWithKey.h"
|
||||
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
|
||||
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
|
||||
#endif
|
||||
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
|
||||
#include "transport/BlockParser.h"
|
||||
#include "transport/BlockSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
|
||||
#include "Swiften/Parser/GenericPayloadParserFactory.h"
|
||||
#include "Swiften/Queries/IQRouter.h"
|
||||
#include "Swiften/Elements/RosterPayload.h"
|
||||
#include "Swiften/Elements/InBandRegistrationPayload.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DEFINE_LOGGER(logger, "Component");
|
||||
DEFINE_LOGGER(logger_xml, "Component.XML");
|
||||
|
||||
Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) {
|
||||
m_component = NULL;
|
||||
m_userRegistry = NULL;
|
||||
m_server = NULL;
|
||||
m_reconnectCount = 0;
|
||||
m_config = config;
|
||||
m_config->onBackendConfigUpdated.connect(boost::bind(&Component::handleBackendConfigChanged, this));
|
||||
m_factory = factory;
|
||||
m_loop = loop;
|
||||
m_userRegistry = userRegistry;
|
||||
m_rawXML = false;
|
||||
|
||||
m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
|
||||
|
||||
m_factories = factories;
|
||||
|
||||
m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000);
|
||||
m_reconnectTimer->onTick.connect(bind(&Component::start, this));
|
||||
|
||||
if (CONFIG_BOOL(m_config, "service.server_mode")) {
|
||||
LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port"));
|
||||
m_server = new Swift::Server(loop, m_factories, m_userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
|
||||
if (!CONFIG_STRING(m_config, "service.cert").empty()) {
|
||||
#ifndef _WIN32
|
||||
//TODO: fix
|
||||
LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
|
||||
LOG4CXX_INFO(logger, "SSLv23_server_method used.");
|
||||
TLSServerContextFactory *f = new OpenSSLServerContextFactory();
|
||||
CertificateWithKey::ref certificate = boost::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password")));
|
||||
m_server->addTLSEncryption(f, certificate);
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
|
||||
}
|
||||
// m_server->start();
|
||||
m_stanzaChannel = m_server->getStanzaChannel();
|
||||
m_iqRouter = m_server->getIQRouter();
|
||||
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
|
||||
|
||||
m_server->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||
m_server->addPayloadSerializer(new Transport::BlockSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::StatsSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
|
||||
|
||||
m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
||||
m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, "Creating component in gateway mode");
|
||||
m_component = new Swift::Component(loop, m_factories, m_jid, CONFIG_STRING(m_config, "service.password"));
|
||||
m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION);
|
||||
m_component->onConnected.connect(bind(&Component::handleConnected, this));
|
||||
m_component->onError.connect(boost::bind(&Component::handleConnectionError, this, _1));
|
||||
m_component->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
||||
m_component->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
||||
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
|
||||
|
||||
m_component->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||
m_component->addPayloadSerializer(new Transport::BlockSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::StatsSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
|
||||
|
||||
m_stanzaChannel = m_component->getStanzaChannel();
|
||||
m_iqRouter = m_component->getIQRouter();
|
||||
}
|
||||
|
||||
m_capsMemoryStorage = new CapsMemoryStorage();
|
||||
m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter);
|
||||
m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
|
||||
m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
|
||||
|
||||
m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel);
|
||||
m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
|
||||
|
||||
|
||||
|
||||
//
|
||||
// m_registerHandler = new SpectrumRegisterHandler(m_component);
|
||||
// m_registerHandler->start();
|
||||
}
|
||||
|
||||
Component::~Component() {
|
||||
delete m_presenceOracle;
|
||||
delete m_entityCapsManager;
|
||||
delete m_capsManager;
|
||||
delete m_capsMemoryStorage;
|
||||
if (m_component)
|
||||
delete m_component;
|
||||
if (m_server) {
|
||||
m_server->stop();
|
||||
delete m_server;
|
||||
}
|
||||
}
|
||||
|
||||
bool Component::handleIQ(boost::shared_ptr<Swift::IQ> iq) {
|
||||
if (!m_rawXML) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iq->getPayload<Swift::RosterPayload>() != NULL) { return false; }
|
||||
if (iq->getPayload<Swift::InBandRegistrationPayload>() != NULL) { return false; }
|
||||
if (iq->getPayload<Swift::StatsPayload>() != NULL) { return false; }
|
||||
|
||||
if (iq->getTo().getNode().empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
onRawIQReceived(iq);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Component::handleBackendConfigChanged() {
|
||||
if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) {
|
||||
m_rawXML = true;
|
||||
m_iqRouter->addHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
Swift::StanzaChannel *Component::getStanzaChannel() {
|
||||
return m_stanzaChannel;
|
||||
}
|
||||
|
||||
Transport::PresenceOracle *Component::getPresenceOracle() {
|
||||
return m_presenceOracle;
|
||||
}
|
||||
|
||||
void Component::start() {
|
||||
if (m_component && !m_component->isAvailable()) {
|
||||
LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port"));
|
||||
if (CONFIG_INT(m_config, "service.port") == 5222) {
|
||||
LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?");
|
||||
}
|
||||
m_reconnectCount++;
|
||||
m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
else if (m_server) {
|
||||
LOG4CXX_INFO(logger, "Starting component in server mode on port " << CONFIG_INT(m_config, "service.port"));
|
||||
m_server->start();
|
||||
|
||||
//Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer
|
||||
//Ideally, onStopped must be defined in ConnectionServer
|
||||
if (boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())) {
|
||||
boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())->onStopped.connect(boost::bind(&Component::handleServerStopped, this, _1));
|
||||
}
|
||||
|
||||
// We're connected right here, because we're in server mode...
|
||||
handleConnected();
|
||||
}
|
||||
}
|
||||
|
||||
void Component::stop() {
|
||||
if (m_component) {
|
||||
m_reconnectCount = 0;
|
||||
// TODO: Call this once swiften will fix assert(!session_);
|
||||
// m_component->disconnect();
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
else if (m_server) {
|
||||
LOG4CXX_INFO(logger, "Stopping component in server mode on port " << CONFIG_INT(m_config, "service.port"));
|
||||
m_server->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Component::handleConnected() {
|
||||
onConnected();
|
||||
m_reconnectCount = 0;
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
|
||||
void Component::handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e) {
|
||||
if(e != NULL ) {
|
||||
if(*e == Swift::BoostConnectionServer::Conflict) {
|
||||
LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server..");
|
||||
if (CONFIG_INT(m_config, "service.port") == 5347) {
|
||||
LOG4CXX_INFO(logger, "Port 5347 is usually used for components. You are using server_mode=1. Are you sure you don't want to use server_mode=0 and run spectrum as component?");
|
||||
}
|
||||
}
|
||||
if(*e == Swift::BoostConnectionServer::UnknownError)
|
||||
LOG4CXX_INFO(logger, "Unknown error occured! Stopping server..");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Component::handleConnectionError(const ComponentError &error) {
|
||||
onConnectionError(error);
|
||||
// if (m_reconnectCount == 2)
|
||||
// Component::instance()->userManager()->removeAllUsers();
|
||||
std::string str = "Unknown error";
|
||||
switch (error.getType()) {
|
||||
case ComponentError::UnknownError: str = "Unknown error"; break;
|
||||
case ComponentError::ConnectionError: str = "Connection error"; break;
|
||||
case ComponentError::ConnectionReadError: str = "Connection read error"; break;
|
||||
case ComponentError::ConnectionWriteError: str = "Connection write error"; break;
|
||||
case ComponentError::XMLError: str = "XML Error"; break;
|
||||
case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break;
|
||||
case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break;
|
||||
}
|
||||
LOG4CXX_INFO(logger, "Disconnected from XMPP server. Error: " << str);
|
||||
|
||||
m_reconnectTimer->start();
|
||||
}
|
||||
|
||||
void Component::handleDataRead(const Swift::SafeByteArray &data) {
|
||||
std::string d = safeByteArrayToString(data);
|
||||
if (!boost::starts_with(d, "<auth")) {
|
||||
LOG4CXX_INFO(logger_xml, "XML IN " << d);
|
||||
}
|
||||
}
|
||||
|
||||
void Component::handleDataWritten(const Swift::SafeByteArray &data) {
|
||||
LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
|
||||
}
|
||||
|
||||
void Component::handlePresence(Swift::Presence::ref presence) {
|
||||
// filter out login/logout presence spam
|
||||
if (!presence->getTo().getNode().empty())
|
||||
return;
|
||||
|
||||
// filter out bad presences
|
||||
if (!presence->getFrom().isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (presence->getType()) {
|
||||
case Presence::Error:
|
||||
case Presence::Subscribe:
|
||||
case Presence::Subscribed:
|
||||
case Presence::Unsubscribe:
|
||||
case Presence::Unsubscribed:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
// check if we have this client's capabilities and ask for them
|
||||
if (presence->getType() != Swift::Presence::Unavailable) {
|
||||
boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>();
|
||||
if (capsInfo && capsInfo->getHash() == "sha-1") {
|
||||
/*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
|
||||
}
|
||||
#ifdef SUPPORT_LEGACY_CAPS
|
||||
else {
|
||||
GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter);
|
||||
discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
|
||||
discoInfoRequest->send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
onUserPresenceReceived(presence);
|
||||
}
|
||||
|
||||
void Component::handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid) {
|
||||
#ifdef SUPPORT_LEGACY_CAPS
|
||||
onUserDiscoInfoReceived(jid, info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Component::handleCapsChanged(const Swift::JID& jid) {
|
||||
onUserDiscoInfoReceived(jid, m_entityCapsManager->getCaps(jid));
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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/transport.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/factory.h"
|
||||
#include "transport/userregistry.h"
|
||||
#include "transport/logging.h"
|
||||
#include "storageparser.h"
|
||||
#ifdef _WIN32
|
||||
#include <Swiften/TLS/CAPICertificate.h>
|
||||
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
|
||||
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
|
||||
#else
|
||||
#include "Swiften/TLS/PKCS12Certificate.h"
|
||||
#include "Swiften/TLS/CertificateWithKey.h"
|
||||
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
|
||||
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
|
||||
#endif
|
||||
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
|
||||
#include "transport/BlockParser.h"
|
||||
#include "transport/BlockSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
|
||||
#include "Swiften/Parser/GenericPayloadParserFactory.h"
|
||||
#include "Swiften/Queries/IQRouter.h"
|
||||
#include "Swiften/Elements/RosterPayload.h"
|
||||
#include "Swiften/Elements/InBandRegistrationPayload.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DEFINE_LOGGER(logger, "Component");
|
||||
DEFINE_LOGGER(logger_xml, "Component.XML");
|
||||
|
||||
Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) {
|
||||
m_component = NULL;
|
||||
m_userRegistry = NULL;
|
||||
m_server = NULL;
|
||||
m_reconnectCount = 0;
|
||||
m_config = config;
|
||||
m_config->onBackendConfigUpdated.connect(boost::bind(&Component::handleBackendConfigChanged, this));
|
||||
m_factory = factory;
|
||||
m_loop = loop;
|
||||
m_userRegistry = userRegistry;
|
||||
m_rawXML = false;
|
||||
|
||||
m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
|
||||
|
||||
m_factories = factories;
|
||||
|
||||
m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000);
|
||||
m_reconnectTimer->onTick.connect(bind(&Component::start, this));
|
||||
|
||||
if (CONFIG_BOOL(m_config, "service.server_mode")) {
|
||||
LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port"));
|
||||
m_server = new Swift::Server(loop, m_factories, m_userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
|
||||
if (!CONFIG_STRING(m_config, "service.cert").empty()) {
|
||||
#ifndef _WIN32
|
||||
//TODO: fix
|
||||
LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
|
||||
LOG4CXX_INFO(logger, "SSLv23_server_method used.");
|
||||
TLSServerContextFactory *f = new OpenSSLServerContextFactory();
|
||||
CertificateWithKey::ref certificate = boost::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password")));
|
||||
m_server->addTLSEncryption(f, certificate);
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
|
||||
}
|
||||
// m_server->start();
|
||||
m_stanzaChannel = m_server->getStanzaChannel();
|
||||
m_iqRouter = m_server->getIQRouter();
|
||||
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
|
||||
|
||||
m_server->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||
m_server->addPayloadSerializer(new Transport::BlockSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::StatsSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
|
||||
|
||||
m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
||||
m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, "Creating component in gateway mode");
|
||||
#if HAVE_SWIFTEN_3
|
||||
m_component = new Swift::Component(m_jid, CONFIG_STRING(m_config, "service.password"), m_factories);
|
||||
#else
|
||||
m_component = new Swift::Component(loop, m_factories, m_jid, CONFIG_STRING(m_config, "service.password"));
|
||||
#endif
|
||||
m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION);
|
||||
m_component->onConnected.connect(bind(&Component::handleConnected, this));
|
||||
m_component->onError.connect(boost::bind(&Component::handleConnectionError, this, _1));
|
||||
m_component->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
||||
m_component->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
||||
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
|
||||
|
||||
m_component->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||
m_component->addPayloadSerializer(new Transport::BlockSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::StatsSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
|
||||
|
||||
m_stanzaChannel = m_component->getStanzaChannel();
|
||||
m_iqRouter = m_component->getIQRouter();
|
||||
}
|
||||
|
||||
m_capsMemoryStorage = new CapsMemoryStorage();
|
||||
#if HAVE_SWIFTEN_3
|
||||
m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter, m_factories->getCryptoProvider());
|
||||
#else
|
||||
m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter);
|
||||
#endif
|
||||
m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
|
||||
m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
|
||||
|
||||
m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel);
|
||||
m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
|
||||
|
||||
|
||||
|
||||
//
|
||||
// m_registerHandler = new SpectrumRegisterHandler(m_component);
|
||||
// m_registerHandler->start();
|
||||
}
|
||||
|
||||
Component::~Component() {
|
||||
delete m_presenceOracle;
|
||||
delete m_entityCapsManager;
|
||||
delete m_capsManager;
|
||||
delete m_capsMemoryStorage;
|
||||
if (m_component)
|
||||
delete m_component;
|
||||
if (m_server) {
|
||||
m_server->stop();
|
||||
delete m_server;
|
||||
}
|
||||
}
|
||||
|
||||
bool Component::handleIQ(boost::shared_ptr<Swift::IQ> iq) {
|
||||
if (!m_rawXML) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iq->getPayload<Swift::RosterPayload>() != NULL) { return false; }
|
||||
if (iq->getPayload<Swift::InBandRegistrationPayload>() != NULL) { return false; }
|
||||
if (iq->getPayload<Swift::StatsPayload>() != NULL) { return false; }
|
||||
|
||||
if (iq->getTo().getNode().empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
onRawIQReceived(iq);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Component::handleBackendConfigChanged() {
|
||||
if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) {
|
||||
m_rawXML = true;
|
||||
m_iqRouter->addHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
Swift::StanzaChannel *Component::getStanzaChannel() {
|
||||
return m_stanzaChannel;
|
||||
}
|
||||
|
||||
Transport::PresenceOracle *Component::getPresenceOracle() {
|
||||
return m_presenceOracle;
|
||||
}
|
||||
|
||||
void Component::start() {
|
||||
if (m_component && !m_component->isAvailable()) {
|
||||
LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port"));
|
||||
if (CONFIG_INT(m_config, "service.port") == 5222) {
|
||||
LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?");
|
||||
}
|
||||
m_reconnectCount++;
|
||||
m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
else if (m_server) {
|
||||
LOG4CXX_INFO(logger, "Starting component in server mode on port " << CONFIG_INT(m_config, "service.port"));
|
||||
m_server->start();
|
||||
|
||||
//Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer
|
||||
//Ideally, onStopped must be defined in ConnectionServer
|
||||
if (boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())) {
|
||||
boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())->onStopped.connect(boost::bind(&Component::handleServerStopped, this, _1));
|
||||
}
|
||||
|
||||
// We're connected right here, because we're in server mode...
|
||||
handleConnected();
|
||||
}
|
||||
}
|
||||
|
||||
void Component::stop() {
|
||||
if (m_component) {
|
||||
m_reconnectCount = 0;
|
||||
// TODO: Call this once swiften will fix assert(!session_);
|
||||
// m_component->disconnect();
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
else if (m_server) {
|
||||
LOG4CXX_INFO(logger, "Stopping component in server mode on port " << CONFIG_INT(m_config, "service.port"));
|
||||
m_server->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Component::handleConnected() {
|
||||
onConnected();
|
||||
m_reconnectCount = 0;
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
|
||||
void Component::handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e) {
|
||||
if(e != NULL ) {
|
||||
if(*e == Swift::BoostConnectionServer::Conflict) {
|
||||
LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server..");
|
||||
if (CONFIG_INT(m_config, "service.port") == 5347) {
|
||||
LOG4CXX_INFO(logger, "Port 5347 is usually used for components. You are using server_mode=1. Are you sure you don't want to use server_mode=0 and run spectrum as component?");
|
||||
}
|
||||
}
|
||||
if(*e == Swift::BoostConnectionServer::UnknownError)
|
||||
LOG4CXX_INFO(logger, "Unknown error occured! Stopping server..");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Component::handleConnectionError(const ComponentError &error) {
|
||||
onConnectionError(error);
|
||||
// if (m_reconnectCount == 2)
|
||||
// Component::instance()->userManager()->removeAllUsers();
|
||||
std::string str = "Unknown error";
|
||||
switch (error.getType()) {
|
||||
case ComponentError::UnknownError: str = "Unknown error"; break;
|
||||
case ComponentError::ConnectionError: str = "Connection error"; break;
|
||||
case ComponentError::ConnectionReadError: str = "Connection read error"; break;
|
||||
case ComponentError::ConnectionWriteError: str = "Connection write error"; break;
|
||||
case ComponentError::XMLError: str = "XML Error"; break;
|
||||
case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break;
|
||||
case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break;
|
||||
}
|
||||
LOG4CXX_INFO(logger, "Disconnected from XMPP server. Error: " << str);
|
||||
|
||||
m_reconnectTimer->start();
|
||||
}
|
||||
|
||||
void Component::handleDataRead(const Swift::SafeByteArray &data) {
|
||||
std::string d = safeByteArrayToString(data);
|
||||
if (!boost::starts_with(d, "<auth")) {
|
||||
LOG4CXX_INFO(logger_xml, "XML IN " << d);
|
||||
}
|
||||
}
|
||||
|
||||
void Component::handleDataWritten(const Swift::SafeByteArray &data) {
|
||||
LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
|
||||
}
|
||||
|
||||
void Component::handlePresence(Swift::Presence::ref presence) {
|
||||
// filter out login/logout presence spam
|
||||
if (!presence->getTo().getNode().empty())
|
||||
return;
|
||||
|
||||
// filter out bad presences
|
||||
if (!presence->getFrom().isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (presence->getType()) {
|
||||
case Presence::Error:
|
||||
case Presence::Subscribe:
|
||||
case Presence::Subscribed:
|
||||
case Presence::Unsubscribe:
|
||||
case Presence::Unsubscribed:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
// check if we have this client's capabilities and ask for them
|
||||
if (presence->getType() != Swift::Presence::Unavailable) {
|
||||
boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>();
|
||||
if (capsInfo && capsInfo->getHash() == "sha-1") {
|
||||
/*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
|
||||
}
|
||||
#ifdef SUPPORT_LEGACY_CAPS
|
||||
else {
|
||||
GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter);
|
||||
discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
|
||||
discoInfoRequest->send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
onUserPresenceReceived(presence);
|
||||
}
|
||||
|
||||
void Component::handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid) {
|
||||
#ifdef SUPPORT_LEGACY_CAPS
|
||||
onUserDiscoInfoReceived(jid, info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Component::handleCapsChanged(const Swift::JID& jid) {
|
||||
onUserDiscoInfoReceived(jid, m_entityCapsManager->getCaps(jid));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
1008
src/user.cpp
1008
src/user.cpp
File diff suppressed because it is too large
Load diff
1208
src/usermanager.cpp
1208
src/usermanager.cpp
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue