diff --git a/pokerth_lib.pro b/pokerth_lib.pro index 0c22d09b..a1b76df6 100644 --- a/pokerth_lib.pro +++ b/pokerth_lib.pro @@ -68,6 +68,8 @@ HEADERS += \ src/net/socket_helper.h \ src/net/socket_msg.h \ src/net/socket_startup.h \ + src/net/irccallback.h \ + src/net/ircthread.h \ src/core/tinyxml/tinystr.h \ src/core/tinyxml/tinyxml.h \ src/core/libircclient/include/libircclient.h \ @@ -154,6 +156,8 @@ SOURCES += \ src/net/common/netcontext.cpp \ src/net/common/netexception.cpp \ src/net/common/receiverhelper.cpp \ + src/net/common/irccallback.cpp \ + src/net/common/ircthread.cpp \ src/gui/qttoolsinterface.cpp \ src/gui/qt/qttools/qttoolswrapper.cpp \ src/gui/qt/qttools/qthelper/qthelper.cpp \ diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 235a3eaa..7198d3c7 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -24,8 +24,8 @@ using namespace std; -ServerGuiWrapper::ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb) -: myConfig(config), myClientcb(clientcb), myServercb(servercb) +ServerGuiWrapper::ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb, IrcCallback *irccb) +: myConfig(config), myClientcb(clientcb), myServercb(servercb), myIrccb(irccb) { } @@ -125,3 +125,4 @@ void ServerGuiWrapper::SignalNetClientWaitDialog() { if (myClientcb) myClientcb- void ServerGuiWrapper::SignalNetServerSuccess(int actionID) { if (myServercb) myServercb->SignalNetServerSuccess(actionID); } void ServerGuiWrapper::SignalNetServerError(int errorID, int osErrorID) { if (myServercb) myServercb->SignalNetServerError(errorID, osErrorID); } +void ServerGuiWrapper::SignalIrcChatMsg(const string &nickName, const string &msg) { if (myIrccb) myIrccb->SignalIrcChatMsg(nickName, msg); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index 481a88c0..0bbd2af9 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -27,7 +27,7 @@ class Session; class ServerGuiWrapper : public GuiInterface { public: - ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb); + ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb, IrcCallback *irccb); ~ServerGuiWrapper(); void initGui(int speed); @@ -110,6 +110,8 @@ public: void SignalNetServerSuccess(int actionID); void SignalNetServerError(int errorID, int osErrorID); + void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); + private: boost::shared_ptr mySession; @@ -117,6 +119,7 @@ private: ClientCallback *myClientcb; ServerCallback *myServercb; + IrcCallback *myIrccb; }; #endif diff --git a/src/gui/guiinterface.h b/src/gui/guiinterface.h index 780f1327..a0194e6d 100644 --- a/src/gui/guiinterface.h +++ b/src/gui/guiinterface.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -30,7 +31,7 @@ class Session; -class GuiInterface : public ClientCallback, public ServerCallback { +class GuiInterface : public ClientCallback, public ServerCallback, public IrcCallback { public: virtual ~GuiInterface(); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp index f047398a..5fa26d6e 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp @@ -38,7 +38,11 @@ gameLobbyDialogImpl::gameLobbyDialogImpl(QWidget *parent, ConfigFile *c) void gameLobbyDialogImpl::exec() { + assert(mySession); + mySession->terminateIrcClient(); + mySession->startIrcClient(); QDialog::exec(); + mySession->terminateIrcClient(); clearDialog(); } @@ -384,9 +388,10 @@ void gameLobbyDialogImpl::kickPlayer() { } void gameLobbyDialogImpl::sendChatMessage() { myChat->sendMessage(); } +void gameLobbyDialogImpl::displayChatMessage(QString nickName, QString msg) { myChat->receiveMessage(nickName, msg); } void gameLobbyDialogImpl::checkChatInputLength(QString string) { myChat->checkInputLength(string); } void gameLobbyDialogImpl::keyPressEvent ( QKeyEvent * event ) { - if (event->key() == Qt::Key_Enter) {} -} \ No newline at end of file + if (event->key() == Qt::Key_Enter) { sendChatMessage(); } +} diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h index 0f485a1c..88499ea7 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h @@ -79,6 +79,7 @@ public slots: void clearDialog(); void sendChatMessage(); + void displayChatMessage(QString nickName, QString msg); void checkChatInputLength(QString string); void keyPressEvent(QKeyEvent * event); diff --git a/src/gui/qt/gamelobbydialog/lobbychat/lobbychat.cpp b/src/gui/qt/gamelobbydialog/lobbychat/lobbychat.cpp index b53ddb94..b983e0b3 100644 --- a/src/gui/qt/gamelobbydialog/lobbychat/lobbychat.cpp +++ b/src/gui/qt/gamelobbydialog/lobbychat/lobbychat.cpp @@ -38,8 +38,12 @@ LobbyChat::~LobbyChat() void LobbyChat::sendMessage() { - myLobby->getSession().sendChatMessage(myLobby->lineEdit_ChatInput->text().toUtf8().constData()); + QString tmpMsg(myLobby->lineEdit_ChatInput->text()); + myLobby->getSession().sendIrcChatMessage(tmpMsg.toUtf8().constData()); myLobby->lineEdit_ChatInput->setText(""); + + // TODO: just temporary instead of callback + receiveMessage("(me)", tmpMsg); } void LobbyChat::receiveMessage(QString playerName, QString message) { diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 496c6fd8..fece9d58 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -139,3 +139,5 @@ void GuiWrapper::SignalNetClientWaitDialog() { myW->signalShowNetworkStartDialog void GuiWrapper::SignalNetServerSuccess(int actionID) { } void GuiWrapper::SignalNetServerError(int errorID, int osErrorID) { myW->signalNetServerError(errorID, osErrorID); } +void GuiWrapper::SignalIrcChatMsg(const std::string &nickName, const std::string &msg) { myW->signalIrcChatMessage(QString::fromUtf8(nickName.c_str()), QString::fromUtf8(msg.c_str())); } + diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index f7c6e38e..241edd2b 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -118,6 +118,8 @@ public: void SignalNetServerSuccess(int actionID); void SignalNetServerError(int errorID, int osErrorID); + void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); + private: Log *myLog; diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 1c09ab1e..3edfadc4 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -676,6 +676,8 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalNetServerError(int, int)), this, SLOT(networkError(int, int))); connect(this, SIGNAL(signalNetClientGameStart(boost::shared_ptr)), this, SLOT(networkStart(boost::shared_ptr))); + connect(this, SIGNAL(signalIrcChatMessage(QString, QString)), myGameLobbyDialog, SLOT(displayChatMessage(QString, QString))); + //Sound mySDLPlayer = new SDLPlayer(myConfig); @@ -758,7 +760,7 @@ void mainWindowImpl::callCreateNetworkGameDialog() { if (!myServerGuiInterface.get()) { // Create pseudo Gui Wrapper for the server. - myServerGuiInterface.reset(new ServerGuiWrapper(myConfig, mySession->getGui(), mySession->getGui())); + myServerGuiInterface.reset(new ServerGuiWrapper(myConfig, mySession->getGui(), mySession->getGui(), mySession->getGui())); { boost::shared_ptr session(new Session(myServerGuiInterface.get(), myConfig)); myServerGuiInterface->setSession(session); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index f6309056..b77a8095 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -138,6 +138,8 @@ signals: void signalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId); void signalNetClientGameStart(boost::shared_ptr game); + void signalIrcChatMessage(QString nickName, QString msg); + public slots: void initGui(int speed); diff --git a/src/net/common/ircthread.cpp b/src/net/common/ircthread.cpp index 780fa1a2..f6e37009 100644 --- a/src/net/common/ircthread.cpp +++ b/src/net/common/ircthread.cpp @@ -34,11 +34,25 @@ struct IrcContext string channel; }; -void event_connect(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned count) +void +irc_connect(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned count) { - IrcContext *ctx = (IrcContext *) irc_get_ctx(session); + IrcContext *context = (IrcContext *) irc_get_ctx(session); - irc_cmd_join(session, ctx->channel.c_str(), 0); + irc_cmd_join(session, context->channel.c_str(), 0); +} + +void +irc_channel(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned count) +{ + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + if (context->channel == params[0]) // check whether this message is for our channel + { + // Signal the message (if any) to GUI. + if (params[1] && *params[1] != 0) + context->ircThread.GetCallback().SignalIrcChatMsg(origin, params[1]); + } } @@ -69,7 +83,7 @@ IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6 irc_callbacks_t callbacks; memset (&callbacks, 0, sizeof(callbacks)); - callbacks.event_connect = event_connect; + callbacks.event_connect = irc_connect; //callbacks.event_join //callbacks.event_nick //callbacks.event_quit @@ -77,7 +91,7 @@ IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6 //callbacks.event_mode //callbacks.event_topic //callbacks.event_kick - //callbacks.event_channel + callbacks.event_channel = irc_channel; //callbacks.event_privmsg //callbacks.event_notice //callbacks.event_invite @@ -100,6 +114,13 @@ IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6 } } +void +IrcThread::SendChatMessage(const std::string &msg) +{ + IrcContext &context = GetContext(); + irc_cmd_msg(context.session, context.channel.c_str(), msg.c_str()); +} + void IrcThread::SignalTermination() { diff --git a/src/net/irccallback.h b/src/net/irccallback.h index 62c25c2b..f9dccb0e 100644 --- a/src/net/irccallback.h +++ b/src/net/irccallback.h @@ -28,7 +28,7 @@ class IrcCallback public: virtual ~IrcCallback(); - virtual void SignalIrcPlayerJoined(const std::string &nickName) = 0; + virtual void SignalIrcChatMsg(const std::string &nickName, const std::string &msg) = 0; }; #endif diff --git a/src/net/ircthread.h b/src/net/ircthread.h index 2e85e2e9..89d99810 100644 --- a/src/net/ircthread.h +++ b/src/net/ircthread.h @@ -36,8 +36,13 @@ public: // Set the parameters. void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel); + // Send a chat message to the channel. + void SendChatMessage(const std::string &msg); + virtual void SignalTermination(); + IrcCallback &GetCallback(); + protected: // Main function of the thread. @@ -46,8 +51,6 @@ protected: const IrcContext &GetContext() const; IrcContext &GetContext(); - IrcCallback &GetCallback(); - private: std::auto_ptr m_context; IrcCallback &m_callback; diff --git a/src/pokerth_server.cpp b/src/pokerth_server.cpp index 93b5dcb6..2c0e4111 100644 --- a/src/pokerth_server.cpp +++ b/src/pokerth_server.cpp @@ -85,7 +85,7 @@ main(int argc, char *argv[]) socket_startup(); // Create pseudo Gui Wrapper for the server. - boost::shared_ptr myServerGuiInterface(new ServerGuiWrapper(myConfig, NULL, NULL)); + boost::shared_ptr myServerGuiInterface(new ServerGuiWrapper(myConfig, NULL, NULL, NULL)); { boost::shared_ptr session(new Session(myServerGuiInterface.get(), myConfig)); session->init(); // TODO handle error diff --git a/src/session.cpp b/src/session.cpp index 1f755bff..c52e17b7 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -25,19 +25,21 @@ #include #include #include +#include #include #include #define NET_CLIENT_TERMINATE_TIMEOUT_MSEC 1000 -#define NET_SERVER_TERMINATE_TIMEOUT_MSEC 1000 +#define NET_SERVER_TERMINATE_TIMEOUT_MSEC 2000 +#define NET_IRC_TERMINATE_TIMEOUT_MSEC 2000 #define NET_DEFAULT_GAME "default" using namespace std; Session::Session(GuiInterface *g, ConfigFile *c) -: currentGameID(0), myNetClient(0), myNetServer(0), myGui(g), myConfig(c) +: currentGameID(0), myNetClient(NULL), myNetServer(NULL), myIrcThread(NULL), myGui(g), myConfig(c) { myAvatarManager.reset(new AvatarManager); } @@ -47,6 +49,7 @@ Session::~Session() { terminateNetworkClient(); terminateNetworkServer(); + terminateIrcClient(); delete myConfig; myConfig = 0; } @@ -242,6 +245,44 @@ void Session::waitForNetworkServer(unsigned timeoutMsec) } } +void Session::startIrcClient() +{ + if (myIrcThread || !myGui) + { + assert(false); + return; + } + myIrcThread = new IrcThread(*myGui); + myIrcThread->Init( + myConfig->readConfigString("IRCServerAddress"), + myConfig->readConfigInt("IRCServerPort"), + myConfig->readConfigInt("IRCServerUseIpv6") == 1, + myConfig->readConfigString("MyName"), + myConfig->readConfigString("IRCChannel")); + myIrcThread->Run(); +} + +void Session::sendIrcChatMessage(const std::string &message) +{ + if (!myIrcThread) + return; + myIrcThread->SendChatMessage(message); +} + +void Session::terminateIrcClient() +{ + if (!myIrcThread) + return; // already terminated + myIrcThread->SignalTermination(); + // Give the thread some time to terminate. + if (myIrcThread->Join(NET_IRC_TERMINATE_TIMEOUT_MSEC)) + delete myIrcThread; + else + assert(false); + // If termination fails, leave a memory leak to prevent a crash. + myIrcThread = 0; +} + void Session::sendLeaveCurrentGame() { if (!myNetClient) diff --git a/src/session.h b/src/session.h index 3bc9e60f..2c1d4f91 100755 --- a/src/session.h +++ b/src/session.h @@ -30,6 +30,7 @@ class Game; class ConfigFile; class ClientThread; class ServerAcceptThread; +class IrcThread; class AvatarManager; class Session{ @@ -61,6 +62,10 @@ public: void terminateNetworkServer(); void waitForNetworkServer(unsigned timeoutMsec); + void startIrcClient(); + void sendIrcChatMessage(const std::string &message); + void terminateIrcClient(); + void sendClientPlayerAction(); void setCurrentGameID(int theValue) { currentGameID = theValue; } @@ -81,6 +86,7 @@ private: ClientThread *myNetClient; ServerAcceptThread *myNetServer; + IrcThread *myIrcThread; boost::shared_ptr myAvatarManager; boost::shared_ptr currentGame;