From fb274284f52ed69688fa84662158ef80c25c3ae2 Mon Sep 17 00:00:00 2001 From: lotodore Date: Thu, 7 Jun 2007 21:19:06 +0000 Subject: [PATCH] Kicking players at the beginning of a network game now works. --- docs/net_protocol.txt | 1 + src/gui/qt/mainwindow/log/log.cpp | 2 - src/gui/qt/mainwindow/mainwindowimpl.cpp | 6 ++ .../startnetworkgamedialogimpl.cpp | 16 +++-- .../startnetworkgamedialogimpl.h | 4 +- src/net/common/clientstate.cpp | 18 ++--- src/net/common/netpacket.cpp | 7 ++ src/net/common/serverrecvthread.cpp | 70 ++++++++++++++----- src/net/common/serverthread.cpp | 13 +++- src/net/serverrecvthread.h | 14 ++-- src/net/serverthread.h | 1 + src/net/socket_msg.h | 1 + src/session.cpp | 13 +++- src/session.h | 1 + 14 files changed, 122 insertions(+), 45 deletions(-) diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index e2bfa138..2060f3e3 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -385,6 +385,7 @@ Error Reason: 0x0006 - Join Game - Invalid Player Name 0xFF01 - General Error - Invalid packet 0xFF02 - General Error - Invalid state + 0xFF03 - General Error - Kicked from the server 0xFFFF - Other reason diff --git a/src/gui/qt/mainwindow/log/log.cpp b/src/gui/qt/mainwindow/log/log.cpp index a05fea17..1e67c840 100644 --- a/src/gui/qt/mainwindow/log/log.cpp +++ b/src/gui/qt/mainwindow/log/log.cpp @@ -444,8 +444,6 @@ void Log::logFlipHoleCardsMsg(QString playerName, int card1, int card2, int card void Log::logPlayerLeftMsg(QString playerName) { - HandInterface *currentHand = myW->getSession().getCurrentGame()->getCurrentHand(); - myW->textBrowser_Log->append( ""+playerName+" has left the game!"); if(myConfig->readConfigInt("LogOnOff")) { diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index d4696ee1..38594f1a 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -720,6 +720,7 @@ void mainWindowImpl::callCreateNetworkGameDialog() { // gameData.guiSpeed = myCreateNetworkGameDialog->spinBox_gameSpeed->value(); gameData.guiSpeed = 4; + myStartNetworkGameDialog->setSession(&myServerGuiInterface->getSession()); myStartNetworkGameDialog->treeWidget->clear(); myServerGuiInterface->getSession().startNetworkServer(gameData); @@ -2482,6 +2483,11 @@ void mainWindowImpl::networkError(int errorID, int osErrorID) { tr("The server referred to an unknown player. Aborting."), QMessageBox::Close); } break; + case ERR_NET_PLAYER_KICKED: + { QMessageBox::warning(this, tr("Network Error"), + tr("You were kicked from the server."), + QMessageBox::Close); } + break; default: { QMessageBox::warning(this, tr("Network Error"), tr("An internal error occured."), QMessageBox::Close); } diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp index 4d671f71..53eeb495 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp @@ -21,12 +21,10 @@ #include "session.h" #include "configfile.h" -startNetworkGameDialogImpl::startNetworkGameDialogImpl(QWidget *parent, ConfigFile *config, Session *session) - : QDialog(parent), myConfig(config), mySession(session) +startNetworkGameDialogImpl::startNetworkGameDialogImpl(QWidget *parent, ConfigFile *config) + : QDialog(parent), myConfig(config) { - assert(mySession); - - setupUi(this); + setupUi(this); connect( pushButton_cancel, SIGNAL( clicked() ), this, SLOT( cancel() ) ); connect( pushButton_startGame, SIGNAL( clicked() ), this, SLOT( startGame() ) ); @@ -81,7 +79,8 @@ void startNetworkGameDialogImpl::kickPlayer() { QMessageBox::Close); } } else { - // kickplayerFunktion(playerName.toStdString()); + assert(mySession); + mySession->kickPlayer(playerName.toUtf8().constData()); } } pushButton_Kick->setEnabled(FALSE); @@ -94,6 +93,11 @@ void startNetworkGameDialogImpl::checkPlayerQuantity() { } +void startNetworkGameDialogImpl::setSession(Session *session) +{ + mySession = session; +} + void startNetworkGameDialogImpl::keyPressEvent ( QKeyEvent * event ) { diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h index a93516e5..956ba630 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h @@ -31,7 +31,7 @@ class ConfigFile; class startNetworkGameDialogImpl: public QDialog, public Ui::startNetworkGameDialog { Q_OBJECT public: - startNetworkGameDialogImpl(QWidget *parent = 0, ConfigFile *config = 0, Session *session = 0); + startNetworkGameDialogImpl(QWidget *parent = 0, ConfigFile *config = 0); public slots: @@ -43,6 +43,8 @@ public slots: void kickPlayer(); void checkPlayerQuantity(); + void setSession(Session *session); + void keyPressEvent ( QKeyEvent*); void setMaxPlayerNumber ( int theValue ) { maxPlayerNumber = theValue; label_maxPlayerNumber->setText(QString::number(theValue,10)); } diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index ac4d7551..85a94637 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -379,7 +379,15 @@ AbstractClientStateReceiving::Process(ClientThread &client) if (tmpPacket.get()) { - if (tmpPacket->ToNetPacketChatText()) + if (tmpPacket->ToNetPacketError()) + { + // Server reported an error. + NetPacketError::Data errorData; + tmpPacket->ToNetPacketError()->GetData(errorData); + // Show the error. + throw ClientException(errorData.errorCode, 0); + } + else if (tmpPacket->ToNetPacketChatText()) { // Chat message - display it in the GUI. NetPacketChatText::Data chatData; @@ -464,14 +472,6 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr< client.SetState(ClientStateWaitGame::Instance()); retVal = MSG_SOCK_SESSION_DONE; } - else if (packet->ToNetPacketError()) - { - // Server reported an error. - NetPacketError::Data errorData; - packet->ToNetPacketError()->GetData(errorData); - // Show the error. - throw ClientException(errorData.errorCode, 0); - } return retVal; } diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index 1b26b4dd..b1b83c94 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -59,6 +59,7 @@ using namespace std; #define NET_ERR_JOIN_GAME_INVALID_PLAYER_NAME 0x0006 #define NET_ERR_GENERAL_INVALID_PACKET 0xFF01 #define NET_ERR_GENERAL_INVALID_STATE 0xFF02 +#define NET_ERR_GENERAL_PLAYER_KICKED 0xFF03 #define NET_ERR_OTHER 0xFFFF #ifdef _MSC_VER @@ -2111,6 +2112,9 @@ NetPacketError::SetData(const NetPacketError::Data &inData) case ERR_SOCK_INVALID_STATE : tmpData->reason = htons(NET_ERR_GENERAL_INVALID_STATE); break; + case ERR_NET_PLAYER_KICKED : + tmpData->reason = htons(NET_ERR_GENERAL_PLAYER_KICKED); + break; default : tmpData->reason = htons(NET_ERR_OTHER); break; @@ -2151,6 +2155,9 @@ NetPacketError::GetData(NetPacketError::Data &outData) const case NET_ERR_GENERAL_INVALID_STATE : outData.errorCode = ERR_SOCK_INVALID_STATE; break; + case NET_ERR_GENERAL_PLAYER_KICKED : + outData.errorCode = ERR_NET_PLAYER_KICKED; + break; default : outData.errorCode = ERR_SOCK_INTERNAL; break; diff --git a/src/net/common/serverrecvthread.cpp b/src/net/common/serverrecvthread.cpp index c9f99a38..ae9f5cbb 100644 --- a/src/net/common/serverrecvthread.cpp +++ b/src/net/common/serverrecvthread.cpp @@ -82,10 +82,10 @@ ServerRecvThread::AddConnection(boost::shared_ptr data) } void -ServerRecvThread::AddNotification(unsigned message, unsigned param1, unsigned param2) +ServerRecvThread::AddNotification(unsigned message, const string ¶m) { boost::mutex::scoped_lock lock(m_notificationQueueMutex); - m_notificationQueue.push_back(Notification(message, param1, param2)); + m_notificationQueue.push_back(Notification(message, param)); } void @@ -145,6 +145,9 @@ ServerRecvThread::NotificationLoop() case NOTIFY_GAME_START: InternalStartGame(); break; + case NOTIFY_KICK_PLAYER: + InternalKickPlayer(notification.param); + break; } } } @@ -287,13 +290,24 @@ ServerRecvThread::InternalStartGame() m_game.reset(new Game(&gui, factory, playerData, GetGameData(), GetStartData(), m_curGameId++)); } +void +ServerRecvThread::InternalKickPlayer(const string playerName) +{ + if (!playerName.empty()) + { + SessionWrapper tmpSession = GetSession(playerName); + + SessionError(tmpSession, ERR_NET_PLAYER_KICKED); + } +} + SessionWrapper -ServerRecvThread::GetSession(SOCKET sock) +ServerRecvThread::GetSession(SOCKET sock) const { SessionWrapper tmpSession; boost::mutex::scoped_lock lock(m_sessionMapMutex); - SocketSessionMap::iterator pos = m_sessionMap.find(sock); + SocketSessionMap::const_iterator pos = m_sessionMap.find(sock); if (pos != m_sessionMap.end()) { tmpSession = pos->second; @@ -301,6 +315,34 @@ ServerRecvThread::GetSession(SOCKET sock) return tmpSession; } +SessionWrapper +ServerRecvThread::GetSession(const string playerName) const +{ + SessionWrapper tmpSession; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SocketSessionMap::const_iterator session_i = m_sessionMap.begin(); + SocketSessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) + { + // Check all players which are fully connected. + if (session_i->second.sessionData->GetState() == SessionData::Established) + { + boost::shared_ptr tmpPlayer(session_i->second.playerData); + assert(tmpPlayer.get()); + if (tmpPlayer->GetName() == playerName) + { + tmpSession = session_i->second; + break; + } + } + + ++session_i; + } + return tmpSession; +} + void ServerRecvThread::AddSession(boost::shared_ptr sessionData) { @@ -415,25 +457,15 @@ ServerRecvThread::GetCurNumberOfPlayers() const } bool -ServerRecvThread::IsPlayerConnected(const std::string &playerName) const +ServerRecvThread::IsPlayerConnected(const string &playerName) const { bool retVal = false; - PlayerDataList playerList = GetPlayerDataList(); - PlayerDataList::const_iterator player_i = playerList.begin(); - PlayerDataList::const_iterator player_end = playerList.end(); + SessionWrapper tmpSession = GetSession(playerName); - // Check by name - the name is unique. - while (player_i != player_end) - { - if ((*player_i)->GetName() == playerName) - { - retVal = true; - break; - } + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + retVal = true; - ++player_i; - } return retVal; } @@ -612,7 +644,7 @@ ServerRecvThread::SetStartData(const StartData &startData) } bool -ServerRecvThread::CheckPassword(const std::string &password) const +ServerRecvThread::CheckPassword(const string &password) const { return (password == m_password); } diff --git a/src/net/common/serverthread.cpp b/src/net/common/serverthread.cpp index d20a50b7..e150a2ac 100644 --- a/src/net/common/serverthread.cpp +++ b/src/net/common/serverthread.cpp @@ -28,6 +28,7 @@ #define ACCEPT_TIMEOUT_MSEC 50 #define NET_SERVER_LISTEN_BACKLOG 5 +using namespace std; ServerThread::ServerThread(GuiInterface &gui, ConfigFile *config) : m_gui(gui) @@ -63,7 +64,17 @@ ServerThread::StartGame() return; // TODO: throw exception // Thread-safe notification. - GetRecvThread().AddNotification(NOTIFY_GAME_START, 0, 0); + GetRecvThread().AddNotification(NOTIFY_GAME_START, ""); +} + +void +ServerThread::KickPlayer(const string &playerName) +{ + if (!IsRunning()) + return; // TODO: throw exception + + // Thread-safe notification. + GetRecvThread().AddNotification(NOTIFY_KICK_PLAYER, playerName); } ServerCallback & diff --git a/src/net/serverrecvthread.h b/src/net/serverrecvthread.h index 6d34cc6e..90cf52ff 100644 --- a/src/net/serverrecvthread.h +++ b/src/net/serverrecvthread.h @@ -38,6 +38,7 @@ // Notifications #define NOTIFY_GAME_START 1 +#define NOTIFY_KICK_PLAYER 2 class ServerRecvState; class SenderThread; @@ -66,7 +67,7 @@ public: void Init(const std::string &pwd, const GameData &gameData); void AddConnection(boost::shared_ptr data); - void AddNotification(unsigned message, unsigned param1, unsigned param2); + void AddNotification(unsigned message, const std::string ¶m); ServerCallback &GetCallback(); @@ -78,11 +79,10 @@ protected: struct Notification { - Notification(unsigned m, unsigned p1, unsigned p2) - : message(m), param1(p1), param2(p2) {} + Notification(unsigned m, std::string p) + : message(m), param(p) {} unsigned message; - unsigned param1; - unsigned param2; + std::string param; }; typedef std::deque > ConnectQueue; @@ -103,8 +103,10 @@ protected: void CleanupSessionMap(); void InternalStartGame(); + void InternalKickPlayer(const std::string playerName); - SessionWrapper GetSession(SOCKET sock); + SessionWrapper GetSession(SOCKET sock) const; + SessionWrapper GetSession(const std::string playerName) const; void AddSession(boost::shared_ptr sessionData); // new Sessions have no player data void SessionError(SessionWrapper session, int errorCode); void RejectNewConnection(boost::shared_ptr connData); diff --git a/src/net/serverthread.h b/src/net/serverthread.h index 7f556bec..3a9ec85c 100644 --- a/src/net/serverthread.h +++ b/src/net/serverthread.h @@ -44,6 +44,7 @@ public: void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const GameData &gameData); void StartGame(); + void KickPlayer(const std::string &playerName); ServerCallback &GetCallback(); GuiInterface &GetGui(); diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index 07ad017d..53a4c8c9 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -53,6 +53,7 @@ #define ERR_NET_INVALID_CHAT_TEXT 110 #define ERR_NET_UNKNOWN_PLAYER_ID 111 #define ERR_NET_INVALID_ROUND 112 +#define ERR_NET_PLAYER_KICKED 113 // This is an internal message which is not reported. #define MSG_SOCK_INTERNAL_PENDING 0 diff --git a/src/session.cpp b/src/session.cpp index 12010120..d5ab10f9 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -203,12 +203,23 @@ void Session::sendClientPlayerAction() myNetClient->SendPlayerAction(); } -void Session::sendChatMessage(const std::string &message) { +void Session::sendChatMessage(const std::string &message) +{ if (!myNetClient) return; // only act if client is running. myNetClient->SendChatMessage(message); } +void Session::kickPlayer(const std::string &playerName) +{ + if (!myNetServer) + { + assert(false); + return; + } + myNetServer->KickPlayer(playerName); +} + bool Session::isNetworkClientRunning() const { // This, and every place which calls this, is a HACK. diff --git a/src/session.h b/src/session.h index 86617cfe..21fe595b 100755 --- a/src/session.h +++ b/src/session.h @@ -59,6 +59,7 @@ public: int getCurrentGameID() const { return currentGameID; } void sendChatMessage(const std::string &message); + void kickPlayer(const std::string &playerName); bool isNetworkClientRunning() const; // TODO hack