diff --git a/src/core/avatarmanager.h b/src/core/avatarmanager.h index 49dee178..5aa44616 100644 --- a/src/core/avatarmanager.h +++ b/src/core/avatarmanager.h @@ -1,84 +1,84 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* A manager for avatar files, MD5sums and a cache. */ - -#ifndef _AVATARMANAGER_H_ -#define _AVATARMANAGER_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define MIN_AVATAR_FILE_SIZE 32 -#define MAX_AVATAR_FILE_SIZE 30720 - -struct AvatarFileState; - -class AvatarManager -{ -public: - - AvatarManager(); - ~AvatarManager(); - - bool Init(const std::string &dataDir, const std::string &cacheDir); - - void AddSingleAvatar(const std::string &fileName); - - boost::shared_ptr OpenAvatarFileForChunkRead(const std::string &fileName, unsigned &outFileSize, AvatarFileType &outFileType); - unsigned ChunkReadAvatarFile(boost::shared_ptr fileState, unsigned char *data, unsigned chunkSize); - - int AvatarFileToNetPackets(const std::string &fileName, unsigned requestId, NetPacketList &packets); - - bool GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf) const; - bool GetAvatarFileName(const MD5Buf &md5buf, std::string &fileName) const; - bool HasAvatar(const MD5Buf &md5buf) const; - bool StoreAvatarInCache(const MD5Buf &md5buf, AvatarFileType avatarFileType, const unsigned char *data, unsigned size); - - static bool IsValidAvatarFileType(AvatarFileType avatarFileType, const unsigned char *fileHeader, unsigned fileHeaderSize); - - void RemoveOldAvatarCacheEntries(); - -protected: - typedef std::map AvatarMap; - typedef std::list AvatarList; - typedef std::map TimeAvatarMap; - - bool InternalReadDirectory(const std::string &dir, AvatarMap &avatars); - -private: - mutable boost::mutex m_avatarsMutex; - AvatarMap m_avatars; - - mutable boost::mutex m_cachedAvatarsMutex; - AvatarMap m_cachedAvatars; - - mutable boost::mutex m_cacheDirMutex; - std::string m_cacheDir; - - mutable boost::mutex m_loadMutex; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* A manager for avatar files, MD5sums and a cache. */ + +#ifndef _AVATARMANAGER_H_ +#define _AVATARMANAGER_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MIN_AVATAR_FILE_SIZE 32 +#define MAX_AVATAR_FILE_SIZE 30720 + +struct AvatarFileState; + +class AvatarManager +{ +public: + + AvatarManager(); + ~AvatarManager(); + + bool Init(const std::string &dataDir, const std::string &cacheDir); + + void AddSingleAvatar(const std::string &fileName); + + boost::shared_ptr OpenAvatarFileForChunkRead(const std::string &fileName, unsigned &outFileSize, AvatarFileType &outFileType); + unsigned ChunkReadAvatarFile(boost::shared_ptr fileState, unsigned char *data, unsigned chunkSize); + + int AvatarFileToNetPackets(const std::string &fileName, unsigned requestId, NetPacketList &packets); + + bool GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf) const; + bool GetAvatarFileName(const MD5Buf &md5buf, std::string &fileName) const; + bool HasAvatar(const MD5Buf &md5buf) const; + bool StoreAvatarInCache(const MD5Buf &md5buf, AvatarFileType avatarFileType, const unsigned char *data, unsigned size); + + static bool IsValidAvatarFileType(AvatarFileType avatarFileType, const unsigned char *fileHeader, unsigned fileHeaderSize); + + void RemoveOldAvatarCacheEntries(); + +protected: + typedef std::map AvatarMap; + typedef std::list AvatarList; + typedef std::map TimeAvatarMap; + + bool InternalReadDirectory(const std::string &dir, AvatarMap &avatars); + +private: + mutable boost::mutex m_avatarsMutex; + AvatarMap m_avatars; + + mutable boost::mutex m_cachedAvatarsMutex; + AvatarMap m_cachedAvatars; + + mutable boost::mutex m_cacheDirMutex; + std::string m_cacheDir; + + mutable boost::mutex m_loadMutex; +}; + +#endif diff --git a/src/core/common/avatarmanager.cpp b/src/core/common/avatarmanager.cpp index a304f331..1eed443a 100644 --- a/src/core/common/avatarmanager.cpp +++ b/src/core/common/avatarmanager.cpp @@ -1,553 +1,553 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "avatarmanager.h" -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#ifdef POKERTH_DEDICATED_SERVER - #define MAX_NUMBER_OF_FILES 1024 - #define MAX_AVATAR_CACHE_AGE 2592000 // 1 Month -#else - #define MAX_NUMBER_OF_FILES 256 - #define MAX_AVATAR_CACHE_AGE 86400 -#endif - -#define PNG_HEADER "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" -#define PNG_HEADER_SIZE (sizeof(PNG_HEADER) - 1) -#define JPG_HEADER "\xff\xd8" -#define JPG_HEADER_SIZE (sizeof(JPG_HEADER) - 1) -#define GIF_HEADER_1 "GIF87a" -#define GIF_HEADER_2 "GIF89a" -#define GIF_HEADER_SIZE (sizeof(GIF_HEADER_1) - 1) -#define MAX_HEADER_SIZE PNG_HEADER_SIZE - - -using namespace std; -using namespace boost::filesystem; - -struct AvatarFileState -{ - ifstream inputStream; -}; - -AvatarManager::AvatarManager() -{ -} - -AvatarManager::~AvatarManager() -{ -} - -bool -AvatarManager::Init(const std::string &dataDir, const std::string &cacheDir) -{ - bool retVal = true; - bool tmpRet; - path tmpCachePath(cacheDir); - path tmpDataPath(dataDir); - { - boost::mutex::scoped_lock lock(m_cacheDirMutex); - m_cacheDir = tmpCachePath.directory_string(); - } - { - boost::mutex::scoped_lock lock(m_avatarsMutex); - tmpRet = InternalReadDirectory((tmpDataPath / "gfx/avatars/default/people/").directory_string(), m_avatars); - retVal = retVal && tmpRet; - tmpRet = InternalReadDirectory((tmpDataPath / "gfx/avatars/default/misc/").directory_string(), m_avatars); - retVal = retVal && tmpRet; - } - if (cacheDir.empty() || tmpCachePath.empty()) - LOG_ERROR("Cache directory was not set!"); - else - { - boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); - tmpRet = InternalReadDirectory(tmpCachePath.directory_string(), m_cachedAvatars); - retVal = retVal && tmpRet; - } - - return retVal; -} - -void -AvatarManager::AddSingleAvatar(const std::string &fileName) -{ - path filePath(fileName); - string tmpFileName(filePath.file_string()); - - if (!fileName.empty() && !tmpFileName.empty()) - { - unsigned outFileSize; - AvatarFileType outFileType; - boost::shared_ptr tmpFileState = OpenAvatarFileForChunkRead(tmpFileName, outFileSize, outFileType); - - // Check whether the avatar file is valid. - if (tmpFileState.get()) - { - tmpFileState.reset(); - - MD5Buf md5buf; - if (CryptHelper::MD5Sum(tmpFileName, md5buf)) - { - boost::mutex::scoped_lock lock(m_avatarsMutex); - m_avatars.insert(AvatarMap::value_type(md5buf, tmpFileName)); - } - } - } -} - -boost::shared_ptr -AvatarManager::OpenAvatarFileForChunkRead(const std::string &fileName, unsigned &outFileSize, AvatarFileType &outFileType) -{ - outFileSize = 0; - outFileType = AVATAR_FILE_TYPE_UNKNOWN; - boost::shared_ptr retVal; - try - { - path filePath(fileName); - string ext(extension(filePath)); - if (boost::algorithm::iequals(ext, ".png")) - outFileType = AVATAR_FILE_TYPE_PNG; - else if (boost::algorithm::iequals(ext, ".jpg") || boost::algorithm::iequals(ext, ".jpeg")) - outFileType = AVATAR_FILE_TYPE_JPG; - else if (boost::algorithm::iequals(ext, ".gif")) - outFileType = AVATAR_FILE_TYPE_GIF; - boost::shared_ptr fileState(new AvatarFileState); - fileState->inputStream.open(fileName.c_str(), ios_base::in | ios_base::binary); - if (!fileState->inputStream.fail()) - { - // Find out file size. - // Not fully portable, but works on win/linux/mac. - fileState->inputStream.seekg(0, ios_base::beg); - std::streampos startPos = fileState->inputStream.tellg(); - fileState->inputStream.seekg(0, ios_base::end); - std::streampos endPos = fileState->inputStream.tellg(); - fileState->inputStream.seekg(0, ios_base::beg); - std::streamoff posDiff(endPos - startPos); - outFileSize = (unsigned)posDiff; - if (outFileSize >= MIN_AVATAR_FILE_SIZE && outFileSize <= MAX_AVATAR_FILE_SIZE) - { - // Validate type of file by verifying image header. - unsigned char fileHeader[MAX_HEADER_SIZE]; - fileState->inputStream.read((char *)fileHeader, sizeof(fileHeader)); - fileState->inputStream.seekg(0, ios_base::beg); - - if (IsValidAvatarFileType(outFileType, fileHeader, sizeof(fileHeader))) - retVal = fileState; - } - } - } catch (...) - { - LOG_ERROR("Exception caught when trying to open avatar."); - } - return retVal; -} - -unsigned -AvatarManager::ChunkReadAvatarFile(boost::shared_ptr fileState, unsigned char *data, unsigned chunkSize) -{ - unsigned retVal = 0; - if (fileState.get()) - { - try - { - if (!fileState->inputStream.fail() && !fileState->inputStream.eof()) - { - fileState->inputStream.read((char *)data, chunkSize); - retVal = fileState->inputStream.gcount(); - } - } catch (...) - { - LOG_ERROR("Exception caught when trying to read avatar."); - } - } - return retVal; -} - -int -AvatarManager::AvatarFileToNetPackets(const string &fileName, unsigned requestId, NetPacketList &packets) -{ - // Serialize avatar access for now. - boost::mutex::scoped_lock lock(m_loadMutex); - - int retVal = ERR_NET_INVALID_AVATAR_FILE; - unsigned fileSize; - AvatarFileType fileType; - boost::shared_ptr tmpState = OpenAvatarFileForChunkRead(fileName, fileSize, fileType); - if (tmpState.get() && fileSize && fileType != AVATAR_FILE_TYPE_UNKNOWN) - { - boost::shared_ptr avatarHeader(new NetPacketAvatarHeader); - NetPacketAvatarHeader::Data avatarHeaderData; - avatarHeaderData.requestId = requestId; - avatarHeaderData.avatarFileSize = fileSize; - avatarHeaderData.avatarFileType = fileType; - static_cast(avatarHeader.get())->SetData(avatarHeaderData); - packets.push_back(avatarHeader); - - unsigned numBytes = 0; - unsigned totalBytesRead = 0; - do - { - boost::shared_ptr avatarFile(new NetPacketAvatarFile); - NetPacketAvatarFile::Data avatarFileData; - avatarFileData.fileData.resize(MAX_FILE_DATA_SIZE); - numBytes = ChunkReadAvatarFile(tmpState, &avatarFileData.fileData[0], MAX_FILE_DATA_SIZE); - if (numBytes) - { - avatarFileData.fileData.resize(numBytes); - avatarFileData.requestId = requestId; - totalBytesRead += numBytes; - static_cast(avatarFile.get())->SetData(avatarFileData); - packets.push_back(avatarFile); - } - } while (numBytes); - - if (fileSize != totalBytesRead) - retVal = ERR_NET_WRONG_AVATAR_SIZE; - else - { - boost::shared_ptr avatarEnd(new NetPacketAvatarEnd); - NetPacketAvatarEnd::Data avatarEndData; - avatarEndData.requestId = requestId; - static_cast(avatarEnd.get())->SetData(avatarEndData); - packets.push_back(avatarEnd); - retVal = 0; - } - } - return retVal; -} - -bool -AvatarManager::GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf) const -{ - bool found = false; - if (exists(fileName)) - { - // Scan default avatars first. - { - boost::mutex::scoped_lock lock(m_avatarsMutex); - AvatarMap::const_iterator i = m_avatars.begin(); - AvatarMap::const_iterator end = m_avatars.end(); - while (i != end) - { - if (i->second == fileName) - { - md5buf = i->first; - found = true; - break; - } - ++i; - } - } - // Check cached avatars next. - if (!found) - { - boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); - AvatarMap::const_iterator i = m_cachedAvatars.begin(); - AvatarMap::const_iterator end = m_cachedAvatars.end(); - while (i != end) - { - if (i->second == fileName) - { - md5buf = i->first; - found = true; - break; - } - ++i; - } - } - - // Calculate md5 sum if not found. - if (!found) - { - if (CryptHelper::MD5Sum(fileName, md5buf)) - found = true; - } - } - return found; -} - -bool -AvatarManager::GetAvatarFileName(const MD5Buf &md5buf, std::string &fileName) const -{ - bool retVal = false; - { - boost::mutex::scoped_lock lock(m_avatarsMutex); - AvatarMap::const_iterator pos = m_avatars.find(md5buf); - if (pos != m_avatars.end()) - { - fileName = pos->second; - retVal = true; - } - } - if (!retVal) - { - boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); - AvatarMap::const_iterator pos = m_cachedAvatars.find(md5buf); - if (pos != m_cachedAvatars.end()) - { - fileName = pos->second; - retVal = true; - } - } - return retVal; -} - -bool -AvatarManager::HasAvatar(const MD5Buf &md5buf) const -{ - string tmpFile; - return GetAvatarFileName(md5buf, tmpFile); -} - -bool -AvatarManager::StoreAvatarInCache(const MD5Buf &md5buf, AvatarFileType avatarFileType, const unsigned char *data, unsigned size) -{ - bool retVal = false; - string cacheDir; - { - boost::mutex::scoped_lock lock(m_cacheDirMutex); - cacheDir = m_cacheDir; - } - try - { - string ext; - switch (avatarFileType) - { - case AVATAR_FILE_TYPE_PNG: - ext = ".png"; - break; - case AVATAR_FILE_TYPE_JPG: - ext = ".jpg"; - break; - case AVATAR_FILE_TYPE_GIF: - ext = ".gif"; - break; - case AVATAR_FILE_TYPE_UNKNOWN: - break; - } - if (!ext.empty() && !cacheDir.empty()) - { - // Check header before storing file. - if (IsValidAvatarFileType(avatarFileType, data, size)) - { - path tmpPath(cacheDir); - tmpPath /= (md5buf.ToString() + ext); - string fileName(tmpPath.file_string()); - ofstream o(fileName.c_str(), ios_base::out | ios_base::binary | ios_base::trunc); - if (!o.fail()) - { - o.write((const char *)data, size); - { - boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); - m_cachedAvatars.insert(AvatarMap::value_type(md5buf, fileName)); - } - retVal = true; - } - } - } - } catch (...) - { - LOG_ERROR("Exception caught when trying to store avatar."); - } - return retVal; -} - -bool -AvatarManager::IsValidAvatarFileType(AvatarFileType avatarFileType, const unsigned char *fileHeader, unsigned fileHeaderSize) -{ - bool validType = false; - - switch (avatarFileType) - { - case AVATAR_FILE_TYPE_PNG: - if (fileHeaderSize >= PNG_HEADER_SIZE - && memcmp(fileHeader, PNG_HEADER, PNG_HEADER_SIZE) == 0) - { - validType = true; - } - break; - case AVATAR_FILE_TYPE_JPG: - if (fileHeaderSize >= JPG_HEADER_SIZE - && memcmp(fileHeader, JPG_HEADER, JPG_HEADER_SIZE) == 0) - { - validType = true; - } - break; - case AVATAR_FILE_TYPE_GIF: - if (fileHeaderSize >= GIF_HEADER_SIZE - && (memcmp(fileHeader, GIF_HEADER_1, GIF_HEADER_SIZE) == 0 - || memcmp(fileHeader, GIF_HEADER_2, GIF_HEADER_SIZE) == 0)) - { - validType = true; - } - break; - case AVATAR_FILE_TYPE_UNKNOWN: - break; - } - return validType; -} - -void -AvatarManager::RemoveOldAvatarCacheEntries() -{ - string cacheDir; - { - boost::mutex::scoped_lock lock(m_cacheDirMutex); - cacheDir = m_cacheDir; - } - try - { - path cachePath(cacheDir); - cacheDir = cachePath.directory_string(); - // Never delete anything if we do not have a special cache dir set. - if (!cacheDir.empty()) - { - boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); - - // First pass: Remove files which no longer exist. - // Count files and record age. - AvatarList removeList; - TimeAvatarMap timeMap; - unsigned fileCount = 0; - { - AvatarMap::const_iterator i = m_cachedAvatars.begin(); - AvatarMap::const_iterator end = m_cachedAvatars.end(); - while (i != end) - { - bool keepFile = false; - path filePath(i->second); - string fileString(filePath.file_string()); - // Only consider files which are definitely in the cache dir. - if (fileString.size() > cacheDir.size() && fileString.substr(0, cacheDir.size()) == cacheDir) - { - // Only consider files with MD5 as file name. - MD5Buf tmpBuf; - if (exists(filePath) && tmpBuf.FromString(basename(filePath))) - { - ++fileCount; - timeMap.insert(TimeAvatarMap::value_type(last_write_time(filePath), i->first)); - keepFile = true; - } - } - if (!keepFile) - removeList.push_back(i->first); - - ++i; - } - } - - { - AvatarList::const_iterator i = removeList.begin(); - AvatarList::const_iterator end = removeList.end(); - while (i != end) - { - m_cachedAvatars.erase(*i); - ++i; - } - removeList.clear(); - } - - // Remove and physically delete files in one of the - // following cases: - // 1. More than MAX_NUMBER_OF_FILES files are present - // - delete until only MAX_NUMBER_OF_FILES/2 are left. - // 2. Files are older than 30 days. - - if (m_cachedAvatars.size() > MAX_NUMBER_OF_FILES) - { - while (!timeMap.empty() && m_cachedAvatars.size() > MAX_NUMBER_OF_FILES / 2) - { - TimeAvatarMap::iterator i = timeMap.begin(); - AvatarMap::iterator pos = m_cachedAvatars.find(i->second); - if (pos != m_cachedAvatars.end()) - { - path tmpPath(pos->second); - remove(tmpPath); - m_cachedAvatars.erase(pos); - } - timeMap.erase(i); - } - } - - // Get reference time. - time_t curTime = time(NULL); - while (!timeMap.empty() && !m_cachedAvatars.empty()) - { - TimeAvatarMap::iterator i = timeMap.begin(); - if (curTime - i->first < MAX_AVATAR_CACHE_AGE) - break; - AvatarMap::iterator pos = m_cachedAvatars.find(i->second); - if (pos != m_cachedAvatars.end()) - { - path tmpPath(pos->second); - remove(tmpPath); - m_cachedAvatars.erase(pos); - } - timeMap.erase(i); - } - } - } catch (...) - { - LOG_ERROR("Exception caught while cleaning up cache."); - } -} - -bool -AvatarManager::InternalReadDirectory(const std::string &dir, AvatarMap &avatars) -{ - bool retVal = true; - try - { - // This method is not thread safe. Only call after locking the map. - directory_iterator i(dir); - directory_iterator end; - - while (i != end) - { - if (is_regular(i->status())) - { - string md5sum(basename(i->path())); - MD5Buf md5buf; - string fileName(i->path().file_string()); - if (md5buf.FromString(md5sum)) - { - // Only consider files with md5sum as name. - avatars.insert(AvatarMap::value_type(md5buf, fileName)); - } - } - ++i; - } - } catch (...) - { - LOG_ERROR("Exception caught when trying to scan avatar directory."); - retVal = false; - } - return retVal; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "avatarmanager.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef POKERTH_DEDICATED_SERVER + #define MAX_NUMBER_OF_FILES 1024 + #define MAX_AVATAR_CACHE_AGE 2592000 // 1 Month +#else + #define MAX_NUMBER_OF_FILES 256 + #define MAX_AVATAR_CACHE_AGE 86400 +#endif + +#define PNG_HEADER "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" +#define PNG_HEADER_SIZE (sizeof(PNG_HEADER) - 1) +#define JPG_HEADER "\xff\xd8" +#define JPG_HEADER_SIZE (sizeof(JPG_HEADER) - 1) +#define GIF_HEADER_1 "GIF87a" +#define GIF_HEADER_2 "GIF89a" +#define GIF_HEADER_SIZE (sizeof(GIF_HEADER_1) - 1) +#define MAX_HEADER_SIZE PNG_HEADER_SIZE + + +using namespace std; +using namespace boost::filesystem; + +struct AvatarFileState +{ + ifstream inputStream; +}; + +AvatarManager::AvatarManager() +{ +} + +AvatarManager::~AvatarManager() +{ +} + +bool +AvatarManager::Init(const std::string &dataDir, const std::string &cacheDir) +{ + bool retVal = true; + bool tmpRet; + path tmpCachePath(cacheDir); + path tmpDataPath(dataDir); + { + boost::mutex::scoped_lock lock(m_cacheDirMutex); + m_cacheDir = tmpCachePath.directory_string(); + } + { + boost::mutex::scoped_lock lock(m_avatarsMutex); + tmpRet = InternalReadDirectory((tmpDataPath / "gfx/avatars/default/people/").directory_string(), m_avatars); + retVal = retVal && tmpRet; + tmpRet = InternalReadDirectory((tmpDataPath / "gfx/avatars/default/misc/").directory_string(), m_avatars); + retVal = retVal && tmpRet; + } + if (cacheDir.empty() || tmpCachePath.empty()) + LOG_ERROR("Cache directory was not set!"); + else + { + boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); + tmpRet = InternalReadDirectory(tmpCachePath.directory_string(), m_cachedAvatars); + retVal = retVal && tmpRet; + } + + return retVal; +} + +void +AvatarManager::AddSingleAvatar(const std::string &fileName) +{ + path filePath(fileName); + string tmpFileName(filePath.file_string()); + + if (!fileName.empty() && !tmpFileName.empty()) + { + unsigned outFileSize; + AvatarFileType outFileType; + boost::shared_ptr tmpFileState = OpenAvatarFileForChunkRead(tmpFileName, outFileSize, outFileType); + + // Check whether the avatar file is valid. + if (tmpFileState.get()) + { + tmpFileState.reset(); + + MD5Buf md5buf; + if (CryptHelper::MD5Sum(tmpFileName, md5buf)) + { + boost::mutex::scoped_lock lock(m_avatarsMutex); + m_avatars.insert(AvatarMap::value_type(md5buf, tmpFileName)); + } + } + } +} + +boost::shared_ptr +AvatarManager::OpenAvatarFileForChunkRead(const std::string &fileName, unsigned &outFileSize, AvatarFileType &outFileType) +{ + outFileSize = 0; + outFileType = AVATAR_FILE_TYPE_UNKNOWN; + boost::shared_ptr retVal; + try + { + path filePath(fileName); + string ext(extension(filePath)); + if (boost::algorithm::iequals(ext, ".png")) + outFileType = AVATAR_FILE_TYPE_PNG; + else if (boost::algorithm::iequals(ext, ".jpg") || boost::algorithm::iequals(ext, ".jpeg")) + outFileType = AVATAR_FILE_TYPE_JPG; + else if (boost::algorithm::iequals(ext, ".gif")) + outFileType = AVATAR_FILE_TYPE_GIF; + boost::shared_ptr fileState(new AvatarFileState); + fileState->inputStream.open(fileName.c_str(), ios_base::in | ios_base::binary); + if (!fileState->inputStream.fail()) + { + // Find out file size. + // Not fully portable, but works on win/linux/mac. + fileState->inputStream.seekg(0, ios_base::beg); + std::streampos startPos = fileState->inputStream.tellg(); + fileState->inputStream.seekg(0, ios_base::end); + std::streampos endPos = fileState->inputStream.tellg(); + fileState->inputStream.seekg(0, ios_base::beg); + std::streamoff posDiff(endPos - startPos); + outFileSize = (unsigned)posDiff; + if (outFileSize >= MIN_AVATAR_FILE_SIZE && outFileSize <= MAX_AVATAR_FILE_SIZE) + { + // Validate type of file by verifying image header. + unsigned char fileHeader[MAX_HEADER_SIZE]; + fileState->inputStream.read((char *)fileHeader, sizeof(fileHeader)); + fileState->inputStream.seekg(0, ios_base::beg); + + if (IsValidAvatarFileType(outFileType, fileHeader, sizeof(fileHeader))) + retVal = fileState; + } + } + } catch (...) + { + LOG_ERROR("Exception caught when trying to open avatar."); + } + return retVal; +} + +unsigned +AvatarManager::ChunkReadAvatarFile(boost::shared_ptr fileState, unsigned char *data, unsigned chunkSize) +{ + unsigned retVal = 0; + if (fileState.get()) + { + try + { + if (!fileState->inputStream.fail() && !fileState->inputStream.eof()) + { + fileState->inputStream.read((char *)data, chunkSize); + retVal = fileState->inputStream.gcount(); + } + } catch (...) + { + LOG_ERROR("Exception caught when trying to read avatar."); + } + } + return retVal; +} + +int +AvatarManager::AvatarFileToNetPackets(const string &fileName, unsigned requestId, NetPacketList &packets) +{ + // Serialize avatar access for now. + boost::mutex::scoped_lock lock(m_loadMutex); + + int retVal = ERR_NET_INVALID_AVATAR_FILE; + unsigned fileSize; + AvatarFileType fileType; + boost::shared_ptr tmpState = OpenAvatarFileForChunkRead(fileName, fileSize, fileType); + if (tmpState.get() && fileSize && fileType != AVATAR_FILE_TYPE_UNKNOWN) + { + boost::shared_ptr avatarHeader(new NetPacketAvatarHeader); + NetPacketAvatarHeader::Data avatarHeaderData; + avatarHeaderData.requestId = requestId; + avatarHeaderData.avatarFileSize = fileSize; + avatarHeaderData.avatarFileType = fileType; + static_cast(avatarHeader.get())->SetData(avatarHeaderData); + packets.push_back(avatarHeader); + + unsigned numBytes = 0; + unsigned totalBytesRead = 0; + do + { + boost::shared_ptr avatarFile(new NetPacketAvatarFile); + NetPacketAvatarFile::Data avatarFileData; + avatarFileData.fileData.resize(MAX_FILE_DATA_SIZE); + numBytes = ChunkReadAvatarFile(tmpState, &avatarFileData.fileData[0], MAX_FILE_DATA_SIZE); + if (numBytes) + { + avatarFileData.fileData.resize(numBytes); + avatarFileData.requestId = requestId; + totalBytesRead += numBytes; + static_cast(avatarFile.get())->SetData(avatarFileData); + packets.push_back(avatarFile); + } + } while (numBytes); + + if (fileSize != totalBytesRead) + retVal = ERR_NET_WRONG_AVATAR_SIZE; + else + { + boost::shared_ptr avatarEnd(new NetPacketAvatarEnd); + NetPacketAvatarEnd::Data avatarEndData; + avatarEndData.requestId = requestId; + static_cast(avatarEnd.get())->SetData(avatarEndData); + packets.push_back(avatarEnd); + retVal = 0; + } + } + return retVal; +} + +bool +AvatarManager::GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf) const +{ + bool found = false; + if (exists(fileName)) + { + // Scan default avatars first. + { + boost::mutex::scoped_lock lock(m_avatarsMutex); + AvatarMap::const_iterator i = m_avatars.begin(); + AvatarMap::const_iterator end = m_avatars.end(); + while (i != end) + { + if (i->second == fileName) + { + md5buf = i->first; + found = true; + break; + } + ++i; + } + } + // Check cached avatars next. + if (!found) + { + boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); + AvatarMap::const_iterator i = m_cachedAvatars.begin(); + AvatarMap::const_iterator end = m_cachedAvatars.end(); + while (i != end) + { + if (i->second == fileName) + { + md5buf = i->first; + found = true; + break; + } + ++i; + } + } + + // Calculate md5 sum if not found. + if (!found) + { + if (CryptHelper::MD5Sum(fileName, md5buf)) + found = true; + } + } + return found; +} + +bool +AvatarManager::GetAvatarFileName(const MD5Buf &md5buf, std::string &fileName) const +{ + bool retVal = false; + { + boost::mutex::scoped_lock lock(m_avatarsMutex); + AvatarMap::const_iterator pos = m_avatars.find(md5buf); + if (pos != m_avatars.end()) + { + fileName = pos->second; + retVal = true; + } + } + if (!retVal) + { + boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); + AvatarMap::const_iterator pos = m_cachedAvatars.find(md5buf); + if (pos != m_cachedAvatars.end()) + { + fileName = pos->second; + retVal = true; + } + } + return retVal; +} + +bool +AvatarManager::HasAvatar(const MD5Buf &md5buf) const +{ + string tmpFile; + return GetAvatarFileName(md5buf, tmpFile); +} + +bool +AvatarManager::StoreAvatarInCache(const MD5Buf &md5buf, AvatarFileType avatarFileType, const unsigned char *data, unsigned size) +{ + bool retVal = false; + string cacheDir; + { + boost::mutex::scoped_lock lock(m_cacheDirMutex); + cacheDir = m_cacheDir; + } + try + { + string ext; + switch (avatarFileType) + { + case AVATAR_FILE_TYPE_PNG: + ext = ".png"; + break; + case AVATAR_FILE_TYPE_JPG: + ext = ".jpg"; + break; + case AVATAR_FILE_TYPE_GIF: + ext = ".gif"; + break; + case AVATAR_FILE_TYPE_UNKNOWN: + break; + } + if (!ext.empty() && !cacheDir.empty()) + { + // Check header before storing file. + if (IsValidAvatarFileType(avatarFileType, data, size)) + { + path tmpPath(cacheDir); + tmpPath /= (md5buf.ToString() + ext); + string fileName(tmpPath.file_string()); + ofstream o(fileName.c_str(), ios_base::out | ios_base::binary | ios_base::trunc); + if (!o.fail()) + { + o.write((const char *)data, size); + { + boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); + m_cachedAvatars.insert(AvatarMap::value_type(md5buf, fileName)); + } + retVal = true; + } + } + } + } catch (...) + { + LOG_ERROR("Exception caught when trying to store avatar."); + } + return retVal; +} + +bool +AvatarManager::IsValidAvatarFileType(AvatarFileType avatarFileType, const unsigned char *fileHeader, unsigned fileHeaderSize) +{ + bool validType = false; + + switch (avatarFileType) + { + case AVATAR_FILE_TYPE_PNG: + if (fileHeaderSize >= PNG_HEADER_SIZE + && memcmp(fileHeader, PNG_HEADER, PNG_HEADER_SIZE) == 0) + { + validType = true; + } + break; + case AVATAR_FILE_TYPE_JPG: + if (fileHeaderSize >= JPG_HEADER_SIZE + && memcmp(fileHeader, JPG_HEADER, JPG_HEADER_SIZE) == 0) + { + validType = true; + } + break; + case AVATAR_FILE_TYPE_GIF: + if (fileHeaderSize >= GIF_HEADER_SIZE + && (memcmp(fileHeader, GIF_HEADER_1, GIF_HEADER_SIZE) == 0 + || memcmp(fileHeader, GIF_HEADER_2, GIF_HEADER_SIZE) == 0)) + { + validType = true; + } + break; + case AVATAR_FILE_TYPE_UNKNOWN: + break; + } + return validType; +} + +void +AvatarManager::RemoveOldAvatarCacheEntries() +{ + string cacheDir; + { + boost::mutex::scoped_lock lock(m_cacheDirMutex); + cacheDir = m_cacheDir; + } + try + { + path cachePath(cacheDir); + cacheDir = cachePath.directory_string(); + // Never delete anything if we do not have a special cache dir set. + if (!cacheDir.empty()) + { + boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); + + // First pass: Remove files which no longer exist. + // Count files and record age. + AvatarList removeList; + TimeAvatarMap timeMap; + unsigned fileCount = 0; + { + AvatarMap::const_iterator i = m_cachedAvatars.begin(); + AvatarMap::const_iterator end = m_cachedAvatars.end(); + while (i != end) + { + bool keepFile = false; + path filePath(i->second); + string fileString(filePath.file_string()); + // Only consider files which are definitely in the cache dir. + if (fileString.size() > cacheDir.size() && fileString.substr(0, cacheDir.size()) == cacheDir) + { + // Only consider files with MD5 as file name. + MD5Buf tmpBuf; + if (exists(filePath) && tmpBuf.FromString(basename(filePath))) + { + ++fileCount; + timeMap.insert(TimeAvatarMap::value_type(last_write_time(filePath), i->first)); + keepFile = true; + } + } + if (!keepFile) + removeList.push_back(i->first); + + ++i; + } + } + + { + AvatarList::const_iterator i = removeList.begin(); + AvatarList::const_iterator end = removeList.end(); + while (i != end) + { + m_cachedAvatars.erase(*i); + ++i; + } + removeList.clear(); + } + + // Remove and physically delete files in one of the + // following cases: + // 1. More than MAX_NUMBER_OF_FILES files are present + // - delete until only MAX_NUMBER_OF_FILES/2 are left. + // 2. Files are older than 30 days. + + if (m_cachedAvatars.size() > MAX_NUMBER_OF_FILES) + { + while (!timeMap.empty() && m_cachedAvatars.size() > MAX_NUMBER_OF_FILES / 2) + { + TimeAvatarMap::iterator i = timeMap.begin(); + AvatarMap::iterator pos = m_cachedAvatars.find(i->second); + if (pos != m_cachedAvatars.end()) + { + path tmpPath(pos->second); + remove(tmpPath); + m_cachedAvatars.erase(pos); + } + timeMap.erase(i); + } + } + + // Get reference time. + time_t curTime = time(NULL); + while (!timeMap.empty() && !m_cachedAvatars.empty()) + { + TimeAvatarMap::iterator i = timeMap.begin(); + if (curTime - i->first < MAX_AVATAR_CACHE_AGE) + break; + AvatarMap::iterator pos = m_cachedAvatars.find(i->second); + if (pos != m_cachedAvatars.end()) + { + path tmpPath(pos->second); + remove(tmpPath); + m_cachedAvatars.erase(pos); + } + timeMap.erase(i); + } + } + } catch (...) + { + LOG_ERROR("Exception caught while cleaning up cache."); + } +} + +bool +AvatarManager::InternalReadDirectory(const std::string &dir, AvatarMap &avatars) +{ + bool retVal = true; + try + { + // This method is not thread safe. Only call after locking the map. + directory_iterator i(dir); + directory_iterator end; + + while (i != end) + { + if (is_regular(i->status())) + { + string md5sum(basename(i->path())); + MD5Buf md5buf; + string fileName(i->path().file_string()); + if (md5buf.FromString(md5sum)) + { + // Only consider files with md5sum as name. + avatars.insert(AvatarMap::value_type(md5buf, fileName)); + } + } + ++i; + } + } catch (...) + { + LOG_ERROR("Exception caught when trying to scan avatar directory."); + retVal = false; + } + return retVal; +} + diff --git a/src/core/common/crypthelper.cpp b/src/core/common/crypthelper.cpp index ebc2a980..622766d6 100644 --- a/src/core/common/crypthelper.cpp +++ b/src/core/common/crypthelper.cpp @@ -1,132 +1,132 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "crypthelper.h" - - -#include -#include -#include - -using namespace std; - -// Helper function. -static int -fromHex(int ch) -{ - int retVal = -1; - - if (ch >= '0' && ch <= '9') - retVal = ch - '0'; - else if (ch >= 'a' && ch <= 'f') - retVal = ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'F') - retVal = ch - 'A' + 10; - - return retVal; -} - - -MD5Buf::MD5Buf() -{ - memset(data, 0, sizeof(data)); -} - - -std::string -MD5Buf::ToString() const -{ - // Create a hex-based string from the MD5 data. - string retValue; - char tmpBuf[2 + 1]; - tmpBuf[sizeof(tmpBuf) - 1] = 0; - for (int i = 0; i < MD5_DATA_SIZE; i++) - { - sprintf(tmpBuf, "%02x", data[i]); - retValue += tmpBuf; - } - return retValue; -} - -bool -MD5Buf::FromString(const std::string &text) -{ - // Convert hex-based string to MD5 data. - bool retVal = false; - if (text.size() == 2 * MD5_DATA_SIZE) - { - unsigned char *tmpData = data; - const char *t = text.c_str(); - int i = 0; - for (; i < MD5_DATA_SIZE; i++) { - int part1 = fromHex(*t++); - if (part1 == -1) - break; - int part2 = fromHex(*t++); - if (part2 == -1) - break; - *tmpData++ = (part1<<4) + part2; - } - retVal = i == MD5_DATA_SIZE; - } - return retVal; -} - -bool -MD5Buf::IsZero() const -{ - return *this == MD5Buf(); -} - -bool -MD5Buf::operator==(const MD5Buf &other) const -{ - return memcmp(data, other.data, MD5_DATA_SIZE) == 0; -} - -bool -MD5Buf::operator<(const MD5Buf &other) const -{ - return memcmp(data, other.data, MD5_DATA_SIZE) < 0; -} - -bool -CryptHelper::MD5Sum(const std::string &fileName, MD5Buf &buf) -{ - bool retVal = false; - FILE *file = fopen(fileName.c_str(), "rb"); - - if (file) - { - // Calculate MD5 sum of file. - unsigned char readBuf[8192]; - MD5_CTX context; - int numBytes; - - MD5_Init(&context); - while ((numBytes = fread(readBuf, 1, sizeof(readBuf), file)) > 0) - MD5_Update(&context, readBuf, numBytes); - MD5_Final(buf.data, &context); - retVal = ferror(file) == 0; - - fclose(file); - } - return retVal; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "crypthelper.h" + + +#include +#include +#include + +using namespace std; + +// Helper function. +static int +fromHex(int ch) +{ + int retVal = -1; + + if (ch >= '0' && ch <= '9') + retVal = ch - '0'; + else if (ch >= 'a' && ch <= 'f') + retVal = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + retVal = ch - 'A' + 10; + + return retVal; +} + + +MD5Buf::MD5Buf() +{ + memset(data, 0, sizeof(data)); +} + + +std::string +MD5Buf::ToString() const +{ + // Create a hex-based string from the MD5 data. + string retValue; + char tmpBuf[2 + 1]; + tmpBuf[sizeof(tmpBuf) - 1] = 0; + for (int i = 0; i < MD5_DATA_SIZE; i++) + { + sprintf(tmpBuf, "%02x", data[i]); + retValue += tmpBuf; + } + return retValue; +} + +bool +MD5Buf::FromString(const std::string &text) +{ + // Convert hex-based string to MD5 data. + bool retVal = false; + if (text.size() == 2 * MD5_DATA_SIZE) + { + unsigned char *tmpData = data; + const char *t = text.c_str(); + int i = 0; + for (; i < MD5_DATA_SIZE; i++) { + int part1 = fromHex(*t++); + if (part1 == -1) + break; + int part2 = fromHex(*t++); + if (part2 == -1) + break; + *tmpData++ = (part1<<4) + part2; + } + retVal = i == MD5_DATA_SIZE; + } + return retVal; +} + +bool +MD5Buf::IsZero() const +{ + return *this == MD5Buf(); +} + +bool +MD5Buf::operator==(const MD5Buf &other) const +{ + return memcmp(data, other.data, MD5_DATA_SIZE) == 0; +} + +bool +MD5Buf::operator<(const MD5Buf &other) const +{ + return memcmp(data, other.data, MD5_DATA_SIZE) < 0; +} + +bool +CryptHelper::MD5Sum(const std::string &fileName, MD5Buf &buf) +{ + bool retVal = false; + FILE *file = fopen(fileName.c_str(), "rb"); + + if (file) + { + // Calculate MD5 sum of file. + unsigned char readBuf[8192]; + MD5_CTX context; + int numBytes; + + MD5_Init(&context); + while ((numBytes = fread(readBuf, 1, sizeof(readBuf), file)) > 0) + MD5_Update(&context, readBuf, numBytes); + MD5_Final(buf.data, &context); + retVal = ferror(file) == 0; + + fclose(file); + } + return retVal; +} + diff --git a/src/core/common/thread.cpp b/src/core/common/thread.cpp index 87e4cdd7..d18eced6 100644 --- a/src/core/common/thread.cpp +++ b/src/core/common/thread.cpp @@ -1,154 +1,154 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "thread.h" - -// This is ugly, but I can't help it. -inline void ADD_MSEC_TO_XTIME(boost::xtime &xt, unsigned msec) -{ - xt.sec += msec / 1000; - xt.nsec += (msec % 1000) * 1000000; - if (xt.nsec > NANOSECONDS_PER_SECOND) - { - xt.sec++; - xt.nsec -= NANOSECONDS_PER_SECOND; - } -} - - -// Helper class for thread creation. -class ThreadStarter -{ -public: - ThreadStarter(Thread &thread) : m_thread(thread) {} - void operator()() - { - m_thread.MainWrapper(); - } - -private: - Thread &m_thread; -}; - -Thread::Thread() -{ -} - -Thread::~Thread() -{ -} - -void -Thread::Run() -{ - boost::mutex::scoped_lock threadLock(m_threadObjMutex); - - // Create the boost thread object. - if (!m_threadObj.get()) - { - // Initialise data structures within the context of the thread - // who runs/terminates this thread. - m_userReqTerminateLock.reset(new boost::timed_mutex::scoped_try_lock(m_shouldTerminateMutex)); - m_threadStartBarrier.reset(new boost::barrier(2)); - - m_threadObj.reset(new boost::thread(ThreadStarter(*this))); - m_threadStartBarrier->wait(); - } -} - -void -Thread::SignalTermination() -{ - // Unlock the shouldTerminateMutex. - if (m_userReqTerminateLock.get()) // cannot signal before calling Run - m_userReqTerminateLock->unlock(); -} - -bool -Thread::Join(unsigned msecTimeout) -{ - if (!IsRunning()) - return true; - - bool tmpIsTerminated; - if (msecTimeout == THREAD_WAIT_INFINITE) - { - // Wait infinitely. - boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); - tmpIsTerminated = true; - } - else - { - // Calculate time after timeout - boost::xtime t; - boost::xtime_get(&t, boost::TIME_UTC); - ADD_MSEC_TO_XTIME(t, msecTimeout); - - // Wait for the termination of the application code. - boost::timed_mutex::scoped_timed_lock lock(m_isTerminatedMutex, t); - tmpIsTerminated = lock.locked(); - } - - if (tmpIsTerminated) - { - boost::mutex::scoped_lock lock(m_threadObjMutex); - // Wait for "real" termination of the thread. - if (m_threadObj.get()) - { - m_threadObj->join(); - m_threadObj.reset(); - } - } - - return tmpIsTerminated; -} - -void -Thread::Msleep(unsigned msecs) -{ - boost::xtime t; - boost::xtime_get(&t, boost::TIME_UTC); - ADD_MSEC_TO_XTIME(t, msecs); - - boost::thread::sleep(t); -} - -void -Thread::MainWrapper() -{ - boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); - assert(m_threadStartBarrier.get()); - m_threadStartBarrier->wait(); - this->Main(); -} - -bool -Thread::ShouldTerminate() const -{ - boost::timed_mutex::scoped_try_lock lock(m_shouldTerminateMutex); - return lock.locked(); -} - -bool -Thread::IsRunning() const -{ - boost::mutex::scoped_lock threadLock(m_threadObjMutex); - return (m_threadObj.get() != NULL); -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "thread.h" + +// This is ugly, but I can't help it. +inline void ADD_MSEC_TO_XTIME(boost::xtime &xt, unsigned msec) +{ + xt.sec += msec / 1000; + xt.nsec += (msec % 1000) * 1000000; + if (xt.nsec > NANOSECONDS_PER_SECOND) + { + xt.sec++; + xt.nsec -= NANOSECONDS_PER_SECOND; + } +} + + +// Helper class for thread creation. +class ThreadStarter +{ +public: + ThreadStarter(Thread &thread) : m_thread(thread) {} + void operator()() + { + m_thread.MainWrapper(); + } + +private: + Thread &m_thread; +}; + +Thread::Thread() +{ +} + +Thread::~Thread() +{ +} + +void +Thread::Run() +{ + boost::mutex::scoped_lock threadLock(m_threadObjMutex); + + // Create the boost thread object. + if (!m_threadObj.get()) + { + // Initialise data structures within the context of the thread + // who runs/terminates this thread. + m_userReqTerminateLock.reset(new boost::timed_mutex::scoped_try_lock(m_shouldTerminateMutex)); + m_threadStartBarrier.reset(new boost::barrier(2)); + + m_threadObj.reset(new boost::thread(ThreadStarter(*this))); + m_threadStartBarrier->wait(); + } +} + +void +Thread::SignalTermination() +{ + // Unlock the shouldTerminateMutex. + if (m_userReqTerminateLock.get()) // cannot signal before calling Run + m_userReqTerminateLock->unlock(); +} + +bool +Thread::Join(unsigned msecTimeout) +{ + if (!IsRunning()) + return true; + + bool tmpIsTerminated; + if (msecTimeout == THREAD_WAIT_INFINITE) + { + // Wait infinitely. + boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); + tmpIsTerminated = true; + } + else + { + // Calculate time after timeout + boost::xtime t; + boost::xtime_get(&t, boost::TIME_UTC); + ADD_MSEC_TO_XTIME(t, msecTimeout); + + // Wait for the termination of the application code. + boost::timed_mutex::scoped_timed_lock lock(m_isTerminatedMutex, t); + tmpIsTerminated = lock.locked(); + } + + if (tmpIsTerminated) + { + boost::mutex::scoped_lock lock(m_threadObjMutex); + // Wait for "real" termination of the thread. + if (m_threadObj.get()) + { + m_threadObj->join(); + m_threadObj.reset(); + } + } + + return tmpIsTerminated; +} + +void +Thread::Msleep(unsigned msecs) +{ + boost::xtime t; + boost::xtime_get(&t, boost::TIME_UTC); + ADD_MSEC_TO_XTIME(t, msecs); + + boost::thread::sleep(t); +} + +void +Thread::MainWrapper() +{ + boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); + assert(m_threadStartBarrier.get()); + m_threadStartBarrier->wait(); + this->Main(); +} + +bool +Thread::ShouldTerminate() const +{ + boost::timed_mutex::scoped_try_lock lock(m_shouldTerminateMutex); + return lock.locked(); +} + +bool +Thread::IsRunning() const +{ + boost::mutex::scoped_lock threadLock(m_threadObjMutex); + return (m_threadObj.get() != NULL); +} + diff --git a/src/core/convhelper.h b/src/core/convhelper.h index 8f94d841..c3d31a42 100644 --- a/src/core/convhelper.h +++ b/src/core/convhelper.h @@ -1,34 +1,34 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Helper class for character conversion functions. */ - -#ifndef _CRYPTHELPER_H_ -#define _CRYPTHELPER_H_ - -#include - -class ConvHelper -{ -public: - - static std::string NativeToUtf8(const std::string &inStr); - static std::string Utf8ToNative(const std::string &inStr); -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Helper class for character conversion functions. */ + +#ifndef _CRYPTHELPER_H_ +#define _CRYPTHELPER_H_ + +#include + +class ConvHelper +{ +public: + + static std::string NativeToUtf8(const std::string &inStr); + static std::string Utf8ToNative(const std::string &inStr); +}; + +#endif diff --git a/src/core/crypthelper.h b/src/core/crypthelper.h index 5d1846d8..09d4699e 100644 --- a/src/core/crypthelper.h +++ b/src/core/crypthelper.h @@ -1,49 +1,49 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Helper class for crypt functions. */ - -#ifndef _CRYPTHELPER_H_ -#define _CRYPTHELPER_H_ - -#include - -#define MD5_DATA_SIZE 16 - -struct MD5Buf -{ - MD5Buf(); - - std::string ToString() const; - bool FromString(const std::string &text); - bool IsZero() const; - - bool operator==(const MD5Buf &other) const; - bool operator<(const MD5Buf &other) const; - - unsigned char data[MD5_DATA_SIZE]; -}; - -class CryptHelper -{ -public: - - static bool MD5Sum(const std::string &fileName, MD5Buf &buf); -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Helper class for crypt functions. */ + +#ifndef _CRYPTHELPER_H_ +#define _CRYPTHELPER_H_ + +#include + +#define MD5_DATA_SIZE 16 + +struct MD5Buf +{ + MD5Buf(); + + std::string ToString() const; + bool FromString(const std::string &text); + bool IsZero() const; + + bool operator==(const MD5Buf &other) const; + bool operator<(const MD5Buf &other) const; + + unsigned char data[MD5_DATA_SIZE]; +}; + +class CryptHelper +{ +public: + + static bool MD5Sum(const std::string &fileName, MD5Buf &buf); +}; + +#endif diff --git a/src/core/thread.h b/src/core/thread.h index f2c1b7e9..6bc90e4d 100644 --- a/src/core/thread.h +++ b/src/core/thread.h @@ -1,88 +1,88 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Base class for threads (used by network client/server). */ - -#ifndef _THREAD_H_ -#define _THREAD_H_ - -#include -#include -#include - -#ifndef NANOSECONDS_PER_SECOND -#define NANOSECONDS_PER_SECOND 1000000000 -#endif - -#define THREAD_WAIT_INFINITE 0xFFFFFFFF - -class Thread -{ -public: - Thread(); - virtual ~Thread(); - - // Start the thread. Will do nothing if the - // thread was already started. - void Run(); - - // Signal that the thread should be terminated - virtual void SignalTermination(); - - // Wait for the termination of the thread. - // Only one Thread should wait for the termination! - // You SHOULD always call join for a thread. - bool Join(unsigned msecTimeout); - - // Sleep the currently active thread. - static void Msleep(unsigned msecs); - -protected: - - // Startup function. - void MainWrapper(); - - // Main function of the thread. - virtual void Main() = 0; - - // Checks whether termination has been requested. - bool ShouldTerminate() const; - - // Checks whether the thread is running. - bool IsRunning() const; - -private: - - // Flag specifying whether the application code within the - // thread was terminated. - mutable boost::timed_mutex m_isTerminatedMutex; - - // Flag specifying whether the thread should be terminated. - mutable boost::timed_mutex m_shouldTerminateMutex; - mutable boost::shared_ptr m_userReqTerminateLock; - - // The boost thread object. - boost::shared_ptr m_threadObj; - mutable boost::mutex m_threadObjMutex; - - mutable boost::shared_ptr m_threadStartBarrier; - -friend class ThreadStarter; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Base class for threads (used by network client/server). */ + +#ifndef _THREAD_H_ +#define _THREAD_H_ + +#include +#include +#include + +#ifndef NANOSECONDS_PER_SECOND +#define NANOSECONDS_PER_SECOND 1000000000 +#endif + +#define THREAD_WAIT_INFINITE 0xFFFFFFFF + +class Thread +{ +public: + Thread(); + virtual ~Thread(); + + // Start the thread. Will do nothing if the + // thread was already started. + void Run(); + + // Signal that the thread should be terminated + virtual void SignalTermination(); + + // Wait for the termination of the thread. + // Only one Thread should wait for the termination! + // You SHOULD always call join for a thread. + bool Join(unsigned msecTimeout); + + // Sleep the currently active thread. + static void Msleep(unsigned msecs); + +protected: + + // Startup function. + void MainWrapper(); + + // Main function of the thread. + virtual void Main() = 0; + + // Checks whether termination has been requested. + bool ShouldTerminate() const; + + // Checks whether the thread is running. + bool IsRunning() const; + +private: + + // Flag specifying whether the application code within the + // thread was terminated. + mutable boost::timed_mutex m_isTerminatedMutex; + + // Flag specifying whether the thread should be terminated. + mutable boost::timed_mutex m_shouldTerminateMutex; + mutable boost::shared_ptr m_userReqTerminateLock; + + // The boost thread object. + boost::shared_ptr m_threadObj; + mutable boost::mutex m_threadObjMutex; + + mutable boost::shared_ptr m_threadStartBarrier; + +friend class ThreadStarter; +}; + +#endif diff --git a/src/core/win32/convhelper.cpp b/src/core/win32/convhelper.cpp index 76d9e413..9ac70d1f 100644 --- a/src/core/win32/convhelper.cpp +++ b/src/core/win32/convhelper.cpp @@ -1,76 +1,76 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "convhelper.h" - -#ifndef _WIN32 -#error This file is Windows only. -#endif - -#include - -using namespace std; - -static string -Convert(const std::string &inStr, int fromCP, int toCP) -{ - // convert str from current Windows source to target charset - string retStr(inStr); - - if (!inStr.empty()) - { - int len = (int)inStr.length() + 1; - int reqLen = ::MultiByteToWideChar(fromCP, 0, inStr.c_str(), len, NULL, 0); - - if (reqLen) - { - wchar_t *wstr = new wchar_t[reqLen]; - wstr[0] = L'\0'; - if (::MultiByteToWideChar(fromCP, 0, inStr.c_str(), len, wstr, reqLen) == (int)reqLen) - { - len = reqLen; - reqLen = ::WideCharToMultiByte(toCP, 0, wstr, len, NULL, 0, NULL, NULL); - - if (reqLen) - { - char *str = new char[reqLen]; - if (::WideCharToMultiByte(toCP, 0, wstr, len, str, reqLen, NULL, NULL) == (int)reqLen) - retStr = str; - delete[] str; - } - } - - delete[] wstr; - } - } - return retStr; -} - -string -ConvHelper::NativeToUtf8(const std::string &inStr) -{ - return Convert(inStr, CP_ACP, CP_UTF8); -} - -string -ConvHelper::Utf8ToNative(const std::string &inStr) -{ - return Convert(inStr, CP_UTF8, CP_ACP); -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "convhelper.h" + +#ifndef _WIN32 +#error This file is Windows only. +#endif + +#include + +using namespace std; + +static string +Convert(const std::string &inStr, int fromCP, int toCP) +{ + // convert str from current Windows source to target charset + string retStr(inStr); + + if (!inStr.empty()) + { + int len = (int)inStr.length() + 1; + int reqLen = ::MultiByteToWideChar(fromCP, 0, inStr.c_str(), len, NULL, 0); + + if (reqLen) + { + wchar_t *wstr = new wchar_t[reqLen]; + wstr[0] = L'\0'; + if (::MultiByteToWideChar(fromCP, 0, inStr.c_str(), len, wstr, reqLen) == (int)reqLen) + { + len = reqLen; + reqLen = ::WideCharToMultiByte(toCP, 0, wstr, len, NULL, 0, NULL, NULL); + + if (reqLen) + { + char *str = new char[reqLen]; + if (::WideCharToMultiByte(toCP, 0, wstr, len, str, reqLen, NULL, NULL) == (int)reqLen) + retStr = str; + delete[] str; + } + } + + delete[] wstr; + } + } + return retStr; +} + +string +ConvHelper::NativeToUtf8(const std::string &inStr) +{ + return Convert(inStr, CP_ACP, CP_UTF8); +} + +string +ConvHelper::Utf8ToNative(const std::string &inStr) +{ + return Convert(inStr, CP_UTF8, CP_ACP); +} + diff --git a/src/engine/local_engine/engine_msg.h b/src/engine/local_engine/engine_msg.h index 9d8fc244..2f18b9ab 100644 --- a/src/engine/local_engine/engine_msg.h +++ b/src/engine/local_engine/engine_msg.h @@ -1,37 +1,37 @@ -/*************************************************************************** - * Copyright (C) 2006 by FThauer FHammer * - * f.thauer@web.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef _ENGINE_MSG_H_ -#define _ENGINE_MSG_H_ - -// Engine errors -> LocalExceptions -#define ERR_SEAT_NOT_FOUND 10001 -#define ERR_ACTIVE_PLAYER_NOT_FOUND 10002 -#define ERR_RUNNING_PLAYER_NOT_FOUND 10003 -#define ERR_DEALER_NOT_FOUND 10004 -#define ERR_CURRENT_PLAYER_NOT_FOUND 10005 - -#define ERR_NEXT_DEALER_NOT_FOUND 10010 -#define ERR_NEXT_ACTIVE_PLAYER_NOT_FOUND 10011 -#define ERR_FORMER_RUNNING_PLAYER_NOT_FOUND 10012 - -#define ERR_NO_WINNER 10020 - -#endif - +/*************************************************************************** + * Copyright (C) 2006 by FThauer FHammer * + * f.thauer@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef _ENGINE_MSG_H_ +#define _ENGINE_MSG_H_ + +// Engine errors -> LocalExceptions +#define ERR_SEAT_NOT_FOUND 10001 +#define ERR_ACTIVE_PLAYER_NOT_FOUND 10002 +#define ERR_RUNNING_PLAYER_NOT_FOUND 10003 +#define ERR_DEALER_NOT_FOUND 10004 +#define ERR_CURRENT_PLAYER_NOT_FOUND 10005 + +#define ERR_NEXT_DEALER_NOT_FOUND 10010 +#define ERR_NEXT_ACTIVE_PLAYER_NOT_FOUND 10011 +#define ERR_FORMER_RUNNING_PLAYER_NOT_FOUND 10012 + +#define ERR_NO_WINNER 10020 + +#endif + diff --git a/src/engine/network_engine/clientboard.cpp b/src/engine/network_engine/clientboard.cpp index 65091ece..cb6a2f78 100644 --- a/src/engine/network_engine/clientboard.cpp +++ b/src/engine/network_engine/clientboard.cpp @@ -1,134 +1,134 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "clientboard.h" - -#include -#include - -using namespace std; - -ClientBoard::ClientBoard() -: currentHand(0), pot(0), sets(0) -{ -} - - -ClientBoard::~ClientBoard() -{ -} - -void -ClientBoard::setPlayerLists(PlayerList sl, PlayerList apl, PlayerList rpl) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - seatsList = sl; - activePlayerList = apl; - runningPlayerList = rpl; -} - -void -ClientBoard::setHand(HandInterface* br) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - currentHand = br; -} - -void -ClientBoard::setMyCards(int* theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i = 0; i < 5; i++) - myCards[i] = theValue[i]; -} - -void -ClientBoard::getMyCards(int* theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i = 0; i < 5; i++) - theValue[i] = myCards[i]; -} - -int -ClientBoard::getPot() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return pot; -} - -void -ClientBoard::setPot(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - pot = theValue; -} - -int -ClientBoard::getSets() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return sets; -} - -void -ClientBoard::setSets(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - sets = theValue; -} - -void -ClientBoard::collectSets() -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - sets = 0; - PlayerListConstIterator it_c; - for (it_c=seatsList->begin(); it_c!=seatsList->end(); it_c++) - sets += (*it_c)->getMySet(); - -} - -void -ClientBoard::collectPot() -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - pot += sets; - sets = 0; -} - -void -ClientBoard::distributePot() -{ - -} - -std::list -ClientBoard::getWinners() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return winners; -} - -void -ClientBoard::setWinners(const std::list &w) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - winners = w; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "clientboard.h" + +#include +#include + +using namespace std; + +ClientBoard::ClientBoard() +: currentHand(0), pot(0), sets(0) +{ +} + + +ClientBoard::~ClientBoard() +{ +} + +void +ClientBoard::setPlayerLists(PlayerList sl, PlayerList apl, PlayerList rpl) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + seatsList = sl; + activePlayerList = apl; + runningPlayerList = rpl; +} + +void +ClientBoard::setHand(HandInterface* br) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + currentHand = br; +} + +void +ClientBoard::setMyCards(int* theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i = 0; i < 5; i++) + myCards[i] = theValue[i]; +} + +void +ClientBoard::getMyCards(int* theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i = 0; i < 5; i++) + theValue[i] = myCards[i]; +} + +int +ClientBoard::getPot() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return pot; +} + +void +ClientBoard::setPot(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + pot = theValue; +} + +int +ClientBoard::getSets() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return sets; +} + +void +ClientBoard::setSets(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + sets = theValue; +} + +void +ClientBoard::collectSets() +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + sets = 0; + PlayerListConstIterator it_c; + for (it_c=seatsList->begin(); it_c!=seatsList->end(); it_c++) + sets += (*it_c)->getMySet(); + +} + +void +ClientBoard::collectPot() +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + pot += sets; + sets = 0; +} + +void +ClientBoard::distributePot() +{ + +} + +std::list +ClientBoard::getWinners() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return winners; +} + +void +ClientBoard::setWinners(const std::list &w) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + winners = w; +} + diff --git a/src/engine/network_engine/clientboard.h b/src/engine/network_engine/clientboard.h index 427a9d27..ded89180 100644 --- a/src/engine/network_engine/clientboard.h +++ b/src/engine/network_engine/clientboard.h @@ -1,72 +1,72 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CLIENTBOARD_H -#define CLIENTBOARD_H - -#include -#include -#include - - -class PlayerInterface; -class HandInterface; - - -class ClientBoard : public BoardInterface -{ -public: - ClientBoard(); - ~ClientBoard(); - - void setPlayerLists(PlayerList, PlayerList, PlayerList); - void setHand(HandInterface*); - - void setMyCards(int* theValue); - void getMyCards(int* theValue); - - int getPot() const; - void setPot(int theValue); - int getSets() const; - void setSets(int theValue); - - void collectSets(); - void collectPot(); - - void distributePot(); - - std::list getWinners() const; - void setWinners(const std::list &winners); - -private: - mutable boost::recursive_mutex m_syncMutex; - - PlayerList seatsList; - PlayerList activePlayerList; - PlayerList runningPlayerList; - - HandInterface *currentHand; - - std::list winners; - - int myCards[5]; - int pot; - int sets; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef CLIENTBOARD_H +#define CLIENTBOARD_H + +#include +#include +#include + + +class PlayerInterface; +class HandInterface; + + +class ClientBoard : public BoardInterface +{ +public: + ClientBoard(); + ~ClientBoard(); + + void setPlayerLists(PlayerList, PlayerList, PlayerList); + void setHand(HandInterface*); + + void setMyCards(int* theValue); + void getMyCards(int* theValue); + + int getPot() const; + void setPot(int theValue); + int getSets() const; + void setSets(int theValue); + + void collectSets(); + void collectPot(); + + void distributePot(); + + std::list getWinners() const; + void setWinners(const std::list &winners); + +private: + mutable boost::recursive_mutex m_syncMutex; + + PlayerList seatsList; + PlayerList activePlayerList; + PlayerList runningPlayerList; + + HandInterface *currentHand; + + std::list winners; + + int myCards[5]; + int pot; + int sets; +}; + +#endif diff --git a/src/engine/network_engine/clientenginefactory.cpp b/src/engine/network_engine/clientenginefactory.cpp index da36de59..43c0442d 100644 --- a/src/engine/network_engine/clientenginefactory.cpp +++ b/src/engine/network_engine/clientenginefactory.cpp @@ -1,66 +1,66 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "clientenginefactory.h" - -#include "clienthand.h" -#include "clientboard.h" -#include "clientplayer.h" -#include "clientbero.h" - - - -ClientEngineFactory::ClientEngineFactory() -{ -} - - -ClientEngineFactory::~ClientEngineFactory() -{ -} - - -HandInterface* ClientEngineFactory::createHand(boost::shared_ptr f, GuiInterface *g, BoardInterface *b, PlayerList sl, PlayerList apl, PlayerList rpl, int id, int sP, int dP, int sB,int sC) -{ - return new ClientHand(f, g, b, sl, apl, rpl, id, sP, dP, sB, sC); -} - -BoardInterface* ClientEngineFactory::createBoard() -{ - return new ClientBoard; -} - -boost::shared_ptr ClientEngineFactory::createPlayer(BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB) -{ - return boost::shared_ptr (new ClientPlayer(NULL, b, id, uniqueId, type, name, avatar, sC, aS, mB)); -} - -std::vector > ClientEngineFactory::createBeRo(HandInterface* hi, int id, unsigned dP, int sB) { - - std::vector > myBeRo; - - myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_PREFLOP))); - myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_FLOP))); - myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_TURN))); - myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_RIVER))); - myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_POST_RIVER))); - - return myBeRo; - -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "clientenginefactory.h" + +#include "clienthand.h" +#include "clientboard.h" +#include "clientplayer.h" +#include "clientbero.h" + + + +ClientEngineFactory::ClientEngineFactory() +{ +} + + +ClientEngineFactory::~ClientEngineFactory() +{ +} + + +HandInterface* ClientEngineFactory::createHand(boost::shared_ptr f, GuiInterface *g, BoardInterface *b, PlayerList sl, PlayerList apl, PlayerList rpl, int id, int sP, int dP, int sB,int sC) +{ + return new ClientHand(f, g, b, sl, apl, rpl, id, sP, dP, sB, sC); +} + +BoardInterface* ClientEngineFactory::createBoard() +{ + return new ClientBoard; +} + +boost::shared_ptr ClientEngineFactory::createPlayer(BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB) +{ + return boost::shared_ptr (new ClientPlayer(NULL, b, id, uniqueId, type, name, avatar, sC, aS, mB)); +} + +std::vector > ClientEngineFactory::createBeRo(HandInterface* hi, int id, unsigned dP, int sB) { + + std::vector > myBeRo; + + myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_PREFLOP))); + myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_FLOP))); + myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_TURN))); + myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_RIVER))); + myBeRo.push_back(boost::shared_ptr(new ClientBeRo(hi, id, dP, sB, GAME_STATE_POST_RIVER))); + + return myBeRo; + +} + diff --git a/src/engine/network_engine/clientenginefactory.h b/src/engine/network_engine/clientenginefactory.h index 6d3e45ab..9243702d 100644 --- a/src/engine/network_engine/clientenginefactory.h +++ b/src/engine/network_engine/clientenginefactory.h @@ -1,47 +1,47 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CLIENTENGINEFACTORY_H -#define CLIENTENGINEFACTORY_H - -#include - -#include -#include -#include - -#include -#include - - -class ConfigFile; - -class ClientEngineFactory : public EngineFactory -{ -public: - ClientEngineFactory(); - ~ClientEngineFactory(); - - HandInterface* createHand(boost::shared_ptr f, GuiInterface *g, BoardInterface *b, PlayerList sl, PlayerList apl, PlayerList rpl, int id, int sP, int dP, int sB,int sC); - BoardInterface* createBoard(); - boost::shared_ptr createPlayer(BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB); - std::vector > createBeRo(HandInterface* hi, int id, unsigned dP, int sB); - -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef CLIENTENGINEFACTORY_H +#define CLIENTENGINEFACTORY_H + +#include + +#include +#include +#include + +#include +#include + + +class ConfigFile; + +class ClientEngineFactory : public EngineFactory +{ +public: + ClientEngineFactory(); + ~ClientEngineFactory(); + + HandInterface* createHand(boost::shared_ptr f, GuiInterface *g, BoardInterface *b, PlayerList sl, PlayerList apl, PlayerList rpl, int id, int sP, int dP, int sB,int sC); + BoardInterface* createBoard(); + boost::shared_ptr createPlayer(BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB); + std::vector > createBeRo(HandInterface* hi, int id, unsigned dP, int sB); + +}; + +#endif diff --git a/src/engine/network_engine/clienthand.cpp b/src/engine/network_engine/clienthand.cpp index 71bc3b61..e2b11e59 100644 --- a/src/engine/network_engine/clienthand.cpp +++ b/src/engine/network_engine/clienthand.cpp @@ -1,337 +1,337 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "clienthand.h" -#include - -using namespace std; - -ClientHand::ClientHand(boost::shared_ptr f, GuiInterface *g, BoardInterface *b, PlayerList sl, PlayerList apl, PlayerList rpl, int id, int sP, int dP, int sB,int sC) -: myFactory(f), myGui(g), myBoard(b), seatsList(sl), activePlayerList(apl), runningPlayerList(rpl), myID(id), startQuantityPlayers(sP), dealerPosition(dP), currentRound(0), - smallBlind(sB), startCash(sC), lastPlayersTurn(-1), allInCondition(0), - cardsShown(false), bettingRoundsPlayed(0) -{ - PlayerListIterator it; - - myBoard->setHand(this); - - for(it=seatsList->begin(); it!=seatsList->end(); it++) { - (*it)->setHand(this); - // myFlipCards auf 0 setzen - (*it)->setMyCardsFlip(0, 0); - } - - // roundStartCashArray fuellen - // cardsvalue zuruecksetzen - // remove all buttons - for(it=activePlayerList->begin(); it!=activePlayerList->end(); it++) { - - boost::shared_ptr tmpPlayer = *it; - - tmpPlayer->setMyRoundStartCash(tmpPlayer->getMyCash()); - tmpPlayer->setMyCardsValueInt(0); - tmpPlayer->setMyButton(0); - if (tmpPlayer->getMyUniqueID() == dealerPosition) - tmpPlayer->setMyButton(1); - } - - // the rest of the buttons are assigned later as received from the server. - - // Preflop, Flop, Turn und River erstellen - myBeRo = myFactory->createBeRo(this, myID, dealerPosition, smallBlind); -} - - - -ClientHand::~ClientHand() -{ -} - -void -ClientHand::start() -{ -} - -PlayerList -ClientHand::getSeatsList() const -{ - return seatsList; -} - -PlayerList -ClientHand::getActivePlayerList() const -{ - return activePlayerList; -} - -PlayerList -ClientHand::getRunningPlayerList() const -{ - return runningPlayerList; -} - -PlayerListIterator -ClientHand::getSeatIt(unsigned uniqueId) const -{ - PlayerListIterator it; - - for(it=seatsList->begin(); it!=seatsList->end(); it++) { - if((*it)->getMyUniqueID() == uniqueId) { - break; - } - } - - return it; -} - -PlayerListIterator -ClientHand::getActivePlayerIt(unsigned uniqueId) const -{ - PlayerListIterator it; - - for(it=activePlayerList->begin(); it!=activePlayerList->end(); it++) { - if((*it)->getMyUniqueID() == uniqueId) { - break; - } - } - - return it; -} - -PlayerListIterator -ClientHand::getRunningPlayerIt(unsigned uniqueId) const -{ - PlayerListIterator it; - - for(it=runningPlayerList->begin(); it!=runningPlayerList->end(); it++) { - if((*it)->getMyUniqueID() == uniqueId) { - break; - } - } - - return it; -} - -BoardInterface* -ClientHand::getBoard() const -{ - return myBoard; -} - -boost::shared_ptr -ClientHand::getPreflop() const -{ - return myBeRo[GAME_STATE_PREFLOP]; -} - -boost::shared_ptr -ClientHand::getFlop() const -{ - return myBeRo[GAME_STATE_FLOP]; -} - -boost::shared_ptr -ClientHand::getTurn() const -{ - return myBeRo[GAME_STATE_TURN]; -} - -boost::shared_ptr -ClientHand::getRiver() const -{ - return myBeRo[GAME_STATE_RIVER]; -} - -boost::shared_ptr -ClientHand::getCurrentBeRo() const -{ - return myBeRo[currentRound]; -} - - -GuiInterface* -ClientHand::getGuiInterface() const -{ - return myGui; -} - -void -ClientHand::setMyID(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myID = theValue; -} - -int -ClientHand::getMyID() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myID; -} - -void -ClientHand::setStartQuantityPlayers(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - startQuantityPlayers = theValue; -} - -int -ClientHand::getStartQuantityPlayers() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return startQuantityPlayers; -} - -void -ClientHand::setCurrentRound(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - currentRound = theValue; -} - -int -ClientHand::getCurrentRound() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return currentRound; -} - -void -ClientHand::setDealerPosition(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - dealerPosition = theValue; -} - -int -ClientHand::getDealerPosition() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return dealerPosition; -} - -void -ClientHand::setSmallBlind(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - smallBlind = theValue; -} - -int -ClientHand::getSmallBlind() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return smallBlind; -} - -void -ClientHand::setAllInCondition(bool theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - allInCondition = theValue; -} - -bool -ClientHand::getAllInCondition() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return allInCondition; -} - -void -ClientHand::setStartCash(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - startCash = theValue; -} - -int -ClientHand::getStartCash() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return startCash; -} - -void -ClientHand::setBettingRoundsPlayed(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - bettingRoundsPlayed = theValue; -} - -int -ClientHand::getBettingRoundsPlayed() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return bettingRoundsPlayed; -} - -void -ClientHand::setLastPlayersTurn(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - lastPlayersTurn = theValue; -} - -int -ClientHand::getLastPlayersTurn() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return lastPlayersTurn; -} - -void -ClientHand::setCardsShown(bool theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - cardsShown = theValue; -} - -bool -ClientHand::getCardsShown() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return cardsShown; -} - -void -ClientHand::switchRounds() -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - - PlayerListIterator it, it_1; - - // refresh runningPlayerList - for(it=runningPlayerList->begin(); it!=runningPlayerList->end(); ) { - if((*it)->getMyAction() == PLAYER_ACTION_FOLD || (*it)->getMyAction() == PLAYER_ACTION_ALLIN) { - it = runningPlayerList->erase(it); - if(!(runningPlayerList->empty())) { - - it_1 = it; - if(it_1 == runningPlayerList->begin()) it_1 = runningPlayerList->end(); - it_1--; - getCurrentBeRo()->setCurrentPlayersTurnId((*it_1)->getMyUniqueID()); - - } - } else { - it++; - } - } -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "clienthand.h" +#include + +using namespace std; + +ClientHand::ClientHand(boost::shared_ptr f, GuiInterface *g, BoardInterface *b, PlayerList sl, PlayerList apl, PlayerList rpl, int id, int sP, int dP, int sB,int sC) +: myFactory(f), myGui(g), myBoard(b), seatsList(sl), activePlayerList(apl), runningPlayerList(rpl), myID(id), startQuantityPlayers(sP), dealerPosition(dP), currentRound(0), + smallBlind(sB), startCash(sC), lastPlayersTurn(-1), allInCondition(0), + cardsShown(false), bettingRoundsPlayed(0) +{ + PlayerListIterator it; + + myBoard->setHand(this); + + for(it=seatsList->begin(); it!=seatsList->end(); it++) { + (*it)->setHand(this); + // myFlipCards auf 0 setzen + (*it)->setMyCardsFlip(0, 0); + } + + // roundStartCashArray fuellen + // cardsvalue zuruecksetzen + // remove all buttons + for(it=activePlayerList->begin(); it!=activePlayerList->end(); it++) { + + boost::shared_ptr tmpPlayer = *it; + + tmpPlayer->setMyRoundStartCash(tmpPlayer->getMyCash()); + tmpPlayer->setMyCardsValueInt(0); + tmpPlayer->setMyButton(0); + if (tmpPlayer->getMyUniqueID() == dealerPosition) + tmpPlayer->setMyButton(1); + } + + // the rest of the buttons are assigned later as received from the server. + + // Preflop, Flop, Turn und River erstellen + myBeRo = myFactory->createBeRo(this, myID, dealerPosition, smallBlind); +} + + + +ClientHand::~ClientHand() +{ +} + +void +ClientHand::start() +{ +} + +PlayerList +ClientHand::getSeatsList() const +{ + return seatsList; +} + +PlayerList +ClientHand::getActivePlayerList() const +{ + return activePlayerList; +} + +PlayerList +ClientHand::getRunningPlayerList() const +{ + return runningPlayerList; +} + +PlayerListIterator +ClientHand::getSeatIt(unsigned uniqueId) const +{ + PlayerListIterator it; + + for(it=seatsList->begin(); it!=seatsList->end(); it++) { + if((*it)->getMyUniqueID() == uniqueId) { + break; + } + } + + return it; +} + +PlayerListIterator +ClientHand::getActivePlayerIt(unsigned uniqueId) const +{ + PlayerListIterator it; + + for(it=activePlayerList->begin(); it!=activePlayerList->end(); it++) { + if((*it)->getMyUniqueID() == uniqueId) { + break; + } + } + + return it; +} + +PlayerListIterator +ClientHand::getRunningPlayerIt(unsigned uniqueId) const +{ + PlayerListIterator it; + + for(it=runningPlayerList->begin(); it!=runningPlayerList->end(); it++) { + if((*it)->getMyUniqueID() == uniqueId) { + break; + } + } + + return it; +} + +BoardInterface* +ClientHand::getBoard() const +{ + return myBoard; +} + +boost::shared_ptr +ClientHand::getPreflop() const +{ + return myBeRo[GAME_STATE_PREFLOP]; +} + +boost::shared_ptr +ClientHand::getFlop() const +{ + return myBeRo[GAME_STATE_FLOP]; +} + +boost::shared_ptr +ClientHand::getTurn() const +{ + return myBeRo[GAME_STATE_TURN]; +} + +boost::shared_ptr +ClientHand::getRiver() const +{ + return myBeRo[GAME_STATE_RIVER]; +} + +boost::shared_ptr +ClientHand::getCurrentBeRo() const +{ + return myBeRo[currentRound]; +} + + +GuiInterface* +ClientHand::getGuiInterface() const +{ + return myGui; +} + +void +ClientHand::setMyID(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myID = theValue; +} + +int +ClientHand::getMyID() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myID; +} + +void +ClientHand::setStartQuantityPlayers(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + startQuantityPlayers = theValue; +} + +int +ClientHand::getStartQuantityPlayers() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return startQuantityPlayers; +} + +void +ClientHand::setCurrentRound(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + currentRound = theValue; +} + +int +ClientHand::getCurrentRound() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return currentRound; +} + +void +ClientHand::setDealerPosition(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + dealerPosition = theValue; +} + +int +ClientHand::getDealerPosition() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return dealerPosition; +} + +void +ClientHand::setSmallBlind(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + smallBlind = theValue; +} + +int +ClientHand::getSmallBlind() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return smallBlind; +} + +void +ClientHand::setAllInCondition(bool theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + allInCondition = theValue; +} + +bool +ClientHand::getAllInCondition() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return allInCondition; +} + +void +ClientHand::setStartCash(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + startCash = theValue; +} + +int +ClientHand::getStartCash() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return startCash; +} + +void +ClientHand::setBettingRoundsPlayed(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + bettingRoundsPlayed = theValue; +} + +int +ClientHand::getBettingRoundsPlayed() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return bettingRoundsPlayed; +} + +void +ClientHand::setLastPlayersTurn(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + lastPlayersTurn = theValue; +} + +int +ClientHand::getLastPlayersTurn() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return lastPlayersTurn; +} + +void +ClientHand::setCardsShown(bool theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + cardsShown = theValue; +} + +bool +ClientHand::getCardsShown() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return cardsShown; +} + +void +ClientHand::switchRounds() +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + + PlayerListIterator it, it_1; + + // refresh runningPlayerList + for(it=runningPlayerList->begin(); it!=runningPlayerList->end(); ) { + if((*it)->getMyAction() == PLAYER_ACTION_FOLD || (*it)->getMyAction() == PLAYER_ACTION_ALLIN) { + it = runningPlayerList->erase(it); + if(!(runningPlayerList->empty())) { + + it_1 = it; + if(it_1 == runningPlayerList->begin()) it_1 = runningPlayerList->end(); + it_1--; + getCurrentBeRo()->setCurrentPlayersTurnId((*it_1)->getMyUniqueID()); + + } + } else { + it++; + } + } +} + diff --git a/src/engine/network_engine/clienthand.h b/src/engine/network_engine/clienthand.h index eebfff94..376b7147 100644 --- a/src/engine/network_engine/clienthand.h +++ b/src/engine/network_engine/clienthand.h @@ -1,123 +1,123 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * -`* but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CLIENTHAND_H -#define CLIENTHAND_H - -#include -#include -#include -#include -#include -#include -#include - -#include - -class ClientHand : public HandInterface -{ - public: - ClientHand ( boost::shared_ptr f, GuiInterface*, BoardInterface*, PlayerList, PlayerList, PlayerList , int, int, int, int, int ); - ~ClientHand(); - - void start(); - - PlayerList getSeatsList() const; - PlayerList getActivePlayerList() const; - PlayerList getRunningPlayerList() const; - - PlayerListIterator getSeatIt(unsigned) const; - PlayerListIterator getActivePlayerIt(unsigned) const; - PlayerListIterator getRunningPlayerIt(unsigned) const; - - BoardInterface* getBoard() const; - boost::shared_ptr getPreflop() const; - boost::shared_ptr getFlop() const; - boost::shared_ptr getTurn() const; - boost::shared_ptr getRiver() const; - GuiInterface* getGuiInterface() const; - boost::shared_ptr getCurrentBeRo() const; - - void setMyID ( int theValue ); - int getMyID() const; - - void setCurrentQuantityPlayers ( int theValue ); - int getCurrentQuantityPlayers() const; - - void setStartQuantityPlayers ( int theValue ); - int getStartQuantityPlayers() const; - - void setCurrentRound ( int theValue ); - int getCurrentRound() const; - - void setDealerPosition ( int theValue ); - int getDealerPosition() const; - - void setSmallBlind ( int theValue ); - int getSmallBlind() const; - - void setAllInCondition ( bool theValue ); - bool getAllInCondition() const; - - void setStartCash ( int theValue ); - int getStartCash() const; - - void setBettingRoundsPlayed ( int theValue ); - int getBettingRoundsPlayed() const; - - void setLastPlayersTurn ( int theValue ); - int getLastPlayersTurn() const; - - void setCardsShown ( bool theValue ); - bool getCardsShown() const; - - void switchRounds(); - - - private: - mutable boost::recursive_mutex m_syncMutex; - - boost::shared_ptr myFactory; - GuiInterface *myGui; - BoardInterface *myBoard; - - PlayerList seatsList; - PlayerList activePlayerList; - PlayerList runningPlayerList; - - std::vector > myBeRo; - - int myID; - int startQuantityPlayers; - unsigned dealerPosition; - int currentRound; //0 = preflop, 1 = flop, 2 = turn, 3 = river - int smallBlind; - int startCash; - - int lastPlayersTurn; - - bool allInCondition; - bool cardsShown; - - // hier steht bis zu welcher bettingRound der human player gespielt hat: 0 - nur Preflop, 1 - bis Flop, ... - int bettingRoundsPlayed; -}; - -#endif - - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * +`* but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef CLIENTHAND_H +#define CLIENTHAND_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +class ClientHand : public HandInterface +{ + public: + ClientHand ( boost::shared_ptr f, GuiInterface*, BoardInterface*, PlayerList, PlayerList, PlayerList , int, int, int, int, int ); + ~ClientHand(); + + void start(); + + PlayerList getSeatsList() const; + PlayerList getActivePlayerList() const; + PlayerList getRunningPlayerList() const; + + PlayerListIterator getSeatIt(unsigned) const; + PlayerListIterator getActivePlayerIt(unsigned) const; + PlayerListIterator getRunningPlayerIt(unsigned) const; + + BoardInterface* getBoard() const; + boost::shared_ptr getPreflop() const; + boost::shared_ptr getFlop() const; + boost::shared_ptr getTurn() const; + boost::shared_ptr getRiver() const; + GuiInterface* getGuiInterface() const; + boost::shared_ptr getCurrentBeRo() const; + + void setMyID ( int theValue ); + int getMyID() const; + + void setCurrentQuantityPlayers ( int theValue ); + int getCurrentQuantityPlayers() const; + + void setStartQuantityPlayers ( int theValue ); + int getStartQuantityPlayers() const; + + void setCurrentRound ( int theValue ); + int getCurrentRound() const; + + void setDealerPosition ( int theValue ); + int getDealerPosition() const; + + void setSmallBlind ( int theValue ); + int getSmallBlind() const; + + void setAllInCondition ( bool theValue ); + bool getAllInCondition() const; + + void setStartCash ( int theValue ); + int getStartCash() const; + + void setBettingRoundsPlayed ( int theValue ); + int getBettingRoundsPlayed() const; + + void setLastPlayersTurn ( int theValue ); + int getLastPlayersTurn() const; + + void setCardsShown ( bool theValue ); + bool getCardsShown() const; + + void switchRounds(); + + + private: + mutable boost::recursive_mutex m_syncMutex; + + boost::shared_ptr myFactory; + GuiInterface *myGui; + BoardInterface *myBoard; + + PlayerList seatsList; + PlayerList activePlayerList; + PlayerList runningPlayerList; + + std::vector > myBeRo; + + int myID; + int startQuantityPlayers; + unsigned dealerPosition; + int currentRound; //0 = preflop, 1 = flop, 2 = turn, 3 = river + int smallBlind; + int startCash; + + int lastPlayersTurn; + + bool allInCondition; + bool cardsShown; + + // hier steht bis zu welcher bettingRound der human player gespielt hat: 0 - nur Preflop, 1 - bis Flop, ... + int bettingRoundsPlayed; +}; + +#endif + + diff --git a/src/engine/network_engine/clientplayer.cpp b/src/engine/network_engine/clientplayer.cpp index 4acd4a16..a994fb00 100644 --- a/src/engine/network_engine/clientplayer.cpp +++ b/src/engine/network_engine/clientplayer.cpp @@ -1,503 +1,503 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "clientplayer.h" -#include - -using namespace std; - - -ClientPlayer::ClientPlayer(ConfigFile *c, BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB) -: PlayerInterface(), myConfig(c), currentHand(0), currentBoard(b), myCardsValue(0), myID(id), myUniqueID(uniqueId), myType(type), myName(name), myAvatar(avatar), myDude(0), myDude4(0), myCardsValueInt(0), myOdds(-1.0), myCash(sC), mySet(0), myLastRelativeSet(0), myAction(0), myButton(mB), myActiveStatus(aS), myTurn(0), myRoundStartCash(0), sBluff(0), sBluffStatus(0) -{ -} - - -ClientPlayer::~ClientPlayer() -{ -} - - -void -ClientPlayer::setHand(HandInterface* br) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - currentHand = br; -} - -int -ClientPlayer::getMyID() const -{ - return myID; -} - -unsigned -ClientPlayer::getMyUniqueID() const -{ - return myUniqueID; -} - -PlayerType -ClientPlayer::getMyType() const -{ - return myType; -} - -void -ClientPlayer::setMyDude(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myDude = theValue; -} - -int -ClientPlayer::getMyDude() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myDude; -} - -void -ClientPlayer::setMyDude4(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myDude4 = theValue; -} - -int -ClientPlayer::getMyDude4() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myDude4; -} - -void -ClientPlayer::setMyName(const std::string& theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myName = theValue; -} - -std::string -ClientPlayer::getMyName() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myName; -} - -void -ClientPlayer::setMyAvatar(const std::string& theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myAvatar = theValue; -} - -std::string -ClientPlayer::getMyAvatar() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myAvatar; -} - -void -ClientPlayer::setMyCash(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myCash = theValue; -} - -int -ClientPlayer::getMyCash() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myCash; -} - -void -ClientPlayer::setMySet(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myLastRelativeSet = theValue; -} - -void -ClientPlayer::setMySetAbsolute(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - mySet = theValue; -} - -void -ClientPlayer::setMySetNull() -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - mySet = 0; - myLastRelativeSet = 0; -} - -int -ClientPlayer::getMySet() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return mySet; -} - -int -ClientPlayer::getMyLastRelativeSet() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myLastRelativeSet; -} - -void -ClientPlayer::setMyAction(int theValue, bool /*blind*/) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myAction = theValue; -} - -int -ClientPlayer::getMyAction() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myAction; -} - -void -ClientPlayer::setMyButton(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myButton = theValue; -} - -int -ClientPlayer::getMyButton() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myButton; -} - -void -ClientPlayer::setMyActiveStatus(bool theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myActiveStatus = theValue; -} - -bool -ClientPlayer::getMyActiveStatus() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myActiveStatus; -} - -void -ClientPlayer::setMyCards(int* theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i = 0; i < 2; i++) - myCards[i] = theValue[i]; -} - -void -ClientPlayer::getMyCards(int* theValue) const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i = 0; i < 2; i++) - theValue[i] = myCards[i]; -} - -void -ClientPlayer::setMyTurn(bool theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myTurn = theValue; -} - -bool -ClientPlayer::getMyTurn() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myTurn; -} - -void -ClientPlayer::setMyCardsFlip(bool theValue, int state) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myCardsFlip = theValue; - // log flipping cards - if (myCardsFlip) { - switch(state) { - case 1: currentHand->getGuiInterface()->logFlipHoleCardsMsg(myName, myCards[0], myCards[1], myCardsValueInt); - break; - case 2: currentHand->getGuiInterface()->logFlipHoleCardsMsg(myName, myCards[0], myCards[1]); - break; - case 3: currentHand->getGuiInterface()->logFlipHoleCardsMsg(myName, myCards[0], myCards[1], myCardsValueInt, "has"); - break; - default: ; - } - } -} - -bool -ClientPlayer::getMyCardsFlip() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myCardsFlip; -} - -void -ClientPlayer::setMyCardsValueInt(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myCardsValueInt = theValue; -} - -int -ClientPlayer::getMyCardsValueInt() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myCardsValueInt; -} - -void -ClientPlayer::setMyBestHandPosition(int* theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i = 0; i < 5; i++) - myBestHandPosition[i] = theValue[i]; -} - -void -ClientPlayer::getMyBestHandPosition(int* theValue) const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i = 0; i < 5; i++) - theValue[i] = myBestHandPosition[i]; -} - -void -ClientPlayer::setMyRoundStartCash(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myRoundStartCash = theValue; -} - -int -ClientPlayer::getMyRoundStartCash() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myRoundStartCash; -} - -void -ClientPlayer::setLastMoneyWon ( int theValue ) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - lastMoneyWon = theValue; -} - -int -ClientPlayer::getLastMoneyWon() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return lastMoneyWon; -} - -void -ClientPlayer::setMyAverageSets(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myAverageSets[0] = myAverageSets[1]; - myAverageSets[1] = myAverageSets[2]; - myAverageSets[2] = myAverageSets[3]; - myAverageSets[3] = theValue; -} - -int -ClientPlayer::getMyAverageSets() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return (myAverageSets[0]+myAverageSets[1]+myAverageSets[2]+myAverageSets[3])/4; -} - -void -ClientPlayer::setMyAggressive(bool theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - for (int i=0; i<6; i++) - { - myAggressive[i] = myAggressive[i+1]; - } - myAggressive[6] = theValue; -} - -int -ClientPlayer::getMyAggressive() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - int sum = 0; - for (int i=0; i<7; i++) - { - sum += myAggressive[i]; - } - return sum; -} - -void -ClientPlayer::setSBluff(int theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - sBluff = theValue; -} - -int -ClientPlayer::getSBluff() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return sBluff; -} - -void -ClientPlayer::setSBluffStatus(bool theValue) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - sBluffStatus = theValue; -} - -bool -ClientPlayer::getSBluffStatus() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return sBluffStatus; -} - -void -ClientPlayer::setMyWinnerState(bool theValue, int pot) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - if(theValue) myWinnerState = theValue; - currentHand->getGuiInterface()->logPlayerWinsMsg(myName, pot, theValue); -} - -bool -ClientPlayer::getMyWinnerState() const -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myWinnerState; -} - -void -ClientPlayer::action() -{ -} - -int -ClientPlayer::checkMyAction(int /*targetAction*/, int /*targetBet*/, int /*highestSet*/, int /*minimumRaise*/, int /*smallBlind*/) -{ - return 0; -} - -void -ClientPlayer::preflopEngine() -{ -} - - -void -ClientPlayer::flopEngine() -{ -} - - -void -ClientPlayer::turnEngine() -{ -} - - -void -ClientPlayer::riverEngine() -{ -} - - -void -ClientPlayer::evaluation(int /*bet*/, int /*raise*/) -{ -} - - -int -ClientPlayer::preflopCardsValue(int* /*cards*/) -{ - return 0; -} - - -int -ClientPlayer::flopCardsValue(int* /*cards*/) -{ - return 0; -} - - -void -ClientPlayer::readFile() -{ -} - -int -ClientPlayer::turnCardsValue(int* /*cards*/) -{ - return 0; -} - -void -ClientPlayer::preflopEngine3() -{ -} - -void -ClientPlayer::flopEngine3() -{ -} - -void -ClientPlayer::turnEngine3() -{ -} - -void -ClientPlayer::riverEngine3() -{ -} - -void ClientPlayer::setNetSessionData(boost::shared_ptr session) -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - myNetSessionData = session; -} - -boost::shared_ptr ClientPlayer::getNetSessionData() -{ - boost::recursive_mutex::scoped_lock lock(m_syncMutex); - return myNetSessionData; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "clientplayer.h" +#include + +using namespace std; + + +ClientPlayer::ClientPlayer(ConfigFile *c, BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB) +: PlayerInterface(), myConfig(c), currentHand(0), currentBoard(b), myCardsValue(0), myID(id), myUniqueID(uniqueId), myType(type), myName(name), myAvatar(avatar), myDude(0), myDude4(0), myCardsValueInt(0), myOdds(-1.0), myCash(sC), mySet(0), myLastRelativeSet(0), myAction(0), myButton(mB), myActiveStatus(aS), myTurn(0), myRoundStartCash(0), sBluff(0), sBluffStatus(0) +{ +} + + +ClientPlayer::~ClientPlayer() +{ +} + + +void +ClientPlayer::setHand(HandInterface* br) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + currentHand = br; +} + +int +ClientPlayer::getMyID() const +{ + return myID; +} + +unsigned +ClientPlayer::getMyUniqueID() const +{ + return myUniqueID; +} + +PlayerType +ClientPlayer::getMyType() const +{ + return myType; +} + +void +ClientPlayer::setMyDude(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myDude = theValue; +} + +int +ClientPlayer::getMyDude() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myDude; +} + +void +ClientPlayer::setMyDude4(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myDude4 = theValue; +} + +int +ClientPlayer::getMyDude4() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myDude4; +} + +void +ClientPlayer::setMyName(const std::string& theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myName = theValue; +} + +std::string +ClientPlayer::getMyName() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myName; +} + +void +ClientPlayer::setMyAvatar(const std::string& theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myAvatar = theValue; +} + +std::string +ClientPlayer::getMyAvatar() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myAvatar; +} + +void +ClientPlayer::setMyCash(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myCash = theValue; +} + +int +ClientPlayer::getMyCash() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myCash; +} + +void +ClientPlayer::setMySet(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myLastRelativeSet = theValue; +} + +void +ClientPlayer::setMySetAbsolute(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + mySet = theValue; +} + +void +ClientPlayer::setMySetNull() +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + mySet = 0; + myLastRelativeSet = 0; +} + +int +ClientPlayer::getMySet() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return mySet; +} + +int +ClientPlayer::getMyLastRelativeSet() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myLastRelativeSet; +} + +void +ClientPlayer::setMyAction(int theValue, bool /*blind*/) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myAction = theValue; +} + +int +ClientPlayer::getMyAction() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myAction; +} + +void +ClientPlayer::setMyButton(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myButton = theValue; +} + +int +ClientPlayer::getMyButton() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myButton; +} + +void +ClientPlayer::setMyActiveStatus(bool theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myActiveStatus = theValue; +} + +bool +ClientPlayer::getMyActiveStatus() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myActiveStatus; +} + +void +ClientPlayer::setMyCards(int* theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i = 0; i < 2; i++) + myCards[i] = theValue[i]; +} + +void +ClientPlayer::getMyCards(int* theValue) const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i = 0; i < 2; i++) + theValue[i] = myCards[i]; +} + +void +ClientPlayer::setMyTurn(bool theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myTurn = theValue; +} + +bool +ClientPlayer::getMyTurn() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myTurn; +} + +void +ClientPlayer::setMyCardsFlip(bool theValue, int state) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myCardsFlip = theValue; + // log flipping cards + if (myCardsFlip) { + switch(state) { + case 1: currentHand->getGuiInterface()->logFlipHoleCardsMsg(myName, myCards[0], myCards[1], myCardsValueInt); + break; + case 2: currentHand->getGuiInterface()->logFlipHoleCardsMsg(myName, myCards[0], myCards[1]); + break; + case 3: currentHand->getGuiInterface()->logFlipHoleCardsMsg(myName, myCards[0], myCards[1], myCardsValueInt, "has"); + break; + default: ; + } + } +} + +bool +ClientPlayer::getMyCardsFlip() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myCardsFlip; +} + +void +ClientPlayer::setMyCardsValueInt(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myCardsValueInt = theValue; +} + +int +ClientPlayer::getMyCardsValueInt() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myCardsValueInt; +} + +void +ClientPlayer::setMyBestHandPosition(int* theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i = 0; i < 5; i++) + myBestHandPosition[i] = theValue[i]; +} + +void +ClientPlayer::getMyBestHandPosition(int* theValue) const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i = 0; i < 5; i++) + theValue[i] = myBestHandPosition[i]; +} + +void +ClientPlayer::setMyRoundStartCash(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myRoundStartCash = theValue; +} + +int +ClientPlayer::getMyRoundStartCash() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myRoundStartCash; +} + +void +ClientPlayer::setLastMoneyWon ( int theValue ) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + lastMoneyWon = theValue; +} + +int +ClientPlayer::getLastMoneyWon() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return lastMoneyWon; +} + +void +ClientPlayer::setMyAverageSets(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myAverageSets[0] = myAverageSets[1]; + myAverageSets[1] = myAverageSets[2]; + myAverageSets[2] = myAverageSets[3]; + myAverageSets[3] = theValue; +} + +int +ClientPlayer::getMyAverageSets() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return (myAverageSets[0]+myAverageSets[1]+myAverageSets[2]+myAverageSets[3])/4; +} + +void +ClientPlayer::setMyAggressive(bool theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + for (int i=0; i<6; i++) + { + myAggressive[i] = myAggressive[i+1]; + } + myAggressive[6] = theValue; +} + +int +ClientPlayer::getMyAggressive() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + int sum = 0; + for (int i=0; i<7; i++) + { + sum += myAggressive[i]; + } + return sum; +} + +void +ClientPlayer::setSBluff(int theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + sBluff = theValue; +} + +int +ClientPlayer::getSBluff() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return sBluff; +} + +void +ClientPlayer::setSBluffStatus(bool theValue) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + sBluffStatus = theValue; +} + +bool +ClientPlayer::getSBluffStatus() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return sBluffStatus; +} + +void +ClientPlayer::setMyWinnerState(bool theValue, int pot) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + if(theValue) myWinnerState = theValue; + currentHand->getGuiInterface()->logPlayerWinsMsg(myName, pot, theValue); +} + +bool +ClientPlayer::getMyWinnerState() const +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myWinnerState; +} + +void +ClientPlayer::action() +{ +} + +int +ClientPlayer::checkMyAction(int /*targetAction*/, int /*targetBet*/, int /*highestSet*/, int /*minimumRaise*/, int /*smallBlind*/) +{ + return 0; +} + +void +ClientPlayer::preflopEngine() +{ +} + + +void +ClientPlayer::flopEngine() +{ +} + + +void +ClientPlayer::turnEngine() +{ +} + + +void +ClientPlayer::riverEngine() +{ +} + + +void +ClientPlayer::evaluation(int /*bet*/, int /*raise*/) +{ +} + + +int +ClientPlayer::preflopCardsValue(int* /*cards*/) +{ + return 0; +} + + +int +ClientPlayer::flopCardsValue(int* /*cards*/) +{ + return 0; +} + + +void +ClientPlayer::readFile() +{ +} + +int +ClientPlayer::turnCardsValue(int* /*cards*/) +{ + return 0; +} + +void +ClientPlayer::preflopEngine3() +{ +} + +void +ClientPlayer::flopEngine3() +{ +} + +void +ClientPlayer::turnEngine3() +{ +} + +void +ClientPlayer::riverEngine3() +{ +} + +void ClientPlayer::setNetSessionData(boost::shared_ptr session) +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + myNetSessionData = session; +} + +boost::shared_ptr ClientPlayer::getNetSessionData() +{ + boost::recursive_mutex::scoped_lock lock(m_syncMutex); + return myNetSessionData; +} + diff --git a/src/engine/network_engine/clientplayer.h b/src/engine/network_engine/clientplayer.h index be2866db..de8b2e67 100644 --- a/src/engine/network_engine/clientplayer.h +++ b/src/engine/network_engine/clientplayer.h @@ -1,182 +1,182 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CLIENTPLAYER_H -#define CLIENTPLAYER_H - -#include - -#include -#include -#include - -class CardsValue; -class ConfigFile; -class HandInterface; -class BoardInterface; - -class ClientPlayer : public PlayerInterface{ -public: - ClientPlayer(ConfigFile*, BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB); - ~ClientPlayer(); - - void setHand(HandInterface*); - - int getMyID() const; - unsigned getMyUniqueID() const; - PlayerType getMyType() const; - - void setMyDude(int theValue); - int getMyDude() const; - - void setMyDude4(int theValue); - int getMyDude4() const; - - void setMyName(const std::string& theValue); - std::string getMyName() const; - - void setMyAvatar(const std::string& theValue); - std::string getMyAvatar() const; - - void setMyCash(int theValue); - int getMyCash() const; - - void setMySet(int theValue); - void setMySetAbsolute(int theValue); - void setMySetNull(); - int getMySet() const; - int getMyLastRelativeSet() const; - - void setMyAction(int theValue, bool blind); - int getMyAction() const; - - void setMyButton(int theValue); - int getMyButton() const; - - void setMyActiveStatus(bool theValue); - bool getMyActiveStatus() const; - - void setMyCards(int* theValue); - void getMyCards(int* theValue) const; - - void setMyTurn(bool theValue); - bool getMyTurn() const; - - void setMyCardsFlip(bool theValue, int state); - bool getMyCardsFlip() const; - - void setMyCardsValueInt(int theValue); - int getMyCardsValueInt() const; - - void setMyBestHandPosition(int* theValue); - void getMyBestHandPosition(int* theValue) const; - - void setMyRoundStartCash(int theValue); - int getMyRoundStartCash() const; - - void setLastMoneyWon ( int theValue ); - int getLastMoneyWon() const; - - void setMyAverageSets(int theValue); - int getMyAverageSets() const; - - void setMyAggressive(bool theValue); - int getMyAggressive() const; - - void setSBluff (int theValue); - int getSBluff() const; - - void setSBluffStatus (bool theValue); - bool getSBluffStatus() const; - - void setMyWinnerState (bool theValue, int pot); - bool getMyWinnerState() const; - - void action(); - int checkMyAction(int targetAction, int targetBet, int highestSet, int minimumRaise, int smallBlind); - - void preflopEngine(); - void flopEngine(); - void turnEngine(); - void riverEngine(); - - void preflopEngine3(); - void flopEngine3(); - void turnEngine3(); - void riverEngine3(); - - int preflopCardsValue(int*); - int flopCardsValue(int*); - int turnCardsValue(int*); - - void readFile(); - - void evaluation(int, int); - - void setNetSessionData(boost::shared_ptr session); - boost::shared_ptr getNetSessionData(); - -private: - mutable boost::recursive_mutex m_syncMutex; - - ConfigFile *myConfig; - HandInterface *currentHand; - BoardInterface *currentBoard; - - CardsValue *myCardsValue; - - // Konstanten - const int myID; - const unsigned myUniqueID; - const PlayerType myType; - std::string myName; - std::string myAvatar; - int myDude; - int myDude4; - - - // Laufvariablen - int myCardsValueInt; - int myBestHandPosition[5]; - double myOdds; - int myNiveau[3]; - - int myCards[2]; - int myCash; - int mySet; - int myLastRelativeSet; - int myAction; // 0 = none, 1 = fold, 2 = check, 3 = call, 4 = bet, 5 = raise, 6 = allin - int myButton; // 0 = none, 1 = dealer, 2 =small, 3 = big - bool myActiveStatus; // 0 = inactive, 1 = active - bool myTurn; // 0 = no, 1 = yes - bool myCardsFlip; // 0 = cards are not fliped, 1 = cards are already flipped, - int myRoundStartCash; - int lastMoneyWon; - - int myAverageSets[4]; - bool myAggressive[7]; - - int sBluff; - bool sBluffStatus; - - bool myWinnerState; - - boost::shared_ptr myNetSessionData; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef CLIENTPLAYER_H +#define CLIENTPLAYER_H + +#include + +#include +#include +#include + +class CardsValue; +class ConfigFile; +class HandInterface; +class BoardInterface; + +class ClientPlayer : public PlayerInterface{ +public: + ClientPlayer(ConfigFile*, BoardInterface *b, int id, unsigned uniqueId, PlayerType type, std::string name, std::string avatar, int sC, bool aS, int mB); + ~ClientPlayer(); + + void setHand(HandInterface*); + + int getMyID() const; + unsigned getMyUniqueID() const; + PlayerType getMyType() const; + + void setMyDude(int theValue); + int getMyDude() const; + + void setMyDude4(int theValue); + int getMyDude4() const; + + void setMyName(const std::string& theValue); + std::string getMyName() const; + + void setMyAvatar(const std::string& theValue); + std::string getMyAvatar() const; + + void setMyCash(int theValue); + int getMyCash() const; + + void setMySet(int theValue); + void setMySetAbsolute(int theValue); + void setMySetNull(); + int getMySet() const; + int getMyLastRelativeSet() const; + + void setMyAction(int theValue, bool blind); + int getMyAction() const; + + void setMyButton(int theValue); + int getMyButton() const; + + void setMyActiveStatus(bool theValue); + bool getMyActiveStatus() const; + + void setMyCards(int* theValue); + void getMyCards(int* theValue) const; + + void setMyTurn(bool theValue); + bool getMyTurn() const; + + void setMyCardsFlip(bool theValue, int state); + bool getMyCardsFlip() const; + + void setMyCardsValueInt(int theValue); + int getMyCardsValueInt() const; + + void setMyBestHandPosition(int* theValue); + void getMyBestHandPosition(int* theValue) const; + + void setMyRoundStartCash(int theValue); + int getMyRoundStartCash() const; + + void setLastMoneyWon ( int theValue ); + int getLastMoneyWon() const; + + void setMyAverageSets(int theValue); + int getMyAverageSets() const; + + void setMyAggressive(bool theValue); + int getMyAggressive() const; + + void setSBluff (int theValue); + int getSBluff() const; + + void setSBluffStatus (bool theValue); + bool getSBluffStatus() const; + + void setMyWinnerState (bool theValue, int pot); + bool getMyWinnerState() const; + + void action(); + int checkMyAction(int targetAction, int targetBet, int highestSet, int minimumRaise, int smallBlind); + + void preflopEngine(); + void flopEngine(); + void turnEngine(); + void riverEngine(); + + void preflopEngine3(); + void flopEngine3(); + void turnEngine3(); + void riverEngine3(); + + int preflopCardsValue(int*); + int flopCardsValue(int*); + int turnCardsValue(int*); + + void readFile(); + + void evaluation(int, int); + + void setNetSessionData(boost::shared_ptr session); + boost::shared_ptr getNetSessionData(); + +private: + mutable boost::recursive_mutex m_syncMutex; + + ConfigFile *myConfig; + HandInterface *currentHand; + BoardInterface *currentBoard; + + CardsValue *myCardsValue; + + // Konstanten + const int myID; + const unsigned myUniqueID; + const PlayerType myType; + std::string myName; + std::string myAvatar; + int myDude; + int myDude4; + + + // Laufvariablen + int myCardsValueInt; + int myBestHandPosition[5]; + double myOdds; + int myNiveau[3]; + + int myCards[2]; + int myCash; + int mySet; + int myLastRelativeSet; + int myAction; // 0 = none, 1 = fold, 2 = check, 3 = call, 4 = bet, 5 = raise, 6 = allin + int myButton; // 0 = none, 1 = dealer, 2 =small, 3 = big + bool myActiveStatus; // 0 = inactive, 1 = active + bool myTurn; // 0 = no, 1 = yes + bool myCardsFlip; // 0 = cards are not fliped, 1 = cards are already flipped, + int myRoundStartCash; + int lastMoneyWon; + + int myAverageSets[4]; + bool myAggressive[7]; + + int sBluff; + bool sBluffStatus; + + bool myWinnerState; + + boost::shared_ptr myNetSessionData; +}; + +#endif diff --git a/src/game_defs.h b/src/game_defs.h index e8a8428a..274c252a 100644 --- a/src/game_defs.h +++ b/src/game_defs.h @@ -1,82 +1,82 @@ -/*************************************************************************** - * Copyright (C) 2006 by FThauer FHammer * - * f.thauer@web.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAME_DEFS_H -#define GAME_DEFS_H - -#define MIN_NUMBER_OF_PLAYERS 2 -#define MAX_NUMBER_OF_PLAYERS 7 - -#define MIN_GUI_SPEED 1 -#define MAX_GUI_SPEED 11 - -#define DEBUG_MODE 0 - -#define POKERTH_VERSION_MAJOR 0 -#define POKERTH_VERSION_MINOR 6 -#define POKERTH_VERSION ((POKERTH_VERSION_MAJOR << 8) | POKERTH_VERSION_MINOR) - -#define POKERTH_BETA_REVISION 5 - -enum GameState { - GAME_STATE_PREFLOP = 0, - GAME_STATE_FLOP, - GAME_STATE_TURN, - GAME_STATE_RIVER, - GAME_STATE_POST_RIVER, - GAME_STATE_PREFLOP_SMALL_BLIND = 0xF0, - GAME_STATE_PREFLOP_BIG_BLIND = 0xF1 }; - -enum PlayerAction { - PLAYER_ACTION_NONE = 0, - PLAYER_ACTION_FOLD, - PLAYER_ACTION_CHECK, - PLAYER_ACTION_CALL, - PLAYER_ACTION_BET, - PLAYER_ACTION_RAISE, - PLAYER_ACTION_ALLIN }; - -enum PlayerActionCode -{ - ACTION_CODE_VALID = 0, - ACTION_CODE_INVALID_STATE, - ACTION_CODE_NOT_YOUR_TURN, - ACTION_CODE_NOT_ALLOWED -}; - - -enum Button { - BUTTON_NONE = 0, - BUTTON_DEALER, - BUTTON_SMALL_BLIND, - BUTTON_BIG_BLIND }; - -struct ServerStats -{ - ServerStats() - : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverCreated(0), - maxGamesOpen(0), maxPlayersLoggedIn(0) {} - unsigned numberOfPlayersOnServer; - unsigned totalPlayersEverLoggedIn; - unsigned totalGamesEverCreated; - unsigned maxGamesOpen; - unsigned maxPlayersLoggedIn; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2006 by FThauer FHammer * + * f.thauer@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef GAME_DEFS_H +#define GAME_DEFS_H + +#define MIN_NUMBER_OF_PLAYERS 2 +#define MAX_NUMBER_OF_PLAYERS 7 + +#define MIN_GUI_SPEED 1 +#define MAX_GUI_SPEED 11 + +#define DEBUG_MODE 0 + +#define POKERTH_VERSION_MAJOR 0 +#define POKERTH_VERSION_MINOR 6 +#define POKERTH_VERSION ((POKERTH_VERSION_MAJOR << 8) | POKERTH_VERSION_MINOR) + +#define POKERTH_BETA_REVISION 5 + +enum GameState { + GAME_STATE_PREFLOP = 0, + GAME_STATE_FLOP, + GAME_STATE_TURN, + GAME_STATE_RIVER, + GAME_STATE_POST_RIVER, + GAME_STATE_PREFLOP_SMALL_BLIND = 0xF0, + GAME_STATE_PREFLOP_BIG_BLIND = 0xF1 }; + +enum PlayerAction { + PLAYER_ACTION_NONE = 0, + PLAYER_ACTION_FOLD, + PLAYER_ACTION_CHECK, + PLAYER_ACTION_CALL, + PLAYER_ACTION_BET, + PLAYER_ACTION_RAISE, + PLAYER_ACTION_ALLIN }; + +enum PlayerActionCode +{ + ACTION_CODE_VALID = 0, + ACTION_CODE_INVALID_STATE, + ACTION_CODE_NOT_YOUR_TURN, + ACTION_CODE_NOT_ALLOWED +}; + + +enum Button { + BUTTON_NONE = 0, + BUTTON_DEALER, + BUTTON_SMALL_BLIND, + BUTTON_BIG_BLIND }; + +struct ServerStats +{ + ServerStats() + : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverCreated(0), + maxGamesOpen(0), maxPlayersLoggedIn(0) {} + unsigned numberOfPlayersOnServer; + unsigned totalPlayersEverLoggedIn; + unsigned totalGamesEverCreated; + unsigned maxGamesOpen; + unsigned maxPlayersLoggedIn; +}; + +#endif diff --git a/src/gamedata.h b/src/gamedata.h index 23135be4..c0181255 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -1,91 +1,91 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Game data. */ - -#ifndef _GAMEDATA_H_ -#define _GAMEDATA_H_ - -#include - -#define SERVER_COMPUTER_PLAYER_NAME "Computer" - -enum GameMode -{ - GAME_MODE_CREATED = 1, - GAME_MODE_STARTED, - GAME_MODE_CLOSED -}; - -enum RaiseIntervalMode -{ - RAISE_ON_HANDNUMBER = 1, - RAISE_ON_MINUTES -}; - -enum RaiseMode -{ - DOUBLE_BLINDS = 1, - MANUAL_BLINDS_ORDER -}; - -enum AfterManualBlindsMode -{ - AFTERMB_DOUBLE_BLINDS = 1, - AFTERMB_RAISE_ABOUT, - AFTERMB_STAY_AT_LAST_BLIND -}; - -// For the sake of simplicity, this is a struct. -struct GameData -{ - GameData() : maxNumberOfPlayers(0), startMoney(0), firstSmallBlind(0), raiseIntervalMode(RAISE_ON_HANDNUMBER), raiseSmallBlindEveryHandsValue(8), raiseSmallBlindEveryMinutesValue(1), raiseMode(DOUBLE_BLINDS), afterManualBlindsMode(AFTERMB_DOUBLE_BLINDS), afterMBAlwaysRaiseValue(0), guiSpeed(4), playerActionTimeoutSec(20) {} - int maxNumberOfPlayers; - int startMoney; - int firstSmallBlind; - RaiseIntervalMode raiseIntervalMode; - int raiseSmallBlindEveryHandsValue; - int raiseSmallBlindEveryMinutesValue; - RaiseMode raiseMode; - std::list manualBlindsList; - AfterManualBlindsMode afterManualBlindsMode; - int afterMBAlwaysRaiseValue; - int guiSpeed; - int playerActionTimeoutSec; -}; - -struct GameInfo -{ - GameInfo() : mode(GAME_MODE_CREATED), adminPlayerId(0), isPasswordProtected(false) {} - std::string name; - GameData data; - GameMode mode; - unsigned adminPlayerId; - PlayerIdList players; - bool isPasswordProtected; -}; - -struct StartData -{ - StartData() : startDealerPlayerId(0), numberOfPlayers(0) {} - unsigned startDealerPlayerId; - int numberOfPlayers; -}; - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Game data. */ + +#ifndef _GAMEDATA_H_ +#define _GAMEDATA_H_ + +#include + +#define SERVER_COMPUTER_PLAYER_NAME "Computer" + +enum GameMode +{ + GAME_MODE_CREATED = 1, + GAME_MODE_STARTED, + GAME_MODE_CLOSED +}; + +enum RaiseIntervalMode +{ + RAISE_ON_HANDNUMBER = 1, + RAISE_ON_MINUTES +}; + +enum RaiseMode +{ + DOUBLE_BLINDS = 1, + MANUAL_BLINDS_ORDER +}; + +enum AfterManualBlindsMode +{ + AFTERMB_DOUBLE_BLINDS = 1, + AFTERMB_RAISE_ABOUT, + AFTERMB_STAY_AT_LAST_BLIND +}; + +// For the sake of simplicity, this is a struct. +struct GameData +{ + GameData() : maxNumberOfPlayers(0), startMoney(0), firstSmallBlind(0), raiseIntervalMode(RAISE_ON_HANDNUMBER), raiseSmallBlindEveryHandsValue(8), raiseSmallBlindEveryMinutesValue(1), raiseMode(DOUBLE_BLINDS), afterManualBlindsMode(AFTERMB_DOUBLE_BLINDS), afterMBAlwaysRaiseValue(0), guiSpeed(4), playerActionTimeoutSec(20) {} + int maxNumberOfPlayers; + int startMoney; + int firstSmallBlind; + RaiseIntervalMode raiseIntervalMode; + int raiseSmallBlindEveryHandsValue; + int raiseSmallBlindEveryMinutesValue; + RaiseMode raiseMode; + std::list manualBlindsList; + AfterManualBlindsMode afterManualBlindsMode; + int afterMBAlwaysRaiseValue; + int guiSpeed; + int playerActionTimeoutSec; +}; + +struct GameInfo +{ + GameInfo() : mode(GAME_MODE_CREATED), adminPlayerId(0), isPasswordProtected(false) {} + std::string name; + GameData data; + GameMode mode; + unsigned adminPlayerId; + PlayerIdList players; + bool isPasswordProtected; +}; + +struct StartData +{ + StartData() : startDealerPlayerId(0), numberOfPlayers(0) {} + unsigned startDealerPlayerId; + int numberOfPlayers; +}; + +#endif + diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 8d784707..29a99ae5 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -1,148 +1,148 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "serverguiwrapper.h" -#include - - -using namespace std; - - -ServerGuiWrapper::ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb, IrcCallback *irccb) -: myConfig(config), myClientcb(clientcb), myServercb(servercb), myIrccb(irccb) -{ -} - -ServerGuiWrapper::~ServerGuiWrapper() -{ -} - -void ServerGuiWrapper::initGui(int /*speed*/) {} - -Session &ServerGuiWrapper::getSession() -{ - assert(mySession.get()); - return *mySession; -} - -void ServerGuiWrapper::setSession(boost::shared_ptr session) -{ - mySession = session; -} - -void ServerGuiWrapper::refreshSet() const {} - -void ServerGuiWrapper::refreshCash() const {} - -void ServerGuiWrapper::refreshAction(int /*playerID*/, int /*playerAction*/) const {} - -void ServerGuiWrapper::refreshChangePlayer() const {} - -void ServerGuiWrapper::refreshAll() const {} - -void ServerGuiWrapper::refreshPot() const {} -void ServerGuiWrapper::refreshGroupbox(int /*playerID*/, int /*status*/) const {} -void ServerGuiWrapper::refreshPlayerName() const {} -void ServerGuiWrapper::refreshButton() const {} -void ServerGuiWrapper::refreshGameLabels(GameState /*state*/) const {} - -void ServerGuiWrapper::setPlayerAvatar(int /*myUniqueID*/, const std::string &/*myAvatar*/) const {}; - -void ServerGuiWrapper::waitForGuiUpdateDone() const {} - -void ServerGuiWrapper::dealBeRoCards(int /*myBeRoID*/) {} -void ServerGuiWrapper::dealHoleCards() {} -void ServerGuiWrapper::dealFlopCards() {} -void ServerGuiWrapper::dealTurnCard() {} -void ServerGuiWrapper::dealRiverCard() {} - -void ServerGuiWrapper::nextPlayerAnimation() {} - -void ServerGuiWrapper::beRoAnimation2(int /*myBeRoID*/) {} - -void ServerGuiWrapper::preflopAnimation1() {} -void ServerGuiWrapper::preflopAnimation2() {} - -void ServerGuiWrapper::flopAnimation1() {} -void ServerGuiWrapper::flopAnimation2() {} - -void ServerGuiWrapper::turnAnimation1() {} -void ServerGuiWrapper::turnAnimation2() {} - -void ServerGuiWrapper::riverAnimation1() {} -void ServerGuiWrapper::riverAnimation2() {} - -void ServerGuiWrapper::postRiverAnimation1() {} -void ServerGuiWrapper::postRiverRunAnimation1() {} - -void ServerGuiWrapper::flipHolecardsAllIn() {} - -void ServerGuiWrapper::nextRoundCleanGui() {} - -void ServerGuiWrapper::meInAction() {} -void ServerGuiWrapper::disableMyButtons() {} -void ServerGuiWrapper::updateMyButtonsState() {} -void ServerGuiWrapper::startTimeoutAnimation(int /*playerId*/, int /*timeoutSec*/) {} -void ServerGuiWrapper::stopTimeoutAnimation(int /*playerId*/) {} - -void ServerGuiWrapper::logPlayerActionMsg(string /*playerName*/, int /*action*/, int /*setValue*/) {} -void ServerGuiWrapper::logNewGameHandMsg(int /*gameID*/, int /*handID*/) {} -void ServerGuiWrapper::logPlayerWinsMsg(std::string /*playerName*/, int /*pot*/, bool /*main*/) {} -void ServerGuiWrapper::logPlayerSitsOut(std::string /*playerName*/) {} -void ServerGuiWrapper::logNewBlindsSetsMsg(int /*sbSet*/, int /*bbSet*/, std::string /*sbName*/, std::string /*bbName*/) {} - -void ServerGuiWrapper::logDealBoardCardsMsg(int /*roundID*/, int /*card1*/, int /*card2*/, int /*card3*/, int /*card4*/, int /*card5*/) {} -void ServerGuiWrapper::logFlipHoleCardsMsg(std::string /*playerName*/, int /*card1*/, int /*card2*/, int /*cardsValueInt*/, std::string /*showHas*/) {} -void ServerGuiWrapper::logPlayerWinGame(std::string /*playerName*/, int /*gameID*/) {} -void ServerGuiWrapper::flushLogAtGame(int /*gameID*/) {} -void ServerGuiWrapper::flushLogAtHand() {} - -void ServerGuiWrapper::SignalNetClientConnect(int actionID) { if (myClientcb) myClientcb->SignalNetClientConnect(actionID); } -void ServerGuiWrapper::SignalNetClientGameInfo(int actionID) { if (myClientcb) myClientcb->SignalNetClientGameInfo(actionID); } -void ServerGuiWrapper::SignalNetClientError(int errorID, int osErrorID) { if (myClientcb) myClientcb->SignalNetClientError(errorID, osErrorID); } -void ServerGuiWrapper::SignalNetClientNotification(int notificationId) { if (myClientcb) myClientcb->SignalNetClientNotification(notificationId); } -void ServerGuiWrapper::SignalNetClientStatsUpdate(const ServerStats &stats) { if (myClientcb) myClientcb->SignalNetClientStatsUpdate(stats); } -void ServerGuiWrapper::SignalNetClientRemovedFromGame(int notificationId) { if (myClientcb) myClientcb->SignalNetClientRemovedFromGame(notificationId); } -void ServerGuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientSelfJoined(playerId, playerName, rights); } -void ServerGuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerId, playerName, rights); } -void ServerGuiWrapper::SignalNetClientPlayerChanged(unsigned playerId, const string &newPlayerName) { if (myClientcb) myClientcb->SignalNetClientPlayerChanged(playerId, newPlayerName); } -void ServerGuiWrapper::SignalNetClientPlayerLeft(unsigned playerId, const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerLeft(playerId, playerName); } -void ServerGuiWrapper::SignalNetClientNewGameAdmin(unsigned playerId, const string &playerName) { if (myClientcb) myClientcb->SignalNetClientNewGameAdmin(playerId, playerName); } -void ServerGuiWrapper::SignalNetClientGameListNew(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListNew(gameId); } -void ServerGuiWrapper::SignalNetClientGameListRemove(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListRemove(gameId); } -void ServerGuiWrapper::SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateMode(gameId, mode); } -void ServerGuiWrapper::SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateAdmin(gameId, adminPlayerId); } -void ServerGuiWrapper::SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) { if (myClientcb) myClientcb->SignalNetClientGameListPlayerJoined(gameId, playerId); } -void ServerGuiWrapper::SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) { if (myClientcb) myClientcb->SignalNetClientGameListPlayerLeft(gameId, playerId); } -void ServerGuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { if (myClientcb) myClientcb->SignalNetClientGameStart(game); } -void ServerGuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { if (myClientcb) myClientcb->SignalNetClientChatMsg(playerName, msg); } -void ServerGuiWrapper::SignalNetClientWaitDialog() { if (myClientcb) myClientcb->SignalNetClientWaitDialog(); } - -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::SignalIrcConnect(const string &server) { if (myIrccb) myIrccb->SignalIrcConnect(server); } -void ServerGuiWrapper::SignalIrcSelfJoined(const string &nickName, const std::string &channel) { if (myIrccb) myIrccb->SignalIrcSelfJoined(nickName, channel); } -void ServerGuiWrapper::SignalIrcPlayerJoined(const string &nickName) { if (myIrccb) myIrccb->SignalIrcPlayerJoined(nickName); } -void ServerGuiWrapper::SignalIrcPlayerChanged(const string &oldNick, const string &newNick) { if (myIrccb) myIrccb->SignalIrcPlayerChanged(oldNick, newNick); } -void ServerGuiWrapper::SignalIrcPlayerKicked(const string &nickName, const string &byWhom, const string &reason) { if (myIrccb) myIrccb->SignalIrcPlayerKicked(nickName, byWhom, reason); } -void ServerGuiWrapper::SignalIrcPlayerLeft(const string &nickName) { if (myIrccb) myIrccb->SignalIrcPlayerLeft(nickName); } -void ServerGuiWrapper::SignalIrcChatMsg(const string &nickName, const string &msg) { if (myIrccb) myIrccb->SignalIrcChatMsg(nickName, msg); } -void ServerGuiWrapper::SignalIrcError(int errorCode) { if (myIrccb) myIrccb->SignalIrcError(errorCode); } -void ServerGuiWrapper::SignalIrcServerError(int errorCode) {if (myIrccb) myIrccb->SignalIrcServerError(errorCode); } +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "serverguiwrapper.h" +#include + + +using namespace std; + + +ServerGuiWrapper::ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb, IrcCallback *irccb) +: myConfig(config), myClientcb(clientcb), myServercb(servercb), myIrccb(irccb) +{ +} + +ServerGuiWrapper::~ServerGuiWrapper() +{ +} + +void ServerGuiWrapper::initGui(int /*speed*/) {} + +Session &ServerGuiWrapper::getSession() +{ + assert(mySession.get()); + return *mySession; +} + +void ServerGuiWrapper::setSession(boost::shared_ptr session) +{ + mySession = session; +} + +void ServerGuiWrapper::refreshSet() const {} + +void ServerGuiWrapper::refreshCash() const {} + +void ServerGuiWrapper::refreshAction(int /*playerID*/, int /*playerAction*/) const {} + +void ServerGuiWrapper::refreshChangePlayer() const {} + +void ServerGuiWrapper::refreshAll() const {} + +void ServerGuiWrapper::refreshPot() const {} +void ServerGuiWrapper::refreshGroupbox(int /*playerID*/, int /*status*/) const {} +void ServerGuiWrapper::refreshPlayerName() const {} +void ServerGuiWrapper::refreshButton() const {} +void ServerGuiWrapper::refreshGameLabels(GameState /*state*/) const {} + +void ServerGuiWrapper::setPlayerAvatar(int /*myUniqueID*/, const std::string &/*myAvatar*/) const {}; + +void ServerGuiWrapper::waitForGuiUpdateDone() const {} + +void ServerGuiWrapper::dealBeRoCards(int /*myBeRoID*/) {} +void ServerGuiWrapper::dealHoleCards() {} +void ServerGuiWrapper::dealFlopCards() {} +void ServerGuiWrapper::dealTurnCard() {} +void ServerGuiWrapper::dealRiverCard() {} + +void ServerGuiWrapper::nextPlayerAnimation() {} + +void ServerGuiWrapper::beRoAnimation2(int /*myBeRoID*/) {} + +void ServerGuiWrapper::preflopAnimation1() {} +void ServerGuiWrapper::preflopAnimation2() {} + +void ServerGuiWrapper::flopAnimation1() {} +void ServerGuiWrapper::flopAnimation2() {} + +void ServerGuiWrapper::turnAnimation1() {} +void ServerGuiWrapper::turnAnimation2() {} + +void ServerGuiWrapper::riverAnimation1() {} +void ServerGuiWrapper::riverAnimation2() {} + +void ServerGuiWrapper::postRiverAnimation1() {} +void ServerGuiWrapper::postRiverRunAnimation1() {} + +void ServerGuiWrapper::flipHolecardsAllIn() {} + +void ServerGuiWrapper::nextRoundCleanGui() {} + +void ServerGuiWrapper::meInAction() {} +void ServerGuiWrapper::disableMyButtons() {} +void ServerGuiWrapper::updateMyButtonsState() {} +void ServerGuiWrapper::startTimeoutAnimation(int /*playerId*/, int /*timeoutSec*/) {} +void ServerGuiWrapper::stopTimeoutAnimation(int /*playerId*/) {} + +void ServerGuiWrapper::logPlayerActionMsg(string /*playerName*/, int /*action*/, int /*setValue*/) {} +void ServerGuiWrapper::logNewGameHandMsg(int /*gameID*/, int /*handID*/) {} +void ServerGuiWrapper::logPlayerWinsMsg(std::string /*playerName*/, int /*pot*/, bool /*main*/) {} +void ServerGuiWrapper::logPlayerSitsOut(std::string /*playerName*/) {} +void ServerGuiWrapper::logNewBlindsSetsMsg(int /*sbSet*/, int /*bbSet*/, std::string /*sbName*/, std::string /*bbName*/) {} + +void ServerGuiWrapper::logDealBoardCardsMsg(int /*roundID*/, int /*card1*/, int /*card2*/, int /*card3*/, int /*card4*/, int /*card5*/) {} +void ServerGuiWrapper::logFlipHoleCardsMsg(std::string /*playerName*/, int /*card1*/, int /*card2*/, int /*cardsValueInt*/, std::string /*showHas*/) {} +void ServerGuiWrapper::logPlayerWinGame(std::string /*playerName*/, int /*gameID*/) {} +void ServerGuiWrapper::flushLogAtGame(int /*gameID*/) {} +void ServerGuiWrapper::flushLogAtHand() {} + +void ServerGuiWrapper::SignalNetClientConnect(int actionID) { if (myClientcb) myClientcb->SignalNetClientConnect(actionID); } +void ServerGuiWrapper::SignalNetClientGameInfo(int actionID) { if (myClientcb) myClientcb->SignalNetClientGameInfo(actionID); } +void ServerGuiWrapper::SignalNetClientError(int errorID, int osErrorID) { if (myClientcb) myClientcb->SignalNetClientError(errorID, osErrorID); } +void ServerGuiWrapper::SignalNetClientNotification(int notificationId) { if (myClientcb) myClientcb->SignalNetClientNotification(notificationId); } +void ServerGuiWrapper::SignalNetClientStatsUpdate(const ServerStats &stats) { if (myClientcb) myClientcb->SignalNetClientStatsUpdate(stats); } +void ServerGuiWrapper::SignalNetClientRemovedFromGame(int notificationId) { if (myClientcb) myClientcb->SignalNetClientRemovedFromGame(notificationId); } +void ServerGuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientSelfJoined(playerId, playerName, rights); } +void ServerGuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerId, playerName, rights); } +void ServerGuiWrapper::SignalNetClientPlayerChanged(unsigned playerId, const string &newPlayerName) { if (myClientcb) myClientcb->SignalNetClientPlayerChanged(playerId, newPlayerName); } +void ServerGuiWrapper::SignalNetClientPlayerLeft(unsigned playerId, const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerLeft(playerId, playerName); } +void ServerGuiWrapper::SignalNetClientNewGameAdmin(unsigned playerId, const string &playerName) { if (myClientcb) myClientcb->SignalNetClientNewGameAdmin(playerId, playerName); } +void ServerGuiWrapper::SignalNetClientGameListNew(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListNew(gameId); } +void ServerGuiWrapper::SignalNetClientGameListRemove(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListRemove(gameId); } +void ServerGuiWrapper::SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateMode(gameId, mode); } +void ServerGuiWrapper::SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateAdmin(gameId, adminPlayerId); } +void ServerGuiWrapper::SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) { if (myClientcb) myClientcb->SignalNetClientGameListPlayerJoined(gameId, playerId); } +void ServerGuiWrapper::SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) { if (myClientcb) myClientcb->SignalNetClientGameListPlayerLeft(gameId, playerId); } +void ServerGuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { if (myClientcb) myClientcb->SignalNetClientGameStart(game); } +void ServerGuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { if (myClientcb) myClientcb->SignalNetClientChatMsg(playerName, msg); } +void ServerGuiWrapper::SignalNetClientWaitDialog() { if (myClientcb) myClientcb->SignalNetClientWaitDialog(); } + +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::SignalIrcConnect(const string &server) { if (myIrccb) myIrccb->SignalIrcConnect(server); } +void ServerGuiWrapper::SignalIrcSelfJoined(const string &nickName, const std::string &channel) { if (myIrccb) myIrccb->SignalIrcSelfJoined(nickName, channel); } +void ServerGuiWrapper::SignalIrcPlayerJoined(const string &nickName) { if (myIrccb) myIrccb->SignalIrcPlayerJoined(nickName); } +void ServerGuiWrapper::SignalIrcPlayerChanged(const string &oldNick, const string &newNick) { if (myIrccb) myIrccb->SignalIrcPlayerChanged(oldNick, newNick); } +void ServerGuiWrapper::SignalIrcPlayerKicked(const string &nickName, const string &byWhom, const string &reason) { if (myIrccb) myIrccb->SignalIrcPlayerKicked(nickName, byWhom, reason); } +void ServerGuiWrapper::SignalIrcPlayerLeft(const string &nickName) { if (myIrccb) myIrccb->SignalIrcPlayerLeft(nickName); } +void ServerGuiWrapper::SignalIrcChatMsg(const string &nickName, const string &msg) { if (myIrccb) myIrccb->SignalIrcChatMsg(nickName, msg); } +void ServerGuiWrapper::SignalIrcError(int errorCode) { if (myIrccb) myIrccb->SignalIrcError(errorCode); } +void ServerGuiWrapper::SignalIrcServerError(int errorCode) {if (myIrccb) myIrccb->SignalIrcServerError(errorCode); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index 8e2ac7bf..347b5ceb 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -1,144 +1,144 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SERVERGUIWRAPPER_H -#define SERVERGUIWRAPPER_H - -#include - -class ConfigFile; -class Session; - -class ServerGuiWrapper : public GuiInterface -{ -public: - ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb, IrcCallback *irccb); - ~ServerGuiWrapper(); - - void initGui(int speed); - - Session &getSession(); - void setSession(boost::shared_ptr session); - - void refreshSet() const; - void refreshCash() const; - void refreshAction(int =-1, int =-1) const; - void refreshChangePlayer() const; - void refreshPot() const; - void refreshGroupbox(int =-1, int =-1) const; - void refreshAll() const; - void refreshPlayerName() const; - void refreshButton() const; - void refreshGameLabels(GameState state) const; - - void setPlayerAvatar(int myUniqueID, const std::string &myAvatar) const; - - void waitForGuiUpdateDone() const; - - void dealBeRoCards(int); - void dealHoleCards(); - void dealFlopCards(); - void dealTurnCard(); - void dealRiverCard(); - - void nextPlayerAnimation(); - - void beRoAnimation2(int); - - void preflopAnimation1(); - void preflopAnimation2(); - - void flopAnimation1(); - void flopAnimation2(); - - void turnAnimation1(); - void turnAnimation2(); - - void riverAnimation1(); - void riverAnimation2(); - - void postRiverAnimation1(); - void postRiverRunAnimation1(); - - void flipHolecardsAllIn(); - - void nextRoundCleanGui(); - - void meInAction(); - void updateMyButtonsState(); - void disableMyButtons(); - void startTimeoutAnimation(int playerId, int timeoutSec); - void stopTimeoutAnimation(int playerId); - - void logPlayerActionMsg(std::string playerName, int action, int setValue) ; - void logNewGameHandMsg(int gameID, int handID) ; - void logPlayerWinsMsg(std::string playerName, int pot, bool main); - void logPlayerSitsOut(std::string playerName); - void logNewBlindsSetsMsg(int sbSet, int bbSet, std::string sbName, std::string bbName); - void logDealBoardCardsMsg(int roundID, int card1, int card2, int card3, int card4 = -1, int card5 = -1) ; - void logFlipHoleCardsMsg(std::string playerName, int card1, int card2, int cardsValueInt = -1, std::string showHas = "shows") ; - void logPlayerWinGame(std::string playerName, int gameID); - void flushLogAtGame(int gameID); - void flushLogAtHand(); - - void SignalNetClientConnect(int actionID); - void SignalNetClientGameInfo(int actionID); - void SignalNetClientError(int errorID, int osErrorID); - void SignalNetClientNotification(int notificationId); - void SignalNetClientStatsUpdate(const ServerStats &stats); - void SignalNetClientRemovedFromGame(int notificationId); - void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); - void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); - void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName); - void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName); - void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName); - void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg); - void SignalNetClientWaitDialog(); - - void SignalNetClientGameListNew(unsigned gameId); - void SignalNetClientGameListRemove(unsigned gameId); - void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode); - void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId); - void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId); - void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId); - void SignalNetClientGameStart(boost::shared_ptr game); - - void SignalNetServerSuccess(int actionID); - void SignalNetServerError(int errorID, int osErrorID); - - void SignalIrcConnect(const std::string &server); - void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel); - void SignalIrcPlayerJoined(const std::string &nickName); - void SignalIrcPlayerChanged(const std::string &oldNick, const std::string &newNick); - void SignalIrcPlayerKicked(const std::string &nickName, const std::string &byWhom, const std::string &reason); - void SignalIrcPlayerLeft(const std::string &nickName); - void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); - void SignalIrcError(int errorCode); - void SignalIrcServerError(int errorCode); - -private: - - boost::shared_ptr mySession; - ConfigFile *myConfig; - - ClientCallback *myClientcb; - ServerCallback *myServercb; - IrcCallback *myIrccb; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SERVERGUIWRAPPER_H +#define SERVERGUIWRAPPER_H + +#include + +class ConfigFile; +class Session; + +class ServerGuiWrapper : public GuiInterface +{ +public: + ServerGuiWrapper(ConfigFile *config, ClientCallback *clientcb, ServerCallback *servercb, IrcCallback *irccb); + ~ServerGuiWrapper(); + + void initGui(int speed); + + Session &getSession(); + void setSession(boost::shared_ptr session); + + void refreshSet() const; + void refreshCash() const; + void refreshAction(int =-1, int =-1) const; + void refreshChangePlayer() const; + void refreshPot() const; + void refreshGroupbox(int =-1, int =-1) const; + void refreshAll() const; + void refreshPlayerName() const; + void refreshButton() const; + void refreshGameLabels(GameState state) const; + + void setPlayerAvatar(int myUniqueID, const std::string &myAvatar) const; + + void waitForGuiUpdateDone() const; + + void dealBeRoCards(int); + void dealHoleCards(); + void dealFlopCards(); + void dealTurnCard(); + void dealRiverCard(); + + void nextPlayerAnimation(); + + void beRoAnimation2(int); + + void preflopAnimation1(); + void preflopAnimation2(); + + void flopAnimation1(); + void flopAnimation2(); + + void turnAnimation1(); + void turnAnimation2(); + + void riverAnimation1(); + void riverAnimation2(); + + void postRiverAnimation1(); + void postRiverRunAnimation1(); + + void flipHolecardsAllIn(); + + void nextRoundCleanGui(); + + void meInAction(); + void updateMyButtonsState(); + void disableMyButtons(); + void startTimeoutAnimation(int playerId, int timeoutSec); + void stopTimeoutAnimation(int playerId); + + void logPlayerActionMsg(std::string playerName, int action, int setValue) ; + void logNewGameHandMsg(int gameID, int handID) ; + void logPlayerWinsMsg(std::string playerName, int pot, bool main); + void logPlayerSitsOut(std::string playerName); + void logNewBlindsSetsMsg(int sbSet, int bbSet, std::string sbName, std::string bbName); + void logDealBoardCardsMsg(int roundID, int card1, int card2, int card3, int card4 = -1, int card5 = -1) ; + void logFlipHoleCardsMsg(std::string playerName, int card1, int card2, int cardsValueInt = -1, std::string showHas = "shows") ; + void logPlayerWinGame(std::string playerName, int gameID); + void flushLogAtGame(int gameID); + void flushLogAtHand(); + + void SignalNetClientConnect(int actionID); + void SignalNetClientGameInfo(int actionID); + void SignalNetClientError(int errorID, int osErrorID); + void SignalNetClientNotification(int notificationId); + void SignalNetClientStatsUpdate(const ServerStats &stats); + void SignalNetClientRemovedFromGame(int notificationId); + void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); + void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); + void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName); + void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName); + void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName); + void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg); + void SignalNetClientWaitDialog(); + + void SignalNetClientGameListNew(unsigned gameId); + void SignalNetClientGameListRemove(unsigned gameId); + void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode); + void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId); + void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId); + void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId); + void SignalNetClientGameStart(boost::shared_ptr game); + + void SignalNetServerSuccess(int actionID); + void SignalNetServerError(int errorID, int osErrorID); + + void SignalIrcConnect(const std::string &server); + void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel); + void SignalIrcPlayerJoined(const std::string &nickName); + void SignalIrcPlayerChanged(const std::string &oldNick, const std::string &newNick); + void SignalIrcPlayerKicked(const std::string &nickName, const std::string &byWhom, const std::string &reason); + void SignalIrcPlayerLeft(const std::string &nickName); + void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); + void SignalIrcError(int errorCode); + void SignalIrcServerError(int errorCode); + +private: + + boost::shared_ptr mySession; + ConfigFile *myConfig; + + ClientCallback *myClientcb; + ServerCallback *myServercb; + IrcCallback *myIrccb; +}; + +#endif diff --git a/src/gui/qt/qttools/nonqthelper/nonqthelper.cpp b/src/gui/qt/qttools/nonqthelper/nonqthelper.cpp index 98bf90dd..6db5fbed 100644 --- a/src/gui/qt/qttools/nonqthelper/nonqthelper.cpp +++ b/src/gui/qt/qttools/nonqthelper/nonqthelper.cpp @@ -1,53 +1,53 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "nonqthelper.h" - -#include -#include - -NonQtHelper::NonQtHelper() -{ -} - - -NonQtHelper::~NonQtHelper() -{ -} - -std::string -NonQtHelper::stringToUtf8(const std::string &myString) -{ - return ConvHelper::NativeToUtf8(myString); -} - -std::string -NonQtHelper::getDefaultLanguage() -{ - return "en"; -} - -std::string -NonQtHelper::getDataPathStdString(const char *argv0) -{ - boost::filesystem::path startPath(argv0); - startPath = startPath.remove_leaf(); - startPath /= "data"; - return stringToUtf8(startPath.directory_string()); -} +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "nonqthelper.h" + +#include +#include + +NonQtHelper::NonQtHelper() +{ +} + + +NonQtHelper::~NonQtHelper() +{ +} + +std::string +NonQtHelper::stringToUtf8(const std::string &myString) +{ + return ConvHelper::NativeToUtf8(myString); +} + +std::string +NonQtHelper::getDefaultLanguage() +{ + return "en"; +} + +std::string +NonQtHelper::getDataPathStdString(const char *argv0) +{ + boost::filesystem::path startPath(argv0); + startPath = startPath.remove_leaf(); + startPath /= "data"; + return stringToUtf8(startPath.directory_string()); +} diff --git a/src/gui/qt/qttools/nonqthelper/nonqthelper.h b/src/gui/qt/qttools/nonqthelper/nonqthelper.h index 7cbfdd36..fda4c68d 100644 --- a/src/gui/qt/qttools/nonqthelper/nonqthelper.h +++ b/src/gui/qt/qttools/nonqthelper/nonqthelper.h @@ -1,44 +1,44 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef NONQTHELPER_H -#define NONQTHELPER_H - -#ifndef POKERTH_DEDICATED_SERVER -#error This file is only for the server. -#endif - -#include - -class NonQtHelper -{ - -public: - NonQtHelper(); - - ~NonQtHelper(); - - std::string stringToUtf8(const std::string &); - std::string getDefaultLanguage(); - - std::string getDataPathStdString(const char *argv0); -}; - - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef NONQTHELPER_H +#define NONQTHELPER_H + +#ifndef POKERTH_DEDICATED_SERVER +#error This file is only for the server. +#endif + +#include + +class NonQtHelper +{ + +public: + NonQtHelper(); + + ~NonQtHelper(); + + std::string stringToUtf8(const std::string &); + std::string getDefaultLanguage(); + + std::string getDataPathStdString(const char *argv0); +}; + + +#endif diff --git a/src/gui/qt/qttools/nonqttoolswrapper.h b/src/gui/qt/qttools/nonqttoolswrapper.h index 8e099aa6..2dfea972 100644 --- a/src/gui/qt/qttools/nonqttoolswrapper.h +++ b/src/gui/qt/qttools/nonqttoolswrapper.h @@ -1,45 +1,45 @@ -/*************************************************************************** - * Copyright (C) 2006 by FThauer FHammer * - * f.thauer@web.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef NONQTTOOLSWRAPPER_H -#define NONQTTOOLSWRAPPER_H - -#include - -#include - -class NonQtHelper; - -class NonQtToolsWrapper : public QtToolsInterface -{ -public: - NonQtToolsWrapper(); - ~NonQtToolsWrapper(); - - std::string stringToUtf8(const std::string &myString); - std::string getDefaultLanguage(); - std::string getDataPathStdString(const char *argv0); - -private: - - NonQtHelper *myQtHelper; - -}; - -#endif +/*************************************************************************** + * Copyright (C) 2006 by FThauer FHammer * + * f.thauer@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef NONQTTOOLSWRAPPER_H +#define NONQTTOOLSWRAPPER_H + +#include + +#include + +class NonQtHelper; + +class NonQtToolsWrapper : public QtToolsInterface +{ +public: + NonQtToolsWrapper(); + ~NonQtToolsWrapper(); + + std::string stringToUtf8(const std::string &myString); + std::string getDefaultLanguage(); + std::string getDataPathStdString(const char *argv0); + +private: + + NonQtHelper *myQtHelper; + +}; + +#endif diff --git a/src/gui/qt/qttools/qttoolswrapper.h b/src/gui/qt/qttools/qttoolswrapper.h index e05f18fb..180629b2 100644 --- a/src/gui/qt/qttools/qttoolswrapper.h +++ b/src/gui/qt/qttools/qttoolswrapper.h @@ -1,46 +1,46 @@ -/*************************************************************************** - * Copyright (C) 2006 by FThauer FHammer * - * f.thauer@web.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef QTTOOLSWRAPPER_H -#define QTTOOLSWRAPPER_H - -#include - -#include - -class QtHelper; - -class QtToolsWrapper : public QtToolsInterface -{ -public: - QtToolsWrapper(); - - ~QtToolsWrapper(); - - std::string stringToUtf8(const std::string &myString); - std::string getDefaultLanguage(); - std::string getDataPathStdString(const char *argv0); - -private: - - QtHelper *myQtHelper; - -}; - -#endif +/*************************************************************************** + * Copyright (C) 2006 by FThauer FHammer * + * f.thauer@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef QTTOOLSWRAPPER_H +#define QTTOOLSWRAPPER_H + +#include + +#include + +class QtHelper; + +class QtToolsWrapper : public QtToolsInterface +{ +public: + QtToolsWrapper(); + + ~QtToolsWrapper(); + + std::string stringToUtf8(const std::string &myString); + std::string getDefaultLanguage(); + std::string getDataPathStdString(const char *argv0); + +private: + + QtHelper *myQtHelper; + +}; + +#endif diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index 37102b04..7955c4e9 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -1,62 +1,62 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Callback interface for network client gui. */ - -#ifndef _CLIENTCALLBACK_H_ -#define _CLIENTCALLBACK_H_ - -#include -#include -#include -#include -#include - -class Game; - -class ClientCallback -{ -public: - virtual ~ClientCallback(); - - virtual void SignalNetClientConnect(int actionID) = 0; - virtual void SignalNetClientGameInfo(int actionID) = 0; - virtual void SignalNetClientError(int errorID, int osErrorID) = 0; - virtual void SignalNetClientNotification(int notificationId) = 0; - virtual void SignalNetClientStatsUpdate(const ServerStats &stats) = 0; - virtual void SignalNetClientRemovedFromGame(int notificationId) = 0; - - virtual void SignalNetClientGameListNew(unsigned gameId) = 0; - virtual void SignalNetClientGameListRemove(unsigned gameId) = 0; - virtual void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) = 0; - virtual void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) = 0; - virtual void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) = 0; - virtual void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) = 0; - - virtual void SignalNetClientGameStart(boost::shared_ptr game) = 0; - virtual void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) = 0; - virtual void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) = 0; - virtual void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName) = 0; - virtual void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName) = 0; - virtual void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName) = 0; - - virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0; - virtual void SignalNetClientWaitDialog() = 0; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Callback interface for network client gui. */ + +#ifndef _CLIENTCALLBACK_H_ +#define _CLIENTCALLBACK_H_ + +#include +#include +#include +#include +#include + +class Game; + +class ClientCallback +{ +public: + virtual ~ClientCallback(); + + virtual void SignalNetClientConnect(int actionID) = 0; + virtual void SignalNetClientGameInfo(int actionID) = 0; + virtual void SignalNetClientError(int errorID, int osErrorID) = 0; + virtual void SignalNetClientNotification(int notificationId) = 0; + virtual void SignalNetClientStatsUpdate(const ServerStats &stats) = 0; + virtual void SignalNetClientRemovedFromGame(int notificationId) = 0; + + virtual void SignalNetClientGameListNew(unsigned gameId) = 0; + virtual void SignalNetClientGameListRemove(unsigned gameId) = 0; + virtual void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) = 0; + virtual void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) = 0; + virtual void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) = 0; + virtual void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) = 0; + + virtual void SignalNetClientGameStart(boost::shared_ptr game) = 0; + virtual void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) = 0; + virtual void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) = 0; + virtual void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName) = 0; + virtual void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName) = 0; + virtual void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName) = 0; + + virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0; + virtual void SignalNetClientWaitDialog() = 0; +}; + +#endif diff --git a/src/net/clientcontext.h b/src/net/clientcontext.h index 1bffdd62..5dbaf784 100644 --- a/src/net/clientcontext.h +++ b/src/net/clientcontext.h @@ -1,90 +1,90 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Context of network client. */ - -#ifndef _CLIENTCONTEXT_H_ -#define _CLIENTCONTEXT_H_ - -#include -#include -#include - -class ClientContext : public NetContext -{ -public: - ClientContext(); - virtual ~ClientContext(); - - virtual SOCKET GetSocket() const; - void SetSocket(SOCKET sockfd); - - boost::shared_ptr GetSessionData() const; - int GetProtocol() const - {return m_protocol;} - void SetProtocol(int protocol) - {m_protocol = protocol;} - int GetAddrFamily() const - {return m_addrFamily;} - void SetAddrFamily(int addrFamily) - {m_addrFamily = addrFamily;} - const std::string &GetServerAddr() const - {return m_serverAddr;} - void SetServerAddr(const std::string &serverAddr) - {m_serverAddr = serverAddr;} - unsigned GetServerPort() const - {return m_serverPort;} - void SetServerPort(unsigned serverPort) - {m_serverPort = serverPort;} - const std::string &GetPassword() const - {return m_password;} - void SetPassword(const std::string &password) - {m_password = password;} - const sockaddr_storage *GetClientSockaddr() const - {return &m_clientSockaddr;} - sockaddr_storage *GetClientSockaddr() - {return &m_clientSockaddr;} - const std::string &GetPlayerName() const - {return m_playerName;} - void SetPlayerName(const std::string &playerName) - {m_playerName = playerName;} - const std::string &GetAvatarFile() const - {return m_avatarFile;} - void SetAvatarFile(const std::string &avatarFile) - {m_avatarFile = avatarFile;} - - int GetClientSockaddrSize() const - {return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);} - - ReceiveBuffer &GetReceiveBuffer() - {return m_receiveBuffer;} - -private: - boost::shared_ptr m_sessionData; - int m_protocol; - int m_addrFamily; - std::string m_serverAddr; - unsigned m_serverPort; - std::string m_password; - sockaddr_storage m_clientSockaddr; - std::string m_playerName; - std::string m_avatarFile; - ReceiveBuffer m_receiveBuffer; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Context of network client. */ + +#ifndef _CLIENTCONTEXT_H_ +#define _CLIENTCONTEXT_H_ + +#include +#include +#include + +class ClientContext : public NetContext +{ +public: + ClientContext(); + virtual ~ClientContext(); + + virtual SOCKET GetSocket() const; + void SetSocket(SOCKET sockfd); + + boost::shared_ptr GetSessionData() const; + int GetProtocol() const + {return m_protocol;} + void SetProtocol(int protocol) + {m_protocol = protocol;} + int GetAddrFamily() const + {return m_addrFamily;} + void SetAddrFamily(int addrFamily) + {m_addrFamily = addrFamily;} + const std::string &GetServerAddr() const + {return m_serverAddr;} + void SetServerAddr(const std::string &serverAddr) + {m_serverAddr = serverAddr;} + unsigned GetServerPort() const + {return m_serverPort;} + void SetServerPort(unsigned serverPort) + {m_serverPort = serverPort;} + const std::string &GetPassword() const + {return m_password;} + void SetPassword(const std::string &password) + {m_password = password;} + const sockaddr_storage *GetClientSockaddr() const + {return &m_clientSockaddr;} + sockaddr_storage *GetClientSockaddr() + {return &m_clientSockaddr;} + const std::string &GetPlayerName() const + {return m_playerName;} + void SetPlayerName(const std::string &playerName) + {m_playerName = playerName;} + const std::string &GetAvatarFile() const + {return m_avatarFile;} + void SetAvatarFile(const std::string &avatarFile) + {m_avatarFile = avatarFile;} + + int GetClientSockaddrSize() const + {return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);} + + ReceiveBuffer &GetReceiveBuffer() + {return m_receiveBuffer;} + +private: + boost::shared_ptr m_sessionData; + int m_protocol; + int m_addrFamily; + std::string m_serverAddr; + unsigned m_serverPort; + std::string m_password; + sockaddr_storage m_clientSockaddr; + std::string m_playerName; + std::string m_avatarFile; + ReceiveBuffer m_receiveBuffer; +}; + +#endif diff --git a/src/net/clientexception.h b/src/net/clientexception.h index eb809fc0..e52f67b3 100644 --- a/src/net/clientexception.h +++ b/src/net/clientexception.h @@ -1,36 +1,36 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Exception class for client errors. */ - -#ifndef _CLIENTEXCEPTION_H_ -#define _CLIENTEXCEPTION_H_ - -#include - -class ClientException : public NetException -{ -public: - - ClientException(const char *sourcefile, int sourceline, int errorId, int osErrorCode) - : NetException(sourcefile, sourceline, errorId, osErrorCode) {} - - virtual ~ClientException() throw(); -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Exception class for client errors. */ + +#ifndef _CLIENTEXCEPTION_H_ +#define _CLIENTEXCEPTION_H_ + +#include + +class ClientException : public NetException +{ +public: + + ClientException(const char *sourcefile, int sourceline, int errorId, int osErrorCode) + : NetException(sourcefile, sourceline, errorId, osErrorCode) {} + + virtual ~ClientException() throw(); +}; + +#endif diff --git a/src/net/clientstate.h b/src/net/clientstate.h index b13269a7..836eabb1 100644 --- a/src/net/clientstate.h +++ b/src/net/clientstate.h @@ -1,327 +1,327 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* State of network client. */ - -#ifndef _CLIENTSTATE_H_ -#define _CLIENTSTATE_H_ - -#include // needed for correct order of header files. -#include -#include -#include - -#define CLIENT_INITIAL_STATE ClientStateInit - -class ClientThread; -class ClientCallback; -class ResolverThread; -class Game; -class NetPacket; - -class ClientState -{ -public: - virtual ~ClientState(); - - // Main processing function of the current state. - virtual int Process(ClientThread &client) = 0; -}; - -// State: Initialization. -class ClientStateInit : public ClientState -{ -public: - // Access the state singleton. - static ClientStateInit &Instance(); - - virtual ~ClientStateInit(); - - // Some basic initialization (socket creation, basic checks). - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateInit(); -}; - -// State: Starting name resolution. -class ClientStateStartResolve : public ClientState -{ -public: - // Access the state singleton. - static ClientStateStartResolve &Instance(); - - virtual ~ClientStateStartResolve(); - - // Initiate the name resolution. - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateStartResolve(); -}; - -// State: Name resolution. -class ClientStateResolving : public ClientState -{ -public: - // Access the state singleton. - static ClientStateResolving &Instance(); - - virtual ~ClientStateResolving(); - - void SetResolver(ResolverThread *resolver); - - // Poll for the completion of the name resolution. - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateResolving(); - - void Cleanup(); - -private: - - ResolverThread *m_resolver; -}; - -// State: Initiate server connection. -class ClientStateStartConnect : public ClientState -{ -public: - // Access the state singleton. - static ClientStateStartConnect &Instance(); - - virtual ~ClientStateStartConnect(); - - // Call connect. - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateStartConnect(); -}; - -// State: Connecting to server. -class ClientStateConnecting : public ClientState -{ -public: - // Access the state singleton. - static ClientStateConnecting &Instance(); - - virtual ~ClientStateConnecting(); - - void SetTimer(const boost::timers::portable::microsec_timer &timer); - - // "Poll" for the completion of the TCP/IP connect call. - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateConnecting(); - -private: - - boost::timers::portable::microsec_timer m_connectTimer; -}; - -// State: Session init. -class ClientStateStartSession : public ClientState -{ -public: - // Access the state singleton. - static ClientStateStartSession &Instance(); - - virtual ~ClientStateStartSession(); - - // sleep. - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateStartSession(); -}; - -// Abstract State: Receiving -class AbstractClientStateReceiving : public ClientState -{ -public: - virtual ~AbstractClientStateReceiving(); - - // select on socket. - virtual int Process(ClientThread &client); - -protected: - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet) = 0; - - AbstractClientStateReceiving(); -}; - -// State: Wait for Session ACK. -class ClientStateWaitSession : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateWaitSession &Instance(); - - virtual ~ClientStateWaitSession(); - - -protected: - - // Protected constructor - this is a singleton. - ClientStateWaitSession(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); -}; - -// State: Wait for Join. -class ClientStateWaitJoin : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateWaitJoin &Instance(); - - virtual ~ClientStateWaitJoin(); - - -protected: - - // Protected constructor - this is a singleton. - ClientStateWaitJoin(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); -}; - -// State: Wait for start of the game or start info. -class ClientStateWaitGame : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateWaitGame &Instance(); - - virtual ~ClientStateWaitGame(); - -protected: - - // Protected constructor - this is a singleton. - ClientStateWaitGame(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); -}; - -// State: Synchronize on game start. -class ClientStateSynchronizeStart : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateSynchronizeStart &Instance(); - - virtual ~ClientStateSynchronizeStart(); - - virtual int Process(ClientThread &client); -protected: - - // Protected constructor - this is a singleton. - ClientStateSynchronizeStart(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); -}; - -// State: Wait for game start. -class ClientStateWaitStart : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateWaitStart &Instance(); - - virtual ~ClientStateWaitStart(); - -protected: - - // Protected constructor - this is a singleton. - ClientStateWaitStart(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); -}; - -// State: Wait for start of the next hand. -class ClientStateWaitHand : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateWaitHand &Instance(); - - virtual ~ClientStateWaitHand(); - -protected: - - // Protected constructor - this is a singleton. - ClientStateWaitHand(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); -}; - -// State: Hand Loop. -class ClientStateRunHand : public AbstractClientStateReceiving -{ -public: - // Access the state singleton. - static ClientStateRunHand &Instance(); - - virtual ~ClientStateRunHand(); - -protected: - - // Protected constructor - this is a singleton. - ClientStateRunHand(); - - virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); - - static void ResetPlayerActions(Game &curGame); - static void ResetPlayerSets(Game &curGame); -}; - -// State: Final (just for testing, should not be used). -class ClientStateFinal : public ClientState -{ -public: - // Access the state singleton. - static ClientStateFinal &Instance(); - - virtual ~ClientStateFinal(); - - // sleep. - virtual int Process(ClientThread &client); - -protected: - - // Protected constructor - this is a singleton. - ClientStateFinal(); -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* State of network client. */ + +#ifndef _CLIENTSTATE_H_ +#define _CLIENTSTATE_H_ + +#include // needed for correct order of header files. +#include +#include +#include + +#define CLIENT_INITIAL_STATE ClientStateInit + +class ClientThread; +class ClientCallback; +class ResolverThread; +class Game; +class NetPacket; + +class ClientState +{ +public: + virtual ~ClientState(); + + // Main processing function of the current state. + virtual int Process(ClientThread &client) = 0; +}; + +// State: Initialization. +class ClientStateInit : public ClientState +{ +public: + // Access the state singleton. + static ClientStateInit &Instance(); + + virtual ~ClientStateInit(); + + // Some basic initialization (socket creation, basic checks). + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateInit(); +}; + +// State: Starting name resolution. +class ClientStateStartResolve : public ClientState +{ +public: + // Access the state singleton. + static ClientStateStartResolve &Instance(); + + virtual ~ClientStateStartResolve(); + + // Initiate the name resolution. + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateStartResolve(); +}; + +// State: Name resolution. +class ClientStateResolving : public ClientState +{ +public: + // Access the state singleton. + static ClientStateResolving &Instance(); + + virtual ~ClientStateResolving(); + + void SetResolver(ResolverThread *resolver); + + // Poll for the completion of the name resolution. + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateResolving(); + + void Cleanup(); + +private: + + ResolverThread *m_resolver; +}; + +// State: Initiate server connection. +class ClientStateStartConnect : public ClientState +{ +public: + // Access the state singleton. + static ClientStateStartConnect &Instance(); + + virtual ~ClientStateStartConnect(); + + // Call connect. + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateStartConnect(); +}; + +// State: Connecting to server. +class ClientStateConnecting : public ClientState +{ +public: + // Access the state singleton. + static ClientStateConnecting &Instance(); + + virtual ~ClientStateConnecting(); + + void SetTimer(const boost::timers::portable::microsec_timer &timer); + + // "Poll" for the completion of the TCP/IP connect call. + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateConnecting(); + +private: + + boost::timers::portable::microsec_timer m_connectTimer; +}; + +// State: Session init. +class ClientStateStartSession : public ClientState +{ +public: + // Access the state singleton. + static ClientStateStartSession &Instance(); + + virtual ~ClientStateStartSession(); + + // sleep. + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateStartSession(); +}; + +// Abstract State: Receiving +class AbstractClientStateReceiving : public ClientState +{ +public: + virtual ~AbstractClientStateReceiving(); + + // select on socket. + virtual int Process(ClientThread &client); + +protected: + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet) = 0; + + AbstractClientStateReceiving(); +}; + +// State: Wait for Session ACK. +class ClientStateWaitSession : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitSession &Instance(); + + virtual ~ClientStateWaitSession(); + + +protected: + + // Protected constructor - this is a singleton. + ClientStateWaitSession(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); +}; + +// State: Wait for Join. +class ClientStateWaitJoin : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitJoin &Instance(); + + virtual ~ClientStateWaitJoin(); + + +protected: + + // Protected constructor - this is a singleton. + ClientStateWaitJoin(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); +}; + +// State: Wait for start of the game or start info. +class ClientStateWaitGame : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitGame &Instance(); + + virtual ~ClientStateWaitGame(); + +protected: + + // Protected constructor - this is a singleton. + ClientStateWaitGame(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); +}; + +// State: Synchronize on game start. +class ClientStateSynchronizeStart : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateSynchronizeStart &Instance(); + + virtual ~ClientStateSynchronizeStart(); + + virtual int Process(ClientThread &client); +protected: + + // Protected constructor - this is a singleton. + ClientStateSynchronizeStart(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); +}; + +// State: Wait for game start. +class ClientStateWaitStart : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitStart &Instance(); + + virtual ~ClientStateWaitStart(); + +protected: + + // Protected constructor - this is a singleton. + ClientStateWaitStart(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); +}; + +// State: Wait for start of the next hand. +class ClientStateWaitHand : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitHand &Instance(); + + virtual ~ClientStateWaitHand(); + +protected: + + // Protected constructor - this is a singleton. + ClientStateWaitHand(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); +}; + +// State: Hand Loop. +class ClientStateRunHand : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateRunHand &Instance(); + + virtual ~ClientStateRunHand(); + +protected: + + // Protected constructor - this is a singleton. + ClientStateRunHand(); + + virtual int InternalProcess(ClientThread &client, boost::shared_ptr packet); + + static void ResetPlayerActions(Game &curGame); + static void ResetPlayerSets(Game &curGame); +}; + +// State: Final (just for testing, should not be used). +class ClientStateFinal : public ClientState +{ +public: + // Access the state singleton. + static ClientStateFinal &Instance(); + + virtual ~ClientStateFinal(); + + // sleep. + virtual int Process(ClientThread &client); + +protected: + + // Protected constructor - this is a singleton. + ClientStateFinal(); +}; + +#endif diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 7173228c..b27d2942 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -1,207 +1,207 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network client thread. */ - -#ifndef _CLIENTTHREAD_H_ -#define _CLIENTTHREAD_H_ - -#include -#include -#include -#include -#include -#include - -class ClientContext; -class ClientState; -class SenderThread; -class ReceiverHelper; -class ClientSenderCallback; -class Game; -class NetPacket; -class AvatarManager; - -class ClientThread : public Thread -{ -public: - ClientThread(GuiInterface &gui, AvatarManager &avatarManager); - virtual ~ClientThread(); - - // Set the parameters. Does not do any error checking. - // Error checking will be done during connect - // (i.e. after starting the thread). - void Init( - const std::string &serverAddress, - unsigned serverPort, - bool ipv6, - bool sctp, - const std::string &pwd, - const std::string &playerName, - const std::string &avatarFile); - - void SendKickPlayer(unsigned playerId); - void SendLeaveCurrentGame(); - void SendStartEvent(bool fillUpWithCpuPlayers); - void SendPlayerAction(); - void SendChatMessage(const std::string &msg); - void SendJoinFirstGame(const std::string &password); - void SendJoinGame(unsigned gameId, const std::string &password); - void SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password); - - GameInfo GetGameInfo(unsigned gameId) const; - PlayerInfo GetPlayerInfo(unsigned playerId) const; - bool GetPlayerIdFromName(const std::string &playerName, unsigned &playerId) const; - ServerStats GetStatData() const; - unsigned GetGameId() const; - - ClientCallback &GetCallback(); - GuiInterface &GetGui(); - AvatarManager &GetAvatarManager(); - -protected: - typedef std::map GameInfoMap; - typedef std::list > NetPacketList; - typedef std::map PlayerInfoMap; - typedef std::map > AvatarDataMap; - - // Main function of the thread. - virtual void Main(); - - void AddPacket(boost::shared_ptr packet); - void SendPacketLoop(); - - bool GetCachedPlayerInfo(unsigned id, PlayerInfo &info) const; - void RequestPlayerInfo(unsigned id, bool requestAvatar = false); - void SetPlayerInfo(unsigned id, const PlayerInfo &info); - void SetUnknownPlayer(unsigned id); - void SetNewGameAdmin(unsigned id); - void RetrieveAvatarIfNeeded(unsigned id, const PlayerInfo &info); - - void AddTempAvatarData(unsigned playerId, unsigned avatarSize, AvatarFileType type); - void StoreInTempAvatarData(unsigned playerId, const std::vector &data); - void CompleteTempAvatarData(unsigned playerId); - void SetUnknownAvatar(unsigned playerId); - - const ClientContext &GetContext() const; - ClientContext &GetContext(); - - ClientState &GetState(); - void SetState(ClientState &newState); - - SenderThread &GetSender(); - ReceiverHelper &GetReceiver(); - - void SetGameId(unsigned id); - const GameData &GetGameData() const; - void SetGameData(const GameData &gameData); - const StartData &GetStartData() const; - void SetStartData(const StartData &startData); - unsigned GetGuiPlayerId() const; - void SetGuiPlayerId(unsigned guiPlayerId); - - boost::shared_ptr GetGame(); - - ClientSenderCallback &GetSenderCallback(); - - void AddPlayerData(boost::shared_ptr playerData); - void RemovePlayerData(unsigned playerId); - void ClearPlayerDataList(); - void MapPlayerDataList(); - const PlayerDataList &GetPlayerDataList() const; - boost::shared_ptr GetPlayerDataByUniqueId(unsigned id); - boost::shared_ptr GetPlayerDataByName(const std::string &name); - - void RemoveDisconnectedPlayers(); - - unsigned GetGameIdByName(const std::string &name) const; - void AddGameInfo(unsigned gameId, const GameInfo &info); - void UpdateGameInfoMode(unsigned gameId, GameMode mode); - void UpdateGameInfoAdmin(unsigned gameId, unsigned adminPlayerId); - void RemoveGameInfo(unsigned gameId); - void ModifyGameInfoAddPlayer(unsigned gameId, unsigned playerId); - void ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId); - void ClearGameInfoMap(); - - void UpdateStatData(const ServerStats &stats); - - bool IsSessionEstablished() const; - void SetSessionEstablished(bool flag); - - bool IsSynchronized() const; - -private: - - NetPacketList m_outPacketList; - mutable boost::mutex m_outPacketListMutex; - - boost::shared_ptr m_context; - boost::shared_ptr m_senderCallback; - ClientState *m_curState; - GuiInterface &m_gui; - AvatarManager &m_avatarManager; - - boost::shared_ptr m_sender; - boost::shared_ptr m_receiver; - - GameData m_gameData; - StartData m_startData; - PlayerDataList m_playerDataList; - - GameInfoMap m_gameInfoMap; - mutable boost::mutex m_gameInfoMapMutex; - - boost::shared_ptr m_game; - - PlayerInfoMap m_playerInfoMap; - mutable boost::mutex m_playerInfoMapMutex; - PlayerIdList m_playerInfoRequestList; - PlayerIdList m_avatarShouldRequestList; - PlayerIdList m_avatarHasRequestedList; - - unsigned m_curGameId; - mutable boost::mutex m_curGameIdMutex; - - AvatarDataMap m_tempAvatarMap; - - unsigned m_curGameNum; - unsigned m_guiPlayerId; - bool m_sessionEstablished; - - mutable boost::mutex m_curStatsMutex; - ServerStats m_curStats; - -friend class AbstractClientStateReceiving; -friend class ClientStateInit; -friend class ClientStateStartResolve; -friend class ClientStateResolving; -friend class ClientStateStartConnect; -friend class ClientStateConnecting; -friend class ClientStateStartSession; -friend class ClientStateWaitSession; -friend class ClientStateWaitJoin; -friend class ClientStateWaitGame; -friend class ClientStateSynchronizeStart; -friend class ClientStateWaitStart; -friend class ClientStateWaitHand; -friend class ClientStateRunHand; -friend class ClientStateFinal; -friend class ClientSenderCallback; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network client thread. */ + +#ifndef _CLIENTTHREAD_H_ +#define _CLIENTTHREAD_H_ + +#include +#include +#include +#include +#include +#include + +class ClientContext; +class ClientState; +class SenderThread; +class ReceiverHelper; +class ClientSenderCallback; +class Game; +class NetPacket; +class AvatarManager; + +class ClientThread : public Thread +{ +public: + ClientThread(GuiInterface &gui, AvatarManager &avatarManager); + virtual ~ClientThread(); + + // Set the parameters. Does not do any error checking. + // Error checking will be done during connect + // (i.e. after starting the thread). + void Init( + const std::string &serverAddress, + unsigned serverPort, + bool ipv6, + bool sctp, + const std::string &pwd, + const std::string &playerName, + const std::string &avatarFile); + + void SendKickPlayer(unsigned playerId); + void SendLeaveCurrentGame(); + void SendStartEvent(bool fillUpWithCpuPlayers); + void SendPlayerAction(); + void SendChatMessage(const std::string &msg); + void SendJoinFirstGame(const std::string &password); + void SendJoinGame(unsigned gameId, const std::string &password); + void SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password); + + GameInfo GetGameInfo(unsigned gameId) const; + PlayerInfo GetPlayerInfo(unsigned playerId) const; + bool GetPlayerIdFromName(const std::string &playerName, unsigned &playerId) const; + ServerStats GetStatData() const; + unsigned GetGameId() const; + + ClientCallback &GetCallback(); + GuiInterface &GetGui(); + AvatarManager &GetAvatarManager(); + +protected: + typedef std::map GameInfoMap; + typedef std::list > NetPacketList; + typedef std::map PlayerInfoMap; + typedef std::map > AvatarDataMap; + + // Main function of the thread. + virtual void Main(); + + void AddPacket(boost::shared_ptr packet); + void SendPacketLoop(); + + bool GetCachedPlayerInfo(unsigned id, PlayerInfo &info) const; + void RequestPlayerInfo(unsigned id, bool requestAvatar = false); + void SetPlayerInfo(unsigned id, const PlayerInfo &info); + void SetUnknownPlayer(unsigned id); + void SetNewGameAdmin(unsigned id); + void RetrieveAvatarIfNeeded(unsigned id, const PlayerInfo &info); + + void AddTempAvatarData(unsigned playerId, unsigned avatarSize, AvatarFileType type); + void StoreInTempAvatarData(unsigned playerId, const std::vector &data); + void CompleteTempAvatarData(unsigned playerId); + void SetUnknownAvatar(unsigned playerId); + + const ClientContext &GetContext() const; + ClientContext &GetContext(); + + ClientState &GetState(); + void SetState(ClientState &newState); + + SenderThread &GetSender(); + ReceiverHelper &GetReceiver(); + + void SetGameId(unsigned id); + const GameData &GetGameData() const; + void SetGameData(const GameData &gameData); + const StartData &GetStartData() const; + void SetStartData(const StartData &startData); + unsigned GetGuiPlayerId() const; + void SetGuiPlayerId(unsigned guiPlayerId); + + boost::shared_ptr GetGame(); + + ClientSenderCallback &GetSenderCallback(); + + void AddPlayerData(boost::shared_ptr playerData); + void RemovePlayerData(unsigned playerId); + void ClearPlayerDataList(); + void MapPlayerDataList(); + const PlayerDataList &GetPlayerDataList() const; + boost::shared_ptr GetPlayerDataByUniqueId(unsigned id); + boost::shared_ptr GetPlayerDataByName(const std::string &name); + + void RemoveDisconnectedPlayers(); + + unsigned GetGameIdByName(const std::string &name) const; + void AddGameInfo(unsigned gameId, const GameInfo &info); + void UpdateGameInfoMode(unsigned gameId, GameMode mode); + void UpdateGameInfoAdmin(unsigned gameId, unsigned adminPlayerId); + void RemoveGameInfo(unsigned gameId); + void ModifyGameInfoAddPlayer(unsigned gameId, unsigned playerId); + void ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId); + void ClearGameInfoMap(); + + void UpdateStatData(const ServerStats &stats); + + bool IsSessionEstablished() const; + void SetSessionEstablished(bool flag); + + bool IsSynchronized() const; + +private: + + NetPacketList m_outPacketList; + mutable boost::mutex m_outPacketListMutex; + + boost::shared_ptr m_context; + boost::shared_ptr m_senderCallback; + ClientState *m_curState; + GuiInterface &m_gui; + AvatarManager &m_avatarManager; + + boost::shared_ptr m_sender; + boost::shared_ptr m_receiver; + + GameData m_gameData; + StartData m_startData; + PlayerDataList m_playerDataList; + + GameInfoMap m_gameInfoMap; + mutable boost::mutex m_gameInfoMapMutex; + + boost::shared_ptr m_game; + + PlayerInfoMap m_playerInfoMap; + mutable boost::mutex m_playerInfoMapMutex; + PlayerIdList m_playerInfoRequestList; + PlayerIdList m_avatarShouldRequestList; + PlayerIdList m_avatarHasRequestedList; + + unsigned m_curGameId; + mutable boost::mutex m_curGameIdMutex; + + AvatarDataMap m_tempAvatarMap; + + unsigned m_curGameNum; + unsigned m_guiPlayerId; + bool m_sessionEstablished; + + mutable boost::mutex m_curStatsMutex; + ServerStats m_curStats; + +friend class AbstractClientStateReceiving; +friend class ClientStateInit; +friend class ClientStateStartResolve; +friend class ClientStateResolving; +friend class ClientStateStartConnect; +friend class ClientStateConnecting; +friend class ClientStateStartSession; +friend class ClientStateWaitSession; +friend class ClientStateWaitJoin; +friend class ClientStateWaitGame; +friend class ClientStateSynchronizeStart; +friend class ClientStateWaitStart; +friend class ClientStateWaitHand; +friend class ClientStateRunHand; +friend class ClientStateFinal; +friend class ClientSenderCallback; +}; + +#endif diff --git a/src/net/common/clientcallback.cpp b/src/net/common/clientcallback.cpp index 0946c91f..36562016 100644 --- a/src/net/common/clientcallback.cpp +++ b/src/net/common/clientcallback.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -ClientCallback::~ClientCallback() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +ClientCallback::~ClientCallback() +{ +} + diff --git a/src/net/common/clientcontext.cpp b/src/net/common/clientcontext.cpp index c874c9f2..e33f697e 100644 --- a/src/net/common/clientcontext.cpp +++ b/src/net/common/clientcontext.cpp @@ -1,50 +1,50 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -ClientContext::ClientContext() -: m_protocol(0), m_addrFamily(AF_INET), m_serverPort(0) -{ - bzero(&m_clientSockaddr, sizeof(m_clientSockaddr)); -} - -ClientContext::~ClientContext() -{ -} - -SOCKET -ClientContext::GetSocket() const -{ - assert(m_sessionData.get()); - return m_sessionData->GetSocket(); -} - -void -ClientContext::SetSocket(SOCKET sockfd) -{ - m_sessionData.reset(new SessionData(sockfd, SESSION_ID_GENERIC)); -} - -boost::shared_ptr -ClientContext::GetSessionData() const -{ - return m_sessionData; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +ClientContext::ClientContext() +: m_protocol(0), m_addrFamily(AF_INET), m_serverPort(0) +{ + bzero(&m_clientSockaddr, sizeof(m_clientSockaddr)); +} + +ClientContext::~ClientContext() +{ +} + +SOCKET +ClientContext::GetSocket() const +{ + assert(m_sessionData.get()); + return m_sessionData->GetSocket(); +} + +void +ClientContext::SetSocket(SOCKET sockfd) +{ + m_sessionData.reset(new SessionData(sockfd, SESSION_ID_GENERIC)); +} + +boost::shared_ptr +ClientContext::GetSessionData() const +{ + return m_sessionData; +} + diff --git a/src/net/common/clientexception.cpp b/src/net/common/clientexception.cpp index f1226f18..55c48927 100644 --- a/src/net/common/clientexception.cpp +++ b/src/net/common/clientexception.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -ClientException::~ClientException() throw() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +ClientException::~ClientException() throw() +{ +} + diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index c0068aa0..a0f707d9 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -1,1236 +1,1236 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -using namespace std; - -#define CLIENT_WAIT_TIMEOUT_MSEC 50 -#define CLIENT_CONNECT_TIMEOUT_SEC 10 - - -ClientState::~ClientState() -{ -} - -//----------------------------------------------------------------------------- - -ClientStateInit & -ClientStateInit::Instance() -{ - static ClientStateInit state; - return state; -} - -ClientStateInit::ClientStateInit() -{ -} - -ClientStateInit::~ClientStateInit() -{ -} - -int -ClientStateInit::Process(ClientThread &client) -{ - ClientContext &context = client.GetContext(); - - if (context.GetServerAddr().empty()) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_SERVERADDR_NOT_SET, 0); - - if (context.GetServerPort() < 1024) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0); - - context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol())); - if (!IS_VALID_SOCKET(context.GetSocket())) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - - unsigned long mode = 1; - if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - - // The following call is optional - the return value is not checked. - int nodelay = 1; - setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); - - client.SetState(ClientStateStartResolve::Instance()); - - return MSG_SOCK_INIT_DONE; -} - -//----------------------------------------------------------------------------- - -ClientStateStartResolve & -ClientStateStartResolve::Instance() -{ - static ClientStateStartResolve state; - return state; -} - -ClientStateStartResolve::ClientStateStartResolve() -{ -} - -ClientStateStartResolve::~ClientStateStartResolve() -{ -} - -int -ClientStateStartResolve::Process(ClientThread &client) -{ - int retVal; - - ClientContext &context = client.GetContext(); - - context.GetClientSockaddr()->ss_family = context.GetAddrFamily(); - - // Treat the server address as numbers first. - if (socket_string_to_addr( - context.GetServerAddr().c_str(), - context.GetAddrFamily(), - (struct sockaddr *)context.GetClientSockaddr(), - context.GetClientSockaddrSize())) - { - // Success - but we still need to set the port. - if (!socket_set_port(context.GetServerPort(), context.GetAddrFamily(), (struct sockaddr *)context.GetClientSockaddr(), context.GetClientSockaddrSize())) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_SET_PORT_FAILED, 0); - - // No need to resolve - start connecting. - client.SetState(ClientStateStartConnect::Instance()); - retVal = MSG_SOCK_RESOLVE_DONE; - } - else - { - // Start name resolution in a separate thread, since it is blocking - // for up to about 30 seconds. - std::auto_ptr resolver(new ResolverThread); - resolver->Init(context); - resolver->Run(); - - ClientStateResolving::Instance().SetResolver(resolver.release()); - client.SetState(ClientStateResolving::Instance()); - - retVal = MSG_SOCK_INTERNAL_PENDING; - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateResolving & -ClientStateResolving::Instance() -{ - static ClientStateResolving state; - return state; -} - -ClientStateResolving::ClientStateResolving() -: m_resolver(NULL) -{ -} - -ClientStateResolving::~ClientStateResolving() -{ - Cleanup(); -} - -void -ClientStateResolving::SetResolver(ResolverThread *resolver) -{ - Cleanup(); - m_resolver = resolver; -} - -int -ClientStateResolving::Process(ClientThread &client) -{ - int retVal; - - if (!m_resolver) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_RESOLVE_FAILED, 0); - - if (m_resolver->Join(CLIENT_WAIT_TIMEOUT_MSEC)) - { - ClientContext &context = client.GetContext(); - bool success = m_resolver->GetResult(context); - Cleanup(); // Not required, but better keep things clean. - - if (!success) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_RESOLVE_FAILED, 0); - - client.SetState(ClientStateStartConnect::Instance()); - retVal = MSG_SOCK_RESOLVE_DONE; - } - else - retVal = MSG_SOCK_INTERNAL_PENDING; - - return retVal; -} - - -void -ClientStateResolving::Cleanup() -{ - if (m_resolver) - { - if (m_resolver->Join(500)) - delete m_resolver; - // If the resolver does not terminate fast enough, leave it - // as memory leak. - m_resolver = NULL; - } -} - -//----------------------------------------------------------------------------- - -ClientStateStartConnect & -ClientStateStartConnect::Instance() -{ - static ClientStateStartConnect state; - return state; -} - -ClientStateStartConnect::ClientStateStartConnect() -{ -} - -ClientStateStartConnect::~ClientStateStartConnect() -{ -} - -int -ClientStateStartConnect::Process(ClientThread &client) -{ - int retVal; - ClientContext &context = client.GetContext(); - - int connectResult = connect(context.GetSocket(), (struct sockaddr *)context.GetClientSockaddr(), context.GetClientSockaddrSize()); - - if (IS_VALID_CONNECT(connectResult)) - { - client.SetState(ClientStateStartSession::Instance()); - retVal = MSG_SOCK_CONNECT_DONE; - } - else - { - int errCode = SOCKET_ERRNO(); - if (IS_SOCKET_ERR_WOULDBLOCK(errCode)) - { - boost::timers::portable::microsec_timer connectTimer; - ClientStateConnecting::Instance().SetTimer(connectTimer); - client.SetState(ClientStateConnecting::Instance()); - retVal = MSG_SOCK_INTERNAL_PENDING; - } - else - throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_FAILED, SOCKET_ERRNO()); - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateConnecting & -ClientStateConnecting::Instance() -{ - static ClientStateConnecting state; - return state; -} - -ClientStateConnecting::ClientStateConnecting() -{ -} - -ClientStateConnecting::~ClientStateConnecting() -{ -} - -void -ClientStateConnecting::SetTimer(const boost::timers::portable::microsec_timer &timer) -{ - m_connectTimer = timer; -} - -int -ClientStateConnecting::Process(ClientThread &client) -{ - int retVal; - ClientContext &context = client.GetContext(); - - fd_set writeSet; - struct timeval timeout; - - FD_ZERO(&writeSet); - FD_SET(context.GetSocket(), &writeSet); - - timeout.tv_sec = 0; - timeout.tv_usec = CLIENT_WAIT_TIMEOUT_MSEC * 1000; - int selectResult = select(context.GetSocket() + 1, NULL, &writeSet, NULL, &timeout); - - if (selectResult > 0) // success - { - // Check whether the connect call succeeded. - int connectResult = 0; - socklen_t tmpSize = sizeof(connectResult); - getsockopt(context.GetSocket(), SOL_SOCKET, SO_ERROR, (char *)&connectResult, &tmpSize); - if (connectResult != 0) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_FAILED, connectResult); - client.SetState(ClientStateStartSession::Instance()); - retVal = MSG_SOCK_CONNECT_DONE; - } - else if (selectResult == 0) // timeout - { - if (m_connectTimer.elapsed().total_seconds() >= CLIENT_CONNECT_TIMEOUT_SEC) - throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_TIMEOUT, 0); - else - retVal = MSG_SOCK_INTERNAL_PENDING; - } - else - throw ClientException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); - - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateStartSession & -ClientStateStartSession::Instance() -{ - static ClientStateStartSession state; - return state; -} - -ClientStateStartSession::ClientStateStartSession() -{ -} - -ClientStateStartSession::~ClientStateStartSession() -{ -} - -int -ClientStateStartSession::Process(ClientThread &client) -{ - ClientContext &context = client.GetContext(); - - NetPacketInit::Data initData; - initData.password = context.GetPassword(); - initData.playerName = context.GetPlayerName(); - string avatarFile = context.GetAvatarFile(); - initData.showAvatar = false; - if (!avatarFile.empty()) - { - if (client.GetAvatarManager().GetHashForAvatar(avatarFile, initData.avatar)) - initData.showAvatar = true; - } - - boost::shared_ptr packet(new NetPacketInit); - ((NetPacketInit *)packet.get())->SetData(initData); - - client.GetSender().Send(context.GetSessionData(), packet); - - client.SetState(ClientStateWaitSession::Instance()); - - return MSG_SOCK_INTERNAL_PENDING; -} - -//----------------------------------------------------------------------------- - -AbstractClientStateReceiving::AbstractClientStateReceiving() -{ -} - -AbstractClientStateReceiving::~AbstractClientStateReceiving() -{ -} - -int -AbstractClientStateReceiving::Process(ClientThread &client) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - // delegate to receiver helper class - boost::shared_ptr tmpPacket = - client.GetReceiver().Recv(client.GetContext().GetSocket(), client.GetContext().GetReceiveBuffer()); - - if (tmpPacket.get()) - { - if (tmpPacket->ToNetPacketPlayerInfo()) - { - NetPacketPlayerInfo::Data infoData; - tmpPacket->ToNetPacketPlayerInfo()->GetData(infoData); - client.SetPlayerInfo(infoData.playerId, infoData.playerInfo); - } - else if (tmpPacket->ToNetPacketUnknownPlayerId()) - { - NetPacketUnknownPlayerId::Data unknownIdData; - tmpPacket->ToNetPacketUnknownPlayerId()->GetData(unknownIdData); - client.SetUnknownPlayer(unknownIdData.playerId); - } - else if (tmpPacket->ToNetPacketRemovedFromGame()) - { - NetPacketRemovedFromGame::Data removedData; - tmpPacket->ToNetPacketRemovedFromGame()->GetData(removedData); - client.ClearPlayerDataList(); - client.GetCallback().SignalNetClientWaitDialog(); - client.GetCallback().SignalNetClientRemovedFromGame(removedData.removeReason); - client.SetState(ClientStateWaitJoin::Instance()); - } - else if (tmpPacket->ToNetPacketChatText()) - { - // Chat message - display it in the GUI. - NetPacketChatText::Data chatData; - tmpPacket->ToNetPacketChatText()->GetData(chatData); - - boost::shared_ptr tmpPlayer = client.GetPlayerDataByUniqueId(chatData.playerId); - if (tmpPlayer.get()) - client.GetCallback().SignalNetClientChatMsg(tmpPlayer->GetName(), chatData.text); - } - else if (tmpPacket->ToNetPacketPlayerLeft()) - { - // A player left the game. - NetPacketPlayerLeft::Data playerLeftData; - tmpPacket->ToNetPacketPlayerLeft()->GetData(playerLeftData); - - // Signal to GUI and remove from data list. - client.RemovePlayerData(playerLeftData.playerId); - } - else if (tmpPacket->ToNetPacketGameAdminChanged()) - { - // New admin for the game. - NetPacketGameAdminChanged::Data adminChangedData; - tmpPacket->ToNetPacketGameAdminChanged()->GetData(adminChangedData); - - // Set new game admin and signal to GUI. - client.SetNewGameAdmin(adminChangedData.playerId); - } - else if (tmpPacket->ToNetPacketGameListNew()) - { - // A new game was created on the server. - NetPacketGameListNew::Data gameListNewData; - tmpPacket->ToNetPacketGameListNew()->GetData(gameListNewData); - - // Request player info for players if needed. - PlayerIdList::const_iterator i = gameListNewData.gameInfo.players.begin(); - PlayerIdList::const_iterator end = gameListNewData.gameInfo.players.end(); - while (i != end) - { - PlayerInfo info; - if (!client.GetCachedPlayerInfo(*i, info)) - { - // Request player info. - client.RequestPlayerInfo(*i); - } - ++i; - } - - client.AddGameInfo(gameListNewData.gameId, gameListNewData.gameInfo); - } - else if (tmpPacket->ToNetPacketGameListUpdate()) - { - // An existing game was updated on the server. - NetPacketGameListUpdate::Data gameListUpdateData; - tmpPacket->ToNetPacketGameListUpdate()->GetData(gameListUpdateData); - if (gameListUpdateData.gameMode == GAME_MODE_CLOSED) - client.RemoveGameInfo(gameListUpdateData.gameId); - else - client.UpdateGameInfoMode(gameListUpdateData.gameId, gameListUpdateData.gameMode); - } - else if (tmpPacket->ToNetPacketGameListPlayerJoined()) - { - NetPacketGameListPlayerJoined::Data playerJoinedData; - tmpPacket->ToNetPacketGameListPlayerJoined()->GetData(playerJoinedData); - client.ModifyGameInfoAddPlayer(playerJoinedData.gameId, playerJoinedData.playerId); - // Request player info if needed. - PlayerInfo info; - if (!client.GetCachedPlayerInfo(playerJoinedData.playerId, info)) - { - client.RequestPlayerInfo(playerJoinedData.playerId); - } - } - else if (tmpPacket->ToNetPacketGameListPlayerLeft()) - { - NetPacketGameListPlayerLeft::Data playerLeftData; - tmpPacket->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData); - client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId); - } - else if (tmpPacket->ToNetPacketGameListAdminChanged()) - { - NetPacketGameListAdminChanged::Data adminChangedData; - tmpPacket->ToNetPacketGameListAdminChanged()->GetData(adminChangedData); - client.UpdateGameInfoAdmin(adminChangedData.gameId, adminChangedData.newAdminplayerId); - } - else if (tmpPacket->ToNetPacketAvatarHeader()) - { - NetPacketAvatarHeader::Data headerData; - tmpPacket->ToNetPacketAvatarHeader()->GetData(headerData); - client.AddTempAvatarData(headerData.requestId, headerData.avatarFileSize, headerData.avatarFileType); - } - else if (tmpPacket->ToNetPacketAvatarFile()) - { - NetPacketAvatarFile::Data fileData; - tmpPacket->ToNetPacketAvatarFile()->GetData(fileData); - client.StoreInTempAvatarData(fileData.requestId, fileData.fileData); - } - else if (tmpPacket->ToNetPacketAvatarEnd()) - { - NetPacketAvatarEnd::Data endData; - tmpPacket->ToNetPacketAvatarEnd()->GetData(endData); - client.CompleteTempAvatarData(endData.requestId); - } - else if (tmpPacket->ToNetPacketUnknownAvatar()) - { - NetPacketUnknownAvatar::Data unknownAvatarData; - tmpPacket->ToNetPacketUnknownAvatar()->GetData(unknownAvatarData); - client.SetUnknownAvatar(unknownAvatarData.requestId); - } - else if (tmpPacket->ToNetPacketStatisticsChanged()) - { - NetPacketStatisticsChanged::Data statData; - tmpPacket->ToNetPacketStatisticsChanged()->GetData(statData); - client.UpdateStatData(statData.stats); - } - else if (tmpPacket->ToNetPacketError()) - { - // Server reported an error. - NetPacketError::Data errorData; - tmpPacket->ToNetPacketError()->GetData(errorData); - // Show the error. - throw ClientException(__FILE__, __LINE__, errorData.errorCode, 0); - } - else - retVal = InternalProcess(client, tmpPacket); - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateWaitSession & -ClientStateWaitSession::Instance() -{ - static ClientStateWaitSession state; - return state; -} - -ClientStateWaitSession::ClientStateWaitSession() -{ -} - -ClientStateWaitSession::~ClientStateWaitSession() -{ -} - -int -ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - if (packet->ToNetPacketInitAck()) - { - // Everything is fine - we are in the lobby. - NetPacketInitAck::Data initAckData; - packet->ToNetPacketInitAck()->GetData(initAckData); - // Check current game version. - if (initAckData.latestGameVersion != POKERTH_VERSION) - client.GetCallback().SignalNetClientNotification(NTF_NET_NEW_RELEASE_AVAILABLE); - else if (POKERTH_BETA_REVISION && initAckData.latestBetaRevision != POKERTH_BETA_REVISION) - client.GetCallback().SignalNetClientNotification(NTF_NET_OUTDATED_BETA); - - client.SetGuiPlayerId(initAckData.playerId); - - client.SetState(ClientStateWaitJoin::Instance()); - client.SetSessionEstablished(true); - retVal = MSG_SOCK_SESSION_DONE; - } - else if (packet->ToNetPacketRetrieveAvatar()) - { - // Before letting us join the lobby, the server requests our avatar. - NetPacketRetrieveAvatar::Data retrieveAvatarData; - packet->ToNetPacketRetrieveAvatar()->GetData(retrieveAvatarData); - - NetPacketList tmpList; - int avatarError = client.GetAvatarManager().AvatarFileToNetPackets( - client.GetContext().GetAvatarFile(), - retrieveAvatarData.requestId, - tmpList); - - if (!avatarError) - client.GetSender().SendLowPrio(client.GetContext().GetSessionData(), tmpList); - else - throw ClientException(__FILE__, __LINE__, avatarError, 0); - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateWaitJoin & -ClientStateWaitJoin::Instance() -{ - static ClientStateWaitJoin state; - return state; -} - -ClientStateWaitJoin::ClientStateWaitJoin() -{ -} - -ClientStateWaitJoin::~ClientStateWaitJoin() -{ -} - -int -ClientStateWaitJoin::InternalProcess(ClientThread &client, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - ClientContext &context = client.GetContext(); - - if (packet->ToNetPacketJoinGameAck()) - { - // Successfully joined a game. - NetPacketJoinGameAck::Data joinGameAckData; - packet->ToNetPacketJoinGameAck()->GetData(joinGameAckData); - client.SetGameId(joinGameAckData.gameId); - client.SetGameData(joinGameAckData.gameData); - - // Player number is 0 on init. Will be set when the game starts. - boost::shared_ptr playerData( - new PlayerData(client.GetGuiPlayerId(), 0, PLAYER_TYPE_HUMAN, joinGameAckData.prights)); - playerData->SetName(context.GetPlayerName()); - playerData->SetAvatarFile(context.GetAvatarFile()); - client.AddPlayerData(playerData); - - client.SetState(ClientStateWaitGame::Instance()); - retVal = MSG_NET_GAME_CLIENT_JOIN; - } - else if (packet->ToNetPacketJoinGameFailed()) - { - // Failed to join a game. - NetPacketJoinGameFailed::Data joinGameFailedData; - packet->ToNetPacketJoinGameFailed()->GetData(joinGameFailedData); - client.GetCallback().SignalNetClientNotification(joinGameFailedData.failureCode); - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateWaitGame & -ClientStateWaitGame::Instance() -{ - static ClientStateWaitGame state; - return state; -} - -ClientStateWaitGame::ClientStateWaitGame() -{ -} - -ClientStateWaitGame::~ClientStateWaitGame() -{ -} - -int -ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - if (packet->ToNetPacketStartEvent()) - { - client.SetState(ClientStateSynchronizeStart::Instance()); - } - else if (packet->ToNetPacketPlayerJoined()) - { - // Another player joined the network game. - NetPacketPlayerJoined::Data netPlayerData; - packet->ToNetPacketPlayerJoined()->GetData(netPlayerData); - - boost::shared_ptr playerData; - PlayerInfo info; - if (client.GetCachedPlayerInfo(netPlayerData.playerId, info)) - { - playerData.reset( - new PlayerData(netPlayerData.playerId, 0, info.ptype, netPlayerData.prights)); - playerData->SetName(info.playerName); - if (info.hasAvatar) - { - string avatarFile; - if (client.GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) - playerData->SetAvatarFile(avatarFile); - else - client.RetrieveAvatarIfNeeded(netPlayerData.playerId, info); - } - } - else - { - ostringstream name; - name << "#" << netPlayerData.playerId; - - // Request player info. - client.RequestPlayerInfo(netPlayerData.playerId, true); - // Use temporary data until the PlayerInfo request is completed. - playerData.reset( - new PlayerData(netPlayerData.playerId, 0, PLAYER_TYPE_HUMAN, netPlayerData.prights)); - playerData->SetName(name.str()); - } - client.AddPlayerData(playerData); - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateSynchronizeStart & -ClientStateSynchronizeStart::Instance() -{ - static ClientStateSynchronizeStart state; - return state; -} - -ClientStateSynchronizeStart::ClientStateSynchronizeStart() -{ -} - -ClientStateSynchronizeStart::~ClientStateSynchronizeStart() -{ -} - -int -ClientStateSynchronizeStart::Process(ClientThread &client) -{ - int retVal = AbstractClientStateReceiving::Process(client); - - if (client.IsSynchronized()) - { - boost::shared_ptr startAck(new NetPacketStartEventAck); - client.GetSender().Send(client.GetContext().GetSessionData(), startAck); - client.SetState(ClientStateWaitStart::Instance()); - } - - return retVal; -} - -int -ClientStateSynchronizeStart::InternalProcess(ClientThread &/*client*/, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - if (packet->ToNetPacketGameStart()) - throw ClientException(__FILE__, __LINE__, ERR_NET_START_TIMEOUT, 0); - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateWaitStart & -ClientStateWaitStart::Instance() -{ - static ClientStateWaitStart state; - return state; -} - -ClientStateWaitStart::ClientStateWaitStart() -{ -} - -ClientStateWaitStart::~ClientStateWaitStart() -{ -} - -int -ClientStateWaitStart::InternalProcess(ClientThread &client, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - if (packet->ToNetPacketGameStart()) - { - // Start the network game as client. - NetPacketGameStart::Data gameStartData; - packet->ToNetPacketGameStart()->GetData(gameStartData); - - client.SetStartData(gameStartData.startData); - - // Set player numbers using the game start data slots. - NetPacketGameStart::PlayerSlotList::const_iterator slot_i = gameStartData.playerSlots.begin(); - NetPacketGameStart::PlayerSlotList::const_iterator slot_end = gameStartData.playerSlots.end(); - int num = 0; - - while (slot_i != slot_end) - { - unsigned playerId = (*slot_i).playerId; - boost::shared_ptr tmpPlayer = client.GetPlayerDataByUniqueId(playerId); - if (!tmpPlayer.get()) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - tmpPlayer->SetNumber(num); - - ++num; - ++slot_i; - } - - client.SetState(ClientStateWaitHand::Instance()); - retVal = MSG_NET_GAME_CLIENT_START; - } - - return retVal; -} - -//----------------------------------------------------------------------------- - -ClientStateWaitHand & -ClientStateWaitHand::Instance() -{ - static ClientStateWaitHand state; - return state; -} - -ClientStateWaitHand::ClientStateWaitHand() -{ -} - -ClientStateWaitHand::~ClientStateWaitHand() -{ -} - -int -ClientStateWaitHand::InternalProcess(ClientThread &client, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - if (packet->ToNetPacketHandStart()) - { - // Remove all players which left the server. - client.RemoveDisconnectedPlayers(); - // Hand was started. - // These are the cards. Good luck. - NetPacketHandStart::Data tmpData; - packet->ToNetPacketHandStart()->GetData(tmpData); - int myCards[2]; - myCards[0] = (int)tmpData.yourCards[0]; - myCards[1] = (int)tmpData.yourCards[1]; - client.GetGame()->getSeatsList()->front()->setMyCards(myCards); - client.GetGame()->initHand(); - client.GetGame()->getCurrentHand()->setSmallBlind(tmpData.smallBlind); - client.GetGame()->startHand(); - client.GetGui().dealHoleCards(); - client.GetGui().refreshGameLabels(GAME_STATE_PREFLOP); - client.GetGui().refreshPot(); - client.GetGui().waitForGuiUpdateDone(); - - client.SetState(ClientStateRunHand::Instance()); - - retVal = MSG_NET_GAME_CLIENT_HAND_START; - } - else if (packet->ToNetPacketEndOfGame()) - { - boost::shared_ptr curGame = client.GetGame(); - if (curGame.get()) - { - NetPacketEndOfGame::Data endData; - packet->ToNetPacketEndOfGame()->GetData(endData); - boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(endData.winnerPlayerId); - if (!tmpPlayer) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - client.GetGui().logPlayerWinGame(tmpPlayer->getMyName(), curGame->getMyGameID()); - client.GetCallback().SignalNetClientWaitDialog(); - client.SetState(ClientStateWaitGame::Instance()); - retVal = MSG_NET_GAME_CLIENT_END; - } - } - - return MSG_SOCK_INTERNAL_PENDING; -} - -//----------------------------------------------------------------------------- - -ClientStateRunHand & -ClientStateRunHand::Instance() -{ - static ClientStateRunHand state; - return state; -} - -ClientStateRunHand::ClientStateRunHand() -{ -} - -ClientStateRunHand::~ClientStateRunHand() -{ -} - -int -ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INTERNAL_PENDING; - - if (packet.get()) - { - boost::shared_ptr curGame = client.GetGame(); - if (packet->ToNetPacketPlayersActionDone()) - { - NetPacketPlayersActionDone::Data actionDoneData; - packet->ToNetPacketPlayersActionDone()->GetData(actionDoneData); - boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(actionDoneData.playerId); - if (!tmpPlayer) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - - bool isBigBlind = false; - - if (actionDoneData.gameState == GAME_STATE_PREFLOP_SMALL_BLIND) - { - curGame->getCurrentHand()->getCurrentBeRo()->setSmallBlindPositionId(tmpPlayer->getMyUniqueID()); - tmpPlayer->setMyButton(BUTTON_SMALL_BLIND); - } - else if (actionDoneData.gameState == GAME_STATE_PREFLOP_BIG_BLIND) - { - curGame->getCurrentHand()->getCurrentBeRo()->setBigBlindPositionId(tmpPlayer->getMyUniqueID()); - tmpPlayer->setMyButton(BUTTON_BIG_BLIND); - isBigBlind = true; - } - else // no blind -> log - { - if (actionDoneData.playerAction) - { - assert(actionDoneData.totalPlayerBet >= (unsigned)tmpPlayer->getMySet()); - client.GetGui().logPlayerActionMsg( - tmpPlayer->getMyName(), - actionDoneData.playerAction, - actionDoneData.totalPlayerBet - tmpPlayer->getMySet()); - } - // Update last players turn only after the blinds. - curGame->getCurrentHand()->setLastPlayersTurn(tmpPlayer->getMyID()); - } - - tmpPlayer->setMyAction(actionDoneData.playerAction); - tmpPlayer->setMySetAbsolute(actionDoneData.totalPlayerBet); - tmpPlayer->setMyCash(actionDoneData.playerMoney); - curGame->getCurrentHand()->getCurrentBeRo()->setHighestSet(actionDoneData.highestSet); - curGame->getCurrentHand()->getBoard()->collectSets(); - curGame->getCurrentHand()->switchRounds(); - - //log blinds sets after setting bigblind-button - if (isBigBlind) { - client.GetGui().logNewBlindsSetsMsg(curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getSmallBlindPositionId())->getMySet(), curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getBigBlindPositionId())->getMySet(), curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getSmallBlindPositionId())->getMyName(), curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getBigBlindPositionId())->getMyName()); - client.GetGui().flushLogAtHand(); - } - - // Stop the timeout for the player. - client.GetGui().stopTimeoutAnimation(tmpPlayer->getMyID()); - - // Unmark last player in GUI. - client.GetGui().refreshGroupbox(tmpPlayer->getMyID(), 3); - - // Refresh GUI - if (tmpPlayer->getMyID() == 0) - client.GetGui().disableMyButtons(); - client.GetGui().refreshAction(tmpPlayer->getMyID(), tmpPlayer->getMyAction()); - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); - client.GetGui().refreshCash(); - client.GetGui().refreshButton(); - client.GetGui().updateMyButtonsState(); - } - else if (packet->ToNetPacketPlayersTurn()) - { - NetPacketPlayersTurn::Data turnData; - packet->ToNetPacketPlayersTurn()->GetData(turnData); - boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(turnData.playerId); - if (!tmpPlayer) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - - // Set round. - if (curGame->getCurrentHand()->getCurrentRound() != turnData.gameState) - { - ResetPlayerActions(*curGame); - curGame->getCurrentHand()->setCurrentRound(turnData.gameState); - // Refresh actions. - client.GetGui().refreshSet(); - client.GetGui().refreshAction(); - } - - // Next player's turn. - curGame->getCurrentHand()->getCurrentBeRo()->setCurrentPlayersTurnId(tmpPlayer->getMyID()); - curGame->getCurrentHand()->getCurrentBeRo()->setMinimumRaise(turnData.minimumRaise); - curGame->getCurrentHand()->getCurrentBeRo()->setPlayersTurn(tmpPlayer->getMyID()); - - // Mark current player in GUI. - int guiStatus = 2; - if (!tmpPlayer->getMyActiveStatus()) - guiStatus = 0; - else if (tmpPlayer->getMyAction() == PLAYER_ACTION_FOLD) - guiStatus = 1; - client.GetGui().refreshGroupbox(tmpPlayer->getMyID(), guiStatus); - client.GetGui().refreshAction(tmpPlayer->getMyID(), PLAYER_ACTION_NONE); - - // Start displaying the timeout for the player. - client.GetGui().startTimeoutAnimation(tmpPlayer->getMyID(), client.GetGameData().playerActionTimeoutSec); - - if (tmpPlayer->getMyID() == 0) // Is this the GUI player? - client.GetGui().meInAction(); - } - else if (packet->ToNetPacketDealFlopCards()) - { - NetPacketDealFlopCards::Data cardsData; - packet->ToNetPacketDealFlopCards()->GetData(cardsData); - int tmpCards[5]; - for (int num = 0; num < 3; num++) - tmpCards[num] = static_cast(cardsData.flopCards[num]); - tmpCards[3] = tmpCards[4] = 0; - curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); - curGame->getCurrentHand()->getBoard()->collectPot(); - curGame->getCurrentHand()->setLastPlayersTurn(-1); - - client.GetGui().logDealBoardCardsMsg(GAME_STATE_FLOP, tmpCards[0], tmpCards[1], tmpCards[2], tmpCards[3], tmpCards[4]); - client.GetGui().refreshGameLabels(GAME_STATE_FLOP); - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); - client.GetGui().dealBeRoCards(1); - } - else if (packet->ToNetPacketDealTurnCard()) - { - NetPacketDealTurnCard::Data cardsData; - packet->ToNetPacketDealTurnCard()->GetData(cardsData); - int tmpCards[5]; - curGame->getCurrentHand()->getBoard()->getMyCards(tmpCards); - tmpCards[3] = static_cast(cardsData.turnCard); - curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); - curGame->getCurrentHand()->getBoard()->collectPot(); - curGame->getCurrentHand()->setLastPlayersTurn(-1); - - client.GetGui().logDealBoardCardsMsg(GAME_STATE_TURN, tmpCards[0], tmpCards[1], tmpCards[2], tmpCards[3], tmpCards[4]); - client.GetGui().refreshGameLabels(GAME_STATE_TURN); - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); - client.GetGui().dealBeRoCards(2); - } - else if (packet->ToNetPacketDealRiverCard()) - { - NetPacketDealRiverCard::Data cardsData; - packet->ToNetPacketDealRiverCard()->GetData(cardsData); - int tmpCards[5]; - curGame->getCurrentHand()->getBoard()->getMyCards(tmpCards); - tmpCards[4] = static_cast(cardsData.riverCard); - curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); - curGame->getCurrentHand()->getBoard()->collectPot(); - curGame->getCurrentHand()->setLastPlayersTurn(-1); - - client.GetGui().logDealBoardCardsMsg(GAME_STATE_RIVER, tmpCards[0], tmpCards[1], tmpCards[2], tmpCards[3], tmpCards[4]); - client.GetGui().refreshGameLabels(GAME_STATE_RIVER); - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); - client.GetGui().dealBeRoCards(3); - } - else if (packet->ToNetPacketAllInShowCards()) - { - curGame->getCurrentHand()->setAllInCondition(true); - - NetPacketAllInShowCards::Data allInData; - packet->ToNetPacketAllInShowCards()->GetData(allInData); - - NetPacketAllInShowCards::PlayerCardsList::const_iterator i - = allInData.playerCards.begin(); - NetPacketAllInShowCards::PlayerCardsList::const_iterator end - = allInData.playerCards.end(); - - while (i != end) - { - boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId((*i).playerId); - if (!tmpPlayer) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - - int tmpCards[2]; - tmpCards[0] = static_cast((*i).cards[0]); - tmpCards[1] = static_cast((*i).cards[1]); - tmpPlayer->setMyCards(tmpCards); - ++i; - } - client.GetGui().flipHolecardsAllIn(); - } - else if (packet->ToNetPacketEndOfHandHideCards()) - { - curGame->getCurrentHand()->getBoard()->collectPot(); - // Reset player sets - ResetPlayerSets(*curGame); - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); - // Synchronize with GUI. - client.GetGui().waitForGuiUpdateDone(); - - // End of Hand, but keep cards hidden. - NetPacketEndOfHandHideCards::Data endHandData; - packet->ToNetPacketEndOfHandHideCards()->GetData(endHandData); - - boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(endHandData.playerId); - if (!tmpPlayer) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - - tmpPlayer->setMyCash(endHandData.playerMoney); - tmpPlayer->setLastMoneyWon(endHandData.moneyWon); - list winnerList; - winnerList.push_back(tmpPlayer->getMyUniqueID()); - - curGame->getCurrentHand()->getBoard()->setPot(0); - curGame->getCurrentHand()->getBoard()->setWinners(winnerList); - - client.GetGui().postRiverRunAnimation1(); - - // Wait for next Hand. - client.SetState(ClientStateWaitHand::Instance()); - retVal = MSG_NET_GAME_SERVER_HAND_END; - } - else if (packet->ToNetPacketEndOfHandShowCards()) - { - curGame->getCurrentHand()->getBoard()->collectPot(); - // Reset player sets - ResetPlayerSets(*curGame); - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); - // Synchronize with GUI. - client.GetGui().waitForGuiUpdateDone(); - - // End of Hand, show cards. - NetPacketEndOfHandShowCards::Data endHandData; - packet->ToNetPacketEndOfHandShowCards()->GetData(endHandData); - - NetPacketEndOfHandShowCards::PlayerResultList::const_iterator i - = endHandData.playerResults.begin(); - NetPacketEndOfHandShowCards::PlayerResultList::const_iterator end - = endHandData.playerResults.end(); - - list winnerList; - int highestValueOfCards = 0; - while (i != end) - { - boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId((*i).playerId); - if (!tmpPlayer) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); - - int tmpCards[2]; - int bestHandPos[5]; - tmpCards[0] = static_cast((*i).cards[0]); - tmpCards[1] = static_cast((*i).cards[1]); - tmpPlayer->setMyCards(tmpCards); - for (int num = 0; num < 5; num++) - bestHandPos[num] = (*i).bestHandPos[num]; - tmpPlayer->setMyCardsValueInt((*i).valueOfCards); - tmpPlayer->setMyBestHandPosition(bestHandPos); - if (tmpPlayer->getMyCardsValueInt() > highestValueOfCards) - highestValueOfCards = tmpPlayer->getMyCardsValueInt(); - tmpPlayer->setMyCash((*i).playerMoney); - tmpPlayer->setLastMoneyWon((*i).moneyWon); - if ((*i).moneyWon) - winnerList.push_back((*i).playerId); - - ++i; - } - curGame->getCurrentHand()->getCurrentBeRo()->setHighestCardsValue(highestValueOfCards); - curGame->getCurrentHand()->getBoard()->setPot(0); - curGame->getCurrentHand()->getBoard()->setWinners(winnerList); - - client.GetGui().postRiverRunAnimation1(); - - // Wait for next Hand. - client.SetState(ClientStateWaitHand::Instance()); - retVal = MSG_NET_GAME_CLIENT_HAND_END; - } - } - - // Synchronize with GUI. - client.GetGui().waitForGuiUpdateDone(); - - return retVal; -} - -void -ClientStateRunHand::ResetPlayerActions(Game &curGame) -{ - // Reset player actions - PlayerListIterator i = curGame.getSeatsList()->begin(); - PlayerListIterator end = curGame.getSeatsList()->end(); - - while (i != end) - { - int action = (*i)->getMyAction(); - if (action != 1 && action != 6) - (*i)->setMyAction(0); - (*i)->setMySetNull(); - ++i; - } -} - -void -ClientStateRunHand::ResetPlayerSets(Game &curGame) -{ - PlayerListIterator i = curGame.getSeatsList()->begin(); - PlayerListIterator end = curGame.getSeatsList()->end(); - while (i != end) - { - (*i)->setMySetNull(); - ++i; - } -} - -//----------------------------------------------------------------------------- - -ClientStateFinal & -ClientStateFinal::Instance() -{ - static ClientStateFinal state; - return state; -} - -ClientStateFinal::ClientStateFinal() -{ -} - -ClientStateFinal::~ClientStateFinal() -{ -} - -int -ClientStateFinal::Process(ClientThread &/*client*/) -{ - Thread::Msleep(10); - - return MSG_SOCK_INTERNAL_PENDING; -} +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +using namespace std; + +#define CLIENT_WAIT_TIMEOUT_MSEC 50 +#define CLIENT_CONNECT_TIMEOUT_SEC 10 + + +ClientState::~ClientState() +{ +} + +//----------------------------------------------------------------------------- + +ClientStateInit & +ClientStateInit::Instance() +{ + static ClientStateInit state; + return state; +} + +ClientStateInit::ClientStateInit() +{ +} + +ClientStateInit::~ClientStateInit() +{ +} + +int +ClientStateInit::Process(ClientThread &client) +{ + ClientContext &context = client.GetContext(); + + if (context.GetServerAddr().empty()) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_SERVERADDR_NOT_SET, 0); + + if (context.GetServerPort() < 1024) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0); + + context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol())); + if (!IS_VALID_SOCKET(context.GetSocket())) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); + + unsigned long mode = 1; + if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); + + // The following call is optional - the return value is not checked. + int nodelay = 1; + setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); + + client.SetState(ClientStateStartResolve::Instance()); + + return MSG_SOCK_INIT_DONE; +} + +//----------------------------------------------------------------------------- + +ClientStateStartResolve & +ClientStateStartResolve::Instance() +{ + static ClientStateStartResolve state; + return state; +} + +ClientStateStartResolve::ClientStateStartResolve() +{ +} + +ClientStateStartResolve::~ClientStateStartResolve() +{ +} + +int +ClientStateStartResolve::Process(ClientThread &client) +{ + int retVal; + + ClientContext &context = client.GetContext(); + + context.GetClientSockaddr()->ss_family = context.GetAddrFamily(); + + // Treat the server address as numbers first. + if (socket_string_to_addr( + context.GetServerAddr().c_str(), + context.GetAddrFamily(), + (struct sockaddr *)context.GetClientSockaddr(), + context.GetClientSockaddrSize())) + { + // Success - but we still need to set the port. + if (!socket_set_port(context.GetServerPort(), context.GetAddrFamily(), (struct sockaddr *)context.GetClientSockaddr(), context.GetClientSockaddrSize())) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_SET_PORT_FAILED, 0); + + // No need to resolve - start connecting. + client.SetState(ClientStateStartConnect::Instance()); + retVal = MSG_SOCK_RESOLVE_DONE; + } + else + { + // Start name resolution in a separate thread, since it is blocking + // for up to about 30 seconds. + std::auto_ptr resolver(new ResolverThread); + resolver->Init(context); + resolver->Run(); + + ClientStateResolving::Instance().SetResolver(resolver.release()); + client.SetState(ClientStateResolving::Instance()); + + retVal = MSG_SOCK_INTERNAL_PENDING; + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateResolving & +ClientStateResolving::Instance() +{ + static ClientStateResolving state; + return state; +} + +ClientStateResolving::ClientStateResolving() +: m_resolver(NULL) +{ +} + +ClientStateResolving::~ClientStateResolving() +{ + Cleanup(); +} + +void +ClientStateResolving::SetResolver(ResolverThread *resolver) +{ + Cleanup(); + m_resolver = resolver; +} + +int +ClientStateResolving::Process(ClientThread &client) +{ + int retVal; + + if (!m_resolver) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_RESOLVE_FAILED, 0); + + if (m_resolver->Join(CLIENT_WAIT_TIMEOUT_MSEC)) + { + ClientContext &context = client.GetContext(); + bool success = m_resolver->GetResult(context); + Cleanup(); // Not required, but better keep things clean. + + if (!success) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_RESOLVE_FAILED, 0); + + client.SetState(ClientStateStartConnect::Instance()); + retVal = MSG_SOCK_RESOLVE_DONE; + } + else + retVal = MSG_SOCK_INTERNAL_PENDING; + + return retVal; +} + + +void +ClientStateResolving::Cleanup() +{ + if (m_resolver) + { + if (m_resolver->Join(500)) + delete m_resolver; + // If the resolver does not terminate fast enough, leave it + // as memory leak. + m_resolver = NULL; + } +} + +//----------------------------------------------------------------------------- + +ClientStateStartConnect & +ClientStateStartConnect::Instance() +{ + static ClientStateStartConnect state; + return state; +} + +ClientStateStartConnect::ClientStateStartConnect() +{ +} + +ClientStateStartConnect::~ClientStateStartConnect() +{ +} + +int +ClientStateStartConnect::Process(ClientThread &client) +{ + int retVal; + ClientContext &context = client.GetContext(); + + int connectResult = connect(context.GetSocket(), (struct sockaddr *)context.GetClientSockaddr(), context.GetClientSockaddrSize()); + + if (IS_VALID_CONNECT(connectResult)) + { + client.SetState(ClientStateStartSession::Instance()); + retVal = MSG_SOCK_CONNECT_DONE; + } + else + { + int errCode = SOCKET_ERRNO(); + if (IS_SOCKET_ERR_WOULDBLOCK(errCode)) + { + boost::timers::portable::microsec_timer connectTimer; + ClientStateConnecting::Instance().SetTimer(connectTimer); + client.SetState(ClientStateConnecting::Instance()); + retVal = MSG_SOCK_INTERNAL_PENDING; + } + else + throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_FAILED, SOCKET_ERRNO()); + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateConnecting & +ClientStateConnecting::Instance() +{ + static ClientStateConnecting state; + return state; +} + +ClientStateConnecting::ClientStateConnecting() +{ +} + +ClientStateConnecting::~ClientStateConnecting() +{ +} + +void +ClientStateConnecting::SetTimer(const boost::timers::portable::microsec_timer &timer) +{ + m_connectTimer = timer; +} + +int +ClientStateConnecting::Process(ClientThread &client) +{ + int retVal; + ClientContext &context = client.GetContext(); + + fd_set writeSet; + struct timeval timeout; + + FD_ZERO(&writeSet); + FD_SET(context.GetSocket(), &writeSet); + + timeout.tv_sec = 0; + timeout.tv_usec = CLIENT_WAIT_TIMEOUT_MSEC * 1000; + int selectResult = select(context.GetSocket() + 1, NULL, &writeSet, NULL, &timeout); + + if (selectResult > 0) // success + { + // Check whether the connect call succeeded. + int connectResult = 0; + socklen_t tmpSize = sizeof(connectResult); + getsockopt(context.GetSocket(), SOL_SOCKET, SO_ERROR, (char *)&connectResult, &tmpSize); + if (connectResult != 0) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_FAILED, connectResult); + client.SetState(ClientStateStartSession::Instance()); + retVal = MSG_SOCK_CONNECT_DONE; + } + else if (selectResult == 0) // timeout + { + if (m_connectTimer.elapsed().total_seconds() >= CLIENT_CONNECT_TIMEOUT_SEC) + throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_TIMEOUT, 0); + else + retVal = MSG_SOCK_INTERNAL_PENDING; + } + else + throw ClientException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); + + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateStartSession & +ClientStateStartSession::Instance() +{ + static ClientStateStartSession state; + return state; +} + +ClientStateStartSession::ClientStateStartSession() +{ +} + +ClientStateStartSession::~ClientStateStartSession() +{ +} + +int +ClientStateStartSession::Process(ClientThread &client) +{ + ClientContext &context = client.GetContext(); + + NetPacketInit::Data initData; + initData.password = context.GetPassword(); + initData.playerName = context.GetPlayerName(); + string avatarFile = context.GetAvatarFile(); + initData.showAvatar = false; + if (!avatarFile.empty()) + { + if (client.GetAvatarManager().GetHashForAvatar(avatarFile, initData.avatar)) + initData.showAvatar = true; + } + + boost::shared_ptr packet(new NetPacketInit); + ((NetPacketInit *)packet.get())->SetData(initData); + + client.GetSender().Send(context.GetSessionData(), packet); + + client.SetState(ClientStateWaitSession::Instance()); + + return MSG_SOCK_INTERNAL_PENDING; +} + +//----------------------------------------------------------------------------- + +AbstractClientStateReceiving::AbstractClientStateReceiving() +{ +} + +AbstractClientStateReceiving::~AbstractClientStateReceiving() +{ +} + +int +AbstractClientStateReceiving::Process(ClientThread &client) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + // delegate to receiver helper class + boost::shared_ptr tmpPacket = + client.GetReceiver().Recv(client.GetContext().GetSocket(), client.GetContext().GetReceiveBuffer()); + + if (tmpPacket.get()) + { + if (tmpPacket->ToNetPacketPlayerInfo()) + { + NetPacketPlayerInfo::Data infoData; + tmpPacket->ToNetPacketPlayerInfo()->GetData(infoData); + client.SetPlayerInfo(infoData.playerId, infoData.playerInfo); + } + else if (tmpPacket->ToNetPacketUnknownPlayerId()) + { + NetPacketUnknownPlayerId::Data unknownIdData; + tmpPacket->ToNetPacketUnknownPlayerId()->GetData(unknownIdData); + client.SetUnknownPlayer(unknownIdData.playerId); + } + else if (tmpPacket->ToNetPacketRemovedFromGame()) + { + NetPacketRemovedFromGame::Data removedData; + tmpPacket->ToNetPacketRemovedFromGame()->GetData(removedData); + client.ClearPlayerDataList(); + client.GetCallback().SignalNetClientWaitDialog(); + client.GetCallback().SignalNetClientRemovedFromGame(removedData.removeReason); + client.SetState(ClientStateWaitJoin::Instance()); + } + else if (tmpPacket->ToNetPacketChatText()) + { + // Chat message - display it in the GUI. + NetPacketChatText::Data chatData; + tmpPacket->ToNetPacketChatText()->GetData(chatData); + + boost::shared_ptr tmpPlayer = client.GetPlayerDataByUniqueId(chatData.playerId); + if (tmpPlayer.get()) + client.GetCallback().SignalNetClientChatMsg(tmpPlayer->GetName(), chatData.text); + } + else if (tmpPacket->ToNetPacketPlayerLeft()) + { + // A player left the game. + NetPacketPlayerLeft::Data playerLeftData; + tmpPacket->ToNetPacketPlayerLeft()->GetData(playerLeftData); + + // Signal to GUI and remove from data list. + client.RemovePlayerData(playerLeftData.playerId); + } + else if (tmpPacket->ToNetPacketGameAdminChanged()) + { + // New admin for the game. + NetPacketGameAdminChanged::Data adminChangedData; + tmpPacket->ToNetPacketGameAdminChanged()->GetData(adminChangedData); + + // Set new game admin and signal to GUI. + client.SetNewGameAdmin(adminChangedData.playerId); + } + else if (tmpPacket->ToNetPacketGameListNew()) + { + // A new game was created on the server. + NetPacketGameListNew::Data gameListNewData; + tmpPacket->ToNetPacketGameListNew()->GetData(gameListNewData); + + // Request player info for players if needed. + PlayerIdList::const_iterator i = gameListNewData.gameInfo.players.begin(); + PlayerIdList::const_iterator end = gameListNewData.gameInfo.players.end(); + while (i != end) + { + PlayerInfo info; + if (!client.GetCachedPlayerInfo(*i, info)) + { + // Request player info. + client.RequestPlayerInfo(*i); + } + ++i; + } + + client.AddGameInfo(gameListNewData.gameId, gameListNewData.gameInfo); + } + else if (tmpPacket->ToNetPacketGameListUpdate()) + { + // An existing game was updated on the server. + NetPacketGameListUpdate::Data gameListUpdateData; + tmpPacket->ToNetPacketGameListUpdate()->GetData(gameListUpdateData); + if (gameListUpdateData.gameMode == GAME_MODE_CLOSED) + client.RemoveGameInfo(gameListUpdateData.gameId); + else + client.UpdateGameInfoMode(gameListUpdateData.gameId, gameListUpdateData.gameMode); + } + else if (tmpPacket->ToNetPacketGameListPlayerJoined()) + { + NetPacketGameListPlayerJoined::Data playerJoinedData; + tmpPacket->ToNetPacketGameListPlayerJoined()->GetData(playerJoinedData); + client.ModifyGameInfoAddPlayer(playerJoinedData.gameId, playerJoinedData.playerId); + // Request player info if needed. + PlayerInfo info; + if (!client.GetCachedPlayerInfo(playerJoinedData.playerId, info)) + { + client.RequestPlayerInfo(playerJoinedData.playerId); + } + } + else if (tmpPacket->ToNetPacketGameListPlayerLeft()) + { + NetPacketGameListPlayerLeft::Data playerLeftData; + tmpPacket->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData); + client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId); + } + else if (tmpPacket->ToNetPacketGameListAdminChanged()) + { + NetPacketGameListAdminChanged::Data adminChangedData; + tmpPacket->ToNetPacketGameListAdminChanged()->GetData(adminChangedData); + client.UpdateGameInfoAdmin(adminChangedData.gameId, adminChangedData.newAdminplayerId); + } + else if (tmpPacket->ToNetPacketAvatarHeader()) + { + NetPacketAvatarHeader::Data headerData; + tmpPacket->ToNetPacketAvatarHeader()->GetData(headerData); + client.AddTempAvatarData(headerData.requestId, headerData.avatarFileSize, headerData.avatarFileType); + } + else if (tmpPacket->ToNetPacketAvatarFile()) + { + NetPacketAvatarFile::Data fileData; + tmpPacket->ToNetPacketAvatarFile()->GetData(fileData); + client.StoreInTempAvatarData(fileData.requestId, fileData.fileData); + } + else if (tmpPacket->ToNetPacketAvatarEnd()) + { + NetPacketAvatarEnd::Data endData; + tmpPacket->ToNetPacketAvatarEnd()->GetData(endData); + client.CompleteTempAvatarData(endData.requestId); + } + else if (tmpPacket->ToNetPacketUnknownAvatar()) + { + NetPacketUnknownAvatar::Data unknownAvatarData; + tmpPacket->ToNetPacketUnknownAvatar()->GetData(unknownAvatarData); + client.SetUnknownAvatar(unknownAvatarData.requestId); + } + else if (tmpPacket->ToNetPacketStatisticsChanged()) + { + NetPacketStatisticsChanged::Data statData; + tmpPacket->ToNetPacketStatisticsChanged()->GetData(statData); + client.UpdateStatData(statData.stats); + } + else if (tmpPacket->ToNetPacketError()) + { + // Server reported an error. + NetPacketError::Data errorData; + tmpPacket->ToNetPacketError()->GetData(errorData); + // Show the error. + throw ClientException(__FILE__, __LINE__, errorData.errorCode, 0); + } + else + retVal = InternalProcess(client, tmpPacket); + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateWaitSession & +ClientStateWaitSession::Instance() +{ + static ClientStateWaitSession state; + return state; +} + +ClientStateWaitSession::ClientStateWaitSession() +{ +} + +ClientStateWaitSession::~ClientStateWaitSession() +{ +} + +int +ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + if (packet->ToNetPacketInitAck()) + { + // Everything is fine - we are in the lobby. + NetPacketInitAck::Data initAckData; + packet->ToNetPacketInitAck()->GetData(initAckData); + // Check current game version. + if (initAckData.latestGameVersion != POKERTH_VERSION) + client.GetCallback().SignalNetClientNotification(NTF_NET_NEW_RELEASE_AVAILABLE); + else if (POKERTH_BETA_REVISION && initAckData.latestBetaRevision != POKERTH_BETA_REVISION) + client.GetCallback().SignalNetClientNotification(NTF_NET_OUTDATED_BETA); + + client.SetGuiPlayerId(initAckData.playerId); + + client.SetState(ClientStateWaitJoin::Instance()); + client.SetSessionEstablished(true); + retVal = MSG_SOCK_SESSION_DONE; + } + else if (packet->ToNetPacketRetrieveAvatar()) + { + // Before letting us join the lobby, the server requests our avatar. + NetPacketRetrieveAvatar::Data retrieveAvatarData; + packet->ToNetPacketRetrieveAvatar()->GetData(retrieveAvatarData); + + NetPacketList tmpList; + int avatarError = client.GetAvatarManager().AvatarFileToNetPackets( + client.GetContext().GetAvatarFile(), + retrieveAvatarData.requestId, + tmpList); + + if (!avatarError) + client.GetSender().SendLowPrio(client.GetContext().GetSessionData(), tmpList); + else + throw ClientException(__FILE__, __LINE__, avatarError, 0); + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateWaitJoin & +ClientStateWaitJoin::Instance() +{ + static ClientStateWaitJoin state; + return state; +} + +ClientStateWaitJoin::ClientStateWaitJoin() +{ +} + +ClientStateWaitJoin::~ClientStateWaitJoin() +{ +} + +int +ClientStateWaitJoin::InternalProcess(ClientThread &client, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + ClientContext &context = client.GetContext(); + + if (packet->ToNetPacketJoinGameAck()) + { + // Successfully joined a game. + NetPacketJoinGameAck::Data joinGameAckData; + packet->ToNetPacketJoinGameAck()->GetData(joinGameAckData); + client.SetGameId(joinGameAckData.gameId); + client.SetGameData(joinGameAckData.gameData); + + // Player number is 0 on init. Will be set when the game starts. + boost::shared_ptr playerData( + new PlayerData(client.GetGuiPlayerId(), 0, PLAYER_TYPE_HUMAN, joinGameAckData.prights)); + playerData->SetName(context.GetPlayerName()); + playerData->SetAvatarFile(context.GetAvatarFile()); + client.AddPlayerData(playerData); + + client.SetState(ClientStateWaitGame::Instance()); + retVal = MSG_NET_GAME_CLIENT_JOIN; + } + else if (packet->ToNetPacketJoinGameFailed()) + { + // Failed to join a game. + NetPacketJoinGameFailed::Data joinGameFailedData; + packet->ToNetPacketJoinGameFailed()->GetData(joinGameFailedData); + client.GetCallback().SignalNetClientNotification(joinGameFailedData.failureCode); + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateWaitGame & +ClientStateWaitGame::Instance() +{ + static ClientStateWaitGame state; + return state; +} + +ClientStateWaitGame::ClientStateWaitGame() +{ +} + +ClientStateWaitGame::~ClientStateWaitGame() +{ +} + +int +ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + if (packet->ToNetPacketStartEvent()) + { + client.SetState(ClientStateSynchronizeStart::Instance()); + } + else if (packet->ToNetPacketPlayerJoined()) + { + // Another player joined the network game. + NetPacketPlayerJoined::Data netPlayerData; + packet->ToNetPacketPlayerJoined()->GetData(netPlayerData); + + boost::shared_ptr playerData; + PlayerInfo info; + if (client.GetCachedPlayerInfo(netPlayerData.playerId, info)) + { + playerData.reset( + new PlayerData(netPlayerData.playerId, 0, info.ptype, netPlayerData.prights)); + playerData->SetName(info.playerName); + if (info.hasAvatar) + { + string avatarFile; + if (client.GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) + playerData->SetAvatarFile(avatarFile); + else + client.RetrieveAvatarIfNeeded(netPlayerData.playerId, info); + } + } + else + { + ostringstream name; + name << "#" << netPlayerData.playerId; + + // Request player info. + client.RequestPlayerInfo(netPlayerData.playerId, true); + // Use temporary data until the PlayerInfo request is completed. + playerData.reset( + new PlayerData(netPlayerData.playerId, 0, PLAYER_TYPE_HUMAN, netPlayerData.prights)); + playerData->SetName(name.str()); + } + client.AddPlayerData(playerData); + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateSynchronizeStart & +ClientStateSynchronizeStart::Instance() +{ + static ClientStateSynchronizeStart state; + return state; +} + +ClientStateSynchronizeStart::ClientStateSynchronizeStart() +{ +} + +ClientStateSynchronizeStart::~ClientStateSynchronizeStart() +{ +} + +int +ClientStateSynchronizeStart::Process(ClientThread &client) +{ + int retVal = AbstractClientStateReceiving::Process(client); + + if (client.IsSynchronized()) + { + boost::shared_ptr startAck(new NetPacketStartEventAck); + client.GetSender().Send(client.GetContext().GetSessionData(), startAck); + client.SetState(ClientStateWaitStart::Instance()); + } + + return retVal; +} + +int +ClientStateSynchronizeStart::InternalProcess(ClientThread &/*client*/, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + if (packet->ToNetPacketGameStart()) + throw ClientException(__FILE__, __LINE__, ERR_NET_START_TIMEOUT, 0); + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateWaitStart & +ClientStateWaitStart::Instance() +{ + static ClientStateWaitStart state; + return state; +} + +ClientStateWaitStart::ClientStateWaitStart() +{ +} + +ClientStateWaitStart::~ClientStateWaitStart() +{ +} + +int +ClientStateWaitStart::InternalProcess(ClientThread &client, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + if (packet->ToNetPacketGameStart()) + { + // Start the network game as client. + NetPacketGameStart::Data gameStartData; + packet->ToNetPacketGameStart()->GetData(gameStartData); + + client.SetStartData(gameStartData.startData); + + // Set player numbers using the game start data slots. + NetPacketGameStart::PlayerSlotList::const_iterator slot_i = gameStartData.playerSlots.begin(); + NetPacketGameStart::PlayerSlotList::const_iterator slot_end = gameStartData.playerSlots.end(); + int num = 0; + + while (slot_i != slot_end) + { + unsigned playerId = (*slot_i).playerId; + boost::shared_ptr tmpPlayer = client.GetPlayerDataByUniqueId(playerId); + if (!tmpPlayer.get()) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + tmpPlayer->SetNumber(num); + + ++num; + ++slot_i; + } + + client.SetState(ClientStateWaitHand::Instance()); + retVal = MSG_NET_GAME_CLIENT_START; + } + + return retVal; +} + +//----------------------------------------------------------------------------- + +ClientStateWaitHand & +ClientStateWaitHand::Instance() +{ + static ClientStateWaitHand state; + return state; +} + +ClientStateWaitHand::ClientStateWaitHand() +{ +} + +ClientStateWaitHand::~ClientStateWaitHand() +{ +} + +int +ClientStateWaitHand::InternalProcess(ClientThread &client, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + if (packet->ToNetPacketHandStart()) + { + // Remove all players which left the server. + client.RemoveDisconnectedPlayers(); + // Hand was started. + // These are the cards. Good luck. + NetPacketHandStart::Data tmpData; + packet->ToNetPacketHandStart()->GetData(tmpData); + int myCards[2]; + myCards[0] = (int)tmpData.yourCards[0]; + myCards[1] = (int)tmpData.yourCards[1]; + client.GetGame()->getSeatsList()->front()->setMyCards(myCards); + client.GetGame()->initHand(); + client.GetGame()->getCurrentHand()->setSmallBlind(tmpData.smallBlind); + client.GetGame()->startHand(); + client.GetGui().dealHoleCards(); + client.GetGui().refreshGameLabels(GAME_STATE_PREFLOP); + client.GetGui().refreshPot(); + client.GetGui().waitForGuiUpdateDone(); + + client.SetState(ClientStateRunHand::Instance()); + + retVal = MSG_NET_GAME_CLIENT_HAND_START; + } + else if (packet->ToNetPacketEndOfGame()) + { + boost::shared_ptr curGame = client.GetGame(); + if (curGame.get()) + { + NetPacketEndOfGame::Data endData; + packet->ToNetPacketEndOfGame()->GetData(endData); + boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(endData.winnerPlayerId); + if (!tmpPlayer) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + client.GetGui().logPlayerWinGame(tmpPlayer->getMyName(), curGame->getMyGameID()); + client.GetCallback().SignalNetClientWaitDialog(); + client.SetState(ClientStateWaitGame::Instance()); + retVal = MSG_NET_GAME_CLIENT_END; + } + } + + return MSG_SOCK_INTERNAL_PENDING; +} + +//----------------------------------------------------------------------------- + +ClientStateRunHand & +ClientStateRunHand::Instance() +{ + static ClientStateRunHand state; + return state; +} + +ClientStateRunHand::ClientStateRunHand() +{ +} + +ClientStateRunHand::~ClientStateRunHand() +{ +} + +int +ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INTERNAL_PENDING; + + if (packet.get()) + { + boost::shared_ptr curGame = client.GetGame(); + if (packet->ToNetPacketPlayersActionDone()) + { + NetPacketPlayersActionDone::Data actionDoneData; + packet->ToNetPacketPlayersActionDone()->GetData(actionDoneData); + boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(actionDoneData.playerId); + if (!tmpPlayer) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + + bool isBigBlind = false; + + if (actionDoneData.gameState == GAME_STATE_PREFLOP_SMALL_BLIND) + { + curGame->getCurrentHand()->getCurrentBeRo()->setSmallBlindPositionId(tmpPlayer->getMyUniqueID()); + tmpPlayer->setMyButton(BUTTON_SMALL_BLIND); + } + else if (actionDoneData.gameState == GAME_STATE_PREFLOP_BIG_BLIND) + { + curGame->getCurrentHand()->getCurrentBeRo()->setBigBlindPositionId(tmpPlayer->getMyUniqueID()); + tmpPlayer->setMyButton(BUTTON_BIG_BLIND); + isBigBlind = true; + } + else // no blind -> log + { + if (actionDoneData.playerAction) + { + assert(actionDoneData.totalPlayerBet >= (unsigned)tmpPlayer->getMySet()); + client.GetGui().logPlayerActionMsg( + tmpPlayer->getMyName(), + actionDoneData.playerAction, + actionDoneData.totalPlayerBet - tmpPlayer->getMySet()); + } + // Update last players turn only after the blinds. + curGame->getCurrentHand()->setLastPlayersTurn(tmpPlayer->getMyID()); + } + + tmpPlayer->setMyAction(actionDoneData.playerAction); + tmpPlayer->setMySetAbsolute(actionDoneData.totalPlayerBet); + tmpPlayer->setMyCash(actionDoneData.playerMoney); + curGame->getCurrentHand()->getCurrentBeRo()->setHighestSet(actionDoneData.highestSet); + curGame->getCurrentHand()->getBoard()->collectSets(); + curGame->getCurrentHand()->switchRounds(); + + //log blinds sets after setting bigblind-button + if (isBigBlind) { + client.GetGui().logNewBlindsSetsMsg(curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getSmallBlindPositionId())->getMySet(), curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getBigBlindPositionId())->getMySet(), curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getSmallBlindPositionId())->getMyName(), curGame->getPlayerByUniqueId(curGame->getCurrentHand()->getCurrentBeRo()->getBigBlindPositionId())->getMyName()); + client.GetGui().flushLogAtHand(); + } + + // Stop the timeout for the player. + client.GetGui().stopTimeoutAnimation(tmpPlayer->getMyID()); + + // Unmark last player in GUI. + client.GetGui().refreshGroupbox(tmpPlayer->getMyID(), 3); + + // Refresh GUI + if (tmpPlayer->getMyID() == 0) + client.GetGui().disableMyButtons(); + client.GetGui().refreshAction(tmpPlayer->getMyID(), tmpPlayer->getMyAction()); + client.GetGui().refreshPot(); + client.GetGui().refreshSet(); + client.GetGui().refreshCash(); + client.GetGui().refreshButton(); + client.GetGui().updateMyButtonsState(); + } + else if (packet->ToNetPacketPlayersTurn()) + { + NetPacketPlayersTurn::Data turnData; + packet->ToNetPacketPlayersTurn()->GetData(turnData); + boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(turnData.playerId); + if (!tmpPlayer) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + + // Set round. + if (curGame->getCurrentHand()->getCurrentRound() != turnData.gameState) + { + ResetPlayerActions(*curGame); + curGame->getCurrentHand()->setCurrentRound(turnData.gameState); + // Refresh actions. + client.GetGui().refreshSet(); + client.GetGui().refreshAction(); + } + + // Next player's turn. + curGame->getCurrentHand()->getCurrentBeRo()->setCurrentPlayersTurnId(tmpPlayer->getMyID()); + curGame->getCurrentHand()->getCurrentBeRo()->setMinimumRaise(turnData.minimumRaise); + curGame->getCurrentHand()->getCurrentBeRo()->setPlayersTurn(tmpPlayer->getMyID()); + + // Mark current player in GUI. + int guiStatus = 2; + if (!tmpPlayer->getMyActiveStatus()) + guiStatus = 0; + else if (tmpPlayer->getMyAction() == PLAYER_ACTION_FOLD) + guiStatus = 1; + client.GetGui().refreshGroupbox(tmpPlayer->getMyID(), guiStatus); + client.GetGui().refreshAction(tmpPlayer->getMyID(), PLAYER_ACTION_NONE); + + // Start displaying the timeout for the player. + client.GetGui().startTimeoutAnimation(tmpPlayer->getMyID(), client.GetGameData().playerActionTimeoutSec); + + if (tmpPlayer->getMyID() == 0) // Is this the GUI player? + client.GetGui().meInAction(); + } + else if (packet->ToNetPacketDealFlopCards()) + { + NetPacketDealFlopCards::Data cardsData; + packet->ToNetPacketDealFlopCards()->GetData(cardsData); + int tmpCards[5]; + for (int num = 0; num < 3; num++) + tmpCards[num] = static_cast(cardsData.flopCards[num]); + tmpCards[3] = tmpCards[4] = 0; + curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); + curGame->getCurrentHand()->getBoard()->collectPot(); + curGame->getCurrentHand()->setLastPlayersTurn(-1); + + client.GetGui().logDealBoardCardsMsg(GAME_STATE_FLOP, tmpCards[0], tmpCards[1], tmpCards[2], tmpCards[3], tmpCards[4]); + client.GetGui().refreshGameLabels(GAME_STATE_FLOP); + client.GetGui().refreshPot(); + client.GetGui().refreshSet(); + client.GetGui().dealBeRoCards(1); + } + else if (packet->ToNetPacketDealTurnCard()) + { + NetPacketDealTurnCard::Data cardsData; + packet->ToNetPacketDealTurnCard()->GetData(cardsData); + int tmpCards[5]; + curGame->getCurrentHand()->getBoard()->getMyCards(tmpCards); + tmpCards[3] = static_cast(cardsData.turnCard); + curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); + curGame->getCurrentHand()->getBoard()->collectPot(); + curGame->getCurrentHand()->setLastPlayersTurn(-1); + + client.GetGui().logDealBoardCardsMsg(GAME_STATE_TURN, tmpCards[0], tmpCards[1], tmpCards[2], tmpCards[3], tmpCards[4]); + client.GetGui().refreshGameLabels(GAME_STATE_TURN); + client.GetGui().refreshPot(); + client.GetGui().refreshSet(); + client.GetGui().dealBeRoCards(2); + } + else if (packet->ToNetPacketDealRiverCard()) + { + NetPacketDealRiverCard::Data cardsData; + packet->ToNetPacketDealRiverCard()->GetData(cardsData); + int tmpCards[5]; + curGame->getCurrentHand()->getBoard()->getMyCards(tmpCards); + tmpCards[4] = static_cast(cardsData.riverCard); + curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); + curGame->getCurrentHand()->getBoard()->collectPot(); + curGame->getCurrentHand()->setLastPlayersTurn(-1); + + client.GetGui().logDealBoardCardsMsg(GAME_STATE_RIVER, tmpCards[0], tmpCards[1], tmpCards[2], tmpCards[3], tmpCards[4]); + client.GetGui().refreshGameLabels(GAME_STATE_RIVER); + client.GetGui().refreshPot(); + client.GetGui().refreshSet(); + client.GetGui().dealBeRoCards(3); + } + else if (packet->ToNetPacketAllInShowCards()) + { + curGame->getCurrentHand()->setAllInCondition(true); + + NetPacketAllInShowCards::Data allInData; + packet->ToNetPacketAllInShowCards()->GetData(allInData); + + NetPacketAllInShowCards::PlayerCardsList::const_iterator i + = allInData.playerCards.begin(); + NetPacketAllInShowCards::PlayerCardsList::const_iterator end + = allInData.playerCards.end(); + + while (i != end) + { + boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId((*i).playerId); + if (!tmpPlayer) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + + int tmpCards[2]; + tmpCards[0] = static_cast((*i).cards[0]); + tmpCards[1] = static_cast((*i).cards[1]); + tmpPlayer->setMyCards(tmpCards); + ++i; + } + client.GetGui().flipHolecardsAllIn(); + } + else if (packet->ToNetPacketEndOfHandHideCards()) + { + curGame->getCurrentHand()->getBoard()->collectPot(); + // Reset player sets + ResetPlayerSets(*curGame); + client.GetGui().refreshPot(); + client.GetGui().refreshSet(); + // Synchronize with GUI. + client.GetGui().waitForGuiUpdateDone(); + + // End of Hand, but keep cards hidden. + NetPacketEndOfHandHideCards::Data endHandData; + packet->ToNetPacketEndOfHandHideCards()->GetData(endHandData); + + boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId(endHandData.playerId); + if (!tmpPlayer) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + + tmpPlayer->setMyCash(endHandData.playerMoney); + tmpPlayer->setLastMoneyWon(endHandData.moneyWon); + list winnerList; + winnerList.push_back(tmpPlayer->getMyUniqueID()); + + curGame->getCurrentHand()->getBoard()->setPot(0); + curGame->getCurrentHand()->getBoard()->setWinners(winnerList); + + client.GetGui().postRiverRunAnimation1(); + + // Wait for next Hand. + client.SetState(ClientStateWaitHand::Instance()); + retVal = MSG_NET_GAME_SERVER_HAND_END; + } + else if (packet->ToNetPacketEndOfHandShowCards()) + { + curGame->getCurrentHand()->getBoard()->collectPot(); + // Reset player sets + ResetPlayerSets(*curGame); + client.GetGui().refreshPot(); + client.GetGui().refreshSet(); + // Synchronize with GUI. + client.GetGui().waitForGuiUpdateDone(); + + // End of Hand, show cards. + NetPacketEndOfHandShowCards::Data endHandData; + packet->ToNetPacketEndOfHandShowCards()->GetData(endHandData); + + NetPacketEndOfHandShowCards::PlayerResultList::const_iterator i + = endHandData.playerResults.begin(); + NetPacketEndOfHandShowCards::PlayerResultList::const_iterator end + = endHandData.playerResults.end(); + + list winnerList; + int highestValueOfCards = 0; + while (i != end) + { + boost::shared_ptr tmpPlayer = curGame->getPlayerByUniqueId((*i).playerId); + if (!tmpPlayer) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + + int tmpCards[2]; + int bestHandPos[5]; + tmpCards[0] = static_cast((*i).cards[0]); + tmpCards[1] = static_cast((*i).cards[1]); + tmpPlayer->setMyCards(tmpCards); + for (int num = 0; num < 5; num++) + bestHandPos[num] = (*i).bestHandPos[num]; + tmpPlayer->setMyCardsValueInt((*i).valueOfCards); + tmpPlayer->setMyBestHandPosition(bestHandPos); + if (tmpPlayer->getMyCardsValueInt() > highestValueOfCards) + highestValueOfCards = tmpPlayer->getMyCardsValueInt(); + tmpPlayer->setMyCash((*i).playerMoney); + tmpPlayer->setLastMoneyWon((*i).moneyWon); + if ((*i).moneyWon) + winnerList.push_back((*i).playerId); + + ++i; + } + curGame->getCurrentHand()->getCurrentBeRo()->setHighestCardsValue(highestValueOfCards); + curGame->getCurrentHand()->getBoard()->setPot(0); + curGame->getCurrentHand()->getBoard()->setWinners(winnerList); + + client.GetGui().postRiverRunAnimation1(); + + // Wait for next Hand. + client.SetState(ClientStateWaitHand::Instance()); + retVal = MSG_NET_GAME_CLIENT_HAND_END; + } + } + + // Synchronize with GUI. + client.GetGui().waitForGuiUpdateDone(); + + return retVal; +} + +void +ClientStateRunHand::ResetPlayerActions(Game &curGame) +{ + // Reset player actions + PlayerListIterator i = curGame.getSeatsList()->begin(); + PlayerListIterator end = curGame.getSeatsList()->end(); + + while (i != end) + { + int action = (*i)->getMyAction(); + if (action != 1 && action != 6) + (*i)->setMyAction(0); + (*i)->setMySetNull(); + ++i; + } +} + +void +ClientStateRunHand::ResetPlayerSets(Game &curGame) +{ + PlayerListIterator i = curGame.getSeatsList()->begin(); + PlayerListIterator end = curGame.getSeatsList()->end(); + while (i != end) + { + (*i)->setMySetNull(); + ++i; + } +} + +//----------------------------------------------------------------------------- + +ClientStateFinal & +ClientStateFinal::Instance() +{ + static ClientStateFinal state; + return state; +} + +ClientStateFinal::ClientStateFinal() +{ +} + +ClientStateFinal::~ClientStateFinal() +{ +} + +int +ClientStateFinal::Process(ClientThread &/*client*/) +{ + Thread::Msleep(10); + + return MSG_SOCK_INTERNAL_PENDING; +} diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 938128b0..cd94179c 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -1,989 +1,989 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -using namespace std; - - -class ClientSenderCallback : public SenderCallback -{ -public: - ClientSenderCallback(ClientThread &client) : m_client(client) {} - virtual ~ClientSenderCallback() {} - - virtual void SignalNetError(SessionId /*session*/, int errorID, int osErrorID) - { - // Just signal the error. - // We assume that the client thread will be terminated. - m_client.GetCallback().SignalNetClientError(errorID, osErrorID); - } - -private: - ClientThread &m_client; -}; - - -ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager) -: m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager), - m_curGameId(0), m_curGameNum(1), m_guiPlayerId(0), m_sessionEstablished(false) -{ - m_context.reset(new ClientContext); - m_senderCallback.reset(new ClientSenderCallback(*this)); - m_sender.reset(new SenderThread(GetSenderCallback())); - m_receiver.reset(new ReceiverHelper); -} - -ClientThread::~ClientThread() -{ -} - -void -ClientThread::Init( - const string &serverAddress, unsigned serverPort, bool ipv6, bool sctp, - const string &pwd, const string &playerName, const string &avatarFile) -{ - if (IsRunning()) - { - assert(false); - return; - } - - ClientContext &context = GetContext(); - - context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0); - context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET); - context.SetServerAddr(serverAddress); - context.SetServerPort(serverPort); - context.SetPassword(pwd); - context.SetPlayerName(playerName); - context.SetAvatarFile(avatarFile); -} - -void -ClientThread::SendKickPlayer(unsigned playerId) -{ - boost::shared_ptr request(new NetPacketKickPlayer); - NetPacketKickPlayer::Data requestData; - requestData.playerId = playerId; - static_cast(request.get())->SetData(requestData); - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(request); -} - -void -ClientThread::SendLeaveCurrentGame() -{ - boost::shared_ptr request(new NetPacketLeaveCurrentGame); - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(request); -} - -void -ClientThread::SendStartEvent(bool fillUpWithCpuPlayers) -{ - // Warning: This function is called in the context of the GUI thread. - // Create a network packet for the server start event. - boost::shared_ptr start(new NetPacketStartEvent); - NetPacketStartEvent::Data startData; - startData.fillUpWithCpuPlayers = fillUpWithCpuPlayers; - try - { - static_cast(start.get())->SetData(startData); - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(start); - } catch (const NetException &e) - { - LOG_ERROR("ClientThread::SendStartEvent: " << e.what()); - } -} - -void -ClientThread::SendPlayerAction() -{ - // Warning: This function is called in the context of the GUI thread. - // Create a network packet containing the current player action. - boost::shared_ptr action(new NetPacketPlayersAction); - NetPacketPlayersAction::Data actionData; - boost::shared_ptr myPlayer = GetGame()->getSeatsList()->front(); - actionData.gameState = static_cast(GetGame()->getCurrentHand()->getCurrentRound()); - actionData.playerAction = static_cast(myPlayer->getMyAction()); - // Only send last bet if not fold/checked. - if (actionData.playerAction != PLAYER_ACTION_FOLD && actionData.playerAction != PLAYER_ACTION_CHECK) - actionData.playerBet = myPlayer->getMyLastRelativeSet(); - else - actionData.playerBet = 0; - try - { - static_cast(action.get())->SetData(actionData); - // Just dump the packet. - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(action); - } catch (const NetException &e) - { - LOG_ERROR("ClientThread::SendPlayerAction: " << e.what()); - } -} - -void -ClientThread::SendChatMessage(const std::string &msg) -{ - // Warning: This function is called in the context of the GUI thread. - // Create a network packet containing the chat message. - boost::shared_ptr chat(new NetPacketSendChatText); - NetPacketSendChatText::Data chatData; - chatData.text = msg; - try - { - static_cast(chat.get())->SetData(chatData); - // Just dump the packet. - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(chat); - } catch (const NetException &e) - { - LOG_ERROR("ClientThread::SendChatMessage: " << e.what()); - } -} - -void -ClientThread::SendJoinFirstGame(const std::string &password) -{ - // Warning: This function is called in the context of the GUI thread. - // Create a network packet to request joining a game. - boost::shared_ptr join(new NetPacketJoinGame); - NetPacketJoinGame::Data joinData; - joinData.gameId = 0; - joinData.password = password; - try - { - static_cast(join.get())->SetData(joinData); - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(join); - } catch (const NetException &e) - { - LOG_ERROR("ClientThread::SendJoinFirstGame: " << e.what()); - } -} - -void -ClientThread::SendJoinGame(unsigned gameId, const std::string &password) -{ - // Warning: This function is called in the context of the GUI thread. - // Create a network packet to request joining a game. - boost::shared_ptr join(new NetPacketJoinGame); - NetPacketJoinGame::Data joinData; - joinData.password = password; - joinData.gameId = gameId; - try - { - static_cast(join.get())->SetData(joinData); - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(join); - } catch (const NetException &e) - { - LOG_ERROR("ClientThread::SendJoinGame: " << e.what()); - } -} - -void -ClientThread::SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password) -{ - // Warning: This function is called in the context of the GUI thread. - // Create a network packet to request creating a new game. - boost::shared_ptr create(new NetPacketCreateGame); - NetPacketCreateGame::Data createData; - createData.gameData = gameData; - createData.gameName = name; - createData.password = password; - try - { - static_cast(create.get())->SetData(createData); - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(create); - } catch (const NetException &e) - { - LOG_ERROR("ClientThread::SendCreateGame: " << e.what()); - } -} - -GameInfo -ClientThread::GetGameInfo(unsigned gameId) const -{ - GameInfo tmpInfo; - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::const_iterator pos = m_gameInfoMap.find(gameId); - if (pos != m_gameInfoMap.end()) - { - tmpInfo = pos->second; - } - return tmpInfo; -} - -PlayerInfo -ClientThread::GetPlayerInfo(unsigned playerId) const -{ - PlayerInfo info; - if (!GetCachedPlayerInfo(playerId, info)) - { - ostringstream name; - name << "#" << playerId; - - info.playerName = name.str(); - } - return info; -} - -bool -ClientThread::GetPlayerIdFromName(const string &playerName, unsigned &playerId) const -{ - bool retVal = false; - - boost::mutex::scoped_lock lock(m_playerInfoMapMutex); - PlayerInfoMap::const_reverse_iterator i = m_playerInfoMap.rbegin(); - PlayerInfoMap::const_reverse_iterator end = m_playerInfoMap.rend(); - - while (i != end) - { - if (i->second.playerName == playerName) - { - playerId = i->first; - retVal = true; - break; - } - ++i; - } - return retVal; -} - -ClientCallback & -ClientThread::GetCallback() -{ - return m_gui; -} - -GuiInterface & -ClientThread::GetGui() -{ - return m_gui; -} - -AvatarManager & -ClientThread::GetAvatarManager() -{ - return m_avatarManager; -} - -void -ClientThread::Main() -{ - SetState(CLIENT_INITIAL_STATE::Instance()); - - GetSender().Run(); - - try - { - while (!ShouldTerminate()) - { - int msg = GetState().Process(*this); - if (msg != MSG_SOCK_INTERNAL_PENDING) - { - if (msg <= MSG_SOCK_LIMIT_CONNECT) - GetCallback().SignalNetClientConnect(msg); - else - GetCallback().SignalNetClientGameInfo(msg); - - // Additionally signal the start of the game. - if (msg == MSG_NET_GAME_CLIENT_START) - { - // EngineFactory erstellen - boost::shared_ptr factory(new ClientEngineFactory); // LocalEngine erstellen - - MapPlayerDataList(); - if (GetPlayerDataList().size() != (unsigned)GetStartData().numberOfPlayers) - throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0); - m_game.reset(new Game(&m_gui, factory, GetPlayerDataList(), GetGameData(), GetStartData(), m_curGameNum++)); - // Initialize GUI speed. - GetGui().initGui(GetGameData().guiSpeed); - // Signal start of game to GUI. - GetCallback().SignalNetClientGameStart(m_game); - } - } - if (IsSessionEstablished()) - SendPacketLoop(); - } - } catch (const PokerTHException &e) - { - GetCallback().SignalNetClientError(e.GetErrorId(), e.GetOsErrorCode()); - } - GetSender().SignalTermination(); - GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); -} - -void -ClientThread::AddPacket(boost::shared_ptr packet) -{ - boost::mutex::scoped_lock lock(m_outPacketListMutex); - m_outPacketList.push_back(packet); -} - -void -ClientThread::SendPacketLoop() -{ - boost::mutex::scoped_lock lock(m_outPacketListMutex); - - if (!m_outPacketList.empty()) - { - NetPacketList::iterator i = m_outPacketList.begin(); - NetPacketList::iterator end = m_outPacketList.end(); - - while (i != end) - { - GetSender().Send(GetContext().GetSessionData(), *i); - ++i; - } - m_outPacketList.clear(); - } -} - -bool -ClientThread::GetCachedPlayerInfo(unsigned id, PlayerInfo &info) const -{ - bool retVal = false; - - boost::mutex::scoped_lock lock(m_playerInfoMapMutex); - PlayerInfoMap::const_iterator pos = m_playerInfoMap.find(id); - if (pos != m_playerInfoMap.end()) - { - info = pos->second; - retVal = true; - } - return retVal; -} - -void -ClientThread::RequestPlayerInfo(unsigned id, bool requestAvatar) -{ - if (find(m_playerInfoRequestList.begin(), m_playerInfoRequestList.end(), id) == m_playerInfoRequestList.end()) - { - boost::shared_ptr req(new NetPacketRetrievePlayerInfo); - NetPacketRetrievePlayerInfo::Data reqData; - reqData.playerId = id; - static_cast(req.get())->SetData(reqData); - GetSender().Send(GetContext().GetSessionData(), req); - - m_playerInfoRequestList.push_back(id); - - } - // Remember that we have to request an avatar. - if (requestAvatar) - { - m_avatarShouldRequestList.push_back(id); - } -} - -void -ClientThread::SetPlayerInfo(unsigned id, const PlayerInfo &info) -{ - { - boost::mutex::scoped_lock lock(m_playerInfoMapMutex); - // Remove previous player entry with different id - // for the same player name if it exists. - // This can only be one entry, since every time a duplicate - // name is added one is removed. - // Only erase non computer player entries. - if (info.playerName.substr(0, sizeof(SERVER_COMPUTER_PLAYER_NAME) - 1) != SERVER_COMPUTER_PLAYER_NAME) - { - PlayerInfoMap::iterator i = m_playerInfoMap.begin(); - PlayerInfoMap::iterator end = m_playerInfoMap.end(); - while (i != end) - { - if (i->first != id && i->second.playerName == info.playerName) - { - m_playerInfoMap.erase(i); - break; - } - ++i; - } - } - m_playerInfoMap[id] = info; - } - - // Update player data for current game. - boost::shared_ptr playerData = GetPlayerDataByUniqueId(id); - if (playerData.get()) - { - playerData->SetName(info.playerName); - playerData->SetType(info.ptype); - if (info.hasAvatar) - { - string avatarFile; - if (GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) - { - playerData->SetAvatarFile(avatarFile); - } - } - } - - if (find(m_avatarShouldRequestList.begin(), m_avatarShouldRequestList.end(), id) != m_avatarShouldRequestList.end()) - { - m_avatarShouldRequestList.remove(id); - // Retrieve avatar if needed. - RetrieveAvatarIfNeeded(id, info); - } - - // Remove it from the request list. - m_playerInfoRequestList.remove(id); - - // Notify GUI - GetCallback().SignalNetClientPlayerChanged(id, info.playerName); - -} - -void -ClientThread::SetUnknownPlayer(unsigned id) -{ - // Just remove it from the request list. - m_playerInfoRequestList.remove(id); - m_avatarShouldRequestList.remove(id); - LOG_ERROR("Server reported unknown player id: " << id); -} - -void -ClientThread::SetNewGameAdmin(unsigned id) -{ - // Update player data for current game. - boost::shared_ptr playerData = GetPlayerDataByUniqueId(id); - if (playerData.get()) - { - playerData->SetRights(PLAYER_RIGHTS_ADMIN); - GetCallback().SignalNetClientNewGameAdmin(id, playerData->GetName()); - } -} - -void -ClientThread::RetrieveAvatarIfNeeded(unsigned id, const PlayerInfo &info) -{ - if (find(m_avatarHasRequestedList.begin(), m_avatarHasRequestedList.end(), id) == m_avatarHasRequestedList.end()) - { - if (info.hasAvatar && !info.avatar.IsZero() && !GetAvatarManager().HasAvatar(info.avatar)) - { - m_avatarHasRequestedList.push_back(id); // Never remove from this list. Only request once. - boost::shared_ptr retrieveAvatar(new NetPacketRetrieveAvatar); - NetPacketRetrieveAvatar::Data retrieveAvatarData; - retrieveAvatarData.requestId = id; - retrieveAvatarData.avatar = info.avatar; - static_cast(retrieveAvatar.get())->SetData(retrieveAvatarData); - GetSender().Send(GetContext().GetSessionData(), retrieveAvatar); - } - } -} - -void -ClientThread::AddTempAvatarData(unsigned playerId, unsigned avatarSize, AvatarFileType type) -{ - boost::shared_ptr tmpAvatar(new AvatarData); - tmpAvatar->fileData.reserve(avatarSize); - tmpAvatar->fileType = type; - tmpAvatar->reportedSize = avatarSize; - - m_tempAvatarMap[playerId] = tmpAvatar; -} - -void -ClientThread::StoreInTempAvatarData(unsigned playerId, const vector &data) -{ - AvatarDataMap::iterator pos = m_tempAvatarMap.find(playerId); - if (pos == m_tempAvatarMap.end()) - throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_REQUEST_ID, 0); - // We trust the server (concerning size of the data). - std::copy(data.begin(), data.end(), back_inserter(pos->second->fileData)); -} - -void -ClientThread::CompleteTempAvatarData(unsigned playerId) -{ - AvatarDataMap::iterator pos = m_tempAvatarMap.find(playerId); - if (pos == m_tempAvatarMap.end()) - throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_REQUEST_ID, 0); - boost::shared_ptr tmpAvatar = pos->second; - unsigned avatarSize = (unsigned)tmpAvatar->fileData.size(); - if (avatarSize != tmpAvatar->reportedSize) - LOG_ERROR("Client received invalid avatar file size!"); - else - { - PlayerInfo tmpPlayerInfo; - if (!GetCachedPlayerInfo(playerId, tmpPlayerInfo)) - LOG_ERROR("Client received invalid player id!"); - else - { - if (!GetAvatarManager().StoreAvatarInCache(tmpPlayerInfo.avatar, tmpAvatar->fileType, &tmpAvatar->fileData[0], avatarSize)) - LOG_ERROR("Failed to store avatar in cache directory."); - - // Update player info, but never re-request avatar. - SetPlayerInfo(playerId, tmpPlayerInfo); - - string fileName; - if (GetAvatarManager().GetAvatarFileName(tmpPlayerInfo.avatar, fileName)) - { - // Dynamically update avatar in GUI. - GetGui().setPlayerAvatar(playerId, fileName); - } - } - } - // Free memory. - m_tempAvatarMap.erase(pos); -} - -void -ClientThread::SetUnknownAvatar(unsigned playerId) -{ - m_tempAvatarMap.erase(playerId); - LOG_ERROR("Server reported unknown avatar for player: " << playerId); -} - -const ClientContext & -ClientThread::GetContext() const -{ - assert(m_context.get()); - return *m_context; -} - -ClientContext & -ClientThread::GetContext() -{ - assert(m_context.get()); - return *m_context; -} - -ClientState & -ClientThread::GetState() -{ - assert(m_curState); - return *m_curState; -} - -void -ClientThread::SetState(ClientState &newState) -{ - m_curState = &newState; -} - -SenderThread & -ClientThread::GetSender() -{ - assert(m_sender.get()); - return *m_sender; -} - -ReceiverHelper & -ClientThread::GetReceiver() -{ - assert(m_receiver.get()); - return *m_receiver; -} - -unsigned -ClientThread::GetGameId() const -{ - boost::mutex::scoped_lock lock(m_curGameIdMutex); - return m_curGameId; -} - -void -ClientThread::SetGameId(unsigned id) -{ - boost::mutex::scoped_lock lock(m_curGameIdMutex); - m_curGameId = id; -} - -const GameData & -ClientThread::GetGameData() const -{ - return m_gameData; -} - -void -ClientThread::SetGameData(const GameData &gameData) -{ - m_gameData = gameData; -} - -const StartData & -ClientThread::GetStartData() const -{ - return m_startData; -} - -void -ClientThread::SetStartData(const StartData &startData) -{ - m_startData = startData; -} - -unsigned -ClientThread::GetGuiPlayerId() const -{ - return m_guiPlayerId; -} - -void -ClientThread::SetGuiPlayerId(unsigned guiPlayerId) -{ - m_guiPlayerId = guiPlayerId; -} - -boost::shared_ptr -ClientThread::GetGame() -{ - return m_game; -} - -ClientSenderCallback & -ClientThread::GetSenderCallback() -{ - assert(m_senderCallback.get()); - return *m_senderCallback; -} - -void -ClientThread::AddPlayerData(boost::shared_ptr playerData) -{ - if (playerData.get() && !playerData->GetName().empty()) - { - m_playerDataList.push_back(playerData); - if (playerData->GetUniqueId() == GetGuiPlayerId()) - GetCallback().SignalNetClientSelfJoined(playerData->GetUniqueId(), playerData->GetName(), playerData->GetRights()); - else - GetCallback().SignalNetClientPlayerJoined(playerData->GetUniqueId(), playerData->GetName(), playerData->GetRights()); - } -} - -void -ClientThread::RemovePlayerData(unsigned playerId) -{ - boost::shared_ptr tmpData; - - PlayerDataList::iterator i = m_playerDataList.begin(); - PlayerDataList::iterator end = m_playerDataList.end(); - while (i != end) - { - if ((*i)->GetUniqueId() == playerId) - { - tmpData = *i; - m_playerDataList.erase(i); - break; - } - ++i; - } - - if (tmpData.get()) - { - // Remove player from gui. - GetCallback().SignalNetClientPlayerLeft(tmpData->GetUniqueId(), tmpData->GetName()); - } -} - -void -ClientThread::ClearPlayerDataList() -{ - m_playerDataList.clear(); -} - -void -ClientThread::MapPlayerDataList() -{ - // Retrieve the GUI player. - boost::shared_ptr guiPlayer = GetPlayerDataByUniqueId(GetGuiPlayerId()); - assert(guiPlayer.get()); - int guiPlayerNum = guiPlayer->GetNumber(); - - // Create a copy of the player list so that the GUI player - // is player 0. This is mapped because the GUI depends on it. - PlayerDataList mappedList; - - PlayerDataList::const_iterator i = m_playerDataList.begin(); - PlayerDataList::const_iterator end = m_playerDataList.end(); - int numPlayers = GetStartData().numberOfPlayers; - - while (i != end) - { - boost::shared_ptr tmpData(new PlayerData(*(*i))); - int numberDiff = tmpData->GetNumber() - guiPlayerNum; - if (numberDiff >= 0) - tmpData->SetNumber(numberDiff); - else - tmpData->SetNumber(numPlayers + numberDiff); - mappedList.push_back(tmpData); - ++i; - } - - // Sort the list by player number. - mappedList.sort(*boost::lambda::_1 < *boost::lambda::_2); - - m_playerDataList = mappedList; -} - -const PlayerDataList & -ClientThread::GetPlayerDataList() const -{ - return m_playerDataList; -} - -boost::shared_ptr -ClientThread::GetPlayerDataByUniqueId(unsigned id) -{ - boost::shared_ptr tmpPlayer; - - PlayerDataList::const_iterator i = m_playerDataList.begin(); - PlayerDataList::const_iterator end = m_playerDataList.end(); - - while (i != end) - { - if ((*i)->GetUniqueId() == id) - { - tmpPlayer = *i; - break; - } - ++i; - } - return tmpPlayer; -} - -boost::shared_ptr -ClientThread::GetPlayerDataByName(const std::string &name) -{ - boost::shared_ptr tmpPlayer; - - if (!name.empty()) - { - PlayerDataList::const_iterator i = m_playerDataList.begin(); - PlayerDataList::const_iterator end = m_playerDataList.end(); - - while (i != end) - { - if ((*i)->GetName() == name) - { - tmpPlayer = *i; - break; - } - ++i; - } - } - return tmpPlayer; -} - -void -ClientThread::RemoveDisconnectedPlayers() -{ - // This should only be called between hands. - if (m_game.get()) - { - PlayerListIterator it; - for (it = m_game->getSeatsList()->begin(); it != m_game->getSeatsList()->end(); it++) - { - boost::shared_ptr tmpPlayer = *it; - if (tmpPlayer->getMyActiveStatus()) - { - // If a player is not in the player data list, it was disconnected. - if (!GetPlayerDataByUniqueId(tmpPlayer->getMyUniqueID()).get()) - { - tmpPlayer->setMyCash(0); - tmpPlayer->setMyActiveStatus(false); - } - } - } - } -} - -unsigned -ClientThread::GetGameIdByName(const std::string &name) const -{ - // Find the game. - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::const_iterator i = m_gameInfoMap.begin(); - GameInfoMap::const_iterator end = m_gameInfoMap.end(); - while (i != end) - { - if (i->second.name == name) - break; - ++i; - } - - if (i == end) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_GAME, 0); - return i->first; -} - -void -ClientThread::AddGameInfo(unsigned gameId, const GameInfo &info) -{ - { - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - m_gameInfoMap.insert(GameInfoMap::value_type(gameId, info)); - } - GetCallback().SignalNetClientGameListNew(gameId); -} - -void -ClientThread::UpdateGameInfoMode(unsigned gameId, GameMode mode) -{ - bool found = false; - { - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); - if (pos != m_gameInfoMap.end()) - { - found = true; - (*pos).second.mode = mode; - } - } - if (found) - GetCallback().SignalNetClientGameListUpdateMode(gameId, mode); -} - -void -ClientThread::UpdateGameInfoAdmin(unsigned gameId, unsigned adminPlayerId) -{ - bool found = false; - { - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); - if (pos != m_gameInfoMap.end()) - { - found = true; - (*pos).second.adminPlayerId = adminPlayerId; - } - } - if (found) - GetCallback().SignalNetClientGameListUpdateAdmin(gameId, adminPlayerId); -} - -void -ClientThread::RemoveGameInfo(unsigned gameId) -{ - bool found = false; - { - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); - if (pos != m_gameInfoMap.end()) - { - found = true; - m_gameInfoMap.erase(pos); - } - } - if (found) - GetCallback().SignalNetClientGameListRemove(gameId); -} - -void -ClientThread::ModifyGameInfoAddPlayer(unsigned gameId, unsigned playerId) -{ - bool playerAdded = false; - { - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); - if (pos != m_gameInfoMap.end()) - { - pos->second.players.push_back(playerId); - playerAdded = true; - } - } - if (playerAdded) - GetCallback().SignalNetClientGameListPlayerJoined(gameId, playerId); -} - -void -ClientThread::ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId) -{ - bool playerRemoved = false; - { - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); - if (pos != m_gameInfoMap.end()) - { - pos->second.players.remove(playerId); - playerRemoved = true; - } - } - if (playerRemoved) - GetCallback().SignalNetClientGameListPlayerLeft(gameId, playerId); -} - -void -ClientThread::ClearGameInfoMap() -{ - boost::mutex::scoped_lock lock(m_gameInfoMapMutex); - m_gameInfoMap.clear(); -} - -void -ClientThread::UpdateStatData(const ServerStats &stats) -{ - boost::mutex::scoped_lock lock(m_curStatsMutex); - if (stats.numberOfPlayersOnServer) - m_curStats.numberOfPlayersOnServer = stats.numberOfPlayersOnServer; - - if (stats.totalPlayersEverLoggedIn) - m_curStats.totalPlayersEverLoggedIn = stats.totalPlayersEverLoggedIn; - - if (stats.totalGamesEverCreated) - m_curStats.totalGamesEverCreated = stats.totalGamesEverCreated; - - GetCallback().SignalNetClientStatsUpdate(m_curStats); -} - -ServerStats -ClientThread::GetStatData() const -{ - boost::mutex::scoped_lock lock(m_curStatsMutex); - return m_curStats; -} - -bool -ClientThread::IsSessionEstablished() const -{ - return m_sessionEstablished; -} - -void -ClientThread::SetSessionEstablished(bool flag) -{ - m_sessionEstablished = flag; -} - -bool -ClientThread::IsSynchronized() const -{ - return m_playerInfoRequestList.empty(); -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; + + +class ClientSenderCallback : public SenderCallback +{ +public: + ClientSenderCallback(ClientThread &client) : m_client(client) {} + virtual ~ClientSenderCallback() {} + + virtual void SignalNetError(SessionId /*session*/, int errorID, int osErrorID) + { + // Just signal the error. + // We assume that the client thread will be terminated. + m_client.GetCallback().SignalNetClientError(errorID, osErrorID); + } + +private: + ClientThread &m_client; +}; + + +ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager) +: m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager), + m_curGameId(0), m_curGameNum(1), m_guiPlayerId(0), m_sessionEstablished(false) +{ + m_context.reset(new ClientContext); + m_senderCallback.reset(new ClientSenderCallback(*this)); + m_sender.reset(new SenderThread(GetSenderCallback())); + m_receiver.reset(new ReceiverHelper); +} + +ClientThread::~ClientThread() +{ +} + +void +ClientThread::Init( + const string &serverAddress, unsigned serverPort, bool ipv6, bool sctp, + const string &pwd, const string &playerName, const string &avatarFile) +{ + if (IsRunning()) + { + assert(false); + return; + } + + ClientContext &context = GetContext(); + + context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0); + context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET); + context.SetServerAddr(serverAddress); + context.SetServerPort(serverPort); + context.SetPassword(pwd); + context.SetPlayerName(playerName); + context.SetAvatarFile(avatarFile); +} + +void +ClientThread::SendKickPlayer(unsigned playerId) +{ + boost::shared_ptr request(new NetPacketKickPlayer); + NetPacketKickPlayer::Data requestData; + requestData.playerId = playerId; + static_cast(request.get())->SetData(requestData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(request); +} + +void +ClientThread::SendLeaveCurrentGame() +{ + boost::shared_ptr request(new NetPacketLeaveCurrentGame); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(request); +} + +void +ClientThread::SendStartEvent(bool fillUpWithCpuPlayers) +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet for the server start event. + boost::shared_ptr start(new NetPacketStartEvent); + NetPacketStartEvent::Data startData; + startData.fillUpWithCpuPlayers = fillUpWithCpuPlayers; + try + { + static_cast(start.get())->SetData(startData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(start); + } catch (const NetException &e) + { + LOG_ERROR("ClientThread::SendStartEvent: " << e.what()); + } +} + +void +ClientThread::SendPlayerAction() +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet containing the current player action. + boost::shared_ptr action(new NetPacketPlayersAction); + NetPacketPlayersAction::Data actionData; + boost::shared_ptr myPlayer = GetGame()->getSeatsList()->front(); + actionData.gameState = static_cast(GetGame()->getCurrentHand()->getCurrentRound()); + actionData.playerAction = static_cast(myPlayer->getMyAction()); + // Only send last bet if not fold/checked. + if (actionData.playerAction != PLAYER_ACTION_FOLD && actionData.playerAction != PLAYER_ACTION_CHECK) + actionData.playerBet = myPlayer->getMyLastRelativeSet(); + else + actionData.playerBet = 0; + try + { + static_cast(action.get())->SetData(actionData); + // Just dump the packet. + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(action); + } catch (const NetException &e) + { + LOG_ERROR("ClientThread::SendPlayerAction: " << e.what()); + } +} + +void +ClientThread::SendChatMessage(const std::string &msg) +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet containing the chat message. + boost::shared_ptr chat(new NetPacketSendChatText); + NetPacketSendChatText::Data chatData; + chatData.text = msg; + try + { + static_cast(chat.get())->SetData(chatData); + // Just dump the packet. + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(chat); + } catch (const NetException &e) + { + LOG_ERROR("ClientThread::SendChatMessage: " << e.what()); + } +} + +void +ClientThread::SendJoinFirstGame(const std::string &password) +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet to request joining a game. + boost::shared_ptr join(new NetPacketJoinGame); + NetPacketJoinGame::Data joinData; + joinData.gameId = 0; + joinData.password = password; + try + { + static_cast(join.get())->SetData(joinData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(join); + } catch (const NetException &e) + { + LOG_ERROR("ClientThread::SendJoinFirstGame: " << e.what()); + } +} + +void +ClientThread::SendJoinGame(unsigned gameId, const std::string &password) +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet to request joining a game. + boost::shared_ptr join(new NetPacketJoinGame); + NetPacketJoinGame::Data joinData; + joinData.password = password; + joinData.gameId = gameId; + try + { + static_cast(join.get())->SetData(joinData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(join); + } catch (const NetException &e) + { + LOG_ERROR("ClientThread::SendJoinGame: " << e.what()); + } +} + +void +ClientThread::SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password) +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet to request creating a new game. + boost::shared_ptr create(new NetPacketCreateGame); + NetPacketCreateGame::Data createData; + createData.gameData = gameData; + createData.gameName = name; + createData.password = password; + try + { + static_cast(create.get())->SetData(createData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(create); + } catch (const NetException &e) + { + LOG_ERROR("ClientThread::SendCreateGame: " << e.what()); + } +} + +GameInfo +ClientThread::GetGameInfo(unsigned gameId) const +{ + GameInfo tmpInfo; + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::const_iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + tmpInfo = pos->second; + } + return tmpInfo; +} + +PlayerInfo +ClientThread::GetPlayerInfo(unsigned playerId) const +{ + PlayerInfo info; + if (!GetCachedPlayerInfo(playerId, info)) + { + ostringstream name; + name << "#" << playerId; + + info.playerName = name.str(); + } + return info; +} + +bool +ClientThread::GetPlayerIdFromName(const string &playerName, unsigned &playerId) const +{ + bool retVal = false; + + boost::mutex::scoped_lock lock(m_playerInfoMapMutex); + PlayerInfoMap::const_reverse_iterator i = m_playerInfoMap.rbegin(); + PlayerInfoMap::const_reverse_iterator end = m_playerInfoMap.rend(); + + while (i != end) + { + if (i->second.playerName == playerName) + { + playerId = i->first; + retVal = true; + break; + } + ++i; + } + return retVal; +} + +ClientCallback & +ClientThread::GetCallback() +{ + return m_gui; +} + +GuiInterface & +ClientThread::GetGui() +{ + return m_gui; +} + +AvatarManager & +ClientThread::GetAvatarManager() +{ + return m_avatarManager; +} + +void +ClientThread::Main() +{ + SetState(CLIENT_INITIAL_STATE::Instance()); + + GetSender().Run(); + + try + { + while (!ShouldTerminate()) + { + int msg = GetState().Process(*this); + if (msg != MSG_SOCK_INTERNAL_PENDING) + { + if (msg <= MSG_SOCK_LIMIT_CONNECT) + GetCallback().SignalNetClientConnect(msg); + else + GetCallback().SignalNetClientGameInfo(msg); + + // Additionally signal the start of the game. + if (msg == MSG_NET_GAME_CLIENT_START) + { + // EngineFactory erstellen + boost::shared_ptr factory(new ClientEngineFactory); // LocalEngine erstellen + + MapPlayerDataList(); + if (GetPlayerDataList().size() != (unsigned)GetStartData().numberOfPlayers) + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0); + m_game.reset(new Game(&m_gui, factory, GetPlayerDataList(), GetGameData(), GetStartData(), m_curGameNum++)); + // Initialize GUI speed. + GetGui().initGui(GetGameData().guiSpeed); + // Signal start of game to GUI. + GetCallback().SignalNetClientGameStart(m_game); + } + } + if (IsSessionEstablished()) + SendPacketLoop(); + } + } catch (const PokerTHException &e) + { + GetCallback().SignalNetClientError(e.GetErrorId(), e.GetOsErrorCode()); + } + GetSender().SignalTermination(); + GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); +} + +void +ClientThread::AddPacket(boost::shared_ptr packet) +{ + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(packet); +} + +void +ClientThread::SendPacketLoop() +{ + boost::mutex::scoped_lock lock(m_outPacketListMutex); + + if (!m_outPacketList.empty()) + { + NetPacketList::iterator i = m_outPacketList.begin(); + NetPacketList::iterator end = m_outPacketList.end(); + + while (i != end) + { + GetSender().Send(GetContext().GetSessionData(), *i); + ++i; + } + m_outPacketList.clear(); + } +} + +bool +ClientThread::GetCachedPlayerInfo(unsigned id, PlayerInfo &info) const +{ + bool retVal = false; + + boost::mutex::scoped_lock lock(m_playerInfoMapMutex); + PlayerInfoMap::const_iterator pos = m_playerInfoMap.find(id); + if (pos != m_playerInfoMap.end()) + { + info = pos->second; + retVal = true; + } + return retVal; +} + +void +ClientThread::RequestPlayerInfo(unsigned id, bool requestAvatar) +{ + if (find(m_playerInfoRequestList.begin(), m_playerInfoRequestList.end(), id) == m_playerInfoRequestList.end()) + { + boost::shared_ptr req(new NetPacketRetrievePlayerInfo); + NetPacketRetrievePlayerInfo::Data reqData; + reqData.playerId = id; + static_cast(req.get())->SetData(reqData); + GetSender().Send(GetContext().GetSessionData(), req); + + m_playerInfoRequestList.push_back(id); + + } + // Remember that we have to request an avatar. + if (requestAvatar) + { + m_avatarShouldRequestList.push_back(id); + } +} + +void +ClientThread::SetPlayerInfo(unsigned id, const PlayerInfo &info) +{ + { + boost::mutex::scoped_lock lock(m_playerInfoMapMutex); + // Remove previous player entry with different id + // for the same player name if it exists. + // This can only be one entry, since every time a duplicate + // name is added one is removed. + // Only erase non computer player entries. + if (info.playerName.substr(0, sizeof(SERVER_COMPUTER_PLAYER_NAME) - 1) != SERVER_COMPUTER_PLAYER_NAME) + { + PlayerInfoMap::iterator i = m_playerInfoMap.begin(); + PlayerInfoMap::iterator end = m_playerInfoMap.end(); + while (i != end) + { + if (i->first != id && i->second.playerName == info.playerName) + { + m_playerInfoMap.erase(i); + break; + } + ++i; + } + } + m_playerInfoMap[id] = info; + } + + // Update player data for current game. + boost::shared_ptr playerData = GetPlayerDataByUniqueId(id); + if (playerData.get()) + { + playerData->SetName(info.playerName); + playerData->SetType(info.ptype); + if (info.hasAvatar) + { + string avatarFile; + if (GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) + { + playerData->SetAvatarFile(avatarFile); + } + } + } + + if (find(m_avatarShouldRequestList.begin(), m_avatarShouldRequestList.end(), id) != m_avatarShouldRequestList.end()) + { + m_avatarShouldRequestList.remove(id); + // Retrieve avatar if needed. + RetrieveAvatarIfNeeded(id, info); + } + + // Remove it from the request list. + m_playerInfoRequestList.remove(id); + + // Notify GUI + GetCallback().SignalNetClientPlayerChanged(id, info.playerName); + +} + +void +ClientThread::SetUnknownPlayer(unsigned id) +{ + // Just remove it from the request list. + m_playerInfoRequestList.remove(id); + m_avatarShouldRequestList.remove(id); + LOG_ERROR("Server reported unknown player id: " << id); +} + +void +ClientThread::SetNewGameAdmin(unsigned id) +{ + // Update player data for current game. + boost::shared_ptr playerData = GetPlayerDataByUniqueId(id); + if (playerData.get()) + { + playerData->SetRights(PLAYER_RIGHTS_ADMIN); + GetCallback().SignalNetClientNewGameAdmin(id, playerData->GetName()); + } +} + +void +ClientThread::RetrieveAvatarIfNeeded(unsigned id, const PlayerInfo &info) +{ + if (find(m_avatarHasRequestedList.begin(), m_avatarHasRequestedList.end(), id) == m_avatarHasRequestedList.end()) + { + if (info.hasAvatar && !info.avatar.IsZero() && !GetAvatarManager().HasAvatar(info.avatar)) + { + m_avatarHasRequestedList.push_back(id); // Never remove from this list. Only request once. + boost::shared_ptr retrieveAvatar(new NetPacketRetrieveAvatar); + NetPacketRetrieveAvatar::Data retrieveAvatarData; + retrieveAvatarData.requestId = id; + retrieveAvatarData.avatar = info.avatar; + static_cast(retrieveAvatar.get())->SetData(retrieveAvatarData); + GetSender().Send(GetContext().GetSessionData(), retrieveAvatar); + } + } +} + +void +ClientThread::AddTempAvatarData(unsigned playerId, unsigned avatarSize, AvatarFileType type) +{ + boost::shared_ptr tmpAvatar(new AvatarData); + tmpAvatar->fileData.reserve(avatarSize); + tmpAvatar->fileType = type; + tmpAvatar->reportedSize = avatarSize; + + m_tempAvatarMap[playerId] = tmpAvatar; +} + +void +ClientThread::StoreInTempAvatarData(unsigned playerId, const vector &data) +{ + AvatarDataMap::iterator pos = m_tempAvatarMap.find(playerId); + if (pos == m_tempAvatarMap.end()) + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_REQUEST_ID, 0); + // We trust the server (concerning size of the data). + std::copy(data.begin(), data.end(), back_inserter(pos->second->fileData)); +} + +void +ClientThread::CompleteTempAvatarData(unsigned playerId) +{ + AvatarDataMap::iterator pos = m_tempAvatarMap.find(playerId); + if (pos == m_tempAvatarMap.end()) + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_REQUEST_ID, 0); + boost::shared_ptr tmpAvatar = pos->second; + unsigned avatarSize = (unsigned)tmpAvatar->fileData.size(); + if (avatarSize != tmpAvatar->reportedSize) + LOG_ERROR("Client received invalid avatar file size!"); + else + { + PlayerInfo tmpPlayerInfo; + if (!GetCachedPlayerInfo(playerId, tmpPlayerInfo)) + LOG_ERROR("Client received invalid player id!"); + else + { + if (!GetAvatarManager().StoreAvatarInCache(tmpPlayerInfo.avatar, tmpAvatar->fileType, &tmpAvatar->fileData[0], avatarSize)) + LOG_ERROR("Failed to store avatar in cache directory."); + + // Update player info, but never re-request avatar. + SetPlayerInfo(playerId, tmpPlayerInfo); + + string fileName; + if (GetAvatarManager().GetAvatarFileName(tmpPlayerInfo.avatar, fileName)) + { + // Dynamically update avatar in GUI. + GetGui().setPlayerAvatar(playerId, fileName); + } + } + } + // Free memory. + m_tempAvatarMap.erase(pos); +} + +void +ClientThread::SetUnknownAvatar(unsigned playerId) +{ + m_tempAvatarMap.erase(playerId); + LOG_ERROR("Server reported unknown avatar for player: " << playerId); +} + +const ClientContext & +ClientThread::GetContext() const +{ + assert(m_context.get()); + return *m_context; +} + +ClientContext & +ClientThread::GetContext() +{ + assert(m_context.get()); + return *m_context; +} + +ClientState & +ClientThread::GetState() +{ + assert(m_curState); + return *m_curState; +} + +void +ClientThread::SetState(ClientState &newState) +{ + m_curState = &newState; +} + +SenderThread & +ClientThread::GetSender() +{ + assert(m_sender.get()); + return *m_sender; +} + +ReceiverHelper & +ClientThread::GetReceiver() +{ + assert(m_receiver.get()); + return *m_receiver; +} + +unsigned +ClientThread::GetGameId() const +{ + boost::mutex::scoped_lock lock(m_curGameIdMutex); + return m_curGameId; +} + +void +ClientThread::SetGameId(unsigned id) +{ + boost::mutex::scoped_lock lock(m_curGameIdMutex); + m_curGameId = id; +} + +const GameData & +ClientThread::GetGameData() const +{ + return m_gameData; +} + +void +ClientThread::SetGameData(const GameData &gameData) +{ + m_gameData = gameData; +} + +const StartData & +ClientThread::GetStartData() const +{ + return m_startData; +} + +void +ClientThread::SetStartData(const StartData &startData) +{ + m_startData = startData; +} + +unsigned +ClientThread::GetGuiPlayerId() const +{ + return m_guiPlayerId; +} + +void +ClientThread::SetGuiPlayerId(unsigned guiPlayerId) +{ + m_guiPlayerId = guiPlayerId; +} + +boost::shared_ptr +ClientThread::GetGame() +{ + return m_game; +} + +ClientSenderCallback & +ClientThread::GetSenderCallback() +{ + assert(m_senderCallback.get()); + return *m_senderCallback; +} + +void +ClientThread::AddPlayerData(boost::shared_ptr playerData) +{ + if (playerData.get() && !playerData->GetName().empty()) + { + m_playerDataList.push_back(playerData); + if (playerData->GetUniqueId() == GetGuiPlayerId()) + GetCallback().SignalNetClientSelfJoined(playerData->GetUniqueId(), playerData->GetName(), playerData->GetRights()); + else + GetCallback().SignalNetClientPlayerJoined(playerData->GetUniqueId(), playerData->GetName(), playerData->GetRights()); + } +} + +void +ClientThread::RemovePlayerData(unsigned playerId) +{ + boost::shared_ptr tmpData; + + PlayerDataList::iterator i = m_playerDataList.begin(); + PlayerDataList::iterator end = m_playerDataList.end(); + while (i != end) + { + if ((*i)->GetUniqueId() == playerId) + { + tmpData = *i; + m_playerDataList.erase(i); + break; + } + ++i; + } + + if (tmpData.get()) + { + // Remove player from gui. + GetCallback().SignalNetClientPlayerLeft(tmpData->GetUniqueId(), tmpData->GetName()); + } +} + +void +ClientThread::ClearPlayerDataList() +{ + m_playerDataList.clear(); +} + +void +ClientThread::MapPlayerDataList() +{ + // Retrieve the GUI player. + boost::shared_ptr guiPlayer = GetPlayerDataByUniqueId(GetGuiPlayerId()); + assert(guiPlayer.get()); + int guiPlayerNum = guiPlayer->GetNumber(); + + // Create a copy of the player list so that the GUI player + // is player 0. This is mapped because the GUI depends on it. + PlayerDataList mappedList; + + PlayerDataList::const_iterator i = m_playerDataList.begin(); + PlayerDataList::const_iterator end = m_playerDataList.end(); + int numPlayers = GetStartData().numberOfPlayers; + + while (i != end) + { + boost::shared_ptr tmpData(new PlayerData(*(*i))); + int numberDiff = tmpData->GetNumber() - guiPlayerNum; + if (numberDiff >= 0) + tmpData->SetNumber(numberDiff); + else + tmpData->SetNumber(numPlayers + numberDiff); + mappedList.push_back(tmpData); + ++i; + } + + // Sort the list by player number. + mappedList.sort(*boost::lambda::_1 < *boost::lambda::_2); + + m_playerDataList = mappedList; +} + +const PlayerDataList & +ClientThread::GetPlayerDataList() const +{ + return m_playerDataList; +} + +boost::shared_ptr +ClientThread::GetPlayerDataByUniqueId(unsigned id) +{ + boost::shared_ptr tmpPlayer; + + PlayerDataList::const_iterator i = m_playerDataList.begin(); + PlayerDataList::const_iterator end = m_playerDataList.end(); + + while (i != end) + { + if ((*i)->GetUniqueId() == id) + { + tmpPlayer = *i; + break; + } + ++i; + } + return tmpPlayer; +} + +boost::shared_ptr +ClientThread::GetPlayerDataByName(const std::string &name) +{ + boost::shared_ptr tmpPlayer; + + if (!name.empty()) + { + PlayerDataList::const_iterator i = m_playerDataList.begin(); + PlayerDataList::const_iterator end = m_playerDataList.end(); + + while (i != end) + { + if ((*i)->GetName() == name) + { + tmpPlayer = *i; + break; + } + ++i; + } + } + return tmpPlayer; +} + +void +ClientThread::RemoveDisconnectedPlayers() +{ + // This should only be called between hands. + if (m_game.get()) + { + PlayerListIterator it; + for (it = m_game->getSeatsList()->begin(); it != m_game->getSeatsList()->end(); it++) + { + boost::shared_ptr tmpPlayer = *it; + if (tmpPlayer->getMyActiveStatus()) + { + // If a player is not in the player data list, it was disconnected. + if (!GetPlayerDataByUniqueId(tmpPlayer->getMyUniqueID()).get()) + { + tmpPlayer->setMyCash(0); + tmpPlayer->setMyActiveStatus(false); + } + } + } + } +} + +unsigned +ClientThread::GetGameIdByName(const std::string &name) const +{ + // Find the game. + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::const_iterator i = m_gameInfoMap.begin(); + GameInfoMap::const_iterator end = m_gameInfoMap.end(); + while (i != end) + { + if (i->second.name == name) + break; + ++i; + } + + if (i == end) + throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_GAME, 0); + return i->first; +} + +void +ClientThread::AddGameInfo(unsigned gameId, const GameInfo &info) +{ + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + m_gameInfoMap.insert(GameInfoMap::value_type(gameId, info)); + } + GetCallback().SignalNetClientGameListNew(gameId); +} + +void +ClientThread::UpdateGameInfoMode(unsigned gameId, GameMode mode) +{ + bool found = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + found = true; + (*pos).second.mode = mode; + } + } + if (found) + GetCallback().SignalNetClientGameListUpdateMode(gameId, mode); +} + +void +ClientThread::UpdateGameInfoAdmin(unsigned gameId, unsigned adminPlayerId) +{ + bool found = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + found = true; + (*pos).second.adminPlayerId = adminPlayerId; + } + } + if (found) + GetCallback().SignalNetClientGameListUpdateAdmin(gameId, adminPlayerId); +} + +void +ClientThread::RemoveGameInfo(unsigned gameId) +{ + bool found = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + found = true; + m_gameInfoMap.erase(pos); + } + } + if (found) + GetCallback().SignalNetClientGameListRemove(gameId); +} + +void +ClientThread::ModifyGameInfoAddPlayer(unsigned gameId, unsigned playerId) +{ + bool playerAdded = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + pos->second.players.push_back(playerId); + playerAdded = true; + } + } + if (playerAdded) + GetCallback().SignalNetClientGameListPlayerJoined(gameId, playerId); +} + +void +ClientThread::ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId) +{ + bool playerRemoved = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + pos->second.players.remove(playerId); + playerRemoved = true; + } + } + if (playerRemoved) + GetCallback().SignalNetClientGameListPlayerLeft(gameId, playerId); +} + +void +ClientThread::ClearGameInfoMap() +{ + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + m_gameInfoMap.clear(); +} + +void +ClientThread::UpdateStatData(const ServerStats &stats) +{ + boost::mutex::scoped_lock lock(m_curStatsMutex); + if (stats.numberOfPlayersOnServer) + m_curStats.numberOfPlayersOnServer = stats.numberOfPlayersOnServer; + + if (stats.totalPlayersEverLoggedIn) + m_curStats.totalPlayersEverLoggedIn = stats.totalPlayersEverLoggedIn; + + if (stats.totalGamesEverCreated) + m_curStats.totalGamesEverCreated = stats.totalGamesEverCreated; + + GetCallback().SignalNetClientStatsUpdate(m_curStats); +} + +ServerStats +ClientThread::GetStatData() const +{ + boost::mutex::scoped_lock lock(m_curStatsMutex); + return m_curStats; +} + +bool +ClientThread::IsSessionEstablished() const +{ + return m_sessionEstablished; +} + +void +ClientThread::SetSessionEstablished(bool flag) +{ + m_sessionEstablished = flag; +} + +bool +ClientThread::IsSynchronized() const +{ + return m_playerInfoRequestList.empty(); +} + diff --git a/src/net/common/connectdata.cpp b/src/net/common/connectdata.cpp index 1cc98117..93883004 100644 --- a/src/net/common/connectdata.cpp +++ b/src/net/common/connectdata.cpp @@ -1,40 +1,40 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -ConnectData::ConnectData() -: m_sockfd(INVALID_SOCKET) -{ -} - -ConnectData::~ConnectData() -{ - if (m_sockfd != INVALID_SOCKET) - CLOSESOCKET(m_sockfd); -} - -SOCKET -ConnectData::ReleaseSocket() -{ - SOCKET tmpSock = m_sockfd; - m_sockfd = INVALID_SOCKET; - return tmpSock; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +ConnectData::ConnectData() +: m_sockfd(INVALID_SOCKET) +{ +} + +ConnectData::~ConnectData() +{ + if (m_sockfd != INVALID_SOCKET) + CLOSESOCKET(m_sockfd); +} + +SOCKET +ConnectData::ReleaseSocket() +{ + SOCKET tmpSock = m_sockfd; + m_sockfd = INVALID_SOCKET; + return tmpSock; +} + diff --git a/src/net/common/irccallback.cpp b/src/net/common/irccallback.cpp index 545ff87f..4d5fc9cf 100644 --- a/src/net/common/irccallback.cpp +++ b/src/net/common/irccallback.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -IrcCallback::~IrcCallback() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +IrcCallback::~IrcCallback() +{ +} + diff --git a/src/net/common/ircthread.cpp b/src/net/common/ircthread.cpp index ee538f31..52fe5dbc 100644 --- a/src/net/common/ircthread.cpp +++ b/src/net/common/ircthread.cpp @@ -1,444 +1,444 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -#define IRC_WAIT_TERMINATION_MSEC 500 -#define IRC_MAX_RENAME_TRIES 5 - - -struct IrcContext -{ - IrcContext(IrcThread &t) : ircThread(t), session(NULL), serverPort(0), useIPv6(false), renameTries(0) {} - IrcThread &ircThread; - irc_session_t *session; - string serverAddress; - unsigned serverPort; - bool useIPv6; - string nick; - string channel; - string channelPassword; - unsigned renameTries; -}; - -void irc_auto_rename_nick(irc_session_t *session) -{ - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - if (context->renameTries <= IRC_MAX_RENAME_TRIES) // Limit number of rename tries. - { - // Automatically rename the nick on collision. - // First: Try to append the string "Lobby". - if (context->nick.find("|Lobby") == string::npos) - { - context->nick = context->nick + "|Lobby"; - } - else - { - // This didn't work out. Append a number or increment it. - string::reverse_iterator end = context->nick.rbegin(); - if (!context->nick.empty() && isdigit(*end)) - { - if (*end != '9') - *end = (*end) + 1; - else - context->nick = context->nick + "0"; - } - else - context->nick = context->nick + "1"; - } - irc_cmd_nick(session, context->nick.c_str()); - context->renameTries++; - } - else - irc_cmd_quit(session, NULL); -} - -void irc_notify_player_list(irc_session_t *session, const char *players) -{ - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - istringstream input(players); - string name; - input >> name; - while (!input.fail() && !input.eof()) - { - context->ircThread.GetCallback().SignalIrcPlayerJoined(name); - input >> name; - } -} - -void irc_handle_server_error(irc_session_t *session, unsigned irc_error_code) -{ - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - context->ircThread.GetCallback().SignalIrcServerError(irc_error_code); -} - -void -irc_event_connect(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char ** /*params*/, unsigned /*count*/) -{ - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - context->ircThread.GetCallback().SignalIrcConnect(origin); - irc_cmd_join(session, context->channel.c_str(), context->channelPassword.c_str()); -} - -void -irc_event_join(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char ** /*params*/, unsigned /*count*/) -{ - // someone joined the channel. - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - if (context->nick == origin) - context->ircThread.GetCallback().SignalIrcSelfJoined(context->nick, context->channel); - else - context->ircThread.GetCallback().SignalIrcPlayerJoined(origin); -} - -void -irc_event_nick(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char **params, unsigned count) -{ - // someone changed his/her nick - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - if (count && context->nick != params[0]) // only act if this was not an auto-rename - { - if (context->nick == origin) - context->nick = params[0]; - context->ircThread.GetCallback().SignalIrcPlayerChanged(origin, params[0]); - } -} - -void -irc_event_kick(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char **params, unsigned count) -{ - // someone got kicked - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - string byWhom(origin); - string who; - string reason; - if (count >= 2) - who = params[1]; - if (count >= 3) - reason = params[2]; - context->ircThread.GetCallback().SignalIrcPlayerKicked(who, byWhom, reason); - if (!who.empty()) - context->ircThread.GetCallback().SignalIrcPlayerLeft(who); -} - -void -irc_event_leave(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char ** /*params*/, unsigned /*count*/) -{ - // someone left the channel. - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - context->ircThread.GetCallback().SignalIrcPlayerLeft(origin); -} - -void -irc_event_channel(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char **params, unsigned count) -{ - IrcContext *context = (IrcContext *) irc_get_ctx(session); - - if (count >= 2 && boost::algorithm::iequals(context->channel, params[0])) // check whether this message is for our channel - { - // Signal the message (if any) to GUI. - if (*params[1] != 0) - context->ircThread.GetCallback().SignalIrcChatMsg(origin, params[1]); - } -} - -void -irc_event_numeric(irc_session_t * session, unsigned irc_event, const char * /*origin*/, const char **params, unsigned count) -{ - switch (irc_event) - { - case LIBIRC_RFC_ERR_NICKNAMEINUSE : - case LIBIRC_RFC_ERR_NICKCOLLISION : - irc_auto_rename_nick(session); - break; - case LIBIRC_RFC_RPL_TOPIC : - break; - case LIBIRC_RFC_RPL_NAMREPLY : - if (count >= 4) - irc_notify_player_list(session, params[3]); - break; - case LIBIRC_RFC_ERR_NOSUCHNICK : - case LIBIRC_RFC_ERR_NOSUCHCHANNEL : - case LIBIRC_RFC_ERR_CANNOTSENDTOCHAN : - case LIBIRC_RFC_ERR_TOOMANYCHANNELS : - case LIBIRC_RFC_ERR_WASNOSUCHNICK : - case LIBIRC_RFC_ERR_TOOMANYTARGETS : - case LIBIRC_RFC_ERR_NOSUCHSERVICE : - case LIBIRC_RFC_ERR_NOORIGIN : - case LIBIRC_RFC_ERR_NORECIPIENT : - case LIBIRC_RFC_ERR_NOTEXTTOSEND : - case LIBIRC_RFC_ERR_NOTOPLEVEL : - case LIBIRC_RFC_ERR_WILDTOPLEVEL : - case LIBIRC_RFC_ERR_BADMASK : - case LIBIRC_RFC_ERR_UNKNOWNCOMMAND : - case LIBIRC_RFC_ERR_NOMOTD : - case LIBIRC_RFC_ERR_NOADMININFO : - case LIBIRC_RFC_ERR_FILEERROR : - case LIBIRC_RFC_ERR_NONICKNAMEGIVEN : - case LIBIRC_RFC_ERR_ERRONEUSNICKNAME : - case LIBIRC_RFC_ERR_UNAVAILRESOURCE : - case LIBIRC_RFC_ERR_USERNOTINCHANNEL : - case LIBIRC_RFC_ERR_NOTONCHANNEL : - case LIBIRC_RFC_ERR_USERONCHANNEL : - case LIBIRC_RFC_ERR_NOLOGIN : - case LIBIRC_RFC_ERR_SUMMONDISABLED : - case LIBIRC_RFC_ERR_USERSDISABLED : - case LIBIRC_RFC_ERR_NOTREGISTERED : - case LIBIRC_RFC_ERR_NEEDMOREPARAMS : - case LIBIRC_RFC_ERR_ALREADYREGISTRED : - case LIBIRC_RFC_ERR_NOPERMFORHOST : - case LIBIRC_RFC_ERR_PASSWDMISMATCH : - case LIBIRC_RFC_ERR_YOUREBANNEDCREEP : - case LIBIRC_RFC_ERR_YOUWILLBEBANNED : - case LIBIRC_RFC_ERR_KEYSET : - case LIBIRC_RFC_ERR_CHANNELISFULL : - case LIBIRC_RFC_ERR_UNKNOWNMODE : - case LIBIRC_RFC_ERR_INVITEONLYCHAN : - case LIBIRC_RFC_ERR_BANNEDFROMCHAN : - case LIBIRC_RFC_ERR_BADCHANNELKEY : - case LIBIRC_RFC_ERR_BADCHANMASK : - case LIBIRC_RFC_ERR_NOCHANMODES : - case LIBIRC_RFC_ERR_BANLISTFULL : - case LIBIRC_RFC_ERR_NOPRIVILEGES : - case LIBIRC_RFC_ERR_CHANOPRIVSNEEDED : - case LIBIRC_RFC_ERR_CANTKILLSERVER : - case LIBIRC_RFC_ERR_RESTRICTED : - case LIBIRC_RFC_ERR_UNIQOPPRIVSNEEDED : - case LIBIRC_RFC_ERR_NOOPERHOST : - case LIBIRC_RFC_ERR_UMODEUNKNOWNFLAG : - case LIBIRC_RFC_ERR_USERSDONTMATCH : - irc_handle_server_error(session, irc_event); - break; - } -} - -IrcThread::IrcThread(IrcCallback &callback) -: m_callback(callback), m_terminationTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start) -{ - m_context.reset(new IrcContext(*this)); -} - -IrcThread::~IrcThread() -{ - IrcContext &context = GetContext(); - if (context.session) - irc_destroy_session(context.session); -} - -void -IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel, const std::string &channelPassword) -{ - if (IsRunning() || serverAddress.empty() || nick.empty() || channel.empty()) - return; // TODO: throw exception - - IrcContext &context = GetContext(); - - context.serverAddress = serverAddress; - context.serverPort = serverPort; - context.useIPv6 = ipv6; - context.nick = nick; - context.channel = channel; - context.channelPassword = channelPassword; - - // Initialize libirc stuff. - irc_callbacks_t callbacks; - memset (&callbacks, 0, sizeof(callbacks)); - - callbacks.event_connect = irc_event_connect; - callbacks.event_join = irc_event_join; - callbacks.event_nick = irc_event_nick; - callbacks.event_quit = irc_event_leave; - callbacks.event_part = irc_event_leave; - //callbacks.event_mode - //callbacks.event_topic - callbacks.event_kick = irc_event_kick; - callbacks.event_channel = irc_event_channel; - //callbacks.event_privmsg - //callbacks.event_notice - //callbacks.event_invite - //callbacks.event_umode - //callbacks.event_ctcp_rep - //callbacks.event_ctcp_action - //callbacks.event_unknown - callbacks.event_numeric = irc_event_numeric; - - //callbacks.event_dcc_chat_req - //callbacks.event_dcc_send_req - - context.session = irc_create_session(&callbacks); - - if (context.session) - { - irc_set_ctx(context.session, &context); - // We want nicknames only, strip them from nick!host. - irc_option_set(context.session, LIBIRC_OPTION_STRIPNICKS); - } -} - -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() -{ - Thread::SignalTermination(); - irc_cmd_quit(GetContext().session, NULL); -} - -void -IrcThread::Main() -{ - IrcContext &context = GetContext(); - - irc_session_t *s = context.session; - if (s) - { - bool connected = false; - if (context.useIPv6) - connected = irc_connect6(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) == 0; - else - connected = irc_connect(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) == 0; - - if (!connected) - HandleIrcError(irc_errno(s)); - else - { - // Main loop. - while (irc_is_connected(s)) - { - // Handle thread termination - gracefully. - if (!m_terminationTimer.is_running()) - { - if (ShouldTerminate()) - m_terminationTimer.start(); - } - else - { - if (m_terminationTimer.elapsed().total_milliseconds() > IRC_WAIT_TERMINATION_MSEC) - break; - } - - struct timeval timeout; - fd_set readSet, writeSet; - int maxfd = 0; - - - FD_ZERO(&readSet); - FD_ZERO(&writeSet); - timeout.tv_sec = 0; - timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000; - - irc_add_select_descriptors(s, &readSet, &writeSet, &maxfd); - - int selectResult = select(maxfd + 1, &readSet, &writeSet, 0, &timeout); - if (!IS_VALID_SELECT(selectResult)) - { - GetCallback().SignalIrcError(ERR_IRC_SELECT_FAILED); - break; - } - - if (irc_process_select_descriptors(s, &readSet, &writeSet) != 0) - { - int errorCode = irc_errno(s); - if (errorCode) - { - HandleIrcError(errorCode); - break; - } - } - Msleep(10); // paranoia - } - } - } -} - -void -IrcThread::HandleIrcError(int errorCode) -{ - int internalErrorCode = ERR_IRC_INTERNAL; - switch(errorCode) - { - case LIBIRC_ERR_RESOLV: - case LIBIRC_ERR_SOCKET: - case LIBIRC_ERR_CONNECT: - internalErrorCode = ERR_IRC_CONNECT_FAILED; - break; - case LIBIRC_ERR_INVAL: - case LIBIRC_ERR_STATE: - internalErrorCode = ERR_IRC_INVALID_PARAM; - break; - case LIBIRC_ERR_CLOSED: - case LIBIRC_ERR_TERMINATED: - internalErrorCode = ERR_IRC_TERMINATED; - break; - case LIBIRC_ERR_READ: - internalErrorCode = ERR_IRC_RECV_FAILED; - break; - case LIBIRC_ERR_WRITE: - internalErrorCode = ERR_IRC_SEND_FAILED; - break; - case LIBIRC_ERR_TIMEOUT: - internalErrorCode = ERR_IRC_TIMEOUT; - break; - } - GetCallback().SignalIrcError(internalErrorCode); -} - -const IrcContext & -IrcThread::GetContext() const -{ - assert(m_context.get()); - return *m_context; -} - -IrcContext & -IrcThread::GetContext() -{ - assert(m_context.get()); - return *m_context; -} - -IrcCallback & -IrcThread::GetCallback() -{ - return m_callback; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define IRC_WAIT_TERMINATION_MSEC 500 +#define IRC_MAX_RENAME_TRIES 5 + + +struct IrcContext +{ + IrcContext(IrcThread &t) : ircThread(t), session(NULL), serverPort(0), useIPv6(false), renameTries(0) {} + IrcThread &ircThread; + irc_session_t *session; + string serverAddress; + unsigned serverPort; + bool useIPv6; + string nick; + string channel; + string channelPassword; + unsigned renameTries; +}; + +void irc_auto_rename_nick(irc_session_t *session) +{ + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + if (context->renameTries <= IRC_MAX_RENAME_TRIES) // Limit number of rename tries. + { + // Automatically rename the nick on collision. + // First: Try to append the string "Lobby". + if (context->nick.find("|Lobby") == string::npos) + { + context->nick = context->nick + "|Lobby"; + } + else + { + // This didn't work out. Append a number or increment it. + string::reverse_iterator end = context->nick.rbegin(); + if (!context->nick.empty() && isdigit(*end)) + { + if (*end != '9') + *end = (*end) + 1; + else + context->nick = context->nick + "0"; + } + else + context->nick = context->nick + "1"; + } + irc_cmd_nick(session, context->nick.c_str()); + context->renameTries++; + } + else + irc_cmd_quit(session, NULL); +} + +void irc_notify_player_list(irc_session_t *session, const char *players) +{ + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + istringstream input(players); + string name; + input >> name; + while (!input.fail() && !input.eof()) + { + context->ircThread.GetCallback().SignalIrcPlayerJoined(name); + input >> name; + } +} + +void irc_handle_server_error(irc_session_t *session, unsigned irc_error_code) +{ + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + context->ircThread.GetCallback().SignalIrcServerError(irc_error_code); +} + +void +irc_event_connect(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char ** /*params*/, unsigned /*count*/) +{ + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + context->ircThread.GetCallback().SignalIrcConnect(origin); + irc_cmd_join(session, context->channel.c_str(), context->channelPassword.c_str()); +} + +void +irc_event_join(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char ** /*params*/, unsigned /*count*/) +{ + // someone joined the channel. + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + if (context->nick == origin) + context->ircThread.GetCallback().SignalIrcSelfJoined(context->nick, context->channel); + else + context->ircThread.GetCallback().SignalIrcPlayerJoined(origin); +} + +void +irc_event_nick(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char **params, unsigned count) +{ + // someone changed his/her nick + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + if (count && context->nick != params[0]) // only act if this was not an auto-rename + { + if (context->nick == origin) + context->nick = params[0]; + context->ircThread.GetCallback().SignalIrcPlayerChanged(origin, params[0]); + } +} + +void +irc_event_kick(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char **params, unsigned count) +{ + // someone got kicked + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + string byWhom(origin); + string who; + string reason; + if (count >= 2) + who = params[1]; + if (count >= 3) + reason = params[2]; + context->ircThread.GetCallback().SignalIrcPlayerKicked(who, byWhom, reason); + if (!who.empty()) + context->ircThread.GetCallback().SignalIrcPlayerLeft(who); +} + +void +irc_event_leave(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char ** /*params*/, unsigned /*count*/) +{ + // someone left the channel. + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + context->ircThread.GetCallback().SignalIrcPlayerLeft(origin); +} + +void +irc_event_channel(irc_session_t *session, const char * /*irc_event*/, const char *origin, const char **params, unsigned count) +{ + IrcContext *context = (IrcContext *) irc_get_ctx(session); + + if (count >= 2 && boost::algorithm::iequals(context->channel, params[0])) // check whether this message is for our channel + { + // Signal the message (if any) to GUI. + if (*params[1] != 0) + context->ircThread.GetCallback().SignalIrcChatMsg(origin, params[1]); + } +} + +void +irc_event_numeric(irc_session_t * session, unsigned irc_event, const char * /*origin*/, const char **params, unsigned count) +{ + switch (irc_event) + { + case LIBIRC_RFC_ERR_NICKNAMEINUSE : + case LIBIRC_RFC_ERR_NICKCOLLISION : + irc_auto_rename_nick(session); + break; + case LIBIRC_RFC_RPL_TOPIC : + break; + case LIBIRC_RFC_RPL_NAMREPLY : + if (count >= 4) + irc_notify_player_list(session, params[3]); + break; + case LIBIRC_RFC_ERR_NOSUCHNICK : + case LIBIRC_RFC_ERR_NOSUCHCHANNEL : + case LIBIRC_RFC_ERR_CANNOTSENDTOCHAN : + case LIBIRC_RFC_ERR_TOOMANYCHANNELS : + case LIBIRC_RFC_ERR_WASNOSUCHNICK : + case LIBIRC_RFC_ERR_TOOMANYTARGETS : + case LIBIRC_RFC_ERR_NOSUCHSERVICE : + case LIBIRC_RFC_ERR_NOORIGIN : + case LIBIRC_RFC_ERR_NORECIPIENT : + case LIBIRC_RFC_ERR_NOTEXTTOSEND : + case LIBIRC_RFC_ERR_NOTOPLEVEL : + case LIBIRC_RFC_ERR_WILDTOPLEVEL : + case LIBIRC_RFC_ERR_BADMASK : + case LIBIRC_RFC_ERR_UNKNOWNCOMMAND : + case LIBIRC_RFC_ERR_NOMOTD : + case LIBIRC_RFC_ERR_NOADMININFO : + case LIBIRC_RFC_ERR_FILEERROR : + case LIBIRC_RFC_ERR_NONICKNAMEGIVEN : + case LIBIRC_RFC_ERR_ERRONEUSNICKNAME : + case LIBIRC_RFC_ERR_UNAVAILRESOURCE : + case LIBIRC_RFC_ERR_USERNOTINCHANNEL : + case LIBIRC_RFC_ERR_NOTONCHANNEL : + case LIBIRC_RFC_ERR_USERONCHANNEL : + case LIBIRC_RFC_ERR_NOLOGIN : + case LIBIRC_RFC_ERR_SUMMONDISABLED : + case LIBIRC_RFC_ERR_USERSDISABLED : + case LIBIRC_RFC_ERR_NOTREGISTERED : + case LIBIRC_RFC_ERR_NEEDMOREPARAMS : + case LIBIRC_RFC_ERR_ALREADYREGISTRED : + case LIBIRC_RFC_ERR_NOPERMFORHOST : + case LIBIRC_RFC_ERR_PASSWDMISMATCH : + case LIBIRC_RFC_ERR_YOUREBANNEDCREEP : + case LIBIRC_RFC_ERR_YOUWILLBEBANNED : + case LIBIRC_RFC_ERR_KEYSET : + case LIBIRC_RFC_ERR_CHANNELISFULL : + case LIBIRC_RFC_ERR_UNKNOWNMODE : + case LIBIRC_RFC_ERR_INVITEONLYCHAN : + case LIBIRC_RFC_ERR_BANNEDFROMCHAN : + case LIBIRC_RFC_ERR_BADCHANNELKEY : + case LIBIRC_RFC_ERR_BADCHANMASK : + case LIBIRC_RFC_ERR_NOCHANMODES : + case LIBIRC_RFC_ERR_BANLISTFULL : + case LIBIRC_RFC_ERR_NOPRIVILEGES : + case LIBIRC_RFC_ERR_CHANOPRIVSNEEDED : + case LIBIRC_RFC_ERR_CANTKILLSERVER : + case LIBIRC_RFC_ERR_RESTRICTED : + case LIBIRC_RFC_ERR_UNIQOPPRIVSNEEDED : + case LIBIRC_RFC_ERR_NOOPERHOST : + case LIBIRC_RFC_ERR_UMODEUNKNOWNFLAG : + case LIBIRC_RFC_ERR_USERSDONTMATCH : + irc_handle_server_error(session, irc_event); + break; + } +} + +IrcThread::IrcThread(IrcCallback &callback) +: m_callback(callback), m_terminationTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start) +{ + m_context.reset(new IrcContext(*this)); +} + +IrcThread::~IrcThread() +{ + IrcContext &context = GetContext(); + if (context.session) + irc_destroy_session(context.session); +} + +void +IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel, const std::string &channelPassword) +{ + if (IsRunning() || serverAddress.empty() || nick.empty() || channel.empty()) + return; // TODO: throw exception + + IrcContext &context = GetContext(); + + context.serverAddress = serverAddress; + context.serverPort = serverPort; + context.useIPv6 = ipv6; + context.nick = nick; + context.channel = channel; + context.channelPassword = channelPassword; + + // Initialize libirc stuff. + irc_callbacks_t callbacks; + memset (&callbacks, 0, sizeof(callbacks)); + + callbacks.event_connect = irc_event_connect; + callbacks.event_join = irc_event_join; + callbacks.event_nick = irc_event_nick; + callbacks.event_quit = irc_event_leave; + callbacks.event_part = irc_event_leave; + //callbacks.event_mode + //callbacks.event_topic + callbacks.event_kick = irc_event_kick; + callbacks.event_channel = irc_event_channel; + //callbacks.event_privmsg + //callbacks.event_notice + //callbacks.event_invite + //callbacks.event_umode + //callbacks.event_ctcp_rep + //callbacks.event_ctcp_action + //callbacks.event_unknown + callbacks.event_numeric = irc_event_numeric; + + //callbacks.event_dcc_chat_req + //callbacks.event_dcc_send_req + + context.session = irc_create_session(&callbacks); + + if (context.session) + { + irc_set_ctx(context.session, &context); + // We want nicknames only, strip them from nick!host. + irc_option_set(context.session, LIBIRC_OPTION_STRIPNICKS); + } +} + +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() +{ + Thread::SignalTermination(); + irc_cmd_quit(GetContext().session, NULL); +} + +void +IrcThread::Main() +{ + IrcContext &context = GetContext(); + + irc_session_t *s = context.session; + if (s) + { + bool connected = false; + if (context.useIPv6) + connected = irc_connect6(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) == 0; + else + connected = irc_connect(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) == 0; + + if (!connected) + HandleIrcError(irc_errno(s)); + else + { + // Main loop. + while (irc_is_connected(s)) + { + // Handle thread termination - gracefully. + if (!m_terminationTimer.is_running()) + { + if (ShouldTerminate()) + m_terminationTimer.start(); + } + else + { + if (m_terminationTimer.elapsed().total_milliseconds() > IRC_WAIT_TERMINATION_MSEC) + break; + } + + struct timeval timeout; + fd_set readSet, writeSet; + int maxfd = 0; + + + FD_ZERO(&readSet); + FD_ZERO(&writeSet); + timeout.tv_sec = 0; + timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000; + + irc_add_select_descriptors(s, &readSet, &writeSet, &maxfd); + + int selectResult = select(maxfd + 1, &readSet, &writeSet, 0, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + GetCallback().SignalIrcError(ERR_IRC_SELECT_FAILED); + break; + } + + if (irc_process_select_descriptors(s, &readSet, &writeSet) != 0) + { + int errorCode = irc_errno(s); + if (errorCode) + { + HandleIrcError(errorCode); + break; + } + } + Msleep(10); // paranoia + } + } + } +} + +void +IrcThread::HandleIrcError(int errorCode) +{ + int internalErrorCode = ERR_IRC_INTERNAL; + switch(errorCode) + { + case LIBIRC_ERR_RESOLV: + case LIBIRC_ERR_SOCKET: + case LIBIRC_ERR_CONNECT: + internalErrorCode = ERR_IRC_CONNECT_FAILED; + break; + case LIBIRC_ERR_INVAL: + case LIBIRC_ERR_STATE: + internalErrorCode = ERR_IRC_INVALID_PARAM; + break; + case LIBIRC_ERR_CLOSED: + case LIBIRC_ERR_TERMINATED: + internalErrorCode = ERR_IRC_TERMINATED; + break; + case LIBIRC_ERR_READ: + internalErrorCode = ERR_IRC_RECV_FAILED; + break; + case LIBIRC_ERR_WRITE: + internalErrorCode = ERR_IRC_SEND_FAILED; + break; + case LIBIRC_ERR_TIMEOUT: + internalErrorCode = ERR_IRC_TIMEOUT; + break; + } + GetCallback().SignalIrcError(internalErrorCode); +} + +const IrcContext & +IrcThread::GetContext() const +{ + assert(m_context.get()); + return *m_context; +} + +IrcContext & +IrcThread::GetContext() +{ + assert(m_context.get()); + return *m_context; +} + +IrcCallback & +IrcThread::GetCallback() +{ + return m_callback; +} + diff --git a/src/net/common/netcontext.cpp b/src/net/common/netcontext.cpp index 611c6340..f28e1c8d 100644 --- a/src/net/common/netcontext.cpp +++ b/src/net/common/netcontext.cpp @@ -1,25 +1,25 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -NetContext::~NetContext() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +NetContext::~NetContext() +{ +} + diff --git a/src/net/common/netexception.cpp b/src/net/common/netexception.cpp index f70c295b..cf552a82 100644 --- a/src/net/common/netexception.cpp +++ b/src/net/common/netexception.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -NetException::~NetException() throw() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +NetException::~NetException() throw() +{ +} + diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index d252608a..53a3eb6b 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -1,4598 +1,4598 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include - -#include - -using namespace std; - -#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2) - -#define NET_TYPE_INIT 0x0001 -#define NET_TYPE_INIT_ACK 0x0002 -#define NET_TYPE_RETRIEVE_AVATAR 0x0003 -#define NET_TYPE_AVATAR_HEADER 0x0004 -#define NET_TYPE_AVATAR_FILE 0x0005 -#define NET_TYPE_AVATAR_END 0x0006 -#define NET_TYPE_UNKNOWN_AVATAR 0x0007 -#define NET_TYPE_GAME_LIST_NEW 0x0010 -#define NET_TYPE_GAME_LIST_UPDATE 0x0011 -#define NET_TYPE_GAME_LIST_PLAYER_JOINED 0x0012 -#define NET_TYPE_GAME_LIST_PLAYER_LEFT 0x0013 -#define NET_TYPE_GAME_LIST_ADMIN_CHANGED 0x0014 -#define NET_TYPE_RETRIEVE_PLAYER_INFO 0x0020 -#define NET_TYPE_PLAYER_INFO 0x0021 -#define NET_TYPE_UNKNOWN_PLAYER_ID 0x0022 -#define NET_TYPE_CREATE_GAME 0x0030 -#define NET_TYPE_JOIN_GAME 0x0031 -#define NET_TYPE_JOIN_GAME_ACK 0x0032 -#define NET_TYPE_JOIN_GAME_FAILED 0x0033 -#define NET_TYPE_PLAYER_JOINED 0x0034 -#define NET_TYPE_PLAYER_LEFT 0x0035 -#define NET_TYPE_GAME_ADMIN_CHANGED 0x0036 -#define NET_TYPE_KICK_PLAYER 0x0040 -#define NET_TYPE_LEAVE_CURRENT_GAME 0x0041 -#define NET_TYPE_START_EVENT 0x0042 -#define NET_TYPE_START_EVENT_ACK 0x0043 -#define NET_TYPE_GAME_START 0x0050 -#define NET_TYPE_HAND_START 0x0051 -#define NET_TYPE_PLAYERS_TURN 0x0052 -#define NET_TYPE_PLAYERS_ACTION 0x0053 -#define NET_TYPE_PLAYERS_ACTION_DONE 0x0054 -#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x0055 -#define NET_TYPE_DEAL_FLOP_CARDS 0x0060 -#define NET_TYPE_DEAL_TURN_CARD 0x0061 -#define NET_TYPE_DEAL_RIVER_CARD 0x0062 -#define NET_TYPE_ALL_IN_SHOW_CARDS 0x0063 -#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x0064 -#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0065 -#define NET_TYPE_END_OF_GAME 0x0070 -#define NET_TYPE_STATISTICS_CHANGED 0x0080 - -#define NET_TYPE_REMOVED_FROM_GAME 0x0100 - -#define NET_TYPE_SEND_CHAT_TEXT 0x0200 -#define NET_TYPE_CHAT_TEXT 0x0201 - -#define NET_TYPE_ERROR 0x0400 - -#define NET_GAME_FLAG_PASSWORD_PROTECTED 0x01 - -#define NET_PLAYER_FLAG_HUMAN 0x01 -#define NET_PLAYER_FLAG_HAS_AVATAR 0x02 - -#define NET_START_FLAG_FILL_WITH_CPU_PLAYERS 0x01 - -#define NET_PRIVACY_FLAG_SHOW_AVATAR 0x01 - -// Reasons why join game failed. -#define NET_JOIN_FAILED_GAME_FULL 0x0001 -#define NET_JOIN_FAILED_GAME_ALREADY_RUNNING 0x0002 -#define NET_JOIN_FAILED_INVALID_PASSWORD 0x0003 -#define NET_JOIN_FAILED_OTHER 0xFFFF - -// Reasons for being removed from a game. -#define NET_REMOVED_ON_REQUEST 0x0000 -#define NET_REMOVED_GAME_FULL 0x0001 -#define NET_REMOVED_GAME_ALREADY_RUNNING 0x0002 -#define NET_REMOVED_KICKED 0x0003 -#define NET_REMOVED_OTHER_REASON 0xFFFF - -// Internal error codes. -#define NET_ERR_RESERVED 0x0000 -#define NET_ERR_INIT_VERSION_NOT_SUPPORTED 0x0001 -#define NET_ERR_INIT_SERVER_FULL 0x0002 -#define NET_ERR_INIT_INVALID_PASSWORD 0x0004 -#define NET_ERR_INIT_PLAYER_NAME_IN_USE 0x0005 -#define NET_ERR_INIT_INVALID_PLAYER_NAME 0x0006 -#define NET_ERR_INIT_SERVER_MAINTENANCE 0x0007 -#define NET_ERR_AVATAR_TOO_LARGE 0x0010 -#define NET_ERR_AVATAR_WRONG_SIZE 0x0011 -#define NET_ERR_JOIN_GAME_UNKNOWN_GAME 0x0020 -#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 - -// Statistics types -#define NET_STAT_CUR_PLAYERS_ON_SERVER 0x0001 -#define NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER 0x0002 -#define NET_STAT_TOTAL_GAMES_EVER_ON_SERVER 0x0003 - -#ifdef _MSC_VER - #pragma pack(push, 1) - #define GCC_PACKED -#else - #define GCC_PACKED __attribute__ ((__packed__)) -#endif - - -struct GCC_PACKED NetPacketHeader -{ - u_int16_t type; - u_int16_t length; -}; - -struct GCC_PACKED NetPacketInitData -{ - NetPacketHeader head; - u_int16_t requestedVersionMajor; - u_int16_t requestedVersionMinor; - u_int16_t passwordLength; - u_int16_t playerNameLength; - u_int16_t privacyFlags; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketInitAckData -{ - NetPacketHeader head; - u_int16_t latestGameVersion; - u_int16_t latestBetaRevision; - u_int32_t sessionId; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketRetrieveAvatarData -{ - NetPacketHeader head; - u_int32_t requestId; - unsigned char avatarMD5[MD5_DATA_SIZE]; -}; - -struct GCC_PACKED NetPacketAvatarHeaderData -{ - NetPacketHeader head; - u_int32_t requestId; - u_int32_t avatarFileSize; - u_int16_t avatarFileType; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketAvatarFileData -{ - NetPacketHeader head; - u_int32_t requestId; - u_int16_t blockSize; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketAvatarEndData -{ - NetPacketHeader head; - u_int32_t requestId; -}; - -struct GCC_PACKED NetPacketUnknownAvatarData -{ - NetPacketHeader head; - u_int32_t requestId; -}; - -struct GCC_PACKED GameInfoData -{ - u_int16_t maxNumberOfPlayers; - u_int16_t raiseIntervalMode; - u_int16_t raiseSmallBlindInterval; - u_int16_t raiseMode; - u_int16_t endRaiseMode; - u_int16_t numberOfManualBlinds; - u_int16_t proposedGuiSpeed; - u_int16_t playerActionTimeout; - u_int32_t firstSmallBlind; - u_int32_t endRaiseSmallBlindValue; - u_int32_t startMoney; -}; - -struct GCC_PACKED NetPacketGameListNewData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int32_t adminPlayerId; - u_int16_t gameMode; - u_int16_t gameNameLength; - u_int16_t curNumberOfPlayers; - u_int16_t gameFlags; - GameInfoData gameData; -}; - -struct GCC_PACKED NetPacketGameListUpdateData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int16_t gameMode; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketGameListPlayerJoinedData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketGameListPlayerLeftData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketGameListAdminChangedData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int32_t newAdminPlayerId; -}; - -struct GCC_PACKED NetPacketRetrievePlayerInfoData -{ - NetPacketHeader head; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketPlayerInfoData -{ - NetPacketHeader head; - u_int32_t playerId; - u_int16_t playerFlags; - u_int16_t playerNameLength; - u_int32_t reserved; -}; - -struct GCC_PACKED NetPacketUnknownPlayerIdData -{ - NetPacketHeader head; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketCreateGameData -{ - NetPacketHeader head; - u_int16_t passwordLength; - u_int16_t gameNameLength; - GameInfoData gameData; -}; - -struct GCC_PACKED NetPacketJoinGameData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int16_t passwordLength; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketJoinGameAckData -{ - NetPacketHeader head; - u_int32_t gameId; - u_int16_t playerRights; - u_int16_t reserved; - GameInfoData gameData; -}; - -struct GCC_PACKED NetPacketJoinGameFailedData -{ - NetPacketHeader head; - u_int16_t failureReason; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketPlayerJoinedData -{ - NetPacketHeader head; - u_int32_t playerId; - u_int16_t playerRights; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketPlayerLeftData -{ - NetPacketHeader head; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketGameAdminChangedData -{ - NetPacketHeader head; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketKickPlayerData -{ - NetPacketHeader head; - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketLeaveCurrentGameData -{ - NetPacketHeader head; - u_int32_t reserved; -}; - -struct GCC_PACKED NetPacketStartEventData -{ - NetPacketHeader head; - u_int16_t startFlags; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketStartEventAckData -{ - NetPacketHeader head; - u_int32_t reserved; -}; - -struct GCC_PACKED NetPacketGameStartData -{ - NetPacketHeader head; - u_int32_t startDealerPlayerId; - u_int16_t numberOfPlayers; - u_int16_t reserved; -}; - -struct GCC_PACKED PlayerSlotData -{ - u_int32_t playerId; -}; - -struct GCC_PACKED NetPacketHandStartData -{ - NetPacketHeader head; - u_int16_t yourCard1; - u_int16_t yourCard2; - u_int32_t smallBlind; -}; - -struct GCC_PACKED NetPacketPlayersTurnData -{ - NetPacketHeader head; - u_int32_t playerId; - u_int32_t minimumRaise; - u_int16_t gameState; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketPlayersActionData -{ - NetPacketHeader head; - u_int16_t gameState; - u_int16_t playerAction; - u_int32_t playerBet; -}; - -struct GCC_PACKED NetPacketPlayersActionDoneData -{ - NetPacketHeader head; - u_int32_t playerId; - u_int16_t gameState; - u_int16_t playerAction; - u_int32_t totalPlayerBet; - u_int32_t playerMoney; - u_int32_t highestSet; -}; - -struct GCC_PACKED NetPacketPlayersActionRejectedData -{ - NetPacketHeader head; - u_int16_t gameState; - u_int16_t playerAction; - u_int32_t playerBet; - u_int16_t rejectionReason; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketDealFlopCardsData -{ - NetPacketHeader head; - u_int16_t flopCard1; - u_int16_t flopCard2; - u_int16_t flopCard3; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketDealTurnCardData -{ - NetPacketHeader head; - u_int16_t turnCard; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketDealRiverCardData -{ - NetPacketHeader head; - u_int16_t riverCard; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketAllInShowCardsData -{ - NetPacketHeader head; - u_int16_t numberOfPlayerCards; - u_int16_t reserved; -}; - -struct GCC_PACKED PlayerCardsData -{ - u_int32_t playerId; - u_int16_t card1; - u_int16_t card2; -}; - -struct GCC_PACKED NetPacketEndOfHandShowCardsData -{ - NetPacketHeader head; - u_int16_t numberOfPlayerResults; - u_int16_t reserved; -}; - -struct GCC_PACKED PlayerResultData -{ - u_int32_t playerId; - u_int16_t card1; - u_int16_t card2; - u_int16_t bestHandPos1; - u_int16_t bestHandPos2; - u_int16_t bestHandPos3; - u_int16_t bestHandPos4; - u_int16_t bestHandPos5; - u_int16_t reserved; - u_int32_t valueOfCards; - u_int32_t moneyWon; - u_int32_t playerMoney; -}; - -struct GCC_PACKED NetPacketEndOfHandHideCardsData -{ - NetPacketHeader head; - u_int32_t playerId; - u_int32_t moneyWon; - u_int32_t playerMoney; -}; - -struct GCC_PACKED NetPacketEndOfGameData -{ - NetPacketHeader head; - u_int32_t winnerPlayerId; -}; - -struct GCC_PACKED StatisticsData -{ - u_int32_t statisticsType; - u_int32_t statisticsValue; -}; - -struct GCC_PACKED NetPacketStatisticsChangedData -{ - NetPacketHeader head; - u_int16_t numberOfStatistics; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketRemovedFromGameData -{ - NetPacketHeader head; - u_int16_t removeReason; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketSendChatTextData -{ - NetPacketHeader head; - u_int16_t textLength; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketChatTextData -{ - NetPacketHeader head; - u_int32_t playerId; - u_int16_t textLength; - u_int16_t reserved; -}; - -struct GCC_PACKED NetPacketErrorData -{ - NetPacketHeader head; - u_int16_t errorReason; - u_int16_t reserved; -}; - -#ifdef _MSC_VER - #pragma pack(pop) -#endif - -// Helper functions - -void SetGameInfoData(const GameData &inData, GameInfoData *outData) -{ - assert(outData); - - u_int16_t numManualBlinds = (u_int16_t)inData.manualBlindsList.size(); - - outData->maxNumberOfPlayers = htons(inData.maxNumberOfPlayers); - outData->raiseIntervalMode = htons(inData.raiseIntervalMode); - outData->raiseSmallBlindInterval = inData.raiseIntervalMode == RAISE_ON_HANDNUMBER - ? htons(inData.raiseSmallBlindEveryHandsValue) : htons(inData.raiseSmallBlindEveryMinutesValue); - outData->raiseMode = htons(inData.raiseMode); - outData->endRaiseMode = htons(inData.afterManualBlindsMode); - outData->numberOfManualBlinds = htons(numManualBlinds); - outData->proposedGuiSpeed = htons(inData.guiSpeed); - outData->playerActionTimeout = htons(inData.playerActionTimeoutSec); - outData->endRaiseSmallBlindValue = htonl(inData.afterMBAlwaysRaiseValue); - outData->firstSmallBlind = htonl(inData.firstSmallBlind); - outData->startMoney = htonl(inData.startMoney); - - if (numManualBlinds) - { - u_int32_t *manualBlindsPtr = (u_int32_t *)((char *)outData + sizeof(GameInfoData)); - list::const_iterator i = inData.manualBlindsList.begin(); - list::const_iterator end = inData.manualBlindsList.end(); - while (i != end) - { - *manualBlindsPtr = htonl(*i); - ++manualBlindsPtr; - ++i; - } - } -} - -void GetGameInfoData(const GameInfoData *inData, GameData &outData) -{ - assert(inData); - - u_int16_t numManualBlinds = ntohs(inData->numberOfManualBlinds); - - outData.maxNumberOfPlayers = ntohs(inData->maxNumberOfPlayers); - outData.raiseIntervalMode = static_cast(ntohs(inData->raiseIntervalMode)); - outData.raiseSmallBlindEveryHandsValue = outData.raiseSmallBlindEveryMinutesValue = 0; - if (outData.raiseIntervalMode == RAISE_ON_HANDNUMBER) - outData.raiseSmallBlindEveryHandsValue = ntohs(inData->raiseSmallBlindInterval); - else - outData.raiseSmallBlindEveryMinutesValue = ntohs(inData->raiseSmallBlindInterval); - outData.raiseMode = static_cast(ntohs(inData->raiseMode)); - outData.afterManualBlindsMode = static_cast(ntohs(inData->endRaiseMode)); - outData.guiSpeed = ntohs(inData->proposedGuiSpeed); - outData.playerActionTimeoutSec = ntohs(inData->playerActionTimeout); - outData.firstSmallBlind = ntohl(inData->firstSmallBlind); - outData.afterMBAlwaysRaiseValue = ntohl(inData->endRaiseSmallBlindValue); - outData.startMoney = ntohl(inData->startMoney); - - if (numManualBlinds) - { - const u_int32_t *manualBlindsPtr = (const u_int32_t *)((const char *)inData + sizeof(GameInfoData)); - for (u_int16_t i = 0; i < numManualBlinds; i++) - { - outData.manualBlindsList.push_back(ntohl(*manualBlindsPtr)); - ++manualBlindsPtr; - } - } -} - -void -CheckGameInfoData(const GameInfoData *tmpData) -{ - // Semantic checks - int maxNumPlayers = ntohs(tmpData->maxNumberOfPlayers); - int proposedGuiSpeed = ntohs(tmpData->proposedGuiSpeed); - if (maxNumPlayers < MIN_NUMBER_OF_PLAYERS - || maxNumPlayers > MAX_NUMBER_OF_PLAYERS - || !ntohs(tmpData->raiseIntervalMode) - || !ntohs(tmpData->raiseSmallBlindInterval) - || !ntohs(tmpData->raiseMode) - || !ntohs(tmpData->endRaiseMode) - || proposedGuiSpeed < MIN_GUI_SPEED - || proposedGuiSpeed > MAX_GUI_SPEED - || !ntohl(tmpData->firstSmallBlind) - || !ntohl(tmpData->startMoney)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -boost::shared_ptr -NetPacket::Create(char *data, unsigned &dataSize) -{ - boost::shared_ptr tmpPacket; - - // Check minimum requirements. - if (!data || dataSize < sizeof(NetPacketHeader)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - - NetPacketHeader *tmpHeader = (NetPacketHeader *)data; - u_int16_t tmpLen = ntohs(tmpHeader->length); - - // Check size restrictions. - if (tmpLen < sizeof(NetPacketHeader) - || tmpLen > MAX_PACKET_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - else if (dataSize >= tmpLen) - { - // OK - we have a complete packet. - // Construct a corresponding object. - try - { - switch(ntohs(tmpHeader->type)) - { - case NET_TYPE_INIT: - tmpPacket = boost::shared_ptr(new NetPacketInit); - break; - case NET_TYPE_INIT_ACK: - tmpPacket = boost::shared_ptr(new NetPacketInitAck); - break; - case NET_TYPE_RETRIEVE_AVATAR: - tmpPacket = boost::shared_ptr(new NetPacketRetrieveAvatar); - break; - case NET_TYPE_AVATAR_HEADER: - tmpPacket = boost::shared_ptr(new NetPacketAvatarHeader); - break; - case NET_TYPE_AVATAR_FILE: - tmpPacket = boost::shared_ptr(new NetPacketAvatarFile); - break; - case NET_TYPE_AVATAR_END: - tmpPacket = boost::shared_ptr(new NetPacketAvatarEnd); - break; - case NET_TYPE_UNKNOWN_AVATAR: - tmpPacket = boost::shared_ptr(new NetPacketUnknownAvatar); - break; - case NET_TYPE_GAME_LIST_NEW: - tmpPacket = boost::shared_ptr(new NetPacketGameListNew); - break; - case NET_TYPE_GAME_LIST_UPDATE: - tmpPacket = boost::shared_ptr(new NetPacketGameListUpdate); - break; - case NET_TYPE_GAME_LIST_PLAYER_JOINED: - tmpPacket = boost::shared_ptr(new NetPacketGameListPlayerJoined); - break; - case NET_TYPE_GAME_LIST_PLAYER_LEFT: - tmpPacket = boost::shared_ptr(new NetPacketGameListPlayerLeft); - break; - case NET_TYPE_GAME_LIST_ADMIN_CHANGED: - tmpPacket = boost::shared_ptr(new NetPacketGameListAdminChanged); - break; - case NET_TYPE_RETRIEVE_PLAYER_INFO: - tmpPacket = boost::shared_ptr(new NetPacketRetrievePlayerInfo); - break; - case NET_TYPE_PLAYER_INFO: - tmpPacket = boost::shared_ptr(new NetPacketPlayerInfo); - break; - case NET_TYPE_UNKNOWN_PLAYER_ID: - tmpPacket = boost::shared_ptr(new NetPacketUnknownPlayerId); - break; - case NET_TYPE_CREATE_GAME: - tmpPacket = boost::shared_ptr(new NetPacketCreateGame); - break; - case NET_TYPE_JOIN_GAME: - tmpPacket = boost::shared_ptr(new NetPacketJoinGame); - break; - case NET_TYPE_JOIN_GAME_ACK: - tmpPacket = boost::shared_ptr(new NetPacketJoinGameAck); - break; - case NET_TYPE_JOIN_GAME_FAILED: - tmpPacket = boost::shared_ptr(new NetPacketJoinGameFailed); - break; - case NET_TYPE_PLAYER_JOINED: - tmpPacket = boost::shared_ptr(new NetPacketPlayerJoined); - break; - case NET_TYPE_PLAYER_LEFT: - tmpPacket = boost::shared_ptr(new NetPacketPlayerLeft); - break; - case NET_TYPE_GAME_ADMIN_CHANGED: - tmpPacket = boost::shared_ptr(new NetPacketGameAdminChanged); - break; - case NET_TYPE_KICK_PLAYER: - tmpPacket = boost::shared_ptr(new NetPacketKickPlayer); - break; - case NET_TYPE_LEAVE_CURRENT_GAME: - tmpPacket = boost::shared_ptr(new NetPacketLeaveCurrentGame); - break; - case NET_TYPE_START_EVENT: - tmpPacket = boost::shared_ptr(new NetPacketStartEvent); - break; - case NET_TYPE_START_EVENT_ACK: - tmpPacket = boost::shared_ptr(new NetPacketStartEventAck); - break; - case NET_TYPE_GAME_START: - tmpPacket = boost::shared_ptr(new NetPacketGameStart); - break; - case NET_TYPE_HAND_START: - tmpPacket = boost::shared_ptr(new NetPacketHandStart); - break; - case NET_TYPE_PLAYERS_TURN: - tmpPacket = boost::shared_ptr(new NetPacketPlayersTurn); - break; - case NET_TYPE_PLAYERS_ACTION: - tmpPacket = boost::shared_ptr(new NetPacketPlayersAction); - break; - case NET_TYPE_PLAYERS_ACTION_DONE: - tmpPacket = boost::shared_ptr(new NetPacketPlayersActionDone); - break; - case NET_TYPE_PLAYERS_ACTION_REJECTED: - tmpPacket = boost::shared_ptr(new NetPacketPlayersActionRejected); - break; - case NET_TYPE_DEAL_FLOP_CARDS: - tmpPacket = boost::shared_ptr(new NetPacketDealFlopCards); - break; - case NET_TYPE_DEAL_TURN_CARD: - tmpPacket = boost::shared_ptr(new NetPacketDealTurnCard); - break; - case NET_TYPE_DEAL_RIVER_CARD: - tmpPacket = boost::shared_ptr(new NetPacketDealRiverCard); - break; - case NET_TYPE_ALL_IN_SHOW_CARDS: - tmpPacket = boost::shared_ptr(new NetPacketAllInShowCards); - break; - case NET_TYPE_END_OF_HAND_SHOW_CARDS: - tmpPacket = boost::shared_ptr(new NetPacketEndOfHandShowCards); - break; - case NET_TYPE_END_OF_HAND_HIDE_CARDS: - tmpPacket = boost::shared_ptr(new NetPacketEndOfHandHideCards); - break; - case NET_TYPE_END_OF_GAME: - tmpPacket = boost::shared_ptr(new NetPacketEndOfGame); - break; - case NET_TYPE_STATISTICS_CHANGED: - tmpPacket = boost::shared_ptr(new NetPacketStatisticsChanged); - break; - case NET_TYPE_REMOVED_FROM_GAME: - tmpPacket = boost::shared_ptr(new NetPacketRemovedFromGame); - break; - case NET_TYPE_SEND_CHAT_TEXT: - tmpPacket = boost::shared_ptr(new NetPacketSendChatText); - break; - case NET_TYPE_CHAT_TEXT: - tmpPacket = boost::shared_ptr(new NetPacketChatText); - break; - case NET_TYPE_ERROR: - tmpPacket = boost::shared_ptr(new NetPacketError); - break; - default: - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_TYPE, 0); - } - if (tmpPacket.get()) - tmpPacket->SetRawData(tmpHeader); - } catch (const NetException &) - { - tmpPacket.reset(); - } - - // Consume the bytes. - if (tmpLen < dataSize) - { - dataSize -= tmpLen; - memmove(data, data + tmpLen, dataSize); - } - else - dataSize = 0; - } - return tmpPacket; -} - -NetPacket::NetPacket(u_int16_t type, u_int16_t initialSize, u_int16_t maxSize) -: m_data(NULL), m_initialSize(initialSize), m_maxSize(maxSize) -{ - assert(initialSize >= sizeof(NetPacketHeader)); - m_data = static_cast(malloc(initialSize)); - assert(m_data); - memset(m_data, 0, initialSize); - m_data->type = htons(type); - m_data->length = htons(initialSize); -} - -NetPacket::~NetPacket() -{ - if (m_data) - free(m_data); -} - -const NetPacketHeader * -NetPacket::GetRawData() const -{ - assert(m_data); - return m_data; -} - -NetPacketHeader * -NetPacket::GetRawData() -{ - assert(m_data); - return m_data; -} - -void -NetPacket::SetRawData(const NetPacketHeader *p) -{ - if (!p) - return; - assert(m_data); - - u_int16_t tmpLen = ntohs(p->length); - if (ntohs(p->type) != GetType()) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check whether the data is valid. - Check(p); - // Resize makes sure m_data is large enough. - Resize(tmpLen); - memcpy(m_data, p, tmpLen); -} - -u_int16_t -NetPacket::GetType() const -{ - return ntohs(GetRawData()->type); -} - -u_int16_t -NetPacket::GetLen() const -{ - return ntohs(GetRawData()->length); -} - -const NetPacketInit * -NetPacket::ToNetPacketInit() const -{ - return NULL; -} - -const NetPacketInitAck * -NetPacket::ToNetPacketInitAck() const -{ - return NULL; -} - -const NetPacketRetrieveAvatar * -NetPacket::ToNetPacketRetrieveAvatar() const -{ - return NULL; -} - -const NetPacketAvatarHeader * -NetPacket::ToNetPacketAvatarHeader() const -{ - return NULL; -} - -const NetPacketAvatarFile * -NetPacket::ToNetPacketAvatarFile() const -{ - return NULL; -} - -const NetPacketAvatarEnd * -NetPacket::ToNetPacketAvatarEnd() const -{ - return NULL; -} - -const NetPacketUnknownAvatar * -NetPacket::ToNetPacketUnknownAvatar() const -{ - return NULL; -} - -const NetPacketGameListNew * -NetPacket::ToNetPacketGameListNew() const -{ - return NULL; -} - -const NetPacketGameListUpdate * -NetPacket::ToNetPacketGameListUpdate() const -{ - return NULL; -} - -const NetPacketGameListPlayerJoined * -NetPacket::ToNetPacketGameListPlayerJoined() const -{ - return NULL; -} - -const NetPacketGameListPlayerLeft * -NetPacket::ToNetPacketGameListPlayerLeft() const -{ - return NULL; -} - -const NetPacketGameListAdminChanged * -NetPacket::ToNetPacketGameListAdminChanged() const -{ - return NULL; -} - -const NetPacketRetrievePlayerInfo * -NetPacket::ToNetPacketRetrievePlayerInfo() const -{ - return NULL; -} - -const NetPacketPlayerInfo * -NetPacket::ToNetPacketPlayerInfo() const -{ - return NULL; -} - -const NetPacketUnknownPlayerId * -NetPacket::ToNetPacketUnknownPlayerId() const -{ - return NULL; -} - -const NetPacketCreateGame * -NetPacket::ToNetPacketCreateGame() const -{ - return NULL; -} - -const NetPacketJoinGame * -NetPacket::ToNetPacketJoinGame() const -{ - return NULL; -} - -const NetPacketJoinGameAck * -NetPacket::ToNetPacketJoinGameAck() const -{ - return NULL; -} - -const NetPacketJoinGameFailed * -NetPacket::ToNetPacketJoinGameFailed() const -{ - return NULL; -} - -const NetPacketPlayerJoined * -NetPacket::ToNetPacketPlayerJoined() const -{ - return NULL; -} - -const NetPacketPlayerLeft * -NetPacket::ToNetPacketPlayerLeft() const -{ - return NULL; -} - -const NetPacketGameAdminChanged * -NetPacket::ToNetPacketGameAdminChanged() const -{ - return NULL; -} - -const NetPacketKickPlayer * -NetPacket::ToNetPacketKickPlayer() const -{ - return NULL; -} - -const NetPacketLeaveCurrentGame * -NetPacket::ToNetPacketLeaveCurrentGame() const -{ - return NULL; -} - -const NetPacketStartEvent * -NetPacket::ToNetPacketStartEvent() const -{ - return NULL; -} - -const NetPacketStartEventAck * -NetPacket::ToNetPacketStartEventAck() const -{ - return NULL; -} - -const NetPacketGameStart * -NetPacket::ToNetPacketGameStart() const -{ - return NULL; -} - -const NetPacketHandStart * -NetPacket::ToNetPacketHandStart() const -{ - return NULL; -} - -const NetPacketPlayersTurn * -NetPacket::ToNetPacketPlayersTurn() const -{ - return NULL; -} - -const NetPacketPlayersAction * -NetPacket::ToNetPacketPlayersAction() const -{ - return NULL; -} - -const NetPacketPlayersActionDone * -NetPacket::ToNetPacketPlayersActionDone() const -{ - return NULL; -} - -const NetPacketPlayersActionRejected * -NetPacket::ToNetPacketPlayersActionRejected() const -{ - return NULL; -} - -const NetPacketDealFlopCards * -NetPacket::ToNetPacketDealFlopCards() const -{ - return NULL; -} - -const NetPacketDealTurnCard * -NetPacket::ToNetPacketDealTurnCard() const -{ - return NULL; -} - -const NetPacketDealRiverCard * -NetPacket::ToNetPacketDealRiverCard() const -{ - return NULL; -} - -const NetPacketAllInShowCards * -NetPacket::ToNetPacketAllInShowCards() const -{ - return NULL; -} - -const NetPacketEndOfHandShowCards * -NetPacket::ToNetPacketEndOfHandShowCards() const -{ - return NULL; -} - -const NetPacketEndOfHandHideCards * -NetPacket::ToNetPacketEndOfHandHideCards() const -{ - return NULL; -} - -const NetPacketEndOfGame * -NetPacket::ToNetPacketEndOfGame() const -{ - return NULL; -} - -const NetPacketStatisticsChanged * -NetPacket::ToNetPacketStatisticsChanged() const -{ - return NULL; -} - -const NetPacketRemovedFromGame * -NetPacket::ToNetPacketRemovedFromGame() const -{ - return NULL; -} - -const NetPacketSendChatText * -NetPacket::ToNetPacketSendChatText() const -{ - return NULL; -} - -const NetPacketChatText * -NetPacket::ToNetPacketChatText() const -{ - return NULL; -} - -const NetPacketError * -NetPacket::ToNetPacketError() const -{ - return NULL; -} - -void -NetPacket::Resize(u_int16_t newLen) -{ - assert(m_data); - u_int16_t oldLen = GetLen(); - if (newLen != oldLen) - { - if (newLen < sizeof(NetPacketHeader)) - throw NetException(__FILE__, __LINE__, ERR_SOCK_INTERNAL, 0); - else - { - NetPacketHeader *newData = (NetPacketHeader *)malloc(newLen); - if (!newData) - throw NetException(__FILE__, __LINE__, ERR_SOCK_INTERNAL, 0); - else - { - // Copy as much data as possible. - memcpy(newData, m_data, newLen > oldLen ? oldLen : newLen); - // Initialize new data to 0. - if (newLen > oldLen) - memset(((unsigned char *)newData) + oldLen, 0, newLen - oldLen); - // Set new len. - newData->length = htons(newLen); - // Switch over to new data. - free(m_data); - m_data = newData; - } - } - } -} - -void -NetPacket::Check(const NetPacketHeader *data) const -{ - // Check the input data. - assert(data); - - // Check minimum and maximum size. - u_int16_t dataLen = ntohs(data->length); - if (dataLen < m_initialSize || dataLen > m_maxSize) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - - InternalCheck(data); -} - -//----------------------------------------------------------------------------- - -NetPacketInit::NetPacketInit() -: NetPacket(NET_TYPE_INIT, sizeof(NetPacketInitData), MAX_PACKET_SIZE) -{ - NetPacketInitData *tmpData = (NetPacketInitData *)GetRawData(); - tmpData->requestedVersionMajor = htons(NET_VERSION_MAJOR); - tmpData->requestedVersionMinor = htons(NET_VERSION_MINOR); -} - -NetPacketInit::~NetPacketInit() -{ -} - -boost::shared_ptr -NetPacketInit::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketInit); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketInit::SetData(const NetPacketInit::Data &inData) -{ - u_int16_t playerNameLen = (u_int16_t)inData.playerName.length(); - u_int16_t passwordLen = (u_int16_t)inData.password.length(); - - // Some basic checks, so we don't use up too much memory. - // The constructed packet will also be checked. - if (!playerNameLen || playerNameLen > MAX_NAME_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_NAME, 0); - if (passwordLen > MAX_PASSWORD_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD_STR, 0); - - int avatarSize = inData.showAvatar ? MD5_DATA_SIZE : 0; - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketInitData) - + avatarSize - + ADD_PADDING(playerNameLen) - + ADD_PADDING(passwordLen))); - - NetPacketInitData *tmpData = (NetPacketInitData *)GetRawData(); - - // Set the data. - tmpData->passwordLength = htons(passwordLen); - tmpData->playerNameLength = htons(playerNameLen); - - if (inData.showAvatar) - { - // Store MD5 sum of avatar. - tmpData->privacyFlags = htons(NET_PRIVACY_FLAG_SHOW_AVATAR); - char *avatarPtr = (char *)tmpData + sizeof(NetPacketInitData); - memcpy(avatarPtr, inData.avatar.data, MD5_DATA_SIZE); - } - - char *passwordPtr = (char *)tmpData + sizeof(NetPacketInitData) + avatarSize; - memcpy(passwordPtr, inData.password.c_str(), passwordLen); - memcpy(passwordPtr + ADD_PADDING(passwordLen), inData.playerName.c_str(), playerNameLen); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketInit::GetData(NetPacketInit::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketInitData *tmpData = (NetPacketInitData *)GetRawData(); - - outData.versionMajor = ntohs(tmpData->requestedVersionMajor); - outData.versionMinor = ntohs(tmpData->requestedVersionMinor); - - outData.showAvatar = ntohs(tmpData->privacyFlags) & NET_PRIVACY_FLAG_SHOW_AVATAR; - - if (outData.showAvatar) - { - char *avatarPtr = (char *)tmpData + sizeof(NetPacketInitData); - memcpy(outData.avatar.data, avatarPtr, MD5_DATA_SIZE); - } - - int avatarSize = outData.showAvatar ? MD5_DATA_SIZE : 0; - u_int16_t passwordLen = ntohs(tmpData->passwordLength); - char *passwordPtr = (char *)tmpData + sizeof(NetPacketInitData) + avatarSize; - outData.password = string(passwordPtr, passwordLen); - outData.playerName = string(passwordPtr + ADD_PADDING(passwordLen), ntohs(tmpData->playerNameLength)); -} - -const NetPacketInit * -NetPacketInit::ToNetPacketInit() const -{ - return this; -} - -void -NetPacketInit::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketInitData *tmpData = (NetPacketInitData *)data; - int passwordLength = ntohs(tmpData->passwordLength); - int playerNameLength = ntohs(tmpData->playerNameLength); - int avatarSize = ntohs(tmpData->privacyFlags) & NET_PRIVACY_FLAG_SHOW_AVATAR ? MD5_DATA_SIZE : 0; - // Generous checking of dynamic packet size - - // larger packets are allowed. - // This is because the version number is in this packet, - // and later versions might provide larger packets. - if (dataLen < - sizeof(NetPacketInitData) - + avatarSize - + ADD_PADDING(passwordLength) - + ADD_PADDING(playerNameLength)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string sizes. - if (passwordLength > MAX_PASSWORD_SIZE - || !playerNameLength - || playerNameLength > MAX_NAME_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check name string. - char *namePtr = (char *)tmpData + sizeof(NetPacketInitData) + avatarSize + ADD_PADDING(passwordLength); - if (namePtr[0] == 0) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketInitAck::NetPacketInitAck() -: NetPacket(NET_TYPE_INIT_ACK, sizeof(NetPacketInitAckData), sizeof(NetPacketInitAckData)) -{ -} - -NetPacketInitAck::~NetPacketInitAck() -{ -} - -boost::shared_ptr -NetPacketInitAck::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketInitAck); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketInitAck::SetData(const NetPacketInitAck::Data &inData) -{ - NetPacketInitAckData *tmpData = (NetPacketInitAckData *)GetRawData(); - - tmpData->latestGameVersion = htons(inData.latestGameVersion); - tmpData->latestBetaRevision = htons(inData.latestBetaRevision); - tmpData->sessionId = htonl(inData.sessionId); - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketInitAck::GetData(NetPacketInitAck::Data &outData) const -{ - NetPacketInitAckData *tmpData = (NetPacketInitAckData *)GetRawData(); - - outData.latestGameVersion = ntohs(tmpData->latestGameVersion); - outData.latestBetaRevision = ntohs(tmpData->latestBetaRevision); - outData.sessionId = ntohl(tmpData->sessionId); - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketInitAck * -NetPacketInitAck::ToNetPacketInitAck() const -{ - return this; -} - -void -NetPacketInitAck::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketRetrieveAvatar::NetPacketRetrieveAvatar() -: NetPacket(NET_TYPE_RETRIEVE_AVATAR, sizeof(NetPacketRetrieveAvatarData), sizeof(NetPacketRetrieveAvatarData)) -{ -} - -NetPacketRetrieveAvatar::~NetPacketRetrieveAvatar() -{ -} - -boost::shared_ptr -NetPacketRetrieveAvatar::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketRetrieveAvatar); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketRetrieveAvatar::SetData(const NetPacketRetrieveAvatar::Data &inData) -{ - NetPacketRetrieveAvatarData *tmpData = (NetPacketRetrieveAvatarData *)GetRawData(); - - tmpData->requestId = htonl(inData.requestId); - memcpy(tmpData->avatarMD5, inData.avatar.data, MD5_DATA_SIZE); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketRetrieveAvatar::GetData(NetPacketRetrieveAvatar::Data &outData) const -{ - NetPacketRetrieveAvatarData *tmpData = (NetPacketRetrieveAvatarData *)GetRawData(); - - outData.requestId = ntohl(tmpData->requestId); - memcpy(outData.avatar.data, tmpData->avatarMD5, MD5_DATA_SIZE); -} - -const NetPacketRetrieveAvatar * -NetPacketRetrieveAvatar::ToNetPacketRetrieveAvatar() const -{ - return this; -} - -void -NetPacketRetrieveAvatar::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketAvatarHeader::NetPacketAvatarHeader() -: NetPacket(NET_TYPE_AVATAR_HEADER, sizeof(NetPacketAvatarHeaderData), sizeof(NetPacketAvatarHeaderData)) -{ -} - -NetPacketAvatarHeader::~NetPacketAvatarHeader() -{ -} - -boost::shared_ptr -NetPacketAvatarHeader::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketAvatarHeader); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketAvatarHeader::SetData(const NetPacketAvatarHeader::Data &inData) -{ - NetPacketAvatarHeaderData *tmpData = (NetPacketAvatarHeaderData *)GetRawData(); - - tmpData->requestId = htonl(inData.requestId); - tmpData->avatarFileSize = htonl(inData.avatarFileSize); - tmpData->avatarFileType = htons(inData.avatarFileType); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketAvatarHeader::GetData(NetPacketAvatarHeader::Data &outData) const -{ - NetPacketAvatarHeaderData *tmpData = (NetPacketAvatarHeaderData *)GetRawData(); - - outData.requestId = ntohl(tmpData->requestId); - outData.avatarFileSize = ntohl(tmpData->avatarFileSize); - outData.avatarFileType = static_cast(ntohs(tmpData->avatarFileType)); -} - -const NetPacketAvatarHeader * -NetPacketAvatarHeader::ToNetPacketAvatarHeader() const -{ - return this; -} - -void -NetPacketAvatarHeader::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketAvatarFile::NetPacketAvatarFile() -: NetPacket(NET_TYPE_AVATAR_FILE, sizeof(NetPacketAvatarFileData), MAX_PACKET_SIZE) -{ -} - -NetPacketAvatarFile::~NetPacketAvatarFile() -{ -} - -boost::shared_ptr -NetPacketAvatarFile::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketAvatarFile); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketAvatarFile::SetData(const NetPacketAvatarFile::Data &inData) -{ - int fileDataSize = static_cast(inData.fileData.size()); - - if (fileDataSize > MAX_FILE_DATA_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_BUF_INVALID_SIZE, 0); - - Resize((u_int16_t) - (sizeof(NetPacketAvatarFileData) - + ADD_PADDING(fileDataSize))); - - NetPacketAvatarFileData *tmpData = (NetPacketAvatarFileData *)GetRawData(); - - tmpData->requestId = htonl(inData.requestId); - tmpData->blockSize = htons(fileDataSize); - - char *avatarDataPtr = (char *)tmpData + sizeof(NetPacketAvatarFileData); - memcpy(avatarDataPtr, &inData.fileData[0], fileDataSize); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketAvatarFile::GetData(NetPacketAvatarFile::Data &outData) const -{ - NetPacketAvatarFileData *tmpData = (NetPacketAvatarFileData *)GetRawData(); - - outData.requestId = ntohl(tmpData->requestId); - int fileDataSize = ntohs(tmpData->blockSize); - - char *avatarDataPtr = (char *)tmpData + sizeof(NetPacketAvatarFileData); - outData.fileData.resize(fileDataSize); - memcpy(&outData.fileData[0], avatarDataPtr, fileDataSize); -} - -const NetPacketAvatarFile * -NetPacketAvatarFile::ToNetPacketAvatarFile() const -{ - return this; -} - -void -NetPacketAvatarFile::InternalCheck(const NetPacketHeader *data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketAvatarFileData *tmpData = (NetPacketAvatarFileData *)data; - int fileDataSize = ntohs(tmpData->blockSize); - - // Exact checking of dynamic packet size. - if (dataLen != - sizeof(NetPacketAvatarFileData) - + ADD_PADDING(fileDataSize)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - if (!fileDataSize || fileDataSize > MAX_FILE_DATA_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketAvatarEnd::NetPacketAvatarEnd() -: NetPacket(NET_TYPE_AVATAR_END, sizeof(NetPacketAvatarEndData), sizeof(NetPacketAvatarEndData)) -{ -} - -NetPacketAvatarEnd::~NetPacketAvatarEnd() -{ -} - -boost::shared_ptr -NetPacketAvatarEnd::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketAvatarEnd); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketAvatarEnd::SetData(const NetPacketAvatarEnd::Data &inData) -{ - NetPacketAvatarEndData *tmpData = (NetPacketAvatarEndData *)GetRawData(); - - tmpData->requestId = htonl(inData.requestId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketAvatarEnd::GetData(NetPacketAvatarEnd::Data &outData) const -{ - NetPacketAvatarEndData *tmpData = (NetPacketAvatarEndData *)GetRawData(); - - outData.requestId = ntohl(tmpData->requestId); -} - -const NetPacketAvatarEnd * -NetPacketAvatarEnd::ToNetPacketAvatarEnd() const -{ - return this; -} - -void -NetPacketAvatarEnd::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketUnknownAvatar::NetPacketUnknownAvatar() -: NetPacket(NET_TYPE_UNKNOWN_AVATAR, sizeof(NetPacketUnknownAvatarData), sizeof(NetPacketUnknownAvatarData)) -{ -} - -NetPacketUnknownAvatar::~NetPacketUnknownAvatar() -{ -} - -boost::shared_ptr -NetPacketUnknownAvatar::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketUnknownAvatar); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketUnknownAvatar::SetData(const NetPacketUnknownAvatar::Data &inData) -{ - NetPacketUnknownAvatarData *tmpData = (NetPacketUnknownAvatarData *)GetRawData(); - - tmpData->requestId = htonl(inData.requestId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketUnknownAvatar::GetData(NetPacketUnknownAvatar::Data &outData) const -{ - NetPacketUnknownAvatarData *tmpData = (NetPacketUnknownAvatarData *)GetRawData(); - - outData.requestId = ntohl(tmpData->requestId); -} - -const NetPacketUnknownAvatar * -NetPacketUnknownAvatar::ToNetPacketUnknownAvatar() const -{ - return this; -} - -void -NetPacketUnknownAvatar::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketGameListNew::NetPacketGameListNew() -: NetPacket(NET_TYPE_GAME_LIST_NEW, sizeof(NetPacketGameListNewData), MAX_PACKET_SIZE) -{ -} - -NetPacketGameListNew::~NetPacketGameListNew() -{ -} - -boost::shared_ptr -NetPacketGameListNew::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameListNew); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) -{ - u_int16_t gameNameLen = (u_int16_t)inData.gameInfo.name.length(); - u_int16_t curNumPlayers = (u_int16_t)inData.gameInfo.players.size(); - u_int16_t numManualBlinds = (u_int16_t)inData.gameInfo.data.manualBlindsList.size(); - - int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); - - // Some basic checks, so we don't use up too much memory. - // The constructed packet will also be checked. - if (!gameNameLen || gameNameLen > MAX_NAME_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_GAME_NAME, 0); - if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) - throw NetException(__FILE__, __LINE__, ERR_NET_TOO_MANY_MANUAL_BLINDS, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketGameListNewData) - + manualBlindsSize - + ADD_PADDING(gameNameLen) - + curNumPlayers * sizeof(unsigned) - )); - - NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->adminPlayerId = htonl(inData.gameInfo.adminPlayerId); - tmpData->gameMode = htons(inData.gameInfo.mode); - tmpData->gameNameLength = htons(gameNameLen); - tmpData->curNumberOfPlayers = htons(curNumPlayers); - tmpData->gameFlags = htons(inData.gameInfo.isPasswordProtected ? NET_GAME_FLAG_PASSWORD_PROTECTED : 0); - - SetGameInfoData(inData.gameInfo.data, &tmpData->gameData); - - char *gameNamePtr = (char *)tmpData + sizeof(NetPacketGameListNewData) + manualBlindsSize; - memcpy(gameNamePtr, inData.gameInfo.name.c_str(), gameNameLen); - - PlayerIdList::const_iterator i = inData.gameInfo.players.begin(); - PlayerIdList::const_iterator end = inData.gameInfo.players.end(); - - // Copy the player list to continous memory - unsigned *tmpPlayer = - (unsigned *)(gameNamePtr + ADD_PADDING(gameNameLen)); - while (i != end) - { - *tmpPlayer = htonl(*i); - ++tmpPlayer; - ++i; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameListNew::GetData(NetPacketGameListNew::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)GetRawData(); - - u_int16_t numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); - int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); - - outData.gameId = ntohl(tmpData->gameId); - outData.gameInfo.adminPlayerId = ntohl(tmpData->adminPlayerId); - outData.gameInfo.mode = static_cast(ntohs(tmpData->gameMode)); - u_int16_t gameNameLen = ntohs(tmpData->gameNameLength); - u_int16_t curNumPlayers = ntohs(tmpData->curNumberOfPlayers); - outData.gameInfo.isPasswordProtected = ntohs(tmpData->gameFlags) == NET_GAME_FLAG_PASSWORD_PROTECTED; - - GetGameInfoData(&tmpData->gameData, outData.gameInfo.data); - - char *gameNamePtr = (char *)tmpData + sizeof(NetPacketGameListNewData) + manualBlindsSize; - outData.gameInfo.name = string(gameNamePtr, gameNameLen); - - unsigned *tmpPlayer = (unsigned *)(gameNamePtr + ADD_PADDING(gameNameLen)); - - // Store all available players. - for (int i = 0; i < curNumPlayers; i++) - { - outData.gameInfo.players.push_back(ntohl(*tmpPlayer)); - ++tmpPlayer; - } -} - -const NetPacketGameListNew * -NetPacketGameListNew::ToNetPacketGameListNew() const -{ - return this; -} - -void -NetPacketGameListNew::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)data; - int gameNameLength = ntohs(tmpData->gameNameLength); - int curNumPlayers = ntohs(tmpData->curNumberOfPlayers); - u_int16_t numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); - int manualBlindsLength = numManualBlinds * sizeof(u_int32_t); - // Exact checking of dynamic packet size. - if (dataLen != - sizeof(NetPacketGameListNewData) - + manualBlindsLength - + ADD_PADDING(gameNameLength) - + curNumPlayers * sizeof(unsigned)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check manual blind list size - if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string size. - if (!gameNameLength - || gameNameLength > MAX_NAME_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check name string. - char *namePtr = (char *)tmpData + sizeof(NetPacketGameListNewData) + manualBlindsLength; - if (namePtr[0] == 0) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketGameListUpdate::NetPacketGameListUpdate() -: NetPacket(NET_TYPE_GAME_LIST_UPDATE, sizeof(NetPacketGameListUpdateData), sizeof(NetPacketGameListUpdateData)) -{ -} - -NetPacketGameListUpdate::~NetPacketGameListUpdate() -{ -} - -boost::shared_ptr -NetPacketGameListUpdate::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameListUpdate); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameListUpdate::SetData(const NetPacketGameListUpdate::Data &inData) -{ - NetPacketGameListUpdateData *tmpData = (NetPacketGameListUpdateData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->gameMode = htons(inData.gameMode); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameListUpdate::GetData(NetPacketGameListUpdate::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketGameListUpdateData *tmpData = (NetPacketGameListUpdateData *)GetRawData(); - - outData.gameId = ntohl(tmpData->gameId); - outData.gameMode = static_cast(ntohs(tmpData->gameMode)); -} - -const NetPacketGameListUpdate * -NetPacketGameListUpdate::ToNetPacketGameListUpdate() const -{ - return this; -} - -void -NetPacketGameListUpdate::InternalCheck(const NetPacketHeader*) const -{ -} - -//----------------------------------------------------------------------------- - -NetPacketGameListPlayerJoined::NetPacketGameListPlayerJoined() -: NetPacket(NET_TYPE_GAME_LIST_PLAYER_JOINED, sizeof(NetPacketGameListPlayerJoinedData), sizeof(NetPacketGameListPlayerJoinedData)) -{ -} - -NetPacketGameListPlayerJoined::~NetPacketGameListPlayerJoined() -{ -} - -boost::shared_ptr -NetPacketGameListPlayerJoined::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameListPlayerJoined); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameListPlayerJoined::SetData(const NetPacketGameListPlayerJoined::Data &inData) -{ - NetPacketGameListPlayerJoinedData *tmpData = (NetPacketGameListPlayerJoinedData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameListPlayerJoined::GetData(NetPacketGameListPlayerJoined::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketGameListPlayerJoinedData *tmpData = (NetPacketGameListPlayerJoinedData *)GetRawData(); - - outData.gameId = ntohl(tmpData->gameId); - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketGameListPlayerJoined * -NetPacketGameListPlayerJoined::ToNetPacketGameListPlayerJoined() const -{ - return this; -} - -void -NetPacketGameListPlayerJoined::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketGameListPlayerLeft::NetPacketGameListPlayerLeft() -: NetPacket(NET_TYPE_GAME_LIST_PLAYER_LEFT, sizeof(NetPacketGameListPlayerLeftData), sizeof(NetPacketGameListPlayerLeftData)) -{ -} - -NetPacketGameListPlayerLeft::~NetPacketGameListPlayerLeft() -{ -} - -boost::shared_ptr -NetPacketGameListPlayerLeft::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameListPlayerLeft); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameListPlayerLeft::SetData(const NetPacketGameListPlayerLeft::Data &inData) -{ - NetPacketGameListPlayerLeftData *tmpData = (NetPacketGameListPlayerLeftData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameListPlayerLeft::GetData(NetPacketGameListPlayerLeft::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketGameListPlayerLeftData *tmpData = (NetPacketGameListPlayerLeftData *)GetRawData(); - - outData.gameId = ntohl(tmpData->gameId); - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketGameListPlayerLeft * -NetPacketGameListPlayerLeft::ToNetPacketGameListPlayerLeft() const -{ - return this; -} - -void -NetPacketGameListPlayerLeft::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketGameListAdminChanged::NetPacketGameListAdminChanged() -: NetPacket(NET_TYPE_GAME_LIST_ADMIN_CHANGED, sizeof(NetPacketGameListAdminChangedData), sizeof(NetPacketGameListAdminChangedData)) -{ -} - -NetPacketGameListAdminChanged::~NetPacketGameListAdminChanged() -{ -} - -boost::shared_ptr -NetPacketGameListAdminChanged::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameListAdminChanged); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameListAdminChanged::SetData(const NetPacketGameListAdminChanged::Data &inData) -{ - NetPacketGameListAdminChangedData *tmpData = (NetPacketGameListAdminChangedData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->newAdminPlayerId = htonl(inData.newAdminplayerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameListAdminChanged::GetData(NetPacketGameListAdminChanged::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketGameListAdminChangedData *tmpData = (NetPacketGameListAdminChangedData *)GetRawData(); - - outData.gameId = ntohl(tmpData->gameId); - outData.newAdminplayerId = ntohl(tmpData->newAdminPlayerId); -} - -const NetPacketGameListAdminChanged * -NetPacketGameListAdminChanged::ToNetPacketGameListAdminChanged() const -{ - return this; -} - -void -NetPacketGameListAdminChanged::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketRetrievePlayerInfo::NetPacketRetrievePlayerInfo() -: NetPacket(NET_TYPE_RETRIEVE_PLAYER_INFO, sizeof(NetPacketRetrievePlayerInfoData), sizeof(NetPacketRetrievePlayerInfoData)) -{ -} - -NetPacketRetrievePlayerInfo::~NetPacketRetrievePlayerInfo() -{ -} - -boost::shared_ptr -NetPacketRetrievePlayerInfo::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketRetrievePlayerInfo); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketRetrievePlayerInfo::SetData(const NetPacketRetrievePlayerInfo::Data &inData) -{ - NetPacketRetrievePlayerInfoData *tmpData = (NetPacketRetrievePlayerInfoData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketRetrievePlayerInfo::GetData(NetPacketRetrievePlayerInfo::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketRetrievePlayerInfoData *tmpData = (NetPacketRetrievePlayerInfoData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketRetrievePlayerInfo * -NetPacketRetrievePlayerInfo::ToNetPacketRetrievePlayerInfo() const -{ - return this; -} - -void -NetPacketRetrievePlayerInfo::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketPlayerInfo::NetPacketPlayerInfo() -: NetPacket(NET_TYPE_PLAYER_INFO, sizeof(NetPacketPlayerInfoData), MAX_PACKET_SIZE) -{ -} - -NetPacketPlayerInfo::~NetPacketPlayerInfo() -{ -} - -boost::shared_ptr -NetPacketPlayerInfo::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayerInfo); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayerInfo::SetData(const NetPacketPlayerInfo::Data &inData) -{ - u_int16_t playerNameLen = (u_int16_t)inData.playerInfo.playerName.length(); - - if (!playerNameLen || playerNameLen > MAX_NAME_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_NAME, 0); - - int avatarSize = inData.playerInfo.hasAvatar ? MD5_DATA_SIZE : 0; - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketPlayerInfoData) + avatarSize + ADD_PADDING(playerNameLen))); - - NetPacketPlayerInfoData *tmpData = (NetPacketPlayerInfoData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - tmpData->playerNameLength = htons(playerNameLen); - - u_int16_t tmpPlayerFlags = inData.playerInfo.ptype == PLAYER_TYPE_HUMAN ? NET_PLAYER_FLAG_HUMAN : 0; - if (inData.playerInfo.hasAvatar) - { - tmpPlayerFlags |= NET_PLAYER_FLAG_HAS_AVATAR; - char *avatarPtr = (char *)tmpData + sizeof(NetPacketPlayerInfoData); - memcpy(avatarPtr, inData.playerInfo.avatar.data, MD5_DATA_SIZE); - } - tmpData->playerFlags = htons(tmpPlayerFlags); - - char *namePtr = (char *)tmpData + sizeof(NetPacketPlayerInfoData) + avatarSize; - memcpy(namePtr, inData.playerInfo.playerName.c_str(), playerNameLen); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayerInfo::GetData(NetPacketPlayerInfo::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketPlayerInfoData *tmpData = (NetPacketPlayerInfoData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); - u_int16_t tmpPlayerFlags = ntohs(tmpData->playerFlags); - outData.playerInfo.ptype = (tmpPlayerFlags & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER; - outData.playerInfo.hasAvatar = (tmpPlayerFlags & NET_PLAYER_FLAG_HAS_AVATAR) ? true : false; - - if (outData.playerInfo.hasAvatar) - { - char *avatarPtr = (char *)tmpData + sizeof(NetPacketPlayerInfoData); - memcpy(outData.playerInfo.avatar.data, avatarPtr, MD5_DATA_SIZE); - } - - int avatarSize = outData.playerInfo.hasAvatar ? MD5_DATA_SIZE : 0; - - char *namePtr = (char *)tmpData + avatarSize + sizeof(NetPacketPlayerInfoData); - outData.playerInfo.playerName = string(namePtr, ntohs(tmpData->playerNameLength)); -} - -const NetPacketPlayerInfo * -NetPacketPlayerInfo::ToNetPacketPlayerInfo() const -{ - return this; -} - -void -NetPacketPlayerInfo::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketPlayerInfoData *tmpData = (NetPacketPlayerInfoData *)data; - int playerNameLength = ntohs(tmpData->playerNameLength); - int avatarSize = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HAS_AVATAR) ? MD5_DATA_SIZE : 0; - // Exact checking this time. - if (dataLen != - sizeof(NetPacketPlayerInfoData) - + avatarSize - + ADD_PADDING(playerNameLength)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string sizes. - if (!playerNameLength - || playerNameLength > MAX_NAME_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketUnknownPlayerId::NetPacketUnknownPlayerId() -: NetPacket(NET_TYPE_UNKNOWN_PLAYER_ID, sizeof(NetPacketUnknownPlayerIdData), sizeof(NetPacketUnknownPlayerIdData)) -{ -} - -NetPacketUnknownPlayerId::~NetPacketUnknownPlayerId() -{ -} - -boost::shared_ptr -NetPacketUnknownPlayerId::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketUnknownPlayerId); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketUnknownPlayerId::SetData(const NetPacketUnknownPlayerId::Data &inData) -{ - NetPacketUnknownPlayerIdData *tmpData = (NetPacketUnknownPlayerIdData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketUnknownPlayerId::GetData(NetPacketUnknownPlayerId::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketUnknownPlayerIdData *tmpData = (NetPacketUnknownPlayerIdData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketUnknownPlayerId * -NetPacketUnknownPlayerId::ToNetPacketUnknownPlayerId() const -{ - return this; -} - -void -NetPacketUnknownPlayerId::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} -//----------------------------------------------------------------------------- - -NetPacketCreateGame::NetPacketCreateGame() -: NetPacket(NET_TYPE_CREATE_GAME, sizeof(NetPacketCreateGameData), MAX_PACKET_SIZE) -{ -} - -NetPacketCreateGame::~NetPacketCreateGame() -{ -} - -boost::shared_ptr -NetPacketCreateGame::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketCreateGame); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketCreateGame::SetData(const NetPacketCreateGame::Data &inData) -{ - u_int16_t gameNameLen = (u_int16_t)inData.gameName.length(); - u_int16_t passwordLen = (u_int16_t)inData.password.length(); - u_int16_t numManualBlinds = (u_int16_t)inData.gameData.manualBlindsList.size(); - - // Some basic checks, so we don't use up too much memory. - // The constructed packet will also be checked. - if (!gameNameLen || gameNameLen > MAX_NAME_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_NAME, 0); - if (passwordLen > MAX_PASSWORD_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD_STR, 0); - if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) - throw NetException(__FILE__, __LINE__, ERR_NET_TOO_MANY_MANUAL_BLINDS, 0); - - int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketCreateGameData) + manualBlindsSize + ADD_PADDING(gameNameLen) + ADD_PADDING(passwordLen))); - - NetPacketCreateGameData *tmpData = (NetPacketCreateGameData *)GetRawData(); - - // Set the data. - tmpData->passwordLength = htons(passwordLen); - tmpData->gameNameLength = htons(gameNameLen); - - SetGameInfoData(inData.gameData, &tmpData->gameData); - - char *passwordPtr = (char *)tmpData + sizeof(NetPacketCreateGameData) + manualBlindsSize; - memcpy(passwordPtr, inData.password.c_str(), passwordLen); - memcpy(passwordPtr + ADD_PADDING(passwordLen), inData.gameName.c_str(), gameNameLen); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketCreateGame::GetData(NetPacketCreateGame::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketCreateGameData *tmpData = (NetPacketCreateGameData *)GetRawData(); - - u_int16_t numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); - int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); - - GetGameInfoData(&tmpData->gameData, outData.gameData); - - u_int16_t passwordLen = ntohs(tmpData->passwordLength); - char *passwordPtr = (char *)tmpData + manualBlindsSize + sizeof(NetPacketCreateGameData); - outData.password = string(passwordPtr, passwordLen); - outData.gameName = string(passwordPtr + ADD_PADDING(passwordLen), ntohs(tmpData->gameNameLength)); -} - -const NetPacketCreateGame * -NetPacketCreateGame::ToNetPacketCreateGame() const -{ - return this; -} - -void -NetPacketCreateGame::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketCreateGameData *tmpData = (NetPacketCreateGameData *)data; - int passwordLength = ntohs(tmpData->passwordLength); - int gameNameLength = ntohs(tmpData->gameNameLength); - int numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); - int manualBlindsLength = numManualBlinds * sizeof(u_int32_t); - // Exact checking of dynamic packet size. - if (dataLen < - sizeof(NetPacketCreateGameData) - + manualBlindsLength - + ADD_PADDING(passwordLength) - + ADD_PADDING(gameNameLength)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check manual blind list size - if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string sizes. - if (passwordLength > MAX_PASSWORD_SIZE - || !gameNameLength - || gameNameLength > MAX_NAME_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check name string. - char *namePtr = (char *)tmpData + sizeof(NetPacketCreateGameData) + manualBlindsLength + ADD_PADDING(passwordLength); - if (namePtr[0] == 0) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - CheckGameInfoData(&tmpData->gameData); -} - -//----------------------------------------------------------------------------- - -NetPacketJoinGame::NetPacketJoinGame() -: NetPacket(NET_TYPE_JOIN_GAME, sizeof(NetPacketJoinGameData), MAX_PACKET_SIZE) -{ -} - -NetPacketJoinGame::~NetPacketJoinGame() -{ -} - -boost::shared_ptr -NetPacketJoinGame::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketJoinGame); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketJoinGame::SetData(const NetPacketJoinGame::Data &inData) -{ - u_int16_t passwordLen = (u_int16_t)inData.password.length(); - - // Some basic checks, so we don't use up too much memory. - // The constructed packet will also be checked. - if (passwordLen > MAX_PASSWORD_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD_STR, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketJoinGameData) + ADD_PADDING(passwordLen))); - - NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->passwordLength = htons(passwordLen); - - char *passwordPtr = (char *)tmpData + sizeof(NetPacketJoinGameData); - memcpy(passwordPtr, inData.password.c_str(), passwordLen); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketJoinGame::GetData(NetPacketJoinGame::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData(); - - outData.gameId = ntohl(tmpData->gameId); - - u_int16_t passwordLen = ntohs(tmpData->passwordLength); - char *passwordPtr = (char *)tmpData + sizeof(NetPacketJoinGameData); - outData.password = string(passwordPtr, passwordLen); -} - -const NetPacketJoinGame * -NetPacketJoinGame::ToNetPacketJoinGame() const -{ - return this; -} - -void -NetPacketJoinGame::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)data; - int passwordLength = ntohs(tmpData->passwordLength); - // Exact checking of dynamic packet size. - if (dataLen < - sizeof(NetPacketJoinGameData) - + ADD_PADDING(passwordLength)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string size. - if (passwordLength > MAX_PASSWORD_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketJoinGameAck::NetPacketJoinGameAck() -: NetPacket(NET_TYPE_JOIN_GAME_ACK, sizeof(NetPacketJoinGameAckData), MAX_PACKET_SIZE) -{ -} - -NetPacketJoinGameAck::~NetPacketJoinGameAck() -{ -} - -boost::shared_ptr -NetPacketJoinGameAck::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketJoinGameAck); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketJoinGameAck::SetData(const NetPacketJoinGameAck::Data &inData) -{ - u_int16_t numManualBlinds = (u_int16_t)inData.gameData.manualBlindsList.size(); - - // Some basic checks, so we don't use up too much memory. - // The constructed packet will also be checked. - if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) - throw NetException(__FILE__, __LINE__, ERR_NET_TOO_MANY_MANUAL_BLINDS, 0); - - int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketJoinGameAckData) + manualBlindsSize)); - - NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)GetRawData(); - - // Set the data. - tmpData->gameId = htonl(inData.gameId); - tmpData->playerRights = htons(inData.prights); - - SetGameInfoData(inData.gameData, &tmpData->gameData); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketJoinGameAck::GetData(NetPacketJoinGameAck::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)GetRawData(); - - outData.gameId = ntohl(tmpData->gameId); - outData.prights = static_cast(ntohs(tmpData->playerRights)); - - GetGameInfoData(&tmpData->gameData, outData.gameData); -} - -const NetPacketJoinGameAck * -NetPacketJoinGameAck::ToNetPacketJoinGameAck() const -{ - return this; -} - -void -NetPacketJoinGameAck::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)data; - int numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); - int manualBlindsLength = numManualBlinds * sizeof(u_int32_t); - // Exact checking of dynamic packet size. - if (dataLen < - sizeof(NetPacketJoinGameAckData) - + manualBlindsLength) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - - // Check manual blind list size - if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Semantic checks - CheckGameInfoData(&tmpData->gameData); -} - -//----------------------------------------------------------------------------- - -NetPacketJoinGameFailed::NetPacketJoinGameFailed() -: NetPacket(NET_TYPE_JOIN_GAME_FAILED, sizeof(NetPacketJoinGameFailedData), sizeof(NetPacketJoinGameFailedData)) -{ -} - -NetPacketJoinGameFailed::~NetPacketJoinGameFailed() -{ -} - -boost::shared_ptr -NetPacketJoinGameFailed::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketJoinGameFailed); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketJoinGameFailed::SetData(const NetPacketJoinGameFailed::Data &inData) -{ - NetPacketJoinGameFailedData *tmpData = (NetPacketJoinGameFailedData *)GetRawData(); - - switch (inData.failureCode) - { - // Join Game Errors. - case NTF_NET_JOIN_GAME_FULL : - tmpData->failureReason = htons(NET_JOIN_FAILED_GAME_FULL); - break; - case NTF_NET_JOIN_ALREADY_RUNNING : - tmpData->failureReason = htons(NET_JOIN_FAILED_GAME_ALREADY_RUNNING); - break; - case NTF_NET_JOIN_INVALID_PASSWORD : - tmpData->failureReason = htons(NET_JOIN_FAILED_INVALID_PASSWORD); - break; - default : - tmpData->failureReason = htons(NET_JOIN_FAILED_OTHER); - break; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketJoinGameFailed::GetData(NetPacketJoinGameFailed::Data &outData) const -{ - NetPacketJoinGameFailedData *tmpData = (NetPacketJoinGameFailedData *)GetRawData(); - - switch (ntohs(tmpData->failureReason)) - { - // Join Game Errors. - case NET_JOIN_FAILED_GAME_FULL : - outData.failureCode = NTF_NET_JOIN_GAME_FULL; - break; - case NET_JOIN_FAILED_GAME_ALREADY_RUNNING : - outData.failureCode = NTF_NET_JOIN_ALREADY_RUNNING; - break; - case NET_JOIN_FAILED_INVALID_PASSWORD : - outData.failureCode = NTF_NET_JOIN_INVALID_PASSWORD; - break; - default : - outData.failureCode = NTF_NET_INTERNAL; - break; - } -} - -const NetPacketJoinGameFailed * -NetPacketJoinGameFailed::ToNetPacketJoinGameFailed() const -{ - return this; -} - -void -NetPacketJoinGameFailed::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketPlayerJoined::NetPacketPlayerJoined() -: NetPacket(NET_TYPE_PLAYER_JOINED, sizeof(NetPacketPlayerJoinedData), sizeof(NetPacketPlayerJoinedData)) -{ -} - -NetPacketPlayerJoined::~NetPacketPlayerJoined() -{ -} - -boost::shared_ptr -NetPacketPlayerJoined::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayerJoined); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayerJoined::SetData(const NetPacketPlayerJoined::Data &inData) -{ - NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - tmpData->playerRights = htons(inData.prights); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayerJoined::GetData(NetPacketPlayerJoined::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); - outData.prights = static_cast(ntohs(tmpData->playerRights)); -} - -const NetPacketPlayerJoined * -NetPacketPlayerJoined::ToNetPacketPlayerJoined() const -{ - return this; -} - -void -NetPacketPlayerJoined::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketPlayerLeft::NetPacketPlayerLeft() -: NetPacket(NET_TYPE_PLAYER_LEFT, sizeof(NetPacketPlayerLeftData), sizeof(NetPacketPlayerLeftData)) -{ -} - -NetPacketPlayerLeft::~NetPacketPlayerLeft() -{ -} - -boost::shared_ptr -NetPacketPlayerLeft::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayerLeft); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayerLeft::SetData(const NetPacketPlayerLeft::Data &inData) -{ - NetPacketPlayerLeftData *tmpData = (NetPacketPlayerLeftData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayerLeft::GetData(NetPacketPlayerLeft::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketPlayerLeftData *tmpData = (NetPacketPlayerLeftData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketPlayerLeft * -NetPacketPlayerLeft::ToNetPacketPlayerLeft() const -{ - return this; -} - -void -NetPacketPlayerLeft::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - - -//----------------------------------------------------------------------------- - -NetPacketGameAdminChanged::NetPacketGameAdminChanged() -: NetPacket(NET_TYPE_GAME_ADMIN_CHANGED, sizeof(NetPacketGameAdminChangedData), sizeof(NetPacketGameAdminChangedData)) -{ -} - -NetPacketGameAdminChanged::~NetPacketGameAdminChanged() -{ -} - -boost::shared_ptr -NetPacketGameAdminChanged::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameAdminChanged); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameAdminChanged::SetData(const NetPacketGameAdminChanged::Data &inData) -{ - NetPacketGameAdminChangedData *tmpData = (NetPacketGameAdminChangedData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameAdminChanged::GetData(NetPacketGameAdminChanged::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketGameAdminChangedData *tmpData = (NetPacketGameAdminChangedData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketGameAdminChanged * -NetPacketGameAdminChanged::ToNetPacketGameAdminChanged() const -{ - return this; -} - -void -NetPacketGameAdminChanged::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketKickPlayer::NetPacketKickPlayer() -: NetPacket(NET_TYPE_KICK_PLAYER, sizeof(NetPacketKickPlayerData), sizeof(NetPacketKickPlayerData)) -{ -} - -NetPacketKickPlayer::~NetPacketKickPlayer() -{ -} - -boost::shared_ptr -NetPacketKickPlayer::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketKickPlayer); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketKickPlayer::SetData(const NetPacketKickPlayer::Data &inData) -{ - NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketKickPlayer::GetData(NetPacketKickPlayer::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); -} - -const NetPacketKickPlayer * -NetPacketKickPlayer::ToNetPacketKickPlayer() const -{ - return this; -} - -void -NetPacketKickPlayer::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketLeaveCurrentGame::NetPacketLeaveCurrentGame() -: NetPacket(NET_TYPE_LEAVE_CURRENT_GAME, sizeof(NetPacketLeaveCurrentGameData), sizeof(NetPacketLeaveCurrentGameData)) -{ -} - -NetPacketLeaveCurrentGame::~NetPacketLeaveCurrentGame() -{ -} - -boost::shared_ptr -NetPacketLeaveCurrentGame::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketLeaveCurrentGame); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -const NetPacketLeaveCurrentGame * -NetPacketLeaveCurrentGame::ToNetPacketLeaveCurrentGame() const -{ - return this; -} - -void -NetPacketLeaveCurrentGame::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketStartEvent::NetPacketStartEvent() -: NetPacket(NET_TYPE_START_EVENT, sizeof(NetPacketStartEventData), sizeof(NetPacketStartEventData)) -{ -} - -NetPacketStartEvent::~NetPacketStartEvent() -{ -} - -boost::shared_ptr -NetPacketStartEvent::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketStartEvent); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketStartEvent::SetData(const NetPacketStartEvent::Data &inData) -{ - NetPacketStartEventData *tmpData = (NetPacketStartEventData *)GetRawData(); - - // Set the data. - tmpData->startFlags = htons(inData.fillUpWithCpuPlayers ? NET_START_FLAG_FILL_WITH_CPU_PLAYERS : 0); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketStartEvent::GetData(NetPacketStartEvent::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketStartEventData *tmpData = (NetPacketStartEventData *)GetRawData(); - - outData.fillUpWithCpuPlayers = (ntohs(tmpData->startFlags) & NET_START_FLAG_FILL_WITH_CPU_PLAYERS); -} - -const NetPacketStartEvent * -NetPacketStartEvent::ToNetPacketStartEvent() const -{ - return this; -} - -void -NetPacketStartEvent::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketStartEventAck::NetPacketStartEventAck() -: NetPacket(NET_TYPE_START_EVENT_ACK, sizeof(NetPacketStartEventAckData), sizeof(NetPacketStartEventAckData)) -{ -} - -NetPacketStartEventAck::~NetPacketStartEventAck() -{ -} - -boost::shared_ptr -NetPacketStartEventAck::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketStartEventAck); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -const NetPacketStartEventAck * -NetPacketStartEventAck::ToNetPacketStartEventAck() const -{ - return this; -} - -void -NetPacketStartEventAck::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketGameStart::NetPacketGameStart() -: NetPacket(NET_TYPE_GAME_START, sizeof(NetPacketGameStartData), MAX_PACKET_SIZE) -{ -} - -NetPacketGameStart::~NetPacketGameStart() -{ -} - -boost::shared_ptr -NetPacketGameStart::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketGameStart); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketGameStart::SetData(const NetPacketGameStart::Data &inData) -{ - u_int16_t numPlayers = (u_int16_t)inData.playerSlots.size(); - - // Basic checking. - if (numPlayers < MIN_NUMBER_OF_PLAYERS || numPlayers > MAX_NUMBER_OF_PLAYERS || numPlayers != inData.startData.numberOfPlayers) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketGameStartData) + ADD_PADDING(numPlayers * sizeof(PlayerSlotData)))); - - NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData(); - - tmpData->startDealerPlayerId = htonl(inData.startData.startDealerPlayerId); - tmpData->numberOfPlayers = htons(numPlayers); - - PlayerSlotList::const_iterator i = inData.playerSlots.begin(); - PlayerSlotList::const_iterator end = inData.playerSlots.end(); - - // Copy the player slot data to continous memory - PlayerSlotData *curPlayerSlotData = - (PlayerSlotData *)((char *)tmpData + sizeof(NetPacketGameStartData)); - while (i != end) - { - curPlayerSlotData->playerId = htonl((*i).playerId); - ++curPlayerSlotData; - ++i; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketGameStart::GetData(NetPacketGameStart::Data &outData) const -{ - NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData(); - - outData.startData.startDealerPlayerId = ntohl(tmpData->startDealerPlayerId); - u_int16_t numPlayers = ntohs(tmpData->numberOfPlayers); - outData.startData.numberOfPlayers = numPlayers; - - PlayerSlotData *curPlayerSlotData = - (PlayerSlotData *)((char *)tmpData + sizeof(NetPacketGameStartData)); - - // Store all available player slots. - for (int i = 0; i < numPlayers; i++) - { - PlayerSlot tmpPlayerSlot; - tmpPlayerSlot.playerId = ntohl(curPlayerSlotData->playerId); - - outData.playerSlots.push_back(tmpPlayerSlot); - ++curPlayerSlotData; - } -} - -const NetPacketGameStart * -NetPacketGameStart::ToNetPacketGameStart() const -{ - return this; -} - -void -NetPacketGameStart::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketGameStartData *tmpData = (NetPacketGameStartData *)data; - int numPlayers = ntohs(tmpData->numberOfPlayers); - // Check exact packet size. - if (dataLen != - sizeof(NetPacketGameStartData) - + numPlayers * sizeof(PlayerSlotData)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Semantic checks not needed. -} - -//----------------------------------------------------------------------------- - -NetPacketHandStart::NetPacketHandStart() -: NetPacket(NET_TYPE_HAND_START, sizeof(NetPacketHandStartData), sizeof(NetPacketHandStartData)) -{ -} - -NetPacketHandStart::~NetPacketHandStart() -{ -} - -boost::shared_ptr -NetPacketHandStart::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketHandStart); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketHandStart::SetData(const NetPacketHandStart::Data &inData) -{ - NetPacketHandStartData *tmpData = (NetPacketHandStartData *)GetRawData(); - - tmpData->yourCard1 = htons(inData.yourCards[0]); - tmpData->yourCard2 = htons(inData.yourCards[1]); - tmpData->smallBlind = htonl(inData.smallBlind); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketHandStart::GetData(NetPacketHandStart::Data &outData) const -{ - NetPacketHandStartData *tmpData = (NetPacketHandStartData *)GetRawData(); - - outData.yourCards[0] = ntohs(tmpData->yourCard1); - outData.yourCards[1] = ntohs(tmpData->yourCard2); - outData.smallBlind = ntohl(tmpData->smallBlind); -} - -const NetPacketHandStart * -NetPacketHandStart::ToNetPacketHandStart() const -{ - return this; -} - -void -NetPacketHandStart::InternalCheck(const NetPacketHeader* data) const -{ - NetPacketHandStartData *tmpData = (NetPacketHandStartData *)data; - if (ntohs(tmpData->yourCard1) > 51 || ntohs(tmpData->yourCard2) > 51) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketPlayersTurn::NetPacketPlayersTurn() -: NetPacket(NET_TYPE_PLAYERS_TURN, sizeof(NetPacketPlayersTurnData), sizeof(NetPacketPlayersTurnData)) -{ -} - -NetPacketPlayersTurn::~NetPacketPlayersTurn() -{ -} - -boost::shared_ptr -NetPacketPlayersTurn::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayersTurn); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayersTurn::SetData(const NetPacketPlayersTurn::Data &inData) -{ - NetPacketPlayersTurnData *tmpData = (NetPacketPlayersTurnData *)GetRawData(); - - tmpData->playerId = htonl(inData.playerId); - tmpData->gameState = htons(inData.gameState); - tmpData->minimumRaise = htonl(inData.minimumRaise); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayersTurn::GetData(NetPacketPlayersTurn::Data &outData) const -{ - NetPacketPlayersTurnData *tmpData = (NetPacketPlayersTurnData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); - outData.gameState = static_cast(ntohs(tmpData->gameState)); - outData.minimumRaise = ntohl(tmpData->minimumRaise); -} - -const NetPacketPlayersTurn * -NetPacketPlayersTurn::ToNetPacketPlayersTurn() const -{ - return this; -} - -void -NetPacketPlayersTurn::InternalCheck(const NetPacketHeader* data) const -{ - // Check whether the state is valid. - NetPacketPlayersTurnData *tmpData = (NetPacketPlayersTurnData *)data; - if (ntohs(tmpData->gameState) > GAME_STATE_RIVER) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketPlayersAction::NetPacketPlayersAction() -: NetPacket(NET_TYPE_PLAYERS_ACTION, sizeof(NetPacketPlayersActionData), sizeof(NetPacketPlayersActionData)) -{ -} - -NetPacketPlayersAction::~NetPacketPlayersAction() -{ -} - -boost::shared_ptr -NetPacketPlayersAction::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayersAction); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayersAction::SetData(const NetPacketPlayersAction::Data &inData) -{ - NetPacketPlayersActionData *tmpData = (NetPacketPlayersActionData *)GetRawData(); - - tmpData->gameState = htons(inData.gameState); - tmpData->playerAction = htons(inData.playerAction); - tmpData->playerBet = htonl(inData.playerBet); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayersAction::GetData(NetPacketPlayersAction::Data &outData) const -{ - NetPacketPlayersActionData *tmpData = (NetPacketPlayersActionData *)GetRawData(); - - outData.gameState = static_cast(ntohs(tmpData->gameState)); - outData.playerAction = static_cast(ntohs(tmpData->playerAction)); - outData.playerBet = ntohl(tmpData->playerBet); -} - -const NetPacketPlayersAction * -NetPacketPlayersAction::ToNetPacketPlayersAction() const -{ - return this; -} - -void -NetPacketPlayersAction::InternalCheck(const NetPacketHeader* data) const -{ - NetPacketPlayersActionData *tmpData = (NetPacketPlayersActionData *)data; - // Check whether the state is valid. - if (ntohs(tmpData->gameState) > GAME_STATE_RIVER) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check whether the player action is valid. - if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Semantic checks are done by the server process. -} - -//----------------------------------------------------------------------------- - -NetPacketPlayersActionDone::NetPacketPlayersActionDone() -: NetPacket(NET_TYPE_PLAYERS_ACTION_DONE, sizeof(NetPacketPlayersActionDoneData), sizeof(NetPacketPlayersActionDoneData)) -{ -} - -NetPacketPlayersActionDone::~NetPacketPlayersActionDone() -{ -} - -boost::shared_ptr -NetPacketPlayersActionDone::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayersActionDone); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayersActionDone::SetData(const NetPacketPlayersActionDone::Data &inData) -{ - NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)GetRawData(); - - tmpData->playerId = htonl(inData.playerId); - tmpData->gameState = htons(inData.gameState); - tmpData->playerAction = htons(inData.playerAction); - tmpData->totalPlayerBet = htonl(inData.totalPlayerBet); - tmpData->playerMoney = htonl(inData.playerMoney); - tmpData->highestSet = htonl(inData.highestSet); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayersActionDone::GetData(NetPacketPlayersActionDone::Data &outData) const -{ - NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); - outData.gameState = static_cast(ntohs(tmpData->gameState)); - outData.playerAction = static_cast(ntohs(tmpData->playerAction)); - outData.totalPlayerBet = ntohl(tmpData->totalPlayerBet); - outData.playerMoney = ntohl(tmpData->playerMoney); - outData.highestSet = ntohl(tmpData->highestSet); -} - -const NetPacketPlayersActionDone * -NetPacketPlayersActionDone::ToNetPacketPlayersActionDone() const -{ - return this; -} - -void -NetPacketPlayersActionDone::InternalCheck(const NetPacketHeader* data) const -{ - NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)data; - // Check whether the state is valid. - int gameState = ntohs(tmpData->gameState); - if (gameState > GAME_STATE_RIVER - && gameState != GAME_STATE_PREFLOP_SMALL_BLIND - && gameState != GAME_STATE_PREFLOP_BIG_BLIND) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check whether the player action is valid. - if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketPlayersActionRejected::NetPacketPlayersActionRejected() -: NetPacket(NET_TYPE_PLAYERS_ACTION_REJECTED, sizeof(NetPacketPlayersActionRejectedData), sizeof(NetPacketPlayersActionRejectedData)) -{ -} - -NetPacketPlayersActionRejected::~NetPacketPlayersActionRejected() -{ -} - -boost::shared_ptr -NetPacketPlayersActionRejected::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketPlayersActionRejected); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketPlayersActionRejected::SetData(const NetPacketPlayersActionRejected::Data &inData) -{ - NetPacketPlayersActionRejectedData *tmpData = (NetPacketPlayersActionRejectedData *)GetRawData(); - - tmpData->gameState = htons(inData.gameState); - tmpData->playerAction = htons(inData.playerAction); - tmpData->playerBet = htonl(inData.playerBet); - tmpData->rejectionReason = htons(inData.rejectionReason); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketPlayersActionRejected::GetData(NetPacketPlayersActionRejected::Data &outData) const -{ - NetPacketPlayersActionRejectedData *tmpData = (NetPacketPlayersActionRejectedData *)GetRawData(); - - outData.gameState = static_cast(ntohs(tmpData->gameState)); - outData.playerAction = static_cast(ntohs(tmpData->playerAction)); - outData.playerBet = ntohl(tmpData->playerBet); - outData.rejectionReason = static_cast(ntohs(tmpData->rejectionReason)); -} - -const NetPacketPlayersActionRejected * -NetPacketPlayersActionRejected::ToNetPacketPlayersActionRejected() const -{ - return this; -} - -void -NetPacketPlayersActionRejected::InternalCheck(const NetPacketHeader* data) const -{ - // Check whether the state is valid. - NetPacketPlayersActionRejectedData *tmpData = (NetPacketPlayersActionRejectedData *)data; - if (ntohs(tmpData->gameState) > GAME_STATE_RIVER) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check whether the player action is valid. - if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - if (!ntohs(tmpData->rejectionReason)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketDealFlopCards::NetPacketDealFlopCards() -: NetPacket(NET_TYPE_DEAL_FLOP_CARDS, sizeof(NetPacketDealFlopCardsData), sizeof(NetPacketDealFlopCardsData)) -{ -} - -NetPacketDealFlopCards::~NetPacketDealFlopCards() -{ -} - -boost::shared_ptr -NetPacketDealFlopCards::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketDealFlopCards); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketDealFlopCards::SetData(const NetPacketDealFlopCards::Data &inData) -{ - NetPacketDealFlopCardsData *tmpData = (NetPacketDealFlopCardsData *)GetRawData(); - - tmpData->flopCard1 = htons(inData.flopCards[0]); - tmpData->flopCard2 = htons(inData.flopCards[1]); - tmpData->flopCard3 = htons(inData.flopCards[2]); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketDealFlopCards::GetData(NetPacketDealFlopCards::Data &outData) const -{ - NetPacketDealFlopCardsData *tmpData = (NetPacketDealFlopCardsData *)GetRawData(); - - outData.flopCards[0] = ntohs(tmpData->flopCard1); - outData.flopCards[1] = ntohs(tmpData->flopCard2); - outData.flopCards[2] = ntohs(tmpData->flopCard3); -} - -const NetPacketDealFlopCards * -NetPacketDealFlopCards::ToNetPacketDealFlopCards() const -{ - return this; -} - -void -NetPacketDealFlopCards::InternalCheck(const NetPacketHeader* data) const -{ - NetPacketDealFlopCardsData *tmpData = (NetPacketDealFlopCardsData *)data; - if (ntohs(tmpData->flopCard1) > 51 || ntohs(tmpData->flopCard2) > 51 || ntohs(tmpData->flopCard3) > 51) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketDealTurnCard::NetPacketDealTurnCard() -: NetPacket(NET_TYPE_DEAL_TURN_CARD, sizeof(NetPacketDealTurnCardData), sizeof(NetPacketDealTurnCardData)) -{ -} - -NetPacketDealTurnCard::~NetPacketDealTurnCard() -{ -} - -boost::shared_ptr -NetPacketDealTurnCard::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketDealTurnCard); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketDealTurnCard::SetData(const NetPacketDealTurnCard::Data &inData) -{ - NetPacketDealTurnCardData *tmpData = (NetPacketDealTurnCardData *)GetRawData(); - - tmpData->turnCard = htons(inData.turnCard); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketDealTurnCard::GetData(NetPacketDealTurnCard::Data &outData) const -{ - NetPacketDealTurnCardData *tmpData = (NetPacketDealTurnCardData *)GetRawData(); - - outData.turnCard = ntohs(tmpData->turnCard); -} - -const NetPacketDealTurnCard * -NetPacketDealTurnCard::ToNetPacketDealTurnCard() const -{ - return this; -} - -void -NetPacketDealTurnCard::InternalCheck(const NetPacketHeader* data) const -{ - NetPacketDealTurnCardData *tmpData = (NetPacketDealTurnCardData *)data; - if (ntohs(tmpData->turnCard) > 51) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketDealRiverCard::NetPacketDealRiverCard() -: NetPacket(NET_TYPE_DEAL_RIVER_CARD, sizeof(NetPacketDealRiverCardData), sizeof(NetPacketDealRiverCardData)) -{ -} - -NetPacketDealRiverCard::~NetPacketDealRiverCard() -{ -} - -boost::shared_ptr -NetPacketDealRiverCard::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketDealRiverCard); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketDealRiverCard::SetData(const NetPacketDealRiverCard::Data &inData) -{ - NetPacketDealRiverCardData *tmpData = (NetPacketDealRiverCardData *)GetRawData(); - - tmpData->riverCard = htons(inData.riverCard); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketDealRiverCard::GetData(NetPacketDealRiverCard::Data &outData) const -{ - NetPacketDealRiverCardData *tmpData = (NetPacketDealRiverCardData *)GetRawData(); - - outData.riverCard = ntohs(tmpData->riverCard); -} - -const NetPacketDealRiverCard * -NetPacketDealRiverCard::ToNetPacketDealRiverCard() const -{ - return this; -} - -void -NetPacketDealRiverCard::InternalCheck(const NetPacketHeader* data) const -{ - NetPacketDealRiverCardData *tmpData = (NetPacketDealRiverCardData *)data; - if (ntohs(tmpData->riverCard) > 51) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketAllInShowCards::NetPacketAllInShowCards() -: NetPacket(NET_TYPE_ALL_IN_SHOW_CARDS, sizeof(NetPacketAllInShowCardsData), MAX_PACKET_SIZE) -{ -} - -NetPacketAllInShowCards::~NetPacketAllInShowCards() -{ -} - -boost::shared_ptr -NetPacketAllInShowCards::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketAllInShowCards); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketAllInShowCards::SetData(const NetPacketAllInShowCards::Data &inData) -{ - u_int16_t numPlayerCards = (u_int16_t)inData.playerCards.size(); - - if (!numPlayerCards || numPlayerCards > MAX_NUM_PLAYER_CARDS) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_CARDS, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketAllInShowCardsData) + numPlayerCards * sizeof(PlayerCardsData))); - - NetPacketAllInShowCardsData *tmpData = (NetPacketAllInShowCardsData *)GetRawData(); - - tmpData->numberOfPlayerCards = htons(numPlayerCards); - - PlayerCardsList::const_iterator i = inData.playerCards.begin(); - PlayerCardsList::const_iterator end = inData.playerCards.end(); - - // Copy the player cards data to continous memory - PlayerCardsData *curPlayerCardsData = - (PlayerCardsData *)((char *)tmpData + sizeof(NetPacketAllInShowCardsData)); - while (i != end) - { - curPlayerCardsData->playerId = htonl((*i).playerId); - curPlayerCardsData->card1 = htons((*i).cards[0]); - curPlayerCardsData->card2 = htons((*i).cards[1]); - ++curPlayerCardsData; - ++i; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketAllInShowCards::GetData(NetPacketAllInShowCards::Data &outData) const -{ - NetPacketAllInShowCardsData *tmpData = (NetPacketAllInShowCardsData *)GetRawData(); - - outData.playerCards.clear(); - - u_int16_t numPlayerCards = ntohs(tmpData->numberOfPlayerCards); - PlayerCardsData *curPlayerCardsData = - (PlayerCardsData *)((char *)tmpData + sizeof(NetPacketAllInShowCardsData)); - - // Store all available player cards. - for (int i = 0; i < numPlayerCards; i++) - { - PlayerCards tmpPlayerCards; - tmpPlayerCards.playerId = ntohl(curPlayerCardsData->playerId); - tmpPlayerCards.cards[0] = ntohs(curPlayerCardsData->card1); - tmpPlayerCards.cards[1] = ntohs(curPlayerCardsData->card2); - - outData.playerCards.push_back(tmpPlayerCards); - ++curPlayerCardsData; - } -} - -const NetPacketAllInShowCards * -NetPacketAllInShowCards::ToNetPacketAllInShowCards() const -{ - return this; -} - -void -NetPacketAllInShowCards::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketAllInShowCardsData *tmpData = (NetPacketAllInShowCardsData *)data; - int numPlayerCards = ntohs(tmpData->numberOfPlayerCards); - - if (dataLen != - sizeof(NetPacketAllInShowCardsData) - + numPlayerCards * sizeof(PlayerCardsData)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - if (ntohs(tmpData->numberOfPlayerCards) > MAX_NUMBER_OF_PLAYERS) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Semantic checks not needed, this packet is sent by the server. -} - -//----------------------------------------------------------------------------- - -NetPacketEndOfHandShowCards::NetPacketEndOfHandShowCards() -: NetPacket(NET_TYPE_END_OF_HAND_SHOW_CARDS, sizeof(NetPacketEndOfHandShowCardsData), MAX_PACKET_SIZE) -{ -} - -NetPacketEndOfHandShowCards::~NetPacketEndOfHandShowCards() -{ -} - -boost::shared_ptr -NetPacketEndOfHandShowCards::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketEndOfHandShowCards); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketEndOfHandShowCards::SetData(const NetPacketEndOfHandShowCards::Data &inData) -{ - u_int16_t numPlayerResults = (u_int16_t)inData.playerResults.size(); - - if (!numPlayerResults || numPlayerResults > MAX_NUM_PLAYER_RESULTS) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_RESULTS, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketEndOfHandShowCardsData) + numPlayerResults * sizeof(PlayerResultData))); - - NetPacketEndOfHandShowCardsData *tmpData = (NetPacketEndOfHandShowCardsData *)GetRawData(); - - tmpData->numberOfPlayerResults = htons(numPlayerResults); - - PlayerResultList::const_iterator i = inData.playerResults.begin(); - PlayerResultList::const_iterator end = inData.playerResults.end(); - - // Copy the player result data to continous memory - PlayerResultData *curPlayerResultData = - (PlayerResultData *)((char *)tmpData + sizeof(NetPacketEndOfHandShowCardsData)); - while (i != end) - { - curPlayerResultData->playerId = htonl((*i).playerId); - curPlayerResultData->card1 = htons((*i).cards[0]); - curPlayerResultData->card2 = htons((*i).cards[1]); - curPlayerResultData->bestHandPos1 = htons((*i).bestHandPos[0]); - curPlayerResultData->bestHandPos2 = htons((*i).bestHandPos[1]); - curPlayerResultData->bestHandPos3 = htons((*i).bestHandPos[2]); - curPlayerResultData->bestHandPos4 = htons((*i).bestHandPos[3]); - curPlayerResultData->bestHandPos5 = htons((*i).bestHandPos[4]); - curPlayerResultData->valueOfCards = htonl((*i).valueOfCards); - curPlayerResultData->moneyWon = htonl((*i).moneyWon); - curPlayerResultData->playerMoney = htonl((*i).playerMoney); - ++curPlayerResultData; - ++i; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketEndOfHandShowCards::GetData(NetPacketEndOfHandShowCards::Data &outData) const -{ - NetPacketEndOfHandShowCardsData *tmpData = (NetPacketEndOfHandShowCardsData *)GetRawData(); - - outData.playerResults.clear(); - - u_int16_t numPlayerResults = ntohs(tmpData->numberOfPlayerResults); - PlayerResultData *curPlayerResultData = - (PlayerResultData *)((char *)tmpData + sizeof(NetPacketEndOfHandShowCardsData)); - - // Store all available player results. - for (int i = 0; i < numPlayerResults; i++) - { - PlayerResult tmpPlayerResult; - tmpPlayerResult.playerId = ntohl(curPlayerResultData->playerId); - tmpPlayerResult.cards[0] = ntohs(curPlayerResultData->card1); - tmpPlayerResult.cards[1] = ntohs(curPlayerResultData->card2); - tmpPlayerResult.bestHandPos[0] = ntohs(curPlayerResultData->bestHandPos1); - tmpPlayerResult.bestHandPos[1] = ntohs(curPlayerResultData->bestHandPos2); - tmpPlayerResult.bestHandPos[2] = ntohs(curPlayerResultData->bestHandPos3); - tmpPlayerResult.bestHandPos[3] = ntohs(curPlayerResultData->bestHandPos4); - tmpPlayerResult.bestHandPos[4] = ntohs(curPlayerResultData->bestHandPos5); - tmpPlayerResult.valueOfCards = ntohl(curPlayerResultData->valueOfCards); - tmpPlayerResult.moneyWon = ntohl(curPlayerResultData->moneyWon); - tmpPlayerResult.playerMoney = ntohl(curPlayerResultData->playerMoney); - - outData.playerResults.push_back(tmpPlayerResult); - ++curPlayerResultData; - } -} - -const NetPacketEndOfHandShowCards * -NetPacketEndOfHandShowCards::ToNetPacketEndOfHandShowCards() const -{ - return this; -} - -void -NetPacketEndOfHandShowCards::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketEndOfHandShowCardsData *tmpData = (NetPacketEndOfHandShowCardsData *)data; - int numPlayerResults = ntohs(tmpData->numberOfPlayerResults); - - if (dataLen != - sizeof(NetPacketEndOfHandShowCardsData) - + numPlayerResults * sizeof(PlayerResultData)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - if (ntohs(tmpData->numberOfPlayerResults) > MAX_NUMBER_OF_PLAYERS) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Semantic checks not needed, this packet is sent by the server. -} - -//----------------------------------------------------------------------------- - -NetPacketEndOfHandHideCards::NetPacketEndOfHandHideCards() -: NetPacket(NET_TYPE_END_OF_HAND_HIDE_CARDS, sizeof(NetPacketEndOfHandHideCardsData), sizeof(NetPacketEndOfHandHideCardsData)) -{ -} - -NetPacketEndOfHandHideCards::~NetPacketEndOfHandHideCards() -{ -} - -boost::shared_ptr -NetPacketEndOfHandHideCards::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketEndOfHandHideCards); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketEndOfHandHideCards::SetData(const NetPacketEndOfHandHideCards::Data &inData) -{ - NetPacketEndOfHandHideCardsData *tmpData = (NetPacketEndOfHandHideCardsData *)GetRawData(); - - tmpData->playerId = htonl(inData.playerId); - tmpData->moneyWon = htonl(inData.moneyWon); - tmpData->playerMoney = htonl(inData.playerMoney); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketEndOfHandHideCards::GetData(NetPacketEndOfHandHideCards::Data &outData) const -{ - NetPacketEndOfHandHideCardsData *tmpData = (NetPacketEndOfHandHideCardsData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); - outData.moneyWon = ntohl(tmpData->moneyWon); - outData.playerMoney = ntohl(tmpData->playerMoney); -} - -const NetPacketEndOfHandHideCards * -NetPacketEndOfHandHideCards::ToNetPacketEndOfHandHideCards() const -{ - return this; -} - -void -NetPacketEndOfHandHideCards::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketEndOfGame::NetPacketEndOfGame() -: NetPacket(NET_TYPE_END_OF_GAME, sizeof(NetPacketEndOfGameData), sizeof(NetPacketEndOfGameData)) -{ -} - -NetPacketEndOfGame::~NetPacketEndOfGame() -{ -} - -boost::shared_ptr -NetPacketEndOfGame::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketEndOfGame); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketEndOfGame::SetData(const NetPacketEndOfGame::Data &inData) -{ - NetPacketEndOfGameData *tmpData = (NetPacketEndOfGameData *)GetRawData(); - - tmpData->winnerPlayerId = htonl(inData.winnerPlayerId); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketEndOfGame::GetData(NetPacketEndOfGame::Data &outData) const -{ - NetPacketEndOfGameData *tmpData = (NetPacketEndOfGameData *)GetRawData(); - - outData.winnerPlayerId = ntohl(tmpData->winnerPlayerId); -} - -const NetPacketEndOfGame * -NetPacketEndOfGame::ToNetPacketEndOfGame() const -{ - return this; -} - -void -NetPacketEndOfGame::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketStatisticsChanged::NetPacketStatisticsChanged() -: NetPacket(NET_TYPE_STATISTICS_CHANGED, sizeof(NetPacketStatisticsChangedData), MAX_PACKET_SIZE) -{ -} - -NetPacketStatisticsChanged::~NetPacketStatisticsChanged() -{ -} - -boost::shared_ptr -NetPacketStatisticsChanged::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketStatisticsChanged); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketStatisticsChanged::SetData(const NetPacketStatisticsChanged::Data &inData) -{ - u_int16_t numValues = 0; - if (inData.stats.numberOfPlayersOnServer) - ++numValues; - if (inData.stats.totalPlayersEverLoggedIn) - ++numValues; - if (inData.stats.totalGamesEverCreated) - ++numValues; - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketStatisticsChangedData) + numValues * sizeof(StatisticsData))); - - NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)GetRawData(); - - tmpData->numberOfStatistics = htons(numValues); - - StatisticsData *curStatisticsData = - (StatisticsData *)((char *)tmpData + sizeof(NetPacketStatisticsChangedData)); - - if (inData.stats.numberOfPlayersOnServer) - { - curStatisticsData->statisticsType = htonl(NET_STAT_CUR_PLAYERS_ON_SERVER); - curStatisticsData->statisticsValue = htonl(inData.stats.numberOfPlayersOnServer); - ++curStatisticsData; - } - if (inData.stats.totalPlayersEverLoggedIn) - { - curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER); - curStatisticsData->statisticsValue = htonl(inData.stats.totalPlayersEverLoggedIn); - ++curStatisticsData; - } - if (inData.stats.totalGamesEverCreated) - { - curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_GAMES_EVER_ON_SERVER); - curStatisticsData->statisticsValue = htonl(inData.stats.totalGamesEverCreated); - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketStatisticsChanged::GetData(NetPacketStatisticsChanged::Data &outData) const -{ - NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)GetRawData(); - - u_int16_t numStatistics = ntohs(tmpData->numberOfStatistics); - StatisticsData *curStatisticsData = - (StatisticsData *)((char *)tmpData + sizeof(NetPacketStatisticsChangedData)); - - for (int i = 0; i < numStatistics; i++) - { - switch(ntohl(curStatisticsData->statisticsType)) - { - case NET_STAT_CUR_PLAYERS_ON_SERVER: - outData.stats.numberOfPlayersOnServer = ntohl(curStatisticsData->statisticsValue); - break; - case NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER: - outData.stats.totalPlayersEverLoggedIn = ntohl(curStatisticsData->statisticsValue); - break; - case NET_STAT_TOTAL_GAMES_EVER_ON_SERVER: - outData.stats.totalGamesEverCreated = ntohl(curStatisticsData->statisticsValue); - break; - } - } -} - -const NetPacketStatisticsChanged * -NetPacketStatisticsChanged::ToNetPacketStatisticsChanged() const -{ - return this; -} - -void -NetPacketStatisticsChanged::InternalCheck(const NetPacketHeader *data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)data; - int numStatistics = ntohs(tmpData->numberOfStatistics); - - if (dataLen != - sizeof(NetPacketStatisticsChangedData) - + numStatistics * sizeof(StatisticsData)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - if (!numStatistics) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Semantic checks not needed, this packet is sent by the server. -} - -//----------------------------------------------------------------------------- - -NetPacketRemovedFromGame::NetPacketRemovedFromGame() -: NetPacket(NET_TYPE_REMOVED_FROM_GAME, sizeof(NetPacketRemovedFromGameData), sizeof(NetPacketRemovedFromGameData)) -{ -} - -NetPacketRemovedFromGame::~NetPacketRemovedFromGame() -{ -} - -boost::shared_ptr -NetPacketRemovedFromGame::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketRemovedFromGame); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketRemovedFromGame::SetData(const NetPacketRemovedFromGame::Data &inData) -{ - NetPacketRemovedFromGameData *tmpData = (NetPacketRemovedFromGameData *)GetRawData(); - - switch (inData.removeReason) - { - case NTF_NET_REMOVED_ON_REQUEST : - tmpData->removeReason = htons(NET_REMOVED_ON_REQUEST); - break; - case NTF_NET_REMOVED_GAME_FULL : - tmpData->removeReason = htons(NET_REMOVED_GAME_FULL); - break; - case NTF_NET_REMOVED_ALREADY_RUNNING : - tmpData->removeReason = htons(NET_REMOVED_GAME_ALREADY_RUNNING); - break; - case NTF_NET_REMOVED_KICKED : - tmpData->removeReason = htons(NET_REMOVED_KICKED); - break; - default : - tmpData->removeReason = htons(NET_REMOVED_OTHER_REASON); - break; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketRemovedFromGame::GetData(NetPacketRemovedFromGame::Data &outData) const -{ - NetPacketRemovedFromGameData *tmpData = (NetPacketRemovedFromGameData *)GetRawData(); - - switch (ntohs(tmpData->removeReason)) - { - // Removed Errors. - case NET_REMOVED_ON_REQUEST : - outData.removeReason = NTF_NET_REMOVED_ON_REQUEST; - break; - case NET_REMOVED_GAME_FULL : - outData.removeReason = NTF_NET_REMOVED_GAME_FULL; - break; - case NET_REMOVED_GAME_ALREADY_RUNNING : - outData.removeReason = NTF_NET_REMOVED_ALREADY_RUNNING; - break; - case NET_REMOVED_KICKED : - outData.removeReason = NTF_NET_REMOVED_KICKED; - break; - default : - outData.removeReason = NTF_NET_INTERNAL; - break; - } -} - -const NetPacketRemovedFromGame * -NetPacketRemovedFromGame::ToNetPacketRemovedFromGame() const -{ - return this; -} - -void -NetPacketRemovedFromGame::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - -NetPacketSendChatText::NetPacketSendChatText() -: NetPacket(NET_TYPE_SEND_CHAT_TEXT, sizeof(NetPacketSendChatTextData), MAX_PACKET_SIZE) -{ -} - -NetPacketSendChatText::~NetPacketSendChatText() -{ -} - -boost::shared_ptr -NetPacketSendChatText::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketSendChatText); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketSendChatText::SetData(const NetPacketSendChatText::Data &inData) -{ - u_int16_t textLen = (u_int16_t)inData.text.length(); - - if (!textLen || textLen > MAX_CHAT_TEXT_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_CHAT_TEXT, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketSendChatTextData) + ADD_PADDING(textLen))); - - NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)GetRawData(); - - // Set the data. - tmpData->textLength = htons(textLen); - char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData); - memcpy(textPtr, inData.text.c_str(), textLen); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketSendChatText::GetData(NetPacketSendChatText::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)GetRawData(); - - char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData); - outData.text = string(textPtr, ntohs(tmpData->textLength)); -} - -const NetPacketSendChatText * -NetPacketSendChatText::ToNetPacketSendChatText() const -{ - return this; -} - -void -NetPacketSendChatText::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)data; - int textLength = ntohs(tmpData->textLength); - // Check exact packet length. - if (dataLen != - sizeof(NetPacketSendChatTextData) - + ADD_PADDING(textLength)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string size. - if (!textLength - || textLength > MAX_CHAT_TEXT_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check text string. - char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData); - if (textPtr[0] == 0) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } -} - -//----------------------------------------------------------------------------- - -NetPacketChatText::NetPacketChatText() -: NetPacket(NET_TYPE_CHAT_TEXT, sizeof(NetPacketChatTextData), MAX_PACKET_SIZE) -{ -} - -NetPacketChatText::~NetPacketChatText() -{ -} - -boost::shared_ptr -NetPacketChatText::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketChatText); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketChatText::SetData(const NetPacketChatText::Data &inData) -{ - u_int16_t textLen = (u_int16_t)inData.text.length(); - - if (!textLen || textLen > MAX_CHAT_TEXT_SIZE) - throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_CHAT_TEXT, 0); - - // Resize the packet so that the data fits in. - Resize((u_int16_t) - (sizeof(NetPacketChatTextData) + ADD_PADDING(textLen))); - - NetPacketChatTextData *tmpData = (NetPacketChatTextData *)GetRawData(); - - // Set the data. - tmpData->playerId = htonl(inData.playerId); - tmpData->textLength = htons(textLen); - char *textPtr = (char *)tmpData + sizeof(NetPacketChatTextData); - memcpy(textPtr, inData.text.c_str(), textLen); - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketChatText::GetData(NetPacketChatText::Data &outData) const -{ - // We assume that the data is valid. Validity has already been checked. - NetPacketChatTextData *tmpData = (NetPacketChatTextData *)GetRawData(); - - outData.playerId = ntohl(tmpData->playerId); - char *textPtr = (char *)tmpData + sizeof(NetPacketChatTextData); - outData.text = string(textPtr, ntohs(tmpData->textLength)); -} - -const NetPacketChatText * -NetPacketChatText::ToNetPacketChatText() const -{ - return this; -} - -void -NetPacketChatText::InternalCheck(const NetPacketHeader* data) const -{ - u_int16_t dataLen = ntohs(data->length); - NetPacketChatTextData *tmpData = (NetPacketChatTextData *)data; - int textLength = ntohs(tmpData->textLength); - // Check exact packet length. - if (dataLen != - sizeof(NetPacketChatTextData) - + ADD_PADDING(textLength)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // Check string size. - if (!textLength - || textLength > MAX_CHAT_TEXT_SIZE) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); - } - // No more checks required - this packet is sent by the server. -} - -//----------------------------------------------------------------------------- - -NetPacketError::NetPacketError() -: NetPacket(NET_TYPE_ERROR, sizeof(NetPacketErrorData), sizeof(NetPacketErrorData)) -{ -} - -NetPacketError::~NetPacketError() -{ -} - -boost::shared_ptr -NetPacketError::Clone() const -{ - boost::shared_ptr newPacket(new NetPacketError); - try - { - newPacket->SetRawData(GetRawData()); - } catch (const NetException &) - { - // Need to return the new packet anyway. - } - return newPacket; -} - -void -NetPacketError::SetData(const NetPacketError::Data &inData) -{ - NetPacketErrorData *tmpData = (NetPacketErrorData *)GetRawData(); - - switch (inData.errorCode) - { - // Init Errors. - case ERR_NET_VERSION_NOT_SUPPORTED : - tmpData->errorReason = htons(NET_ERR_INIT_VERSION_NOT_SUPPORTED); - break; - case ERR_NET_SERVER_FULL : - tmpData->errorReason = htons(NET_ERR_INIT_SERVER_FULL); - break; - case ERR_NET_INVALID_PASSWORD : - tmpData->errorReason = htons(NET_ERR_INIT_INVALID_PASSWORD); - break; - case ERR_NET_PLAYER_NAME_IN_USE : - tmpData->errorReason = htons(NET_ERR_INIT_PLAYER_NAME_IN_USE); - break; - case ERR_NET_INVALID_PLAYER_NAME : - tmpData->errorReason = htons(NET_ERR_INIT_INVALID_PLAYER_NAME); - break; - case ERR_NET_SERVER_MAINTENANCE : - tmpData->errorReason = htons(NET_ERR_INIT_SERVER_MAINTENANCE); - break; - case ERR_NET_AVATAR_TOO_LARGE : - tmpData->errorReason = htons(NET_ERR_AVATAR_TOO_LARGE); - break; - case ERR_NET_WRONG_AVATAR_SIZE : - tmpData->errorReason = htons(NET_ERR_AVATAR_WRONG_SIZE); - break; - case ERR_NET_UNKNOWN_GAME : - tmpData->errorReason = htons(NET_ERR_JOIN_GAME_UNKNOWN_GAME); - break; - - // General Errors. - case ERR_SOCK_INVALID_PACKET : - tmpData->errorReason = htons(NET_ERR_GENERAL_INVALID_PACKET); - break; - case ERR_SOCK_INVALID_STATE : - tmpData->errorReason = htons(NET_ERR_GENERAL_INVALID_STATE); - break; - case ERR_NET_PLAYER_KICKED : - tmpData->errorReason = htons(NET_ERR_GENERAL_PLAYER_KICKED); - break; - default : - tmpData->errorReason = htons(NET_ERR_OTHER); - break; - } - - // Check the packet - just in case. - Check(GetRawData()); -} - -void -NetPacketError::GetData(NetPacketError::Data &outData) const -{ - NetPacketErrorData *tmpData = (NetPacketErrorData *)GetRawData(); - - switch (ntohs(tmpData->errorReason)) - { - // Init Errors. - case NET_ERR_INIT_VERSION_NOT_SUPPORTED : - outData.errorCode = ERR_NET_VERSION_NOT_SUPPORTED; - break; - case NET_ERR_INIT_SERVER_FULL : - outData.errorCode = ERR_NET_SERVER_FULL; - break; - case NET_ERR_INIT_INVALID_PASSWORD : - outData.errorCode = ERR_NET_INVALID_PASSWORD; - break; - case NET_ERR_INIT_PLAYER_NAME_IN_USE : - outData.errorCode = ERR_NET_PLAYER_NAME_IN_USE; - break; - case NET_ERR_INIT_INVALID_PLAYER_NAME : - outData.errorCode = ERR_NET_INVALID_PLAYER_NAME; - break; - case NET_ERR_INIT_SERVER_MAINTENANCE : - outData.errorCode = ERR_NET_SERVER_MAINTENANCE; - break; - case NET_ERR_AVATAR_TOO_LARGE : - outData.errorCode = ERR_NET_AVATAR_TOO_LARGE; - break; - case NET_ERR_AVATAR_WRONG_SIZE : - outData.errorCode = ERR_NET_WRONG_AVATAR_SIZE; - break; - case NET_ERR_JOIN_GAME_UNKNOWN_GAME : - outData.errorCode = ERR_NET_UNKNOWN_GAME; - break; - - // General Errors. - case NET_ERR_GENERAL_INVALID_PACKET : - outData.errorCode = ERR_SOCK_INVALID_PACKET; - break; - 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; - } -} - -const NetPacketError * -NetPacketError::ToNetPacketError() const -{ - return this; -} - -void -NetPacketError::InternalCheck(const NetPacketHeader*) const -{ - // Nothing to do. -} - -//----------------------------------------------------------------------------- - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include + +using namespace std; + +#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2) + +#define NET_TYPE_INIT 0x0001 +#define NET_TYPE_INIT_ACK 0x0002 +#define NET_TYPE_RETRIEVE_AVATAR 0x0003 +#define NET_TYPE_AVATAR_HEADER 0x0004 +#define NET_TYPE_AVATAR_FILE 0x0005 +#define NET_TYPE_AVATAR_END 0x0006 +#define NET_TYPE_UNKNOWN_AVATAR 0x0007 +#define NET_TYPE_GAME_LIST_NEW 0x0010 +#define NET_TYPE_GAME_LIST_UPDATE 0x0011 +#define NET_TYPE_GAME_LIST_PLAYER_JOINED 0x0012 +#define NET_TYPE_GAME_LIST_PLAYER_LEFT 0x0013 +#define NET_TYPE_GAME_LIST_ADMIN_CHANGED 0x0014 +#define NET_TYPE_RETRIEVE_PLAYER_INFO 0x0020 +#define NET_TYPE_PLAYER_INFO 0x0021 +#define NET_TYPE_UNKNOWN_PLAYER_ID 0x0022 +#define NET_TYPE_CREATE_GAME 0x0030 +#define NET_TYPE_JOIN_GAME 0x0031 +#define NET_TYPE_JOIN_GAME_ACK 0x0032 +#define NET_TYPE_JOIN_GAME_FAILED 0x0033 +#define NET_TYPE_PLAYER_JOINED 0x0034 +#define NET_TYPE_PLAYER_LEFT 0x0035 +#define NET_TYPE_GAME_ADMIN_CHANGED 0x0036 +#define NET_TYPE_KICK_PLAYER 0x0040 +#define NET_TYPE_LEAVE_CURRENT_GAME 0x0041 +#define NET_TYPE_START_EVENT 0x0042 +#define NET_TYPE_START_EVENT_ACK 0x0043 +#define NET_TYPE_GAME_START 0x0050 +#define NET_TYPE_HAND_START 0x0051 +#define NET_TYPE_PLAYERS_TURN 0x0052 +#define NET_TYPE_PLAYERS_ACTION 0x0053 +#define NET_TYPE_PLAYERS_ACTION_DONE 0x0054 +#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x0055 +#define NET_TYPE_DEAL_FLOP_CARDS 0x0060 +#define NET_TYPE_DEAL_TURN_CARD 0x0061 +#define NET_TYPE_DEAL_RIVER_CARD 0x0062 +#define NET_TYPE_ALL_IN_SHOW_CARDS 0x0063 +#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x0064 +#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0065 +#define NET_TYPE_END_OF_GAME 0x0070 +#define NET_TYPE_STATISTICS_CHANGED 0x0080 + +#define NET_TYPE_REMOVED_FROM_GAME 0x0100 + +#define NET_TYPE_SEND_CHAT_TEXT 0x0200 +#define NET_TYPE_CHAT_TEXT 0x0201 + +#define NET_TYPE_ERROR 0x0400 + +#define NET_GAME_FLAG_PASSWORD_PROTECTED 0x01 + +#define NET_PLAYER_FLAG_HUMAN 0x01 +#define NET_PLAYER_FLAG_HAS_AVATAR 0x02 + +#define NET_START_FLAG_FILL_WITH_CPU_PLAYERS 0x01 + +#define NET_PRIVACY_FLAG_SHOW_AVATAR 0x01 + +// Reasons why join game failed. +#define NET_JOIN_FAILED_GAME_FULL 0x0001 +#define NET_JOIN_FAILED_GAME_ALREADY_RUNNING 0x0002 +#define NET_JOIN_FAILED_INVALID_PASSWORD 0x0003 +#define NET_JOIN_FAILED_OTHER 0xFFFF + +// Reasons for being removed from a game. +#define NET_REMOVED_ON_REQUEST 0x0000 +#define NET_REMOVED_GAME_FULL 0x0001 +#define NET_REMOVED_GAME_ALREADY_RUNNING 0x0002 +#define NET_REMOVED_KICKED 0x0003 +#define NET_REMOVED_OTHER_REASON 0xFFFF + +// Internal error codes. +#define NET_ERR_RESERVED 0x0000 +#define NET_ERR_INIT_VERSION_NOT_SUPPORTED 0x0001 +#define NET_ERR_INIT_SERVER_FULL 0x0002 +#define NET_ERR_INIT_INVALID_PASSWORD 0x0004 +#define NET_ERR_INIT_PLAYER_NAME_IN_USE 0x0005 +#define NET_ERR_INIT_INVALID_PLAYER_NAME 0x0006 +#define NET_ERR_INIT_SERVER_MAINTENANCE 0x0007 +#define NET_ERR_AVATAR_TOO_LARGE 0x0010 +#define NET_ERR_AVATAR_WRONG_SIZE 0x0011 +#define NET_ERR_JOIN_GAME_UNKNOWN_GAME 0x0020 +#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 + +// Statistics types +#define NET_STAT_CUR_PLAYERS_ON_SERVER 0x0001 +#define NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER 0x0002 +#define NET_STAT_TOTAL_GAMES_EVER_ON_SERVER 0x0003 + +#ifdef _MSC_VER + #pragma pack(push, 1) + #define GCC_PACKED +#else + #define GCC_PACKED __attribute__ ((__packed__)) +#endif + + +struct GCC_PACKED NetPacketHeader +{ + u_int16_t type; + u_int16_t length; +}; + +struct GCC_PACKED NetPacketInitData +{ + NetPacketHeader head; + u_int16_t requestedVersionMajor; + u_int16_t requestedVersionMinor; + u_int16_t passwordLength; + u_int16_t playerNameLength; + u_int16_t privacyFlags; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketInitAckData +{ + NetPacketHeader head; + u_int16_t latestGameVersion; + u_int16_t latestBetaRevision; + u_int32_t sessionId; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketRetrieveAvatarData +{ + NetPacketHeader head; + u_int32_t requestId; + unsigned char avatarMD5[MD5_DATA_SIZE]; +}; + +struct GCC_PACKED NetPacketAvatarHeaderData +{ + NetPacketHeader head; + u_int32_t requestId; + u_int32_t avatarFileSize; + u_int16_t avatarFileType; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketAvatarFileData +{ + NetPacketHeader head; + u_int32_t requestId; + u_int16_t blockSize; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketAvatarEndData +{ + NetPacketHeader head; + u_int32_t requestId; +}; + +struct GCC_PACKED NetPacketUnknownAvatarData +{ + NetPacketHeader head; + u_int32_t requestId; +}; + +struct GCC_PACKED GameInfoData +{ + u_int16_t maxNumberOfPlayers; + u_int16_t raiseIntervalMode; + u_int16_t raiseSmallBlindInterval; + u_int16_t raiseMode; + u_int16_t endRaiseMode; + u_int16_t numberOfManualBlinds; + u_int16_t proposedGuiSpeed; + u_int16_t playerActionTimeout; + u_int32_t firstSmallBlind; + u_int32_t endRaiseSmallBlindValue; + u_int32_t startMoney; +}; + +struct GCC_PACKED NetPacketGameListNewData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int32_t adminPlayerId; + u_int16_t gameMode; + u_int16_t gameNameLength; + u_int16_t curNumberOfPlayers; + u_int16_t gameFlags; + GameInfoData gameData; +}; + +struct GCC_PACKED NetPacketGameListUpdateData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int16_t gameMode; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketGameListPlayerJoinedData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketGameListPlayerLeftData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketGameListAdminChangedData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int32_t newAdminPlayerId; +}; + +struct GCC_PACKED NetPacketRetrievePlayerInfoData +{ + NetPacketHeader head; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketPlayerInfoData +{ + NetPacketHeader head; + u_int32_t playerId; + u_int16_t playerFlags; + u_int16_t playerNameLength; + u_int32_t reserved; +}; + +struct GCC_PACKED NetPacketUnknownPlayerIdData +{ + NetPacketHeader head; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketCreateGameData +{ + NetPacketHeader head; + u_int16_t passwordLength; + u_int16_t gameNameLength; + GameInfoData gameData; +}; + +struct GCC_PACKED NetPacketJoinGameData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int16_t passwordLength; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketJoinGameAckData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int16_t playerRights; + u_int16_t reserved; + GameInfoData gameData; +}; + +struct GCC_PACKED NetPacketJoinGameFailedData +{ + NetPacketHeader head; + u_int16_t failureReason; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketPlayerJoinedData +{ + NetPacketHeader head; + u_int32_t playerId; + u_int16_t playerRights; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketPlayerLeftData +{ + NetPacketHeader head; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketGameAdminChangedData +{ + NetPacketHeader head; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketKickPlayerData +{ + NetPacketHeader head; + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketLeaveCurrentGameData +{ + NetPacketHeader head; + u_int32_t reserved; +}; + +struct GCC_PACKED NetPacketStartEventData +{ + NetPacketHeader head; + u_int16_t startFlags; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketStartEventAckData +{ + NetPacketHeader head; + u_int32_t reserved; +}; + +struct GCC_PACKED NetPacketGameStartData +{ + NetPacketHeader head; + u_int32_t startDealerPlayerId; + u_int16_t numberOfPlayers; + u_int16_t reserved; +}; + +struct GCC_PACKED PlayerSlotData +{ + u_int32_t playerId; +}; + +struct GCC_PACKED NetPacketHandStartData +{ + NetPacketHeader head; + u_int16_t yourCard1; + u_int16_t yourCard2; + u_int32_t smallBlind; +}; + +struct GCC_PACKED NetPacketPlayersTurnData +{ + NetPacketHeader head; + u_int32_t playerId; + u_int32_t minimumRaise; + u_int16_t gameState; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketPlayersActionData +{ + NetPacketHeader head; + u_int16_t gameState; + u_int16_t playerAction; + u_int32_t playerBet; +}; + +struct GCC_PACKED NetPacketPlayersActionDoneData +{ + NetPacketHeader head; + u_int32_t playerId; + u_int16_t gameState; + u_int16_t playerAction; + u_int32_t totalPlayerBet; + u_int32_t playerMoney; + u_int32_t highestSet; +}; + +struct GCC_PACKED NetPacketPlayersActionRejectedData +{ + NetPacketHeader head; + u_int16_t gameState; + u_int16_t playerAction; + u_int32_t playerBet; + u_int16_t rejectionReason; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketDealFlopCardsData +{ + NetPacketHeader head; + u_int16_t flopCard1; + u_int16_t flopCard2; + u_int16_t flopCard3; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketDealTurnCardData +{ + NetPacketHeader head; + u_int16_t turnCard; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketDealRiverCardData +{ + NetPacketHeader head; + u_int16_t riverCard; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketAllInShowCardsData +{ + NetPacketHeader head; + u_int16_t numberOfPlayerCards; + u_int16_t reserved; +}; + +struct GCC_PACKED PlayerCardsData +{ + u_int32_t playerId; + u_int16_t card1; + u_int16_t card2; +}; + +struct GCC_PACKED NetPacketEndOfHandShowCardsData +{ + NetPacketHeader head; + u_int16_t numberOfPlayerResults; + u_int16_t reserved; +}; + +struct GCC_PACKED PlayerResultData +{ + u_int32_t playerId; + u_int16_t card1; + u_int16_t card2; + u_int16_t bestHandPos1; + u_int16_t bestHandPos2; + u_int16_t bestHandPos3; + u_int16_t bestHandPos4; + u_int16_t bestHandPos5; + u_int16_t reserved; + u_int32_t valueOfCards; + u_int32_t moneyWon; + u_int32_t playerMoney; +}; + +struct GCC_PACKED NetPacketEndOfHandHideCardsData +{ + NetPacketHeader head; + u_int32_t playerId; + u_int32_t moneyWon; + u_int32_t playerMoney; +}; + +struct GCC_PACKED NetPacketEndOfGameData +{ + NetPacketHeader head; + u_int32_t winnerPlayerId; +}; + +struct GCC_PACKED StatisticsData +{ + u_int32_t statisticsType; + u_int32_t statisticsValue; +}; + +struct GCC_PACKED NetPacketStatisticsChangedData +{ + NetPacketHeader head; + u_int16_t numberOfStatistics; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketRemovedFromGameData +{ + NetPacketHeader head; + u_int16_t removeReason; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketSendChatTextData +{ + NetPacketHeader head; + u_int16_t textLength; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketChatTextData +{ + NetPacketHeader head; + u_int32_t playerId; + u_int16_t textLength; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketErrorData +{ + NetPacketHeader head; + u_int16_t errorReason; + u_int16_t reserved; +}; + +#ifdef _MSC_VER + #pragma pack(pop) +#endif + +// Helper functions + +void SetGameInfoData(const GameData &inData, GameInfoData *outData) +{ + assert(outData); + + u_int16_t numManualBlinds = (u_int16_t)inData.manualBlindsList.size(); + + outData->maxNumberOfPlayers = htons(inData.maxNumberOfPlayers); + outData->raiseIntervalMode = htons(inData.raiseIntervalMode); + outData->raiseSmallBlindInterval = inData.raiseIntervalMode == RAISE_ON_HANDNUMBER + ? htons(inData.raiseSmallBlindEveryHandsValue) : htons(inData.raiseSmallBlindEveryMinutesValue); + outData->raiseMode = htons(inData.raiseMode); + outData->endRaiseMode = htons(inData.afterManualBlindsMode); + outData->numberOfManualBlinds = htons(numManualBlinds); + outData->proposedGuiSpeed = htons(inData.guiSpeed); + outData->playerActionTimeout = htons(inData.playerActionTimeoutSec); + outData->endRaiseSmallBlindValue = htonl(inData.afterMBAlwaysRaiseValue); + outData->firstSmallBlind = htonl(inData.firstSmallBlind); + outData->startMoney = htonl(inData.startMoney); + + if (numManualBlinds) + { + u_int32_t *manualBlindsPtr = (u_int32_t *)((char *)outData + sizeof(GameInfoData)); + list::const_iterator i = inData.manualBlindsList.begin(); + list::const_iterator end = inData.manualBlindsList.end(); + while (i != end) + { + *manualBlindsPtr = htonl(*i); + ++manualBlindsPtr; + ++i; + } + } +} + +void GetGameInfoData(const GameInfoData *inData, GameData &outData) +{ + assert(inData); + + u_int16_t numManualBlinds = ntohs(inData->numberOfManualBlinds); + + outData.maxNumberOfPlayers = ntohs(inData->maxNumberOfPlayers); + outData.raiseIntervalMode = static_cast(ntohs(inData->raiseIntervalMode)); + outData.raiseSmallBlindEveryHandsValue = outData.raiseSmallBlindEveryMinutesValue = 0; + if (outData.raiseIntervalMode == RAISE_ON_HANDNUMBER) + outData.raiseSmallBlindEveryHandsValue = ntohs(inData->raiseSmallBlindInterval); + else + outData.raiseSmallBlindEveryMinutesValue = ntohs(inData->raiseSmallBlindInterval); + outData.raiseMode = static_cast(ntohs(inData->raiseMode)); + outData.afterManualBlindsMode = static_cast(ntohs(inData->endRaiseMode)); + outData.guiSpeed = ntohs(inData->proposedGuiSpeed); + outData.playerActionTimeoutSec = ntohs(inData->playerActionTimeout); + outData.firstSmallBlind = ntohl(inData->firstSmallBlind); + outData.afterMBAlwaysRaiseValue = ntohl(inData->endRaiseSmallBlindValue); + outData.startMoney = ntohl(inData->startMoney); + + if (numManualBlinds) + { + const u_int32_t *manualBlindsPtr = (const u_int32_t *)((const char *)inData + sizeof(GameInfoData)); + for (u_int16_t i = 0; i < numManualBlinds; i++) + { + outData.manualBlindsList.push_back(ntohl(*manualBlindsPtr)); + ++manualBlindsPtr; + } + } +} + +void +CheckGameInfoData(const GameInfoData *tmpData) +{ + // Semantic checks + int maxNumPlayers = ntohs(tmpData->maxNumberOfPlayers); + int proposedGuiSpeed = ntohs(tmpData->proposedGuiSpeed); + if (maxNumPlayers < MIN_NUMBER_OF_PLAYERS + || maxNumPlayers > MAX_NUMBER_OF_PLAYERS + || !ntohs(tmpData->raiseIntervalMode) + || !ntohs(tmpData->raiseSmallBlindInterval) + || !ntohs(tmpData->raiseMode) + || !ntohs(tmpData->endRaiseMode) + || proposedGuiSpeed < MIN_GUI_SPEED + || proposedGuiSpeed > MAX_GUI_SPEED + || !ntohl(tmpData->firstSmallBlind) + || !ntohl(tmpData->startMoney)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +boost::shared_ptr +NetPacket::Create(char *data, unsigned &dataSize) +{ + boost::shared_ptr tmpPacket; + + // Check minimum requirements. + if (!data || dataSize < sizeof(NetPacketHeader)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + + NetPacketHeader *tmpHeader = (NetPacketHeader *)data; + u_int16_t tmpLen = ntohs(tmpHeader->length); + + // Check size restrictions. + if (tmpLen < sizeof(NetPacketHeader) + || tmpLen > MAX_PACKET_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + else if (dataSize >= tmpLen) + { + // OK - we have a complete packet. + // Construct a corresponding object. + try + { + switch(ntohs(tmpHeader->type)) + { + case NET_TYPE_INIT: + tmpPacket = boost::shared_ptr(new NetPacketInit); + break; + case NET_TYPE_INIT_ACK: + tmpPacket = boost::shared_ptr(new NetPacketInitAck); + break; + case NET_TYPE_RETRIEVE_AVATAR: + tmpPacket = boost::shared_ptr(new NetPacketRetrieveAvatar); + break; + case NET_TYPE_AVATAR_HEADER: + tmpPacket = boost::shared_ptr(new NetPacketAvatarHeader); + break; + case NET_TYPE_AVATAR_FILE: + tmpPacket = boost::shared_ptr(new NetPacketAvatarFile); + break; + case NET_TYPE_AVATAR_END: + tmpPacket = boost::shared_ptr(new NetPacketAvatarEnd); + break; + case NET_TYPE_UNKNOWN_AVATAR: + tmpPacket = boost::shared_ptr(new NetPacketUnknownAvatar); + break; + case NET_TYPE_GAME_LIST_NEW: + tmpPacket = boost::shared_ptr(new NetPacketGameListNew); + break; + case NET_TYPE_GAME_LIST_UPDATE: + tmpPacket = boost::shared_ptr(new NetPacketGameListUpdate); + break; + case NET_TYPE_GAME_LIST_PLAYER_JOINED: + tmpPacket = boost::shared_ptr(new NetPacketGameListPlayerJoined); + break; + case NET_TYPE_GAME_LIST_PLAYER_LEFT: + tmpPacket = boost::shared_ptr(new NetPacketGameListPlayerLeft); + break; + case NET_TYPE_GAME_LIST_ADMIN_CHANGED: + tmpPacket = boost::shared_ptr(new NetPacketGameListAdminChanged); + break; + case NET_TYPE_RETRIEVE_PLAYER_INFO: + tmpPacket = boost::shared_ptr(new NetPacketRetrievePlayerInfo); + break; + case NET_TYPE_PLAYER_INFO: + tmpPacket = boost::shared_ptr(new NetPacketPlayerInfo); + break; + case NET_TYPE_UNKNOWN_PLAYER_ID: + tmpPacket = boost::shared_ptr(new NetPacketUnknownPlayerId); + break; + case NET_TYPE_CREATE_GAME: + tmpPacket = boost::shared_ptr(new NetPacketCreateGame); + break; + case NET_TYPE_JOIN_GAME: + tmpPacket = boost::shared_ptr(new NetPacketJoinGame); + break; + case NET_TYPE_JOIN_GAME_ACK: + tmpPacket = boost::shared_ptr(new NetPacketJoinGameAck); + break; + case NET_TYPE_JOIN_GAME_FAILED: + tmpPacket = boost::shared_ptr(new NetPacketJoinGameFailed); + break; + case NET_TYPE_PLAYER_JOINED: + tmpPacket = boost::shared_ptr(new NetPacketPlayerJoined); + break; + case NET_TYPE_PLAYER_LEFT: + tmpPacket = boost::shared_ptr(new NetPacketPlayerLeft); + break; + case NET_TYPE_GAME_ADMIN_CHANGED: + tmpPacket = boost::shared_ptr(new NetPacketGameAdminChanged); + break; + case NET_TYPE_KICK_PLAYER: + tmpPacket = boost::shared_ptr(new NetPacketKickPlayer); + break; + case NET_TYPE_LEAVE_CURRENT_GAME: + tmpPacket = boost::shared_ptr(new NetPacketLeaveCurrentGame); + break; + case NET_TYPE_START_EVENT: + tmpPacket = boost::shared_ptr(new NetPacketStartEvent); + break; + case NET_TYPE_START_EVENT_ACK: + tmpPacket = boost::shared_ptr(new NetPacketStartEventAck); + break; + case NET_TYPE_GAME_START: + tmpPacket = boost::shared_ptr(new NetPacketGameStart); + break; + case NET_TYPE_HAND_START: + tmpPacket = boost::shared_ptr(new NetPacketHandStart); + break; + case NET_TYPE_PLAYERS_TURN: + tmpPacket = boost::shared_ptr(new NetPacketPlayersTurn); + break; + case NET_TYPE_PLAYERS_ACTION: + tmpPacket = boost::shared_ptr(new NetPacketPlayersAction); + break; + case NET_TYPE_PLAYERS_ACTION_DONE: + tmpPacket = boost::shared_ptr(new NetPacketPlayersActionDone); + break; + case NET_TYPE_PLAYERS_ACTION_REJECTED: + tmpPacket = boost::shared_ptr(new NetPacketPlayersActionRejected); + break; + case NET_TYPE_DEAL_FLOP_CARDS: + tmpPacket = boost::shared_ptr(new NetPacketDealFlopCards); + break; + case NET_TYPE_DEAL_TURN_CARD: + tmpPacket = boost::shared_ptr(new NetPacketDealTurnCard); + break; + case NET_TYPE_DEAL_RIVER_CARD: + tmpPacket = boost::shared_ptr(new NetPacketDealRiverCard); + break; + case NET_TYPE_ALL_IN_SHOW_CARDS: + tmpPacket = boost::shared_ptr(new NetPacketAllInShowCards); + break; + case NET_TYPE_END_OF_HAND_SHOW_CARDS: + tmpPacket = boost::shared_ptr(new NetPacketEndOfHandShowCards); + break; + case NET_TYPE_END_OF_HAND_HIDE_CARDS: + tmpPacket = boost::shared_ptr(new NetPacketEndOfHandHideCards); + break; + case NET_TYPE_END_OF_GAME: + tmpPacket = boost::shared_ptr(new NetPacketEndOfGame); + break; + case NET_TYPE_STATISTICS_CHANGED: + tmpPacket = boost::shared_ptr(new NetPacketStatisticsChanged); + break; + case NET_TYPE_REMOVED_FROM_GAME: + tmpPacket = boost::shared_ptr(new NetPacketRemovedFromGame); + break; + case NET_TYPE_SEND_CHAT_TEXT: + tmpPacket = boost::shared_ptr(new NetPacketSendChatText); + break; + case NET_TYPE_CHAT_TEXT: + tmpPacket = boost::shared_ptr(new NetPacketChatText); + break; + case NET_TYPE_ERROR: + tmpPacket = boost::shared_ptr(new NetPacketError); + break; + default: + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_TYPE, 0); + } + if (tmpPacket.get()) + tmpPacket->SetRawData(tmpHeader); + } catch (const NetException &) + { + tmpPacket.reset(); + } + + // Consume the bytes. + if (tmpLen < dataSize) + { + dataSize -= tmpLen; + memmove(data, data + tmpLen, dataSize); + } + else + dataSize = 0; + } + return tmpPacket; +} + +NetPacket::NetPacket(u_int16_t type, u_int16_t initialSize, u_int16_t maxSize) +: m_data(NULL), m_initialSize(initialSize), m_maxSize(maxSize) +{ + assert(initialSize >= sizeof(NetPacketHeader)); + m_data = static_cast(malloc(initialSize)); + assert(m_data); + memset(m_data, 0, initialSize); + m_data->type = htons(type); + m_data->length = htons(initialSize); +} + +NetPacket::~NetPacket() +{ + if (m_data) + free(m_data); +} + +const NetPacketHeader * +NetPacket::GetRawData() const +{ + assert(m_data); + return m_data; +} + +NetPacketHeader * +NetPacket::GetRawData() +{ + assert(m_data); + return m_data; +} + +void +NetPacket::SetRawData(const NetPacketHeader *p) +{ + if (!p) + return; + assert(m_data); + + u_int16_t tmpLen = ntohs(p->length); + if (ntohs(p->type) != GetType()) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check whether the data is valid. + Check(p); + // Resize makes sure m_data is large enough. + Resize(tmpLen); + memcpy(m_data, p, tmpLen); +} + +u_int16_t +NetPacket::GetType() const +{ + return ntohs(GetRawData()->type); +} + +u_int16_t +NetPacket::GetLen() const +{ + return ntohs(GetRawData()->length); +} + +const NetPacketInit * +NetPacket::ToNetPacketInit() const +{ + return NULL; +} + +const NetPacketInitAck * +NetPacket::ToNetPacketInitAck() const +{ + return NULL; +} + +const NetPacketRetrieveAvatar * +NetPacket::ToNetPacketRetrieveAvatar() const +{ + return NULL; +} + +const NetPacketAvatarHeader * +NetPacket::ToNetPacketAvatarHeader() const +{ + return NULL; +} + +const NetPacketAvatarFile * +NetPacket::ToNetPacketAvatarFile() const +{ + return NULL; +} + +const NetPacketAvatarEnd * +NetPacket::ToNetPacketAvatarEnd() const +{ + return NULL; +} + +const NetPacketUnknownAvatar * +NetPacket::ToNetPacketUnknownAvatar() const +{ + return NULL; +} + +const NetPacketGameListNew * +NetPacket::ToNetPacketGameListNew() const +{ + return NULL; +} + +const NetPacketGameListUpdate * +NetPacket::ToNetPacketGameListUpdate() const +{ + return NULL; +} + +const NetPacketGameListPlayerJoined * +NetPacket::ToNetPacketGameListPlayerJoined() const +{ + return NULL; +} + +const NetPacketGameListPlayerLeft * +NetPacket::ToNetPacketGameListPlayerLeft() const +{ + return NULL; +} + +const NetPacketGameListAdminChanged * +NetPacket::ToNetPacketGameListAdminChanged() const +{ + return NULL; +} + +const NetPacketRetrievePlayerInfo * +NetPacket::ToNetPacketRetrievePlayerInfo() const +{ + return NULL; +} + +const NetPacketPlayerInfo * +NetPacket::ToNetPacketPlayerInfo() const +{ + return NULL; +} + +const NetPacketUnknownPlayerId * +NetPacket::ToNetPacketUnknownPlayerId() const +{ + return NULL; +} + +const NetPacketCreateGame * +NetPacket::ToNetPacketCreateGame() const +{ + return NULL; +} + +const NetPacketJoinGame * +NetPacket::ToNetPacketJoinGame() const +{ + return NULL; +} + +const NetPacketJoinGameAck * +NetPacket::ToNetPacketJoinGameAck() const +{ + return NULL; +} + +const NetPacketJoinGameFailed * +NetPacket::ToNetPacketJoinGameFailed() const +{ + return NULL; +} + +const NetPacketPlayerJoined * +NetPacket::ToNetPacketPlayerJoined() const +{ + return NULL; +} + +const NetPacketPlayerLeft * +NetPacket::ToNetPacketPlayerLeft() const +{ + return NULL; +} + +const NetPacketGameAdminChanged * +NetPacket::ToNetPacketGameAdminChanged() const +{ + return NULL; +} + +const NetPacketKickPlayer * +NetPacket::ToNetPacketKickPlayer() const +{ + return NULL; +} + +const NetPacketLeaveCurrentGame * +NetPacket::ToNetPacketLeaveCurrentGame() const +{ + return NULL; +} + +const NetPacketStartEvent * +NetPacket::ToNetPacketStartEvent() const +{ + return NULL; +} + +const NetPacketStartEventAck * +NetPacket::ToNetPacketStartEventAck() const +{ + return NULL; +} + +const NetPacketGameStart * +NetPacket::ToNetPacketGameStart() const +{ + return NULL; +} + +const NetPacketHandStart * +NetPacket::ToNetPacketHandStart() const +{ + return NULL; +} + +const NetPacketPlayersTurn * +NetPacket::ToNetPacketPlayersTurn() const +{ + return NULL; +} + +const NetPacketPlayersAction * +NetPacket::ToNetPacketPlayersAction() const +{ + return NULL; +} + +const NetPacketPlayersActionDone * +NetPacket::ToNetPacketPlayersActionDone() const +{ + return NULL; +} + +const NetPacketPlayersActionRejected * +NetPacket::ToNetPacketPlayersActionRejected() const +{ + return NULL; +} + +const NetPacketDealFlopCards * +NetPacket::ToNetPacketDealFlopCards() const +{ + return NULL; +} + +const NetPacketDealTurnCard * +NetPacket::ToNetPacketDealTurnCard() const +{ + return NULL; +} + +const NetPacketDealRiverCard * +NetPacket::ToNetPacketDealRiverCard() const +{ + return NULL; +} + +const NetPacketAllInShowCards * +NetPacket::ToNetPacketAllInShowCards() const +{ + return NULL; +} + +const NetPacketEndOfHandShowCards * +NetPacket::ToNetPacketEndOfHandShowCards() const +{ + return NULL; +} + +const NetPacketEndOfHandHideCards * +NetPacket::ToNetPacketEndOfHandHideCards() const +{ + return NULL; +} + +const NetPacketEndOfGame * +NetPacket::ToNetPacketEndOfGame() const +{ + return NULL; +} + +const NetPacketStatisticsChanged * +NetPacket::ToNetPacketStatisticsChanged() const +{ + return NULL; +} + +const NetPacketRemovedFromGame * +NetPacket::ToNetPacketRemovedFromGame() const +{ + return NULL; +} + +const NetPacketSendChatText * +NetPacket::ToNetPacketSendChatText() const +{ + return NULL; +} + +const NetPacketChatText * +NetPacket::ToNetPacketChatText() const +{ + return NULL; +} + +const NetPacketError * +NetPacket::ToNetPacketError() const +{ + return NULL; +} + +void +NetPacket::Resize(u_int16_t newLen) +{ + assert(m_data); + u_int16_t oldLen = GetLen(); + if (newLen != oldLen) + { + if (newLen < sizeof(NetPacketHeader)) + throw NetException(__FILE__, __LINE__, ERR_SOCK_INTERNAL, 0); + else + { + NetPacketHeader *newData = (NetPacketHeader *)malloc(newLen); + if (!newData) + throw NetException(__FILE__, __LINE__, ERR_SOCK_INTERNAL, 0); + else + { + // Copy as much data as possible. + memcpy(newData, m_data, newLen > oldLen ? oldLen : newLen); + // Initialize new data to 0. + if (newLen > oldLen) + memset(((unsigned char *)newData) + oldLen, 0, newLen - oldLen); + // Set new len. + newData->length = htons(newLen); + // Switch over to new data. + free(m_data); + m_data = newData; + } + } + } +} + +void +NetPacket::Check(const NetPacketHeader *data) const +{ + // Check the input data. + assert(data); + + // Check minimum and maximum size. + u_int16_t dataLen = ntohs(data->length); + if (dataLen < m_initialSize || dataLen > m_maxSize) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + + InternalCheck(data); +} + +//----------------------------------------------------------------------------- + +NetPacketInit::NetPacketInit() +: NetPacket(NET_TYPE_INIT, sizeof(NetPacketInitData), MAX_PACKET_SIZE) +{ + NetPacketInitData *tmpData = (NetPacketInitData *)GetRawData(); + tmpData->requestedVersionMajor = htons(NET_VERSION_MAJOR); + tmpData->requestedVersionMinor = htons(NET_VERSION_MINOR); +} + +NetPacketInit::~NetPacketInit() +{ +} + +boost::shared_ptr +NetPacketInit::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketInit); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketInit::SetData(const NetPacketInit::Data &inData) +{ + u_int16_t playerNameLen = (u_int16_t)inData.playerName.length(); + u_int16_t passwordLen = (u_int16_t)inData.password.length(); + + // Some basic checks, so we don't use up too much memory. + // The constructed packet will also be checked. + if (!playerNameLen || playerNameLen > MAX_NAME_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_NAME, 0); + if (passwordLen > MAX_PASSWORD_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD_STR, 0); + + int avatarSize = inData.showAvatar ? MD5_DATA_SIZE : 0; + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketInitData) + + avatarSize + + ADD_PADDING(playerNameLen) + + ADD_PADDING(passwordLen))); + + NetPacketInitData *tmpData = (NetPacketInitData *)GetRawData(); + + // Set the data. + tmpData->passwordLength = htons(passwordLen); + tmpData->playerNameLength = htons(playerNameLen); + + if (inData.showAvatar) + { + // Store MD5 sum of avatar. + tmpData->privacyFlags = htons(NET_PRIVACY_FLAG_SHOW_AVATAR); + char *avatarPtr = (char *)tmpData + sizeof(NetPacketInitData); + memcpy(avatarPtr, inData.avatar.data, MD5_DATA_SIZE); + } + + char *passwordPtr = (char *)tmpData + sizeof(NetPacketInitData) + avatarSize; + memcpy(passwordPtr, inData.password.c_str(), passwordLen); + memcpy(passwordPtr + ADD_PADDING(passwordLen), inData.playerName.c_str(), playerNameLen); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketInit::GetData(NetPacketInit::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketInitData *tmpData = (NetPacketInitData *)GetRawData(); + + outData.versionMajor = ntohs(tmpData->requestedVersionMajor); + outData.versionMinor = ntohs(tmpData->requestedVersionMinor); + + outData.showAvatar = ntohs(tmpData->privacyFlags) & NET_PRIVACY_FLAG_SHOW_AVATAR; + + if (outData.showAvatar) + { + char *avatarPtr = (char *)tmpData + sizeof(NetPacketInitData); + memcpy(outData.avatar.data, avatarPtr, MD5_DATA_SIZE); + } + + int avatarSize = outData.showAvatar ? MD5_DATA_SIZE : 0; + u_int16_t passwordLen = ntohs(tmpData->passwordLength); + char *passwordPtr = (char *)tmpData + sizeof(NetPacketInitData) + avatarSize; + outData.password = string(passwordPtr, passwordLen); + outData.playerName = string(passwordPtr + ADD_PADDING(passwordLen), ntohs(tmpData->playerNameLength)); +} + +const NetPacketInit * +NetPacketInit::ToNetPacketInit() const +{ + return this; +} + +void +NetPacketInit::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketInitData *tmpData = (NetPacketInitData *)data; + int passwordLength = ntohs(tmpData->passwordLength); + int playerNameLength = ntohs(tmpData->playerNameLength); + int avatarSize = ntohs(tmpData->privacyFlags) & NET_PRIVACY_FLAG_SHOW_AVATAR ? MD5_DATA_SIZE : 0; + // Generous checking of dynamic packet size - + // larger packets are allowed. + // This is because the version number is in this packet, + // and later versions might provide larger packets. + if (dataLen < + sizeof(NetPacketInitData) + + avatarSize + + ADD_PADDING(passwordLength) + + ADD_PADDING(playerNameLength)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string sizes. + if (passwordLength > MAX_PASSWORD_SIZE + || !playerNameLength + || playerNameLength > MAX_NAME_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check name string. + char *namePtr = (char *)tmpData + sizeof(NetPacketInitData) + avatarSize + ADD_PADDING(passwordLength); + if (namePtr[0] == 0) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketInitAck::NetPacketInitAck() +: NetPacket(NET_TYPE_INIT_ACK, sizeof(NetPacketInitAckData), sizeof(NetPacketInitAckData)) +{ +} + +NetPacketInitAck::~NetPacketInitAck() +{ +} + +boost::shared_ptr +NetPacketInitAck::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketInitAck); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketInitAck::SetData(const NetPacketInitAck::Data &inData) +{ + NetPacketInitAckData *tmpData = (NetPacketInitAckData *)GetRawData(); + + tmpData->latestGameVersion = htons(inData.latestGameVersion); + tmpData->latestBetaRevision = htons(inData.latestBetaRevision); + tmpData->sessionId = htonl(inData.sessionId); + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketInitAck::GetData(NetPacketInitAck::Data &outData) const +{ + NetPacketInitAckData *tmpData = (NetPacketInitAckData *)GetRawData(); + + outData.latestGameVersion = ntohs(tmpData->latestGameVersion); + outData.latestBetaRevision = ntohs(tmpData->latestBetaRevision); + outData.sessionId = ntohl(tmpData->sessionId); + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketInitAck * +NetPacketInitAck::ToNetPacketInitAck() const +{ + return this; +} + +void +NetPacketInitAck::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketRetrieveAvatar::NetPacketRetrieveAvatar() +: NetPacket(NET_TYPE_RETRIEVE_AVATAR, sizeof(NetPacketRetrieveAvatarData), sizeof(NetPacketRetrieveAvatarData)) +{ +} + +NetPacketRetrieveAvatar::~NetPacketRetrieveAvatar() +{ +} + +boost::shared_ptr +NetPacketRetrieveAvatar::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketRetrieveAvatar); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketRetrieveAvatar::SetData(const NetPacketRetrieveAvatar::Data &inData) +{ + NetPacketRetrieveAvatarData *tmpData = (NetPacketRetrieveAvatarData *)GetRawData(); + + tmpData->requestId = htonl(inData.requestId); + memcpy(tmpData->avatarMD5, inData.avatar.data, MD5_DATA_SIZE); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketRetrieveAvatar::GetData(NetPacketRetrieveAvatar::Data &outData) const +{ + NetPacketRetrieveAvatarData *tmpData = (NetPacketRetrieveAvatarData *)GetRawData(); + + outData.requestId = ntohl(tmpData->requestId); + memcpy(outData.avatar.data, tmpData->avatarMD5, MD5_DATA_SIZE); +} + +const NetPacketRetrieveAvatar * +NetPacketRetrieveAvatar::ToNetPacketRetrieveAvatar() const +{ + return this; +} + +void +NetPacketRetrieveAvatar::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketAvatarHeader::NetPacketAvatarHeader() +: NetPacket(NET_TYPE_AVATAR_HEADER, sizeof(NetPacketAvatarHeaderData), sizeof(NetPacketAvatarHeaderData)) +{ +} + +NetPacketAvatarHeader::~NetPacketAvatarHeader() +{ +} + +boost::shared_ptr +NetPacketAvatarHeader::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketAvatarHeader); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketAvatarHeader::SetData(const NetPacketAvatarHeader::Data &inData) +{ + NetPacketAvatarHeaderData *tmpData = (NetPacketAvatarHeaderData *)GetRawData(); + + tmpData->requestId = htonl(inData.requestId); + tmpData->avatarFileSize = htonl(inData.avatarFileSize); + tmpData->avatarFileType = htons(inData.avatarFileType); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketAvatarHeader::GetData(NetPacketAvatarHeader::Data &outData) const +{ + NetPacketAvatarHeaderData *tmpData = (NetPacketAvatarHeaderData *)GetRawData(); + + outData.requestId = ntohl(tmpData->requestId); + outData.avatarFileSize = ntohl(tmpData->avatarFileSize); + outData.avatarFileType = static_cast(ntohs(tmpData->avatarFileType)); +} + +const NetPacketAvatarHeader * +NetPacketAvatarHeader::ToNetPacketAvatarHeader() const +{ + return this; +} + +void +NetPacketAvatarHeader::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketAvatarFile::NetPacketAvatarFile() +: NetPacket(NET_TYPE_AVATAR_FILE, sizeof(NetPacketAvatarFileData), MAX_PACKET_SIZE) +{ +} + +NetPacketAvatarFile::~NetPacketAvatarFile() +{ +} + +boost::shared_ptr +NetPacketAvatarFile::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketAvatarFile); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketAvatarFile::SetData(const NetPacketAvatarFile::Data &inData) +{ + int fileDataSize = static_cast(inData.fileData.size()); + + if (fileDataSize > MAX_FILE_DATA_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_BUF_INVALID_SIZE, 0); + + Resize((u_int16_t) + (sizeof(NetPacketAvatarFileData) + + ADD_PADDING(fileDataSize))); + + NetPacketAvatarFileData *tmpData = (NetPacketAvatarFileData *)GetRawData(); + + tmpData->requestId = htonl(inData.requestId); + tmpData->blockSize = htons(fileDataSize); + + char *avatarDataPtr = (char *)tmpData + sizeof(NetPacketAvatarFileData); + memcpy(avatarDataPtr, &inData.fileData[0], fileDataSize); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketAvatarFile::GetData(NetPacketAvatarFile::Data &outData) const +{ + NetPacketAvatarFileData *tmpData = (NetPacketAvatarFileData *)GetRawData(); + + outData.requestId = ntohl(tmpData->requestId); + int fileDataSize = ntohs(tmpData->blockSize); + + char *avatarDataPtr = (char *)tmpData + sizeof(NetPacketAvatarFileData); + outData.fileData.resize(fileDataSize); + memcpy(&outData.fileData[0], avatarDataPtr, fileDataSize); +} + +const NetPacketAvatarFile * +NetPacketAvatarFile::ToNetPacketAvatarFile() const +{ + return this; +} + +void +NetPacketAvatarFile::InternalCheck(const NetPacketHeader *data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketAvatarFileData *tmpData = (NetPacketAvatarFileData *)data; + int fileDataSize = ntohs(tmpData->blockSize); + + // Exact checking of dynamic packet size. + if (dataLen != + sizeof(NetPacketAvatarFileData) + + ADD_PADDING(fileDataSize)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + if (!fileDataSize || fileDataSize > MAX_FILE_DATA_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketAvatarEnd::NetPacketAvatarEnd() +: NetPacket(NET_TYPE_AVATAR_END, sizeof(NetPacketAvatarEndData), sizeof(NetPacketAvatarEndData)) +{ +} + +NetPacketAvatarEnd::~NetPacketAvatarEnd() +{ +} + +boost::shared_ptr +NetPacketAvatarEnd::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketAvatarEnd); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketAvatarEnd::SetData(const NetPacketAvatarEnd::Data &inData) +{ + NetPacketAvatarEndData *tmpData = (NetPacketAvatarEndData *)GetRawData(); + + tmpData->requestId = htonl(inData.requestId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketAvatarEnd::GetData(NetPacketAvatarEnd::Data &outData) const +{ + NetPacketAvatarEndData *tmpData = (NetPacketAvatarEndData *)GetRawData(); + + outData.requestId = ntohl(tmpData->requestId); +} + +const NetPacketAvatarEnd * +NetPacketAvatarEnd::ToNetPacketAvatarEnd() const +{ + return this; +} + +void +NetPacketAvatarEnd::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketUnknownAvatar::NetPacketUnknownAvatar() +: NetPacket(NET_TYPE_UNKNOWN_AVATAR, sizeof(NetPacketUnknownAvatarData), sizeof(NetPacketUnknownAvatarData)) +{ +} + +NetPacketUnknownAvatar::~NetPacketUnknownAvatar() +{ +} + +boost::shared_ptr +NetPacketUnknownAvatar::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketUnknownAvatar); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketUnknownAvatar::SetData(const NetPacketUnknownAvatar::Data &inData) +{ + NetPacketUnknownAvatarData *tmpData = (NetPacketUnknownAvatarData *)GetRawData(); + + tmpData->requestId = htonl(inData.requestId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketUnknownAvatar::GetData(NetPacketUnknownAvatar::Data &outData) const +{ + NetPacketUnknownAvatarData *tmpData = (NetPacketUnknownAvatarData *)GetRawData(); + + outData.requestId = ntohl(tmpData->requestId); +} + +const NetPacketUnknownAvatar * +NetPacketUnknownAvatar::ToNetPacketUnknownAvatar() const +{ + return this; +} + +void +NetPacketUnknownAvatar::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketGameListNew::NetPacketGameListNew() +: NetPacket(NET_TYPE_GAME_LIST_NEW, sizeof(NetPacketGameListNewData), MAX_PACKET_SIZE) +{ +} + +NetPacketGameListNew::~NetPacketGameListNew() +{ +} + +boost::shared_ptr +NetPacketGameListNew::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameListNew); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) +{ + u_int16_t gameNameLen = (u_int16_t)inData.gameInfo.name.length(); + u_int16_t curNumPlayers = (u_int16_t)inData.gameInfo.players.size(); + u_int16_t numManualBlinds = (u_int16_t)inData.gameInfo.data.manualBlindsList.size(); + + int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); + + // Some basic checks, so we don't use up too much memory. + // The constructed packet will also be checked. + if (!gameNameLen || gameNameLen > MAX_NAME_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_GAME_NAME, 0); + if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) + throw NetException(__FILE__, __LINE__, ERR_NET_TOO_MANY_MANUAL_BLINDS, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketGameListNewData) + + manualBlindsSize + + ADD_PADDING(gameNameLen) + + curNumPlayers * sizeof(unsigned) + )); + + NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->adminPlayerId = htonl(inData.gameInfo.adminPlayerId); + tmpData->gameMode = htons(inData.gameInfo.mode); + tmpData->gameNameLength = htons(gameNameLen); + tmpData->curNumberOfPlayers = htons(curNumPlayers); + tmpData->gameFlags = htons(inData.gameInfo.isPasswordProtected ? NET_GAME_FLAG_PASSWORD_PROTECTED : 0); + + SetGameInfoData(inData.gameInfo.data, &tmpData->gameData); + + char *gameNamePtr = (char *)tmpData + sizeof(NetPacketGameListNewData) + manualBlindsSize; + memcpy(gameNamePtr, inData.gameInfo.name.c_str(), gameNameLen); + + PlayerIdList::const_iterator i = inData.gameInfo.players.begin(); + PlayerIdList::const_iterator end = inData.gameInfo.players.end(); + + // Copy the player list to continous memory + unsigned *tmpPlayer = + (unsigned *)(gameNamePtr + ADD_PADDING(gameNameLen)); + while (i != end) + { + *tmpPlayer = htonl(*i); + ++tmpPlayer; + ++i; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameListNew::GetData(NetPacketGameListNew::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)GetRawData(); + + u_int16_t numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); + int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); + + outData.gameId = ntohl(tmpData->gameId); + outData.gameInfo.adminPlayerId = ntohl(tmpData->adminPlayerId); + outData.gameInfo.mode = static_cast(ntohs(tmpData->gameMode)); + u_int16_t gameNameLen = ntohs(tmpData->gameNameLength); + u_int16_t curNumPlayers = ntohs(tmpData->curNumberOfPlayers); + outData.gameInfo.isPasswordProtected = ntohs(tmpData->gameFlags) == NET_GAME_FLAG_PASSWORD_PROTECTED; + + GetGameInfoData(&tmpData->gameData, outData.gameInfo.data); + + char *gameNamePtr = (char *)tmpData + sizeof(NetPacketGameListNewData) + manualBlindsSize; + outData.gameInfo.name = string(gameNamePtr, gameNameLen); + + unsigned *tmpPlayer = (unsigned *)(gameNamePtr + ADD_PADDING(gameNameLen)); + + // Store all available players. + for (int i = 0; i < curNumPlayers; i++) + { + outData.gameInfo.players.push_back(ntohl(*tmpPlayer)); + ++tmpPlayer; + } +} + +const NetPacketGameListNew * +NetPacketGameListNew::ToNetPacketGameListNew() const +{ + return this; +} + +void +NetPacketGameListNew::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)data; + int gameNameLength = ntohs(tmpData->gameNameLength); + int curNumPlayers = ntohs(tmpData->curNumberOfPlayers); + u_int16_t numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); + int manualBlindsLength = numManualBlinds * sizeof(u_int32_t); + // Exact checking of dynamic packet size. + if (dataLen != + sizeof(NetPacketGameListNewData) + + manualBlindsLength + + ADD_PADDING(gameNameLength) + + curNumPlayers * sizeof(unsigned)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check manual blind list size + if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string size. + if (!gameNameLength + || gameNameLength > MAX_NAME_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check name string. + char *namePtr = (char *)tmpData + sizeof(NetPacketGameListNewData) + manualBlindsLength; + if (namePtr[0] == 0) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketGameListUpdate::NetPacketGameListUpdate() +: NetPacket(NET_TYPE_GAME_LIST_UPDATE, sizeof(NetPacketGameListUpdateData), sizeof(NetPacketGameListUpdateData)) +{ +} + +NetPacketGameListUpdate::~NetPacketGameListUpdate() +{ +} + +boost::shared_ptr +NetPacketGameListUpdate::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameListUpdate); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameListUpdate::SetData(const NetPacketGameListUpdate::Data &inData) +{ + NetPacketGameListUpdateData *tmpData = (NetPacketGameListUpdateData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->gameMode = htons(inData.gameMode); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameListUpdate::GetData(NetPacketGameListUpdate::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameListUpdateData *tmpData = (NetPacketGameListUpdateData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + outData.gameMode = static_cast(ntohs(tmpData->gameMode)); +} + +const NetPacketGameListUpdate * +NetPacketGameListUpdate::ToNetPacketGameListUpdate() const +{ + return this; +} + +void +NetPacketGameListUpdate::InternalCheck(const NetPacketHeader*) const +{ +} + +//----------------------------------------------------------------------------- + +NetPacketGameListPlayerJoined::NetPacketGameListPlayerJoined() +: NetPacket(NET_TYPE_GAME_LIST_PLAYER_JOINED, sizeof(NetPacketGameListPlayerJoinedData), sizeof(NetPacketGameListPlayerJoinedData)) +{ +} + +NetPacketGameListPlayerJoined::~NetPacketGameListPlayerJoined() +{ +} + +boost::shared_ptr +NetPacketGameListPlayerJoined::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameListPlayerJoined); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameListPlayerJoined::SetData(const NetPacketGameListPlayerJoined::Data &inData) +{ + NetPacketGameListPlayerJoinedData *tmpData = (NetPacketGameListPlayerJoinedData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameListPlayerJoined::GetData(NetPacketGameListPlayerJoined::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameListPlayerJoinedData *tmpData = (NetPacketGameListPlayerJoinedData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketGameListPlayerJoined * +NetPacketGameListPlayerJoined::ToNetPacketGameListPlayerJoined() const +{ + return this; +} + +void +NetPacketGameListPlayerJoined::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketGameListPlayerLeft::NetPacketGameListPlayerLeft() +: NetPacket(NET_TYPE_GAME_LIST_PLAYER_LEFT, sizeof(NetPacketGameListPlayerLeftData), sizeof(NetPacketGameListPlayerLeftData)) +{ +} + +NetPacketGameListPlayerLeft::~NetPacketGameListPlayerLeft() +{ +} + +boost::shared_ptr +NetPacketGameListPlayerLeft::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameListPlayerLeft); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameListPlayerLeft::SetData(const NetPacketGameListPlayerLeft::Data &inData) +{ + NetPacketGameListPlayerLeftData *tmpData = (NetPacketGameListPlayerLeftData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameListPlayerLeft::GetData(NetPacketGameListPlayerLeft::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameListPlayerLeftData *tmpData = (NetPacketGameListPlayerLeftData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketGameListPlayerLeft * +NetPacketGameListPlayerLeft::ToNetPacketGameListPlayerLeft() const +{ + return this; +} + +void +NetPacketGameListPlayerLeft::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketGameListAdminChanged::NetPacketGameListAdminChanged() +: NetPacket(NET_TYPE_GAME_LIST_ADMIN_CHANGED, sizeof(NetPacketGameListAdminChangedData), sizeof(NetPacketGameListAdminChangedData)) +{ +} + +NetPacketGameListAdminChanged::~NetPacketGameListAdminChanged() +{ +} + +boost::shared_ptr +NetPacketGameListAdminChanged::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameListAdminChanged); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameListAdminChanged::SetData(const NetPacketGameListAdminChanged::Data &inData) +{ + NetPacketGameListAdminChangedData *tmpData = (NetPacketGameListAdminChangedData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->newAdminPlayerId = htonl(inData.newAdminplayerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameListAdminChanged::GetData(NetPacketGameListAdminChanged::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameListAdminChangedData *tmpData = (NetPacketGameListAdminChangedData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + outData.newAdminplayerId = ntohl(tmpData->newAdminPlayerId); +} + +const NetPacketGameListAdminChanged * +NetPacketGameListAdminChanged::ToNetPacketGameListAdminChanged() const +{ + return this; +} + +void +NetPacketGameListAdminChanged::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketRetrievePlayerInfo::NetPacketRetrievePlayerInfo() +: NetPacket(NET_TYPE_RETRIEVE_PLAYER_INFO, sizeof(NetPacketRetrievePlayerInfoData), sizeof(NetPacketRetrievePlayerInfoData)) +{ +} + +NetPacketRetrievePlayerInfo::~NetPacketRetrievePlayerInfo() +{ +} + +boost::shared_ptr +NetPacketRetrievePlayerInfo::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketRetrievePlayerInfo); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketRetrievePlayerInfo::SetData(const NetPacketRetrievePlayerInfo::Data &inData) +{ + NetPacketRetrievePlayerInfoData *tmpData = (NetPacketRetrievePlayerInfoData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketRetrievePlayerInfo::GetData(NetPacketRetrievePlayerInfo::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketRetrievePlayerInfoData *tmpData = (NetPacketRetrievePlayerInfoData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketRetrievePlayerInfo * +NetPacketRetrievePlayerInfo::ToNetPacketRetrievePlayerInfo() const +{ + return this; +} + +void +NetPacketRetrievePlayerInfo::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketPlayerInfo::NetPacketPlayerInfo() +: NetPacket(NET_TYPE_PLAYER_INFO, sizeof(NetPacketPlayerInfoData), MAX_PACKET_SIZE) +{ +} + +NetPacketPlayerInfo::~NetPacketPlayerInfo() +{ +} + +boost::shared_ptr +NetPacketPlayerInfo::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayerInfo); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayerInfo::SetData(const NetPacketPlayerInfo::Data &inData) +{ + u_int16_t playerNameLen = (u_int16_t)inData.playerInfo.playerName.length(); + + if (!playerNameLen || playerNameLen > MAX_NAME_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_NAME, 0); + + int avatarSize = inData.playerInfo.hasAvatar ? MD5_DATA_SIZE : 0; + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketPlayerInfoData) + avatarSize + ADD_PADDING(playerNameLen))); + + NetPacketPlayerInfoData *tmpData = (NetPacketPlayerInfoData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + tmpData->playerNameLength = htons(playerNameLen); + + u_int16_t tmpPlayerFlags = inData.playerInfo.ptype == PLAYER_TYPE_HUMAN ? NET_PLAYER_FLAG_HUMAN : 0; + if (inData.playerInfo.hasAvatar) + { + tmpPlayerFlags |= NET_PLAYER_FLAG_HAS_AVATAR; + char *avatarPtr = (char *)tmpData + sizeof(NetPacketPlayerInfoData); + memcpy(avatarPtr, inData.playerInfo.avatar.data, MD5_DATA_SIZE); + } + tmpData->playerFlags = htons(tmpPlayerFlags); + + char *namePtr = (char *)tmpData + sizeof(NetPacketPlayerInfoData) + avatarSize; + memcpy(namePtr, inData.playerInfo.playerName.c_str(), playerNameLen); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayerInfo::GetData(NetPacketPlayerInfo::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketPlayerInfoData *tmpData = (NetPacketPlayerInfoData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); + u_int16_t tmpPlayerFlags = ntohs(tmpData->playerFlags); + outData.playerInfo.ptype = (tmpPlayerFlags & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER; + outData.playerInfo.hasAvatar = (tmpPlayerFlags & NET_PLAYER_FLAG_HAS_AVATAR) ? true : false; + + if (outData.playerInfo.hasAvatar) + { + char *avatarPtr = (char *)tmpData + sizeof(NetPacketPlayerInfoData); + memcpy(outData.playerInfo.avatar.data, avatarPtr, MD5_DATA_SIZE); + } + + int avatarSize = outData.playerInfo.hasAvatar ? MD5_DATA_SIZE : 0; + + char *namePtr = (char *)tmpData + avatarSize + sizeof(NetPacketPlayerInfoData); + outData.playerInfo.playerName = string(namePtr, ntohs(tmpData->playerNameLength)); +} + +const NetPacketPlayerInfo * +NetPacketPlayerInfo::ToNetPacketPlayerInfo() const +{ + return this; +} + +void +NetPacketPlayerInfo::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketPlayerInfoData *tmpData = (NetPacketPlayerInfoData *)data; + int playerNameLength = ntohs(tmpData->playerNameLength); + int avatarSize = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HAS_AVATAR) ? MD5_DATA_SIZE : 0; + // Exact checking this time. + if (dataLen != + sizeof(NetPacketPlayerInfoData) + + avatarSize + + ADD_PADDING(playerNameLength)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string sizes. + if (!playerNameLength + || playerNameLength > MAX_NAME_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketUnknownPlayerId::NetPacketUnknownPlayerId() +: NetPacket(NET_TYPE_UNKNOWN_PLAYER_ID, sizeof(NetPacketUnknownPlayerIdData), sizeof(NetPacketUnknownPlayerIdData)) +{ +} + +NetPacketUnknownPlayerId::~NetPacketUnknownPlayerId() +{ +} + +boost::shared_ptr +NetPacketUnknownPlayerId::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketUnknownPlayerId); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketUnknownPlayerId::SetData(const NetPacketUnknownPlayerId::Data &inData) +{ + NetPacketUnknownPlayerIdData *tmpData = (NetPacketUnknownPlayerIdData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketUnknownPlayerId::GetData(NetPacketUnknownPlayerId::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketUnknownPlayerIdData *tmpData = (NetPacketUnknownPlayerIdData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketUnknownPlayerId * +NetPacketUnknownPlayerId::ToNetPacketUnknownPlayerId() const +{ + return this; +} + +void +NetPacketUnknownPlayerId::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} +//----------------------------------------------------------------------------- + +NetPacketCreateGame::NetPacketCreateGame() +: NetPacket(NET_TYPE_CREATE_GAME, sizeof(NetPacketCreateGameData), MAX_PACKET_SIZE) +{ +} + +NetPacketCreateGame::~NetPacketCreateGame() +{ +} + +boost::shared_ptr +NetPacketCreateGame::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketCreateGame); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketCreateGame::SetData(const NetPacketCreateGame::Data &inData) +{ + u_int16_t gameNameLen = (u_int16_t)inData.gameName.length(); + u_int16_t passwordLen = (u_int16_t)inData.password.length(); + u_int16_t numManualBlinds = (u_int16_t)inData.gameData.manualBlindsList.size(); + + // Some basic checks, so we don't use up too much memory. + // The constructed packet will also be checked. + if (!gameNameLen || gameNameLen > MAX_NAME_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_NAME, 0); + if (passwordLen > MAX_PASSWORD_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD_STR, 0); + if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) + throw NetException(__FILE__, __LINE__, ERR_NET_TOO_MANY_MANUAL_BLINDS, 0); + + int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketCreateGameData) + manualBlindsSize + ADD_PADDING(gameNameLen) + ADD_PADDING(passwordLen))); + + NetPacketCreateGameData *tmpData = (NetPacketCreateGameData *)GetRawData(); + + // Set the data. + tmpData->passwordLength = htons(passwordLen); + tmpData->gameNameLength = htons(gameNameLen); + + SetGameInfoData(inData.gameData, &tmpData->gameData); + + char *passwordPtr = (char *)tmpData + sizeof(NetPacketCreateGameData) + manualBlindsSize; + memcpy(passwordPtr, inData.password.c_str(), passwordLen); + memcpy(passwordPtr + ADD_PADDING(passwordLen), inData.gameName.c_str(), gameNameLen); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketCreateGame::GetData(NetPacketCreateGame::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketCreateGameData *tmpData = (NetPacketCreateGameData *)GetRawData(); + + u_int16_t numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); + int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); + + GetGameInfoData(&tmpData->gameData, outData.gameData); + + u_int16_t passwordLen = ntohs(tmpData->passwordLength); + char *passwordPtr = (char *)tmpData + manualBlindsSize + sizeof(NetPacketCreateGameData); + outData.password = string(passwordPtr, passwordLen); + outData.gameName = string(passwordPtr + ADD_PADDING(passwordLen), ntohs(tmpData->gameNameLength)); +} + +const NetPacketCreateGame * +NetPacketCreateGame::ToNetPacketCreateGame() const +{ + return this; +} + +void +NetPacketCreateGame::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketCreateGameData *tmpData = (NetPacketCreateGameData *)data; + int passwordLength = ntohs(tmpData->passwordLength); + int gameNameLength = ntohs(tmpData->gameNameLength); + int numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); + int manualBlindsLength = numManualBlinds * sizeof(u_int32_t); + // Exact checking of dynamic packet size. + if (dataLen < + sizeof(NetPacketCreateGameData) + + manualBlindsLength + + ADD_PADDING(passwordLength) + + ADD_PADDING(gameNameLength)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check manual blind list size + if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string sizes. + if (passwordLength > MAX_PASSWORD_SIZE + || !gameNameLength + || gameNameLength > MAX_NAME_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check name string. + char *namePtr = (char *)tmpData + sizeof(NetPacketCreateGameData) + manualBlindsLength + ADD_PADDING(passwordLength); + if (namePtr[0] == 0) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + CheckGameInfoData(&tmpData->gameData); +} + +//----------------------------------------------------------------------------- + +NetPacketJoinGame::NetPacketJoinGame() +: NetPacket(NET_TYPE_JOIN_GAME, sizeof(NetPacketJoinGameData), MAX_PACKET_SIZE) +{ +} + +NetPacketJoinGame::~NetPacketJoinGame() +{ +} + +boost::shared_ptr +NetPacketJoinGame::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketJoinGame); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketJoinGame::SetData(const NetPacketJoinGame::Data &inData) +{ + u_int16_t passwordLen = (u_int16_t)inData.password.length(); + + // Some basic checks, so we don't use up too much memory. + // The constructed packet will also be checked. + if (passwordLen > MAX_PASSWORD_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD_STR, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketJoinGameData) + ADD_PADDING(passwordLen))); + + NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->passwordLength = htons(passwordLen); + + char *passwordPtr = (char *)tmpData + sizeof(NetPacketJoinGameData); + memcpy(passwordPtr, inData.password.c_str(), passwordLen); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketJoinGame::GetData(NetPacketJoinGame::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + + u_int16_t passwordLen = ntohs(tmpData->passwordLength); + char *passwordPtr = (char *)tmpData + sizeof(NetPacketJoinGameData); + outData.password = string(passwordPtr, passwordLen); +} + +const NetPacketJoinGame * +NetPacketJoinGame::ToNetPacketJoinGame() const +{ + return this; +} + +void +NetPacketJoinGame::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)data; + int passwordLength = ntohs(tmpData->passwordLength); + // Exact checking of dynamic packet size. + if (dataLen < + sizeof(NetPacketJoinGameData) + + ADD_PADDING(passwordLength)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string size. + if (passwordLength > MAX_PASSWORD_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketJoinGameAck::NetPacketJoinGameAck() +: NetPacket(NET_TYPE_JOIN_GAME_ACK, sizeof(NetPacketJoinGameAckData), MAX_PACKET_SIZE) +{ +} + +NetPacketJoinGameAck::~NetPacketJoinGameAck() +{ +} + +boost::shared_ptr +NetPacketJoinGameAck::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketJoinGameAck); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketJoinGameAck::SetData(const NetPacketJoinGameAck::Data &inData) +{ + u_int16_t numManualBlinds = (u_int16_t)inData.gameData.manualBlindsList.size(); + + // Some basic checks, so we don't use up too much memory. + // The constructed packet will also be checked. + if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) + throw NetException(__FILE__, __LINE__, ERR_NET_TOO_MANY_MANUAL_BLINDS, 0); + + int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketJoinGameAckData) + manualBlindsSize)); + + NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->playerRights = htons(inData.prights); + + SetGameInfoData(inData.gameData, &tmpData->gameData); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketJoinGameAck::GetData(NetPacketJoinGameAck::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + outData.prights = static_cast(ntohs(tmpData->playerRights)); + + GetGameInfoData(&tmpData->gameData, outData.gameData); +} + +const NetPacketJoinGameAck * +NetPacketJoinGameAck::ToNetPacketJoinGameAck() const +{ + return this; +} + +void +NetPacketJoinGameAck::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)data; + int numManualBlinds = ntohs(tmpData->gameData.numberOfManualBlinds); + int manualBlindsLength = numManualBlinds * sizeof(u_int32_t); + // Exact checking of dynamic packet size. + if (dataLen < + sizeof(NetPacketJoinGameAckData) + + manualBlindsLength) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + + // Check manual blind list size + if (numManualBlinds > MAX_NUM_MANUAL_BLINDS) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Semantic checks + CheckGameInfoData(&tmpData->gameData); +} + +//----------------------------------------------------------------------------- + +NetPacketJoinGameFailed::NetPacketJoinGameFailed() +: NetPacket(NET_TYPE_JOIN_GAME_FAILED, sizeof(NetPacketJoinGameFailedData), sizeof(NetPacketJoinGameFailedData)) +{ +} + +NetPacketJoinGameFailed::~NetPacketJoinGameFailed() +{ +} + +boost::shared_ptr +NetPacketJoinGameFailed::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketJoinGameFailed); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketJoinGameFailed::SetData(const NetPacketJoinGameFailed::Data &inData) +{ + NetPacketJoinGameFailedData *tmpData = (NetPacketJoinGameFailedData *)GetRawData(); + + switch (inData.failureCode) + { + // Join Game Errors. + case NTF_NET_JOIN_GAME_FULL : + tmpData->failureReason = htons(NET_JOIN_FAILED_GAME_FULL); + break; + case NTF_NET_JOIN_ALREADY_RUNNING : + tmpData->failureReason = htons(NET_JOIN_FAILED_GAME_ALREADY_RUNNING); + break; + case NTF_NET_JOIN_INVALID_PASSWORD : + tmpData->failureReason = htons(NET_JOIN_FAILED_INVALID_PASSWORD); + break; + default : + tmpData->failureReason = htons(NET_JOIN_FAILED_OTHER); + break; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketJoinGameFailed::GetData(NetPacketJoinGameFailed::Data &outData) const +{ + NetPacketJoinGameFailedData *tmpData = (NetPacketJoinGameFailedData *)GetRawData(); + + switch (ntohs(tmpData->failureReason)) + { + // Join Game Errors. + case NET_JOIN_FAILED_GAME_FULL : + outData.failureCode = NTF_NET_JOIN_GAME_FULL; + break; + case NET_JOIN_FAILED_GAME_ALREADY_RUNNING : + outData.failureCode = NTF_NET_JOIN_ALREADY_RUNNING; + break; + case NET_JOIN_FAILED_INVALID_PASSWORD : + outData.failureCode = NTF_NET_JOIN_INVALID_PASSWORD; + break; + default : + outData.failureCode = NTF_NET_INTERNAL; + break; + } +} + +const NetPacketJoinGameFailed * +NetPacketJoinGameFailed::ToNetPacketJoinGameFailed() const +{ + return this; +} + +void +NetPacketJoinGameFailed::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketPlayerJoined::NetPacketPlayerJoined() +: NetPacket(NET_TYPE_PLAYER_JOINED, sizeof(NetPacketPlayerJoinedData), sizeof(NetPacketPlayerJoinedData)) +{ +} + +NetPacketPlayerJoined::~NetPacketPlayerJoined() +{ +} + +boost::shared_ptr +NetPacketPlayerJoined::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayerJoined); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayerJoined::SetData(const NetPacketPlayerJoined::Data &inData) +{ + NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + tmpData->playerRights = htons(inData.prights); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayerJoined::GetData(NetPacketPlayerJoined::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); + outData.prights = static_cast(ntohs(tmpData->playerRights)); +} + +const NetPacketPlayerJoined * +NetPacketPlayerJoined::ToNetPacketPlayerJoined() const +{ + return this; +} + +void +NetPacketPlayerJoined::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketPlayerLeft::NetPacketPlayerLeft() +: NetPacket(NET_TYPE_PLAYER_LEFT, sizeof(NetPacketPlayerLeftData), sizeof(NetPacketPlayerLeftData)) +{ +} + +NetPacketPlayerLeft::~NetPacketPlayerLeft() +{ +} + +boost::shared_ptr +NetPacketPlayerLeft::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayerLeft); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayerLeft::SetData(const NetPacketPlayerLeft::Data &inData) +{ + NetPacketPlayerLeftData *tmpData = (NetPacketPlayerLeftData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayerLeft::GetData(NetPacketPlayerLeft::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketPlayerLeftData *tmpData = (NetPacketPlayerLeftData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketPlayerLeft * +NetPacketPlayerLeft::ToNetPacketPlayerLeft() const +{ + return this; +} + +void +NetPacketPlayerLeft::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + + +//----------------------------------------------------------------------------- + +NetPacketGameAdminChanged::NetPacketGameAdminChanged() +: NetPacket(NET_TYPE_GAME_ADMIN_CHANGED, sizeof(NetPacketGameAdminChangedData), sizeof(NetPacketGameAdminChangedData)) +{ +} + +NetPacketGameAdminChanged::~NetPacketGameAdminChanged() +{ +} + +boost::shared_ptr +NetPacketGameAdminChanged::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameAdminChanged); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameAdminChanged::SetData(const NetPacketGameAdminChanged::Data &inData) +{ + NetPacketGameAdminChangedData *tmpData = (NetPacketGameAdminChangedData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameAdminChanged::GetData(NetPacketGameAdminChanged::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameAdminChangedData *tmpData = (NetPacketGameAdminChangedData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketGameAdminChanged * +NetPacketGameAdminChanged::ToNetPacketGameAdminChanged() const +{ + return this; +} + +void +NetPacketGameAdminChanged::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketKickPlayer::NetPacketKickPlayer() +: NetPacket(NET_TYPE_KICK_PLAYER, sizeof(NetPacketKickPlayerData), sizeof(NetPacketKickPlayerData)) +{ +} + +NetPacketKickPlayer::~NetPacketKickPlayer() +{ +} + +boost::shared_ptr +NetPacketKickPlayer::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketKickPlayer); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketKickPlayer::SetData(const NetPacketKickPlayer::Data &inData) +{ + NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketKickPlayer::GetData(NetPacketKickPlayer::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketKickPlayer * +NetPacketKickPlayer::ToNetPacketKickPlayer() const +{ + return this; +} + +void +NetPacketKickPlayer::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketLeaveCurrentGame::NetPacketLeaveCurrentGame() +: NetPacket(NET_TYPE_LEAVE_CURRENT_GAME, sizeof(NetPacketLeaveCurrentGameData), sizeof(NetPacketLeaveCurrentGameData)) +{ +} + +NetPacketLeaveCurrentGame::~NetPacketLeaveCurrentGame() +{ +} + +boost::shared_ptr +NetPacketLeaveCurrentGame::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketLeaveCurrentGame); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +const NetPacketLeaveCurrentGame * +NetPacketLeaveCurrentGame::ToNetPacketLeaveCurrentGame() const +{ + return this; +} + +void +NetPacketLeaveCurrentGame::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketStartEvent::NetPacketStartEvent() +: NetPacket(NET_TYPE_START_EVENT, sizeof(NetPacketStartEventData), sizeof(NetPacketStartEventData)) +{ +} + +NetPacketStartEvent::~NetPacketStartEvent() +{ +} + +boost::shared_ptr +NetPacketStartEvent::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketStartEvent); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketStartEvent::SetData(const NetPacketStartEvent::Data &inData) +{ + NetPacketStartEventData *tmpData = (NetPacketStartEventData *)GetRawData(); + + // Set the data. + tmpData->startFlags = htons(inData.fillUpWithCpuPlayers ? NET_START_FLAG_FILL_WITH_CPU_PLAYERS : 0); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketStartEvent::GetData(NetPacketStartEvent::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketStartEventData *tmpData = (NetPacketStartEventData *)GetRawData(); + + outData.fillUpWithCpuPlayers = (ntohs(tmpData->startFlags) & NET_START_FLAG_FILL_WITH_CPU_PLAYERS); +} + +const NetPacketStartEvent * +NetPacketStartEvent::ToNetPacketStartEvent() const +{ + return this; +} + +void +NetPacketStartEvent::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketStartEventAck::NetPacketStartEventAck() +: NetPacket(NET_TYPE_START_EVENT_ACK, sizeof(NetPacketStartEventAckData), sizeof(NetPacketStartEventAckData)) +{ +} + +NetPacketStartEventAck::~NetPacketStartEventAck() +{ +} + +boost::shared_ptr +NetPacketStartEventAck::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketStartEventAck); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +const NetPacketStartEventAck * +NetPacketStartEventAck::ToNetPacketStartEventAck() const +{ + return this; +} + +void +NetPacketStartEventAck::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketGameStart::NetPacketGameStart() +: NetPacket(NET_TYPE_GAME_START, sizeof(NetPacketGameStartData), MAX_PACKET_SIZE) +{ +} + +NetPacketGameStart::~NetPacketGameStart() +{ +} + +boost::shared_ptr +NetPacketGameStart::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameStart); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameStart::SetData(const NetPacketGameStart::Data &inData) +{ + u_int16_t numPlayers = (u_int16_t)inData.playerSlots.size(); + + // Basic checking. + if (numPlayers < MIN_NUMBER_OF_PLAYERS || numPlayers > MAX_NUMBER_OF_PLAYERS || numPlayers != inData.startData.numberOfPlayers) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketGameStartData) + ADD_PADDING(numPlayers * sizeof(PlayerSlotData)))); + + NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData(); + + tmpData->startDealerPlayerId = htonl(inData.startData.startDealerPlayerId); + tmpData->numberOfPlayers = htons(numPlayers); + + PlayerSlotList::const_iterator i = inData.playerSlots.begin(); + PlayerSlotList::const_iterator end = inData.playerSlots.end(); + + // Copy the player slot data to continous memory + PlayerSlotData *curPlayerSlotData = + (PlayerSlotData *)((char *)tmpData + sizeof(NetPacketGameStartData)); + while (i != end) + { + curPlayerSlotData->playerId = htonl((*i).playerId); + ++curPlayerSlotData; + ++i; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameStart::GetData(NetPacketGameStart::Data &outData) const +{ + NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData(); + + outData.startData.startDealerPlayerId = ntohl(tmpData->startDealerPlayerId); + u_int16_t numPlayers = ntohs(tmpData->numberOfPlayers); + outData.startData.numberOfPlayers = numPlayers; + + PlayerSlotData *curPlayerSlotData = + (PlayerSlotData *)((char *)tmpData + sizeof(NetPacketGameStartData)); + + // Store all available player slots. + for (int i = 0; i < numPlayers; i++) + { + PlayerSlot tmpPlayerSlot; + tmpPlayerSlot.playerId = ntohl(curPlayerSlotData->playerId); + + outData.playerSlots.push_back(tmpPlayerSlot); + ++curPlayerSlotData; + } +} + +const NetPacketGameStart * +NetPacketGameStart::ToNetPacketGameStart() const +{ + return this; +} + +void +NetPacketGameStart::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketGameStartData *tmpData = (NetPacketGameStartData *)data; + int numPlayers = ntohs(tmpData->numberOfPlayers); + // Check exact packet size. + if (dataLen != + sizeof(NetPacketGameStartData) + + numPlayers * sizeof(PlayerSlotData)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Semantic checks not needed. +} + +//----------------------------------------------------------------------------- + +NetPacketHandStart::NetPacketHandStart() +: NetPacket(NET_TYPE_HAND_START, sizeof(NetPacketHandStartData), sizeof(NetPacketHandStartData)) +{ +} + +NetPacketHandStart::~NetPacketHandStart() +{ +} + +boost::shared_ptr +NetPacketHandStart::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketHandStart); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketHandStart::SetData(const NetPacketHandStart::Data &inData) +{ + NetPacketHandStartData *tmpData = (NetPacketHandStartData *)GetRawData(); + + tmpData->yourCard1 = htons(inData.yourCards[0]); + tmpData->yourCard2 = htons(inData.yourCards[1]); + tmpData->smallBlind = htonl(inData.smallBlind); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketHandStart::GetData(NetPacketHandStart::Data &outData) const +{ + NetPacketHandStartData *tmpData = (NetPacketHandStartData *)GetRawData(); + + outData.yourCards[0] = ntohs(tmpData->yourCard1); + outData.yourCards[1] = ntohs(tmpData->yourCard2); + outData.smallBlind = ntohl(tmpData->smallBlind); +} + +const NetPacketHandStart * +NetPacketHandStart::ToNetPacketHandStart() const +{ + return this; +} + +void +NetPacketHandStart::InternalCheck(const NetPacketHeader* data) const +{ + NetPacketHandStartData *tmpData = (NetPacketHandStartData *)data; + if (ntohs(tmpData->yourCard1) > 51 || ntohs(tmpData->yourCard2) > 51) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketPlayersTurn::NetPacketPlayersTurn() +: NetPacket(NET_TYPE_PLAYERS_TURN, sizeof(NetPacketPlayersTurnData), sizeof(NetPacketPlayersTurnData)) +{ +} + +NetPacketPlayersTurn::~NetPacketPlayersTurn() +{ +} + +boost::shared_ptr +NetPacketPlayersTurn::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayersTurn); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayersTurn::SetData(const NetPacketPlayersTurn::Data &inData) +{ + NetPacketPlayersTurnData *tmpData = (NetPacketPlayersTurnData *)GetRawData(); + + tmpData->playerId = htonl(inData.playerId); + tmpData->gameState = htons(inData.gameState); + tmpData->minimumRaise = htonl(inData.minimumRaise); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayersTurn::GetData(NetPacketPlayersTurn::Data &outData) const +{ + NetPacketPlayersTurnData *tmpData = (NetPacketPlayersTurnData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); + outData.gameState = static_cast(ntohs(tmpData->gameState)); + outData.minimumRaise = ntohl(tmpData->minimumRaise); +} + +const NetPacketPlayersTurn * +NetPacketPlayersTurn::ToNetPacketPlayersTurn() const +{ + return this; +} + +void +NetPacketPlayersTurn::InternalCheck(const NetPacketHeader* data) const +{ + // Check whether the state is valid. + NetPacketPlayersTurnData *tmpData = (NetPacketPlayersTurnData *)data; + if (ntohs(tmpData->gameState) > GAME_STATE_RIVER) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketPlayersAction::NetPacketPlayersAction() +: NetPacket(NET_TYPE_PLAYERS_ACTION, sizeof(NetPacketPlayersActionData), sizeof(NetPacketPlayersActionData)) +{ +} + +NetPacketPlayersAction::~NetPacketPlayersAction() +{ +} + +boost::shared_ptr +NetPacketPlayersAction::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayersAction); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayersAction::SetData(const NetPacketPlayersAction::Data &inData) +{ + NetPacketPlayersActionData *tmpData = (NetPacketPlayersActionData *)GetRawData(); + + tmpData->gameState = htons(inData.gameState); + tmpData->playerAction = htons(inData.playerAction); + tmpData->playerBet = htonl(inData.playerBet); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayersAction::GetData(NetPacketPlayersAction::Data &outData) const +{ + NetPacketPlayersActionData *tmpData = (NetPacketPlayersActionData *)GetRawData(); + + outData.gameState = static_cast(ntohs(tmpData->gameState)); + outData.playerAction = static_cast(ntohs(tmpData->playerAction)); + outData.playerBet = ntohl(tmpData->playerBet); +} + +const NetPacketPlayersAction * +NetPacketPlayersAction::ToNetPacketPlayersAction() const +{ + return this; +} + +void +NetPacketPlayersAction::InternalCheck(const NetPacketHeader* data) const +{ + NetPacketPlayersActionData *tmpData = (NetPacketPlayersActionData *)data; + // Check whether the state is valid. + if (ntohs(tmpData->gameState) > GAME_STATE_RIVER) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check whether the player action is valid. + if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Semantic checks are done by the server process. +} + +//----------------------------------------------------------------------------- + +NetPacketPlayersActionDone::NetPacketPlayersActionDone() +: NetPacket(NET_TYPE_PLAYERS_ACTION_DONE, sizeof(NetPacketPlayersActionDoneData), sizeof(NetPacketPlayersActionDoneData)) +{ +} + +NetPacketPlayersActionDone::~NetPacketPlayersActionDone() +{ +} + +boost::shared_ptr +NetPacketPlayersActionDone::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayersActionDone); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayersActionDone::SetData(const NetPacketPlayersActionDone::Data &inData) +{ + NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)GetRawData(); + + tmpData->playerId = htonl(inData.playerId); + tmpData->gameState = htons(inData.gameState); + tmpData->playerAction = htons(inData.playerAction); + tmpData->totalPlayerBet = htonl(inData.totalPlayerBet); + tmpData->playerMoney = htonl(inData.playerMoney); + tmpData->highestSet = htonl(inData.highestSet); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayersActionDone::GetData(NetPacketPlayersActionDone::Data &outData) const +{ + NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); + outData.gameState = static_cast(ntohs(tmpData->gameState)); + outData.playerAction = static_cast(ntohs(tmpData->playerAction)); + outData.totalPlayerBet = ntohl(tmpData->totalPlayerBet); + outData.playerMoney = ntohl(tmpData->playerMoney); + outData.highestSet = ntohl(tmpData->highestSet); +} + +const NetPacketPlayersActionDone * +NetPacketPlayersActionDone::ToNetPacketPlayersActionDone() const +{ + return this; +} + +void +NetPacketPlayersActionDone::InternalCheck(const NetPacketHeader* data) const +{ + NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)data; + // Check whether the state is valid. + int gameState = ntohs(tmpData->gameState); + if (gameState > GAME_STATE_RIVER + && gameState != GAME_STATE_PREFLOP_SMALL_BLIND + && gameState != GAME_STATE_PREFLOP_BIG_BLIND) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check whether the player action is valid. + if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketPlayersActionRejected::NetPacketPlayersActionRejected() +: NetPacket(NET_TYPE_PLAYERS_ACTION_REJECTED, sizeof(NetPacketPlayersActionRejectedData), sizeof(NetPacketPlayersActionRejectedData)) +{ +} + +NetPacketPlayersActionRejected::~NetPacketPlayersActionRejected() +{ +} + +boost::shared_ptr +NetPacketPlayersActionRejected::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayersActionRejected); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayersActionRejected::SetData(const NetPacketPlayersActionRejected::Data &inData) +{ + NetPacketPlayersActionRejectedData *tmpData = (NetPacketPlayersActionRejectedData *)GetRawData(); + + tmpData->gameState = htons(inData.gameState); + tmpData->playerAction = htons(inData.playerAction); + tmpData->playerBet = htonl(inData.playerBet); + tmpData->rejectionReason = htons(inData.rejectionReason); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketPlayersActionRejected::GetData(NetPacketPlayersActionRejected::Data &outData) const +{ + NetPacketPlayersActionRejectedData *tmpData = (NetPacketPlayersActionRejectedData *)GetRawData(); + + outData.gameState = static_cast(ntohs(tmpData->gameState)); + outData.playerAction = static_cast(ntohs(tmpData->playerAction)); + outData.playerBet = ntohl(tmpData->playerBet); + outData.rejectionReason = static_cast(ntohs(tmpData->rejectionReason)); +} + +const NetPacketPlayersActionRejected * +NetPacketPlayersActionRejected::ToNetPacketPlayersActionRejected() const +{ + return this; +} + +void +NetPacketPlayersActionRejected::InternalCheck(const NetPacketHeader* data) const +{ + // Check whether the state is valid. + NetPacketPlayersActionRejectedData *tmpData = (NetPacketPlayersActionRejectedData *)data; + if (ntohs(tmpData->gameState) > GAME_STATE_RIVER) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check whether the player action is valid. + if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + if (!ntohs(tmpData->rejectionReason)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketDealFlopCards::NetPacketDealFlopCards() +: NetPacket(NET_TYPE_DEAL_FLOP_CARDS, sizeof(NetPacketDealFlopCardsData), sizeof(NetPacketDealFlopCardsData)) +{ +} + +NetPacketDealFlopCards::~NetPacketDealFlopCards() +{ +} + +boost::shared_ptr +NetPacketDealFlopCards::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketDealFlopCards); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketDealFlopCards::SetData(const NetPacketDealFlopCards::Data &inData) +{ + NetPacketDealFlopCardsData *tmpData = (NetPacketDealFlopCardsData *)GetRawData(); + + tmpData->flopCard1 = htons(inData.flopCards[0]); + tmpData->flopCard2 = htons(inData.flopCards[1]); + tmpData->flopCard3 = htons(inData.flopCards[2]); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketDealFlopCards::GetData(NetPacketDealFlopCards::Data &outData) const +{ + NetPacketDealFlopCardsData *tmpData = (NetPacketDealFlopCardsData *)GetRawData(); + + outData.flopCards[0] = ntohs(tmpData->flopCard1); + outData.flopCards[1] = ntohs(tmpData->flopCard2); + outData.flopCards[2] = ntohs(tmpData->flopCard3); +} + +const NetPacketDealFlopCards * +NetPacketDealFlopCards::ToNetPacketDealFlopCards() const +{ + return this; +} + +void +NetPacketDealFlopCards::InternalCheck(const NetPacketHeader* data) const +{ + NetPacketDealFlopCardsData *tmpData = (NetPacketDealFlopCardsData *)data; + if (ntohs(tmpData->flopCard1) > 51 || ntohs(tmpData->flopCard2) > 51 || ntohs(tmpData->flopCard3) > 51) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketDealTurnCard::NetPacketDealTurnCard() +: NetPacket(NET_TYPE_DEAL_TURN_CARD, sizeof(NetPacketDealTurnCardData), sizeof(NetPacketDealTurnCardData)) +{ +} + +NetPacketDealTurnCard::~NetPacketDealTurnCard() +{ +} + +boost::shared_ptr +NetPacketDealTurnCard::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketDealTurnCard); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketDealTurnCard::SetData(const NetPacketDealTurnCard::Data &inData) +{ + NetPacketDealTurnCardData *tmpData = (NetPacketDealTurnCardData *)GetRawData(); + + tmpData->turnCard = htons(inData.turnCard); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketDealTurnCard::GetData(NetPacketDealTurnCard::Data &outData) const +{ + NetPacketDealTurnCardData *tmpData = (NetPacketDealTurnCardData *)GetRawData(); + + outData.turnCard = ntohs(tmpData->turnCard); +} + +const NetPacketDealTurnCard * +NetPacketDealTurnCard::ToNetPacketDealTurnCard() const +{ + return this; +} + +void +NetPacketDealTurnCard::InternalCheck(const NetPacketHeader* data) const +{ + NetPacketDealTurnCardData *tmpData = (NetPacketDealTurnCardData *)data; + if (ntohs(tmpData->turnCard) > 51) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketDealRiverCard::NetPacketDealRiverCard() +: NetPacket(NET_TYPE_DEAL_RIVER_CARD, sizeof(NetPacketDealRiverCardData), sizeof(NetPacketDealRiverCardData)) +{ +} + +NetPacketDealRiverCard::~NetPacketDealRiverCard() +{ +} + +boost::shared_ptr +NetPacketDealRiverCard::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketDealRiverCard); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketDealRiverCard::SetData(const NetPacketDealRiverCard::Data &inData) +{ + NetPacketDealRiverCardData *tmpData = (NetPacketDealRiverCardData *)GetRawData(); + + tmpData->riverCard = htons(inData.riverCard); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketDealRiverCard::GetData(NetPacketDealRiverCard::Data &outData) const +{ + NetPacketDealRiverCardData *tmpData = (NetPacketDealRiverCardData *)GetRawData(); + + outData.riverCard = ntohs(tmpData->riverCard); +} + +const NetPacketDealRiverCard * +NetPacketDealRiverCard::ToNetPacketDealRiverCard() const +{ + return this; +} + +void +NetPacketDealRiverCard::InternalCheck(const NetPacketHeader* data) const +{ + NetPacketDealRiverCardData *tmpData = (NetPacketDealRiverCardData *)data; + if (ntohs(tmpData->riverCard) > 51) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketAllInShowCards::NetPacketAllInShowCards() +: NetPacket(NET_TYPE_ALL_IN_SHOW_CARDS, sizeof(NetPacketAllInShowCardsData), MAX_PACKET_SIZE) +{ +} + +NetPacketAllInShowCards::~NetPacketAllInShowCards() +{ +} + +boost::shared_ptr +NetPacketAllInShowCards::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketAllInShowCards); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketAllInShowCards::SetData(const NetPacketAllInShowCards::Data &inData) +{ + u_int16_t numPlayerCards = (u_int16_t)inData.playerCards.size(); + + if (!numPlayerCards || numPlayerCards > MAX_NUM_PLAYER_CARDS) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_CARDS, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketAllInShowCardsData) + numPlayerCards * sizeof(PlayerCardsData))); + + NetPacketAllInShowCardsData *tmpData = (NetPacketAllInShowCardsData *)GetRawData(); + + tmpData->numberOfPlayerCards = htons(numPlayerCards); + + PlayerCardsList::const_iterator i = inData.playerCards.begin(); + PlayerCardsList::const_iterator end = inData.playerCards.end(); + + // Copy the player cards data to continous memory + PlayerCardsData *curPlayerCardsData = + (PlayerCardsData *)((char *)tmpData + sizeof(NetPacketAllInShowCardsData)); + while (i != end) + { + curPlayerCardsData->playerId = htonl((*i).playerId); + curPlayerCardsData->card1 = htons((*i).cards[0]); + curPlayerCardsData->card2 = htons((*i).cards[1]); + ++curPlayerCardsData; + ++i; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketAllInShowCards::GetData(NetPacketAllInShowCards::Data &outData) const +{ + NetPacketAllInShowCardsData *tmpData = (NetPacketAllInShowCardsData *)GetRawData(); + + outData.playerCards.clear(); + + u_int16_t numPlayerCards = ntohs(tmpData->numberOfPlayerCards); + PlayerCardsData *curPlayerCardsData = + (PlayerCardsData *)((char *)tmpData + sizeof(NetPacketAllInShowCardsData)); + + // Store all available player cards. + for (int i = 0; i < numPlayerCards; i++) + { + PlayerCards tmpPlayerCards; + tmpPlayerCards.playerId = ntohl(curPlayerCardsData->playerId); + tmpPlayerCards.cards[0] = ntohs(curPlayerCardsData->card1); + tmpPlayerCards.cards[1] = ntohs(curPlayerCardsData->card2); + + outData.playerCards.push_back(tmpPlayerCards); + ++curPlayerCardsData; + } +} + +const NetPacketAllInShowCards * +NetPacketAllInShowCards::ToNetPacketAllInShowCards() const +{ + return this; +} + +void +NetPacketAllInShowCards::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketAllInShowCardsData *tmpData = (NetPacketAllInShowCardsData *)data; + int numPlayerCards = ntohs(tmpData->numberOfPlayerCards); + + if (dataLen != + sizeof(NetPacketAllInShowCardsData) + + numPlayerCards * sizeof(PlayerCardsData)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + if (ntohs(tmpData->numberOfPlayerCards) > MAX_NUMBER_OF_PLAYERS) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Semantic checks not needed, this packet is sent by the server. +} + +//----------------------------------------------------------------------------- + +NetPacketEndOfHandShowCards::NetPacketEndOfHandShowCards() +: NetPacket(NET_TYPE_END_OF_HAND_SHOW_CARDS, sizeof(NetPacketEndOfHandShowCardsData), MAX_PACKET_SIZE) +{ +} + +NetPacketEndOfHandShowCards::~NetPacketEndOfHandShowCards() +{ +} + +boost::shared_ptr +NetPacketEndOfHandShowCards::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketEndOfHandShowCards); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketEndOfHandShowCards::SetData(const NetPacketEndOfHandShowCards::Data &inData) +{ + u_int16_t numPlayerResults = (u_int16_t)inData.playerResults.size(); + + if (!numPlayerResults || numPlayerResults > MAX_NUM_PLAYER_RESULTS) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_RESULTS, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketEndOfHandShowCardsData) + numPlayerResults * sizeof(PlayerResultData))); + + NetPacketEndOfHandShowCardsData *tmpData = (NetPacketEndOfHandShowCardsData *)GetRawData(); + + tmpData->numberOfPlayerResults = htons(numPlayerResults); + + PlayerResultList::const_iterator i = inData.playerResults.begin(); + PlayerResultList::const_iterator end = inData.playerResults.end(); + + // Copy the player result data to continous memory + PlayerResultData *curPlayerResultData = + (PlayerResultData *)((char *)tmpData + sizeof(NetPacketEndOfHandShowCardsData)); + while (i != end) + { + curPlayerResultData->playerId = htonl((*i).playerId); + curPlayerResultData->card1 = htons((*i).cards[0]); + curPlayerResultData->card2 = htons((*i).cards[1]); + curPlayerResultData->bestHandPos1 = htons((*i).bestHandPos[0]); + curPlayerResultData->bestHandPos2 = htons((*i).bestHandPos[1]); + curPlayerResultData->bestHandPos3 = htons((*i).bestHandPos[2]); + curPlayerResultData->bestHandPos4 = htons((*i).bestHandPos[3]); + curPlayerResultData->bestHandPos5 = htons((*i).bestHandPos[4]); + curPlayerResultData->valueOfCards = htonl((*i).valueOfCards); + curPlayerResultData->moneyWon = htonl((*i).moneyWon); + curPlayerResultData->playerMoney = htonl((*i).playerMoney); + ++curPlayerResultData; + ++i; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketEndOfHandShowCards::GetData(NetPacketEndOfHandShowCards::Data &outData) const +{ + NetPacketEndOfHandShowCardsData *tmpData = (NetPacketEndOfHandShowCardsData *)GetRawData(); + + outData.playerResults.clear(); + + u_int16_t numPlayerResults = ntohs(tmpData->numberOfPlayerResults); + PlayerResultData *curPlayerResultData = + (PlayerResultData *)((char *)tmpData + sizeof(NetPacketEndOfHandShowCardsData)); + + // Store all available player results. + for (int i = 0; i < numPlayerResults; i++) + { + PlayerResult tmpPlayerResult; + tmpPlayerResult.playerId = ntohl(curPlayerResultData->playerId); + tmpPlayerResult.cards[0] = ntohs(curPlayerResultData->card1); + tmpPlayerResult.cards[1] = ntohs(curPlayerResultData->card2); + tmpPlayerResult.bestHandPos[0] = ntohs(curPlayerResultData->bestHandPos1); + tmpPlayerResult.bestHandPos[1] = ntohs(curPlayerResultData->bestHandPos2); + tmpPlayerResult.bestHandPos[2] = ntohs(curPlayerResultData->bestHandPos3); + tmpPlayerResult.bestHandPos[3] = ntohs(curPlayerResultData->bestHandPos4); + tmpPlayerResult.bestHandPos[4] = ntohs(curPlayerResultData->bestHandPos5); + tmpPlayerResult.valueOfCards = ntohl(curPlayerResultData->valueOfCards); + tmpPlayerResult.moneyWon = ntohl(curPlayerResultData->moneyWon); + tmpPlayerResult.playerMoney = ntohl(curPlayerResultData->playerMoney); + + outData.playerResults.push_back(tmpPlayerResult); + ++curPlayerResultData; + } +} + +const NetPacketEndOfHandShowCards * +NetPacketEndOfHandShowCards::ToNetPacketEndOfHandShowCards() const +{ + return this; +} + +void +NetPacketEndOfHandShowCards::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketEndOfHandShowCardsData *tmpData = (NetPacketEndOfHandShowCardsData *)data; + int numPlayerResults = ntohs(tmpData->numberOfPlayerResults); + + if (dataLen != + sizeof(NetPacketEndOfHandShowCardsData) + + numPlayerResults * sizeof(PlayerResultData)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + if (ntohs(tmpData->numberOfPlayerResults) > MAX_NUMBER_OF_PLAYERS) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Semantic checks not needed, this packet is sent by the server. +} + +//----------------------------------------------------------------------------- + +NetPacketEndOfHandHideCards::NetPacketEndOfHandHideCards() +: NetPacket(NET_TYPE_END_OF_HAND_HIDE_CARDS, sizeof(NetPacketEndOfHandHideCardsData), sizeof(NetPacketEndOfHandHideCardsData)) +{ +} + +NetPacketEndOfHandHideCards::~NetPacketEndOfHandHideCards() +{ +} + +boost::shared_ptr +NetPacketEndOfHandHideCards::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketEndOfHandHideCards); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketEndOfHandHideCards::SetData(const NetPacketEndOfHandHideCards::Data &inData) +{ + NetPacketEndOfHandHideCardsData *tmpData = (NetPacketEndOfHandHideCardsData *)GetRawData(); + + tmpData->playerId = htonl(inData.playerId); + tmpData->moneyWon = htonl(inData.moneyWon); + tmpData->playerMoney = htonl(inData.playerMoney); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketEndOfHandHideCards::GetData(NetPacketEndOfHandHideCards::Data &outData) const +{ + NetPacketEndOfHandHideCardsData *tmpData = (NetPacketEndOfHandHideCardsData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); + outData.moneyWon = ntohl(tmpData->moneyWon); + outData.playerMoney = ntohl(tmpData->playerMoney); +} + +const NetPacketEndOfHandHideCards * +NetPacketEndOfHandHideCards::ToNetPacketEndOfHandHideCards() const +{ + return this; +} + +void +NetPacketEndOfHandHideCards::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketEndOfGame::NetPacketEndOfGame() +: NetPacket(NET_TYPE_END_OF_GAME, sizeof(NetPacketEndOfGameData), sizeof(NetPacketEndOfGameData)) +{ +} + +NetPacketEndOfGame::~NetPacketEndOfGame() +{ +} + +boost::shared_ptr +NetPacketEndOfGame::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketEndOfGame); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketEndOfGame::SetData(const NetPacketEndOfGame::Data &inData) +{ + NetPacketEndOfGameData *tmpData = (NetPacketEndOfGameData *)GetRawData(); + + tmpData->winnerPlayerId = htonl(inData.winnerPlayerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketEndOfGame::GetData(NetPacketEndOfGame::Data &outData) const +{ + NetPacketEndOfGameData *tmpData = (NetPacketEndOfGameData *)GetRawData(); + + outData.winnerPlayerId = ntohl(tmpData->winnerPlayerId); +} + +const NetPacketEndOfGame * +NetPacketEndOfGame::ToNetPacketEndOfGame() const +{ + return this; +} + +void +NetPacketEndOfGame::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketStatisticsChanged::NetPacketStatisticsChanged() +: NetPacket(NET_TYPE_STATISTICS_CHANGED, sizeof(NetPacketStatisticsChangedData), MAX_PACKET_SIZE) +{ +} + +NetPacketStatisticsChanged::~NetPacketStatisticsChanged() +{ +} + +boost::shared_ptr +NetPacketStatisticsChanged::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketStatisticsChanged); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketStatisticsChanged::SetData(const NetPacketStatisticsChanged::Data &inData) +{ + u_int16_t numValues = 0; + if (inData.stats.numberOfPlayersOnServer) + ++numValues; + if (inData.stats.totalPlayersEverLoggedIn) + ++numValues; + if (inData.stats.totalGamesEverCreated) + ++numValues; + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketStatisticsChangedData) + numValues * sizeof(StatisticsData))); + + NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)GetRawData(); + + tmpData->numberOfStatistics = htons(numValues); + + StatisticsData *curStatisticsData = + (StatisticsData *)((char *)tmpData + sizeof(NetPacketStatisticsChangedData)); + + if (inData.stats.numberOfPlayersOnServer) + { + curStatisticsData->statisticsType = htonl(NET_STAT_CUR_PLAYERS_ON_SERVER); + curStatisticsData->statisticsValue = htonl(inData.stats.numberOfPlayersOnServer); + ++curStatisticsData; + } + if (inData.stats.totalPlayersEverLoggedIn) + { + curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER); + curStatisticsData->statisticsValue = htonl(inData.stats.totalPlayersEverLoggedIn); + ++curStatisticsData; + } + if (inData.stats.totalGamesEverCreated) + { + curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_GAMES_EVER_ON_SERVER); + curStatisticsData->statisticsValue = htonl(inData.stats.totalGamesEverCreated); + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketStatisticsChanged::GetData(NetPacketStatisticsChanged::Data &outData) const +{ + NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)GetRawData(); + + u_int16_t numStatistics = ntohs(tmpData->numberOfStatistics); + StatisticsData *curStatisticsData = + (StatisticsData *)((char *)tmpData + sizeof(NetPacketStatisticsChangedData)); + + for (int i = 0; i < numStatistics; i++) + { + switch(ntohl(curStatisticsData->statisticsType)) + { + case NET_STAT_CUR_PLAYERS_ON_SERVER: + outData.stats.numberOfPlayersOnServer = ntohl(curStatisticsData->statisticsValue); + break; + case NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER: + outData.stats.totalPlayersEverLoggedIn = ntohl(curStatisticsData->statisticsValue); + break; + case NET_STAT_TOTAL_GAMES_EVER_ON_SERVER: + outData.stats.totalGamesEverCreated = ntohl(curStatisticsData->statisticsValue); + break; + } + } +} + +const NetPacketStatisticsChanged * +NetPacketStatisticsChanged::ToNetPacketStatisticsChanged() const +{ + return this; +} + +void +NetPacketStatisticsChanged::InternalCheck(const NetPacketHeader *data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)data; + int numStatistics = ntohs(tmpData->numberOfStatistics); + + if (dataLen != + sizeof(NetPacketStatisticsChangedData) + + numStatistics * sizeof(StatisticsData)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + if (!numStatistics) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Semantic checks not needed, this packet is sent by the server. +} + +//----------------------------------------------------------------------------- + +NetPacketRemovedFromGame::NetPacketRemovedFromGame() +: NetPacket(NET_TYPE_REMOVED_FROM_GAME, sizeof(NetPacketRemovedFromGameData), sizeof(NetPacketRemovedFromGameData)) +{ +} + +NetPacketRemovedFromGame::~NetPacketRemovedFromGame() +{ +} + +boost::shared_ptr +NetPacketRemovedFromGame::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketRemovedFromGame); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketRemovedFromGame::SetData(const NetPacketRemovedFromGame::Data &inData) +{ + NetPacketRemovedFromGameData *tmpData = (NetPacketRemovedFromGameData *)GetRawData(); + + switch (inData.removeReason) + { + case NTF_NET_REMOVED_ON_REQUEST : + tmpData->removeReason = htons(NET_REMOVED_ON_REQUEST); + break; + case NTF_NET_REMOVED_GAME_FULL : + tmpData->removeReason = htons(NET_REMOVED_GAME_FULL); + break; + case NTF_NET_REMOVED_ALREADY_RUNNING : + tmpData->removeReason = htons(NET_REMOVED_GAME_ALREADY_RUNNING); + break; + case NTF_NET_REMOVED_KICKED : + tmpData->removeReason = htons(NET_REMOVED_KICKED); + break; + default : + tmpData->removeReason = htons(NET_REMOVED_OTHER_REASON); + break; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketRemovedFromGame::GetData(NetPacketRemovedFromGame::Data &outData) const +{ + NetPacketRemovedFromGameData *tmpData = (NetPacketRemovedFromGameData *)GetRawData(); + + switch (ntohs(tmpData->removeReason)) + { + // Removed Errors. + case NET_REMOVED_ON_REQUEST : + outData.removeReason = NTF_NET_REMOVED_ON_REQUEST; + break; + case NET_REMOVED_GAME_FULL : + outData.removeReason = NTF_NET_REMOVED_GAME_FULL; + break; + case NET_REMOVED_GAME_ALREADY_RUNNING : + outData.removeReason = NTF_NET_REMOVED_ALREADY_RUNNING; + break; + case NET_REMOVED_KICKED : + outData.removeReason = NTF_NET_REMOVED_KICKED; + break; + default : + outData.removeReason = NTF_NET_INTERNAL; + break; + } +} + +const NetPacketRemovedFromGame * +NetPacketRemovedFromGame::ToNetPacketRemovedFromGame() const +{ + return this; +} + +void +NetPacketRemovedFromGame::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketSendChatText::NetPacketSendChatText() +: NetPacket(NET_TYPE_SEND_CHAT_TEXT, sizeof(NetPacketSendChatTextData), MAX_PACKET_SIZE) +{ +} + +NetPacketSendChatText::~NetPacketSendChatText() +{ +} + +boost::shared_ptr +NetPacketSendChatText::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketSendChatText); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketSendChatText::SetData(const NetPacketSendChatText::Data &inData) +{ + u_int16_t textLen = (u_int16_t)inData.text.length(); + + if (!textLen || textLen > MAX_CHAT_TEXT_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_CHAT_TEXT, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketSendChatTextData) + ADD_PADDING(textLen))); + + NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)GetRawData(); + + // Set the data. + tmpData->textLength = htons(textLen); + char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData); + memcpy(textPtr, inData.text.c_str(), textLen); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketSendChatText::GetData(NetPacketSendChatText::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)GetRawData(); + + char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData); + outData.text = string(textPtr, ntohs(tmpData->textLength)); +} + +const NetPacketSendChatText * +NetPacketSendChatText::ToNetPacketSendChatText() const +{ + return this; +} + +void +NetPacketSendChatText::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketSendChatTextData *tmpData = (NetPacketSendChatTextData *)data; + int textLength = ntohs(tmpData->textLength); + // Check exact packet length. + if (dataLen != + sizeof(NetPacketSendChatTextData) + + ADD_PADDING(textLength)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string size. + if (!textLength + || textLength > MAX_CHAT_TEXT_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check text string. + char *textPtr = (char *)tmpData + sizeof(NetPacketSendChatTextData); + if (textPtr[0] == 0) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + +NetPacketChatText::NetPacketChatText() +: NetPacket(NET_TYPE_CHAT_TEXT, sizeof(NetPacketChatTextData), MAX_PACKET_SIZE) +{ +} + +NetPacketChatText::~NetPacketChatText() +{ +} + +boost::shared_ptr +NetPacketChatText::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketChatText); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketChatText::SetData(const NetPacketChatText::Data &inData) +{ + u_int16_t textLen = (u_int16_t)inData.text.length(); + + if (!textLen || textLen > MAX_CHAT_TEXT_SIZE) + throw NetException(__FILE__, __LINE__, ERR_NET_INVALID_CHAT_TEXT, 0); + + // Resize the packet so that the data fits in. + Resize((u_int16_t) + (sizeof(NetPacketChatTextData) + ADD_PADDING(textLen))); + + NetPacketChatTextData *tmpData = (NetPacketChatTextData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + tmpData->textLength = htons(textLen); + char *textPtr = (char *)tmpData + sizeof(NetPacketChatTextData); + memcpy(textPtr, inData.text.c_str(), textLen); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketChatText::GetData(NetPacketChatText::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketChatTextData *tmpData = (NetPacketChatTextData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); + char *textPtr = (char *)tmpData + sizeof(NetPacketChatTextData); + outData.text = string(textPtr, ntohs(tmpData->textLength)); +} + +const NetPacketChatText * +NetPacketChatText::ToNetPacketChatText() const +{ + return this; +} + +void +NetPacketChatText::InternalCheck(const NetPacketHeader* data) const +{ + u_int16_t dataLen = ntohs(data->length); + NetPacketChatTextData *tmpData = (NetPacketChatTextData *)data; + int textLength = ntohs(tmpData->textLength); + // Check exact packet length. + if (dataLen != + sizeof(NetPacketChatTextData) + + ADD_PADDING(textLength)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // Check string size. + if (!textLength + || textLength > MAX_CHAT_TEXT_SIZE) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0); + } + // No more checks required - this packet is sent by the server. +} + +//----------------------------------------------------------------------------- + +NetPacketError::NetPacketError() +: NetPacket(NET_TYPE_ERROR, sizeof(NetPacketErrorData), sizeof(NetPacketErrorData)) +{ +} + +NetPacketError::~NetPacketError() +{ +} + +boost::shared_ptr +NetPacketError::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketError); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketError::SetData(const NetPacketError::Data &inData) +{ + NetPacketErrorData *tmpData = (NetPacketErrorData *)GetRawData(); + + switch (inData.errorCode) + { + // Init Errors. + case ERR_NET_VERSION_NOT_SUPPORTED : + tmpData->errorReason = htons(NET_ERR_INIT_VERSION_NOT_SUPPORTED); + break; + case ERR_NET_SERVER_FULL : + tmpData->errorReason = htons(NET_ERR_INIT_SERVER_FULL); + break; + case ERR_NET_INVALID_PASSWORD : + tmpData->errorReason = htons(NET_ERR_INIT_INVALID_PASSWORD); + break; + case ERR_NET_PLAYER_NAME_IN_USE : + tmpData->errorReason = htons(NET_ERR_INIT_PLAYER_NAME_IN_USE); + break; + case ERR_NET_INVALID_PLAYER_NAME : + tmpData->errorReason = htons(NET_ERR_INIT_INVALID_PLAYER_NAME); + break; + case ERR_NET_SERVER_MAINTENANCE : + tmpData->errorReason = htons(NET_ERR_INIT_SERVER_MAINTENANCE); + break; + case ERR_NET_AVATAR_TOO_LARGE : + tmpData->errorReason = htons(NET_ERR_AVATAR_TOO_LARGE); + break; + case ERR_NET_WRONG_AVATAR_SIZE : + tmpData->errorReason = htons(NET_ERR_AVATAR_WRONG_SIZE); + break; + case ERR_NET_UNKNOWN_GAME : + tmpData->errorReason = htons(NET_ERR_JOIN_GAME_UNKNOWN_GAME); + break; + + // General Errors. + case ERR_SOCK_INVALID_PACKET : + tmpData->errorReason = htons(NET_ERR_GENERAL_INVALID_PACKET); + break; + case ERR_SOCK_INVALID_STATE : + tmpData->errorReason = htons(NET_ERR_GENERAL_INVALID_STATE); + break; + case ERR_NET_PLAYER_KICKED : + tmpData->errorReason = htons(NET_ERR_GENERAL_PLAYER_KICKED); + break; + default : + tmpData->errorReason = htons(NET_ERR_OTHER); + break; + } + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketError::GetData(NetPacketError::Data &outData) const +{ + NetPacketErrorData *tmpData = (NetPacketErrorData *)GetRawData(); + + switch (ntohs(tmpData->errorReason)) + { + // Init Errors. + case NET_ERR_INIT_VERSION_NOT_SUPPORTED : + outData.errorCode = ERR_NET_VERSION_NOT_SUPPORTED; + break; + case NET_ERR_INIT_SERVER_FULL : + outData.errorCode = ERR_NET_SERVER_FULL; + break; + case NET_ERR_INIT_INVALID_PASSWORD : + outData.errorCode = ERR_NET_INVALID_PASSWORD; + break; + case NET_ERR_INIT_PLAYER_NAME_IN_USE : + outData.errorCode = ERR_NET_PLAYER_NAME_IN_USE; + break; + case NET_ERR_INIT_INVALID_PLAYER_NAME : + outData.errorCode = ERR_NET_INVALID_PLAYER_NAME; + break; + case NET_ERR_INIT_SERVER_MAINTENANCE : + outData.errorCode = ERR_NET_SERVER_MAINTENANCE; + break; + case NET_ERR_AVATAR_TOO_LARGE : + outData.errorCode = ERR_NET_AVATAR_TOO_LARGE; + break; + case NET_ERR_AVATAR_WRONG_SIZE : + outData.errorCode = ERR_NET_WRONG_AVATAR_SIZE; + break; + case NET_ERR_JOIN_GAME_UNKNOWN_GAME : + outData.errorCode = ERR_NET_UNKNOWN_GAME; + break; + + // General Errors. + case NET_ERR_GENERAL_INVALID_PACKET : + outData.errorCode = ERR_SOCK_INVALID_PACKET; + break; + 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; + } +} + +const NetPacketError * +NetPacketError::ToNetPacketError() const +{ + return this; +} + +void +NetPacketError::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + diff --git a/src/net/common/receiverhelper.cpp b/src/net/common/receiverhelper.cpp index ffe4a928..14e91f61 100644 --- a/src/net/common/receiverhelper.cpp +++ b/src/net/common/receiverhelper.cpp @@ -1,123 +1,123 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifdef _WIN32 - #define FD_SETSIZE 512 -#endif - -#include -#include -#include -#include - -using namespace std; - - -ReceiverHelper::ReceiverHelper() -{ -} - -ReceiverHelper::~ReceiverHelper() -{ -} - -boost::shared_ptr -ReceiverHelper::Recv(SOCKET sock, ReceiveBuffer &buf) -{ - if (buf.receivedPackets.empty()) - { - int bufSize = RECV_BUF_SIZE - buf.recvBufUsed; - - if (bufSize > 0) // check if there is room in the input buffer - { - fd_set readSet; - struct timeval timeout; - - FD_ZERO(&readSet); - FD_SET(sock, &readSet); - - timeout.tv_sec = 0; - timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000; - int selectResult = select(sock + 1, &readSet, NULL, NULL, &timeout); - if (!IS_VALID_SELECT(selectResult)) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); - } - if (selectResult > 0) // recv is possible - { - int bytesRecvd = recv(sock, buf.recvBuf + buf.recvBufUsed, bufSize, 0); - - if (!IS_VALID_RECV(bytesRecvd)) - { - int errCode = SOCKET_ERRNO(); - if (!IS_SOCKET_ERR_WOULDBLOCK(errCode)) - throw NetException(__FILE__, __LINE__, ERR_SOCK_RECV_FAILED, SOCKET_ERRNO()); - } - else if (bytesRecvd == 0) - { - throw NetException(__FILE__, __LINE__, ERR_SOCK_CONN_RESET, 0); - } - else - { - buf.recvBufUsed += bytesRecvd; - InternalGetPackets(buf); - } - } - } - } - boost::shared_ptr tmpPacket; - if (!buf.receivedPackets.empty()) - { - tmpPacket = buf.receivedPackets.front(); - buf.receivedPackets.pop_front(); - } - return tmpPacket; -} - -void -ReceiverHelper::InternalGetPackets(ReceiveBuffer &buf) -{ - bool dataAvailable = true; - do - { - boost::shared_ptr tmpPacket; - // This is necessary, because we use TCP. - // Packets may be received in multiple chunks or - // several packets may be received at once. - if (buf.recvBufUsed >= MIN_PACKET_SIZE) - { - try - { - // This call will also handle the memmove stuff, i.e. - // buffering for partial packets. - tmpPacket = NetPacket::Create(buf.recvBuf, buf.recvBufUsed); - } catch (const NetException &) - { - // Reset buffer on error. - buf.recvBufUsed = 0; - // TODO: log error/increase error counter. - } - } - if (tmpPacket.get()) - buf.receivedPackets.push_back(tmpPacket); - else - dataAvailable = false; - } while(dataAvailable); -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifdef _WIN32 + #define FD_SETSIZE 512 +#endif + +#include +#include +#include +#include + +using namespace std; + + +ReceiverHelper::ReceiverHelper() +{ +} + +ReceiverHelper::~ReceiverHelper() +{ +} + +boost::shared_ptr +ReceiverHelper::Recv(SOCKET sock, ReceiveBuffer &buf) +{ + if (buf.receivedPackets.empty()) + { + int bufSize = RECV_BUF_SIZE - buf.recvBufUsed; + + if (bufSize > 0) // check if there is room in the input buffer + { + fd_set readSet; + struct timeval timeout; + + FD_ZERO(&readSet); + FD_SET(sock, &readSet); + + timeout.tv_sec = 0; + timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000; + int selectResult = select(sock + 1, &readSet, NULL, NULL, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); + } + if (selectResult > 0) // recv is possible + { + int bytesRecvd = recv(sock, buf.recvBuf + buf.recvBufUsed, bufSize, 0); + + if (!IS_VALID_RECV(bytesRecvd)) + { + int errCode = SOCKET_ERRNO(); + if (!IS_SOCKET_ERR_WOULDBLOCK(errCode)) + throw NetException(__FILE__, __LINE__, ERR_SOCK_RECV_FAILED, SOCKET_ERRNO()); + } + else if (bytesRecvd == 0) + { + throw NetException(__FILE__, __LINE__, ERR_SOCK_CONN_RESET, 0); + } + else + { + buf.recvBufUsed += bytesRecvd; + InternalGetPackets(buf); + } + } + } + } + boost::shared_ptr tmpPacket; + if (!buf.receivedPackets.empty()) + { + tmpPacket = buf.receivedPackets.front(); + buf.receivedPackets.pop_front(); + } + return tmpPacket; +} + +void +ReceiverHelper::InternalGetPackets(ReceiveBuffer &buf) +{ + bool dataAvailable = true; + do + { + boost::shared_ptr tmpPacket; + // This is necessary, because we use TCP. + // Packets may be received in multiple chunks or + // several packets may be received at once. + if (buf.recvBufUsed >= MIN_PACKET_SIZE) + { + try + { + // This call will also handle the memmove stuff, i.e. + // buffering for partial packets. + tmpPacket = NetPacket::Create(buf.recvBuf, buf.recvBufUsed); + } catch (const NetException &) + { + // Reset buffer on error. + buf.recvBufUsed = 0; + // TODO: log error/increase error counter. + } + } + if (tmpPacket.get()) + buf.receivedPackets.push_back(tmpPacket); + else + dataAvailable = false; + } while(dataAvailable); +} + diff --git a/src/net/common/resolverthread.cpp b/src/net/common/resolverthread.cpp index 12d4cfe9..a19e78c3 100644 --- a/src/net/common/resolverthread.cpp +++ b/src/net/common/resolverthread.cpp @@ -1,96 +1,96 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include - -#include -#include - -using namespace std; - - -ResolverThread::ResolverThread() -: m_retVal(false) -{ - m_context.reset(new ClientContext); -} - -ResolverThread::~ResolverThread() -{ -} - -void -ResolverThread::Init(const ClientContext &context) -{ - if (IsRunning()) - return; // TODO: throw exception - - GetContext().SetAddrFamily(context.GetAddrFamily()); - GetContext().SetServerAddr(context.GetServerAddr()); - GetContext().SetServerPort(context.GetServerPort()); -} - -bool -ResolverThread::GetResult(ClientContext &context) const -{ - if (IsRunning()) - return false; // TODO: throw exception - - if (m_retVal) - memcpy(context.GetClientSockaddr(), GetContext().GetClientSockaddr(), GetContext().GetClientSockaddrSize()); - - return m_retVal; -} - -void -ResolverThread::Main() -{ - const ClientContext &context = GetContext(); - - // Convert the port to a string. - ostringstream tmpStr; - tmpStr << context.GetServerPort(); - - // Start the name resolution. - m_retVal = socket_resolve( - context.GetServerAddr().c_str(), - tmpStr.str().c_str(), - context.GetAddrFamily(), - SOCK_STREAM, - context.GetProtocol(), - (struct sockaddr *)context.GetClientSockaddr(), - context.GetClientSockaddrSize()); -} - -const ClientContext & -ResolverThread::GetContext() const -{ - assert(m_context.get()); - return *m_context; -} - -ClientContext & -ResolverThread::GetContext() -{ - assert(m_context.get()); - return *m_context; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include +#include + +using namespace std; + + +ResolverThread::ResolverThread() +: m_retVal(false) +{ + m_context.reset(new ClientContext); +} + +ResolverThread::~ResolverThread() +{ +} + +void +ResolverThread::Init(const ClientContext &context) +{ + if (IsRunning()) + return; // TODO: throw exception + + GetContext().SetAddrFamily(context.GetAddrFamily()); + GetContext().SetServerAddr(context.GetServerAddr()); + GetContext().SetServerPort(context.GetServerPort()); +} + +bool +ResolverThread::GetResult(ClientContext &context) const +{ + if (IsRunning()) + return false; // TODO: throw exception + + if (m_retVal) + memcpy(context.GetClientSockaddr(), GetContext().GetClientSockaddr(), GetContext().GetClientSockaddrSize()); + + return m_retVal; +} + +void +ResolverThread::Main() +{ + const ClientContext &context = GetContext(); + + // Convert the port to a string. + ostringstream tmpStr; + tmpStr << context.GetServerPort(); + + // Start the name resolution. + m_retVal = socket_resolve( + context.GetServerAddr().c_str(), + tmpStr.str().c_str(), + context.GetAddrFamily(), + SOCK_STREAM, + context.GetProtocol(), + (struct sockaddr *)context.GetClientSockaddr(), + context.GetClientSockaddrSize()); +} + +const ClientContext & +ResolverThread::GetContext() const +{ + assert(m_context.get()); + return *m_context; +} + +ClientContext & +ResolverThread::GetContext() +{ + assert(m_context.get()); + return *m_context; +} + diff --git a/src/net/common/sendercallback.cpp b/src/net/common/sendercallback.cpp index e6f451b6..54193c66 100644 --- a/src/net/common/sendercallback.cpp +++ b/src/net/common/sendercallback.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -SenderCallback::~SenderCallback() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +SenderCallback::~SenderCallback() +{ +} + diff --git a/src/net/common/senderthread.cpp b/src/net/common/senderthread.cpp index 6afb3b1a..5344a039 100644 --- a/src/net/common/senderthread.cpp +++ b/src/net/common/senderthread.cpp @@ -1,280 +1,280 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace std; - -#define SEND_ERROR_TIMEOUT_MSEC 20000 -#define SEND_TIMEOUT_MSEC 10 -#ifdef POKERTH_DEDICATED_SERVER - #define SEND_QUEUE_SIZE 10000 - #define SEND_LOW_PRIO_QUEUE_SIZE 10000000 -#else - #define SEND_QUEUE_SIZE 1000 - #define SEND_LOW_PRIO_QUEUE_SIZE 10000 -#endif - -SenderThread::SenderThread(SenderCallback &cb) -: m_tmpOutBufSize(0), m_lastInvalidSessionId(INVALID_SESSION), m_callback(cb) -{ -} - -SenderThread::~SenderThread() -{ -} - -void -SenderThread::Send(boost::shared_ptr session, boost::shared_ptr packet) -{ - if (packet.get() && session.get()) - { - boost::mutex::scoped_lock lock(m_outBufMutex); - InternalStore(m_outBuf, SEND_QUEUE_SIZE, session, packet); - } -} - -void -SenderThread::Send(boost::shared_ptr session, const NetPacketList &packetList) -{ - if (!packetList.empty() && session.get()) - { - boost::mutex::scoped_lock lock(m_outBufMutex); - InternalStore(m_outBuf, SEND_QUEUE_SIZE, session, packetList); - } -} - -void -SenderThread::SendLowPrio(boost::shared_ptr session, boost::shared_ptr packet) -{ - if (packet.get() && session.get()) - { - boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); - InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, session, packet); - } -} - -void -SenderThread::SendLowPrio(boost::shared_ptr session, const NetPacketList &packetList) -{ - if (!packetList.empty() && session.get()) - { - boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); - InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, session, packetList); - } -} - -unsigned -SenderThread::GetNumPacketsInQueue() const -{ - unsigned numPackets; - { - boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); - numPackets = m_lowPrioOutBuf.size(); - } - { - boost::mutex::scoped_lock lock(m_outBufMutex); - numPackets += m_outBuf.size(); - } - return numPackets; -} - -bool -SenderThread::operator<(const SenderThread &other) const -{ - return GetNumPacketsInQueue() < other.GetNumPacketsInQueue(); -} - -void -SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, boost::shared_ptr packet) -{ - if (sendQueue.size() < maxQueueSize) // Queue is limited in size. - sendQueue.push_back(std::make_pair(packet, session)); - // TODO: Throw exception if failed. -} - -void -SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, const NetPacketList &packetList) -{ - if (sendQueue.size() + packetList.size() < maxQueueSize) - { - NetPacketList::const_iterator i = packetList.begin(); - NetPacketList::const_iterator end = packetList.end(); - while (i != end) - { - sendQueue.push_back(std::make_pair(*i, session)); - ++i; - } - } - // TODO: Throw exception if failed. -} - -void -SenderThread::RemoveCurSendData() -{ - m_tmpOutBufSize = 0; - m_curSession.reset(); - // TODO use callback to remove session. -} - -void -SenderThread::Main() -{ - boost::timers::portable::microsec_timer sendTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start); - - while (!ShouldTerminate()) - { - // Send remaining bytes of output buffer OR - // copy ONE packet to output buffer. - // For reasons of simplicity, only one packet is sent at a time. - if (!m_tmpOutBufSize) - { - bool isLowPrio = false; - SendData tmpData; - // Check main queue first. - { - boost::mutex::scoped_lock lock(m_outBufMutex); - if (!m_outBuf.empty()) - { - tmpData = m_outBuf.front(); - m_outBuf.pop_front(); - } - } - - // Check low prio queue only if there is nothing in the main queue. - if (!tmpData.first.get()) - { - boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); - if (!m_lowPrioOutBuf.empty()) - { - tmpData = m_lowPrioOutBuf.front(); - m_lowPrioOutBuf.pop_front(); - isLowPrio = true; - } - } - - if (tmpData.first.get() && tmpData.second.get()) - { - if (!isLowPrio || tmpData.second->GetId() != m_lastInvalidSessionId) - { - u_int16_t tmpLen = tmpData.first->GetLen(); - if (tmpLen <= MAX_PACKET_SIZE) - { - m_curSession = tmpData.second; - m_tmpOutBufSize = tmpLen; - memcpy(m_tmpOutBuf, tmpData.first->GetRawData(), tmpLen); - sendTimer.restart(); - } - } - } - } - if (m_tmpOutBufSize) - { - SOCKET tmpSocket = m_curSession->GetSocket(); - - // send next chunk of data - int bytesSent = send(tmpSocket, m_tmpOutBuf, m_tmpOutBufSize, SOCKET_SEND_FLAGS); - - if (!IS_VALID_SEND(bytesSent)) - { - // Never assume that this is a fatal error. - int errCode = SOCKET_ERRNO(); - if (IS_SOCKET_ERR_WOULDBLOCK(errCode)) - { - fd_set writeSet; - struct timeval timeout; - - FD_ZERO(&writeSet); - FD_SET(tmpSocket, &writeSet); - - timeout.tv_sec = 0; - timeout.tv_usec = SEND_TIMEOUT_MSEC * 1000; - int selectResult = select(tmpSocket + 1, NULL, &writeSet, NULL, &timeout); - if (!IS_VALID_SELECT(selectResult)) - { - // Never assume that this is a fatal error. - int errCode = SOCKET_ERRNO(); - if (!IS_SOCKET_ERR_WOULDBLOCK(errCode)) - { - // Skip this packet - this is bad, and is therefore reported. - // Ignore invalid or not connected sockets. - if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK) - m_callback.SignalNetError(m_curSession->GetId(), ERR_SOCK_SELECT_FAILED, errCode); - RemoveCurSendData(); - } - Msleep(SEND_TIMEOUT_MSEC); - } - } - else // other errors than would block - { - // Skip this packet - this is bad, and is therefore reported. - // Ignore invalid or not connected sockets. - if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK) - m_callback.SignalNetError(m_curSession->GetId(), ERR_SOCK_SEND_FAILED, errCode); - RemoveCurSendData(); - Msleep(SEND_TIMEOUT_MSEC); - } - } - else if ((unsigned)bytesSent < m_tmpOutBufSize) - { - if (bytesSent) - { - m_tmpOutBufSize -= (unsigned)bytesSent; - memmove(m_tmpOutBuf, m_tmpOutBuf + bytesSent, m_tmpOutBufSize); - } - else - Msleep(SEND_TIMEOUT_MSEC); - } - else - { - assert(bytesSent == m_tmpOutBufSize); - m_tmpOutBufSize = 0; - m_curSession.reset(); - sendTimer.reset(); - } - } - else - Msleep(SEND_TIMEOUT_MSEC); - - // Check whether the send timed out. - if (sendTimer.is_running()) - { - if (sendTimer.elapsed().total_milliseconds() > SEND_ERROR_TIMEOUT_MSEC) - { - if (m_curSession.get()) - { - m_lastInvalidSessionId = m_curSession->GetId(); - LOG_MSG("Send operation for session " << m_lastInvalidSessionId << " timed out."); - } - RemoveCurSendData(); - sendTimer.reset(); - } - } - } -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace std; + +#define SEND_ERROR_TIMEOUT_MSEC 20000 +#define SEND_TIMEOUT_MSEC 10 +#ifdef POKERTH_DEDICATED_SERVER + #define SEND_QUEUE_SIZE 10000 + #define SEND_LOW_PRIO_QUEUE_SIZE 10000000 +#else + #define SEND_QUEUE_SIZE 1000 + #define SEND_LOW_PRIO_QUEUE_SIZE 10000 +#endif + +SenderThread::SenderThread(SenderCallback &cb) +: m_tmpOutBufSize(0), m_lastInvalidSessionId(INVALID_SESSION), m_callback(cb) +{ +} + +SenderThread::~SenderThread() +{ +} + +void +SenderThread::Send(boost::shared_ptr session, boost::shared_ptr packet) +{ + if (packet.get() && session.get()) + { + boost::mutex::scoped_lock lock(m_outBufMutex); + InternalStore(m_outBuf, SEND_QUEUE_SIZE, session, packet); + } +} + +void +SenderThread::Send(boost::shared_ptr session, const NetPacketList &packetList) +{ + if (!packetList.empty() && session.get()) + { + boost::mutex::scoped_lock lock(m_outBufMutex); + InternalStore(m_outBuf, SEND_QUEUE_SIZE, session, packetList); + } +} + +void +SenderThread::SendLowPrio(boost::shared_ptr session, boost::shared_ptr packet) +{ + if (packet.get() && session.get()) + { + boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); + InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, session, packet); + } +} + +void +SenderThread::SendLowPrio(boost::shared_ptr session, const NetPacketList &packetList) +{ + if (!packetList.empty() && session.get()) + { + boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); + InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, session, packetList); + } +} + +unsigned +SenderThread::GetNumPacketsInQueue() const +{ + unsigned numPackets; + { + boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); + numPackets = m_lowPrioOutBuf.size(); + } + { + boost::mutex::scoped_lock lock(m_outBufMutex); + numPackets += m_outBuf.size(); + } + return numPackets; +} + +bool +SenderThread::operator<(const SenderThread &other) const +{ + return GetNumPacketsInQueue() < other.GetNumPacketsInQueue(); +} + +void +SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, boost::shared_ptr packet) +{ + if (sendQueue.size() < maxQueueSize) // Queue is limited in size. + sendQueue.push_back(std::make_pair(packet, session)); + // TODO: Throw exception if failed. +} + +void +SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, const NetPacketList &packetList) +{ + if (sendQueue.size() + packetList.size() < maxQueueSize) + { + NetPacketList::const_iterator i = packetList.begin(); + NetPacketList::const_iterator end = packetList.end(); + while (i != end) + { + sendQueue.push_back(std::make_pair(*i, session)); + ++i; + } + } + // TODO: Throw exception if failed. +} + +void +SenderThread::RemoveCurSendData() +{ + m_tmpOutBufSize = 0; + m_curSession.reset(); + // TODO use callback to remove session. +} + +void +SenderThread::Main() +{ + boost::timers::portable::microsec_timer sendTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start); + + while (!ShouldTerminate()) + { + // Send remaining bytes of output buffer OR + // copy ONE packet to output buffer. + // For reasons of simplicity, only one packet is sent at a time. + if (!m_tmpOutBufSize) + { + bool isLowPrio = false; + SendData tmpData; + // Check main queue first. + { + boost::mutex::scoped_lock lock(m_outBufMutex); + if (!m_outBuf.empty()) + { + tmpData = m_outBuf.front(); + m_outBuf.pop_front(); + } + } + + // Check low prio queue only if there is nothing in the main queue. + if (!tmpData.first.get()) + { + boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex); + if (!m_lowPrioOutBuf.empty()) + { + tmpData = m_lowPrioOutBuf.front(); + m_lowPrioOutBuf.pop_front(); + isLowPrio = true; + } + } + + if (tmpData.first.get() && tmpData.second.get()) + { + if (!isLowPrio || tmpData.second->GetId() != m_lastInvalidSessionId) + { + u_int16_t tmpLen = tmpData.first->GetLen(); + if (tmpLen <= MAX_PACKET_SIZE) + { + m_curSession = tmpData.second; + m_tmpOutBufSize = tmpLen; + memcpy(m_tmpOutBuf, tmpData.first->GetRawData(), tmpLen); + sendTimer.restart(); + } + } + } + } + if (m_tmpOutBufSize) + { + SOCKET tmpSocket = m_curSession->GetSocket(); + + // send next chunk of data + int bytesSent = send(tmpSocket, m_tmpOutBuf, m_tmpOutBufSize, SOCKET_SEND_FLAGS); + + if (!IS_VALID_SEND(bytesSent)) + { + // Never assume that this is a fatal error. + int errCode = SOCKET_ERRNO(); + if (IS_SOCKET_ERR_WOULDBLOCK(errCode)) + { + fd_set writeSet; + struct timeval timeout; + + FD_ZERO(&writeSet); + FD_SET(tmpSocket, &writeSet); + + timeout.tv_sec = 0; + timeout.tv_usec = SEND_TIMEOUT_MSEC * 1000; + int selectResult = select(tmpSocket + 1, NULL, &writeSet, NULL, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + // Never assume that this is a fatal error. + int errCode = SOCKET_ERRNO(); + if (!IS_SOCKET_ERR_WOULDBLOCK(errCode)) + { + // Skip this packet - this is bad, and is therefore reported. + // Ignore invalid or not connected sockets. + if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK) + m_callback.SignalNetError(m_curSession->GetId(), ERR_SOCK_SELECT_FAILED, errCode); + RemoveCurSendData(); + } + Msleep(SEND_TIMEOUT_MSEC); + } + } + else // other errors than would block + { + // Skip this packet - this is bad, and is therefore reported. + // Ignore invalid or not connected sockets. + if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK) + m_callback.SignalNetError(m_curSession->GetId(), ERR_SOCK_SEND_FAILED, errCode); + RemoveCurSendData(); + Msleep(SEND_TIMEOUT_MSEC); + } + } + else if ((unsigned)bytesSent < m_tmpOutBufSize) + { + if (bytesSent) + { + m_tmpOutBufSize -= (unsigned)bytesSent; + memmove(m_tmpOutBuf, m_tmpOutBuf + bytesSent, m_tmpOutBufSize); + } + else + Msleep(SEND_TIMEOUT_MSEC); + } + else + { + assert(bytesSent == m_tmpOutBufSize); + m_tmpOutBufSize = 0; + m_curSession.reset(); + sendTimer.reset(); + } + } + else + Msleep(SEND_TIMEOUT_MSEC); + + // Check whether the send timed out. + if (sendTimer.is_running()) + { + if (sendTimer.elapsed().total_milliseconds() > SEND_ERROR_TIMEOUT_MSEC) + { + if (m_curSession.get()) + { + m_lastInvalidSessionId = m_curSession->GetId(); + LOG_MSG("Send operation for session " << m_lastInvalidSessionId << " timed out."); + } + RemoveCurSendData(); + sendTimer.reset(); + } + } + } +} + diff --git a/src/net/common/serveracceptthread.cpp b/src/net/common/serveracceptthread.cpp index 20bb2f36..3c786441 100644 --- a/src/net/common/serveracceptthread.cpp +++ b/src/net/common/serveracceptthread.cpp @@ -1,294 +1,294 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define ACCEPT_TIMEOUT_MSEC 50 -#define NET_SERVER_LISTEN_BACKLOG 5 - -using namespace std; - -ServerAcceptThread::ServerAcceptThread(GuiInterface &gui, ConfigFile *config, AvatarManager &avatarManager) -: m_gui(gui) -{ - m_context.reset(new ServerContext); - m_lobbyThread.reset(new ServerLobbyThread(gui, config, avatarManager)); -} - -ServerAcceptThread::~ServerAcceptThread() -{ -} - -void -ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const string &pwd, const string &logDir, boost::shared_ptr ircThread) -{ - if (IsRunning()) - { - assert(false); - return; - } - - ServerContext &context = GetContext(); - - context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0); - // If a "dual stack" is available, the pokerth server always uses ipv6. - // In this case, ipv4 requests will be mapped to ipv6. - context.SetAddrFamily(socket_has_dual_stack() ? AF_INET6 : (ipv6 ? AF_INET6 : AF_INET)); - context.SetServerPort(serverPort); - - GetLobbyThread().Init(pwd, logDir); - m_ircThread = ircThread; -} - -ServerCallback & -ServerAcceptThread::GetCallback() -{ - return m_gui; -} - -GuiInterface & -ServerAcceptThread::GetGui() -{ - return m_gui; -} - -void -ServerAcceptThread::SignalIrcConnect(const std::string &server) -{ - LOG_MSG("Connected to IRC server " << server << "."); -} - -void -ServerAcceptThread::SignalIrcSelfJoined(const std::string &nickName, const std::string &channel) -{ - LOG_MSG("Joined IRC channel " << channel << " as user " << nickName << "."); - m_ircNick = nickName; -} - -void -ServerAcceptThread::SignalIrcChatMsg(const std::string &nickName, const std::string &msg) -{ - if (m_ircThread) - { - istringstream msgStream(msg); - string target; - msgStream >> target; - if (boost::algorithm::iequals(target, m_ircNick + ":")) - { - string command; - msgStream >> command; - if (command == "kick") - { - while (msgStream.peek() == ' ') - msgStream.get(); - string playerName(msgStream.str().substr(msgStream.tellg())); - if (!playerName.empty()) - { - if (GetLobbyThread().KickPlayerByName(playerName)) - m_ircThread->SendChatMessage(nickName + ": Successfully kicked player \"" + playerName + "\" from the server."); - else - m_ircThread->SendChatMessage(nickName + ": Player \"" + playerName + "\" was not found on the server."); - } - } - else if (command == "stat") - { - ServerStats tmpStats = GetLobbyThread().GetStats(); - ostringstream statStream; - statStream - << "Players on Server: " << tmpStats.numberOfPlayersOnServer; - m_ircThread->SendChatMessage(statStream.str()); - } - else - m_ircThread->SendChatMessage(nickName + ": Invalid command \"" + command + "\"."); - } - } -} - -void -ServerAcceptThread::SignalIrcError(int errorCode) -{ -} - -void -ServerAcceptThread::SignalIrcServerError(int errorCode) -{ -} - -void -ServerAcceptThread::Main() -{ - try - { - Listen(); - if (m_ircThread) - m_ircThread->Run(); - GetLobbyThread().Run(); - - while (!ShouldTerminate() && !GetLobbyThread().Join(0)) - { - // The main server thread is simple. It only accepts connections. - AcceptLoop(); - } - } catch (const PokerTHException &e) - { - GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); - LOG_ERROR(e.what()); - } - GetLobbyThread().SignalTermination(); - GetLobbyThread().Join(LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC); - - if (m_ircThread) - { - m_ircThread->SignalTermination(); - m_ircThread->Join(ADMIN_IRC_TERMINATE_TIMEOUT_MSEC); - } -} - -void -ServerAcceptThread::Listen() -{ - ServerContext &context = GetContext(); - - if (context.GetServerPort() < 1024) - throw ServerException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0); - - context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol())); - if (!IS_VALID_SOCKET(context.GetSocket())) - throw ServerException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - - unsigned long mode = 1; - if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) - throw ServerException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - - // The following three calls are optional. If they fail, we don't care. - int reuse = 1; - setsockopt(context.GetSocket(), SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)); - int nodelay = 1; - setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); - // Enable dual-stack socket on Windows Vista. - int ipv6only = 0; - setsockopt(context.GetSocket(), IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); - - context.GetServerSockaddr()->ss_family = context.GetAddrFamily(); - - const char *localAddr = (context.GetAddrFamily() == AF_INET6) ? "::0" : "0.0.0.0"; - if (!socket_string_to_addr( - localAddr, - context.GetAddrFamily(), - (struct sockaddr *)context.GetServerSockaddr(), - context.GetServerSockaddrSize())) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_SET_ADDR_FAILED, 0); - } - if (!socket_set_port( - context.GetServerPort(), - context.GetAddrFamily(), - (struct sockaddr *)context.GetServerSockaddr(), - context.GetServerSockaddrSize())) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_SET_PORT_FAILED, 0); - } - - if (!IS_VALID_BIND(bind( - context.GetSocket(), - (const struct sockaddr *)context.GetServerSockaddr(), - context.GetServerSockaddrSize()))) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_BIND_FAILED, SOCKET_ERRNO()); - } - - if (!IS_VALID_LISTEN(listen(context.GetSocket(), NET_SERVER_LISTEN_BACKLOG))) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_LISTEN_FAILED, SOCKET_ERRNO()); - } -} - -void -ServerAcceptThread::AcceptLoop() -{ - ServerContext &context = GetContext(); - - fd_set readSet; - struct timeval timeout; - - FD_ZERO(&readSet); - FD_SET(context.GetSocket(), &readSet); - - timeout.tv_sec = 0; - timeout.tv_usec = ACCEPT_TIMEOUT_MSEC * 1000; - int selectResult = select(context.GetSocket() + 1, &readSet, NULL, NULL, &timeout); - if (!IS_VALID_SELECT(selectResult)) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); - } - if (selectResult > 0) // accept is possible - { - boost::shared_ptr tmpData(new ConnectData); - tmpData->SetSocket(accept(context.GetSocket(), NULL, NULL)); - - if (!IS_VALID_SOCKET(tmpData->GetSocket())) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_ACCEPT_FAILED, SOCKET_ERRNO()); - } - unsigned long mode = 1; - if (IOCTLSOCKET(tmpData->GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - } - // Optional call - don't check return value. - // Enable keepalive - won't be of much use but better than nothing. - int keepalive = 1; - setsockopt(tmpData->GetSocket(), SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, sizeof(keepalive)); - - GetLobbyThread().AddConnection(tmpData); - } -} - -const ServerContext & -ServerAcceptThread::GetContext() const -{ - assert(m_context.get()); - return *m_context; -} - -ServerContext & -ServerAcceptThread::GetContext() -{ - assert(m_context.get()); - return *m_context; -} - -ServerLobbyThread & -ServerAcceptThread::GetLobbyThread() -{ - assert(m_lobbyThread.get()); - return *m_lobbyThread; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ACCEPT_TIMEOUT_MSEC 50 +#define NET_SERVER_LISTEN_BACKLOG 5 + +using namespace std; + +ServerAcceptThread::ServerAcceptThread(GuiInterface &gui, ConfigFile *config, AvatarManager &avatarManager) +: m_gui(gui) +{ + m_context.reset(new ServerContext); + m_lobbyThread.reset(new ServerLobbyThread(gui, config, avatarManager)); +} + +ServerAcceptThread::~ServerAcceptThread() +{ +} + +void +ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const string &pwd, const string &logDir, boost::shared_ptr ircThread) +{ + if (IsRunning()) + { + assert(false); + return; + } + + ServerContext &context = GetContext(); + + context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0); + // If a "dual stack" is available, the pokerth server always uses ipv6. + // In this case, ipv4 requests will be mapped to ipv6. + context.SetAddrFamily(socket_has_dual_stack() ? AF_INET6 : (ipv6 ? AF_INET6 : AF_INET)); + context.SetServerPort(serverPort); + + GetLobbyThread().Init(pwd, logDir); + m_ircThread = ircThread; +} + +ServerCallback & +ServerAcceptThread::GetCallback() +{ + return m_gui; +} + +GuiInterface & +ServerAcceptThread::GetGui() +{ + return m_gui; +} + +void +ServerAcceptThread::SignalIrcConnect(const std::string &server) +{ + LOG_MSG("Connected to IRC server " << server << "."); +} + +void +ServerAcceptThread::SignalIrcSelfJoined(const std::string &nickName, const std::string &channel) +{ + LOG_MSG("Joined IRC channel " << channel << " as user " << nickName << "."); + m_ircNick = nickName; +} + +void +ServerAcceptThread::SignalIrcChatMsg(const std::string &nickName, const std::string &msg) +{ + if (m_ircThread) + { + istringstream msgStream(msg); + string target; + msgStream >> target; + if (boost::algorithm::iequals(target, m_ircNick + ":")) + { + string command; + msgStream >> command; + if (command == "kick") + { + while (msgStream.peek() == ' ') + msgStream.get(); + string playerName(msgStream.str().substr(msgStream.tellg())); + if (!playerName.empty()) + { + if (GetLobbyThread().KickPlayerByName(playerName)) + m_ircThread->SendChatMessage(nickName + ": Successfully kicked player \"" + playerName + "\" from the server."); + else + m_ircThread->SendChatMessage(nickName + ": Player \"" + playerName + "\" was not found on the server."); + } + } + else if (command == "stat") + { + ServerStats tmpStats = GetLobbyThread().GetStats(); + ostringstream statStream; + statStream + << "Players on Server: " << tmpStats.numberOfPlayersOnServer; + m_ircThread->SendChatMessage(statStream.str()); + } + else + m_ircThread->SendChatMessage(nickName + ": Invalid command \"" + command + "\"."); + } + } +} + +void +ServerAcceptThread::SignalIrcError(int errorCode) +{ +} + +void +ServerAcceptThread::SignalIrcServerError(int errorCode) +{ +} + +void +ServerAcceptThread::Main() +{ + try + { + Listen(); + if (m_ircThread) + m_ircThread->Run(); + GetLobbyThread().Run(); + + while (!ShouldTerminate() && !GetLobbyThread().Join(0)) + { + // The main server thread is simple. It only accepts connections. + AcceptLoop(); + } + } catch (const PokerTHException &e) + { + GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); + LOG_ERROR(e.what()); + } + GetLobbyThread().SignalTermination(); + GetLobbyThread().Join(LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC); + + if (m_ircThread) + { + m_ircThread->SignalTermination(); + m_ircThread->Join(ADMIN_IRC_TERMINATE_TIMEOUT_MSEC); + } +} + +void +ServerAcceptThread::Listen() +{ + ServerContext &context = GetContext(); + + if (context.GetServerPort() < 1024) + throw ServerException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0); + + context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol())); + if (!IS_VALID_SOCKET(context.GetSocket())) + throw ServerException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); + + unsigned long mode = 1; + if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) + throw ServerException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); + + // The following three calls are optional. If they fail, we don't care. + int reuse = 1; + setsockopt(context.GetSocket(), SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)); + int nodelay = 1; + setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); + // Enable dual-stack socket on Windows Vista. + int ipv6only = 0; + setsockopt(context.GetSocket(), IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); + + context.GetServerSockaddr()->ss_family = context.GetAddrFamily(); + + const char *localAddr = (context.GetAddrFamily() == AF_INET6) ? "::0" : "0.0.0.0"; + if (!socket_string_to_addr( + localAddr, + context.GetAddrFamily(), + (struct sockaddr *)context.GetServerSockaddr(), + context.GetServerSockaddrSize())) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_SET_ADDR_FAILED, 0); + } + if (!socket_set_port( + context.GetServerPort(), + context.GetAddrFamily(), + (struct sockaddr *)context.GetServerSockaddr(), + context.GetServerSockaddrSize())) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_SET_PORT_FAILED, 0); + } + + if (!IS_VALID_BIND(bind( + context.GetSocket(), + (const struct sockaddr *)context.GetServerSockaddr(), + context.GetServerSockaddrSize()))) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_BIND_FAILED, SOCKET_ERRNO()); + } + + if (!IS_VALID_LISTEN(listen(context.GetSocket(), NET_SERVER_LISTEN_BACKLOG))) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_LISTEN_FAILED, SOCKET_ERRNO()); + } +} + +void +ServerAcceptThread::AcceptLoop() +{ + ServerContext &context = GetContext(); + + fd_set readSet; + struct timeval timeout; + + FD_ZERO(&readSet); + FD_SET(context.GetSocket(), &readSet); + + timeout.tv_sec = 0; + timeout.tv_usec = ACCEPT_TIMEOUT_MSEC * 1000; + int selectResult = select(context.GetSocket() + 1, &readSet, NULL, NULL, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); + } + if (selectResult > 0) // accept is possible + { + boost::shared_ptr tmpData(new ConnectData); + tmpData->SetSocket(accept(context.GetSocket(), NULL, NULL)); + + if (!IS_VALID_SOCKET(tmpData->GetSocket())) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_ACCEPT_FAILED, SOCKET_ERRNO()); + } + unsigned long mode = 1; + if (IOCTLSOCKET(tmpData->GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); + } + // Optional call - don't check return value. + // Enable keepalive - won't be of much use but better than nothing. + int keepalive = 1; + setsockopt(tmpData->GetSocket(), SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, sizeof(keepalive)); + + GetLobbyThread().AddConnection(tmpData); + } +} + +const ServerContext & +ServerAcceptThread::GetContext() const +{ + assert(m_context.get()); + return *m_context; +} + +ServerContext & +ServerAcceptThread::GetContext() +{ + assert(m_context.get()); + return *m_context; +} + +ServerLobbyThread & +ServerAcceptThread::GetLobbyThread() +{ + assert(m_lobbyThread.get()); + return *m_lobbyThread; +} + diff --git a/src/net/common/servercallback.cpp b/src/net/common/servercallback.cpp index fb1c0a65..5fe77c5d 100644 --- a/src/net/common/servercallback.cpp +++ b/src/net/common/servercallback.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -ServerCallback::~ServerCallback() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +ServerCallback::~ServerCallback() +{ +} + diff --git a/src/net/common/servercontext.cpp b/src/net/common/servercontext.cpp index f6bb554b..f4e7746d 100644 --- a/src/net/common/servercontext.cpp +++ b/src/net/common/servercontext.cpp @@ -1,45 +1,45 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -ServerContext::ServerContext() -: m_sockfd(INVALID_SOCKET), m_protocol(0), m_addrFamily(AF_INET), m_serverPort(0) -{ - bzero(&m_serverSockaddr, sizeof(m_serverSockaddr)); -} - -ServerContext::~ServerContext() -{ - if (m_sockfd != INVALID_SOCKET) - CLOSESOCKET(m_sockfd); -} - -SOCKET -ServerContext::GetSocket() const -{ - return m_sockfd; -} - -void -ServerContext::SetSocket(SOCKET sockfd) -{ - m_sockfd = sockfd; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +ServerContext::ServerContext() +: m_sockfd(INVALID_SOCKET), m_protocol(0), m_addrFamily(AF_INET), m_serverPort(0) +{ + bzero(&m_serverSockaddr, sizeof(m_serverSockaddr)); +} + +ServerContext::~ServerContext() +{ + if (m_sockfd != INVALID_SOCKET) + CLOSESOCKET(m_sockfd); +} + +SOCKET +ServerContext::GetSocket() const +{ + return m_sockfd; +} + +void +ServerContext::SetSocket(SOCKET sockfd) +{ + m_sockfd = sockfd; +} + diff --git a/src/net/common/serverexception.cpp b/src/net/common/serverexception.cpp index cae5bc08..69054c88 100644 --- a/src/net/common/serverexception.cpp +++ b/src/net/common/serverexception.cpp @@ -1,26 +1,26 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - - -ServerException::~ServerException() throw() -{ -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + + +ServerException::~ServerException() throw() +{ +} + diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 97f45f2e..62f2d045 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -1,1167 +1,1167 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. -#define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day -#define SERVER_SAVE_STATISTICS_INTERVAL_SEC 60 -#define SERVER_INIT_SESSION_TIMEOUT_SEC 20 - -#define SERVER_NUM_AVATAR_SENDER_THREADS 1 - -#define SERVER_STATISTICS_FILE_NAME "server_statistics.log" -#define SERVER_STATISTICS_STR_TOTAL_PLAYERS "TotalNumPlayersLoggedIn" -#define SERVER_STATISTICS_STR_TOTAL_GAMES "TotalNumGamesCreated" -#define SERVER_STATISTICS_STR_MAX_GAMES "MaxGamesOpen" -#define SERVER_STATISTICS_STR_MAX_PLAYERS "MaxPlayersLoggedIn" - -using namespace std; - - -class ServerSenderCallback : public SenderCallback -{ -public: - ServerSenderCallback(ServerLobbyThread &server) : m_server(server) {} - virtual ~ServerSenderCallback() {} - - virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/) - { - // We just ignore send errors for now, on server side. - // A serious send error should trigger a read error or a read - // returning 0 afterwards, and we will handle this error. - } - -private: - ServerLobbyThread &m_server; -}; - - -ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager) -: m_gui(gui), m_avatarManager(avatarManager), m_playerConfig(playerConfig), - m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1), - m_statDataChanged(false) -{ - m_senderCallback.reset(new ServerSenderCallback(*this)); - m_sender.reset(new SenderThread(GetSenderCallback())); - for (int i = 0; i < SERVER_NUM_AVATAR_SENDER_THREADS; i++) - m_avatarSenderThreadPool.push_back(boost::shared_ptr(new SenderThread(GetSenderCallback()))); - m_receiver.reset(new ReceiverHelper); -} - -ServerLobbyThread::~ServerLobbyThread() -{ - CleanupConnectQueue(); -} - -void -ServerLobbyThread::Init(const string &pwd, const string &logDir) -{ - m_password = pwd; - // Read previous server statistics. - if (!logDir.empty()) - { - boost::filesystem::path logPath(logDir); - if (!logDir.empty()) - { - logPath /= SERVER_STATISTICS_FILE_NAME; - m_statisticsFileName = logPath.directory_string(); - ReadStatisticsFile(); - } - } -} - -void -ServerLobbyThread::AddConnection(boost::shared_ptr data) -{ - boost::mutex::scoped_lock lock(m_connectQueueMutex); - m_connectQueue.push_back(data); -} - -void -ServerLobbyThread::ReAddSession(SessionWrapper session, int reason) -{ - boost::shared_ptr packet(new NetPacketRemovedFromGame); - NetPacketRemovedFromGame::Data removedData; - removedData.removeReason = reason; - static_cast(packet.get())->SetData(removedData); - GetSender().Send(session.sessionData, packet); - - boost::mutex::scoped_lock lock(m_sessionQueueMutex); - m_sessionQueue.push_back(session); -} - -void -ServerLobbyThread::MoveSessionToGame(ServerGameThread &game, SessionWrapper session) -{ - // Remove session from the lobby. - m_sessionManager.RemoveSession(session.sessionData->GetId()); - // Session is now in game state. - session.sessionData->SetState(SessionData::Game); - // Store it in the list of game sessions. - m_gameSessionManager.AddSession(session); - // Add session to the game. - game.AddSession(session); -} - -void -ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session) -{ - // Just remove the session. Only for fatal errors. - CloseSession(session); -} - -void -ServerLobbyThread::CloseSession(SessionWrapper session) -{ - { - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - m_initTimerSessionMap.erase(session.sessionData->GetId()); - } - m_sessionManager.RemoveSession(session.sessionData->GetId()); - m_gameSessionManager.RemoveSession(session.sessionData->GetId()); - - // Update stats (if needed). - UpdateStatisticsNumberOfPlayers(); -} - -void -ServerLobbyThread::NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId) -{ - // Send notification to players in lobby. - boost::shared_ptr packet(new NetPacketGameListPlayerJoined); - NetPacketGameListPlayerJoined::Data packetData; - packetData.gameId = gameId; - packetData.playerId = playerId; - static_cast(packet.get())->SetData(packetData); - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); -} - -void -ServerLobbyThread::NotifyPlayerLeftGame(unsigned gameId, unsigned playerId) -{ - // Send notification to players in lobby. - boost::shared_ptr packet(new NetPacketGameListPlayerLeft); - NetPacketGameListPlayerLeft::Data packetData; - packetData.gameId = gameId; - packetData.playerId = playerId; - static_cast(packet.get())->SetData(packetData); - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); -} - -void -ServerLobbyThread::NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId) -{ - // Send notification to players in lobby. - boost::shared_ptr packet(new NetPacketGameListAdminChanged); - NetPacketGameListAdminChanged::Data packetData; - packetData.gameId = gameId; - packetData.newAdminplayerId = newAdminPlayerId; - static_cast(packet.get())->SetData(packetData); - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); -} - -void -ServerLobbyThread::NotifyStartingGame(unsigned gameId) -{ - boost::shared_ptr packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_STARTED); - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); -} - -void -ServerLobbyThread::NotifyReopeningGame(unsigned gameId) -{ - boost::shared_ptr packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_CREATED); - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); -} - -void -ServerLobbyThread::HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket) -{ - // Someone within a game requested player info. - HandleNetPacketRetrievePlayerInfo(session, tmpPacket); -} - -void -ServerLobbyThread::HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket) -{ - // Someone within a game requested an avatar. - HandleNetPacketRetrieveAvatar(session, tmpPacket); -} - -bool -ServerLobbyThread::KickPlayerByName(const std::string &playerName) -{ - bool retVal = false; - SessionWrapper session = m_sessionManager.GetSessionByPlayerName(playerName); - if (!session.sessionData.get()) - session = m_gameSessionManager.GetSessionByPlayerName(playerName); - - if (session.sessionData.get() && session.playerData.get()) - { - boost::mutex::scoped_lock lock(m_kickPlayerListMutex); - m_kickPlayerList.push_back(session.playerData->GetUniqueId()); - retVal = true; - } - - return retVal; -} - -void -ServerLobbyThread::AddComputerPlayer(boost::shared_ptr player) -{ - boost::mutex::scoped_lock lock(m_computerPlayersMutex); - m_computerPlayers.insert(PlayerDataMap::value_type(player->GetUniqueId(), player)); -} - -void -ServerLobbyThread::RemoveComputerPlayer(boost::shared_ptr player) -{ - boost::mutex::scoped_lock lock(m_computerPlayersMutex); - m_computerPlayers.erase(player->GetUniqueId()); -} - -void -ServerLobbyThread::RemoveGame(unsigned id) -{ - boost::mutex::scoped_lock lock(m_removeGameListMutex); - m_removeGameList.push_back(id); -} - -AvatarManager & -ServerLobbyThread::GetAvatarManager() -{ - return m_avatarManager; -} - -ServerStats -ServerLobbyThread::GetStats() const -{ - boost::mutex::scoped_lock lock(m_statMutex); - return m_statData; -} - -u_int32_t -ServerLobbyThread::GetNextUniquePlayerId() -{ - boost::mutex::scoped_lock lock(m_curUniquePlayerIdMutex); - return m_curUniquePlayerId++; -} - -u_int32_t -ServerLobbyThread::GetNextGameId() -{ - return m_curGameId++; -} - -void -ServerLobbyThread::Main() -{ - GetSender().Run(); - for_each(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), boost::mem_fn(&SenderThread::Run)); - - try - { - while (!ShouldTerminate()) - { - // Process new connections. - NewConnectionLoop(); - // Process re-added sessions. - NewSessionLoop(); - // Main loop. - ProcessLoop(); - // Close sessions. - CloseSessionLoop(); - // Remove games. - RemoveGameLoop(); - // Kick players. - KickPlayerLoop(); - // Cleanup cache. - CleanupAvatarCache(); - // Save statistics if needed. - SaveStatisticsFile(); - } - } catch (const PokerTHException &e) - { - GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); - LOG_ERROR(e.what()); - } - - TerminateGames(); - - GetSender().SignalTermination(); - for_each(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), boost::mem_fn(&SenderThread::SignalTermination)); - - GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); - for_each(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), boost::bind(&SenderThread::Join, _1, SENDER_THREAD_TERMINATE_TIMEOUT)); - - CleanupConnectQueue(); -} - -void -ServerLobbyThread::ProcessLoop() -{ - // Wait for data. - SessionWrapper session = m_sessionManager.Select(RECV_TIMEOUT_MSEC); - - if (session.sessionData.get()) - { - boost::shared_ptr packet; - try - { - // Receive the next packet. - packet = GetReceiver().Recv(session.sessionData->GetSocket(), session.sessionData->GetReceiveBuffer()); - } catch (const NetException &) - { - // On error: Close this session. - CloseSession(session); - return; - } - if (packet.get()) - { - if (session.sessionData->GetState() == SessionData::Init) - { - if (packet->ToNetPacketInit()) - HandleNetPacketInit(session, *packet->ToNetPacketInit()); - else if (packet->ToNetPacketAvatarHeader()) - HandleNetPacketAvatarHeader(session, *packet->ToNetPacketAvatarHeader()); - else if (packet->ToNetPacketUnknownAvatar()) - HandleNetPacketUnknownAvatar(session, *packet->ToNetPacketUnknownAvatar()); - else - SessionError(session, ERR_SOCK_INVALID_STATE); - } - else if (session.sessionData->GetState() == SessionData::ReceivingAvatar) - { - if (packet->ToNetPacketAvatarFile()) - HandleNetPacketAvatarFile(session, *packet->ToNetPacketAvatarFile()); - else if (packet->ToNetPacketAvatarEnd()) - HandleNetPacketAvatarEnd(session, *packet->ToNetPacketAvatarEnd()); - else - SessionError(session, ERR_SOCK_INVALID_STATE); - } - else - { - if (packet->ToNetPacketRetrievePlayerInfo()) - HandleNetPacketRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo()); - else if (packet->ToNetPacketRetrieveAvatar()) - HandleNetPacketRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); - else if (packet->ToNetPacketCreateGame()) - HandleNetPacketCreateGame(session, *packet->ToNetPacketCreateGame()); - else if (packet->ToNetPacketJoinGame()) - HandleNetPacketJoinGame(session, *packet->ToNetPacketJoinGame()); - else - SessionError(session, ERR_SOCK_INVALID_STATE); - } - } - } -} - -void -ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketInit &tmpPacket) -{ - NetPacketInit::Data initData; - tmpPacket.GetData(initData); - - // Check the protocol version. - if (initData.versionMajor != NET_VERSION_MAJOR) - { - SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); - return; - } - - // Check the server password. - if (!CheckPassword(initData.password)) - { - SessionError(session, ERR_NET_INVALID_PASSWORD); - return; - } - - // Check whether the player name is correct. - // Partly, this is also done in netpacket. - // However, some disallowed names are checked only here. - if (initData.playerName.empty() || initData.playerName.size() > MAX_NAME_SIZE - || initData.playerName[0] == '#' - || initData.playerName[0] == ' ' - || initData.playerName.substr(0, sizeof(SERVER_COMPUTER_PLAYER_NAME) - 1) == SERVER_COMPUTER_PLAYER_NAME) - { - SessionError(session, ERR_NET_INVALID_PLAYER_NAME); - return; - } - - // Check whether this player is already connected. - if (IsPlayerConnected(initData.playerName)) - { - SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); - return; - } - - // Create player data object. - boost::shared_ptr tmpPlayerData( - new PlayerData(GetNextUniquePlayerId(), 0, PLAYER_TYPE_HUMAN, PLAYER_RIGHTS_NORMAL)); - tmpPlayerData->SetName(initData.playerName); - tmpPlayerData->SetNetSessionData(session.sessionData); - if (initData.showAvatar) - tmpPlayerData->SetAvatarMD5(initData.avatar); - - // Set player data for session. - m_sessionManager.SetSessionPlayerData(session.sessionData->GetId(), tmpPlayerData); - session.playerData = tmpPlayerData; - - if (initData.showAvatar && !initData.avatar.IsZero() && !GetAvatarManager().HasAvatar(initData.avatar)) - RequestPlayerAvatar(session); - else - EstablishSession(session); -} - -void -ServerLobbyThread::HandleNetPacketAvatarHeader(SessionWrapper session, const NetPacketAvatarHeader &tmpPacket) -{ - if (session.playerData.get()) - { - NetPacketAvatarHeader::Data headerData; - tmpPacket.GetData(headerData); - - if (headerData.avatarFileSize >= MIN_AVATAR_FILE_SIZE && headerData.avatarFileSize <= MAX_AVATAR_FILE_SIZE) - { - boost::shared_ptr tmpAvatarData(new AvatarData); - tmpAvatarData->fileData.reserve(headerData.avatarFileSize); - tmpAvatarData->fileType = headerData.avatarFileType; - tmpAvatarData->reportedSize = headerData.avatarFileSize; - // Ignore request id for now. - - session.playerData->SetNetAvatarData(tmpAvatarData); - - // Session is now receiving an avatar. - session.sessionData->SetState(SessionData::ReceivingAvatar); - } - else - SessionError(session, ERR_NET_AVATAR_TOO_LARGE); - } -} - -void -ServerLobbyThread::HandleNetPacketUnknownAvatar(SessionWrapper session, const NetPacketUnknownAvatar &/*tmpPacket*/) -{ - if (session.playerData.get()) - { - // Free memory (just in case). - session.playerData->SetNetAvatarData(boost::shared_ptr()); - session.playerData->SetAvatarMD5(MD5Buf()); - // Start session. - EstablishSession(session); - } -} - -void -ServerLobbyThread::HandleNetPacketAvatarFile(SessionWrapper session, const NetPacketAvatarFile &tmpPacket) -{ - if (session.playerData.get()) - { - NetPacketAvatarFile::Data data; - tmpPacket.GetData(data); - - boost::shared_ptr tmpAvatar = session.playerData->GetNetAvatarData(); - if (tmpAvatar.get() && tmpAvatar->fileData.size() + data.fileData.size() <= tmpAvatar->reportedSize) - { - std::copy(data.fileData.begin(), data.fileData.end(), back_inserter(tmpAvatar->fileData)); - } - } -} - -void -ServerLobbyThread::HandleNetPacketAvatarEnd(SessionWrapper session, const NetPacketAvatarEnd &/*tmpPacket*/) -{ - if (session.playerData.get()) - { - boost::shared_ptr tmpAvatar = session.playerData->GetNetAvatarData(); - MD5Buf avatarMD5 = session.playerData->GetAvatarMD5(); - if (!avatarMD5.IsZero() && tmpAvatar.get()) - { - unsigned avatarSize = (unsigned)tmpAvatar->fileData.size(); - if (avatarSize == tmpAvatar->reportedSize) - { - if (!GetAvatarManager().StoreAvatarInCache(avatarMD5, tmpAvatar->fileType, &tmpAvatar->fileData[0], avatarSize)) - { - session.playerData->SetAvatarMD5(MD5Buf()); - LOG_ERROR("Failed to store avatar in cache directory."); - } - - // Free memory. - session.playerData->SetNetAvatarData(boost::shared_ptr()); - // Init finished - start session. - EstablishSession(session); - } - else - SessionError(session, ERR_NET_WRONG_AVATAR_SIZE); - } - } -} - -void -ServerLobbyThread::HandleNetPacketRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket) -{ - NetPacketRetrievePlayerInfo::Data request; - tmpPacket.GetData(request); - - // Find player in lobby or in a game. - boost::shared_ptr tmpPlayer = m_sessionManager.GetSessionByUniquePlayerId(request.playerId).playerData; - if (!tmpPlayer.get()) - tmpPlayer = m_gameSessionManager.GetSessionByUniquePlayerId(request.playerId).playerData; - if (!tmpPlayer.get()) - { - boost::mutex::scoped_lock lock(m_computerPlayersMutex); - PlayerDataMap::const_iterator pos = m_computerPlayers.find(request.playerId); - if (pos != m_computerPlayers.end()) - tmpPlayer = pos->second; - } - - if (tmpPlayer.get()) - { - // Send player info to client. - boost::shared_ptr info(new NetPacketPlayerInfo); - NetPacketPlayerInfo::Data infoData; - infoData.playerId = tmpPlayer->GetUniqueId(); - infoData.playerInfo.ptype = tmpPlayer->GetType(); - infoData.playerInfo.playerName = tmpPlayer->GetName(); - infoData.playerInfo.hasAvatar = !tmpPlayer->GetAvatarMD5().IsZero(); - if (infoData.playerInfo.hasAvatar) - infoData.playerInfo.avatar = tmpPlayer->GetAvatarMD5(); - static_cast(info.get())->SetData(infoData); - GetSender().Send(session.sessionData, info); - } - else - { - // Unknown player id - notify client. - boost::shared_ptr unknown(new NetPacketUnknownPlayerId); - NetPacketUnknownPlayerId::Data unknownData; - unknownData.playerId = request.playerId; - static_cast(unknown.get())->SetData(unknownData); - GetSender().Send(session.sessionData, unknown); - } -} - -void -ServerLobbyThread::HandleNetPacketRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket) -{ - bool avatarFound = false; - NetPacketRetrieveAvatar::Data request; - tmpPacket.GetData(request); - - string tmpFile; - if (GetAvatarManager().GetAvatarFileName(request.avatar, tmpFile)) - { - NetPacketList tmpPackets; - if (GetAvatarManager().AvatarFileToNetPackets(tmpFile, request.requestId, tmpPackets) == 0) - { - avatarFound = true; - SenderThreadList::iterator pos = min_element(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), *boost::lambda::_1 < *boost::lambda::_2); - if (pos != m_avatarSenderThreadPool.end()) - (*pos)->SendLowPrio(session.sessionData, tmpPackets); - else - LOG_ERROR("Load balancing for avatar sender threads failed."); - } - else - LOG_ERROR("Failed to read avatar file for network transmission."); - } - - if (!avatarFound) - { - // Notify client we didn't find the avatar. - boost::shared_ptr unknown(new NetPacketUnknownAvatar); - NetPacketUnknownAvatar::Data unknownData; - unknownData.requestId = request.requestId; - static_cast(unknown.get())->SetData(unknownData); - GetSender().Send(session.sessionData, unknown); - } -} - -void -ServerLobbyThread::HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket) -{ - // Create a new game. - NetPacketCreateGame::Data createGameData; - tmpPacket.GetData(createGameData); - - boost::shared_ptr game( - new ServerGameThread( - *this, - GetNextGameId(), - createGameData.gameName, - createGameData.password, - createGameData.gameData, - session.playerData->GetUniqueId(), - GetGui(), - m_playerConfig)); - - MoveSessionToGame(*game, session); - - // Add game to list of games. - InternalAddGame(game); - - // Start the game. - game->Run(); -} - -void -ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket) -{ - // Join an existing game. - NetPacketJoinGame::Data joinGameData; - tmpPacket.GetData(joinGameData); - - GameMap::iterator pos = m_gameMap.find(joinGameData.gameId); - - if (pos != m_gameMap.end()) - { - ServerGameThread &game = *pos->second; - if (game.CheckPassword(joinGameData.password)) - { - MoveSessionToGame(game, session); - } - else - { - SendJoinGameFailed(session.sessionData, NTF_NET_JOIN_INVALID_PASSWORD); - } - } - else - { - SessionError(session, ERR_NET_UNKNOWN_GAME); - } -} - -void -ServerLobbyThread::EstablishSession(SessionWrapper session) -{ - if (!session.playerData.get()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - // Send ACK to client. - boost::shared_ptr initAck(new NetPacketInitAck); - NetPacketInitAck::Data initAckData; - initAckData.latestGameVersion = POKERTH_VERSION; - initAckData.latestBetaRevision = POKERTH_BETA_REVISION; - initAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused. - initAckData.playerId = session.playerData->GetUniqueId(); - static_cast(initAck.get())->SetData(initAckData); - GetSender().Send(session.sessionData, initAck); - - // Send the game list to the client. - SendGameList(session.sessionData); - - // Session is now established. - { - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - m_initTimerSessionMap.erase(session.sessionData->GetId()); - } - session.sessionData->SetState(SessionData::Established); - - { - boost::mutex::scoped_lock lock(m_statMutex); - ++m_statData.totalPlayersEverLoggedIn; - m_statDataChanged = true; - } - UpdateStatisticsNumberOfPlayers(); -} - -void -ServerLobbyThread::RequestPlayerAvatar(SessionWrapper session) -{ - if (!session.playerData.get()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - // Ask the client to send its avatar. - boost::shared_ptr retrieveAvatar(new NetPacketRetrieveAvatar); - NetPacketRetrieveAvatar::Data retrieveAvatarData; - retrieveAvatarData.requestId = session.playerData->GetUniqueId(); - retrieveAvatarData.avatar = session.playerData->GetAvatarMD5(); - static_cast(retrieveAvatar.get())->SetData(retrieveAvatarData); - GetSender().Send(session.sessionData, retrieveAvatar); -} - -void -ServerLobbyThread::NewConnectionLoop() -{ - // Handle one incoming connection at a time. - boost::shared_ptr tmpData; - { - boost::mutex::scoped_lock lock(m_connectQueueMutex); - if (!m_connectQueue.empty()) - { - tmpData = m_connectQueue.front(); - m_connectQueue.pop_front(); - } - } - if (tmpData.get()) - HandleNewConnection(tmpData); -} - -void -ServerLobbyThread::NewSessionLoop() -{ - // Handle one incoming session at a time. - SessionWrapper tmpSession; - { - boost::mutex::scoped_lock lock(m_sessionQueueMutex); - if (!m_sessionQueue.empty()) - { - tmpSession = m_sessionQueue.front(); - m_sessionQueue.pop_front(); - } - } - if (tmpSession.sessionData.get() && tmpSession.playerData.get()) - HandleReAddedSession(tmpSession); -} - -void -ServerLobbyThread::CloseSessionLoop() -{ - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - InitTimerSessionMap::iterator i = m_initTimerSessionMap.begin(); - InitTimerSessionMap::iterator end = m_initTimerSessionMap.end(); - - // Remove sessions if they do not initialize within a certain period. - while (i != end) - { - InitTimerSessionMap::iterator next = i; - ++next; - if (i->second.elapsed().total_seconds() > SERVER_INIT_SESSION_TIMEOUT_SEC) - { - m_sessionManager.RemoveSession(i->first); - m_initTimerSessionMap.erase(i); - } - i = next; - } -} - -void -ServerLobbyThread::RemoveGameLoop() -{ - boost::mutex::scoped_lock lock(m_removeGameListMutex); - - RemoveGameList::iterator i = m_removeGameList.begin(); - RemoveGameList::iterator end = m_removeGameList.end(); - - // Synchronously remove games which have been closed. - while (i != end) - { - GameMap::iterator pos = m_gameMap.find(*i); - if (pos != m_gameMap.end()) - { - boost::shared_ptr tmpGame = pos->second; - tmpGame->SignalTermination(); - if (!tmpGame->Join(GAME_THREAD_TERMINATE_TIMEOUT)) - throw ServerException(__FILE__, __LINE__, ERR_NET_GAME_TERMINATION_FAILED, 0); - InternalRemoveGame(tmpGame); - } - ++i; - } - m_removeGameList.clear(); -} - -void -ServerLobbyThread::KickPlayerLoop() -{ - boost::mutex::scoped_lock lock(m_kickPlayerListMutex); - - PlayerIdList::iterator i = m_kickPlayerList.begin(); - PlayerIdList::iterator end = m_kickPlayerList.end(); - - while (i != end) - { - InternalKickPlayer(*i); - ++i; - } - m_kickPlayerList.clear(); -} - -void -ServerLobbyThread::CleanupAvatarCache() -{ - // Only act on timer and if there are no sessions. - if (m_cacheCleanupTimer.elapsed().total_seconds() > SERVER_CACHE_CLEANUP_INTERVAL_SEC - && !m_sessionManager.HasSessions() && !m_gameSessionManager.HasSessions()) - { - m_avatarManager.RemoveOldAvatarCacheEntries(); - m_cacheCleanupTimer.reset(); - m_cacheCleanupTimer.start(); - } -} - -void -ServerLobbyThread::InternalAddGame(boost::shared_ptr game) -{ - // Add game to list. - m_gameMap.insert(GameMap::value_type(game->GetId(), game)); - // Notify all players. - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game); - - { - boost::mutex::scoped_lock lock(m_statMutex); - ++m_statData.totalGamesEverCreated; - unsigned numGames = static_cast(m_gameMap.size()); - if (numGames > m_statData.maxGamesOpen) - m_statData.maxGamesOpen = numGames; - m_statDataChanged = true; - } -} - -void -ServerLobbyThread::InternalRemoveGame(boost::shared_ptr game) -{ - // Remove game from list. - m_gameMap.erase(game->GetId()); - // Remove all sessions left in the game. - game->RemoveAllSessions(); - // Notify all players. - boost::shared_ptr packet = CreateNetPacketGameListUpdate(game->GetId(), GAME_MODE_CLOSED); - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); -} - -void -ServerLobbyThread::InternalKickPlayer(unsigned playerId) -{ - SessionWrapper session = m_sessionManager.GetSessionByUniquePlayerId(playerId); - if (session.sessionData.get()) - SessionError(session, ERR_NET_PLAYER_KICKED); - else - { - // Scan games for the player. - GameMap::iterator i = m_gameMap.begin(); - GameMap::iterator end = m_gameMap.end(); - - while (i != end) - { - boost::shared_ptr tmpGame = i->second; - if (tmpGame->GetPlayerDataByUniqueId(playerId).get()) - { - tmpGame->KickPlayer(playerId); - break; - } - ++i; - } - } -} - -void -ServerLobbyThread::TerminateGames() -{ - GameMap::iterator i = m_gameMap.begin(); - GameMap::iterator end = m_gameMap.end(); - - while (i != end) - { - i->second->SignalTermination(); - i->second->Join(GAME_THREAD_TERMINATE_TIMEOUT); - ++i; - } - m_gameMap.clear(); -} - -void -ServerLobbyThread::HandleNewConnection(boost::shared_ptr connData) -{ - // Create a random session id. - // This id can be used to reconnect to the server if the connection was lost. - //unsigned sessionId; - - // TODO: use randomized method. - //if(!RAND_bytes((unsigned char *)&sessionId, sizeof(sessionId))) - //{ - // RAND_pseudo_bytes((unsigned char *)&sessionId, sizeof(sessionId)); - //} - - // Create a new session. - boost::shared_ptr sessionData(new SessionData(connData->ReleaseSocket(), m_curSessionId++)); - m_sessionManager.AddSession(sessionData); - - if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS) - { - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - m_initTimerSessionMap[sessionData->GetId()] = boost::timers::portable::microsec_timer(); - } - else - { - // Server is full. - // Gracefully close this session. - SessionError(SessionWrapper(sessionData, boost::shared_ptr()), ERR_NET_SERVER_FULL); - } -} - -void -ServerLobbyThread::HandleReAddedSession(SessionWrapper session) -{ - // Remove session from game session list. - m_gameSessionManager.RemoveSession(session.sessionData->GetId()); - - if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS) - { - // Set state (back) to established. - session.sessionData->SetState(SessionData::Established); - // Add session to lobby list. - m_sessionManager.AddSession(session); - } - else - { - // Gracefully close this session. - SessionError(session, ERR_NET_SERVER_FULL); - } -} - -void -ServerLobbyThread::CleanupConnectQueue() -{ - boost::mutex::scoped_lock lock(m_connectQueueMutex); - - // Sockets will be closed automatically. - m_connectQueue.clear(); -} - -void -ServerLobbyThread::SessionError(SessionWrapper session, int errorCode) -{ - if (session.sessionData.get()) - { - SendError(session.sessionData, errorCode); - CloseSession(session); - } -} - -void -ServerLobbyThread::SendError(boost::shared_ptr s, int errorCode) -{ - boost::shared_ptr packet(new NetPacketError); - NetPacketError::Data errorData; - errorData.errorCode = errorCode; - static_cast(packet.get())->SetData(errorData); - GetSender().Send(s, packet); -} - -void -ServerLobbyThread::SendJoinGameFailed(boost::shared_ptr s, int reason) -{ - boost::shared_ptr packet(new NetPacketJoinGameFailed); - NetPacketJoinGameFailed::Data failedData; - failedData.failureCode = reason; - static_cast(packet.get())->SetData(failedData); - GetSender().Send(s, packet); -} - -void -ServerLobbyThread::SendGameList(boost::shared_ptr s) -{ - GameMap::const_iterator game_i = m_gameMap.begin(); - GameMap::const_iterator game_end = m_gameMap.end(); - while (game_i != game_end) - { - GetSender().Send(s, CreateNetPacketGameListNew(*game_i->second)); - ++game_i; - } -} - -void -ServerLobbyThread::UpdateStatisticsNumberOfPlayers() -{ - ServerStats stats; - unsigned curNumberOfPlayersOnServer = m_sessionManager.GetRawSessionCount() + m_gameSessionManager.GetRawSessionCount(); - { - boost::mutex::scoped_lock lock(m_statMutex); - if (curNumberOfPlayersOnServer != m_statData.numberOfPlayersOnServer) - { - m_statData.numberOfPlayersOnServer = stats.numberOfPlayersOnServer = curNumberOfPlayersOnServer; - if (curNumberOfPlayersOnServer > m_statData.maxPlayersLoggedIn) - m_statData.maxPlayersLoggedIn = curNumberOfPlayersOnServer; - m_statDataChanged = true; - } - } - // Do not send other stats than number of players for now. - BroadcastStatisticsUpdate(stats); -} - -void -ServerLobbyThread::BroadcastStatisticsUpdate(const ServerStats &stats) -{ - if (stats.numberOfPlayersOnServer) - { - boost::shared_ptr packet(new NetPacketStatisticsChanged); - NetPacketStatisticsChanged::Data statData; - statData.stats = stats; - try { - static_cast(packet.get())->SetData(statData); - - m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); - m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); - } catch (const NetException &) - { - // Ignore errors for now. - //LOG_ERROR("ServerLobbyThread::BroadcastStatisticsUpdate: " << e.what()); - } - } -} - -void -ServerLobbyThread::ReadStatisticsFile() -{ - ifstream i(m_statisticsFileName.c_str(), ios_base::in); - - if (!i.fail() && !i.eof()) - { - boost::mutex::scoped_lock lock(m_statMutex); - do - { - string statisticsType; - unsigned statisticsValue; - i >> statisticsType; - i >> statisticsValue; - if (statisticsType == SERVER_STATISTICS_STR_TOTAL_PLAYERS) - m_statData.totalPlayersEverLoggedIn = statisticsValue; - else if (statisticsType == SERVER_STATISTICS_STR_TOTAL_GAMES) - m_statData.totalGamesEverCreated = statisticsValue; - else if (statisticsType == SERVER_STATISTICS_STR_MAX_PLAYERS) - m_statData.maxPlayersLoggedIn = statisticsValue; - else if (statisticsType == SERVER_STATISTICS_STR_MAX_GAMES) - m_statData.maxGamesOpen = statisticsValue; - } while (!i.fail() && !i.eof()); - m_statDataChanged = false; - } -} - -void -ServerLobbyThread::SaveStatisticsFile() -{ - if (m_saveStatisticsTimer.elapsed().total_seconds() > SERVER_SAVE_STATISTICS_INTERVAL_SEC) - { - { - boost::mutex::scoped_lock lock(m_statMutex); - if (m_statDataChanged) - { - ofstream o(m_statisticsFileName.c_str(), ios_base::out | ios_base::trunc); - if (!o.fail()) - { - o << SERVER_STATISTICS_STR_TOTAL_PLAYERS " " << m_statData.totalPlayersEverLoggedIn << endl; - o << SERVER_STATISTICS_STR_TOTAL_GAMES " " << m_statData.totalGamesEverCreated << endl; - o << SERVER_STATISTICS_STR_MAX_PLAYERS " " << m_statData.maxPlayersLoggedIn << endl; - o << SERVER_STATISTICS_STR_MAX_GAMES " " << m_statData.maxGamesOpen << endl; - m_statDataChanged = false; - } - } - } - m_saveStatisticsTimer.reset(); - m_saveStatisticsTimer.start(); - } -} - -ServerCallback & -ServerLobbyThread::GetCallback() -{ - return m_gui; -} - -SenderThread & -ServerLobbyThread::GetSender() -{ - assert(m_sender.get()); - return *m_sender; -} - -ReceiverHelper & -ServerLobbyThread::GetReceiver() -{ - assert(m_receiver.get()); - return *m_receiver; -} - -bool -ServerLobbyThread::CheckPassword(const string &password) const -{ - return (password == m_password); -} - -ServerSenderCallback & -ServerLobbyThread::GetSenderCallback() -{ - assert(m_senderCallback.get()); - return *m_senderCallback; -} - -GuiInterface & -ServerLobbyThread::GetGui() -{ - return m_gui; -} - -bool -ServerLobbyThread::IsPlayerConnected(const string &name) -{ - bool retVal = false; - - retVal = m_sessionManager.IsPlayerConnected(name); - - if (!retVal) - retVal = m_gameSessionManager.IsPlayerConnected(name); - - return retVal; -} - -boost::shared_ptr -ServerLobbyThread::CreateNetPacketGameListNew(const ServerGameThread &game) -{ - boost::shared_ptr packet(new NetPacketGameListNew); - NetPacketGameListNew::Data packetData; - packetData.gameId = game.GetId(); - packetData.gameInfo.adminPlayerId = game.GetAdminPlayerId(); - packetData.gameInfo.mode = game.IsRunning() ? GAME_MODE_STARTED : GAME_MODE_CREATED; - packetData.gameInfo.name = game.GetName(); - packetData.gameInfo.data = game.GetGameData(); - packetData.gameInfo.players = game.GetPlayerIdList(); - packetData.gameInfo.isPasswordProtected = game.IsPasswordProtected(); - static_cast(packet.get())->SetData(packetData); - return packet; -} - -boost::shared_ptr -ServerLobbyThread::CreateNetPacketGameListUpdate(unsigned gameId, GameMode mode) -{ - boost::shared_ptr packet(new NetPacketGameListUpdate); - NetPacketGameListUpdate::Data packetData; - packetData.gameId = gameId; - packetData.gameMode = mode; - static_cast(packet.get())->SetData(packetData); - return packet; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. +#define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day +#define SERVER_SAVE_STATISTICS_INTERVAL_SEC 60 +#define SERVER_INIT_SESSION_TIMEOUT_SEC 20 + +#define SERVER_NUM_AVATAR_SENDER_THREADS 1 + +#define SERVER_STATISTICS_FILE_NAME "server_statistics.log" +#define SERVER_STATISTICS_STR_TOTAL_PLAYERS "TotalNumPlayersLoggedIn" +#define SERVER_STATISTICS_STR_TOTAL_GAMES "TotalNumGamesCreated" +#define SERVER_STATISTICS_STR_MAX_GAMES "MaxGamesOpen" +#define SERVER_STATISTICS_STR_MAX_PLAYERS "MaxPlayersLoggedIn" + +using namespace std; + + +class ServerSenderCallback : public SenderCallback +{ +public: + ServerSenderCallback(ServerLobbyThread &server) : m_server(server) {} + virtual ~ServerSenderCallback() {} + + virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/) + { + // We just ignore send errors for now, on server side. + // A serious send error should trigger a read error or a read + // returning 0 afterwards, and we will handle this error. + } + +private: + ServerLobbyThread &m_server; +}; + + +ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager) +: m_gui(gui), m_avatarManager(avatarManager), m_playerConfig(playerConfig), + m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1), + m_statDataChanged(false) +{ + m_senderCallback.reset(new ServerSenderCallback(*this)); + m_sender.reset(new SenderThread(GetSenderCallback())); + for (int i = 0; i < SERVER_NUM_AVATAR_SENDER_THREADS; i++) + m_avatarSenderThreadPool.push_back(boost::shared_ptr(new SenderThread(GetSenderCallback()))); + m_receiver.reset(new ReceiverHelper); +} + +ServerLobbyThread::~ServerLobbyThread() +{ + CleanupConnectQueue(); +} + +void +ServerLobbyThread::Init(const string &pwd, const string &logDir) +{ + m_password = pwd; + // Read previous server statistics. + if (!logDir.empty()) + { + boost::filesystem::path logPath(logDir); + if (!logDir.empty()) + { + logPath /= SERVER_STATISTICS_FILE_NAME; + m_statisticsFileName = logPath.directory_string(); + ReadStatisticsFile(); + } + } +} + +void +ServerLobbyThread::AddConnection(boost::shared_ptr data) +{ + boost::mutex::scoped_lock lock(m_connectQueueMutex); + m_connectQueue.push_back(data); +} + +void +ServerLobbyThread::ReAddSession(SessionWrapper session, int reason) +{ + boost::shared_ptr packet(new NetPacketRemovedFromGame); + NetPacketRemovedFromGame::Data removedData; + removedData.removeReason = reason; + static_cast(packet.get())->SetData(removedData); + GetSender().Send(session.sessionData, packet); + + boost::mutex::scoped_lock lock(m_sessionQueueMutex); + m_sessionQueue.push_back(session); +} + +void +ServerLobbyThread::MoveSessionToGame(ServerGameThread &game, SessionWrapper session) +{ + // Remove session from the lobby. + m_sessionManager.RemoveSession(session.sessionData->GetId()); + // Session is now in game state. + session.sessionData->SetState(SessionData::Game); + // Store it in the list of game sessions. + m_gameSessionManager.AddSession(session); + // Add session to the game. + game.AddSession(session); +} + +void +ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session) +{ + // Just remove the session. Only for fatal errors. + CloseSession(session); +} + +void +ServerLobbyThread::CloseSession(SessionWrapper session) +{ + { + boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); + m_initTimerSessionMap.erase(session.sessionData->GetId()); + } + m_sessionManager.RemoveSession(session.sessionData->GetId()); + m_gameSessionManager.RemoveSession(session.sessionData->GetId()); + + // Update stats (if needed). + UpdateStatisticsNumberOfPlayers(); +} + +void +ServerLobbyThread::NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId) +{ + // Send notification to players in lobby. + boost::shared_ptr packet(new NetPacketGameListPlayerJoined); + NetPacketGameListPlayerJoined::Data packetData; + packetData.gameId = gameId; + packetData.playerId = playerId; + static_cast(packet.get())->SetData(packetData); + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); +} + +void +ServerLobbyThread::NotifyPlayerLeftGame(unsigned gameId, unsigned playerId) +{ + // Send notification to players in lobby. + boost::shared_ptr packet(new NetPacketGameListPlayerLeft); + NetPacketGameListPlayerLeft::Data packetData; + packetData.gameId = gameId; + packetData.playerId = playerId; + static_cast(packet.get())->SetData(packetData); + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); +} + +void +ServerLobbyThread::NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId) +{ + // Send notification to players in lobby. + boost::shared_ptr packet(new NetPacketGameListAdminChanged); + NetPacketGameListAdminChanged::Data packetData; + packetData.gameId = gameId; + packetData.newAdminplayerId = newAdminPlayerId; + static_cast(packet.get())->SetData(packetData); + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); +} + +void +ServerLobbyThread::NotifyStartingGame(unsigned gameId) +{ + boost::shared_ptr packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_STARTED); + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); +} + +void +ServerLobbyThread::NotifyReopeningGame(unsigned gameId) +{ + boost::shared_ptr packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_CREATED); + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); +} + +void +ServerLobbyThread::HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket) +{ + // Someone within a game requested player info. + HandleNetPacketRetrievePlayerInfo(session, tmpPacket); +} + +void +ServerLobbyThread::HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket) +{ + // Someone within a game requested an avatar. + HandleNetPacketRetrieveAvatar(session, tmpPacket); +} + +bool +ServerLobbyThread::KickPlayerByName(const std::string &playerName) +{ + bool retVal = false; + SessionWrapper session = m_sessionManager.GetSessionByPlayerName(playerName); + if (!session.sessionData.get()) + session = m_gameSessionManager.GetSessionByPlayerName(playerName); + + if (session.sessionData.get() && session.playerData.get()) + { + boost::mutex::scoped_lock lock(m_kickPlayerListMutex); + m_kickPlayerList.push_back(session.playerData->GetUniqueId()); + retVal = true; + } + + return retVal; +} + +void +ServerLobbyThread::AddComputerPlayer(boost::shared_ptr player) +{ + boost::mutex::scoped_lock lock(m_computerPlayersMutex); + m_computerPlayers.insert(PlayerDataMap::value_type(player->GetUniqueId(), player)); +} + +void +ServerLobbyThread::RemoveComputerPlayer(boost::shared_ptr player) +{ + boost::mutex::scoped_lock lock(m_computerPlayersMutex); + m_computerPlayers.erase(player->GetUniqueId()); +} + +void +ServerLobbyThread::RemoveGame(unsigned id) +{ + boost::mutex::scoped_lock lock(m_removeGameListMutex); + m_removeGameList.push_back(id); +} + +AvatarManager & +ServerLobbyThread::GetAvatarManager() +{ + return m_avatarManager; +} + +ServerStats +ServerLobbyThread::GetStats() const +{ + boost::mutex::scoped_lock lock(m_statMutex); + return m_statData; +} + +u_int32_t +ServerLobbyThread::GetNextUniquePlayerId() +{ + boost::mutex::scoped_lock lock(m_curUniquePlayerIdMutex); + return m_curUniquePlayerId++; +} + +u_int32_t +ServerLobbyThread::GetNextGameId() +{ + return m_curGameId++; +} + +void +ServerLobbyThread::Main() +{ + GetSender().Run(); + for_each(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), boost::mem_fn(&SenderThread::Run)); + + try + { + while (!ShouldTerminate()) + { + // Process new connections. + NewConnectionLoop(); + // Process re-added sessions. + NewSessionLoop(); + // Main loop. + ProcessLoop(); + // Close sessions. + CloseSessionLoop(); + // Remove games. + RemoveGameLoop(); + // Kick players. + KickPlayerLoop(); + // Cleanup cache. + CleanupAvatarCache(); + // Save statistics if needed. + SaveStatisticsFile(); + } + } catch (const PokerTHException &e) + { + GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); + LOG_ERROR(e.what()); + } + + TerminateGames(); + + GetSender().SignalTermination(); + for_each(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), boost::mem_fn(&SenderThread::SignalTermination)); + + GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); + for_each(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), boost::bind(&SenderThread::Join, _1, SENDER_THREAD_TERMINATE_TIMEOUT)); + + CleanupConnectQueue(); +} + +void +ServerLobbyThread::ProcessLoop() +{ + // Wait for data. + SessionWrapper session = m_sessionManager.Select(RECV_TIMEOUT_MSEC); + + if (session.sessionData.get()) + { + boost::shared_ptr packet; + try + { + // Receive the next packet. + packet = GetReceiver().Recv(session.sessionData->GetSocket(), session.sessionData->GetReceiveBuffer()); + } catch (const NetException &) + { + // On error: Close this session. + CloseSession(session); + return; + } + if (packet.get()) + { + if (session.sessionData->GetState() == SessionData::Init) + { + if (packet->ToNetPacketInit()) + HandleNetPacketInit(session, *packet->ToNetPacketInit()); + else if (packet->ToNetPacketAvatarHeader()) + HandleNetPacketAvatarHeader(session, *packet->ToNetPacketAvatarHeader()); + else if (packet->ToNetPacketUnknownAvatar()) + HandleNetPacketUnknownAvatar(session, *packet->ToNetPacketUnknownAvatar()); + else + SessionError(session, ERR_SOCK_INVALID_STATE); + } + else if (session.sessionData->GetState() == SessionData::ReceivingAvatar) + { + if (packet->ToNetPacketAvatarFile()) + HandleNetPacketAvatarFile(session, *packet->ToNetPacketAvatarFile()); + else if (packet->ToNetPacketAvatarEnd()) + HandleNetPacketAvatarEnd(session, *packet->ToNetPacketAvatarEnd()); + else + SessionError(session, ERR_SOCK_INVALID_STATE); + } + else + { + if (packet->ToNetPacketRetrievePlayerInfo()) + HandleNetPacketRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo()); + else if (packet->ToNetPacketRetrieveAvatar()) + HandleNetPacketRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); + else if (packet->ToNetPacketCreateGame()) + HandleNetPacketCreateGame(session, *packet->ToNetPacketCreateGame()); + else if (packet->ToNetPacketJoinGame()) + HandleNetPacketJoinGame(session, *packet->ToNetPacketJoinGame()); + else + SessionError(session, ERR_SOCK_INVALID_STATE); + } + } + } +} + +void +ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketInit &tmpPacket) +{ + NetPacketInit::Data initData; + tmpPacket.GetData(initData); + + // Check the protocol version. + if (initData.versionMajor != NET_VERSION_MAJOR) + { + SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); + return; + } + + // Check the server password. + if (!CheckPassword(initData.password)) + { + SessionError(session, ERR_NET_INVALID_PASSWORD); + return; + } + + // Check whether the player name is correct. + // Partly, this is also done in netpacket. + // However, some disallowed names are checked only here. + if (initData.playerName.empty() || initData.playerName.size() > MAX_NAME_SIZE + || initData.playerName[0] == '#' + || initData.playerName[0] == ' ' + || initData.playerName.substr(0, sizeof(SERVER_COMPUTER_PLAYER_NAME) - 1) == SERVER_COMPUTER_PLAYER_NAME) + { + SessionError(session, ERR_NET_INVALID_PLAYER_NAME); + return; + } + + // Check whether this player is already connected. + if (IsPlayerConnected(initData.playerName)) + { + SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); + return; + } + + // Create player data object. + boost::shared_ptr tmpPlayerData( + new PlayerData(GetNextUniquePlayerId(), 0, PLAYER_TYPE_HUMAN, PLAYER_RIGHTS_NORMAL)); + tmpPlayerData->SetName(initData.playerName); + tmpPlayerData->SetNetSessionData(session.sessionData); + if (initData.showAvatar) + tmpPlayerData->SetAvatarMD5(initData.avatar); + + // Set player data for session. + m_sessionManager.SetSessionPlayerData(session.sessionData->GetId(), tmpPlayerData); + session.playerData = tmpPlayerData; + + if (initData.showAvatar && !initData.avatar.IsZero() && !GetAvatarManager().HasAvatar(initData.avatar)) + RequestPlayerAvatar(session); + else + EstablishSession(session); +} + +void +ServerLobbyThread::HandleNetPacketAvatarHeader(SessionWrapper session, const NetPacketAvatarHeader &tmpPacket) +{ + if (session.playerData.get()) + { + NetPacketAvatarHeader::Data headerData; + tmpPacket.GetData(headerData); + + if (headerData.avatarFileSize >= MIN_AVATAR_FILE_SIZE && headerData.avatarFileSize <= MAX_AVATAR_FILE_SIZE) + { + boost::shared_ptr tmpAvatarData(new AvatarData); + tmpAvatarData->fileData.reserve(headerData.avatarFileSize); + tmpAvatarData->fileType = headerData.avatarFileType; + tmpAvatarData->reportedSize = headerData.avatarFileSize; + // Ignore request id for now. + + session.playerData->SetNetAvatarData(tmpAvatarData); + + // Session is now receiving an avatar. + session.sessionData->SetState(SessionData::ReceivingAvatar); + } + else + SessionError(session, ERR_NET_AVATAR_TOO_LARGE); + } +} + +void +ServerLobbyThread::HandleNetPacketUnknownAvatar(SessionWrapper session, const NetPacketUnknownAvatar &/*tmpPacket*/) +{ + if (session.playerData.get()) + { + // Free memory (just in case). + session.playerData->SetNetAvatarData(boost::shared_ptr()); + session.playerData->SetAvatarMD5(MD5Buf()); + // Start session. + EstablishSession(session); + } +} + +void +ServerLobbyThread::HandleNetPacketAvatarFile(SessionWrapper session, const NetPacketAvatarFile &tmpPacket) +{ + if (session.playerData.get()) + { + NetPacketAvatarFile::Data data; + tmpPacket.GetData(data); + + boost::shared_ptr tmpAvatar = session.playerData->GetNetAvatarData(); + if (tmpAvatar.get() && tmpAvatar->fileData.size() + data.fileData.size() <= tmpAvatar->reportedSize) + { + std::copy(data.fileData.begin(), data.fileData.end(), back_inserter(tmpAvatar->fileData)); + } + } +} + +void +ServerLobbyThread::HandleNetPacketAvatarEnd(SessionWrapper session, const NetPacketAvatarEnd &/*tmpPacket*/) +{ + if (session.playerData.get()) + { + boost::shared_ptr tmpAvatar = session.playerData->GetNetAvatarData(); + MD5Buf avatarMD5 = session.playerData->GetAvatarMD5(); + if (!avatarMD5.IsZero() && tmpAvatar.get()) + { + unsigned avatarSize = (unsigned)tmpAvatar->fileData.size(); + if (avatarSize == tmpAvatar->reportedSize) + { + if (!GetAvatarManager().StoreAvatarInCache(avatarMD5, tmpAvatar->fileType, &tmpAvatar->fileData[0], avatarSize)) + { + session.playerData->SetAvatarMD5(MD5Buf()); + LOG_ERROR("Failed to store avatar in cache directory."); + } + + // Free memory. + session.playerData->SetNetAvatarData(boost::shared_ptr()); + // Init finished - start session. + EstablishSession(session); + } + else + SessionError(session, ERR_NET_WRONG_AVATAR_SIZE); + } + } +} + +void +ServerLobbyThread::HandleNetPacketRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket) +{ + NetPacketRetrievePlayerInfo::Data request; + tmpPacket.GetData(request); + + // Find player in lobby or in a game. + boost::shared_ptr tmpPlayer = m_sessionManager.GetSessionByUniquePlayerId(request.playerId).playerData; + if (!tmpPlayer.get()) + tmpPlayer = m_gameSessionManager.GetSessionByUniquePlayerId(request.playerId).playerData; + if (!tmpPlayer.get()) + { + boost::mutex::scoped_lock lock(m_computerPlayersMutex); + PlayerDataMap::const_iterator pos = m_computerPlayers.find(request.playerId); + if (pos != m_computerPlayers.end()) + tmpPlayer = pos->second; + } + + if (tmpPlayer.get()) + { + // Send player info to client. + boost::shared_ptr info(new NetPacketPlayerInfo); + NetPacketPlayerInfo::Data infoData; + infoData.playerId = tmpPlayer->GetUniqueId(); + infoData.playerInfo.ptype = tmpPlayer->GetType(); + infoData.playerInfo.playerName = tmpPlayer->GetName(); + infoData.playerInfo.hasAvatar = !tmpPlayer->GetAvatarMD5().IsZero(); + if (infoData.playerInfo.hasAvatar) + infoData.playerInfo.avatar = tmpPlayer->GetAvatarMD5(); + static_cast(info.get())->SetData(infoData); + GetSender().Send(session.sessionData, info); + } + else + { + // Unknown player id - notify client. + boost::shared_ptr unknown(new NetPacketUnknownPlayerId); + NetPacketUnknownPlayerId::Data unknownData; + unknownData.playerId = request.playerId; + static_cast(unknown.get())->SetData(unknownData); + GetSender().Send(session.sessionData, unknown); + } +} + +void +ServerLobbyThread::HandleNetPacketRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket) +{ + bool avatarFound = false; + NetPacketRetrieveAvatar::Data request; + tmpPacket.GetData(request); + + string tmpFile; + if (GetAvatarManager().GetAvatarFileName(request.avatar, tmpFile)) + { + NetPacketList tmpPackets; + if (GetAvatarManager().AvatarFileToNetPackets(tmpFile, request.requestId, tmpPackets) == 0) + { + avatarFound = true; + SenderThreadList::iterator pos = min_element(m_avatarSenderThreadPool.begin(), m_avatarSenderThreadPool.end(), *boost::lambda::_1 < *boost::lambda::_2); + if (pos != m_avatarSenderThreadPool.end()) + (*pos)->SendLowPrio(session.sessionData, tmpPackets); + else + LOG_ERROR("Load balancing for avatar sender threads failed."); + } + else + LOG_ERROR("Failed to read avatar file for network transmission."); + } + + if (!avatarFound) + { + // Notify client we didn't find the avatar. + boost::shared_ptr unknown(new NetPacketUnknownAvatar); + NetPacketUnknownAvatar::Data unknownData; + unknownData.requestId = request.requestId; + static_cast(unknown.get())->SetData(unknownData); + GetSender().Send(session.sessionData, unknown); + } +} + +void +ServerLobbyThread::HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket) +{ + // Create a new game. + NetPacketCreateGame::Data createGameData; + tmpPacket.GetData(createGameData); + + boost::shared_ptr game( + new ServerGameThread( + *this, + GetNextGameId(), + createGameData.gameName, + createGameData.password, + createGameData.gameData, + session.playerData->GetUniqueId(), + GetGui(), + m_playerConfig)); + + MoveSessionToGame(*game, session); + + // Add game to list of games. + InternalAddGame(game); + + // Start the game. + game->Run(); +} + +void +ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket) +{ + // Join an existing game. + NetPacketJoinGame::Data joinGameData; + tmpPacket.GetData(joinGameData); + + GameMap::iterator pos = m_gameMap.find(joinGameData.gameId); + + if (pos != m_gameMap.end()) + { + ServerGameThread &game = *pos->second; + if (game.CheckPassword(joinGameData.password)) + { + MoveSessionToGame(game, session); + } + else + { + SendJoinGameFailed(session.sessionData, NTF_NET_JOIN_INVALID_PASSWORD); + } + } + else + { + SessionError(session, ERR_NET_UNKNOWN_GAME); + } +} + +void +ServerLobbyThread::EstablishSession(SessionWrapper session) +{ + if (!session.playerData.get()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + // Send ACK to client. + boost::shared_ptr initAck(new NetPacketInitAck); + NetPacketInitAck::Data initAckData; + initAckData.latestGameVersion = POKERTH_VERSION; + initAckData.latestBetaRevision = POKERTH_BETA_REVISION; + initAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused. + initAckData.playerId = session.playerData->GetUniqueId(); + static_cast(initAck.get())->SetData(initAckData); + GetSender().Send(session.sessionData, initAck); + + // Send the game list to the client. + SendGameList(session.sessionData); + + // Session is now established. + { + boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); + m_initTimerSessionMap.erase(session.sessionData->GetId()); + } + session.sessionData->SetState(SessionData::Established); + + { + boost::mutex::scoped_lock lock(m_statMutex); + ++m_statData.totalPlayersEverLoggedIn; + m_statDataChanged = true; + } + UpdateStatisticsNumberOfPlayers(); +} + +void +ServerLobbyThread::RequestPlayerAvatar(SessionWrapper session) +{ + if (!session.playerData.get()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + // Ask the client to send its avatar. + boost::shared_ptr retrieveAvatar(new NetPacketRetrieveAvatar); + NetPacketRetrieveAvatar::Data retrieveAvatarData; + retrieveAvatarData.requestId = session.playerData->GetUniqueId(); + retrieveAvatarData.avatar = session.playerData->GetAvatarMD5(); + static_cast(retrieveAvatar.get())->SetData(retrieveAvatarData); + GetSender().Send(session.sessionData, retrieveAvatar); +} + +void +ServerLobbyThread::NewConnectionLoop() +{ + // Handle one incoming connection at a time. + boost::shared_ptr tmpData; + { + boost::mutex::scoped_lock lock(m_connectQueueMutex); + if (!m_connectQueue.empty()) + { + tmpData = m_connectQueue.front(); + m_connectQueue.pop_front(); + } + } + if (tmpData.get()) + HandleNewConnection(tmpData); +} + +void +ServerLobbyThread::NewSessionLoop() +{ + // Handle one incoming session at a time. + SessionWrapper tmpSession; + { + boost::mutex::scoped_lock lock(m_sessionQueueMutex); + if (!m_sessionQueue.empty()) + { + tmpSession = m_sessionQueue.front(); + m_sessionQueue.pop_front(); + } + } + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + HandleReAddedSession(tmpSession); +} + +void +ServerLobbyThread::CloseSessionLoop() +{ + boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); + InitTimerSessionMap::iterator i = m_initTimerSessionMap.begin(); + InitTimerSessionMap::iterator end = m_initTimerSessionMap.end(); + + // Remove sessions if they do not initialize within a certain period. + while (i != end) + { + InitTimerSessionMap::iterator next = i; + ++next; + if (i->second.elapsed().total_seconds() > SERVER_INIT_SESSION_TIMEOUT_SEC) + { + m_sessionManager.RemoveSession(i->first); + m_initTimerSessionMap.erase(i); + } + i = next; + } +} + +void +ServerLobbyThread::RemoveGameLoop() +{ + boost::mutex::scoped_lock lock(m_removeGameListMutex); + + RemoveGameList::iterator i = m_removeGameList.begin(); + RemoveGameList::iterator end = m_removeGameList.end(); + + // Synchronously remove games which have been closed. + while (i != end) + { + GameMap::iterator pos = m_gameMap.find(*i); + if (pos != m_gameMap.end()) + { + boost::shared_ptr tmpGame = pos->second; + tmpGame->SignalTermination(); + if (!tmpGame->Join(GAME_THREAD_TERMINATE_TIMEOUT)) + throw ServerException(__FILE__, __LINE__, ERR_NET_GAME_TERMINATION_FAILED, 0); + InternalRemoveGame(tmpGame); + } + ++i; + } + m_removeGameList.clear(); +} + +void +ServerLobbyThread::KickPlayerLoop() +{ + boost::mutex::scoped_lock lock(m_kickPlayerListMutex); + + PlayerIdList::iterator i = m_kickPlayerList.begin(); + PlayerIdList::iterator end = m_kickPlayerList.end(); + + while (i != end) + { + InternalKickPlayer(*i); + ++i; + } + m_kickPlayerList.clear(); +} + +void +ServerLobbyThread::CleanupAvatarCache() +{ + // Only act on timer and if there are no sessions. + if (m_cacheCleanupTimer.elapsed().total_seconds() > SERVER_CACHE_CLEANUP_INTERVAL_SEC + && !m_sessionManager.HasSessions() && !m_gameSessionManager.HasSessions()) + { + m_avatarManager.RemoveOldAvatarCacheEntries(); + m_cacheCleanupTimer.reset(); + m_cacheCleanupTimer.start(); + } +} + +void +ServerLobbyThread::InternalAddGame(boost::shared_ptr game) +{ + // Add game to list. + m_gameMap.insert(GameMap::value_type(game->GetId(), game)); + // Notify all players. + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game); + + { + boost::mutex::scoped_lock lock(m_statMutex); + ++m_statData.totalGamesEverCreated; + unsigned numGames = static_cast(m_gameMap.size()); + if (numGames > m_statData.maxGamesOpen) + m_statData.maxGamesOpen = numGames; + m_statDataChanged = true; + } +} + +void +ServerLobbyThread::InternalRemoveGame(boost::shared_ptr game) +{ + // Remove game from list. + m_gameMap.erase(game->GetId()); + // Remove all sessions left in the game. + game->RemoveAllSessions(); + // Notify all players. + boost::shared_ptr packet = CreateNetPacketGameListUpdate(game->GetId(), GAME_MODE_CLOSED); + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); +} + +void +ServerLobbyThread::InternalKickPlayer(unsigned playerId) +{ + SessionWrapper session = m_sessionManager.GetSessionByUniquePlayerId(playerId); + if (session.sessionData.get()) + SessionError(session, ERR_NET_PLAYER_KICKED); + else + { + // Scan games for the player. + GameMap::iterator i = m_gameMap.begin(); + GameMap::iterator end = m_gameMap.end(); + + while (i != end) + { + boost::shared_ptr tmpGame = i->second; + if (tmpGame->GetPlayerDataByUniqueId(playerId).get()) + { + tmpGame->KickPlayer(playerId); + break; + } + ++i; + } + } +} + +void +ServerLobbyThread::TerminateGames() +{ + GameMap::iterator i = m_gameMap.begin(); + GameMap::iterator end = m_gameMap.end(); + + while (i != end) + { + i->second->SignalTermination(); + i->second->Join(GAME_THREAD_TERMINATE_TIMEOUT); + ++i; + } + m_gameMap.clear(); +} + +void +ServerLobbyThread::HandleNewConnection(boost::shared_ptr connData) +{ + // Create a random session id. + // This id can be used to reconnect to the server if the connection was lost. + //unsigned sessionId; + + // TODO: use randomized method. + //if(!RAND_bytes((unsigned char *)&sessionId, sizeof(sessionId))) + //{ + // RAND_pseudo_bytes((unsigned char *)&sessionId, sizeof(sessionId)); + //} + + // Create a new session. + boost::shared_ptr sessionData(new SessionData(connData->ReleaseSocket(), m_curSessionId++)); + m_sessionManager.AddSession(sessionData); + + if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS) + { + boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); + m_initTimerSessionMap[sessionData->GetId()] = boost::timers::portable::microsec_timer(); + } + else + { + // Server is full. + // Gracefully close this session. + SessionError(SessionWrapper(sessionData, boost::shared_ptr()), ERR_NET_SERVER_FULL); + } +} + +void +ServerLobbyThread::HandleReAddedSession(SessionWrapper session) +{ + // Remove session from game session list. + m_gameSessionManager.RemoveSession(session.sessionData->GetId()); + + if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS) + { + // Set state (back) to established. + session.sessionData->SetState(SessionData::Established); + // Add session to lobby list. + m_sessionManager.AddSession(session); + } + else + { + // Gracefully close this session. + SessionError(session, ERR_NET_SERVER_FULL); + } +} + +void +ServerLobbyThread::CleanupConnectQueue() +{ + boost::mutex::scoped_lock lock(m_connectQueueMutex); + + // Sockets will be closed automatically. + m_connectQueue.clear(); +} + +void +ServerLobbyThread::SessionError(SessionWrapper session, int errorCode) +{ + if (session.sessionData.get()) + { + SendError(session.sessionData, errorCode); + CloseSession(session); + } +} + +void +ServerLobbyThread::SendError(boost::shared_ptr s, int errorCode) +{ + boost::shared_ptr packet(new NetPacketError); + NetPacketError::Data errorData; + errorData.errorCode = errorCode; + static_cast(packet.get())->SetData(errorData); + GetSender().Send(s, packet); +} + +void +ServerLobbyThread::SendJoinGameFailed(boost::shared_ptr s, int reason) +{ + boost::shared_ptr packet(new NetPacketJoinGameFailed); + NetPacketJoinGameFailed::Data failedData; + failedData.failureCode = reason; + static_cast(packet.get())->SetData(failedData); + GetSender().Send(s, packet); +} + +void +ServerLobbyThread::SendGameList(boost::shared_ptr s) +{ + GameMap::const_iterator game_i = m_gameMap.begin(); + GameMap::const_iterator game_end = m_gameMap.end(); + while (game_i != game_end) + { + GetSender().Send(s, CreateNetPacketGameListNew(*game_i->second)); + ++game_i; + } +} + +void +ServerLobbyThread::UpdateStatisticsNumberOfPlayers() +{ + ServerStats stats; + unsigned curNumberOfPlayersOnServer = m_sessionManager.GetRawSessionCount() + m_gameSessionManager.GetRawSessionCount(); + { + boost::mutex::scoped_lock lock(m_statMutex); + if (curNumberOfPlayersOnServer != m_statData.numberOfPlayersOnServer) + { + m_statData.numberOfPlayersOnServer = stats.numberOfPlayersOnServer = curNumberOfPlayersOnServer; + if (curNumberOfPlayersOnServer > m_statData.maxPlayersLoggedIn) + m_statData.maxPlayersLoggedIn = curNumberOfPlayersOnServer; + m_statDataChanged = true; + } + } + // Do not send other stats than number of players for now. + BroadcastStatisticsUpdate(stats); +} + +void +ServerLobbyThread::BroadcastStatisticsUpdate(const ServerStats &stats) +{ + if (stats.numberOfPlayersOnServer) + { + boost::shared_ptr packet(new NetPacketStatisticsChanged); + NetPacketStatisticsChanged::Data statData; + statData.stats = stats; + try { + static_cast(packet.get())->SetData(statData); + + m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); + } catch (const NetException &) + { + // Ignore errors for now. + //LOG_ERROR("ServerLobbyThread::BroadcastStatisticsUpdate: " << e.what()); + } + } +} + +void +ServerLobbyThread::ReadStatisticsFile() +{ + ifstream i(m_statisticsFileName.c_str(), ios_base::in); + + if (!i.fail() && !i.eof()) + { + boost::mutex::scoped_lock lock(m_statMutex); + do + { + string statisticsType; + unsigned statisticsValue; + i >> statisticsType; + i >> statisticsValue; + if (statisticsType == SERVER_STATISTICS_STR_TOTAL_PLAYERS) + m_statData.totalPlayersEverLoggedIn = statisticsValue; + else if (statisticsType == SERVER_STATISTICS_STR_TOTAL_GAMES) + m_statData.totalGamesEverCreated = statisticsValue; + else if (statisticsType == SERVER_STATISTICS_STR_MAX_PLAYERS) + m_statData.maxPlayersLoggedIn = statisticsValue; + else if (statisticsType == SERVER_STATISTICS_STR_MAX_GAMES) + m_statData.maxGamesOpen = statisticsValue; + } while (!i.fail() && !i.eof()); + m_statDataChanged = false; + } +} + +void +ServerLobbyThread::SaveStatisticsFile() +{ + if (m_saveStatisticsTimer.elapsed().total_seconds() > SERVER_SAVE_STATISTICS_INTERVAL_SEC) + { + { + boost::mutex::scoped_lock lock(m_statMutex); + if (m_statDataChanged) + { + ofstream o(m_statisticsFileName.c_str(), ios_base::out | ios_base::trunc); + if (!o.fail()) + { + o << SERVER_STATISTICS_STR_TOTAL_PLAYERS " " << m_statData.totalPlayersEverLoggedIn << endl; + o << SERVER_STATISTICS_STR_TOTAL_GAMES " " << m_statData.totalGamesEverCreated << endl; + o << SERVER_STATISTICS_STR_MAX_PLAYERS " " << m_statData.maxPlayersLoggedIn << endl; + o << SERVER_STATISTICS_STR_MAX_GAMES " " << m_statData.maxGamesOpen << endl; + m_statDataChanged = false; + } + } + } + m_saveStatisticsTimer.reset(); + m_saveStatisticsTimer.start(); + } +} + +ServerCallback & +ServerLobbyThread::GetCallback() +{ + return m_gui; +} + +SenderThread & +ServerLobbyThread::GetSender() +{ + assert(m_sender.get()); + return *m_sender; +} + +ReceiverHelper & +ServerLobbyThread::GetReceiver() +{ + assert(m_receiver.get()); + return *m_receiver; +} + +bool +ServerLobbyThread::CheckPassword(const string &password) const +{ + return (password == m_password); +} + +ServerSenderCallback & +ServerLobbyThread::GetSenderCallback() +{ + assert(m_senderCallback.get()); + return *m_senderCallback; +} + +GuiInterface & +ServerLobbyThread::GetGui() +{ + return m_gui; +} + +bool +ServerLobbyThread::IsPlayerConnected(const string &name) +{ + bool retVal = false; + + retVal = m_sessionManager.IsPlayerConnected(name); + + if (!retVal) + retVal = m_gameSessionManager.IsPlayerConnected(name); + + return retVal; +} + +boost::shared_ptr +ServerLobbyThread::CreateNetPacketGameListNew(const ServerGameThread &game) +{ + boost::shared_ptr packet(new NetPacketGameListNew); + NetPacketGameListNew::Data packetData; + packetData.gameId = game.GetId(); + packetData.gameInfo.adminPlayerId = game.GetAdminPlayerId(); + packetData.gameInfo.mode = game.IsRunning() ? GAME_MODE_STARTED : GAME_MODE_CREATED; + packetData.gameInfo.name = game.GetName(); + packetData.gameInfo.data = game.GetGameData(); + packetData.gameInfo.players = game.GetPlayerIdList(); + packetData.gameInfo.isPasswordProtected = game.IsPasswordProtected(); + static_cast(packet.get())->SetData(packetData); + return packet; +} + +boost::shared_ptr +ServerLobbyThread::CreateNetPacketGameListUpdate(unsigned gameId, GameMode mode) +{ + boost::shared_ptr packet(new NetPacketGameListUpdate); + NetPacketGameListUpdate::Data packetData; + packetData.gameId = gameId; + packetData.gameMode = mode; + static_cast(packet.get())->SetData(packetData); + return packet; +} + diff --git a/src/net/common/sessiondata.cpp b/src/net/common/sessiondata.cpp index a5ae3d31..cd82e060 100644 --- a/src/net/common/sessiondata.cpp +++ b/src/net/common/sessiondata.cpp @@ -1,102 +1,102 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -SessionData::SessionData(SOCKET sockfd, SessionId id) -: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false) -{ -} - -SessionData::~SessionData() -{ - if (m_sockfd != INVALID_SOCKET) - CLOSESOCKET(m_sockfd); -} - -SessionId -SessionData::GetId() const -{ - // const value - no mutex needed. - return m_id; -} - -SessionData::State -SessionData::GetState() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_state; -} - -void -SessionData::SetState(SessionData::State state) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_state = state; -} - -SOCKET -SessionData::GetSocket() const -{ - // value never modified - no mutex needed. - return m_sockfd; -} - -void -SessionData::SetReadyFlag() -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_readyFlag = true; -} - -void -SessionData::ResetReadyFlag() -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_readyFlag = false; -} - -bool -SessionData::IsReady() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_readyFlag; -} - -const std::string & -SessionData::GetClientAddr() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_clientAddr; -} - -void -SessionData::SetClientAddr(const std::string &addr) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_clientAddr = addr; -} - -ReceiveBuffer & -SessionData::GetReceiveBuffer() -{ - // mutex protection, if needed, within buffer. - return m_receiveBuffer; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +SessionData::SessionData(SOCKET sockfd, SessionId id) +: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false) +{ +} + +SessionData::~SessionData() +{ + if (m_sockfd != INVALID_SOCKET) + CLOSESOCKET(m_sockfd); +} + +SessionId +SessionData::GetId() const +{ + // const value - no mutex needed. + return m_id; +} + +SessionData::State +SessionData::GetState() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_state; +} + +void +SessionData::SetState(SessionData::State state) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_state = state; +} + +SOCKET +SessionData::GetSocket() const +{ + // value never modified - no mutex needed. + return m_sockfd; +} + +void +SessionData::SetReadyFlag() +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_readyFlag = true; +} + +void +SessionData::ResetReadyFlag() +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_readyFlag = false; +} + +bool +SessionData::IsReady() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_readyFlag; +} + +const std::string & +SessionData::GetClientAddr() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_clientAddr; +} + +void +SessionData::SetClientAddr(const std::string &addr) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_clientAddr = addr; +} + +ReceiveBuffer & +SessionData::GetReceiveBuffer() +{ + // mutex protection, if needed, within buffer. + return m_receiveBuffer; +} + diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index 942b41e1..10fea918 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -1,403 +1,403 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include - -using namespace std; - - -SessionManager::SessionManager() -{ -} - -SessionManager::~SessionManager() -{ - Clear(); -} - -bool -SessionManager::HasSessions() const -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - return !m_sessionMap.empty(); -} - -void -SessionManager::AddSession(boost::shared_ptr sessionData) -{ - AddSession(SessionWrapper(sessionData, boost::shared_ptr())); -} - -void -SessionManager::AddSession(SessionWrapper session) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::iterator pos = m_sessionMap.lower_bound(session.sessionData->GetId()); - - // If pos points to a pair whose key is equivalent to the socket, this handle - // already exists within the list. - if (pos != m_sessionMap.end() && session.sessionData->GetId() == pos->first) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_CONN_EXISTS, 0); - } - m_sessionMap.insert(pos, SessionMap::value_type(session.sessionData->GetId(), session)); -} - -void -SessionManager::SetSessionPlayerData(SessionId session, boost::shared_ptr playerData) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - SessionMap::iterator pos = m_sessionMap.find(session); - - if (pos != m_sessionMap.end()) - pos->second.playerData = playerData; -} - -void -SessionManager::RemoveSession(SessionId session) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - m_sessionMap.erase(session); -} - -SessionWrapper -SessionManager::Select(unsigned timeoutMsec) -{ - SessionWrapper retSession; - SOCKET maxSock = INVALID_SOCKET; - fd_set rdset; - FD_ZERO(&rdset); - - { - boost::mutex::scoped_lock lock(m_sessionMapMutex); - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - // Collect all sockets. - SOCKET tmpSock = i->second.sessionData->GetSocket(); - FD_SET(tmpSock, &rdset); - if (tmpSock > maxSock || maxSock == INVALID_SOCKET) - maxSock = tmpSock; - - // Check if a packet is available. - if (!i->second.sessionData->GetReceiveBuffer().receivedPackets.empty()) - { - retSession = i->second; - break; - } - ++i; - } - } - - if (!retSession.sessionData.get()) - { - if (maxSock == INVALID_SOCKET) - { - Thread::Msleep(timeoutMsec); // just sleep if there is no session - } - else - { - // wait for data - struct timeval timeout; - timeout.tv_sec = timeoutMsec / 1000; - timeout.tv_usec = (timeoutMsec % 1000) * 1000; - int selectResult = select(maxSock + 1, &rdset, NULL, NULL, &timeout); - if (!IS_VALID_SELECT(selectResult)) - { - throw ServerException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); - } - if (selectResult > 0) // one (or more) of the sockets is readable - { - // Check which socket is readable, return the first. - boost::mutex::scoped_lock lock(m_sessionMapMutex); - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - if (FD_ISSET(i->second.sessionData->GetSocket(), &rdset)) - { - retSession = i->second; - break; - } - ++i; - } - } - } - } - return retSession; -} - -SessionWrapper -SessionManager::GetSessionByPlayerName(const string playerName) const -{ - SessionWrapper tmpSession; - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::const_iterator session_i = m_sessionMap.begin(); - SessionMap::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::Init) - { - boost::shared_ptr tmpPlayer(session_i->second.playerData); - if (!tmpPlayer.get()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - if (tmpPlayer->GetName() == playerName) - { - tmpSession = session_i->second; - break; - } - } - - ++session_i; - } - return tmpSession; -} - -SessionWrapper -SessionManager::GetSessionByUniquePlayerId(unsigned uniqueId) const -{ - SessionWrapper tmpSession; - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::const_iterator session_i = m_sessionMap.begin(); - SessionMap::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::Init) - { - boost::shared_ptr tmpPlayer(session_i->second.playerData); - if (!tmpPlayer.get()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - if (tmpPlayer->GetUniqueId() == uniqueId) - { - tmpSession = session_i->second; - break; - } - } - - ++session_i; - } - return tmpSession; -} - -PlayerDataList -SessionManager::GetPlayerDataList() const -{ - PlayerDataList playerList; - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::const_iterator session_i = m_sessionMap.begin(); - SessionMap::const_iterator session_end = m_sessionMap.end(); - - while (session_i != session_end) - { - // Get all players in the game. - if (session_i->second.sessionData->GetState() == SessionData::Game) - { - boost::shared_ptr tmpPlayer(session_i->second.playerData); - if (!tmpPlayer.get() || tmpPlayer->GetName().empty()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - playerList.push_back(tmpPlayer); - } - ++session_i; - } - return playerList; -} - -PlayerIdList -SessionManager::GetPlayerIdList() const -{ - PlayerIdList playerList; - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::const_iterator session_i = m_sessionMap.begin(); - SessionMap::const_iterator session_end = m_sessionMap.end(); - - while (session_i != session_end) - { - // Get all players in the game. - if (session_i->second.sessionData->GetState() == SessionData::Game) - { - playerList.push_back(session_i->second.playerData->GetUniqueId()); - } - ++session_i; - } - return playerList; -} - -bool -SessionManager::IsPlayerConnected(const string &playerName) const -{ - bool retVal = false; - - SessionWrapper tmpSession = GetSessionByPlayerName(playerName); - - if (tmpSession.sessionData.get() && tmpSession.playerData.get()) - retVal = true; - - return retVal; -} - -bool -SessionManager::IsPlayerConnected(unsigned uniqueId) const -{ - bool retVal = false; - - SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniqueId); - - if (tmpSession.sessionData.get() && tmpSession.playerData.get()) - retVal = true; - - return retVal; -} - -void -SessionManager::ForEach(boost::function func) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - func((*i).second); - ++i; - } -} - -unsigned -SessionManager::CountReadySessions() const -{ - unsigned counter = 0; - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::const_iterator i = m_sessionMap.begin(); - SessionMap::const_iterator end = m_sessionMap.end(); - - while (i != end) - { - if ((*i).second.sessionData->IsReady()) - ++counter; - ++i; - } - return counter; -} - -void -SessionManager::ResetAllReadyFlags() -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - (*i).second.sessionData->ResetReadyFlag(); - ++i; - } -} - -void -SessionManager::Clear() -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - // Sockets will be closed automatically. - m_sessionMap.clear(); -} - -unsigned -SessionManager::GetRawSessionCount() -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - return m_sessionMap.size(); -} - -void -SessionManager::SendToAllSessions(SenderThread &sender, boost::shared_ptr packet, SessionData::State state) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - if (!i->second.sessionData.get()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - - // Send each client (with a certain state) a copy of the packet. - if (i->second.sessionData->GetState() == state) - sender.Send(i->second.sessionData, boost::shared_ptr(packet->Clone())); - ++i; - } -} - -void -SessionManager::SendToAllSessionsLowPrio(SenderThread &sender, boost::shared_ptr packet, SessionData::State state) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - if (!i->second.sessionData.get()) - throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); - - // Send each client (with a certain state) a copy of the packet. - if (i->second.sessionData->GetState() == state) - sender.SendLowPrio(i->second.sessionData, boost::shared_ptr(packet->Clone())); - ++i; - } -} - -void -SessionManager::SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr packet, SessionId except, SessionData::State state) -{ - boost::mutex::scoped_lock lock(m_sessionMapMutex); - - SessionMap::iterator i = m_sessionMap.begin(); - SessionMap::iterator end = m_sessionMap.end(); - - while (i != end) - { - // Send each fully connected client but one a copy of the packet. - if (i->second.sessionData->GetState() == state) - if (i->first != except) - sender.Send(i->second.sessionData, boost::shared_ptr(packet->Clone())); - ++i; - } -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +using namespace std; + + +SessionManager::SessionManager() +{ +} + +SessionManager::~SessionManager() +{ + Clear(); +} + +bool +SessionManager::HasSessions() const +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + return !m_sessionMap.empty(); +} + +void +SessionManager::AddSession(boost::shared_ptr sessionData) +{ + AddSession(SessionWrapper(sessionData, boost::shared_ptr())); +} + +void +SessionManager::AddSession(SessionWrapper session) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator pos = m_sessionMap.lower_bound(session.sessionData->GetId()); + + // If pos points to a pair whose key is equivalent to the socket, this handle + // already exists within the list. + if (pos != m_sessionMap.end() && session.sessionData->GetId() == pos->first) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_CONN_EXISTS, 0); + } + m_sessionMap.insert(pos, SessionMap::value_type(session.sessionData->GetId(), session)); +} + +void +SessionManager::SetSessionPlayerData(SessionId session, boost::shared_ptr playerData) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + SessionMap::iterator pos = m_sessionMap.find(session); + + if (pos != m_sessionMap.end()) + pos->second.playerData = playerData; +} + +void +SessionManager::RemoveSession(SessionId session) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + m_sessionMap.erase(session); +} + +SessionWrapper +SessionManager::Select(unsigned timeoutMsec) +{ + SessionWrapper retSession; + SOCKET maxSock = INVALID_SOCKET; + fd_set rdset; + FD_ZERO(&rdset); + + { + boost::mutex::scoped_lock lock(m_sessionMapMutex); + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + // Collect all sockets. + SOCKET tmpSock = i->second.sessionData->GetSocket(); + FD_SET(tmpSock, &rdset); + if (tmpSock > maxSock || maxSock == INVALID_SOCKET) + maxSock = tmpSock; + + // Check if a packet is available. + if (!i->second.sessionData->GetReceiveBuffer().receivedPackets.empty()) + { + retSession = i->second; + break; + } + ++i; + } + } + + if (!retSession.sessionData.get()) + { + if (maxSock == INVALID_SOCKET) + { + Thread::Msleep(timeoutMsec); // just sleep if there is no session + } + else + { + // wait for data + struct timeval timeout; + timeout.tv_sec = timeoutMsec / 1000; + timeout.tv_usec = (timeoutMsec % 1000) * 1000; + int selectResult = select(maxSock + 1, &rdset, NULL, NULL, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + throw ServerException(__FILE__, __LINE__, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); + } + if (selectResult > 0) // one (or more) of the sockets is readable + { + // Check which socket is readable, return the first. + boost::mutex::scoped_lock lock(m_sessionMapMutex); + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + if (FD_ISSET(i->second.sessionData->GetSocket(), &rdset)) + { + retSession = i->second; + break; + } + ++i; + } + } + } + } + return retSession; +} + +SessionWrapper +SessionManager::GetSessionByPlayerName(const string playerName) const +{ + SessionWrapper tmpSession; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::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::Init) + { + boost::shared_ptr tmpPlayer(session_i->second.playerData); + if (!tmpPlayer.get()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + if (tmpPlayer->GetName() == playerName) + { + tmpSession = session_i->second; + break; + } + } + + ++session_i; + } + return tmpSession; +} + +SessionWrapper +SessionManager::GetSessionByUniquePlayerId(unsigned uniqueId) const +{ + SessionWrapper tmpSession; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::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::Init) + { + boost::shared_ptr tmpPlayer(session_i->second.playerData); + if (!tmpPlayer.get()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + if (tmpPlayer->GetUniqueId() == uniqueId) + { + tmpSession = session_i->second; + break; + } + } + + ++session_i; + } + return tmpSession; +} + +PlayerDataList +SessionManager::GetPlayerDataList() const +{ + PlayerDataList playerList; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) + { + // Get all players in the game. + if (session_i->second.sessionData->GetState() == SessionData::Game) + { + boost::shared_ptr tmpPlayer(session_i->second.playerData); + if (!tmpPlayer.get() || tmpPlayer->GetName().empty()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + playerList.push_back(tmpPlayer); + } + ++session_i; + } + return playerList; +} + +PlayerIdList +SessionManager::GetPlayerIdList() const +{ + PlayerIdList playerList; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) + { + // Get all players in the game. + if (session_i->second.sessionData->GetState() == SessionData::Game) + { + playerList.push_back(session_i->second.playerData->GetUniqueId()); + } + ++session_i; + } + return playerList; +} + +bool +SessionManager::IsPlayerConnected(const string &playerName) const +{ + bool retVal = false; + + SessionWrapper tmpSession = GetSessionByPlayerName(playerName); + + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + retVal = true; + + return retVal; +} + +bool +SessionManager::IsPlayerConnected(unsigned uniqueId) const +{ + bool retVal = false; + + SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniqueId); + + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + retVal = true; + + return retVal; +} + +void +SessionManager::ForEach(boost::function func) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + func((*i).second); + ++i; + } +} + +unsigned +SessionManager::CountReadySessions() const +{ + unsigned counter = 0; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator i = m_sessionMap.begin(); + SessionMap::const_iterator end = m_sessionMap.end(); + + while (i != end) + { + if ((*i).second.sessionData->IsReady()) + ++counter; + ++i; + } + return counter; +} + +void +SessionManager::ResetAllReadyFlags() +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + (*i).second.sessionData->ResetReadyFlag(); + ++i; + } +} + +void +SessionManager::Clear() +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + // Sockets will be closed automatically. + m_sessionMap.clear(); +} + +unsigned +SessionManager::GetRawSessionCount() +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + return m_sessionMap.size(); +} + +void +SessionManager::SendToAllSessions(SenderThread &sender, boost::shared_ptr packet, SessionData::State state) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + if (!i->second.sessionData.get()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + + // Send each client (with a certain state) a copy of the packet. + if (i->second.sessionData->GetState() == state) + sender.Send(i->second.sessionData, boost::shared_ptr(packet->Clone())); + ++i; + } +} + +void +SessionManager::SendToAllSessionsLowPrio(SenderThread &sender, boost::shared_ptr packet, SessionData::State state) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + if (!i->second.sessionData.get()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + + // Send each client (with a certain state) a copy of the packet. + if (i->second.sessionData->GetState() == state) + sender.SendLowPrio(i->second.sessionData, boost::shared_ptr(packet->Clone())); + ++i; + } +} + +void +SessionManager::SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr packet, SessionId except, SessionData::State state) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + // Send each fully connected client but one a copy of the packet. + if (i->second.sessionData->GetState() == state) + if (i->first != except) + sender.Send(i->second.sessionData, boost::shared_ptr(packet->Clone())); + ++i; + } +} + diff --git a/src/net/common/socket_helper_cmn.cpp b/src/net/common/socket_helper_cmn.cpp index 230298a4..e3035447 100644 --- a/src/net/common/socket_helper_cmn.cpp +++ b/src/net/common/socket_helper_cmn.cpp @@ -1,46 +1,46 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include - -using namespace std; - -bool -socket_set_port(unsigned port, int addrFamily, struct sockaddr *addr, int addrLen) -{ - bool retVal = false; - - if (addr) - { - if (addrFamily == AF_INET && addrLen >= (int)sizeof(sockaddr_in)) - { - ((sockaddr_in *)addr)->sin_port = htons(port); - retVal = true; - } - else if (addrFamily == AF_INET6 && addrLen >= (int)sizeof(sockaddr_in6)) - { - ((sockaddr_in6 *)addr)->sin6_port = htons(port); - retVal = true; - } - } - - return retVal; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +using namespace std; + +bool +socket_set_port(unsigned port, int addrFamily, struct sockaddr *addr, int addrLen) +{ + bool retVal = false; + + if (addr) + { + if (addrFamily == AF_INET && addrLen >= (int)sizeof(sockaddr_in)) + { + ((sockaddr_in *)addr)->sin_port = htons(port); + retVal = true; + } + else if (addrFamily == AF_INET6 && addrLen >= (int)sizeof(sockaddr_in6)) + { + ((sockaddr_in6 *)addr)->sin6_port = htons(port); + retVal = true; + } + } + + return retVal; +} + diff --git a/src/net/common/socket_startup_cmn.cpp b/src/net/common/socket_startup_cmn.cpp index 28230967..872ec01d 100644 --- a/src/net/common/socket_startup_cmn.cpp +++ b/src/net/common/socket_startup_cmn.cpp @@ -1,65 +1,65 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include - - -bool -socket_has_sctp() -{ -#ifdef IPPROTO_SCTP - SOCKET test = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); - - if (test == INVALID_SOCKET) - return false; - CLOSESOCKET(test); - return true; -#else - return false; -#endif -} - -bool -socket_has_ipv6() -{ - SOCKET test = socket(AF_INET6, SOCK_STREAM, 0); - - if (test == INVALID_SOCKET) - return false; - CLOSESOCKET(test); - return true; -} - -bool -socket_has_dual_stack() -{ - bool retVal = false; - SOCKET test = socket(AF_INET6, SOCK_STREAM, 0); - - if (test != INVALID_SOCKET) - { - int ipv6only = 0; - if (setsockopt(test, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)) == 0) - retVal = true; - CLOSESOCKET(test); - } - return retVal; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + + +bool +socket_has_sctp() +{ +#ifdef IPPROTO_SCTP + SOCKET test = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (test == INVALID_SOCKET) + return false; + CLOSESOCKET(test); + return true; +#else + return false; +#endif +} + +bool +socket_has_ipv6() +{ + SOCKET test = socket(AF_INET6, SOCK_STREAM, 0); + + if (test == INVALID_SOCKET) + return false; + CLOSESOCKET(test); + return true; +} + +bool +socket_has_dual_stack() +{ + bool retVal = false; + SOCKET test = socket(AF_INET6, SOCK_STREAM, 0); + + if (test != INVALID_SOCKET) + { + int ipv6only = 0; + if (setsockopt(test, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)) == 0) + retVal = true; + CLOSESOCKET(test); + } + return retVal; +} + diff --git a/src/net/connectdata.h b/src/net/connectdata.h index 8cbe6fd1..485ae05c 100644 --- a/src/net/connectdata.h +++ b/src/net/connectdata.h @@ -1,43 +1,43 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Connection data. */ - -#ifndef _CONNECTDATA_H_ -#define _CONNECTDATA_H_ - -#include - -class ConnectData -{ -public: - ConnectData(); - ~ConnectData(); - - SOCKET GetSocket() const - {return m_sockfd;} - void SetSocket(SOCKET sockfd) - {m_sockfd = sockfd;} - - SOCKET ReleaseSocket(); - -private: - SOCKET m_sockfd; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Connection data. */ + +#ifndef _CONNECTDATA_H_ +#define _CONNECTDATA_H_ + +#include + +class ConnectData +{ +public: + ConnectData(); + ~ConnectData(); + + SOCKET GetSocket() const + {return m_sockfd;} + void SetSocket(SOCKET sockfd) + {m_sockfd = sockfd;} + + SOCKET ReleaseSocket(); + +private: + SOCKET m_sockfd; +}; + +#endif diff --git a/src/net/irccallback.h b/src/net/irccallback.h index f7863b4f..4b5ee616 100644 --- a/src/net/irccallback.h +++ b/src/net/irccallback.h @@ -1,42 +1,42 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Callback interface for irc gui. */ - -#ifndef _IRCCALLBACK_H_ -#define _IRCCALLBACK_H_ - -#include - -class IrcCallback -{ -public: - virtual ~IrcCallback(); - - virtual void SignalIrcConnect(const std::string &server) = 0; - virtual void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel) = 0; - virtual void SignalIrcPlayerJoined(const std::string &nickName) = 0; - virtual void SignalIrcPlayerChanged(const std::string &oldNick, const std::string &newNick) = 0; - virtual void SignalIrcPlayerKicked(const std::string &nickName, const std::string &byWhom, const std::string &reason) = 0; - virtual void SignalIrcPlayerLeft(const std::string &nickName) = 0; - virtual void SignalIrcChatMsg(const std::string &nickName, const std::string &msg) = 0; - virtual void SignalIrcError(int errorCode) = 0; - virtual void SignalIrcServerError(int errorCode) = 0; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Callback interface for irc gui. */ + +#ifndef _IRCCALLBACK_H_ +#define _IRCCALLBACK_H_ + +#include + +class IrcCallback +{ +public: + virtual ~IrcCallback(); + + virtual void SignalIrcConnect(const std::string &server) = 0; + virtual void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel) = 0; + virtual void SignalIrcPlayerJoined(const std::string &nickName) = 0; + virtual void SignalIrcPlayerChanged(const std::string &oldNick, const std::string &newNick) = 0; + virtual void SignalIrcPlayerKicked(const std::string &nickName, const std::string &byWhom, const std::string &reason) = 0; + virtual void SignalIrcPlayerLeft(const std::string &nickName) = 0; + virtual void SignalIrcChatMsg(const std::string &nickName, const std::string &msg) = 0; + virtual void SignalIrcError(int errorCode) = 0; + virtual void SignalIrcServerError(int errorCode) = 0; +}; + +#endif diff --git a/src/net/ircthread.h b/src/net/ircthread.h index fac67d82..d9290876 100644 --- a/src/net/ircthread.h +++ b/src/net/ircthread.h @@ -1,64 +1,64 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* IRC thread for the lobby. */ - -#ifndef _IRCTHREAD_H_ -#define _IRCTHREAD_H_ - -#include -#include -#include -#include - -struct IrcContext; - -class IrcThread : public Thread -{ -public: - IrcThread(IrcCallback &callback); - virtual ~IrcThread(); - - // Set the parameters. - void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel, const std::string &channelPassword); - - // Send a chat message to the channel. - void SendChatMessage(const std::string &msg); - - virtual void SignalTermination(); - - IrcCallback &GetCallback(); - -protected: - - // Main function of the thread. - virtual void Main(); - - void HandleIrcError(int errorCode); - - const IrcContext &GetContext() const; - IrcContext &GetContext(); - -private: - boost::shared_ptr m_context; - IrcCallback &m_callback; - - boost::timers::portable::microsec_timer m_terminationTimer; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* IRC thread for the lobby. */ + +#ifndef _IRCTHREAD_H_ +#define _IRCTHREAD_H_ + +#include +#include +#include +#include + +struct IrcContext; + +class IrcThread : public Thread +{ +public: + IrcThread(IrcCallback &callback); + virtual ~IrcThread(); + + // Set the parameters. + void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel, const std::string &channelPassword); + + // Send a chat message to the channel. + void SendChatMessage(const std::string &msg); + + virtual void SignalTermination(); + + IrcCallback &GetCallback(); + +protected: + + // Main function of the thread. + virtual void Main(); + + void HandleIrcError(int errorCode); + + const IrcContext &GetContext() const; + IrcContext &GetContext(); + +private: + boost::shared_ptr m_context; + IrcCallback &m_callback; + + boost::timers::portable::microsec_timer m_terminationTimer; +}; + +#endif diff --git a/src/net/linux/socket_helper.cpp b/src/net/linux/socket_helper.cpp index 13d23c07..83a08e6f 100644 --- a/src/net/linux/socket_helper.cpp +++ b/src/net/linux/socket_helper.cpp @@ -1,68 +1,68 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifdef _WIN32 -#error This source code is not for Win32. -#endif - -#include - - -bool -socket_string_to_addr(const char *str, int addrFamily, struct sockaddr *addr, int /*addrLen*/) -{ - if (addrFamily == AF_INET) - return (inet_pton(addrFamily, str, &((struct sockaddr_in *)addr)->sin_addr) == 1); - else if (addrFamily == AF_INET6) - return (inet_pton(addrFamily, str, &((struct sockaddr_in6 *)addr)->sin6_addr) == 1); - else - return false; -} - -bool -socket_resolve(const char *str, const char *port, int addrFamily, int sockType, int protocol, struct sockaddr *addr, int addrLen) -{ - bool retVal = false; - - if (str && *str != 0) - { - struct addrinfo aiHints; - struct addrinfo *aiList = NULL; - - memset(&aiHints, 0, sizeof(aiHints)); - aiHints.ai_family = addrFamily; - aiHints.ai_socktype = sockType; - aiHints.ai_protocol = protocol; - - // Try to resolve the name. - // Will (hopefully) use UTF-8 if called on Linux. - bool success = (getaddrinfo(str, port, &aiHints, &aiList) == 0); - - if (success && aiList) - { - if ((int)aiList->ai_addrlen <= addrLen) - { - memcpy(addr, aiList->ai_addr, aiList->ai_addrlen); - retVal = true; - } - freeaddrinfo(aiList); - } - } - return retVal; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef _WIN32 +#error This source code is not for Win32. +#endif + +#include + + +bool +socket_string_to_addr(const char *str, int addrFamily, struct sockaddr *addr, int /*addrLen*/) +{ + if (addrFamily == AF_INET) + return (inet_pton(addrFamily, str, &((struct sockaddr_in *)addr)->sin_addr) == 1); + else if (addrFamily == AF_INET6) + return (inet_pton(addrFamily, str, &((struct sockaddr_in6 *)addr)->sin6_addr) == 1); + else + return false; +} + +bool +socket_resolve(const char *str, const char *port, int addrFamily, int sockType, int protocol, struct sockaddr *addr, int addrLen) +{ + bool retVal = false; + + if (str && *str != 0) + { + struct addrinfo aiHints; + struct addrinfo *aiList = NULL; + + memset(&aiHints, 0, sizeof(aiHints)); + aiHints.ai_family = addrFamily; + aiHints.ai_socktype = sockType; + aiHints.ai_protocol = protocol; + + // Try to resolve the name. + // Will (hopefully) use UTF-8 if called on Linux. + bool success = (getaddrinfo(str, port, &aiHints, &aiList) == 0); + + if (success && aiList) + { + if ((int)aiList->ai_addrlen <= addrLen) + { + memcpy(addr, aiList->ai_addr, aiList->ai_addrlen); + retVal = true; + } + freeaddrinfo(aiList); + } + } + return retVal; +} + diff --git a/src/net/netcontext.h b/src/net/netcontext.h index 04e5c7db..496c90c5 100644 --- a/src/net/netcontext.h +++ b/src/net/netcontext.h @@ -1,36 +1,36 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network context data. */ - -#ifndef _NETCONTEXT_H_ -#define _NETCONTEXT_H_ - -#include -#include - - -class NetContext -{ -public: - virtual ~NetContext(); - - virtual SOCKET GetSocket() const = 0; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network context data. */ + +#ifndef _NETCONTEXT_H_ +#define _NETCONTEXT_H_ + +#include +#include + + +class NetContext +{ +public: + virtual ~NetContext(); + + virtual SOCKET GetSocket() const = 0; +}; + +#endif diff --git a/src/net/netexception.h b/src/net/netexception.h index dd0e40e3..c3f2b3b9 100644 --- a/src/net/netexception.h +++ b/src/net/netexception.h @@ -1,35 +1,35 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Exception class for network errors. */ - -#ifndef _NETEXCEPTION_H_ -#define _NETEXCEPTION_H_ - -#include "pokerthexception.h" - -class NetException : public PokerTHException -{ -public: - - NetException(const char *sourcefile, int sourceline, int errorId, int osErrorCode) - : PokerTHException(sourcefile, sourceline, errorId, osErrorCode) {} - virtual ~NetException() throw(); -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Exception class for network errors. */ + +#ifndef _NETEXCEPTION_H_ +#define _NETEXCEPTION_H_ + +#include "pokerthexception.h" + +class NetException : public PokerTHException +{ +public: + + NetException(const char *sourcefile, int sourceline, int errorId, int osErrorCode) + : PokerTHException(sourcefile, sourceline, errorId, osErrorCode) {} + virtual ~NetException() throw(); +}; + +#endif diff --git a/src/net/netpacket.h b/src/net/netpacket.h index 1e06803f..5dcab030 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -1,1243 +1,1243 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* PokerTH network packet. */ - -#ifndef _NETPACKET_H_ -#define _NETPACKET_H_ - -#include -#include -#include -#include -#include - -#include -#include - -#define NET_VERSION_MAJOR 2 -#define NET_VERSION_MINOR 0 - -#define MIN_PACKET_SIZE 4 -#define MAX_PACKET_SIZE 268 -#define MAX_NAME_SIZE 64 -#define MAX_PASSWORD_SIZE 64 -#define MAX_NUM_MANUAL_BLINDS 30 -#define MAX_CHAT_TEXT_SIZE 128 -#define MAX_FILE_DATA_SIZE 256 -#define MAX_NUM_PLAYER_RESULTS MAX_NUMBER_OF_PLAYERS -#define MAX_NUM_PLAYER_CARDS MAX_NUMBER_OF_PLAYERS - - -struct NetPacketHeader; - -class NetPacketInit; -class NetPacketInitAck; -class NetPacketRetrieveAvatar; -class NetPacketAvatarHeader; -class NetPacketAvatarFile; -class NetPacketAvatarEnd; -class NetPacketUnknownAvatar; -class NetPacketGameListNew; -class NetPacketGameListUpdate; -class NetPacketGameListPlayerJoined; -class NetPacketGameListPlayerLeft; -class NetPacketGameListAdminChanged; -class NetPacketRetrievePlayerInfo; -class NetPacketPlayerInfo; -class NetPacketUnknownPlayerId; -class NetPacketCreateGame; -class NetPacketJoinGame; -class NetPacketJoinGameAck; -class NetPacketJoinGameFailed; -class NetPacketPlayerJoined; -class NetPacketPlayerLeft; -class NetPacketGameAdminChanged; -class NetPacketKickPlayer; -class NetPacketLeaveCurrentGame; -class NetPacketStartEvent; -class NetPacketStartEventAck; -class NetPacketGameStart; -class NetPacketHandStart; -class NetPacketPlayersTurn; -class NetPacketPlayersAction; -class NetPacketPlayersActionDone; -class NetPacketPlayersActionRejected; -class NetPacketDealFlopCards; -class NetPacketDealTurnCard; -class NetPacketDealRiverCard; -class NetPacketAllInShowCards; -class NetPacketEndOfHandShowCards; -class NetPacketEndOfHandHideCards; -class NetPacketEndOfGame; -class NetPacketStatisticsChanged; -class NetPacketRemovedFromGame; -class NetPacketSendChatText; -class NetPacketChatText; -class NetPacketError; - -class NetPacket -{ -public: - static boost::shared_ptr Create(char *data, unsigned &dataSize); - - NetPacket(u_int16_t type, u_int16_t initialSize, u_int16_t maxSize); - virtual ~NetPacket(); - - virtual boost::shared_ptr Clone() const = 0; - - const NetPacketHeader *GetRawData() const; - NetPacketHeader *GetRawData(); - void SetRawData(const NetPacketHeader *p); - - u_int16_t GetType() const; - u_int16_t GetLen() const; - - virtual const NetPacketInit *ToNetPacketInit() const; - virtual const NetPacketInitAck *ToNetPacketInitAck() const; - virtual const NetPacketRetrieveAvatar *ToNetPacketRetrieveAvatar() const; - virtual const NetPacketAvatarHeader *ToNetPacketAvatarHeader() const; - virtual const NetPacketAvatarFile *ToNetPacketAvatarFile() const; - virtual const NetPacketAvatarEnd *ToNetPacketAvatarEnd() const; - virtual const NetPacketUnknownAvatar *ToNetPacketUnknownAvatar() const; - virtual const NetPacketGameListNew *ToNetPacketGameListNew() const; - virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const; - virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const; - virtual const NetPacketGameListPlayerLeft *ToNetPacketGameListPlayerLeft() const; - virtual const NetPacketGameListAdminChanged *ToNetPacketGameListAdminChanged() const; - virtual const NetPacketRetrievePlayerInfo *ToNetPacketRetrievePlayerInfo() const; - virtual const NetPacketPlayerInfo *ToNetPacketPlayerInfo() const; - virtual const NetPacketUnknownPlayerId *ToNetPacketUnknownPlayerId() const; - virtual const NetPacketCreateGame *ToNetPacketCreateGame() const; - virtual const NetPacketJoinGame *ToNetPacketJoinGame() const; - virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const; - virtual const NetPacketJoinGameFailed *ToNetPacketJoinGameFailed() const; - virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const; - virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const; - virtual const NetPacketGameAdminChanged *ToNetPacketGameAdminChanged() const; - virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; - virtual const NetPacketLeaveCurrentGame *ToNetPacketLeaveCurrentGame() const; - virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; - virtual const NetPacketStartEventAck *ToNetPacketStartEventAck() const; - virtual const NetPacketGameStart *ToNetPacketGameStart() const; - virtual const NetPacketHandStart *ToNetPacketHandStart() const; - virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const; - virtual const NetPacketPlayersAction *ToNetPacketPlayersAction() const; - virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const; - virtual const NetPacketPlayersActionRejected *ToNetPacketPlayersActionRejected() const; - virtual const NetPacketDealFlopCards *ToNetPacketDealFlopCards() const; - virtual const NetPacketDealTurnCard *ToNetPacketDealTurnCard() const; - virtual const NetPacketDealRiverCard *ToNetPacketDealRiverCard() const; - virtual const NetPacketAllInShowCards *ToNetPacketAllInShowCards() const; - virtual const NetPacketEndOfHandShowCards *ToNetPacketEndOfHandShowCards() const; - virtual const NetPacketEndOfHandHideCards *ToNetPacketEndOfHandHideCards() const; - virtual const NetPacketEndOfGame *ToNetPacketEndOfGame() const; - virtual const NetPacketStatisticsChanged *ToNetPacketStatisticsChanged() const; - virtual const NetPacketRemovedFromGame *ToNetPacketRemovedFromGame() const; - virtual const NetPacketSendChatText *ToNetPacketSendChatText() const; - virtual const NetPacketChatText *ToNetPacketChatText() const; - virtual const NetPacketError *ToNetPacketError() const; - -protected: - - NetPacket &operator=(const NetPacket& right); // not allowed - - void Check(const NetPacketHeader *data) const; - virtual void InternalCheck(const NetPacketHeader *data) const = 0; - - void Resize(u_int16_t newLen); - -private: - - NetPacketHeader *m_data; - const u_int16_t m_initialSize; - const u_int16_t m_maxSize; -}; - -typedef std::list > NetPacketList; - -class NetPacketInit : public NetPacket -{ -public: - struct Data - { - int versionMajor; - int versionMinor; - std::string playerName; - std::string password; - bool showAvatar; - MD5Buf avatar; - }; - - NetPacketInit(); - virtual ~NetPacketInit(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketInit *ToNetPacketInit() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketInitAck : public NetPacket -{ -public: - struct Data - { - u_int16_t latestGameVersion; - u_int16_t latestBetaRevision; - u_int32_t sessionId; - u_int32_t playerId; - }; - - NetPacketInitAck(); - virtual ~NetPacketInitAck(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketInitAck *ToNetPacketInitAck() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketRetrieveAvatar : public NetPacket -{ -public: - struct Data - { - u_int32_t requestId; - MD5Buf avatar; - }; - - NetPacketRetrieveAvatar(); - virtual ~NetPacketRetrieveAvatar(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketRetrieveAvatar *ToNetPacketRetrieveAvatar() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketAvatarHeader : public NetPacket -{ -public: - struct Data - { - u_int32_t requestId; - u_int32_t avatarFileSize; - AvatarFileType avatarFileType; - }; - - NetPacketAvatarHeader(); - virtual ~NetPacketAvatarHeader(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketAvatarHeader *ToNetPacketAvatarHeader() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketAvatarFile : public NetPacket -{ -public: - struct Data - { - u_int32_t requestId; - std::vector fileData; - }; - - NetPacketAvatarFile(); - virtual ~NetPacketAvatarFile(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketAvatarFile *ToNetPacketAvatarFile() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketAvatarEnd : public NetPacket -{ -public: - struct Data - { - u_int32_t requestId; - }; - - NetPacketAvatarEnd(); - virtual ~NetPacketAvatarEnd(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketAvatarEnd *ToNetPacketAvatarEnd() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketUnknownAvatar : public NetPacket -{ -public: - struct Data - { - u_int32_t requestId; - }; - - NetPacketUnknownAvatar(); - virtual ~NetPacketUnknownAvatar(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketUnknownAvatar *ToNetPacketUnknownAvatar() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameListNew : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - GameInfo gameInfo; - }; - - NetPacketGameListNew(); - virtual ~NetPacketGameListNew(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameListNew *ToNetPacketGameListNew() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameListUpdate : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - GameMode gameMode; - }; - - NetPacketGameListUpdate(); - virtual ~NetPacketGameListUpdate(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameListPlayerJoined : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - u_int32_t playerId; - }; - - NetPacketGameListPlayerJoined(); - virtual ~NetPacketGameListPlayerJoined(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameListPlayerLeft : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - u_int32_t playerId; - }; - - NetPacketGameListPlayerLeft(); - virtual ~NetPacketGameListPlayerLeft(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameListPlayerLeft *ToNetPacketGameListPlayerLeft() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameListAdminChanged : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - u_int32_t newAdminplayerId; - }; - - NetPacketGameListAdminChanged(); - virtual ~NetPacketGameListAdminChanged(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameListAdminChanged *ToNetPacketGameListAdminChanged() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketRetrievePlayerInfo : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - }; - - NetPacketRetrievePlayerInfo(); - virtual ~NetPacketRetrievePlayerInfo(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketRetrievePlayerInfo *ToNetPacketRetrievePlayerInfo() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayerInfo : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - PlayerInfo playerInfo; - }; - - NetPacketPlayerInfo(); - virtual ~NetPacketPlayerInfo(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayerInfo *ToNetPacketPlayerInfo() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketUnknownPlayerId : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - }; - - NetPacketUnknownPlayerId(); - virtual ~NetPacketUnknownPlayerId(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketUnknownPlayerId *ToNetPacketUnknownPlayerId() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketCreateGame : public NetPacket -{ -public: - struct Data - { - std::string gameName; - std::string password; - GameData gameData; - }; - - NetPacketCreateGame(); - virtual ~NetPacketCreateGame(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketCreateGame *ToNetPacketCreateGame() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketJoinGame : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - std::string password; - }; - - NetPacketJoinGame(); - virtual ~NetPacketJoinGame(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketJoinGame *ToNetPacketJoinGame() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketJoinGameAck : public NetPacket -{ -public: - struct Data - { - u_int32_t gameId; - GameData gameData; - PlayerRights prights; - }; - - NetPacketJoinGameAck(); - virtual ~NetPacketJoinGameAck(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketJoinGameFailed : public NetPacket -{ -public: - struct Data - { - int failureCode; - }; - - NetPacketJoinGameFailed(); - virtual ~NetPacketJoinGameFailed(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketJoinGameFailed *ToNetPacketJoinGameFailed() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayerJoined : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - PlayerRights prights; - }; - - NetPacketPlayerJoined(); - virtual ~NetPacketPlayerJoined(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayerLeft : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - }; - - NetPacketPlayerLeft(); - virtual ~NetPacketPlayerLeft(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameAdminChanged : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - }; - - NetPacketGameAdminChanged(); - virtual ~NetPacketGameAdminChanged(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameAdminChanged *ToNetPacketGameAdminChanged() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketKickPlayer : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - }; - - NetPacketKickPlayer(); - virtual ~NetPacketKickPlayer(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketLeaveCurrentGame : public NetPacket -{ -public: - - NetPacketLeaveCurrentGame(); - virtual ~NetPacketLeaveCurrentGame(); - - virtual boost::shared_ptr Clone() const; - - virtual const NetPacketLeaveCurrentGame *ToNetPacketLeaveCurrentGame() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketStartEvent : public NetPacket -{ -public: - struct Data - { - bool fillUpWithCpuPlayers; - }; - - NetPacketStartEvent(); - virtual ~NetPacketStartEvent(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketStartEventAck : public NetPacket -{ -public: - - NetPacketStartEventAck(); - virtual ~NetPacketStartEventAck(); - - virtual boost::shared_ptr Clone() const; - - virtual const NetPacketStartEventAck *ToNetPacketStartEventAck() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketGameStart : public NetPacket -{ -public: - - struct PlayerSlot - { - u_int32_t playerId; - }; - - typedef std::list PlayerSlotList; - - struct Data - { - StartData startData; - PlayerSlotList playerSlots; - }; - - NetPacketGameStart(); - virtual ~NetPacketGameStart(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketGameStart *ToNetPacketGameStart() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketHandStart : public NetPacket -{ -public: - struct Data - { - u_int16_t yourCards[2]; - u_int32_t smallBlind; - }; - - NetPacketHandStart(); - virtual ~NetPacketHandStart(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketHandStart *ToNetPacketHandStart() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayersTurn : public NetPacket -{ -public: - struct Data - { - GameState gameState; - u_int32_t playerId; - u_int32_t minimumRaise; - }; - - NetPacketPlayersTurn(); - virtual ~NetPacketPlayersTurn(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayersAction : public NetPacket -{ -public: - struct Data - { - GameState gameState; - PlayerAction playerAction; - u_int32_t playerBet; - }; - - NetPacketPlayersAction(); - virtual ~NetPacketPlayersAction(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayersAction *ToNetPacketPlayersAction() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayersActionDone : public NetPacket -{ -public: - struct Data - { - GameState gameState; - u_int32_t playerId; - PlayerAction playerAction; - u_int32_t totalPlayerBet; - u_int32_t playerMoney; - u_int32_t highestSet; - }; - - NetPacketPlayersActionDone(); - virtual ~NetPacketPlayersActionDone(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketPlayersActionRejected : public NetPacket -{ -public: - - struct Data - { - GameState gameState; - PlayerAction playerAction; - u_int32_t playerBet; - PlayerActionCode rejectionReason; - }; - - NetPacketPlayersActionRejected(); - virtual ~NetPacketPlayersActionRejected(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketPlayersActionRejected *ToNetPacketPlayersActionRejected() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketDealFlopCards : public NetPacket -{ -public: - struct Data - { - u_int16_t flopCards[3]; - }; - - NetPacketDealFlopCards(); - virtual ~NetPacketDealFlopCards(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketDealFlopCards *ToNetPacketDealFlopCards() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketDealTurnCard : public NetPacket -{ -public: - struct Data - { - u_int16_t turnCard; - }; - - NetPacketDealTurnCard(); - virtual ~NetPacketDealTurnCard(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketDealTurnCard *ToNetPacketDealTurnCard() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketDealRiverCard : public NetPacket -{ -public: - struct Data - { - u_int16_t riverCard; - }; - - NetPacketDealRiverCard(); - virtual ~NetPacketDealRiverCard(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketDealRiverCard *ToNetPacketDealRiverCard() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketAllInShowCards : public NetPacket -{ -public: - struct PlayerCards - { - u_int32_t playerId; - u_int16_t cards[2]; - }; - - typedef std::list PlayerCardsList; - - struct Data - { - PlayerCardsList playerCards; - }; - - NetPacketAllInShowCards(); - virtual ~NetPacketAllInShowCards(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketAllInShowCards *ToNetPacketAllInShowCards() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketEndOfHandShowCards : public NetPacket -{ -public: - struct PlayerResult - { - u_int32_t playerId; - u_int16_t cards[2]; - u_int16_t bestHandPos[5]; - u_int32_t valueOfCards; - u_int32_t moneyWon; - u_int32_t playerMoney; - }; - - typedef std::list PlayerResultList; - - struct Data - { - PlayerResultList playerResults; - }; - - NetPacketEndOfHandShowCards(); - virtual ~NetPacketEndOfHandShowCards(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketEndOfHandShowCards *ToNetPacketEndOfHandShowCards() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketEndOfHandHideCards : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - u_int32_t moneyWon; - u_int32_t playerMoney; - }; - - NetPacketEndOfHandHideCards(); - virtual ~NetPacketEndOfHandHideCards(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketEndOfHandHideCards *ToNetPacketEndOfHandHideCards() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketEndOfGame : public NetPacket -{ -public: - struct Data - { - u_int32_t winnerPlayerId; - }; - - NetPacketEndOfGame(); - virtual ~NetPacketEndOfGame(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketEndOfGame *ToNetPacketEndOfGame() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketStatisticsChanged : public NetPacket -{ -public: - struct Data - { - ServerStats stats; - }; - - NetPacketStatisticsChanged(); - virtual ~NetPacketStatisticsChanged(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketStatisticsChanged *ToNetPacketStatisticsChanged() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketRemovedFromGame : public NetPacket -{ -public: - struct Data - { - u_int16_t removeReason; - }; - - NetPacketRemovedFromGame(); - virtual ~NetPacketRemovedFromGame(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketRemovedFromGame *ToNetPacketRemovedFromGame() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketSendChatText : public NetPacket -{ -public: - struct Data - { - std::string text; - }; - - NetPacketSendChatText(); - virtual ~NetPacketSendChatText(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketSendChatText *ToNetPacketSendChatText() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketChatText : public NetPacket -{ -public: - struct Data - { - u_int32_t playerId; - std::string text; - }; - - NetPacketChatText(); - virtual ~NetPacketChatText(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketChatText *ToNetPacketChatText() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -class NetPacketError : public NetPacket -{ -public: - struct Data - { - int errorCode; - }; - - NetPacketError(); - virtual ~NetPacketError(); - - virtual boost::shared_ptr Clone() const; - - void SetData(const Data &inData); - void GetData(Data &outData) const; - - virtual const NetPacketError *ToNetPacketError() const; - -protected: - - virtual void InternalCheck(const NetPacketHeader* data) const; -}; - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* PokerTH network packet. */ + +#ifndef _NETPACKET_H_ +#define _NETPACKET_H_ + +#include +#include +#include +#include +#include + +#include +#include + +#define NET_VERSION_MAJOR 2 +#define NET_VERSION_MINOR 0 + +#define MIN_PACKET_SIZE 4 +#define MAX_PACKET_SIZE 268 +#define MAX_NAME_SIZE 64 +#define MAX_PASSWORD_SIZE 64 +#define MAX_NUM_MANUAL_BLINDS 30 +#define MAX_CHAT_TEXT_SIZE 128 +#define MAX_FILE_DATA_SIZE 256 +#define MAX_NUM_PLAYER_RESULTS MAX_NUMBER_OF_PLAYERS +#define MAX_NUM_PLAYER_CARDS MAX_NUMBER_OF_PLAYERS + + +struct NetPacketHeader; + +class NetPacketInit; +class NetPacketInitAck; +class NetPacketRetrieveAvatar; +class NetPacketAvatarHeader; +class NetPacketAvatarFile; +class NetPacketAvatarEnd; +class NetPacketUnknownAvatar; +class NetPacketGameListNew; +class NetPacketGameListUpdate; +class NetPacketGameListPlayerJoined; +class NetPacketGameListPlayerLeft; +class NetPacketGameListAdminChanged; +class NetPacketRetrievePlayerInfo; +class NetPacketPlayerInfo; +class NetPacketUnknownPlayerId; +class NetPacketCreateGame; +class NetPacketJoinGame; +class NetPacketJoinGameAck; +class NetPacketJoinGameFailed; +class NetPacketPlayerJoined; +class NetPacketPlayerLeft; +class NetPacketGameAdminChanged; +class NetPacketKickPlayer; +class NetPacketLeaveCurrentGame; +class NetPacketStartEvent; +class NetPacketStartEventAck; +class NetPacketGameStart; +class NetPacketHandStart; +class NetPacketPlayersTurn; +class NetPacketPlayersAction; +class NetPacketPlayersActionDone; +class NetPacketPlayersActionRejected; +class NetPacketDealFlopCards; +class NetPacketDealTurnCard; +class NetPacketDealRiverCard; +class NetPacketAllInShowCards; +class NetPacketEndOfHandShowCards; +class NetPacketEndOfHandHideCards; +class NetPacketEndOfGame; +class NetPacketStatisticsChanged; +class NetPacketRemovedFromGame; +class NetPacketSendChatText; +class NetPacketChatText; +class NetPacketError; + +class NetPacket +{ +public: + static boost::shared_ptr Create(char *data, unsigned &dataSize); + + NetPacket(u_int16_t type, u_int16_t initialSize, u_int16_t maxSize); + virtual ~NetPacket(); + + virtual boost::shared_ptr Clone() const = 0; + + const NetPacketHeader *GetRawData() const; + NetPacketHeader *GetRawData(); + void SetRawData(const NetPacketHeader *p); + + u_int16_t GetType() const; + u_int16_t GetLen() const; + + virtual const NetPacketInit *ToNetPacketInit() const; + virtual const NetPacketInitAck *ToNetPacketInitAck() const; + virtual const NetPacketRetrieveAvatar *ToNetPacketRetrieveAvatar() const; + virtual const NetPacketAvatarHeader *ToNetPacketAvatarHeader() const; + virtual const NetPacketAvatarFile *ToNetPacketAvatarFile() const; + virtual const NetPacketAvatarEnd *ToNetPacketAvatarEnd() const; + virtual const NetPacketUnknownAvatar *ToNetPacketUnknownAvatar() const; + virtual const NetPacketGameListNew *ToNetPacketGameListNew() const; + virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const; + virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const; + virtual const NetPacketGameListPlayerLeft *ToNetPacketGameListPlayerLeft() const; + virtual const NetPacketGameListAdminChanged *ToNetPacketGameListAdminChanged() const; + virtual const NetPacketRetrievePlayerInfo *ToNetPacketRetrievePlayerInfo() const; + virtual const NetPacketPlayerInfo *ToNetPacketPlayerInfo() const; + virtual const NetPacketUnknownPlayerId *ToNetPacketUnknownPlayerId() const; + virtual const NetPacketCreateGame *ToNetPacketCreateGame() const; + virtual const NetPacketJoinGame *ToNetPacketJoinGame() const; + virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const; + virtual const NetPacketJoinGameFailed *ToNetPacketJoinGameFailed() const; + virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const; + virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const; + virtual const NetPacketGameAdminChanged *ToNetPacketGameAdminChanged() const; + virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; + virtual const NetPacketLeaveCurrentGame *ToNetPacketLeaveCurrentGame() const; + virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; + virtual const NetPacketStartEventAck *ToNetPacketStartEventAck() const; + virtual const NetPacketGameStart *ToNetPacketGameStart() const; + virtual const NetPacketHandStart *ToNetPacketHandStart() const; + virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const; + virtual const NetPacketPlayersAction *ToNetPacketPlayersAction() const; + virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const; + virtual const NetPacketPlayersActionRejected *ToNetPacketPlayersActionRejected() const; + virtual const NetPacketDealFlopCards *ToNetPacketDealFlopCards() const; + virtual const NetPacketDealTurnCard *ToNetPacketDealTurnCard() const; + virtual const NetPacketDealRiverCard *ToNetPacketDealRiverCard() const; + virtual const NetPacketAllInShowCards *ToNetPacketAllInShowCards() const; + virtual const NetPacketEndOfHandShowCards *ToNetPacketEndOfHandShowCards() const; + virtual const NetPacketEndOfHandHideCards *ToNetPacketEndOfHandHideCards() const; + virtual const NetPacketEndOfGame *ToNetPacketEndOfGame() const; + virtual const NetPacketStatisticsChanged *ToNetPacketStatisticsChanged() const; + virtual const NetPacketRemovedFromGame *ToNetPacketRemovedFromGame() const; + virtual const NetPacketSendChatText *ToNetPacketSendChatText() const; + virtual const NetPacketChatText *ToNetPacketChatText() const; + virtual const NetPacketError *ToNetPacketError() const; + +protected: + + NetPacket &operator=(const NetPacket& right); // not allowed + + void Check(const NetPacketHeader *data) const; + virtual void InternalCheck(const NetPacketHeader *data) const = 0; + + void Resize(u_int16_t newLen); + +private: + + NetPacketHeader *m_data; + const u_int16_t m_initialSize; + const u_int16_t m_maxSize; +}; + +typedef std::list > NetPacketList; + +class NetPacketInit : public NetPacket +{ +public: + struct Data + { + int versionMajor; + int versionMinor; + std::string playerName; + std::string password; + bool showAvatar; + MD5Buf avatar; + }; + + NetPacketInit(); + virtual ~NetPacketInit(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketInit *ToNetPacketInit() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketInitAck : public NetPacket +{ +public: + struct Data + { + u_int16_t latestGameVersion; + u_int16_t latestBetaRevision; + u_int32_t sessionId; + u_int32_t playerId; + }; + + NetPacketInitAck(); + virtual ~NetPacketInitAck(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketInitAck *ToNetPacketInitAck() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketRetrieveAvatar : public NetPacket +{ +public: + struct Data + { + u_int32_t requestId; + MD5Buf avatar; + }; + + NetPacketRetrieveAvatar(); + virtual ~NetPacketRetrieveAvatar(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketRetrieveAvatar *ToNetPacketRetrieveAvatar() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketAvatarHeader : public NetPacket +{ +public: + struct Data + { + u_int32_t requestId; + u_int32_t avatarFileSize; + AvatarFileType avatarFileType; + }; + + NetPacketAvatarHeader(); + virtual ~NetPacketAvatarHeader(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketAvatarHeader *ToNetPacketAvatarHeader() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketAvatarFile : public NetPacket +{ +public: + struct Data + { + u_int32_t requestId; + std::vector fileData; + }; + + NetPacketAvatarFile(); + virtual ~NetPacketAvatarFile(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketAvatarFile *ToNetPacketAvatarFile() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketAvatarEnd : public NetPacket +{ +public: + struct Data + { + u_int32_t requestId; + }; + + NetPacketAvatarEnd(); + virtual ~NetPacketAvatarEnd(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketAvatarEnd *ToNetPacketAvatarEnd() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketUnknownAvatar : public NetPacket +{ +public: + struct Data + { + u_int32_t requestId; + }; + + NetPacketUnknownAvatar(); + virtual ~NetPacketUnknownAvatar(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketUnknownAvatar *ToNetPacketUnknownAvatar() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameListNew : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + GameInfo gameInfo; + }; + + NetPacketGameListNew(); + virtual ~NetPacketGameListNew(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameListNew *ToNetPacketGameListNew() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameListUpdate : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + GameMode gameMode; + }; + + NetPacketGameListUpdate(); + virtual ~NetPacketGameListUpdate(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameListPlayerJoined : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + u_int32_t playerId; + }; + + NetPacketGameListPlayerJoined(); + virtual ~NetPacketGameListPlayerJoined(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameListPlayerLeft : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + u_int32_t playerId; + }; + + NetPacketGameListPlayerLeft(); + virtual ~NetPacketGameListPlayerLeft(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameListPlayerLeft *ToNetPacketGameListPlayerLeft() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameListAdminChanged : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + u_int32_t newAdminplayerId; + }; + + NetPacketGameListAdminChanged(); + virtual ~NetPacketGameListAdminChanged(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameListAdminChanged *ToNetPacketGameListAdminChanged() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketRetrievePlayerInfo : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + }; + + NetPacketRetrievePlayerInfo(); + virtual ~NetPacketRetrievePlayerInfo(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketRetrievePlayerInfo *ToNetPacketRetrievePlayerInfo() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayerInfo : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + PlayerInfo playerInfo; + }; + + NetPacketPlayerInfo(); + virtual ~NetPacketPlayerInfo(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayerInfo *ToNetPacketPlayerInfo() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketUnknownPlayerId : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + }; + + NetPacketUnknownPlayerId(); + virtual ~NetPacketUnknownPlayerId(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketUnknownPlayerId *ToNetPacketUnknownPlayerId() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketCreateGame : public NetPacket +{ +public: + struct Data + { + std::string gameName; + std::string password; + GameData gameData; + }; + + NetPacketCreateGame(); + virtual ~NetPacketCreateGame(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketCreateGame *ToNetPacketCreateGame() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketJoinGame : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + std::string password; + }; + + NetPacketJoinGame(); + virtual ~NetPacketJoinGame(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketJoinGame *ToNetPacketJoinGame() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketJoinGameAck : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + GameData gameData; + PlayerRights prights; + }; + + NetPacketJoinGameAck(); + virtual ~NetPacketJoinGameAck(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketJoinGameFailed : public NetPacket +{ +public: + struct Data + { + int failureCode; + }; + + NetPacketJoinGameFailed(); + virtual ~NetPacketJoinGameFailed(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketJoinGameFailed *ToNetPacketJoinGameFailed() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayerJoined : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + PlayerRights prights; + }; + + NetPacketPlayerJoined(); + virtual ~NetPacketPlayerJoined(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayerLeft : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + }; + + NetPacketPlayerLeft(); + virtual ~NetPacketPlayerLeft(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameAdminChanged : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + }; + + NetPacketGameAdminChanged(); + virtual ~NetPacketGameAdminChanged(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameAdminChanged *ToNetPacketGameAdminChanged() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketKickPlayer : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + }; + + NetPacketKickPlayer(); + virtual ~NetPacketKickPlayer(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketLeaveCurrentGame : public NetPacket +{ +public: + + NetPacketLeaveCurrentGame(); + virtual ~NetPacketLeaveCurrentGame(); + + virtual boost::shared_ptr Clone() const; + + virtual const NetPacketLeaveCurrentGame *ToNetPacketLeaveCurrentGame() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketStartEvent : public NetPacket +{ +public: + struct Data + { + bool fillUpWithCpuPlayers; + }; + + NetPacketStartEvent(); + virtual ~NetPacketStartEvent(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketStartEventAck : public NetPacket +{ +public: + + NetPacketStartEventAck(); + virtual ~NetPacketStartEventAck(); + + virtual boost::shared_ptr Clone() const; + + virtual const NetPacketStartEventAck *ToNetPacketStartEventAck() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketGameStart : public NetPacket +{ +public: + + struct PlayerSlot + { + u_int32_t playerId; + }; + + typedef std::list PlayerSlotList; + + struct Data + { + StartData startData; + PlayerSlotList playerSlots; + }; + + NetPacketGameStart(); + virtual ~NetPacketGameStart(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameStart *ToNetPacketGameStart() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketHandStart : public NetPacket +{ +public: + struct Data + { + u_int16_t yourCards[2]; + u_int32_t smallBlind; + }; + + NetPacketHandStart(); + virtual ~NetPacketHandStart(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketHandStart *ToNetPacketHandStart() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayersTurn : public NetPacket +{ +public: + struct Data + { + GameState gameState; + u_int32_t playerId; + u_int32_t minimumRaise; + }; + + NetPacketPlayersTurn(); + virtual ~NetPacketPlayersTurn(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayersAction : public NetPacket +{ +public: + struct Data + { + GameState gameState; + PlayerAction playerAction; + u_int32_t playerBet; + }; + + NetPacketPlayersAction(); + virtual ~NetPacketPlayersAction(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayersAction *ToNetPacketPlayersAction() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayersActionDone : public NetPacket +{ +public: + struct Data + { + GameState gameState; + u_int32_t playerId; + PlayerAction playerAction; + u_int32_t totalPlayerBet; + u_int32_t playerMoney; + u_int32_t highestSet; + }; + + NetPacketPlayersActionDone(); + virtual ~NetPacketPlayersActionDone(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketPlayersActionRejected : public NetPacket +{ +public: + + struct Data + { + GameState gameState; + PlayerAction playerAction; + u_int32_t playerBet; + PlayerActionCode rejectionReason; + }; + + NetPacketPlayersActionRejected(); + virtual ~NetPacketPlayersActionRejected(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayersActionRejected *ToNetPacketPlayersActionRejected() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketDealFlopCards : public NetPacket +{ +public: + struct Data + { + u_int16_t flopCards[3]; + }; + + NetPacketDealFlopCards(); + virtual ~NetPacketDealFlopCards(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketDealFlopCards *ToNetPacketDealFlopCards() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketDealTurnCard : public NetPacket +{ +public: + struct Data + { + u_int16_t turnCard; + }; + + NetPacketDealTurnCard(); + virtual ~NetPacketDealTurnCard(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketDealTurnCard *ToNetPacketDealTurnCard() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketDealRiverCard : public NetPacket +{ +public: + struct Data + { + u_int16_t riverCard; + }; + + NetPacketDealRiverCard(); + virtual ~NetPacketDealRiverCard(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketDealRiverCard *ToNetPacketDealRiverCard() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketAllInShowCards : public NetPacket +{ +public: + struct PlayerCards + { + u_int32_t playerId; + u_int16_t cards[2]; + }; + + typedef std::list PlayerCardsList; + + struct Data + { + PlayerCardsList playerCards; + }; + + NetPacketAllInShowCards(); + virtual ~NetPacketAllInShowCards(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketAllInShowCards *ToNetPacketAllInShowCards() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketEndOfHandShowCards : public NetPacket +{ +public: + struct PlayerResult + { + u_int32_t playerId; + u_int16_t cards[2]; + u_int16_t bestHandPos[5]; + u_int32_t valueOfCards; + u_int32_t moneyWon; + u_int32_t playerMoney; + }; + + typedef std::list PlayerResultList; + + struct Data + { + PlayerResultList playerResults; + }; + + NetPacketEndOfHandShowCards(); + virtual ~NetPacketEndOfHandShowCards(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketEndOfHandShowCards *ToNetPacketEndOfHandShowCards() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketEndOfHandHideCards : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + u_int32_t moneyWon; + u_int32_t playerMoney; + }; + + NetPacketEndOfHandHideCards(); + virtual ~NetPacketEndOfHandHideCards(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketEndOfHandHideCards *ToNetPacketEndOfHandHideCards() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketEndOfGame : public NetPacket +{ +public: + struct Data + { + u_int32_t winnerPlayerId; + }; + + NetPacketEndOfGame(); + virtual ~NetPacketEndOfGame(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketEndOfGame *ToNetPacketEndOfGame() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketStatisticsChanged : public NetPacket +{ +public: + struct Data + { + ServerStats stats; + }; + + NetPacketStatisticsChanged(); + virtual ~NetPacketStatisticsChanged(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketStatisticsChanged *ToNetPacketStatisticsChanged() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketRemovedFromGame : public NetPacket +{ +public: + struct Data + { + u_int16_t removeReason; + }; + + NetPacketRemovedFromGame(); + virtual ~NetPacketRemovedFromGame(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketRemovedFromGame *ToNetPacketRemovedFromGame() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketSendChatText : public NetPacket +{ +public: + struct Data + { + std::string text; + }; + + NetPacketSendChatText(); + virtual ~NetPacketSendChatText(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketSendChatText *ToNetPacketSendChatText() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketChatText : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + std::string text; + }; + + NetPacketChatText(); + virtual ~NetPacketChatText(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketChatText *ToNetPacketChatText() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketError : public NetPacket +{ +public: + struct Data + { + int errorCode; + }; + + NetPacketError(); + virtual ~NetPacketError(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketError *ToNetPacketError() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +#endif + diff --git a/src/net/receivebuffer.h b/src/net/receivebuffer.h index 8e027329..866556ee 100644 --- a/src/net/receivebuffer.h +++ b/src/net/receivebuffer.h @@ -1,40 +1,40 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Buffer for ReceiveHelper. */ - -#ifndef _RECEIVEBUFFER_H_ -#define _RECEIVEBUFFER_H_ - -#include -#include - -// MUST be larger than MAX_PACKET_SIZE -#define RECV_BUF_SIZE 2 * MAX_PACKET_SIZE - -typedef std::list > NetPacketList; - -struct ReceiveBuffer -{ - ReceiveBuffer() : recvBufUsed(0) {} - NetPacketList receivedPackets; - char recvBuf[RECV_BUF_SIZE]; - unsigned recvBufUsed; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Buffer for ReceiveHelper. */ + +#ifndef _RECEIVEBUFFER_H_ +#define _RECEIVEBUFFER_H_ + +#include +#include + +// MUST be larger than MAX_PACKET_SIZE +#define RECV_BUF_SIZE 2 * MAX_PACKET_SIZE + +typedef std::list > NetPacketList; + +struct ReceiveBuffer +{ + ReceiveBuffer() : recvBufUsed(0) {} + NetPacketList receivedPackets; + char recvBuf[RECV_BUF_SIZE]; + unsigned recvBufUsed; +}; + +#endif diff --git a/src/net/receiverhelper.h b/src/net/receiverhelper.h index 131993de..e955316f 100644 --- a/src/net/receiverhelper.h +++ b/src/net/receiverhelper.h @@ -1,47 +1,47 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network receiver helper class. NOTE: By design, this is not a thread. */ - -#ifndef _RECEIVERHELPER_H_ -#define _RECEIVERHELPER_H_ - -#include -#include -#include - -#include -#include - -class ReceiverHelper -{ -public: - ReceiverHelper(); - virtual ~ReceiverHelper(); - - // Set the socket from which to receive data. - void Init(SOCKET socket); - - boost::shared_ptr Recv(SOCKET sock, ReceiveBuffer &buf); - -protected: - void InternalGetPackets(ReceiveBuffer &buf); -}; - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network receiver helper class. NOTE: By design, this is not a thread. */ + +#ifndef _RECEIVERHELPER_H_ +#define _RECEIVERHELPER_H_ + +#include +#include +#include + +#include +#include + +class ReceiverHelper +{ +public: + ReceiverHelper(); + virtual ~ReceiverHelper(); + + // Set the socket from which to receive data. + void Init(SOCKET socket); + + boost::shared_ptr Recv(SOCKET sock, ReceiveBuffer &buf); + +protected: + void InternalGetPackets(ReceiveBuffer &buf); +}; + +#endif + diff --git a/src/net/resolverthread.h b/src/net/resolverthread.h index 85a95663..3186b55a 100644 --- a/src/net/resolverthread.h +++ b/src/net/resolverthread.h @@ -1,61 +1,61 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Name resolution thread. */ - -#ifndef _RESOLVERTHREAD_H_ -#define _RESOLVERTHREAD_H_ - -#include -#include -#include - -class ClientContext; - -class ResolverThread : public Thread -{ -public: - ResolverThread(); - virtual ~ResolverThread(); - - // Set the parameters. Does not do any error checking. - // To prevent access faults if this thread cannot be - // terminated, the data is not modified. - void Init(const ClientContext &context); - - // Retrieve the result of the name resolution. - // ONLY CALL THIS FUNCTION AFTER THE THREAD TERMINATED. - // You have been warned... - bool GetResult(ClientContext &context) const; - -protected: - - // Main function of the thread. - virtual void Main(); - - const ClientContext &GetContext() const; - ClientContext &GetContext(); - -private: - - boost::shared_ptr m_context; - bool m_retVal; -}; - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Name resolution thread. */ + +#ifndef _RESOLVERTHREAD_H_ +#define _RESOLVERTHREAD_H_ + +#include +#include +#include + +class ClientContext; + +class ResolverThread : public Thread +{ +public: + ResolverThread(); + virtual ~ResolverThread(); + + // Set the parameters. Does not do any error checking. + // To prevent access faults if this thread cannot be + // terminated, the data is not modified. + void Init(const ClientContext &context); + + // Retrieve the result of the name resolution. + // ONLY CALL THIS FUNCTION AFTER THE THREAD TERMINATED. + // You have been warned... + bool GetResult(ClientContext &context) const; + +protected: + + // Main function of the thread. + virtual void Main(); + + const ClientContext &GetContext() const; + ClientContext &GetContext(); + +private: + + boost::shared_ptr m_context; + bool m_retVal; +}; + +#endif + diff --git a/src/net/sendercallback.h b/src/net/sendercallback.h index 445e200e..798fe34a 100644 --- a/src/net/sendercallback.h +++ b/src/net/sendercallback.h @@ -1,35 +1,35 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Callback interface for the sender thread. */ - -#ifndef _SENDERCALLBACK_H_ -#define _SENDERCALLBACK_H_ - -#include -#include - -class SenderCallback -{ -public: - virtual ~SenderCallback(); - - virtual void SignalNetError(SessionId session, int errorID, int osErrorID) = 0; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Callback interface for the sender thread. */ + +#ifndef _SENDERCALLBACK_H_ +#define _SENDERCALLBACK_H_ + +#include +#include + +class SenderCallback +{ +public: + virtual ~SenderCallback(); + + virtual void SignalNetError(SessionId session, int errorID, int osErrorID) = 0; +}; + +#endif diff --git a/src/net/senderthread.h b/src/net/senderthread.h index 0beda89d..c2ff4863 100644 --- a/src/net/senderthread.h +++ b/src/net/senderthread.h @@ -1,80 +1,80 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network sender thread. */ - -#ifndef _SENDERTHREAD_H_ -#define _SENDERTHREAD_H_ - -#include -#include -#include -#include - -#include -#include - -#define SENDER_THREAD_TERMINATE_TIMEOUT THREAD_WAIT_INFINITE - -class SenderThread : public Thread -{ -public: - SenderThread(SenderCallback &cb); - virtual ~SenderThread(); - - void Send(boost::shared_ptr session, boost::shared_ptr packet); - void Send(boost::shared_ptr session, const NetPacketList &packetList); - - void SendLowPrio(boost::shared_ptr session, boost::shared_ptr packet); - void SendLowPrio(boost::shared_ptr session, const NetPacketList &packetList); - - unsigned GetNumPacketsInQueue() const; - bool operator<(const SenderThread &other) const; - -protected: - typedef std::pair, boost::shared_ptr > SendData; - typedef std::deque SendDataDeque; - - // Main function of the thread. - virtual void Main(); - - void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, boost::shared_ptr packet); - void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, const NetPacketList &packetList); - - void RemoveCurSendData(); - -private: - - boost::shared_ptr m_curSession; - - std::deque m_outBuf; - mutable boost::mutex m_outBufMutex; - - std::deque m_lowPrioOutBuf; - mutable boost::mutex m_lowPrioOutBufMutex; - - char m_tmpOutBuf[MAX_PACKET_SIZE]; - unsigned m_tmpOutBufSize; - bool m_tmpIsLowPrio; - unsigned m_lastInvalidSessionId; - - SenderCallback &m_callback; -}; - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network sender thread. */ + +#ifndef _SENDERTHREAD_H_ +#define _SENDERTHREAD_H_ + +#include +#include +#include +#include + +#include +#include + +#define SENDER_THREAD_TERMINATE_TIMEOUT THREAD_WAIT_INFINITE + +class SenderThread : public Thread +{ +public: + SenderThread(SenderCallback &cb); + virtual ~SenderThread(); + + void Send(boost::shared_ptr session, boost::shared_ptr packet); + void Send(boost::shared_ptr session, const NetPacketList &packetList); + + void SendLowPrio(boost::shared_ptr session, boost::shared_ptr packet); + void SendLowPrio(boost::shared_ptr session, const NetPacketList &packetList); + + unsigned GetNumPacketsInQueue() const; + bool operator<(const SenderThread &other) const; + +protected: + typedef std::pair, boost::shared_ptr > SendData; + typedef std::deque SendDataDeque; + + // Main function of the thread. + virtual void Main(); + + void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, boost::shared_ptr packet); + void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, boost::shared_ptr session, const NetPacketList &packetList); + + void RemoveCurSendData(); + +private: + + boost::shared_ptr m_curSession; + + std::deque m_outBuf; + mutable boost::mutex m_outBufMutex; + + std::deque m_lowPrioOutBuf; + mutable boost::mutex m_lowPrioOutBufMutex; + + char m_tmpOutBuf[MAX_PACKET_SIZE]; + unsigned m_tmpOutBufSize; + bool m_tmpIsLowPrio; + unsigned m_lastInvalidSessionId; + + SenderCallback &m_callback; +}; + +#endif + diff --git a/src/net/serveracceptthread.h b/src/net/serveracceptthread.h index c7540ae4..3648e220 100644 --- a/src/net/serveracceptthread.h +++ b/src/net/serveracceptthread.h @@ -1,84 +1,84 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network server thread to accept connections. */ - -#ifndef _SERVERACCEPTTHREAD_H_ -#define _SERVERACCEPTTHREAD_H_ - -#include -#include - -#include -#include - -class ServerContext; -class ServerLobbyThread; -class ServerSenderCallback; -class SenderThread; -class ConfigFile; -class AvatarManager; -class IrcThread; -struct GameData; - -class ServerAcceptThread : public Thread, public IrcCallback -{ -public: - ServerAcceptThread(GuiInterface &gui, ConfigFile *config, AvatarManager &avatarManager); - virtual ~ServerAcceptThread(); - - // Set the parameters. - void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const std::string &logDir, boost::shared_ptr ircThread); - - ServerCallback &GetCallback(); - GuiInterface &GetGui(); - - virtual void SignalIrcConnect(const std::string &server); - virtual void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel); - virtual void SignalIrcPlayerJoined(const std::string & /*nickName*/) {} - virtual void SignalIrcPlayerChanged(const std::string & /*oldNick*/, const std::string & /*newNick*/) {} - virtual void SignalIrcPlayerKicked(const std::string & /*nickName*/, const std::string & /*byWhom*/, const std::string & /*reason*/) {} - virtual void SignalIrcPlayerLeft(const std::string & /*nickName*/) {} - virtual void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); - virtual void SignalIrcError(int errorCode); - virtual void SignalIrcServerError(int errorCode); - -protected: - - // Main function of the thread. - virtual void Main(); - - void Listen(); - void AcceptLoop(); - - const ServerContext &GetContext() const; - ServerContext &GetContext(); - - ServerLobbyThread &GetLobbyThread(); - -private: - boost::shared_ptr m_context; - boost::shared_ptr m_lobbyThread; - - GuiInterface &m_gui; - - std::string m_ircNick; - boost::shared_ptr m_ircThread; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network server thread to accept connections. */ + +#ifndef _SERVERACCEPTTHREAD_H_ +#define _SERVERACCEPTTHREAD_H_ + +#include +#include + +#include +#include + +class ServerContext; +class ServerLobbyThread; +class ServerSenderCallback; +class SenderThread; +class ConfigFile; +class AvatarManager; +class IrcThread; +struct GameData; + +class ServerAcceptThread : public Thread, public IrcCallback +{ +public: + ServerAcceptThread(GuiInterface &gui, ConfigFile *config, AvatarManager &avatarManager); + virtual ~ServerAcceptThread(); + + // Set the parameters. + void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const std::string &logDir, boost::shared_ptr ircThread); + + ServerCallback &GetCallback(); + GuiInterface &GetGui(); + + virtual void SignalIrcConnect(const std::string &server); + virtual void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel); + virtual void SignalIrcPlayerJoined(const std::string & /*nickName*/) {} + virtual void SignalIrcPlayerChanged(const std::string & /*oldNick*/, const std::string & /*newNick*/) {} + virtual void SignalIrcPlayerKicked(const std::string & /*nickName*/, const std::string & /*byWhom*/, const std::string & /*reason*/) {} + virtual void SignalIrcPlayerLeft(const std::string & /*nickName*/) {} + virtual void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); + virtual void SignalIrcError(int errorCode); + virtual void SignalIrcServerError(int errorCode); + +protected: + + // Main function of the thread. + virtual void Main(); + + void Listen(); + void AcceptLoop(); + + const ServerContext &GetContext() const; + ServerContext &GetContext(); + + ServerLobbyThread &GetLobbyThread(); + +private: + boost::shared_ptr m_context; + boost::shared_ptr m_lobbyThread; + + GuiInterface &m_gui; + + std::string m_ircNick; + boost::shared_ptr m_ircThread; +}; + +#endif diff --git a/src/net/servercallback.h b/src/net/servercallback.h index 920837d2..7715364b 100644 --- a/src/net/servercallback.h +++ b/src/net/servercallback.h @@ -1,35 +1,35 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Callback interface for network server gui. */ - -#ifndef _SERVERCALLBACK_H_ -#define _SERVERCALLBACK_H_ - -#include - -class ServerCallback -{ -public: - virtual ~ServerCallback(); - - virtual void SignalNetServerSuccess(int actionID) = 0; - virtual void SignalNetServerError(int errorID, int osErrorID) = 0; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Callback interface for network server gui. */ + +#ifndef _SERVERCALLBACK_H_ +#define _SERVERCALLBACK_H_ + +#include + +class ServerCallback +{ +public: + virtual ~ServerCallback(); + + virtual void SignalNetServerSuccess(int actionID) = 0; + virtual void SignalNetServerError(int errorID, int osErrorID) = 0; +}; + +#endif diff --git a/src/net/servercontext.h b/src/net/servercontext.h index 7d2e27e6..61cbbc21 100644 --- a/src/net/servercontext.h +++ b/src/net/servercontext.h @@ -1,65 +1,65 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Context of network server. */ - -#ifndef _SERVERCONTEXT_H_ -#define _SERVERCONTEXT_H_ - -#include - - -class ServerContext : public NetContext -{ -public: - ServerContext(); - virtual ~ServerContext(); - - virtual SOCKET GetSocket() const; - - void SetSocket(SOCKET sockfd); - - int GetProtocol() const - {return m_protocol;} - void SetProtocol(int protocol) - {m_protocol = protocol;} - int GetAddrFamily() const - {return m_addrFamily;} - void SetAddrFamily(int addrFamily) - {m_addrFamily = addrFamily;} - unsigned GetServerPort() const - {return m_serverPort;} - void SetServerPort(unsigned serverPort) - {m_serverPort = serverPort;} - const sockaddr_storage *GetServerSockaddr() const - {return &m_serverSockaddr;} - sockaddr_storage *GetServerSockaddr() - {return &m_serverSockaddr;} - - int GetServerSockaddrSize() const - {return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);} - -private: - SOCKET m_sockfd; - int m_protocol; - int m_addrFamily; - unsigned m_serverPort; - sockaddr_storage m_serverSockaddr; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Context of network server. */ + +#ifndef _SERVERCONTEXT_H_ +#define _SERVERCONTEXT_H_ + +#include + + +class ServerContext : public NetContext +{ +public: + ServerContext(); + virtual ~ServerContext(); + + virtual SOCKET GetSocket() const; + + void SetSocket(SOCKET sockfd); + + int GetProtocol() const + {return m_protocol;} + void SetProtocol(int protocol) + {m_protocol = protocol;} + int GetAddrFamily() const + {return m_addrFamily;} + void SetAddrFamily(int addrFamily) + {m_addrFamily = addrFamily;} + unsigned GetServerPort() const + {return m_serverPort;} + void SetServerPort(unsigned serverPort) + {m_serverPort = serverPort;} + const sockaddr_storage *GetServerSockaddr() const + {return &m_serverSockaddr;} + sockaddr_storage *GetServerSockaddr() + {return &m_serverSockaddr;} + + int GetServerSockaddrSize() const + {return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);} + +private: + SOCKET m_sockfd; + int m_protocol; + int m_addrFamily; + unsigned m_serverPort; + sockaddr_storage m_serverSockaddr; +}; + +#endif diff --git a/src/net/serverexception.h b/src/net/serverexception.h index 16265009..c8949821 100644 --- a/src/net/serverexception.h +++ b/src/net/serverexception.h @@ -1,36 +1,36 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Exception class for server errors. */ - -#ifndef _SERVEREXCEPTION_H_ -#define _SERVEREXCEPTION_H_ - -#include - -class ServerException : public NetException -{ -public: - - ServerException(const char *sourcefile, int sourceline, int errorId, int osErrorCode) - : NetException(sourcefile, sourceline, errorId, osErrorCode) {} - - virtual ~ServerException() throw(); -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Exception class for server errors. */ + +#ifndef _SERVEREXCEPTION_H_ +#define _SERVEREXCEPTION_H_ + +#include + +class ServerException : public NetException +{ +public: + + ServerException(const char *sourcefile, int sourceline, int errorId, int osErrorCode) + : NetException(sourcefile, sourceline, errorId, osErrorCode) {} + + virtual ~ServerException() throw(); +}; + +#endif diff --git a/src/net/servergamestate.h b/src/net/servergamestate.h index 4d40b8fa..08cb6b91 100644 --- a/src/net/servergamestate.h +++ b/src/net/servergamestate.h @@ -1,401 +1,401 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* State of network server. */ - -#ifndef _SERVERGAMESTATE_H_ -#define _SERVERGAMESTATE_H_ - -#include -#include -#include - - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4250) -#endif - -#define SERVER_INITIAL_STATE ServerGameStateInit -#define SERVER_START_GAME_STATE ServerGameStateStartGame - -class Game; -class PlayerInterface; -class ServerCallback; - -class ServerGameState -{ -public: - virtual ~ServerGameState(); - - // Initialize after switching to this state. - virtual void Init() = 0; - - // Handling of a new session. - virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session) = 0; - - // Main processing function of the current state. - virtual int Process(ServerGameThread &server) = 0; -}; - -// Abstract State: Receiving. -class AbstractServerGameStateReceiving : virtual public ServerGameState -{ -public: - virtual ~AbstractServerGameStateReceiving(); - - // Globally handle packets which are allowed in all running states. - // Calls InternalProcess if packet has not been processed. - virtual int Process(ServerGameThread &server); - -protected: - - AbstractServerGameStateReceiving(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) = 0; -}; - -// Abstract State: Timer. -class AbstractServerGameStateTimer : virtual public ServerGameState -{ -public: - virtual ~AbstractServerGameStateTimer(); - - virtual void Init(); - - const boost::timers::portable::microsec_timer &GetTimer() const {return m_timer;} - -protected: - - AbstractServerGameStateTimer(); - -private: - boost::timers::portable::microsec_timer m_timer; -}; - -// Abstract State: Game is running. -class AbstractServerGameStateRunning : virtual public ServerGameState -{ -public: - virtual ~AbstractServerGameStateRunning(); - - // Reject new connections. - virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); - -protected: - - AbstractServerGameStateRunning(); -}; - -// State: Initialization. -class ServerGameStateInit : public AbstractServerGameStateReceiving -{ -public: - // Access the state singleton. - static ServerGameStateInit &Instance(); - - virtual ~ServerGameStateInit(); - - virtual void Init() {} - // - virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateInit(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - - static boost::shared_ptr CreateNetPacketPlayerJoined(const PlayerData &playerData); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// Wait for Ack of start event. -class ServerGameStateWaitAck : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateWaitAck &Instance(); - - virtual ~ServerGameStateWaitAck(); - - // Timeout if waiting takes too long. - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateWaitAck(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Start server game. -class ServerGameStateStartGame : public AbstractServerGameStateRunning -{ -public: - // Access the state singleton. - static ServerGameStateStartGame &Instance(); - - virtual ~ServerGameStateStartGame(); - - virtual void Init() {} - - // - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateStartGame(); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Start new hand. -class ServerGameStateStartHand : public AbstractServerGameStateRunning -{ -public: - // Access the state singleton. - static ServerGameStateStartHand &Instance(); - - virtual ~ServerGameStateStartHand(); - - virtual void Init() {} - - // - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateStartHand(); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Start new round. -class ServerGameStateStartRound : public AbstractServerGameStateRunning -{ -public: - // Access the state singleton. - static ServerGameStateStartRound &Instance(); - - virtual ~ServerGameStateStartRound(); - - virtual void Init() {} - - // - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateStartRound(); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Wait for a player action. -class ServerGameStateWaitPlayerAction : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateWaitPlayerAction &Instance(); - - virtual ~ServerGameStateWaitPlayerAction(); - - // Handle leaving players. - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateWaitPlayerAction(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - - static void PerformPlayerAction(ServerGameThread &server, boost::shared_ptr player, PlayerAction action, int bet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay and computer action -class ServerGameStateComputerAction : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateComputerAction &Instance(); - - virtual ~ServerGameStateComputerAction(); - - // Overwrite default processing - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateComputerAction(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay after dealing cards -class ServerGameStateDealCardsDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateDealCardsDelay &Instance(); - - virtual ~ServerGameStateDealCardsDelay(); - - // Overwrite default processing - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateDealCardsDelay(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay after showing cards (all in) -class ServerGameStateShowCardsDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateShowCardsDelay &Instance(); - - virtual ~ServerGameStateShowCardsDelay(); - - // Overwrite default processing - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateShowCardsDelay(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay before next hand. -class ServerGameStateNextHandDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateNextHandDelay &Instance(); - - virtual ~ServerGameStateNextHandDelay(); - - // Overwrite default processing - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateNextHandDelay(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay before next hand. -class ServerGameStateNextGameDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer -{ -public: - // Access the state singleton. - static ServerGameStateNextGameDelay &Instance(); - - virtual ~ServerGameStateNextGameDelay(); - - // Overwrite default processing - virtual int Process(ServerGameThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateNextGameDelay(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Final. -class ServerGameStateFinal : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning -{ -public: - // Access the state singleton. - static ServerGameStateFinal &Instance(); - - virtual ~ServerGameStateFinal(); - - virtual void Init() {} - -protected: - - // Protected constructor - this is a singleton. - ServerGameStateFinal(); - - virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* State of network server. */ + +#ifndef _SERVERGAMESTATE_H_ +#define _SERVERGAMESTATE_H_ + +#include +#include +#include + + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4250) +#endif + +#define SERVER_INITIAL_STATE ServerGameStateInit +#define SERVER_START_GAME_STATE ServerGameStateStartGame + +class Game; +class PlayerInterface; +class ServerCallback; + +class ServerGameState +{ +public: + virtual ~ServerGameState(); + + // Initialize after switching to this state. + virtual void Init() = 0; + + // Handling of a new session. + virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session) = 0; + + // Main processing function of the current state. + virtual int Process(ServerGameThread &server) = 0; +}; + +// Abstract State: Receiving. +class AbstractServerGameStateReceiving : virtual public ServerGameState +{ +public: + virtual ~AbstractServerGameStateReceiving(); + + // Globally handle packets which are allowed in all running states. + // Calls InternalProcess if packet has not been processed. + virtual int Process(ServerGameThread &server); + +protected: + + AbstractServerGameStateReceiving(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) = 0; +}; + +// Abstract State: Timer. +class AbstractServerGameStateTimer : virtual public ServerGameState +{ +public: + virtual ~AbstractServerGameStateTimer(); + + virtual void Init(); + + const boost::timers::portable::microsec_timer &GetTimer() const {return m_timer;} + +protected: + + AbstractServerGameStateTimer(); + +private: + boost::timers::portable::microsec_timer m_timer; +}; + +// Abstract State: Game is running. +class AbstractServerGameStateRunning : virtual public ServerGameState +{ +public: + virtual ~AbstractServerGameStateRunning(); + + // Reject new connections. + virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); + +protected: + + AbstractServerGameStateRunning(); +}; + +// State: Initialization. +class ServerGameStateInit : public AbstractServerGameStateReceiving +{ +public: + // Access the state singleton. + static ServerGameStateInit &Instance(); + + virtual ~ServerGameStateInit(); + + virtual void Init() {} + // + virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateInit(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + + static boost::shared_ptr CreateNetPacketPlayerJoined(const PlayerData &playerData); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// Wait for Ack of start event. +class ServerGameStateWaitAck : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateWaitAck &Instance(); + + virtual ~ServerGameStateWaitAck(); + + // Timeout if waiting takes too long. + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateWaitAck(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Start server game. +class ServerGameStateStartGame : public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateStartGame &Instance(); + + virtual ~ServerGameStateStartGame(); + + virtual void Init() {} + + // + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateStartGame(); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Start new hand. +class ServerGameStateStartHand : public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateStartHand &Instance(); + + virtual ~ServerGameStateStartHand(); + + virtual void Init() {} + + // + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateStartHand(); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Start new round. +class ServerGameStateStartRound : public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateStartRound &Instance(); + + virtual ~ServerGameStateStartRound(); + + virtual void Init() {} + + // + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateStartRound(); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Wait for a player action. +class ServerGameStateWaitPlayerAction : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateWaitPlayerAction &Instance(); + + virtual ~ServerGameStateWaitPlayerAction(); + + // Handle leaving players. + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateWaitPlayerAction(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + + static void PerformPlayerAction(ServerGameThread &server, boost::shared_ptr player, PlayerAction action, int bet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay and computer action +class ServerGameStateComputerAction : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateComputerAction &Instance(); + + virtual ~ServerGameStateComputerAction(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateComputerAction(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay after dealing cards +class ServerGameStateDealCardsDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateDealCardsDelay &Instance(); + + virtual ~ServerGameStateDealCardsDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateDealCardsDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay after showing cards (all in) +class ServerGameStateShowCardsDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateShowCardsDelay &Instance(); + + virtual ~ServerGameStateShowCardsDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateShowCardsDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay before next hand. +class ServerGameStateNextHandDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateNextHandDelay &Instance(); + + virtual ~ServerGameStateNextHandDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateNextHandDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay before next hand. +class ServerGameStateNextGameDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateNextGameDelay &Instance(); + + virtual ~ServerGameStateNextGameDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateNextGameDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Final. +class ServerGameStateFinal : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateFinal &Instance(); + + virtual ~ServerGameStateFinal(); + + virtual void Init() {} + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateFinal(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index 2c2a38ba..05d62fba 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -1,172 +1,172 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network server game thread. */ - -#ifndef _SERVERGAMETHREAD_H_ -#define _SERVERGAMETHREAD_H_ - -#include -#include -#include - -#include - -#define GAME_THREAD_TERMINATE_TIMEOUT THREAD_WAIT_INFINITE - - -class SenderThread; -class ReceiverHelper; -class ServerLobbyThread; -class GameSenderCallback; -class ServerGameState; -class ConfigFile; -struct GameData; -class Game; - -class ServerGameThread : public Thread -{ -public: - ServerGameThread( - ServerLobbyThread &lobbyThread, u_int32_t id, const std::string &name, const std::string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig); - virtual ~ServerGameThread(); - - u_int32_t GetId() const; - const std::string &GetName() const; - - void AddSession(SessionWrapper session); - void KickPlayer(unsigned playerId); - - ServerCallback &GetCallback(); - GameState GetCurRound() const; - - void SendToAllPlayers(boost::shared_ptr packet, SessionData::State state); - void RemoveAllSessions(); - - bool IsPasswordProtected() const; - bool CheckPassword(const std::string &password) const; - const GameData &GetGameData() const; - - boost::shared_ptr GetPlayerDataByUniqueId(unsigned playerId) const; - PlayerIdList GetPlayerIdList() const; - bool IsPlayerConnected(const std::string &name) const; - - bool IsRunning() const; - - unsigned GetAdminPlayerId() const; - void SetAdminPlayerId(unsigned playerId); - - // should be protected, but is needed in function. - const Game &GetGame() const; - Game &GetGame(); - -protected: - - typedef std::deque SessionQueue; - - // Main function of the thread. - virtual void Main(); - void KickPlayerLoop(); - - void InternalStartGame(); - void ResetGame(); - - void InternalKickPlayer(unsigned playerId); - - PlayerDataList GetFullPlayerDataList() const; - - void AddComputerPlayer(boost::shared_ptr player); - void ResetComputerPlayerList(); - - void GracefulRemoveSession(SessionWrapper session); - void RemovePlayerData(boost::shared_ptr player); - void ErrorRemoveSession(SessionWrapper session); - void SessionError(SessionWrapper session, int errorCode); - void MoveSessionToLobby(SessionWrapper session, int reason); - - void RemoveDisconnectedPlayers(); - size_t GetCurNumberOfPlayers() const; - void AssignPlayerNumbers(); - - ServerLobbyThread &GetLobbyThread(); - - ServerGameState &GetState(); - void SetState(ServerGameState &newState); - - SenderThread &GetSender(); - ReceiverHelper &GetReceiver(); - - const StartData &GetStartData() const; - void SetStartData(const StartData &startData); - - GameSenderCallback &GetSenderCallback(); - GuiInterface &GetGui(); - - unsigned GetNextGameNum(); - - const SessionManager &GetSessionManager() const; - SessionManager &GetSessionManager(); - -private: - - SessionQueue m_sessionQueue; - mutable boost::mutex m_sessionQueueMutex; - - SessionManager m_sessionManager; - PlayerDataList m_computerPlayerList; - mutable boost::mutex m_computerPlayerListMutex; - - PlayerIdList m_kickPlayerList; - mutable boost::mutex m_kickPlayerListMutex; - - unsigned m_adminPlayerId; - mutable boost::mutex m_adminPlayerIdMutex; - - ServerLobbyThread &m_lobbyThread; - boost::shared_ptr m_receiver; - boost::shared_ptr m_sender; - boost::shared_ptr m_senderCallback; - GuiInterface &m_gui; - - const GameData m_gameData; - StartData m_startData; - boost::shared_ptr m_game; - const u_int32_t m_id; - const std::string m_name; - const std::string m_password; - ConfigFile *m_playerConfig; - ServerGameState *m_curState; - unsigned m_gameNum; - -friend class AbstractServerGameStateReceiving; -friend class AbstractServerGameStateRunning; -friend class ServerGameStateInit; -friend class ServerGameStateWaitAck; -friend class ServerGameStateStartGame; -friend class ServerGameStateStartHand; -friend class ServerGameStateStartRound; -friend class ServerGameStateWaitPlayerAction; -friend class ServerGameStateComputerAction; -friend class ServerGameStateDealCardsDelay; -friend class ServerGameStateShowCardsDelay; -friend class ServerGameStateNextHandDelay; -friend class ServerGameStateNextGameDelay; -friend class GameSenderCallback; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network server game thread. */ + +#ifndef _SERVERGAMETHREAD_H_ +#define _SERVERGAMETHREAD_H_ + +#include +#include +#include + +#include + +#define GAME_THREAD_TERMINATE_TIMEOUT THREAD_WAIT_INFINITE + + +class SenderThread; +class ReceiverHelper; +class ServerLobbyThread; +class GameSenderCallback; +class ServerGameState; +class ConfigFile; +struct GameData; +class Game; + +class ServerGameThread : public Thread +{ +public: + ServerGameThread( + ServerLobbyThread &lobbyThread, u_int32_t id, const std::string &name, const std::string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig); + virtual ~ServerGameThread(); + + u_int32_t GetId() const; + const std::string &GetName() const; + + void AddSession(SessionWrapper session); + void KickPlayer(unsigned playerId); + + ServerCallback &GetCallback(); + GameState GetCurRound() const; + + void SendToAllPlayers(boost::shared_ptr packet, SessionData::State state); + void RemoveAllSessions(); + + bool IsPasswordProtected() const; + bool CheckPassword(const std::string &password) const; + const GameData &GetGameData() const; + + boost::shared_ptr GetPlayerDataByUniqueId(unsigned playerId) const; + PlayerIdList GetPlayerIdList() const; + bool IsPlayerConnected(const std::string &name) const; + + bool IsRunning() const; + + unsigned GetAdminPlayerId() const; + void SetAdminPlayerId(unsigned playerId); + + // should be protected, but is needed in function. + const Game &GetGame() const; + Game &GetGame(); + +protected: + + typedef std::deque SessionQueue; + + // Main function of the thread. + virtual void Main(); + void KickPlayerLoop(); + + void InternalStartGame(); + void ResetGame(); + + void InternalKickPlayer(unsigned playerId); + + PlayerDataList GetFullPlayerDataList() const; + + void AddComputerPlayer(boost::shared_ptr player); + void ResetComputerPlayerList(); + + void GracefulRemoveSession(SessionWrapper session); + void RemovePlayerData(boost::shared_ptr player); + void ErrorRemoveSession(SessionWrapper session); + void SessionError(SessionWrapper session, int errorCode); + void MoveSessionToLobby(SessionWrapper session, int reason); + + void RemoveDisconnectedPlayers(); + size_t GetCurNumberOfPlayers() const; + void AssignPlayerNumbers(); + + ServerLobbyThread &GetLobbyThread(); + + ServerGameState &GetState(); + void SetState(ServerGameState &newState); + + SenderThread &GetSender(); + ReceiverHelper &GetReceiver(); + + const StartData &GetStartData() const; + void SetStartData(const StartData &startData); + + GameSenderCallback &GetSenderCallback(); + GuiInterface &GetGui(); + + unsigned GetNextGameNum(); + + const SessionManager &GetSessionManager() const; + SessionManager &GetSessionManager(); + +private: + + SessionQueue m_sessionQueue; + mutable boost::mutex m_sessionQueueMutex; + + SessionManager m_sessionManager; + PlayerDataList m_computerPlayerList; + mutable boost::mutex m_computerPlayerListMutex; + + PlayerIdList m_kickPlayerList; + mutable boost::mutex m_kickPlayerListMutex; + + unsigned m_adminPlayerId; + mutable boost::mutex m_adminPlayerIdMutex; + + ServerLobbyThread &m_lobbyThread; + boost::shared_ptr m_receiver; + boost::shared_ptr m_sender; + boost::shared_ptr m_senderCallback; + GuiInterface &m_gui; + + const GameData m_gameData; + StartData m_startData; + boost::shared_ptr m_game; + const u_int32_t m_id; + const std::string m_name; + const std::string m_password; + ConfigFile *m_playerConfig; + ServerGameState *m_curState; + unsigned m_gameNum; + +friend class AbstractServerGameStateReceiving; +friend class AbstractServerGameStateRunning; +friend class ServerGameStateInit; +friend class ServerGameStateWaitAck; +friend class ServerGameStateStartGame; +friend class ServerGameStateStartHand; +friend class ServerGameStateStartRound; +friend class ServerGameStateWaitPlayerAction; +friend class ServerGameStateComputerAction; +friend class ServerGameStateDealCardsDelay; +friend class ServerGameStateShowCardsDelay; +friend class ServerGameStateNextHandDelay; +friend class ServerGameStateNextGameDelay; +friend class GameSenderCallback; +}; + +#endif diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 4a76d608..5b539959 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -1,204 +1,204 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network server receive thread. */ - -#ifndef _SERVERRECVTHREAD_H_ -#define _SERVERRECVTHREAD_H_ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC 20000 -#define ADMIN_IRC_TERMINATE_TIMEOUT_MSEC 2000 - - -class SenderThread; -class ReceiverHelper; -class ServerSenderCallback; -class ServerGameThread; -class ConfigFile; -class AvatarManager; -struct GameData; -class Game; - -class ServerLobbyThread : public Thread -{ -public: - ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager); - virtual ~ServerLobbyThread(); - - void Init(const std::string &pwd, const std::string &logDir); - - void AddConnection(boost::shared_ptr data); - void ReAddSession(SessionWrapper session, int reason); - void MoveSessionToGame(ServerGameThread &game, SessionWrapper session); - void RemoveSessionFromGame(SessionWrapper session); - void SessionError(SessionWrapper session, int errorCode); - void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId); - void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId); - void NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId); - void NotifyStartingGame(unsigned gameId); - void NotifyReopeningGame(unsigned gameId); - - void HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); - void HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); - - bool KickPlayerByName(const std::string &playerName); - - void AddComputerPlayer(boost::shared_ptr player); - void RemoveComputerPlayer(boost::shared_ptr player); - - void RemoveGame(unsigned id); - - u_int32_t GetNextUniquePlayerId(); - u_int32_t GetNextGameId(); - ServerCallback &GetCallback(); - - AvatarManager &GetAvatarManager(); - - ServerStats GetStats() const; - -protected: - - typedef std::deque > ConnectQueue; - typedef std::deque SessionQueue; - typedef std::list SessionList; - typedef std::map InitTimerSessionMap; - typedef std::map > GameMap; - typedef std::list RemoveGameList; - typedef std::list > SenderThreadList; - - // Main function of the thread. - virtual void Main(); - - void ProcessLoop(); - void HandleNetPacketInit(SessionWrapper session, const NetPacketInit &tmpPacket); - void HandleNetPacketAvatarHeader(SessionWrapper session, const NetPacketAvatarHeader &tmpPacket); - void HandleNetPacketUnknownAvatar(SessionWrapper session, const NetPacketUnknownAvatar &tmpPacket); - void HandleNetPacketAvatarFile(SessionWrapper session, const NetPacketAvatarFile &tmpPacket); - void HandleNetPacketAvatarEnd(SessionWrapper session, const NetPacketAvatarEnd &tmpPacket); - void HandleNetPacketRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); - void HandleNetPacketRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); - void HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket); - void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket); - void EstablishSession(SessionWrapper session); - void RequestPlayerAvatar(SessionWrapper session); - void NewConnectionLoop(); - void NewSessionLoop(); - void CloseSessionLoop(); - void RemoveGameLoop(); - void KickPlayerLoop(); - void CleanupAvatarCache(); - - void InternalAddGame(boost::shared_ptr game); - void InternalRemoveGame(boost::shared_ptr game); - void InternalKickPlayer(unsigned playerId); - - void TerminateGames(); - - void HandleNewConnection(boost::shared_ptr connData); - void HandleReAddedSession(SessionWrapper session); - - SOCKET Select(); - - void CleanupConnectQueue(); - void CleanupSessionMap(); - - void CloseSession(SessionWrapper session); - void SendError(boost::shared_ptr s, int errorCode); - void SendJoinGameFailed(boost::shared_ptr s, int reason); - void SendGameList(boost::shared_ptr s); - void UpdateStatisticsNumberOfPlayers(); - void BroadcastStatisticsUpdate(const ServerStats &stats); - - void ReadStatisticsFile(); - void SaveStatisticsFile(); - - SenderThread &GetSender(); - ReceiverHelper &GetReceiver(); - - bool CheckPassword(const std::string &password) const; - - ServerSenderCallback &GetSenderCallback(); - GuiInterface &GetGui(); - - bool IsPlayerConnected(const std::string &name); - - static boost::shared_ptr CreateNetPacketGameListNew(const ServerGameThread &game); - static boost::shared_ptr CreateNetPacketGameListUpdate(unsigned gameId, GameMode mode); - -private: - - ConnectQueue m_connectQueue; - mutable boost::mutex m_connectQueueMutex; - - SessionQueue m_sessionQueue; - mutable boost::mutex m_sessionQueueMutex; - - SessionManager m_sessionManager; - SessionManager m_gameSessionManager; - - InitTimerSessionMap m_initTimerSessionMap; - mutable boost::mutex m_initTimerSessionMapMutex; - - RemoveGameList m_removeGameList; - mutable boost::mutex m_removeGameListMutex; - - PlayerIdList m_kickPlayerList; - mutable boost::mutex m_kickPlayerListMutex; - - PlayerDataMap m_computerPlayers; - mutable boost::mutex m_computerPlayersMutex; - - GameMap m_gameMap; - - boost::shared_ptr m_receiver; - boost::shared_ptr m_sender; - SenderThreadList m_avatarSenderThreadPool; - boost::shared_ptr m_senderCallback; - GuiInterface &m_gui; - AvatarManager &m_avatarManager; - - std::string m_password; - std::string m_statisticsFileName; - ConfigFile *m_playerConfig; - u_int32_t m_curGameId; - - u_int32_t m_curUniquePlayerId; - u_int32_t m_curSessionId; - mutable boost::mutex m_curUniquePlayerIdMutex; - - - ServerStats m_statData; - bool m_statDataChanged; - mutable boost::mutex m_statMutex; - - boost::timers::portable::microsec_timer m_cacheCleanupTimer; - boost::timers::portable::microsec_timer m_saveStatisticsTimer; - boost::timers::portable::microsec_timer m_uptimeTimer; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network server receive thread. */ + +#ifndef _SERVERRECVTHREAD_H_ +#define _SERVERRECVTHREAD_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC 20000 +#define ADMIN_IRC_TERMINATE_TIMEOUT_MSEC 2000 + + +class SenderThread; +class ReceiverHelper; +class ServerSenderCallback; +class ServerGameThread; +class ConfigFile; +class AvatarManager; +struct GameData; +class Game; + +class ServerLobbyThread : public Thread +{ +public: + ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager); + virtual ~ServerLobbyThread(); + + void Init(const std::string &pwd, const std::string &logDir); + + void AddConnection(boost::shared_ptr data); + void ReAddSession(SessionWrapper session, int reason); + void MoveSessionToGame(ServerGameThread &game, SessionWrapper session); + void RemoveSessionFromGame(SessionWrapper session); + void SessionError(SessionWrapper session, int errorCode); + void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId); + void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId); + void NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId); + void NotifyStartingGame(unsigned gameId); + void NotifyReopeningGame(unsigned gameId); + + void HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); + void HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); + + bool KickPlayerByName(const std::string &playerName); + + void AddComputerPlayer(boost::shared_ptr player); + void RemoveComputerPlayer(boost::shared_ptr player); + + void RemoveGame(unsigned id); + + u_int32_t GetNextUniquePlayerId(); + u_int32_t GetNextGameId(); + ServerCallback &GetCallback(); + + AvatarManager &GetAvatarManager(); + + ServerStats GetStats() const; + +protected: + + typedef std::deque > ConnectQueue; + typedef std::deque SessionQueue; + typedef std::list SessionList; + typedef std::map InitTimerSessionMap; + typedef std::map > GameMap; + typedef std::list RemoveGameList; + typedef std::list > SenderThreadList; + + // Main function of the thread. + virtual void Main(); + + void ProcessLoop(); + void HandleNetPacketInit(SessionWrapper session, const NetPacketInit &tmpPacket); + void HandleNetPacketAvatarHeader(SessionWrapper session, const NetPacketAvatarHeader &tmpPacket); + void HandleNetPacketUnknownAvatar(SessionWrapper session, const NetPacketUnknownAvatar &tmpPacket); + void HandleNetPacketAvatarFile(SessionWrapper session, const NetPacketAvatarFile &tmpPacket); + void HandleNetPacketAvatarEnd(SessionWrapper session, const NetPacketAvatarEnd &tmpPacket); + void HandleNetPacketRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); + void HandleNetPacketRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); + void HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket); + void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket); + void EstablishSession(SessionWrapper session); + void RequestPlayerAvatar(SessionWrapper session); + void NewConnectionLoop(); + void NewSessionLoop(); + void CloseSessionLoop(); + void RemoveGameLoop(); + void KickPlayerLoop(); + void CleanupAvatarCache(); + + void InternalAddGame(boost::shared_ptr game); + void InternalRemoveGame(boost::shared_ptr game); + void InternalKickPlayer(unsigned playerId); + + void TerminateGames(); + + void HandleNewConnection(boost::shared_ptr connData); + void HandleReAddedSession(SessionWrapper session); + + SOCKET Select(); + + void CleanupConnectQueue(); + void CleanupSessionMap(); + + void CloseSession(SessionWrapper session); + void SendError(boost::shared_ptr s, int errorCode); + void SendJoinGameFailed(boost::shared_ptr s, int reason); + void SendGameList(boost::shared_ptr s); + void UpdateStatisticsNumberOfPlayers(); + void BroadcastStatisticsUpdate(const ServerStats &stats); + + void ReadStatisticsFile(); + void SaveStatisticsFile(); + + SenderThread &GetSender(); + ReceiverHelper &GetReceiver(); + + bool CheckPassword(const std::string &password) const; + + ServerSenderCallback &GetSenderCallback(); + GuiInterface &GetGui(); + + bool IsPlayerConnected(const std::string &name); + + static boost::shared_ptr CreateNetPacketGameListNew(const ServerGameThread &game); + static boost::shared_ptr CreateNetPacketGameListUpdate(unsigned gameId, GameMode mode); + +private: + + ConnectQueue m_connectQueue; + mutable boost::mutex m_connectQueueMutex; + + SessionQueue m_sessionQueue; + mutable boost::mutex m_sessionQueueMutex; + + SessionManager m_sessionManager; + SessionManager m_gameSessionManager; + + InitTimerSessionMap m_initTimerSessionMap; + mutable boost::mutex m_initTimerSessionMapMutex; + + RemoveGameList m_removeGameList; + mutable boost::mutex m_removeGameListMutex; + + PlayerIdList m_kickPlayerList; + mutable boost::mutex m_kickPlayerListMutex; + + PlayerDataMap m_computerPlayers; + mutable boost::mutex m_computerPlayersMutex; + + GameMap m_gameMap; + + boost::shared_ptr m_receiver; + boost::shared_ptr m_sender; + SenderThreadList m_avatarSenderThreadPool; + boost::shared_ptr m_senderCallback; + GuiInterface &m_gui; + AvatarManager &m_avatarManager; + + std::string m_password; + std::string m_statisticsFileName; + ConfigFile *m_playerConfig; + u_int32_t m_curGameId; + + u_int32_t m_curUniquePlayerId; + u_int32_t m_curSessionId; + mutable boost::mutex m_curUniquePlayerIdMutex; + + + ServerStats m_statData; + bool m_statDataChanged; + mutable boost::mutex m_statMutex; + + boost::timers::portable::microsec_timer m_cacheCleanupTimer; + boost::timers::portable::microsec_timer m_saveStatisticsTimer; + boost::timers::portable::microsec_timer m_uptimeTimer; +}; + +#endif diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index 1e509449..a99a3160 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -1,74 +1,74 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Session data (a session is a valid client connection). */ - -#ifndef _SESSIONDATA_H_ -#define _SESSIONDATA_H_ - -#include -#include -#include -#include - -#define INVALID_SESSION 0 -#define SESSION_ID_INIT INVALID_SESSION -#define SESSION_ID_GENERIC 0xFFFFFFFF - -typedef unsigned SessionId; -/*struct SessionId -{ - unsigned id; -};*/ - - -class SessionData -{ -public: - enum State { Init, ReceivingAvatar, Established, Game }; - - SessionData(SOCKET sockfd, SessionId id); - ~SessionData(); - - SessionId GetId() const; - State GetState() const; - void SetState(State state); - - SOCKET GetSocket() const; - - void SetReadyFlag(); - void ResetReadyFlag(); - bool IsReady() const; - - const std::string &GetClientAddr() const; - void SetClientAddr(const std::string &addr); - - ReceiveBuffer &GetReceiveBuffer(); - -private: - SOCKET m_sockfd; - const SessionId m_id; - State m_state; - std::string m_clientAddr; - ReceiveBuffer m_receiveBuffer; - bool m_readyFlag; - - mutable boost::mutex m_dataMutex; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Session data (a session is a valid client connection). */ + +#ifndef _SESSIONDATA_H_ +#define _SESSIONDATA_H_ + +#include +#include +#include +#include + +#define INVALID_SESSION 0 +#define SESSION_ID_INIT INVALID_SESSION +#define SESSION_ID_GENERIC 0xFFFFFFFF + +typedef unsigned SessionId; +/*struct SessionId +{ + unsigned id; +};*/ + + +class SessionData +{ +public: + enum State { Init, ReceivingAvatar, Established, Game }; + + SessionData(SOCKET sockfd, SessionId id); + ~SessionData(); + + SessionId GetId() const; + State GetState() const; + void SetState(State state); + + SOCKET GetSocket() const; + + void SetReadyFlag(); + void ResetReadyFlag(); + bool IsReady() const; + + const std::string &GetClientAddr() const; + void SetClientAddr(const std::string &addr); + + ReceiveBuffer &GetReceiveBuffer(); + +private: + SOCKET m_sockfd; + const SessionId m_id; + State m_state; + std::string m_clientAddr; + ReceiveBuffer m_receiveBuffer; + bool m_readyFlag; + + mutable boost::mutex m_dataMutex; +}; + +#endif diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index dab5b94a..6e8c28f5 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -1,90 +1,90 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Thread safe server session manager. */ - -#ifndef _SESSIONMANAGER_H_ -#define _SESSIONMANAGER_H_ - -#include -#include -#include - -#include -#include -#include - -class SenderThread; -class NetPacket; - -struct SessionWrapper -{ - SessionWrapper() {} - SessionWrapper(boost::shared_ptr s, boost::shared_ptr p) - : sessionData(s), playerData(p) {} - boost::shared_ptr sessionData; - boost::shared_ptr playerData; -}; - -class SessionManager -{ -public: - SessionManager(); - virtual ~SessionManager(); - - bool HasSessions() const; - - void AddSession(boost::shared_ptr sessionData); // new Sessions without player data - void AddSession(SessionWrapper session); - void SetSessionPlayerData(SessionId session, boost::shared_ptr playerData); - void RemoveSession(SessionId session); - - SessionWrapper Select(unsigned timeoutMsec); - SessionWrapper GetSessionByPlayerName(const std::string playerName) const; - SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const; - - bool GetSocketForSession(SessionId session, SOCKET &outSocket); - - PlayerDataList GetPlayerDataList() const; - PlayerIdList GetPlayerIdList() const; - bool IsPlayerConnected(const std::string &playerName) const; - bool IsPlayerConnected(unsigned uniqueId) const; - - void ForEach(boost::function func); - - unsigned CountReadySessions() const; - void ResetAllReadyFlags(); - - void Clear(); - unsigned GetRawSessionCount(); - - void SendToAllSessions(SenderThread &sender, boost::shared_ptr packet, SessionData::State state); - void SendToAllSessionsLowPrio(SenderThread &sender, boost::shared_ptr packet, SessionData::State state); - void SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr packet, SessionId except, SessionData::State state); - -protected: - - typedef std::map SessionMap; - -private: - - SessionMap m_sessionMap; - mutable boost::mutex m_sessionMapMutex; -}; - -#endif +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Thread safe server session manager. */ + +#ifndef _SESSIONMANAGER_H_ +#define _SESSIONMANAGER_H_ + +#include +#include +#include + +#include +#include +#include + +class SenderThread; +class NetPacket; + +struct SessionWrapper +{ + SessionWrapper() {} + SessionWrapper(boost::shared_ptr s, boost::shared_ptr p) + : sessionData(s), playerData(p) {} + boost::shared_ptr sessionData; + boost::shared_ptr playerData; +}; + +class SessionManager +{ +public: + SessionManager(); + virtual ~SessionManager(); + + bool HasSessions() const; + + void AddSession(boost::shared_ptr sessionData); // new Sessions without player data + void AddSession(SessionWrapper session); + void SetSessionPlayerData(SessionId session, boost::shared_ptr playerData); + void RemoveSession(SessionId session); + + SessionWrapper Select(unsigned timeoutMsec); + SessionWrapper GetSessionByPlayerName(const std::string playerName) const; + SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const; + + bool GetSocketForSession(SessionId session, SOCKET &outSocket); + + PlayerDataList GetPlayerDataList() const; + PlayerIdList GetPlayerIdList() const; + bool IsPlayerConnected(const std::string &playerName) const; + bool IsPlayerConnected(unsigned uniqueId) const; + + void ForEach(boost::function func); + + unsigned CountReadySessions() const; + void ResetAllReadyFlags(); + + void Clear(); + unsigned GetRawSessionCount(); + + void SendToAllSessions(SenderThread &sender, boost::shared_ptr packet, SessionData::State state); + void SendToAllSessionsLowPrio(SenderThread &sender, boost::shared_ptr packet, SessionData::State state); + void SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr packet, SessionId except, SessionData::State state); + +protected: + + typedef std::map SessionMap; + +private: + + SessionMap m_sessionMap; + mutable boost::mutex m_sessionMapMutex; +}; + +#endif diff --git a/src/net/socket_helper.h b/src/net/socket_helper.h index 25b95b0e..b44a5b57 100644 --- a/src/net/socket_helper.h +++ b/src/net/socket_helper.h @@ -1,107 +1,107 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Socket helper defines and functions. */ -#ifndef _SOCKET_HELPER_H_ -#define _SOCKET_HELPER_H_ - -#include - -#ifndef bzero - #include - #define bzero(_ptr, _n) std::memset(_ptr, 0, _n) -#endif - -#ifdef _WIN32 -#define CLOSESOCKET closesocket -#define IOCTLSOCKET ioctlsocket -#define SOCKET_ERRNO() WSAGetLastError() -#define IS_SOCKET_ERR_WOULDBLOCK(_e) ((_e) == WSAEWOULDBLOCK) -#define SOCKET_ERR_NOTCONN WSAENOTCONN -#define SOCKET_ERR_NOTSOCK WSAENOTSOCK -#define SOCKET_SEND_FLAGS 0 - -#ifndef IPV6_V6ONLY - #define IPV6_V6ONLY 27 -#endif - -#ifdef __GNUC__ /* mingw provides stdint.h */ - #include - typedef uint16_t u_int16_t; - typedef uint32_t u_int32_t; -#else - typedef unsigned __int16 u_int16_t; - typedef unsigned __int32 u_int32_t; - typedef __int16 int16_t; - typedef __int32 int32_t; -#endif - -typedef unsigned char u_char; - -#else -#define SOCKET int -#define SOCKET_ERROR -1 -#define INVALID_SOCKET -1 -#define CLOSESOCKET close -#define SOCKET_ERRNO() errno -#define IOCTLSOCKET ioctl -#define SOCKET_ERR_NOTCONN ENOTCONN -#define SOCKET_ERR_NOTSOCK ENOTSOCK -#define SOCKET_SEND_FLAGS MSG_NOSIGNAL - -#define IS_SOCKET_ERR_WOULDBLOCK(_e) ((_e) == EINPROGRESS || (_e) == EAGAIN) - -#endif - -#define IS_VALID_SOCKET(_s) ((_s) != INVALID_SOCKET) -#define IS_VALID_CONNECT(_c) ((_c) == 0) -#define IS_VALID_BIND(_b) ((_b) != SOCKET_ERROR) -#define IS_VALID_LISTEN(_l) ((_l) != SOCKET_ERROR) -#define IS_VALID_RECV(_r) ((_r) != SOCKET_ERROR) -#define IS_VALID_SEND(_s) ((_s) != SOCKET_ERROR) -#define IS_VALID_SELECT(_s) ((_s) != SOCKET_ERROR) - -#define RECV_TIMEOUT_MSEC 50 - -#ifdef IPPROTO_SCTP - #define SOCKET_IPPROTO_SCTP IPPROTO_SCTP -#else - #define SOCKET_IPPROTO_SCTP 0 -#endif - -// All char *s are assumed to be UTF-8. - -/** - * Convert an address string to a numeric address. - * str is assumed to be UTF-8 encoded. - */ -bool socket_string_to_addr(const char *str, int addrFamily, struct sockaddr *addr, int addrLen); - -/** - * Resolve a name to a numeric address. - * str is assumed to be UTF-8 encoded. - */ -bool socket_resolve(const char *str, const char *port, int addrFamily, int sockType, int protocol, struct sockaddr *addr, int addrLen); - -/** - * Set the port in the sockaddr structure. - */ -bool socket_set_port(unsigned port, int addrFamily, struct sockaddr *addr, int addrLen); - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Socket helper defines and functions. */ +#ifndef _SOCKET_HELPER_H_ +#define _SOCKET_HELPER_H_ + +#include + +#ifndef bzero + #include + #define bzero(_ptr, _n) std::memset(_ptr, 0, _n) +#endif + +#ifdef _WIN32 +#define CLOSESOCKET closesocket +#define IOCTLSOCKET ioctlsocket +#define SOCKET_ERRNO() WSAGetLastError() +#define IS_SOCKET_ERR_WOULDBLOCK(_e) ((_e) == WSAEWOULDBLOCK) +#define SOCKET_ERR_NOTCONN WSAENOTCONN +#define SOCKET_ERR_NOTSOCK WSAENOTSOCK +#define SOCKET_SEND_FLAGS 0 + +#ifndef IPV6_V6ONLY + #define IPV6_V6ONLY 27 +#endif + +#ifdef __GNUC__ /* mingw provides stdint.h */ + #include + typedef uint16_t u_int16_t; + typedef uint32_t u_int32_t; +#else + typedef unsigned __int16 u_int16_t; + typedef unsigned __int32 u_int32_t; + typedef __int16 int16_t; + typedef __int32 int32_t; +#endif + +typedef unsigned char u_char; + +#else +#define SOCKET int +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 +#define CLOSESOCKET close +#define SOCKET_ERRNO() errno +#define IOCTLSOCKET ioctl +#define SOCKET_ERR_NOTCONN ENOTCONN +#define SOCKET_ERR_NOTSOCK ENOTSOCK +#define SOCKET_SEND_FLAGS MSG_NOSIGNAL + +#define IS_SOCKET_ERR_WOULDBLOCK(_e) ((_e) == EINPROGRESS || (_e) == EAGAIN) + +#endif + +#define IS_VALID_SOCKET(_s) ((_s) != INVALID_SOCKET) +#define IS_VALID_CONNECT(_c) ((_c) == 0) +#define IS_VALID_BIND(_b) ((_b) != SOCKET_ERROR) +#define IS_VALID_LISTEN(_l) ((_l) != SOCKET_ERROR) +#define IS_VALID_RECV(_r) ((_r) != SOCKET_ERROR) +#define IS_VALID_SEND(_s) ((_s) != SOCKET_ERROR) +#define IS_VALID_SELECT(_s) ((_s) != SOCKET_ERROR) + +#define RECV_TIMEOUT_MSEC 50 + +#ifdef IPPROTO_SCTP + #define SOCKET_IPPROTO_SCTP IPPROTO_SCTP +#else + #define SOCKET_IPPROTO_SCTP 0 +#endif + +// All char *s are assumed to be UTF-8. + +/** + * Convert an address string to a numeric address. + * str is assumed to be UTF-8 encoded. + */ +bool socket_string_to_addr(const char *str, int addrFamily, struct sockaddr *addr, int addrLen); + +/** + * Resolve a name to a numeric address. + * str is assumed to be UTF-8 encoded. + */ +bool socket_resolve(const char *str, const char *port, int addrFamily, int sockType, int protocol, struct sockaddr *addr, int addrLen); + +/** + * Set the port in the sockaddr structure. + */ +bool socket_set_port(unsigned port, int addrFamily, struct sockaddr *addr, int addrLen); + +#endif + diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index d709c90c..f6f992fa 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -1,128 +1,128 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Socket message definitions. */ -#ifndef _SOCKET_MSG_H_ -#define _SOCKET_MSG_H_ - -// Socket or socket related errors. -#define ERR_SOCK_INTERNAL 1 -#define ERR_SOCK_SERVERADDR_NOT_SET 2 -#define ERR_SOCK_INVALID_PORT 3 -#define ERR_SOCK_CREATION_FAILED 4 -#define ERR_SOCK_SET_ADDR_FAILED 5 -#define ERR_SOCK_SET_PORT_FAILED 6 -#define ERR_SOCK_RESOLVE_FAILED 7 -#define ERR_SOCK_BIND_FAILED 8 -#define ERR_SOCK_LISTEN_FAILED 9 -#define ERR_SOCK_ACCEPT_FAILED 10 -#define ERR_SOCK_CONNECT_FAILED 11 -#define ERR_SOCK_CONNECT_TIMEOUT 12 -#define ERR_SOCK_SELECT_FAILED 13 -#define ERR_SOCK_RECV_FAILED 14 -#define ERR_SOCK_SEND_FAILED 15 -#define ERR_SOCK_CONN_RESET 16 -#define ERR_SOCK_CONN_EXISTS 17 -#define ERR_SOCK_INVALID_PACKET 18 -#define ERR_SOCK_INVALID_STATE 19 -#define ERR_SOCK_INVALID_TYPE 20 -// The following errors are game errors. -#define ERR_NET_VERSION_NOT_SUPPORTED 101 -#define ERR_NET_SERVER_MAINTENANCE 102 -#define ERR_NET_SERVER_FULL 103 -#define ERR_NET_INVALID_PASSWORD 104 -#define ERR_NET_INVALID_PASSWORD_STR 105 -#define ERR_NET_PLAYER_NAME_IN_USE 106 -#define ERR_NET_INVALID_PLAYER_NAME 107 -#define ERR_NET_INVALID_PLAYER_CARDS 108 -#define ERR_NET_INVALID_PLAYER_RESULTS 109 -#define ERR_NET_INVALID_GAME_NAME 110 -#define ERR_NET_INVALID_GAME_ROUND 111 -#define ERR_NET_INVALID_SESSION 112 -#define ERR_NET_UNKNOWN_GAME 113 -#define ERR_NET_INVALID_CHAT_TEXT 114 -#define ERR_NET_UNKNOWN_PLAYER_ID 115 -#define ERR_NET_NO_CURRENT_PLAYER 116 -#define ERR_NET_PLAYER_NOT_ACTIVE 117 -#define ERR_NET_PLAYER_KICKED 118 -#define ERR_NET_INVALID_PLAYER_COUNT 119 -#define ERR_NET_TOO_MANY_MANUAL_BLINDS 120 -#define ERR_NET_INVALID_AVATAR_FILE 121 -#define ERR_NET_AVATAR_TOO_LARGE 122 -#define ERR_NET_BUF_INVALID_SIZE 123 -#define ERR_NET_INVALID_REQUEST_ID 124 -#define ERR_NET_WRONG_AVATAR_SIZE 125 -#define ERR_NET_START_TIMEOUT 126 -#define ERR_NET_GAME_TERMINATION_FAILED 127 -#define ERR_NET_INTERNAL_GAME_ERROR 128 -#define ERR_NET_DEALER_NOT_FOUND 129 - -#define ERR_IRC_INTERNAL 151 -#define ERR_IRC_CONNECT_FAILED 152 -#define ERR_IRC_TERMINATED 153 -#define ERR_IRC_SELECT_FAILED 154 -#define ERR_IRC_RECV_FAILED 155 -#define ERR_IRC_SEND_FAILED 156 -#define ERR_IRC_INVALID_PARAM 157 -#define ERR_IRC_TIMEOUT 158 - -// Notifications - removed from game -#define NTF_NET_INTERNAL 201 -#define NTF_NET_REMOVED_ON_REQUEST 202 -#define NTF_NET_REMOVED_GAME_FULL 203 -#define NTF_NET_REMOVED_ALREADY_RUNNING 204 -#define NTF_NET_REMOVED_KICKED 205 - -// Notifications - join failed -#define NTF_NET_JOIN_GAME_FULL 206 -#define NTF_NET_JOIN_ALREADY_RUNNING 207 -#define NTF_NET_JOIN_INVALID_PASSWORD 208 - -// Notifications - version -#define NTF_NET_NEW_RELEASE_AVAILABLE 209 -#define NTF_NET_OUTDATED_BETA 210 - -// This is an internal message which is not reported. -#define MSG_SOCK_INTERNAL_PENDING 0 - -// The following messages are connect messages. -#define MSG_SOCK_INIT_DONE 1 -#define MSG_SOCK_RESOLVE_DONE 2 -#define MSG_SOCK_CONNECT_DONE 3 -#define MSG_SOCK_SESSION_DONE 4 - -#define MSG_SOCK_LIMIT_CONNECT MSG_SOCK_SESSION_DONE -#define MSG_SOCK_LAST MSG_SOCK_SESSION_DONE - -// The following messages are game messages. -#define MSG_NET_GAME_CLIENT_JOIN 5 -#define MSG_NET_GAME_CLIENT_START 6 -#define MSG_NET_GAME_CLIENT_HAND_START 7 -#define MSG_NET_GAME_CLIENT_HAND_END 8 -#define MSG_NET_GAME_CLIENT_END 9 - -#define MSG_NET_GAME_SERVER_START 10 -#define MSG_NET_GAME_SERVER_HAND_START 11 -#define MSG_NET_GAME_SERVER_HAND_END 12 -#define MSG_NET_GAME_SERVER_ROUND 13 -#define MSG_NET_GAME_SERVER_ACTION 14 -#define MSG_NET_GAME_SERVER_CARDS_DELAY 15 -#define MSG_NET_GAME_SERVER_END 16 - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Socket message definitions. */ +#ifndef _SOCKET_MSG_H_ +#define _SOCKET_MSG_H_ + +// Socket or socket related errors. +#define ERR_SOCK_INTERNAL 1 +#define ERR_SOCK_SERVERADDR_NOT_SET 2 +#define ERR_SOCK_INVALID_PORT 3 +#define ERR_SOCK_CREATION_FAILED 4 +#define ERR_SOCK_SET_ADDR_FAILED 5 +#define ERR_SOCK_SET_PORT_FAILED 6 +#define ERR_SOCK_RESOLVE_FAILED 7 +#define ERR_SOCK_BIND_FAILED 8 +#define ERR_SOCK_LISTEN_FAILED 9 +#define ERR_SOCK_ACCEPT_FAILED 10 +#define ERR_SOCK_CONNECT_FAILED 11 +#define ERR_SOCK_CONNECT_TIMEOUT 12 +#define ERR_SOCK_SELECT_FAILED 13 +#define ERR_SOCK_RECV_FAILED 14 +#define ERR_SOCK_SEND_FAILED 15 +#define ERR_SOCK_CONN_RESET 16 +#define ERR_SOCK_CONN_EXISTS 17 +#define ERR_SOCK_INVALID_PACKET 18 +#define ERR_SOCK_INVALID_STATE 19 +#define ERR_SOCK_INVALID_TYPE 20 +// The following errors are game errors. +#define ERR_NET_VERSION_NOT_SUPPORTED 101 +#define ERR_NET_SERVER_MAINTENANCE 102 +#define ERR_NET_SERVER_FULL 103 +#define ERR_NET_INVALID_PASSWORD 104 +#define ERR_NET_INVALID_PASSWORD_STR 105 +#define ERR_NET_PLAYER_NAME_IN_USE 106 +#define ERR_NET_INVALID_PLAYER_NAME 107 +#define ERR_NET_INVALID_PLAYER_CARDS 108 +#define ERR_NET_INVALID_PLAYER_RESULTS 109 +#define ERR_NET_INVALID_GAME_NAME 110 +#define ERR_NET_INVALID_GAME_ROUND 111 +#define ERR_NET_INVALID_SESSION 112 +#define ERR_NET_UNKNOWN_GAME 113 +#define ERR_NET_INVALID_CHAT_TEXT 114 +#define ERR_NET_UNKNOWN_PLAYER_ID 115 +#define ERR_NET_NO_CURRENT_PLAYER 116 +#define ERR_NET_PLAYER_NOT_ACTIVE 117 +#define ERR_NET_PLAYER_KICKED 118 +#define ERR_NET_INVALID_PLAYER_COUNT 119 +#define ERR_NET_TOO_MANY_MANUAL_BLINDS 120 +#define ERR_NET_INVALID_AVATAR_FILE 121 +#define ERR_NET_AVATAR_TOO_LARGE 122 +#define ERR_NET_BUF_INVALID_SIZE 123 +#define ERR_NET_INVALID_REQUEST_ID 124 +#define ERR_NET_WRONG_AVATAR_SIZE 125 +#define ERR_NET_START_TIMEOUT 126 +#define ERR_NET_GAME_TERMINATION_FAILED 127 +#define ERR_NET_INTERNAL_GAME_ERROR 128 +#define ERR_NET_DEALER_NOT_FOUND 129 + +#define ERR_IRC_INTERNAL 151 +#define ERR_IRC_CONNECT_FAILED 152 +#define ERR_IRC_TERMINATED 153 +#define ERR_IRC_SELECT_FAILED 154 +#define ERR_IRC_RECV_FAILED 155 +#define ERR_IRC_SEND_FAILED 156 +#define ERR_IRC_INVALID_PARAM 157 +#define ERR_IRC_TIMEOUT 158 + +// Notifications - removed from game +#define NTF_NET_INTERNAL 201 +#define NTF_NET_REMOVED_ON_REQUEST 202 +#define NTF_NET_REMOVED_GAME_FULL 203 +#define NTF_NET_REMOVED_ALREADY_RUNNING 204 +#define NTF_NET_REMOVED_KICKED 205 + +// Notifications - join failed +#define NTF_NET_JOIN_GAME_FULL 206 +#define NTF_NET_JOIN_ALREADY_RUNNING 207 +#define NTF_NET_JOIN_INVALID_PASSWORD 208 + +// Notifications - version +#define NTF_NET_NEW_RELEASE_AVAILABLE 209 +#define NTF_NET_OUTDATED_BETA 210 + +// This is an internal message which is not reported. +#define MSG_SOCK_INTERNAL_PENDING 0 + +// The following messages are connect messages. +#define MSG_SOCK_INIT_DONE 1 +#define MSG_SOCK_RESOLVE_DONE 2 +#define MSG_SOCK_CONNECT_DONE 3 +#define MSG_SOCK_SESSION_DONE 4 + +#define MSG_SOCK_LIMIT_CONNECT MSG_SOCK_SESSION_DONE +#define MSG_SOCK_LAST MSG_SOCK_SESSION_DONE + +// The following messages are game messages. +#define MSG_NET_GAME_CLIENT_JOIN 5 +#define MSG_NET_GAME_CLIENT_START 6 +#define MSG_NET_GAME_CLIENT_HAND_START 7 +#define MSG_NET_GAME_CLIENT_HAND_END 8 +#define MSG_NET_GAME_CLIENT_END 9 + +#define MSG_NET_GAME_SERVER_START 10 +#define MSG_NET_GAME_SERVER_HAND_START 11 +#define MSG_NET_GAME_SERVER_HAND_END 12 +#define MSG_NET_GAME_SERVER_ROUND 13 +#define MSG_NET_GAME_SERVER_ACTION 14 +#define MSG_NET_GAME_SERVER_CARDS_DELAY 15 +#define MSG_NET_GAME_SERVER_END 16 + +#endif + diff --git a/src/net/socket_startup.h b/src/net/socket_startup.h index 057c1a31..d387f3c5 100644 --- a/src/net/socket_startup.h +++ b/src/net/socket_startup.h @@ -1,31 +1,31 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Socket startup/cleanup/detection functions. */ -#ifndef _SOCKET_STARTUP_H_ -#define _SOCKET_STARTUP_H_ - -bool socket_startup(); -void socket_cleanup(); - -bool socket_has_sctp(); -bool socket_has_ipv6(); -bool socket_has_dual_stack(); - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Socket startup/cleanup/detection functions. */ +#ifndef _SOCKET_STARTUP_H_ +#define _SOCKET_STARTUP_H_ + +bool socket_startup(); +void socket_cleanup(); + +bool socket_has_sctp(); +bool socket_has_ipv6(); +bool socket_has_dual_stack(); + +#endif + diff --git a/src/net/win32/socket_helper.cpp b/src/net/win32/socket_helper.cpp index c62873b7..02c217e7 100644 --- a/src/net/win32/socket_helper.cpp +++ b/src/net/win32/socket_helper.cpp @@ -1,137 +1,137 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef _WIN32 -#error This source code is Win32 only. -#endif - -#include - -#include -#include -#include - -using namespace std; - -typedef int (WSAAPI * getaddrinfo_ptr_t) (const char *, const char* , const struct addrinfo *, struct addrinfo **); -typedef void (WSAAPI * freeaddrinfo_ptr_t) (struct addrinfo*); - -static wstring -utf8ToWchar(const char *str) -{ - // convert str from UTF-8 to UTF-16 (Win32 byte order) - wstring retStr; - if (str) - { - size_t len = strlen(str) + 1; - if (len > 1) - { - size_t reqLen = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, len, NULL, 0); - - if (reqLen) - { - wchar_t *wstr = new wchar_t[reqLen]; - wstr[0] = L'\0'; - if (::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, len, wstr, reqLen) == (int)reqLen) - retStr = wstr; - delete[] wstr; - } - } - } - return retStr; -} - -bool -socket_string_to_addr(const char *str, int addrFamily, struct sockaddr * addr, int addrLen) -{ - bool retVal = false; -#ifdef UNICODE - // convert str from UTF-8 to UTF-16 (Win32 byte order) - wstring wstr(utf8ToWchar(str)); - if (!wstr.empty()) - retVal = (WSAStringToAddress((LPWSTR)wstr.c_str(), addrFamily, NULL, addr, &addrLen) != SOCKET_ERROR); -#else - if (str && *str != 0) - retVal = (WSAStringToAddress(str, addrFamily, NULL, addr, &addrLen) != SOCKET_ERROR); -#endif - - return retVal; -} - -bool -socket_resolve(const char *str, const char *port, int addrFamily, int sockType, int protocol, struct sockaddr *addr, int addrLen) -{ - bool retVal = false; - bool useGetaddrinfo = false; - - if (str && *str != 0) - { - HMODULE hWsock = ::LoadLibraryA("ws2_32"); - - if (hWsock) - { - // Determine functions at runtime, because windows systems < XP do not - // support getaddrinfo. - getaddrinfo_ptr_t getaddrinfo_ptr = (getaddrinfo_ptr_t)::GetProcAddress(hWsock, "getaddrinfo"); - freeaddrinfo_ptr_t freeaddrinfo_ptr = (freeaddrinfo_ptr_t)::GetProcAddress(hWsock, "freeaddrinfo"); - - if (getaddrinfo_ptr && freeaddrinfo_ptr) - { - useGetaddrinfo = true; - - struct addrinfo aiHints; - struct addrinfo *aiList = NULL; - - memset(&aiHints, 0, sizeof(aiHints)); - aiHints.ai_family = addrFamily; - aiHints.ai_socktype = sockType; - aiHints.ai_protocol = protocol; - - // Try to resolve the name. - bool success = (getaddrinfo_ptr(str, port, &aiHints, &aiList) == 0); - - if (success && aiList) - { - if ((int)aiList->ai_addrlen <= addrLen) - { - memcpy(addr, aiList->ai_addr, aiList->ai_addrlen); - retVal = true; - } - freeaddrinfo_ptr(aiList); - } - } - ::FreeLibrary(hWsock); - } - // If we cannot use getaddrinfo (OS older than XP), - // we call the "classic" gethostbyname. - if (!useGetaddrinfo && addrFamily == AF_INET) - { - struct hostent *host = gethostbyname(str); - if (host && host->h_addr_list) - { - struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; - addr_in->sin_family = AF_INET; - addr_in->sin_port = htons(atoi(port)); - memcpy(&addr_in->sin_addr, host->h_addr_list[0], host->h_length); - retVal = true; - } - } - } - return retVal; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef _WIN32 +#error This source code is Win32 only. +#endif + +#include + +#include +#include +#include + +using namespace std; + +typedef int (WSAAPI * getaddrinfo_ptr_t) (const char *, const char* , const struct addrinfo *, struct addrinfo **); +typedef void (WSAAPI * freeaddrinfo_ptr_t) (struct addrinfo*); + +static wstring +utf8ToWchar(const char *str) +{ + // convert str from UTF-8 to UTF-16 (Win32 byte order) + wstring retStr; + if (str) + { + size_t len = strlen(str) + 1; + if (len > 1) + { + size_t reqLen = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, len, NULL, 0); + + if (reqLen) + { + wchar_t *wstr = new wchar_t[reqLen]; + wstr[0] = L'\0'; + if (::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, len, wstr, reqLen) == (int)reqLen) + retStr = wstr; + delete[] wstr; + } + } + } + return retStr; +} + +bool +socket_string_to_addr(const char *str, int addrFamily, struct sockaddr * addr, int addrLen) +{ + bool retVal = false; +#ifdef UNICODE + // convert str from UTF-8 to UTF-16 (Win32 byte order) + wstring wstr(utf8ToWchar(str)); + if (!wstr.empty()) + retVal = (WSAStringToAddress((LPWSTR)wstr.c_str(), addrFamily, NULL, addr, &addrLen) != SOCKET_ERROR); +#else + if (str && *str != 0) + retVal = (WSAStringToAddress(str, addrFamily, NULL, addr, &addrLen) != SOCKET_ERROR); +#endif + + return retVal; +} + +bool +socket_resolve(const char *str, const char *port, int addrFamily, int sockType, int protocol, struct sockaddr *addr, int addrLen) +{ + bool retVal = false; + bool useGetaddrinfo = false; + + if (str && *str != 0) + { + HMODULE hWsock = ::LoadLibraryA("ws2_32"); + + if (hWsock) + { + // Determine functions at runtime, because windows systems < XP do not + // support getaddrinfo. + getaddrinfo_ptr_t getaddrinfo_ptr = (getaddrinfo_ptr_t)::GetProcAddress(hWsock, "getaddrinfo"); + freeaddrinfo_ptr_t freeaddrinfo_ptr = (freeaddrinfo_ptr_t)::GetProcAddress(hWsock, "freeaddrinfo"); + + if (getaddrinfo_ptr && freeaddrinfo_ptr) + { + useGetaddrinfo = true; + + struct addrinfo aiHints; + struct addrinfo *aiList = NULL; + + memset(&aiHints, 0, sizeof(aiHints)); + aiHints.ai_family = addrFamily; + aiHints.ai_socktype = sockType; + aiHints.ai_protocol = protocol; + + // Try to resolve the name. + bool success = (getaddrinfo_ptr(str, port, &aiHints, &aiList) == 0); + + if (success && aiList) + { + if ((int)aiList->ai_addrlen <= addrLen) + { + memcpy(addr, aiList->ai_addr, aiList->ai_addrlen); + retVal = true; + } + freeaddrinfo_ptr(aiList); + } + } + ::FreeLibrary(hWsock); + } + // If we cannot use getaddrinfo (OS older than XP), + // we call the "classic" gethostbyname. + if (!useGetaddrinfo && addrFamily == AF_INET) + { + struct hostent *host = gethostbyname(str); + if (host && host->h_addr_list) + { + struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; + addr_in->sin_family = AF_INET; + addr_in->sin_port = htons(atoi(port)); + memcpy(&addr_in->sin_addr, host->h_addr_list[0], host->h_length); + retVal = true; + } + } + } + return retVal; +} + diff --git a/src/net/win32/socket_startup.cpp b/src/net/win32/socket_startup.cpp index 2aec0c21..e5607f5d 100644 --- a/src/net/win32/socket_startup.cpp +++ b/src/net/win32/socket_startup.cpp @@ -1,68 +1,68 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef _WIN32 -#error This source code is Win32 only. -#endif - -#include -#include - -#define USE_SOCKET_VERSION_MAJOR 2 -#define USE_SOCKET_VERSION_MINOR 2 - -bool -socket_startup() -{ - WORD wVersionRequested; - WSADATA wsaData; - int err; - - wVersionRequested = MAKEWORD(USE_SOCKET_VERSION_MAJOR, USE_SOCKET_VERSION_MINOR); - err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) - { - /* Tell the user that we could not find a usable */ - /* WinSock DLL. */ - return false; - } - - /* Confirm that the WinSock DLL supports 2.2.*/ - /* Note that if the DLL supports versions greater */ - /* than 2.2 in addition to 2.2, it will still return */ - /* 2.2 in wVersion since that is the version we */ - /* requested. */ - - if (LOBYTE(wsaData.wVersion) != USE_SOCKET_VERSION_MAJOR || - HIBYTE(wsaData.wVersion) != USE_SOCKET_VERSION_MINOR) { - /* Tell the user that we could not find a usable */ - /* WinSock DLL. */ - WSACleanup(); - return false; - } - - /* The WinSock DLL is acceptable. Proceed. */ - return true; -} - -void -socket_cleanup() -{ - WSACleanup(); -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef _WIN32 +#error This source code is Win32 only. +#endif + +#include +#include + +#define USE_SOCKET_VERSION_MAJOR 2 +#define USE_SOCKET_VERSION_MINOR 2 + +bool +socket_startup() +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(USE_SOCKET_VERSION_MAJOR, USE_SOCKET_VERSION_MINOR); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) + { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + return false; + } + + /* Confirm that the WinSock DLL supports 2.2.*/ + /* Note that if the DLL supports versions greater */ + /* than 2.2 in addition to 2.2, it will still return */ + /* 2.2 in wVersion since that is the version we */ + /* requested. */ + + if (LOBYTE(wsaData.wVersion) != USE_SOCKET_VERSION_MAJOR || + HIBYTE(wsaData.wVersion) != USE_SOCKET_VERSION_MINOR) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + WSACleanup(); + return false; + } + + /* The WinSock DLL is acceptable. Proceed. */ + return true; +} + +void +socket_cleanup() +{ + WSACleanup(); +} + diff --git a/src/playerdata.cpp b/src/playerdata.cpp index f67b145f..7e865977 100644 --- a/src/playerdata.cpp +++ b/src/playerdata.cpp @@ -1,162 +1,162 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -using namespace std; - -PlayerData::PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights) -: m_uniqueId(uniqueId), m_number(number), m_type(type), m_rights(rights) -{ -} - -PlayerData::PlayerData(const PlayerData &other) -: m_uniqueId(other.GetUniqueId()), m_number(other.GetNumber()), m_name(other.GetName()), - m_avatarFile(other.GetAvatarFile()), m_type(other.GetType()), m_rights(other.GetRights()), - m_netSessionData(other.GetNetSessionData()) -{ -} - -PlayerData::~PlayerData() -{ -} - -string -PlayerData::GetName() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_name; -} - -void -PlayerData::SetName(const std::string &name) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_name = name; -} - -string -PlayerData::GetAvatarFile() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_avatarFile; -} - -void -PlayerData::SetAvatarFile(const std::string &avatarFile) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_avatarFile = avatarFile; -} - -MD5Buf -PlayerData::GetAvatarMD5() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_avatarMD5; -} -void -PlayerData::SetAvatarMD5(const MD5Buf &avatarMD5) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_avatarMD5 = avatarMD5; -} - -boost::shared_ptr -PlayerData::GetNetSessionData() const -{ - // setting/getting boost::shared_ptr is thread safe. - return m_netSessionData; -} - -void -PlayerData::SetNetSessionData(boost::shared_ptr session) -{ - // setting/getting boost::shared_ptr is thread safe. - m_netSessionData = session; -} - -boost::shared_ptr -PlayerData::GetNetAvatarData() const -{ - return m_netAvatarData; -} - -void -PlayerData::SetNetAvatarData(boost::shared_ptr avatarData) -{ - m_netAvatarData = avatarData; -} - -PlayerType -PlayerData::GetType() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_type; -} - -void -PlayerData::SetType(PlayerType type) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_type = type; -} - -PlayerRights -PlayerData::GetRights() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_rights; -} - -void -PlayerData::SetRights(PlayerRights rights) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_rights = rights; -} - -unsigned -PlayerData::GetUniqueId() const -{ - // const value - no mutex needed. - return m_uniqueId; -} - -int -PlayerData::GetNumber() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_number; -} - -void -PlayerData::SetNumber(int number) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_number = number; -} - -bool -PlayerData::operator<(const PlayerData &other) const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_number < other.GetNumber(); -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +using namespace std; + +PlayerData::PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights) +: m_uniqueId(uniqueId), m_number(number), m_type(type), m_rights(rights) +{ +} + +PlayerData::PlayerData(const PlayerData &other) +: m_uniqueId(other.GetUniqueId()), m_number(other.GetNumber()), m_name(other.GetName()), + m_avatarFile(other.GetAvatarFile()), m_type(other.GetType()), m_rights(other.GetRights()), + m_netSessionData(other.GetNetSessionData()) +{ +} + +PlayerData::~PlayerData() +{ +} + +string +PlayerData::GetName() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_name; +} + +void +PlayerData::SetName(const std::string &name) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_name = name; +} + +string +PlayerData::GetAvatarFile() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_avatarFile; +} + +void +PlayerData::SetAvatarFile(const std::string &avatarFile) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_avatarFile = avatarFile; +} + +MD5Buf +PlayerData::GetAvatarMD5() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_avatarMD5; +} +void +PlayerData::SetAvatarMD5(const MD5Buf &avatarMD5) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_avatarMD5 = avatarMD5; +} + +boost::shared_ptr +PlayerData::GetNetSessionData() const +{ + // setting/getting boost::shared_ptr is thread safe. + return m_netSessionData; +} + +void +PlayerData::SetNetSessionData(boost::shared_ptr session) +{ + // setting/getting boost::shared_ptr is thread safe. + m_netSessionData = session; +} + +boost::shared_ptr +PlayerData::GetNetAvatarData() const +{ + return m_netAvatarData; +} + +void +PlayerData::SetNetAvatarData(boost::shared_ptr avatarData) +{ + m_netAvatarData = avatarData; +} + +PlayerType +PlayerData::GetType() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_type; +} + +void +PlayerData::SetType(PlayerType type) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_type = type; +} + +PlayerRights +PlayerData::GetRights() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_rights; +} + +void +PlayerData::SetRights(PlayerRights rights) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_rights = rights; +} + +unsigned +PlayerData::GetUniqueId() const +{ + // const value - no mutex needed. + return m_uniqueId; +} + +int +PlayerData::GetNumber() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_number; +} + +void +PlayerData::SetNumber(int number) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_number = number; +} + +bool +PlayerData::operator<(const PlayerData &other) const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_number < other.GetNumber(); +} + diff --git a/src/playerdata.h b/src/playerdata.h index ebdbb30a..8cc0ab4f 100644 --- a/src/playerdata.h +++ b/src/playerdata.h @@ -1,117 +1,117 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Player data. */ - -#ifndef _PLAYERDATA_H_ -#define _PLAYERDATA_H_ - -#include -#include -#include -#include -#include -#include -#include - -class SessionData; - -enum PlayerType -{ - PLAYER_TYPE_COMPUTER, - PLAYER_TYPE_HUMAN -}; - -enum PlayerRights -{ - PLAYER_RIGHTS_NORMAL, - PLAYER_RIGHTS_ADMIN -}; - -enum AvatarFileType -{ - AVATAR_FILE_TYPE_UNKNOWN = 0, - AVATAR_FILE_TYPE_PNG, - AVATAR_FILE_TYPE_JPG, - AVATAR_FILE_TYPE_GIF -}; - -struct AvatarData -{ - AvatarData() : fileType(AVATAR_FILE_TYPE_UNKNOWN), reportedSize(0) {} - std::vector fileData; - AvatarFileType fileType; - unsigned reportedSize; -}; - -struct PlayerInfo -{ - PlayerInfo() : ptype(PLAYER_TYPE_HUMAN) {} - std::string playerName; - PlayerType ptype; - bool hasAvatar; - MD5Buf avatar; -}; - -class PlayerData -{ -public: - PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights); - PlayerData(const PlayerData &other); - ~PlayerData(); - - std::string GetName() const; - void SetName(const std::string &name); - std::string GetAvatarFile() const; - void SetAvatarFile(const std::string &avatarFile); - MD5Buf GetAvatarMD5() const; - void SetAvatarMD5(const MD5Buf &avatarMD5); - boost::shared_ptr GetNetSessionData() const; - void SetNetSessionData(boost::shared_ptr session); - boost::shared_ptr GetNetAvatarData() const; - void SetNetAvatarData(boost::shared_ptr avatarData); - PlayerType GetType() const; - void SetType(PlayerType type); - PlayerRights GetRights() const; - void SetRights(PlayerRights rights); - unsigned GetUniqueId() const; - int GetNumber() const; - void SetNumber(int number); - - bool operator<(const PlayerData &other) const; - -private: - const unsigned m_uniqueId; - int m_number; - std::string m_name; - std::string m_avatarFile; - MD5Buf m_avatarMD5; - PlayerType m_type; - PlayerRights m_rights; - boost::shared_ptr m_netSessionData; - boost::shared_ptr m_netAvatarData; - - mutable boost::mutex m_dataMutex; -}; - -typedef std::list PlayerIdList; -typedef std::list > PlayerDataList; -typedef std::map > PlayerDataMap; - -#endif - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Player data. */ + +#ifndef _PLAYERDATA_H_ +#define _PLAYERDATA_H_ + +#include +#include +#include +#include +#include +#include +#include + +class SessionData; + +enum PlayerType +{ + PLAYER_TYPE_COMPUTER, + PLAYER_TYPE_HUMAN +}; + +enum PlayerRights +{ + PLAYER_RIGHTS_NORMAL, + PLAYER_RIGHTS_ADMIN +}; + +enum AvatarFileType +{ + AVATAR_FILE_TYPE_UNKNOWN = 0, + AVATAR_FILE_TYPE_PNG, + AVATAR_FILE_TYPE_JPG, + AVATAR_FILE_TYPE_GIF +}; + +struct AvatarData +{ + AvatarData() : fileType(AVATAR_FILE_TYPE_UNKNOWN), reportedSize(0) {} + std::vector fileData; + AvatarFileType fileType; + unsigned reportedSize; +}; + +struct PlayerInfo +{ + PlayerInfo() : ptype(PLAYER_TYPE_HUMAN) {} + std::string playerName; + PlayerType ptype; + bool hasAvatar; + MD5Buf avatar; +}; + +class PlayerData +{ +public: + PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights); + PlayerData(const PlayerData &other); + ~PlayerData(); + + std::string GetName() const; + void SetName(const std::string &name); + std::string GetAvatarFile() const; + void SetAvatarFile(const std::string &avatarFile); + MD5Buf GetAvatarMD5() const; + void SetAvatarMD5(const MD5Buf &avatarMD5); + boost::shared_ptr GetNetSessionData() const; + void SetNetSessionData(boost::shared_ptr session); + boost::shared_ptr GetNetAvatarData() const; + void SetNetAvatarData(boost::shared_ptr avatarData); + PlayerType GetType() const; + void SetType(PlayerType type); + PlayerRights GetRights() const; + void SetRights(PlayerRights rights); + unsigned GetUniqueId() const; + int GetNumber() const; + void SetNumber(int number); + + bool operator<(const PlayerData &other) const; + +private: + const unsigned m_uniqueId; + int m_number; + std::string m_name; + std::string m_avatarFile; + MD5Buf m_avatarMD5; + PlayerType m_type; + PlayerRights m_rights; + boost::shared_ptr m_netSessionData; + boost::shared_ptr m_netAvatarData; + + mutable boost::mutex m_dataMutex; +}; + +typedef std::list PlayerIdList; +typedef std::list > PlayerDataList; +typedef std::map > PlayerDataMap; + +#endif + diff --git a/src/pokerth_server.cpp b/src/pokerth_server.cpp index 7c8d9941..83e0b96b 100644 --- a/src/pokerth_server.cpp +++ b/src/pokerth_server.cpp @@ -1,108 +1,108 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#include "session.h" -#include "configfile.h" -#include -#include -#include - -#include - -#ifdef _MSC_VER - #ifdef _DEBUG - #define _CRTDBG_MAP_ALLOC - #include - - #define ENABLE_LEAK_CHECK() \ - { \ - int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); \ - tmpFlag |= _CRTDBG_LEAK_CHECK_DF; \ - _CrtSetDbgFlag(tmpFlag); \ - } - #endif -#endif - -#ifndef ENABLE_LEAK_CHECK - #define ENABLE_LEAK_CHECK() -#endif - -using namespace std; - -volatile int g_pokerthTerminate = 0; - -void -TerminateHandler(int /*signal*/) -{ - g_pokerthTerminate = 1; -} - -// TODO: Hack -#ifndef _WIN32 - #include - #ifndef daemon - int daemon(int, int); - #endif -#endif - -int -main(int argc, char *argv[]) -{ - ENABLE_LEAK_CHECK(); - -// _CrtSetBreakAlloc(4772); - - //create defaultconfig - ConfigFile *myConfig = new ConfigFile(argc, argv); - - // TODO: Hack -#ifndef _WIN32 - daemon(0, 0); -#endif - - signal(SIGTERM, TerminateHandler); - signal(SIGINT, TerminateHandler); - - socket_startup(); - - LOG_MSG("Starting PokerTH dedicated server. Availability: IPv6 " - << socket_has_ipv6() << ", SCTP " << socket_has_sctp() << ", Dual Stack " << socket_has_dual_stack() << "."); - - // Create pseudo Gui Wrapper for the server. - boost::shared_ptr myServerGuiInterface(new ServerGuiWrapper(myConfig, NULL, NULL, NULL)); - boost::shared_ptr session(new Session(myServerGuiInterface.get(), myConfig)); - if (!session->init()) - LOG_ERROR("Missing files - please check your directory settings!"); - myServerGuiInterface->setSession(session); - - myServerGuiInterface->getSession().startNetworkServer(); - while (!g_pokerthTerminate) - { - if (myServerGuiInterface->getSession().waitForNetworkServer(100)) - g_pokerthTerminate = true; - } - myServerGuiInterface->getSession().terminateNetworkServer(); - - LOG_MSG("Terminating PokerTH dedicated server."); - socket_cleanup(); - return 0; -} - +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "session.h" +#include "configfile.h" +#include +#include +#include + +#include + +#ifdef _MSC_VER + #ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + + #define ENABLE_LEAK_CHECK() \ + { \ + int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); \ + tmpFlag |= _CRTDBG_LEAK_CHECK_DF; \ + _CrtSetDbgFlag(tmpFlag); \ + } + #endif +#endif + +#ifndef ENABLE_LEAK_CHECK + #define ENABLE_LEAK_CHECK() +#endif + +using namespace std; + +volatile int g_pokerthTerminate = 0; + +void +TerminateHandler(int /*signal*/) +{ + g_pokerthTerminate = 1; +} + +// TODO: Hack +#ifndef _WIN32 + #include + #ifndef daemon + int daemon(int, int); + #endif +#endif + +int +main(int argc, char *argv[]) +{ + ENABLE_LEAK_CHECK(); + +// _CrtSetBreakAlloc(4772); + + //create defaultconfig + ConfigFile *myConfig = new ConfigFile(argc, argv); + + // TODO: Hack +#ifndef _WIN32 + daemon(0, 0); +#endif + + signal(SIGTERM, TerminateHandler); + signal(SIGINT, TerminateHandler); + + socket_startup(); + + LOG_MSG("Starting PokerTH dedicated server. Availability: IPv6 " + << socket_has_ipv6() << ", SCTP " << socket_has_sctp() << ", Dual Stack " << socket_has_dual_stack() << "."); + + // Create pseudo Gui Wrapper for the server. + boost::shared_ptr myServerGuiInterface(new ServerGuiWrapper(myConfig, NULL, NULL, NULL)); + boost::shared_ptr session(new Session(myServerGuiInterface.get(), myConfig)); + if (!session->init()) + LOG_ERROR("Missing files - please check your directory settings!"); + myServerGuiInterface->setSession(session); + + myServerGuiInterface->getSession().startNetworkServer(); + while (!g_pokerthTerminate) + { + if (myServerGuiInterface->getSession().waitForNetworkServer(100)) + g_pokerthTerminate = true; + } + myServerGuiInterface->getSession().terminateNetworkServer(); + + LOG_MSG("Terminating PokerTH dedicated server."); + socket_cleanup(); + return 0; +} +