diff --git a/CMakeLists.txt b/CMakeLists.txt index f2c7699ba..ea2f84610 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ option(ENABLE_SMSTOOLS3 "Build SMSTools3 plugin" ON) option(ENABLE_XMPP "Build XMPP plugin" ON) option(ENABLE_TWITTER "Build Twitter plugin" ON) option(ENABLE_WEBUI "Build Web UI" ON) - +option(ENABLE_SLACK_FRONTEND "Build Slack frontend" OFF) option(ENABLE_DOCS "Build Docs" ON) # option(ENABLE_LOG "Build with logging using Log4cxx" ON) option(ENABLE_TESTS "Build Tests using CppUnit" OFF) diff --git a/backends/libcommuni/CMakeLists.txt b/backends/libcommuni/CMakeLists.txt index 0d3ee4ccc..e727aeabb 100644 --- a/backends/libcommuni/CMakeLists.txt +++ b/backends/libcommuni/CMakeLists.txt @@ -13,15 +13,15 @@ add_executable(spectrum2_libcommuni_backend ${SRC}) if(NOT WIN32) if(ENABLE_QT4) - target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport pthread) + target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport-plugin pthread) else() - target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt5::Network Qt5::Core transport pthread) + target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt5::Network Qt5::Core transport-plugin pthread) endif() else() if(ENABLE_QT4) - target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport) + target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport-plugin) else() - target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt5::Network Qt5::Core transport) + target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt5::Network Qt5::Core transport-plugin) endif() endif() diff --git a/backends/swiften/CMakeLists.txt b/backends/swiften/CMakeLists.txt index fa8db5d87..32dd12a5a 100644 --- a/backends/swiften/CMakeLists.txt +++ b/backends/swiften/CMakeLists.txt @@ -3,9 +3,9 @@ file(GLOB SRC *.cpp) add_executable(spectrum2_swiften_backend ${SRC}) if(NOT WIN32) - target_link_libraries(spectrum2_swiften_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + target_link_libraries(spectrum2_swiften_backend transport-plugin pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) else() - target_link_libraries(spectrum2_swiften_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + target_link_libraries(spectrum2_swiften_backend transport-plugin ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) endif() install(TARGETS spectrum2_swiften_backend RUNTIME DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}) diff --git a/backends/swiften/main.cpp b/backends/swiften/main.cpp index 9d6dc4b89..aeb6f0e6d 100644 --- a/backends/swiften/main.cpp +++ b/backends/swiften/main.cpp @@ -80,36 +80,15 @@ class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient { Swift::XMPPParser *m_xmppParser; Swift::FullPayloadParserFactoryCollection m_collection2; - SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() { + SwiftenPlugin(Config *config, 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::fromString(host)), port)); serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType, false); m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory()); m_xmppParser->parse(""); 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(std::shared_ptr data) { - if (m_firstPing) { - m_firstPing = false; - NetworkPlugin::PluginConfig cfg; - cfg.setRawXML(true); - cfg.setNeedRegistration(false); - sendConfig(cfg); - } - std::string d(data->begin(), data->end()); - handleDataRead(d); + connect(host, std::to_string(port)); } void handleStreamStart(const Swift::ProtocolHeader&) {} @@ -446,10 +425,7 @@ int main (int argc, char* argv[]) { Logging::initBackendLogging(cfg); - Swift::SimpleEventLoop eventLoop; - loop_ = &eventLoop; - np = new SwiftenPlugin(cfg, &eventLoop, host, port); - loop_->run(); + np = new SwiftenPlugin(cfg, host, port); return 0; } diff --git a/backends/template/CMakeLists.txt b/backends/template/CMakeLists.txt index 37828416d..66490e639 100644 --- a/backends/template/CMakeLists.txt +++ b/backends/template/CMakeLists.txt @@ -4,12 +4,12 @@ add_executable(spectrum2_template_backend ${SRC}) if(CMAKE_COMPILER_IS_GNUCXX) if(NOT WIN32) - target_link_libraries(spectrum2_template_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + target_link_libraries(spectrum2_template_backend transport-plugin pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) else() - target_link_libraries(spectrum2_template_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + target_link_libraries(spectrum2_template_backend transport-plugin ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) endif() else() - target_link_libraries(spectrum2_template_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + target_link_libraries(spectrum2_template_backend transport-plugin ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) endif() #install(TARGETS spectrum2_template_backend RUNTIME DESTINATION bin) diff --git a/backends/template/main.cpp b/backends/template/main.cpp index 5f9df1a81..1a7324d86 100644 --- a/backends/template/main.cpp +++ b/backends/template/main.cpp @@ -5,9 +5,6 @@ #include "transport/NetworkPlugin.h" #include "transport/Logging.h" -// Swiften -#include "Swiften/Swiften.h" - #ifndef _WIN32 // for signal handler #include "unistd.h" @@ -17,6 +14,7 @@ #endif // Boost #include +#include using namespace boost::filesystem; using namespace boost::program_options; using namespace Transport; @@ -60,9 +58,7 @@ int main (int argc, char* argv[]) { Logging::initBackendLogging(cfg); - Swift::SimpleEventLoop eventLoop; - Plugin p(cfg, &eventLoop, host, port); - eventLoop.run(); + Plugin p(cfg, host, port); return 0; } diff --git a/backends/template/plugin.cpp b/backends/template/plugin.cpp index 57b828487..447476a22 100644 --- a/backends/template/plugin.cpp +++ b/backends/template/plugin.cpp @@ -4,36 +4,19 @@ #include "transport/NetworkPlugin.h" #include "transport/Logging.h" -// Swiften -#include "Swiften/Swiften.h" - // Boost #include +#include using namespace boost::filesystem; using namespace boost::program_options; using namespace Transport; DEFINE_LOGGER(logger, "Backend Template"); -Plugin::Plugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() { +Plugin::Plugin(Config *config, 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(&Plugin::_handleDataRead, this, _1)); - m_conn->connect(Swift::HostAddressPort(*(Swift::HostAddress::fromString(host)), port)); - LOG4CXX_INFO(logger, "Starting the plugin."); -} - -// NetworkPlugin uses this method to send the data to networkplugin server -void Plugin::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 Plugin::_handleDataRead(std::shared_ptr data) { - std::string d(data->begin(), data->end()); - handleDataRead(d); + connect(host, std::to_string(port)); } void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map &settings) { diff --git a/backends/template/plugin.h b/backends/template/plugin.h index be2d876d8..9dc56d7db 100644 --- a/backends/template/plugin.h +++ b/backends/template/plugin.h @@ -1,13 +1,11 @@ #pragma once -#include "Swiften/Swiften.h" - #include "transport/Config.h" #include "transport/NetworkPlugin.h" class Plugin : public Transport::NetworkPlugin { public: - Plugin(Transport::Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port); + Plugin(Transport::Config *config, const std::string &host, int port); // NetworkPlugin uses this method to send the data to networkplugin server void sendData(const std::string &string); @@ -23,12 +21,5 @@ class Plugin : public Transport::NetworkPlugin { void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups); private: - // This method has to call handleDataRead with all received data from network plugin server - void _handleDataRead(std::shared_ptr data); - - private: - Swift::BoostNetworkFactories *m_factories; - Swift::BoostIOServiceThread m_boostIOServiceThread; - std::shared_ptr m_conn; Transport::Config *config; }; diff --git a/backends/twitter/CMakeLists.txt b/backends/twitter/CMakeLists.txt index 93a3af353..4b96144fb 100644 --- a/backends/twitter/CMakeLists.txt +++ b/backends/twitter/CMakeLists.txt @@ -8,7 +8,7 @@ find_package(CURL) if(CURL_FOUND) message(STATUS "Using curl ${CURL_VERSION_STRING}: ${CURL_INCLUDE_DIRS} ${CURL_LIBRARIES}") - target_link_libraries(spectrum2_twitter_backend transport JsonCpp::JsonCpp ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + target_link_libraries(spectrum2_twitter_backend transport-plugin ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) else() message(FATAL_ERROR "curl not found") endif() diff --git a/backends/twitter/HTTPRequest.h b/backends/twitter/HTTPRequest.h deleted file mode 100644 index 40db66a1e..000000000 --- a/backends/twitter/HTTPRequest.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef HTTPREQ_H -#define HTTPREQ_H - -#include "curl/curl.h" -#include "transport/Logging.h" -#include -#include -#include - -class HTTPRequest -{ - CURL *curlhandle; - char curl_errorbuffer[1024]; - std::string error; - std::string callbackdata; - - static int curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest *obj); - - public: - HTTPRequest() { - curlhandle = NULL; - } - - ~HTTPRequest() { - if(curlhandle) { - curl_easy_cleanup(curlhandle); - curlhandle = NULL; - } - } - - bool init(); - void setProxy(std::string, std::string, std::string, std::string); - bool GET(std::string, std::string &); - std::string getCurlError() {return std::string(curl_errorbuffer);} -}; - -#endif diff --git a/backends/twitter/Requests/ProfileImageRequest.cpp b/backends/twitter/Requests/ProfileImageRequest.cpp index 9a42a4527..722810484 100644 --- a/backends/twitter/Requests/ProfileImageRequest.cpp +++ b/backends/twitter/Requests/ProfileImageRequest.cpp @@ -1,5 +1,5 @@ #include "ProfileImageRequest.h" -#include "../HTTPRequest.h" +#include "transport/HTTPRequest.h" DEFINE_LOGGER(profileImageRequestLogger, "ProfileImageRequest") void ProfileImageRequest::run() { diff --git a/backends/twitter/TwitterPlugin.cpp b/backends/twitter/TwitterPlugin.cpp index 59d901872..5ab9eb870 100644 --- a/backends/twitter/TwitterPlugin.cpp +++ b/backends/twitter/TwitterPlugin.cpp @@ -10,12 +10,14 @@ #include "Requests/DestroyFriendRequest.h" #include "Requests/RetweetRequest.h" #include "Requests/ProfileImageRequest.h" -#include "Swiften/StringCodecs/Hexify.h" + +#include + +#include DEFINE_LOGGER(logger, "Twitter Backend"); TwitterPlugin *np = NULL; -Swift::SimpleEventLoop *loop_; // Event Loop const std::string OLD_APP_KEY = "PCWAdQpyyR12ezp2fVwEhw"; const std::string OLD_APP_SECRET = "EveLmCXJIg2R7BTCpm6OWV8YyX49nI0pxnYXh7JMvDg"; @@ -34,8 +36,26 @@ static int cmp(std::string a, std::string b) return 1; } +std::string get_sha1(const std::string& p_arg) +{ + boost::uuids::detail::sha1 sha1; + sha1.process_bytes(p_arg.data(), p_arg.size()); + unsigned hash[5] = {0}; + sha1.get_digest(hash); + + // Back to string + char buf[41] = {0}; + + for (int i = 0; i < 5; i++) + { + std::sprintf(buf + (i << 3), "%08x", hash[i]); + } + + return std::string(buf); +} + -TwitterPlugin::TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port) : NetworkPlugin() +TwitterPlugin::TwitterPlugin(Config *config, StorageBackend *storagebackend, const std::string &host, int port) : NetworkPlugin() { this->config = config; this->storagebackend = storagebackend; @@ -68,26 +88,17 @@ TwitterPlugin::TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, Stora OAUTH_SECRET = "twitter_oauth_secret"; MODE = "mode"; - m_factories = new Swift::BoostNetworkFactories(loop); - m_conn = m_factories->getConnectionFactory()->createConnection(); - m_conn->onDataRead.connect(boost::bind(&TwitterPlugin::_handleDataRead, this, _1)); - m_conn->connect(Swift::HostAddressPort(*(Swift::HostAddress::fromString(host)), port)); - - tp = new ThreadPool(loop_, 10); - LOG4CXX_INFO(logger, "Fetch timeout is set to " << CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000)); - tweet_timer = m_factories->getTimerFactory()->createTimer(CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000)); - message_timer = m_factories->getTimerFactory()->createTimer(CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000)); - - tweet_timer->onTick.connect(boost::bind(&TwitterPlugin::pollForTweets, this)); - //message_timer->onTick.connect(boost::bind(&TwitterPlugin::pollForDirectMessages, this)); + io = std::make_shared(); + tweet_timer = std::make_shared(io, boost::posix_time::seconds(CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000))); + message_timer = std::make_shared(io, boost::posix_time::seconds(CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000))); - tweet_timer->start(); - message_timer->start(); - cryptoProvider = std::shared_ptr(Swift::PlatformCryptoProvider::create()); + tweet_timer->async_wait(boost::bind(&TwitterPlugin::pollForTweets, this)); + //message_timer->async_wait(boost::bind(&TwitterPlugin::pollForDirectMessages, this)); LOG4CXX_INFO(logger, "Starting the plugin."); + connect(host, std::to_string(port)); } TwitterPlugin::~TwitterPlugin() @@ -95,29 +106,6 @@ TwitterPlugin::~TwitterPlugin() delete storagebackend; std::set::iterator it; for (it = onlineUsers.begin() ; it != onlineUsers.end() ; it++) delete userdb[*it].sessions; - delete tp; -} - -// Send data to NetworkPlugin server -void TwitterPlugin::sendData(const std::string &string) -{ - m_conn->write(Swift::createSafeByteArray(string)); -} - -// Receive date from the NetworkPlugin server and invoke the appropirate payload handler (implement in the NetworkPlugin class) -void TwitterPlugin::_handleDataRead(std::shared_ptr data) -{ - if (m_firstPing) { - m_firstPing = false; - // Users can join the network without registering if we allow - // one user to connect multiple IRC networks. - NetworkPlugin::PluginConfig cfg; - cfg.setNeedPassword(false); - sendConfig(cfg); - } - - std::string d(data->begin(), data->end()); - handleDataRead(d); } // User trying to login into his twitter account @@ -655,9 +643,13 @@ void TwitterPlugin::populateRoster(std::string &user, std::vector &friends if(userdb[user].twitterMode == MULTIPLECONTACT) { std::string lastTweet = friends[i].getLastStatus().getTweet(); - //LOG4CXX_INFO(logger, user << " - " << SHA(friendAvatars[i])) + + auto friendAvatarHash = get_sha1(friendAvatars[i]); + + LOG4CXX_INFO(logger, user << " - " << friendAvatarHash); + handleBuddyChanged(user, friends[i].getScreenName(), friends[i].getUserName(), std::vector(), - pbnetwork::STATUS_ONLINE, lastTweet, Swift::Hexify::hexify(cryptoProvider->getSHA1Hash(Swift::createByteArray(friendAvatars[i])))); + pbnetwork::STATUS_ONLINE, lastTweet, friendAvatarHash); } else if(userdb[user].twitterMode == CHATROOM) handleParticipantChanged(user, friends[i].getScreenName(), adminChatRoom, 0, pbnetwork::STATUS_ONLINE); @@ -831,7 +823,7 @@ void TwitterPlugin::createFriendResponse(std::string &user, User &frnd, std::str LOG4CXX_INFO(logger, user << " - " << frnd.getScreenName() << ", " << frnd.getProfileImgURL()); if(userdb[user].twitterMode == MULTIPLECONTACT) { - handleBuddyChanged(user, frnd.getScreenName(), frnd.getUserName(), std::vector(), pbnetwork::STATUS_ONLINE, "", Swift::byteArrayToString(cryptoProvider->getSHA1Hash(Swift::createByteArray(img)))); + handleBuddyChanged(user, frnd.getScreenName(), frnd.getUserName(), std::vector(), pbnetwork::STATUS_ONLINE, "", get_sha1(img)); } else if(userdb[user].twitterMode == CHATROOM) { handleParticipantChanged(user, frnd.getScreenName(), adminChatRoom, 0, pbnetwork::STATUS_ONLINE); } diff --git a/backends/twitter/TwitterPlugin.h b/backends/twitter/TwitterPlugin.h index 967df7fc3..09978cc13 100644 --- a/backends/twitter/TwitterPlugin.h +++ b/backends/twitter/TwitterPlugin.h @@ -9,7 +9,6 @@ #include "transport/StorageBackend.h" #include "transport/ThreadPool.h" -#include #ifndef _WIN32 #include "unistd.h" #include "signal.h" @@ -17,9 +16,11 @@ #include "sys/signal.h" #endif #include +#include #include #include +#include "SHA1.h" #include "twitcurl.h" #include "TwitterResponseParser.h" @@ -30,8 +31,7 @@ #include #include #include -#include -#include + using namespace boost::filesystem; using namespace boost::program_options; using namespace Transport; @@ -40,27 +40,20 @@ using namespace Transport; class TwitterPlugin; extern TwitterPlugin *np; -extern Swift::SimpleEventLoop *loop_; // Event Loop class TwitterPlugin : public NetworkPlugin { public: - Swift::BoostNetworkFactories *m_factories; - Swift::BoostIOServiceThread m_boostIOServiceThread; - std::shared_ptr m_conn; - std::shared_ptr cryptoProvider; - Swift::Timer::ref tweet_timer; - Swift::Timer::ref message_timer; + std::shared_ptr tweet_timer; + std::shared_ptr message_timer; + std::shared_ptr io; StorageBackend *storagebackend; - TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port); + TwitterPlugin(Config *config, 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(std::shared_ptr data); // User trying to login into his twitter account void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map &settings); @@ -153,7 +146,6 @@ class TwitterPlugin : public NetworkPlugin { boost::mutex dblock, userlock; - ThreadPool *tp; std::set onlineUsers; struct UserData { diff --git a/backends/twitter/main.cpp b/backends/twitter/main.cpp index 5d4d61dad..27f285b3e 100644 --- a/backends/twitter/main.cpp +++ b/backends/twitter/main.cpp @@ -52,11 +52,7 @@ int main (int argc, char* argv[]) { LOG4CXX_ERROR(logger, "Can't connect to database!"); return -1; } - - Swift::SimpleEventLoop eventLoop; - loop_ = &eventLoop; - np = new TwitterPlugin(cfg, &eventLoop, storagebackend, host, port); - loop_->run(); + np = new TwitterPlugin(cfg, storagebackend, host, port); return 0; } diff --git a/include/transport/HTTPRequest.h b/include/transport/HTTPRequest.h index ea3fd6473..40db66a1e 100644 --- a/include/transport/HTTPRequest.h +++ b/include/transport/HTTPRequest.h @@ -1,73 +1,37 @@ +#ifndef HTTPREQ_H +#define HTTPREQ_H -#pragma once - -#include -#include +#include "curl/curl.h" #include "transport/Logging.h" -#include "transport/ThreadPool.h" #include #include #include -#include - -namespace Transport { - -class HTTPRequest : public Thread { - public: - typedef enum { Get } Type; - typedef boost::function< void (HTTPRequest *, bool, Json::Value &json, const std::string &data) > Callback; - - HTTPRequest(ThreadPool *tp, Type type, const std::string &url, Callback callback); - HTTPRequest(Type type, const std::string &url); - - virtual ~HTTPRequest(); - - void setProxy(std::string, std::string, std::string, std::string); - bool execute(); - bool execute(Json::Value &json); - std::string getError() {return std::string(curl_errorbuffer);} - const std::string &getRawData() { - return m_data; - } - - void run(); - void finalize(); - const std::string &getURL() { - return m_url; - } - - boost::signals2::signal onRequestFinished; +class HTTPRequest +{ + CURL *curlhandle; + char curl_errorbuffer[1024]; + std::string error; + std::string callbackdata; - static void globalInit() { - curl_global_init(CURL_GLOBAL_ALL); - } + static int curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest *obj); - static void globalCleanup() { - curl_global_cleanup(); + public: + HTTPRequest() { + curlhandle = NULL; + } + + ~HTTPRequest() { + if(curlhandle) { + curl_easy_cleanup(curlhandle); + curlhandle = NULL; } + } - private: - bool init(); - bool GET(std::string url, std::string &output); - bool GET(std::string url, Json::Value &json); - - - CURL *curlhandle; - char curl_errorbuffer[1024]; - std::string error; - std::string callbackdata; - ThreadPool *m_tp; - std::string m_url; - bool m_ok; - Json::Value m_json; - std::string m_data; - Callback m_callback; - Type m_type; - - static int curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest *obj); - + bool init(); + void setProxy(std::string, std::string, std::string, std::string); + bool GET(std::string, std::string &); + std::string getCurlError() {return std::string(curl_errorbuffer);} }; -} - +#endif diff --git a/include/transport/HTTPRequestQueue.h b/include/transport/HTTPRequestQueue.h deleted file mode 100644 index 32475cfa1..000000000 --- a/include/transport/HTTPRequestQueue.h +++ /dev/null @@ -1,40 +0,0 @@ - -#pragma once - -#include "curl/curl.h" -#include "transport/Logging.h" -#include "transport/ThreadPool.h" -#include -#include -#include - -#include "Swiften/Network/Timer.h" - -namespace Transport { - -class HTTPRequest; -class Component; - -class HTTPRequestQueue { - public: - HTTPRequestQueue(Component *component, const std::string &user, int delayBetweenRequests = 1); - - virtual ~HTTPRequestQueue(); - - void queueRequest(HTTPRequest *req); - - void sendNextRequest(); - - private: - void handleRequestFinished(); - - private: - int m_delay; - std::queue m_queue; - HTTPRequest *m_req; - Swift::Timer::ref m_queueTimer; - std::string m_user; -}; - -} - diff --git a/include/transport/NetworkPlugin.h b/include/transport/NetworkPlugin.h index eecf9497d..a696bb5bd 100644 --- a/include/transport/NetworkPlugin.h +++ b/include/transport/NetworkPlugin.h @@ -27,6 +27,8 @@ #include #include +#include + namespace Transport { /// Represents Spectrum2 legacy network plugin. @@ -50,7 +52,6 @@ class NetworkPlugin { void setExtraFields(const std::vector &fields) { m_extraFields = fields; } void setRawXML(bool rawXML = false) { m_rawXML = rawXML; } void disableJIDEscaping() { m_disableJIDEscaping = true; } - private: bool m_needPassword; bool m_needRegistration; @@ -62,15 +63,17 @@ class NetworkPlugin { friend class NetworkPlugin; }; - /// Creates new NetworkPlugin and connects the Spectrum2 NetworkPluginServer. - /// \param loop Event loop. - /// \param host Host where Spectrum2 NetworkPluginServer runs. - /// \param port Port. + /// Creates new NetworkPlugin NetworkPlugin(); /// Destructor. virtual ~NetworkPlugin(); + /// Connects the Spectrum2 NetworkPluginServer. + /// \param host Host where Spectrum2 NetworkPluginServer runs. + /// \param port Port ("http" or "8080") + void connect(const std::string &host, const std::string &port); + void sendConfig(const PluginConfig &cfg); void sendRawXML(std::string &xml); @@ -266,8 +269,8 @@ class NetworkPlugin { virtual void handleMemoryUsage(double &res, double &shared) {res = 0; shared = 0;} virtual void handleExitRequest() { exit(1); } - void handleDataRead(std::string &data); - virtual void sendData(const std::string &string) {} + void handleDataRead(std::istream &data); + void sendData(const std::string& string); void checkPing(); @@ -292,7 +295,7 @@ class NetworkPlugin { std::string m_data; bool m_pingReceived; double m_init_res; - + boost::asio::ip::tcp::iostream stream; }; } diff --git a/libtransport/HTTPRequest.cpp b/libtransport/HTTPRequest.cpp deleted file mode 100644 index a3bcdb819..000000000 --- a/libtransport/HTTPRequest.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "transport/HTTPRequest.h" - -namespace Transport { - -DEFINE_LOGGER(httpRequestLogger, "HTTPRequest") - -HTTPRequest::HTTPRequest(ThreadPool *tp, Type type, const std::string &url, Callback callback) { - m_type = type; - m_url = url; - m_tp = tp; - m_callback = callback; - curlhandle = NULL; -} - -HTTPRequest::HTTPRequest(Type type, const std::string &url) { - m_type = type; - m_url = url; - m_tp = NULL; - curlhandle = NULL; -} - -HTTPRequest::~HTTPRequest() { - if (curlhandle) { - LOG4CXX_INFO(httpRequestLogger, "Cleaning up CURL handle"); - curl_easy_cleanup(curlhandle); - curlhandle = NULL; - } -} - -bool HTTPRequest::init() { - if (curlhandle) { - return true; - } - - curlhandle = curl_easy_init(); - if (curlhandle) { - curl_easy_setopt(curlhandle, CURLOPT_PROXY, NULL); - curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, NULL); - curl_easy_setopt(curlhandle, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY); - return true; - } - - LOG4CXX_ERROR(httpRequestLogger, "Couldn't Initialize curl!"); - return false; -} - -void HTTPRequest::setProxy(std::string IP, std::string port, std::string username, std::string password) { - if (curlhandle) { - std::string proxyIpPort = IP + ":" + port; - curl_easy_setopt(curlhandle, CURLOPT_PROXY, proxyIpPort.c_str()); - if (username.length() && password.length()) { - std::string proxyUserPass = username + ":" + password; - curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, proxyUserPass.c_str()); - } - } else { - LOG4CXX_ERROR(httpRequestLogger, "Trying to set proxy while CURL isn't initialized"); - } -} - -int HTTPRequest::curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest* obj) { - int writtenSize = 0; - if (obj && data) { - obj->callbackdata.append(data, size*nmemb); - writtenSize = (int)(size*nmemb); - } - - return writtenSize; -} - -bool HTTPRequest::GET(std::string url, std::string &data) { - if (curlhandle) { - curl_easy_setopt(curlhandle, CURLOPT_CUSTOMREQUEST, NULL); - curl_easy_setopt(curlhandle, CURLOPT_ENCODING, ""); - - data = ""; - callbackdata = ""; - memset(curl_errorbuffer, 0, 1024); - - curl_easy_setopt(curlhandle, CURLOPT_ERRORBUFFER, curl_errorbuffer); - curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, curlCallBack); - curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, this); - - /* Set http request and url */ - curl_easy_setopt(curlhandle, CURLOPT_HTTPGET, 1); - curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 0); - curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str()); - - /* Send http request and return status*/ - if (CURLE_OK == curl_easy_perform(curlhandle)) { - data = callbackdata; - return true; - } - } else { - LOG4CXX_ERROR(httpRequestLogger, "CURL not initialized!"); - strcpy(curl_errorbuffer, "CURL not initialized!"); - } - LOG4CXX_ERROR(httpRequestLogger, "Error fetching " << url); - return false; -} - -bool HTTPRequest::GET(std::string url, Json::Value &json) { - if (!GET(url, m_data)) { - return false; - } - - Json::CharReaderBuilder rbuilder; - std::shared_ptr const reader(rbuilder.newCharReader()); - if (!reader->parse(m_data.c_str(), m_data.c_str() + m_data.size(), &json, NULL)) { - LOG4CXX_ERROR(httpRequestLogger, "Error while parsing JSON"); - LOG4CXX_ERROR(httpRequestLogger, m_data); - strcpy(curl_errorbuffer, "Error while parsing JSON"); - return false; - } - - return true; -} - -void HTTPRequest::run() { - if (!init()) { - m_ok = false; - return; - } - - switch (m_type) { - case Get: - m_ok = GET(m_url, m_json); - break; - } - - curl_easy_cleanup(curlhandle); - curlhandle = NULL; -} - -void HTTPRequest::finalize() { - m_callback(this, m_ok, m_json, m_data); - onRequestFinished(); -} - -bool HTTPRequest::execute() { - if (!m_tp) { - return false; - } - - m_tp->runAsThread(this); - return true; -} - -bool HTTPRequest::execute(Json::Value &json) { - init(); - switch (m_type) { - case Get: - m_ok = GET(m_url, json); - break; - } - - return m_ok; -} - -} diff --git a/libtransport/HTTPRequestQueue.cpp b/libtransport/HTTPRequestQueue.cpp deleted file mode 100644 index de298806a..000000000 --- a/libtransport/HTTPRequestQueue.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "transport/HTTPRequestQueue.h" -#include "transport/HTTPRequest.h" -#include "transport/Transport.h" - -namespace Transport { - -DEFINE_LOGGER(httpRequestQueueLogger, "HTTPRequestQueue") - -HTTPRequestQueue::HTTPRequestQueue(Component *component, const std::string &user, int delay) { - m_delay = delay; - m_req = NULL; - m_user = user; - - m_queueTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(500); - m_queueTimer->onTick.connect(boost::bind(&HTTPRequestQueue::sendNextRequest, this)); -} - -HTTPRequestQueue::~HTTPRequestQueue() { - m_queueTimer->stop(); - - if (m_req) { - m_req->onRequestFinished.disconnect(boost::bind(&HTTPRequestQueue::handleRequestFinished, this)); - } -} - -void HTTPRequestQueue::handleRequestFinished() { - m_req = NULL; - m_queueTimer->start(); -} - -void HTTPRequestQueue::sendNextRequest() { - if (m_queue.empty()) { - LOG4CXX_INFO(httpRequestQueueLogger, m_user << ": Queue is empty."); - m_req = NULL; - m_queueTimer->stop(); - return; - } - - if (m_req) { - LOG4CXX_INFO(httpRequestQueueLogger, m_user << ": There is already a request being handled."); - return; - } - - m_req = m_queue.front(); - m_queue.pop(); - - LOG4CXX_INFO(httpRequestQueueLogger, m_user << ": Starting request '" << m_req->getURL() << "'."); - m_req->onRequestFinished.connect(boost::bind(&HTTPRequestQueue::handleRequestFinished, this)); - m_req->execute(); -} - -void HTTPRequestQueue::queueRequest(HTTPRequest *req) { - m_queue.push(req); - - if (!m_req) { - sendNextRequest(); - } - else { - LOG4CXX_INFO(httpRequestQueueLogger, m_user << ": Request '" << req->getURL() << "' queued."); - } -} - - -} diff --git a/libtransport/OAuth2.cpp b/libtransport/OAuth2.cpp index bf0f0a592..f6b8e0c3e 100644 --- a/libtransport/OAuth2.cpp +++ b/libtransport/OAuth2.cpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace Transport { @@ -81,20 +82,21 @@ std::string OAuth2::requestToken(const std::string &code, std::string &token, st url += "&redirect_uri=" + Util::urlencode(m_redirectURL); } - Json::Value resp; - HTTPRequest req(HTTPRequest::Get, url); - if (!req.execute(resp)) { + std::string responseData; + HTTPRequest req; + req.init(); + if (!req.GET(url, responseData)) { LOG4CXX_ERROR(oauth2Logger, url); - LOG4CXX_ERROR(oauth2Logger, req.getError()); - return req.getError(); + LOG4CXX_ERROR(oauth2Logger, req.getCurlError()); + return req.getCurlError(); } - LOG4CXX_ERROR(oauth2Logger, req.getRawData()); + LOG4CXX_ERROR(oauth2Logger, responseData); + Json::Value resp(responseData); Json::Value& access_token = resp["access_token"]; if (!access_token.isString()) { LOG4CXX_ERROR(oauth2Logger, "No 'access_token' object in the reply."); LOG4CXX_ERROR(oauth2Logger, url); - LOG4CXX_ERROR(oauth2Logger, req.getRawData()); return "No 'access_token' object in the reply."; } @@ -102,7 +104,6 @@ std::string OAuth2::requestToken(const std::string &code, std::string &token, st if (token.empty()) { LOG4CXX_ERROR(oauth2Logger, "Empty 'access_token' object in the reply."); LOG4CXX_ERROR(oauth2Logger, url); - LOG4CXX_ERROR(oauth2Logger, req.getRawData()); return "Empty 'access_token' object in the reply."; } diff --git a/plugin/cpp/CMakeLists.txt b/plugin/cpp/CMakeLists.txt index 370d02b5e..3fa8e4d33 100644 --- a/plugin/cpp/CMakeLists.txt +++ b/plugin/cpp/CMakeLists.txt @@ -18,10 +18,14 @@ if(CMAKE_COMPILER_IS_GNUCXX) endif() endif() +target_link_libraries(transport-plugin JsonCpp::JsonCpp) + +find_package(CURL) + if(NOT WIN32) - target_link_libraries(transport-plugin ${PROTOBUF_LIBRARY} ${LOG4CXX_LIBRARIES} ${Boost_LIBRARIES}) + target_link_libraries(transport-plugin ${PROTOBUF_LIBRARY} ${LOG4CXX_LIBRARIES} ${Boost_LIBRARIES} ${PQXX_LIBRARIES} ${CURL_LIBRARIES} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES}) else() - target_link_libraries(transport-plugin ${PROTOBUF_LIBRARY} ${LOG4CXX_LIBRARIES} ${Boost_LIBRARIES} ws2_32.lib) + target_link_libraries(transport-plugin ${PROTOBUF_LIBRARY} ${LOG4CXX_LIBRARIES} ${Boost_LIBRARIES} ${PQXX_LIBRARIES} ${CURL_LIBRARIES} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ws2_32.lib) endif() set_target_properties(transport-plugin PROPERTIES diff --git a/backends/twitter/HTTPRequest.cpp b/plugin/cpp/HTTPRequest.cpp similarity index 98% rename from backends/twitter/HTTPRequest.cpp rename to plugin/cpp/HTTPRequest.cpp index 9e9dd09ee..33efef15f 100644 --- a/backends/twitter/HTTPRequest.cpp +++ b/plugin/cpp/HTTPRequest.cpp @@ -1,4 +1,4 @@ -#include "HTTPRequest.h" +#include "transport/HTTPRequest.h" DEFINE_LOGGER(httpRequestLogger, "HTTPRequest") bool HTTPRequest::init() diff --git a/libtransport/MySQLBackend.cpp b/plugin/cpp/MySQLBackend.cpp similarity index 100% rename from libtransport/MySQLBackend.cpp rename to plugin/cpp/MySQLBackend.cpp diff --git a/libtransport/PQXXBackend.cpp b/plugin/cpp/PQXXBackend.cpp similarity index 100% rename from libtransport/PQXXBackend.cpp rename to plugin/cpp/PQXXBackend.cpp diff --git a/libtransport/SQLite3Backend.cpp b/plugin/cpp/SQLite3Backend.cpp similarity index 100% rename from libtransport/SQLite3Backend.cpp rename to plugin/cpp/SQLite3Backend.cpp diff --git a/libtransport/StorageBackend.cpp b/plugin/cpp/StorageBackend.cpp similarity index 100% rename from libtransport/StorageBackend.cpp rename to plugin/cpp/StorageBackend.cpp diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index cc1dba244..53f5ec568 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -24,14 +24,9 @@ #include -#ifndef WIN32 -#include -#include -#include -#else -#include -#include -#include +#include + +#ifdef _WIN32 #define getpid _getpid #endif @@ -60,6 +55,12 @@ NetworkPlugin::NetworkPlugin() { NetworkPlugin::~NetworkPlugin() { } +void NetworkPlugin::connect(const std::string& host, const std::string &port) { + stream.expires_after(boost::asio::chrono::seconds(60)); + stream.connect(host, port); + handleDataRead(stream); +} + void NetworkPlugin::sendConfig(const PluginConfig &cfg) { std::string data = "[registration]\n"; data += std::string("needPassword=") + (cfg.m_needPassword ? "1" : "0") + "\n"; @@ -496,30 +497,11 @@ void NetworkPlugin::handleChatStatePayload(const std::string &data, int type) { } } -void NetworkPlugin::handleDataRead(std::string &data) { - m_data.insert(m_data.end(), data.begin(), data.end()); - - while (m_data.size() != 0) { - unsigned int expected_size; - - if (m_data.size() >= 4) { - expected_size = *((unsigned int*) &m_data[0]); - expected_size = ntohl(expected_size); - if (m_data.size() - 4 < expected_size) - return; - } - else { - return; - } - +void NetworkPlugin::handleDataRead(std::istream& data) { + while (true) { pbnetwork::WrapperMessage wrapper; - if (wrapper.ParseFromArray(&m_data[4], expected_size) == false) { - m_data.erase(m_data.begin(), m_data.begin() + 4 + expected_size); - return; - } - m_data.erase(m_data.begin(), m_data.begin() + 4 + expected_size); - - switch(wrapper.type()) { + if (wrapper.ParseFromIstream(&data)) { + switch (wrapper.type()) { case pbnetwork::WrapperMessage_Type_TYPE_LOGIN: handleLoginPayload(wrapper.payload()); break; @@ -573,6 +555,10 @@ void NetworkPlugin::handleDataRead(std::string &data) { break; default: return; + } + } else { + LOG4CXX_ERROR(logger, "Error reading from server"); + break; } } } @@ -583,6 +569,11 @@ void NetworkPlugin::send(const std::string &data) { sendData(std::string(header, 4) + data); } +void NetworkPlugin::sendData(const std::string& data) { + stream << data; + stream.flush(); +} + void NetworkPlugin::checkPing() { if (m_pingReceived == false) { LOG4CXX_ERROR(logger, "PING request not received - exiting..."); diff --git a/spectrum/src/CMakeLists.txt b/spectrum/src/CMakeLists.txt index 8779129c1..6075099fa 100644 --- a/spectrum/src/CMakeLists.txt +++ b/spectrum/src/CMakeLists.txt @@ -16,7 +16,11 @@ if (ENABLE_PURPLE AND PURPLE_FOUND) add_dependencies(spectrum2 spectrum2_libpurple_backend) endif() -target_link_libraries(spectrum2 transport spectrum2-xmpp-frontend spectrum2-slack-frontend ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY}) +target_link_libraries(spectrum2 transport spectrum2-xmpp-frontend ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY}) + +if(ENABLE_SLACK_FRONTEND) + target_link_libraries(spectrum2 spectrum2-slack-frontend) +endif() if(NOT MSVC AND NOT APPLE) # export all symbols (used for loading frontends) diff --git a/spectrum/src/frontends/CMakeLists.txt b/spectrum/src/frontends/CMakeLists.txt index eb6249560..44342804f 100644 --- a/spectrum/src/frontends/CMakeLists.txt +++ b/spectrum/src/frontends/CMakeLists.txt @@ -1,2 +1,4 @@ add_subdirectory(xmpp) +if(ENABLE_SLACK_FRONTEND) add_subdirectory(slack) +endif()