// Transport includes #include "transport/config.h" #include "transport/networkplugin.h" // Swiften #include "Swiften/Swiften.h" #ifndef _MSC_VER // for signal handler #include "unistd.h" #include "signal.h" #include "sys/wait.h" #include "sys/signal.h" #endif // Log4cxx #include "log4cxx/logger.h" #include "log4cxx/consoleappender.h" #include "log4cxx/patternlayout.h" #include "log4cxx/propertyconfigurator.h" #include "log4cxx/helpers/properties.h" #include "log4cxx/helpers/fileinputstream.h" #include "log4cxx/helpers/transcoder.h" // Boost #include using namespace boost::filesystem; using namespace boost::program_options; using namespace Transport; // log4cxx main logger using namespace log4cxx; static LoggerPtr logger = log4cxx::Logger::getLogger("Backend Template"); // eventloop Swift::SimpleEventLoop *loop_; // Plugin class TemplatePlugin; TemplatePlugin * np = NULL; class TemplatePlugin : public NetworkPlugin { public: Swift::BoostNetworkFactories *m_factories; Swift::BoostIOServiceThread m_boostIOServiceThread; boost::shared_ptr m_conn; TemplatePlugin(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(&TemplatePlugin::_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 data) { std::string d(data->begin(), data->end()); handleDataRead(d); } void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { handleConnected(user); } void handleLogoutRequest(const std::string &user, const std::string &legacyName) { } void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") { LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << "."); } void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << "."); handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE); } void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups) { } private: Config *config; }; #ifndef _MSC_VER 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 _MSC_VER if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) { std::cout << "SIGCHLD handler can't be set\n"; return -1; } #endif boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \nAllowed options"); desc.add_options() ("host,h", value(&host), "host") ("port,p", value(&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; } if (CONFIG_STRING(&config, "logging.backend_config").empty()) { LoggerPtr root = log4cxx::Logger::getRootLogger(); #ifndef _MSC_VER root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n"))); #else root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n"))); #endif } else { log4cxx::helpers::Properties p; log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config")); p.load(istream); LogString pid, jid; log4cxx::helpers::Transcoder::decode(boost::lexical_cast(getpid()), pid); log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid); #ifdef _MSC_VER p.setProperty(L"pid", pid); p.setProperty(L"jid", jid); #else p.setProperty("pid", pid); p.setProperty("jid", jid); #endif log4cxx::PropertyConfigurator::configure(p); } Swift::SimpleEventLoop eventLoop; loop_ = &eventLoop; np = new TemplatePlugin(&config, &eventLoop, host, port); loop_->run(); return 0; }