Initial swiften 3 support

This commit is contained in:
Vitaly Takmazov 2015-03-31 14:14:15 +03:00
parent bc4450cfca
commit 0d99e8c85d
65 changed files with 8152 additions and 8960 deletions

File diff suppressed because it is too large Load diff

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,5 @@
#define NOMINMAX
#include <algorithm>
#include <memory.h>
#include "twitcurlurls.h"
#include "twitcurl.h"

View file

@ -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 )

View file

@ -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() {
}
}

View file

@ -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;
};
}

View file

@ -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() {
}
}

View file

@ -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;
};
}

View file

@ -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) {
}
}

View file

@ -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;
};
}

View file

@ -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) {
}
}

View file

@ -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;
};
}

View file

@ -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) {
}
}

View file

@ -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;
};
}

View file

@ -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>();
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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));
}
}
}

View file

@ -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;
};
}

View file

@ -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));
}
}
}

View file

@ -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;
};
}

View file

@ -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));
}
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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
};
}

View file

@ -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;
};
}

View file

@ -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";
}
};
}

View file

@ -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;
};
}

View file

@ -1,2 +1 @@
ADD_SUBDIRECTORY(sqlite3)
ADD_SUBDIRECTORY(curl)
ADD_SUBDIRECTORY(sqlite3)

@ -1 +1 @@
Subproject commit 9ce2d7001939b795b45a8ce7700d1a3dcde0475d
Subproject commit f39b1c080129c01c8204d3a5a40aad038c7a57f3

View file

@ -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;
}
}

View file

@ -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
};
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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));
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff