diff --git a/backends/libircclient-qt/main.cpp b/backends/libircclient-qt/main.cpp index 7059b397..346fd4ad 100644 --- a/backends/libircclient-qt/main.cpp +++ b/backends/libircclient-qt/main.cpp @@ -28,7 +28,7 @@ class IRCNetworkPlugin : public NetworkPlugin { void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { Swift::JID jid(legacyName); - MyIrcSession *session = new MyIrcSession(); + MyIrcSession *session = new MyIrcSession(user, this); session->setNick(QString::fromStdString(jid.getNode())); session->connectToServer(QString::fromStdString(jid.getDomain()), 6667); std::cout << "CONNECTING IRC NETWORK " << jid.getNode() << " " << jid.getDomain() << "\n"; diff --git a/backends/libircclient-qt/session.cpp b/backends/libircclient-qt/session.cpp index 4b43b540..7142453c 100644 --- a/backends/libircclient-qt/session.cpp +++ b/backends/libircclient-qt/session.cpp @@ -12,8 +12,10 @@ #include #include -MyIrcSession::MyIrcSession(QObject* parent) : Irc::Session(parent) +MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, QObject* parent) : Irc::Session(parent) { + this->np = np; + this->user = user; } void MyIrcSession::on_connected() @@ -38,12 +40,14 @@ void MyIrcSession::on_bufferRemoved(Irc::Buffer* buffer) Irc::Buffer* MyIrcSession::createBuffer(const QString& receiver) { - return new MyIrcBuffer(receiver, this); + return new MyIrcBuffer(receiver, user, np, this); } -MyIrcBuffer::MyIrcBuffer(const QString& receiver, Irc::Session* parent) +MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, Irc::Session* parent) : Irc::Buffer(receiver, parent) { + this->np = np; + this->user = user; connect(this, SIGNAL(receiverChanged(QString)), SLOT(on_receiverChanged(QString))); connect(this, SIGNAL(joined(QString)), SLOT(on_joined(QString))); connect(this, SIGNAL(parted(QString, QString)), SLOT(on_parted(QString, QString))); @@ -144,6 +148,16 @@ void MyIrcBuffer::on_ctcpActionReceived(const QString& origin, const QString& ac void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, const QStringList& params) { + switch (code) { + case 353: + QString channel = params.value(2); + QStringList members = params.value(3).split(" "); + + for (int i = 0; i < members.size(); i++) { + np->handleParticipantChanged(user, members.at(i).toStdString(), channel.toStdString(), 0); + } + break; + } qDebug() << "numeric message received:" << receiver() << origin << code << params; } diff --git a/backends/libircclient-qt/session.h b/backends/libircclient-qt/session.h index 7e3326ee..cf2a201c 100644 --- a/backends/libircclient-qt/session.h +++ b/backends/libircclient-qt/session.h @@ -13,13 +13,16 @@ #include #include +#include + +using namespace Transport; class MyIrcSession : public Irc::Session { Q_OBJECT public: - MyIrcSession(QObject* parent = 0); + MyIrcSession(const std::string &user, NetworkPlugin *np, QObject* parent = 0); protected Q_SLOTS: void on_connected(); @@ -29,6 +32,8 @@ protected Q_SLOTS: void on_bufferRemoved(Irc::Buffer* buffer); protected: + NetworkPlugin *np; + std::string user; virtual Irc::Buffer* createBuffer(const QString& receiver); }; @@ -37,7 +42,9 @@ class MyIrcBuffer : public Irc::Buffer Q_OBJECT public: - MyIrcBuffer(const QString& receiver, Irc::Session* parent); + MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, Irc::Session* parent); + NetworkPlugin *np; + std::string user; protected Q_SLOTS: void on_receiverChanged(const QString& receiver); diff --git a/cmake_modules/IRCClientQtConfig.cmake b/cmake_modules/IRCClientQtConfig.cmake new file mode 100644 index 00000000..8259a81f --- /dev/null +++ b/cmake_modules/IRCClientQtConfig.cmake @@ -0,0 +1,10 @@ +FIND_LIBRARY(IRC_LIBRARY NAMES ircclient-qt) +FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES ircclient-qt ) + +# message( STATUS ${IRC_LIBRARY}) +if( IRC_LIBRARY AND IRC_INCLUDE_DIR ) + message( STATUS "Found libircclient-qt: ${IRC_LIBRARY}, ${IRC_INCLUDE_DIR}") + set( IRC_FOUND 1 ) +else() + message( STATUS "Could NOT find libircclient-qt" ) +endif() diff --git a/examples/external_network_plugin/CMakeLists.txt b/examples/external_network_plugin/CMakeLists.txt new file mode 100644 index 00000000..e3c24cf4 --- /dev/null +++ b/examples/external_network_plugin/CMakeLists.txt @@ -0,0 +1,13 @@ +FILE(GLOB SRC *.cpp) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pbnetwork_pb2.py" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} + ARGS --python_out ${CMAKE_CURRENT_BINARY_DIR} pbnetwork.proto + COMMENT "Running Py protocol buffer compiler on pbnetwork.proto" + VERBATIM ) + +ADD_EXECUTABLE(external_network_plugin ${SRC} ${CMAKE_CURRENT_BINARY_DIR}/pbnetwork_pb2.py) + +TARGET_LINK_LIBRARIES(external_network_plugin transport ${SWIFTEN_LIBRARIES}) + diff --git a/examples/external_network_plugin/main.cpp b/examples/external_network_plugin/main.cpp new file mode 100644 index 00000000..6edd0e76 --- /dev/null +++ b/examples/external_network_plugin/main.cpp @@ -0,0 +1,39 @@ +#include "transport/config.h" +#include "transport/transport.h" +#include "transport/usermanager.h" +#include "transport/logger.h" +#include "transport/sqlite3backend.h" +#include "transport/userregistration.h" +#include "transport/networkpluginserver.h" +#include "Swiften/EventLoop/SimpleEventLoop.h" + +using namespace Transport; + +int main(void) +{ + Config config; + if (!config.load("sample.cfg")) { + std::cout << "Can't open sample.cfg configuration file.\n"; + return 1; + } + + Swift::SimpleEventLoop eventLoop; + Component transport(&eventLoop, &config, NULL); + Logger logger(&transport); + + SQLite3Backend sql(&config); + logger.setStorageBackend(&sql); + if (!sql.connect()) { + std::cout << "Can't connect to database.\n"; + } + + UserManager userManager(&transport, &sql); + UserRegistration userRegistration(&transport, &userManager, &sql); + logger.setUserRegistration(&userRegistration); + logger.setUserManager(&userManager); + + NetworkPluginServer plugin(&transport, &config, &userManager); + + transport.connect(); + eventLoop.run(); +} diff --git a/examples/external_network_plugin/pbnetwork.proto b/examples/external_network_plugin/pbnetwork.proto new file mode 100644 index 00000000..d3c2231a --- /dev/null +++ b/examples/external_network_plugin/pbnetwork.proto @@ -0,0 +1,29 @@ +package pbnetwork; + +message Connected { + required string name = 1; +} + +message Disconnected { + required string name = 1; + required int32 error = 2; + optional string message = 3; +} + +message Login { + required string protocol = 1; + required string legacyName = 2; + required string password = 3; +} + +message WrapperMessage { + enum Type { + TYPE_CONNECTED = 1; + TYPE_DISCONNECTED = 2; + TYPE_LOGIN = 3; + TYPE_LOGOUT = 4; + } + required Type type = 1; + required bytes payload = 2; +} +; \ No newline at end of file diff --git a/examples/external_network_plugin/plugin.py b/examples/external_network_plugin/plugin.py new file mode 100644 index 00000000..51a5c58e --- /dev/null +++ b/examples/external_network_plugin/plugin.py @@ -0,0 +1,29 @@ +#! /usr/bin/python + +from pbnetwork_pb2 import * +import time +import sys +import socket +import struct + + +connected = Connected() +connected.name = "hanzz.k@gmail.com" + +wrapper = WrapperMessage() +wrapper.type = WrapperMessage.TYPE_CONNECTED +wrapper.payload = connected.SerializeToString() + +sck = socket.socket() +sck.connect(("localhost", 10000)) + +message = wrapper.SerializeToString(); +header = struct.pack(">L", len(message)) +print [header] +sck.send(header + message+header + message); +sck.send(header + message); +sck.send(header + message); +sck.send(header + message); +sck.send(header + message); + +print sck.recv(255) diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 2ccd52cb..8192d61c 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -42,6 +42,10 @@ class Conversation { const std::string &getLegacyName() { return m_legacyName; } void handleMessage(boost::shared_ptr &message); + void handleParticipantChanged(const std::string &nickname, int flag); + void setNickname(const std::string &nickname) { + m_nickname = nickname; + } virtual void sendMessage(boost::shared_ptr &message) = 0; @@ -52,6 +56,7 @@ class Conversation { private: ConversationManager *m_conversationManager; std::string m_legacyName; + std::string m_nickname; }; } diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 26d7e53f..54523923 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -44,6 +44,8 @@ class NetworkPlugin { const std::string &groups, int status, const std::string &statusMessage = "", const std::string &iconHash = "" ); + void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags); + void handleDisconnected(const std::string &user, const std::string &legacyName, int error, const std::string &message); void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message); diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 61253f45..2e3663e8 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -55,6 +55,7 @@ class NetworkPluginServer { void handleDisconnectedPayload(const std::string &payload); void handleBuddyChangedPayload(const std::string &payload); void handleConvMessagePayload(const std::string &payload); + void handleParticipantChangedPayload(const std::string &payload); void handleUserCreated(User *user); void handleRoomJoined(User *user, const std::string &room, const std::string &nickname, const std::string &password); diff --git a/src/conversation.cpp b/src/conversation.cpp index 17353e40..4a41add2 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -38,17 +38,37 @@ Conversation::~Conversation() { } void Conversation::handleMessage(boost::shared_ptr &message) { - message->setTo(m_conversationManager->getUser()->getJID().toBare()); - Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName); - if (buddy) { - std::cout << m_legacyName << " 222222\n"; - message->setFrom(buddy->getJID()); + if (message->getType() != Swift::Message::Groupchat) { + message->setTo(m_conversationManager->getUser()->getJID().toBare()); + Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName); + if (buddy) { + std::cout << m_legacyName << " 222222\n"; + message->setFrom(buddy->getJID()); + } + else { + std::cout << m_legacyName << " 1111111\n"; + // TODO: escape from and setFrom + } + m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); } - else { - std::cout << m_legacyName << " 1111111\n"; - // TODO: escape from and setFrom +} + +void Conversation::handleParticipantChanged(const std::string &nickname, int flag) { + Swift::Presence::ref presence = Swift::Presence::create(); + presence->setFrom(Swift::JID(m_legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname)); + presence->setTo(m_conversationManager->getUser()->getJID().toString()); + presence->setType(Swift::Presence::Available); + + Swift::MUCUserPayload *p = new Swift::MUCUserPayload (); + if (m_nickname == nickname) { + Swift::MUCUserPayload::StatusCode c; + c.code = 110; + p->addStatusCode(c); } - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + p->addItem(Swift::MUCUserPayload::Item(Swift::MUCOccupant::Member, Swift::MUCOccupant::Participant)); + + presence->addPayload(boost::shared_ptr(p)); + m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); } } diff --git a/src/networkplugin.cpp b/src/networkplugin.cpp index 4a3bd92e..79b22571 100644 --- a/src/networkplugin.cpp +++ b/src/networkplugin.cpp @@ -104,6 +104,21 @@ void NetworkPlugin::handleDisconnected(const std::string &user, const std::strin send(message); } +void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags) { + pbnetwork::Participant d; + d.set_username(user); + d.set_nickname(nickname); + d.set_room(room); + d.set_flag(flags); + + std::string message; + d.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_PARTICIPANT_CHANGED); + + send(message); +} + void NetworkPlugin::handleConnected(bool error) { if (error) { std::cout << "Connecting error\n"; diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 46bbfdf8..ad9ce5de 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -194,6 +194,37 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) { } } +void NetworkPluginServer::handleParticipantChangedPayload(const std::string &data) { + pbnetwork::Participant payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + User *user = m_userManager->getUser(payload.username()); + if (!user) + return; + + NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.room()); + if (!conv) { + return; + } + + conv->handleParticipantChanged(payload.nickname(), payload.flag()); + +// LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname()); +// if (buddy) { +// handleBuddyPayload(buddy, payload); +// buddy->buddyChanged(); +// } +// else { +// buddy = new LocalBuddy(user->getRosterManager(), -1); +// handleBuddyPayload(buddy, payload); +// user->getRosterManager()->setBuddy(buddy); +// } + std::cout << payload.nickname() << "\n"; +} + void NetworkPluginServer::handleConvMessagePayload(const std::string &data) { pbnetwork::ConversationMessage payload; // std::cout << "payload...\n"; @@ -258,6 +289,9 @@ void NetworkPluginServer::handleDataRead(boost::shared_ptr c, case pbnetwork::WrapperMessage_Type_TYPE_PONG: m_pongReceived = true; break; + case pbnetwork::WrapperMessage_Type_TYPE_PARTICIPANT_CHANGED: + handleParticipantChangedPayload(wrapper.payload()); + break; default: return; } @@ -320,6 +354,10 @@ void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, con WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM); send(m_client, message); + + NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r); + conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2)); + conv->setNickname(nickname); } void NetworkPluginServer::handleUserDestroyed(User *user) {