Skip to content
Browse files

Merge branch 'master' of https://github.com/hanzz/libtransport

  • Loading branch information...
2 parents 68699f9 + 596a58a commit 892af5dc57c2ed20634723b0979944a14c35457e @vitalyster committed
View
4 backends/CMakeLists.txt
@@ -7,6 +7,10 @@ if (PROTOBUF_FOUND)
ADD_SUBDIRECTORY(libcommuni)
endif()
+ ADD_SUBDIRECTORY(smstools3)
+
+ ADD_SUBDIRECTORY(swiften)
+
ADD_SUBDIRECTORY(template)
if (NOT WIN32)
View
26 backends/libpurple/main.cpp
@@ -50,6 +50,21 @@ template <class T> std::string stringOf(T object) {
return (os.str());
}
+static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
+ std::stringstream ss(s);
+ std::string item;
+ while(std::getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+ return elems;
+}
+
+
+static std::vector<std::string> split(const std::string &s, char delim) {
+ std::vector<std::string> elems;
+ return split(s, delim, elems);
+}
+
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond);
class SpectrumNetworkPlugin;
@@ -296,6 +311,17 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
if (ret) {
purple_account_set_int(account, "version", fromString<int>(std::string(contents, length)));
}
+
+
+ if (KEYFILE_STRING("service", "protocol") == "prpl-novell") {
+ std::string username(purple_account_get_username(account));
+ std::vector <std::string> u = split(username, '@');
+ purple_account_set_username(account, (const char*) u.front().c_str());
+ std::vector <std::string> s = split(u.back(), ':');
+ purple_account_set_string(account, "server", s.front().c_str());
+ purple_account_set_int(account, "port", atoi(s.back().c_str()));
+ }
+
}
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
View
10 backends/swiften/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.6)
+
+FILE(GLOB SRC *.cpp)
+
+ADD_EXECUTABLE(spectrum2_swiften_backend ${SRC})
+
+target_link_libraries(spectrum2_swiften_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
+
+INSTALL(TARGETS spectrum2_swiften_backend RUNTIME DESTINATION bin)
+
View
301 backends/swiften/main.cpp
@@ -0,0 +1,301 @@
+// Transport includes
+#include "transport/config.h"
+#include "transport/networkplugin.h"
+#include "transport/logging.h"
+
+// Swiften
+#include "Swiften/Swiften.h"
+
+// for signal handler
+#include "unistd.h"
+#include "signal.h"
+#include "sys/wait.h"
+#include "sys/signal.h"
+
+// malloc_trim
+#include "malloc.h"
+
+// Boost
+#include <boost/algorithm/string.hpp>
+using namespace boost::filesystem;
+using namespace boost::program_options;
+using namespace Transport;
+
+DEFINE_LOGGER(logger, "Swiften");
+
+// eventloop
+Swift::SimpleEventLoop *loop_;
+
+// Plugins
+class SwiftenPlugin;
+SwiftenPlugin *np = NULL;
+
+class SwiftenPlugin : public NetworkPlugin {
+ public:
+ Swift::BoostNetworkFactories *m_factories;
+ Swift::BoostIOServiceThread m_boostIOServiceThread;
+ boost::shared_ptr<Swift::Connection> m_conn;
+
+ SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
+ this->config = config;
+ 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));
+
+ 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) {
+ std::string d(data->begin(), data->end());
+ handleDataRead(d);
+ }
+
+ void handleSwiftDisconnected(const std::string &user, const boost::optional<Swift::ClientError> &error) {
+ std::string message = "";
+ if (error) {
+ switch(error->getType()) {
+ case Swift::ClientError::UnknownError: message = ("Unknown Error"); 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"); break;
+ case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); break;
+ case Swift::ClientError::XMLError: message = ("Error parsing server data"); 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, 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);
+ }
+
+#ifndef WIN32
+ // force returning of memory chunks allocated by libxml2 to kernel
+ malloc_trim(0);
+#endif
+ }
+
+ void handleSwiftConnected(const std::string &user) {
+ 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) {
+ 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);
+ }
+ }
+
+ void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) {
+ std::string body = message->getBody();
+ boost::shared_ptr<Swift::Client> client = m_users[user];
+ if (client) {
+ handleMessage(user, message->getFrom().toBare().toString(), body, "", "");
+ }
+ }
+
+ void handleSwiftVCardReceived(const std::string &user, unsigned int id, Swift::VCard::ref vcard, Swift::ErrorPayload::ref error) {
+ if (error || !vcard) {
+ LOG4CXX_INFO(logger, user << ": error fetching VCard with id=" << id);
+ handleVCard(user, id, "", "", "", "");
+ return;
+ }
+ LOG4CXX_INFO(logger, user << ": VCard fetched - id=" << id);
+ std::string photo((const char *)&vcard->getPhoto()[0], vcard->getPhoto().size());
+ handleVCard(user, id, vcard->getFullName(), vcard->getFullName(), vcard->getNickname(), photo);
+ }
+
+ 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), 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));
+ Swift::ClientOptions opt;
+ opt.allowPLAINWithoutTLS = true;
+ client->connect(opt);
+ }
+
+ 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 = "") {
+ LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
+ boost::shared_ptr<Swift::Client> client = m_users[user];
+ if (client) {
+ boost::shared_ptr<Swift::Message> message(new Swift::Message());
+ message->setTo(Swift::JID(legacyName));
+ message->setFrom(client->getJID());
+ message->setBody(msg);
+
+ client->sendMessage(message);
+ }
+ }
+
+ void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
+ boost::shared_ptr<Swift::Client> client = m_users[user];
+ if (client) {
+ LOG4CXX_INFO(logger, user << ": fetching VCard of " << legacyName << " id=" << id);
+ Swift::GetVCardRequest::ref request = Swift::GetVCardRequest::create(Swift::JID(legacyName), client->getIQRouter());
+ request->onResponse.connect(boost::bind(&SwiftenPlugin::handleSwiftVCardReceived, this, user, id, _1, _2));
+ request->send();
+ }
+ }
+
+ void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
+ LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << ".");
+// handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
+ }
+
+ void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
+
+ }
+
+ private:
+ Config *config;
+ std::map<std::string, boost::shared_ptr<Swift::Client> > m_users;
+};
+
+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);
+ }
+}
+
+
+int main (int argc, char* argv[]) {
+ std::string host;
+ int port;
+
+ if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
+ std::cout << "SIGCHLD handler can't be set\n";
+ return -1;
+ }
+
+ boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
+ desc.add_options()
+ ("host,h", value<std::string>(&host), "host")
+ ("port,p", value<int>(&port), "port")
+ ;
+ try
+ {
+ boost::program_options::variables_map vm;
+ boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
+ boost::program_options::notify(vm);
+ }
+ catch (std::runtime_error& e)
+ {
+ std::cout << desc << "\n";
+ exit(1);
+ }
+ catch (...)
+ {
+ std::cout << desc << "\n";
+ exit(1);
+ }
+
+
+ if (argc < 5) {
+ return 1;
+ }
+
+ Config config;
+ if (!config.load(argv[5])) {
+ std::cerr << "Can't open " << argv[1] << " configuration file.\n";
+ return 1;
+ }
+
+ Logging::initBackendLogging(&config);
+
+ Swift::SimpleEventLoop eventLoop;
+ loop_ = &eventLoop;
+ np = new SwiftenPlugin(&config, &eventLoop, host, port);
+ loop_->run();
+
+ return 0;
+}
View
6 include/transport/config.h
@@ -28,13 +28,13 @@
#include <boost/bind.hpp>
#include <boost/signal.hpp>
-
+#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY)
#define CONFIG_STRING(PTR, KEY) (*PTR)[KEY].as<std::string>()
#define CONFIG_INT(PTR, KEY) (*PTR)[KEY].as<int>()
#define CONFIG_BOOL(PTR, KEY) (*PTR)[KEY].as<bool>()
#define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as<std::list<std::string> >()
-#define CONFIG_VECTOR(PTR, KEY) (*PTR)[KEY].as<std::vector<std::string> >()
-#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY)
+#define CONFIG_VECTOR(PTR, KEY) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as<std::vector<std::string> >() : std::vector<std::string>())
+
namespace Transport {
View
2 plugin/cpp/networkplugin.cpp
@@ -26,6 +26,8 @@
#ifndef WIN32
#include <arpa/inet.h>
+#include <sys/types.h>
+#include <unistd.h>
#else
#include <winsock2.h>
#include <stdint.h>
View
2 spectrum/src/main.cpp
@@ -148,7 +148,7 @@ int main(int argc, char **argv)
boost::program_options::positional_options_description p;
p.add("config", -1);
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
- options(desc).positional(p).run(), vm);
+ options(desc).positional(p).allow_unregistered().run(), vm);
boost::program_options::notify(vm);
if (vm.count("version")) {
View
6 spectrum/src/sample.cfg
@@ -13,10 +13,10 @@ admin_password=test
#cert=server.pfx #patch to PKCS#12 certificate
#cert_password=test #password to that certificate if any
users_per_backend=10
-backend=../..//backends/libpurple/spectrum2_libpurple_backend
+backend=../..//backends/swiften/spectrum2_swiften_backend
#backend=../../backends/template/template_backend.py
-protocol=prpl-jabber
-#protocol=prpl-msn
+#protocol=prpl-jabber
+protocol=prpl-msn
#protocol=any
#protocol=prpl-icq
working_dir=./
View
2 spectrum_manager/src/main.cpp
@@ -308,10 +308,12 @@ static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactorie
Config cfg;
if (cfg.load(itr->path().string()) == false) {
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
+ continue;
}
if (CONFIG_VECTOR(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) {
std::cerr << itr->path().string() << ": service.admin_jid or service.admin_password empty. This server can't be queried over XMPP.\n";
+ continue;
}
finished++;
View
4 spectrum_manager/src/managerconfig.h
@@ -68,6 +68,10 @@ class ManagerConfig {
return m_variables[key];
}
+ bool hasKey(const std::string &key) {
+ return m_variables.find(key) != m_variables.end();
+ }
+
/// Returns path to config file from which data were loaded.
const std::string &getManagerConfigFile() { return m_file; }
View
12 src/config.cpp
@@ -124,6 +124,13 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
("backend.no_vcard_fetch", value<bool>()->default_value(false), "True if VCards for buddies should not be fetched. Only avatars will be forwarded.")
;
+ // Load configs passed by command line
+ if (m_argc != 0 && m_argv) {
+ basic_command_line_parser<char> parser = command_line_parser(m_argc, m_argv).options(opts).allow_unregistered();
+ parsed_options parsed = parser.run();
+ store(parsed, m_variables);
+ }
+
parsed_options parsed = parse_config_file(ifs, opts, true);
bool found_working = false;
@@ -189,11 +196,6 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
}
}
- // Load configs passed by command line
- if (m_argc != 0 && m_argv) {
- store(parse_command_line(m_argc, m_argv, opts), m_variables);
- }
-
store(parsed, m_variables);
notify(m_variables);
View
2 src/userregistration.cpp
@@ -189,7 +189,7 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID
reg->setRegistered(registered);
reg->setUsername(res.uin);
if (CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour")
- reg->setPassword(res.password);
+ reg->setPassword("");
// form

0 comments on commit 892af5d

Please sign in to comment.
Something went wrong with that request. Please try again.