From ccc59ecdafbee07dc8c01a5c4160590404500101 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 8 Jan 2009 16:11:59 -0500 Subject: [PATCH] Pre-emptive removal of gamedata updater pending rewrite. --- configs/core.cfg | 10 - core/GameConfigs.cpp | 3 +- core/GameDataFetcher.cpp | 911 ------------------------------ core/GameDataFetcher.h | 106 ---- core/Makefile | 2 +- core/msvc9/sourcemod_mm.vcproj | 8 - tools/daemon/Makefile | 76 --- tools/daemon/smud.cpp | 157 ----- tools/daemon/smud.h | 25 - tools/daemon/smud_connections.cpp | 541 ------------------ tools/daemon/smud_connections.h | 116 ---- tools/daemon/smud_threads.cpp | 86 --- tools/daemon/smud_threads.h | 41 -- tools/daemon/updateGameData.sh | 30 - 14 files changed, 3 insertions(+), 2109 deletions(-) delete mode 100644 core/GameDataFetcher.cpp delete mode 100644 core/GameDataFetcher.h delete mode 100644 tools/daemon/Makefile delete mode 100644 tools/daemon/smud.cpp delete mode 100644 tools/daemon/smud.h delete mode 100644 tools/daemon/smud_connections.cpp delete mode 100644 tools/daemon/smud_connections.h delete mode 100644 tools/daemon/smud_threads.cpp delete mode 100644 tools/daemon/smud_threads.h delete mode 100644 tools/daemon/updateGameData.sh diff --git a/configs/core.cfg b/configs/core.cfg index 02889b7c..8ee957e8 100644 --- a/configs/core.cfg +++ b/configs/core.cfg @@ -104,16 +104,6 @@ */ "ForceRestartAfterUpdate" "no" - /** - * Sets the server to connect to for auotmatic gamedata updates. - */ - "AutoUpdateServer" "smupdate.alliedmods.net" - - /** - * Sets the port to connect to on the AutoUpdateServer server - */ - "AutoUpdatePort" "6500" - /** * Whether to show debug spew. * Currently this will log details about the gamedata updating process. diff --git a/core/GameConfigs.cpp b/core/GameConfigs.cpp index 726c1744..0897f49a 100644 --- a/core/GameConfigs.cpp +++ b/core/GameConfigs.cpp @@ -42,7 +42,6 @@ #include "LibrarySys.h" #include "HandleSys.h" #include "sm_crc32.h" -#include "GameDataFetcher.h" #if defined PLATFORM_LINUX #include @@ -680,12 +679,14 @@ void GameConfigManager::OnSourceModAllShutdown() bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength) { +#if 0 /* A crash was detected during last load - We block the gamedata loading so it hopefully won't happen again */ if (g_blockGameDataLoad) { UTIL_Format(error, maxlength, "GameData loaded blocked due to detected crash"); return false; } +#endif CGameConfig *pConfig; diff --git a/core/GameDataFetcher.cpp b/core/GameDataFetcher.cpp deleted file mode 100644 index fa4c8e1e..00000000 --- a/core/GameDataFetcher.cpp +++ /dev/null @@ -1,911 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "GameDataFetcher.h" -#include "bitbuf.h" - -#ifdef PLATFORM_WINDOWS -#include -#else -#include -#include -#include -#include -#include -#include - -#define INVALID_SOCKET -1 -#define closesocket close -#define WSAGetLastError() errno -#endif - -#include "sh_vector.h" -#include "sh_string.h" -#include "sm_version.h" - -#if SOURCE_ENGINE == SE_LEFT4DEAD -#include "convar_sm_l4d.h" -#elif SOURCE_ENGINE == SE_ORANGEBOX -#include "convar_sm_ob.h" -#else -#include "convar_sm.h" -#endif - -#include "sourcemm_api.h" -#include "time.h" -#include "TimerSys.h" -#include "compat_wrappers.h" -#include "sm_stringutil.h" -#include "md5.h" -#include "frame_hooks.h" - -#define QUERY_MAX_LENGTH 1024 - -static BuildMD5ableBuffer g_MD5Builder; -static FetcherThread g_FetchThread; - -static FILE *logfile = NULL; - -bool g_disableGameDataUpdate = false; - -/** - * Note on this. If we issue a reload and changelevel, my srcds.exe will emit - * Assertion Failed: !m_bServiceStarted - * on quit. This seems like a non-issue, because before we just terminated the - * server anyway. If anyone notices and files a bug, we can look into it further. - */ -bool g_restartAfterUpdate = false; - -static bool was_level_started = false; -static int g_serverPort = 6500; -static char g_serverAddress[100] = "smupdate.alliedmods.net"; - -static void _ForceRestart(void *data) -{ - char cmd[300]; - g_Logger.LogMessage("Automatically restarting SourceMod after a successful gamedata update."); - UTIL_Format(cmd, sizeof(cmd), "meta unload %d\n", g_PLID); - engine->ServerCommand(cmd); - UTIL_Format(cmd, sizeof(cmd), "changelevel \"%s\"\n", STRING(gpGlobals->mapname)); - engine->ServerCommand(cmd); - UTIL_Format(cmd, sizeof(cmd), "echo SourceMod restarted after gamedata update.\n"); - engine->ServerCommand(cmd); -} - -static void ForceRestart() -{ - FrameAction action; - - action.action = _ForceRestart; - action.data = NULL; - AddFrameAction(action); -} - -void FetcherThread::RunThread(IThreadHandle *pHandle) -{ - char lock_path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp"); - g_LibSys.CreateFolder(lock_path); - - g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp/gamedata.lock"); - - char log_path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_SM, log_path, sizeof(log_path), "logs/gamedata"); - - g_LibSys.CreateFolder(log_path); - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - g_SourceMod.BuildPath(Path_SM, - log_path, - sizeof(log_path), - "logs/gamedata/L%04d%02d%02d.log", - curtime->tm_year + 1900, - curtime->tm_mon + 1, - curtime->tm_mday); - - logfile = fopen(log_path, "at"); - - if (!logfile) - { - /* :( */ - return; - } - - //Create a blank lock file - FILE *fp = fopen(lock_path, "w"); - if (fp) - { - fclose(fp); - } - - char query[QUERY_MAX_LENGTH]; - - /* Check for updated gamedata files */ - int len = BuildGameDataQuery(query, QUERY_MAX_LENGTH); - - if (len == 0) - { - g_Logger.LogToFileOnly(logfile, "Could not build gamedata query!"); - fclose(logfile); - unlink(lock_path); - return; - } - - /* We check this late so we have the MD5 sums available. This may change in the future. */ - if (g_disableGameDataUpdate) - { - g_Logger.LogToFileOnly(logfile, "Skipping gamedata fetcher (DisableAutoUpdate set)"); - fclose(logfile); - unlink(lock_path); - return; - } - - /* Create a new socket for this connection */ - int socketDescriptor = ConnectSocket(); - - if (socketDescriptor == INVALID_SOCKET) - { - fclose(logfile); - unlink(lock_path); - return; - } - - int sent = SendData(socketDescriptor, query, len); - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Sent gamedata query"); -ENDIF_DEBUG_SPEW - - if (sent == 0) - { -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Failed to send gamedata query data to remote host"); -ENDIF_DEBUG_SPEW - - closesocket(socketDescriptor); - fclose(logfile); - unlink(lock_path); - return; - } - - ProcessGameDataQuery(socketDescriptor); - - /* And we're done! */ - closesocket(socketDescriptor); - fclose(logfile); - unlink(lock_path); -} - -void FetcherThread::OnTerminate(IThreadHandle *pHandle, bool cancel) -{ - g_blockGameDataLoad = false; - - if (cancel) - { - return; - } - - if (wasSuccess) - { - HandleUpdateStatus(updateStatus, build); - - if (needsRestart) - { - if (g_restartAfterUpdate) - { - if (was_level_started) - { - ForceRestart(); - } - } - else - { - g_Logger.LogMessage("Your gamedata files have been updated, please restart your server."); - } - } - } - else if (!g_disableGameDataUpdate) - { - g_Logger.LogError("An error occurred in the gamedata fetcher, see your gamedata log files for more information."); - } -} - -int FetcherThread::BuildGameDataQuery(char *buffer, int maxlen) -{ - char gamedata_path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_SM, gamedata_path, sizeof(gamedata_path), "gamedata"); - - IDirectory *dir = g_LibSys.OpenDirectory(gamedata_path); - - if (dir == NULL) - { - return 0; - } - - bf_write Writer = bf_write("GameDataQuery", buffer, maxlen); - - Writer.WriteByte('A'); //Generic Header char - Writer.WriteByte('G'); //G for gamedata query, or green, like my hat. - - short build[4] = { SVN_FILE_VERSION }; - - Writer.WriteBytes(&build[0], 8); - - Writer.WriteByte(0); // Initialize the file counter - Index 10 - - while (dir->MoreFiles()) - { - if (dir->IsEntryFile()) - { - const char *name = dir->GetEntryName(); - size_t len = strlen(name); - if (len >= 4 && strcmp(&name[len-4], ".txt") == 0) - { - MD5 md5; - SMCError err; - SMCStates states; - unsigned char raw[16]; - char file[PLATFORM_MAX_PATH]; - - g_LibSys.PathFormat(file, sizeof(file), "%s/%s", gamedata_path, name); - - g_MD5Builder.checksum = &md5; - if ((err = g_TextParser.ParseFile_SMC(file, &g_MD5Builder, &states)) == SMCError_Okay) - { - md5.raw_digest(raw); - (uint8_t)buffer[10]++; //Increment the file counter - Writer.WriteBytes(raw, 16); - - FileData *data = new FileData(); - data->filename = new SourceHook::String(file); - md5.hex_digest(data->checksum); - filenames.push_back(data); - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Parsed file: %s as %s", file, data->checksum); -ENDIF_DEBUG_SPEW - - } - else - { -IF_DEBUG_SPEW - const char *error = g_TextParser.GetSMCErrorString(err); - g_Logger.LogToFileOnly(logfile, "Parsing of file %s failed: %s", file, error); -ENDIF_DEBUG_SPEW - } - } - } - dir->NextEntry(); - } - - return Writer.GetNumBytesWritten(); -} - -int FetcherThread::ConnectSocket() -{ -#if defined PLATFORM_WINDOWS - WSADATA wsaData; - WSAStartup(0x0101, &wsaData); -#endif - - struct protoent *ptrp; - - if ((ptrp = getprotobyname("tcp")) == NULL) - { - g_Logger.LogToFileOnly(logfile, "Error: Failed to find TCP protocol"); - return INVALID_SOCKET; - } - - int socketDescriptor = socket(AF_INET, SOCK_STREAM, ptrp->p_proto); - - if (socketDescriptor == INVALID_SOCKET) - { - char error[255]; - g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error)); - g_Logger.LogToFileOnly(logfile, "Error: Failed to create socket: %s", error); - closesocket(socketDescriptor); - return INVALID_SOCKET; - } - - struct hostent *he; - struct sockaddr_in local_addr; - - local_addr.sin_family = AF_INET; - local_addr.sin_port = htons((u_short)g_serverPort); - - he = gethostbyname(g_serverAddress); - - if (!he) - { - if ((local_addr.sin_addr.s_addr = inet_addr(g_serverAddress)) == INADDR_NONE) - { - g_Logger.LogToFileOnly(logfile, "Couldn't locate address: %s", g_serverAddress); - closesocket(socketDescriptor); - return INVALID_SOCKET; - } - } - else - { - memcpy(&local_addr.sin_addr, (struct in_addr *)he->h_addr, he->h_length); - } - - if (connect(socketDescriptor, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) - { - char error[255]; - g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error)); - g_Logger.LogToFileOnly(logfile, "Couldn't connect to %s: %s", g_serverAddress, error); - closesocket(socketDescriptor); - return INVALID_SOCKET; - } - - return socketDescriptor; -} - -void FetcherThread::ProcessGameDataQuery(int socketDescriptor) -{ - char buffer[50]; - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Waiting for reply!"); -ENDIF_DEBUG_SPEW - - //Read in the header bytes - int returnLen = RecvData(socketDescriptor, buffer, 12); - - - if (returnLen == 0) - { - char error[255]; - g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error)); - g_Logger.LogToFileOnly(logfile, "Did not receive reply: %s", error); - return; - } - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Received Header!"); -ENDIF_DEBUG_SPEW - - bf_read Reader = bf_read("GameDataQuery", buffer, 12); - - if (Reader.ReadByte() != 'A' || Reader.ReadByte() != 'G') - { -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Unknown Query Response"); -ENDIF_DEBUG_SPEW - return; - } - - updateStatus = (UpdateStatus)Reader.ReadByte(); - - build[0] = Reader.ReadShort(); - build[1] = Reader.ReadShort(); - build[2] = Reader.ReadShort(); - build[3] = Reader.ReadShort(); - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, - "Update Status: %i - Latest %i.%i.%i.%i", - updateStatus, - build[0], - build[1], - build[2], - build[3]); -ENDIF_DEBUG_SPEW - - int changedFiles = Reader.ReadByte(); - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Files to download: %i", changedFiles); -ENDIF_DEBUG_SPEW - - for (int i=0; iCreateMem(tempLen+1, &memPtr); - - //Read the contents of our file into the memtable - returnLen = RecvData(socketDescriptor, (char *)memPtr, tempLen); - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Received %i bytes", returnLen); -ENDIF_DEBUG_SPEW - - if (returnLen == 0) - { - /* Timeout or fail? */ - return; - } - - ((unsigned char *)memPtr)[tempLen] = '\0'; - - FileData *data = filenames.at(index); - const char *filename; - if (data != NULL) - { - filename = data->filename->c_str(); - - FILE *fp = fopen(filename, "w"); - - if (fp) - { - fprintf(fp, "%s", (const char *)memPtr); - fclose(fp); - } - else - { - g_Logger.LogToFileOnly(logfile, "Failed to open file \"%s\" for writing", filename); - } - } - else - { - filename = ""; - } - - memtable->Reset(); - - g_Logger.LogToFileOnly(logfile, "Updated file: %s", filename); - } - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "File Downloads Completed!"); -ENDIF_DEBUG_SPEW - - needsRestart = false; - - if (changedFiles > 0) - { - needsRestart = true; - } - - //Read changed file count - returnLen = RecvData(socketDescriptor, buffer, 1); - - if (returnLen == 0) - { - char error[255]; - g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error)); - g_Logger.LogToFileOnly(logfile, "Did not receive count reply: %s", error); - return; - } - - Reader.StartReading(buffer, 1); - - changedFiles = Reader.ReadByte(); - - if (changedFiles < 1) - { -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "No unknown files. We're all done"); -ENDIF_DEBUG_SPEW - return; - } - - char *changedFileIndexes = new char[changedFiles]; - -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "%i files were unknown", changedFiles); -ENDIF_DEBUG_SPEW - - returnLen = RecvData(socketDescriptor, changedFileIndexes, changedFiles); - - if (returnLen == 0) - { - char error[255]; - g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error)); - g_Logger.LogToFileOnly(logfile, "Did not receive list reply: %s", error); - return; - } - - Reader.StartReading(changedFileIndexes, changedFiles); - - for (int i=0; ifilename->c_str(); - } - else - { - pathname = ""; - } - - g_LibSys.GetFileFromPath(fileName, sizeof(fileName), pathname); -IF_DEBUG_SPEW - g_Logger.LogToFileOnly(logfile, "Unknown File %i : %s", index, fileName); -ENDIF_DEBUG_SPEW - } - - delete [] changedFileIndexes; - - wasSuccess = true; -} - -int FetcherThread::RecvData(int socketDescriptor, char *buffer, int len) -{ - fd_set fds; - struct timeval tv; - - /* Create a 10 Second Timeout */ - tv.tv_sec = 10; - tv.tv_usec = 0; - - int bytesReceivedTotal = 0; - - while (bytesReceivedTotal < len) - { - /* Add our socket to a socket set */ - FD_ZERO(&fds); - FD_SET(socketDescriptor, &fds); - - /* Wait max of 10 seconds for recv to become available */ - select(socketDescriptor+1, &fds, NULL, NULL, &tv); - - int bytesReceived = 0; - - /* Is there a limit on how much we can receive? Some site said 1024 bytes, which will be well short of a file */ - if (FD_ISSET(socketDescriptor, &fds)) - { - bytesReceived = recv(socketDescriptor, buffer+bytesReceivedTotal, len-bytesReceivedTotal, 0); - } - - if (bytesReceived == 0 || bytesReceived == -1) - { - return 0; - } - - bytesReceivedTotal += bytesReceived; - } - - return bytesReceivedTotal; -} - -int FetcherThread::SendData(int socketDescriptor, char *buffer, int len) -{ - fd_set fds; - struct timeval tv; - - tv.tv_sec = 10; - tv.tv_usec = 0; - - int sentBytesTotal = 0; - - while (sentBytesTotal < len) - { - FD_ZERO(&fds); - FD_SET(socketDescriptor, &fds); - - select(socketDescriptor+1, NULL, &fds, NULL, &tv); - - int sentBytes = 0; - - if (FD_ISSET(socketDescriptor, &fds)) - { - sentBytes = send(socketDescriptor, buffer+sentBytesTotal, len-sentBytesTotal, 0); - } - - if (sentBytes == 0 || sentBytes == -1) - { - return 0; - } - - sentBytesTotal += sentBytes; - } - - return sentBytesTotal; -} - -void FetcherThread::HandleUpdateStatus(UpdateStatus status, short version[4]) -{ - switch (status) - { - case Update_Unknown: - case Update_Current: - { - break; - } - - case Update_NewBuild: - { - break; - } - - case Update_MinorAvailable: - { - g_Logger.LogMessage("SourceMod Update: A new release of SourceMod is now available from sourcemod.net"); - g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]); - break; - } - - case Update_MajorAvailable: - { - g_Logger.LogMessage("SourceMod Update: An major release of SourceMod is now available from sourcemod.net"); - g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]); - break; - } - - case Update_CriticalAvailable: - { - g_Logger.LogError("SourceMod Update: A critical SourceMod release is available from sourcemod.net. It is strongly recommended that you update!"); - g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]); - break; - } - } -} - -bool g_blockGameDataLoad = false; -static IThreadHandle *fetch_thread_hndl; - -class InitFetch : public SMGlobalClass -{ -public: - void OnSourceModAllInitialized_Post() - { - char lock_path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp/gamedata.lock"); - - if (g_LibSys.IsPathFile(lock_path) && g_LibSys.PathExists(lock_path)) - { - g_Logger.LogError("sourcemod/data/temp/gamedata.lock file detected. This is most likely due to a crash during GameData updating - Blocking GameData loading"); - g_Logger.LogError("If this error persists delete the file manually"); - g_blockGameDataLoad = true; - } - - ThreadParams fetchThreadParams = ThreadParams(); - fetchThreadParams.prio = ThreadPrio_Low; - fetch_thread_hndl = g_pThreader->MakeThread(&g_FetchThread, &fetchThreadParams); - } - - void OnSourceModShutdown() - { - fetch_thread_hndl->WaitForThread(); - fetch_thread_hndl->DestroyThis(); - } - - void OnSourceModLevelActivated() - { - was_level_started = true; - - if (g_restartAfterUpdate && - g_FetchThread.wasSuccess && - g_FetchThread.needsRestart) - { - ForceRestart(); - } - } - - void OnSourceModLevelEnd() - { - was_level_started = false; - } - - ConfigResult OnSourceModConfigChanged(const char *key, - const char *value, - ConfigSource source, - char *error, - size_t maxlength) - { - if (strcasecmp(key, "DisableAutoUpdate") == 0) - { - if (strcasecmp(value, "yes") == 0) - { - g_disableGameDataUpdate = true; - return ConfigResult_Accept; - } - else if (strcasecmp(value, "no") == 0) - { - g_disableGameDataUpdate = false; - return ConfigResult_Accept; - } - - return ConfigResult_Reject; - } - - if (strcasecmp(key, "ForceRestartAfterUpdate") == 0) - { - if (strcasecmp(value, "yes") == 0) - { - g_restartAfterUpdate = true; - return ConfigResult_Accept; - } - else if (strcasecmp(value, "no") == 0) - { - g_restartAfterUpdate = false; - return ConfigResult_Accept; - } - - return ConfigResult_Reject; - } - - if (strcasecmp(key, "AutoUpdateServer") == 0) - { - UTIL_Format(g_serverAddress, sizeof(g_serverAddress), "%s", value); - - return ConfigResult_Accept; - } - - if (strcasecmp(key, "AutoUpdatePort") == 0) - { - int port = atoi(value); - - if (!port) - { - return ConfigResult_Reject; - } - - g_serverPort = port; - - return ConfigResult_Accept; - } - - return ConfigResult_Ignore; - } -} g_InitFetch; - -BuildMD5ableBuffer::BuildMD5ableBuffer() -{ - stringTable = new BaseStringTable(2048); -} - -BuildMD5ableBuffer::~BuildMD5ableBuffer() -{ - delete stringTable; -} - -void BuildMD5ableBuffer::ReadSMC_ParseStart() -{ - stringTable->Reset(); -} - -SMCResult BuildMD5ableBuffer::ReadSMC_KeyValue(const SMCStates *states, - const char *key, - const char *value) -{ - stringTable->AddString(key); - stringTable->AddString(value); - - return SMCResult_Continue; -} - -SMCResult BuildMD5ableBuffer::ReadSMC_NewSection(const SMCStates *states, const char *name) -{ - stringTable->AddString(name); - - return SMCResult_Continue; -} - -void BuildMD5ableBuffer::ReadSMC_ParseEnd(bool halted, bool failed) -{ - if (halted || failed) - { - return; - } - - void *data = stringTable->GetMemTable()->GetAddress(0); - - if (data != NULL) - { - checksum->update((unsigned char *)data, stringTable->GetMemTable()->GetActualMemUsed()); - } - - checksum->finalize(); -} - -CON_COMMAND(sm_gamedata_md5, "Checks the MD5 sum for a given gamedata file") -{ -#if SOURCE_ENGINE == SE_EPISODEONE - CCommand args; -#endif - - if (args.ArgC() < 2) - { - g_SMAPI->ConPrint("Usage: sm_gamedata_md5 \n"); - return; - } - - const char *file = args.Arg(1); - if (!file || file[0] == '\0') - { - g_SMAPI->ConPrint("Usage: sm_gamedata_md5 \n"); - return; - } - - SourceHook::CVector::iterator iter = g_FetchThread.filenames.begin(); - - FileData *curData; - - while (iter != g_FetchThread.filenames.end()) - { - curData = (*iter); - - char fileName[30]; - - g_LibSys.GetFileFromPath(fileName, sizeof(fileName), curData->filename->c_str()); - - if (strcmpi(fileName, file) == 0) - { - g_SMAPI->ConPrintf("MD5 Sum: %s\n", curData->checksum); - return; - } - - iter++; - } - - g_SMAPI->ConPrint("File not found!\n"); -} - -FetcherThread::~FetcherThread() -{ - SourceHook::CVector::iterator iter = filenames.begin(); - - FileData *curData; - - while (iter != filenames.end()) - { - curData = (*iter); - delete curData->filename; - delete curData; - iter = filenames.erase(iter); - } -} - -FetcherThread::FetcherThread() -{ - memtable = new BaseMemTable(4096); - wasSuccess = false; - needsRestart = false; -} - diff --git a/core/GameDataFetcher.h b/core/GameDataFetcher.h deleted file mode 100644 index c397642f..00000000 --- a/core/GameDataFetcher.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_SOURCEMOD_GAMEDATAFETCHER_H_ -#define _INCLUDE_SOURCEMOD_GAMEDATAFETCHER_H_ - -#include "sourcemod.h" -#include "TextParsers.h" -#include "IThreader.h" -#include "Logger.h" -#include "LibrarySys.h" -#include "ThreadSupport.h" -#include "sm_memtable.h" -#include -#include - -enum UpdateStatus -{ - Update_Unknown = 0, /* Version wasn't recognised or version querying is unsupported */ - Update_Current = 1, /* Server is running latest version */ - Update_NewBuild = 2, /* Server is on a svn release and a newer version is available */ - Update_MinorAvailable = 3, /* Server is on a release and a minor release has superceeded it */ - Update_MajorAvailable = 4, /* Server is on a release and a major release has superceeded it */ - Update_CriticalAvailable = 5, /* A critical update has been released (security fixes etc) */ -}; - -class MD5; - -class BuildMD5ableBuffer : public ITextListener_SMC -{ -public: - BuildMD5ableBuffer(); - ~BuildMD5ableBuffer(); - void ReadSMC_ParseStart(); - SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); - SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); - void ReadSMC_ParseEnd(bool halted, bool failed); -public: - MD5 *checksum; -private: - BaseStringTable *stringTable; -}; - -struct FileData -{ - SourceHook::String *filename; - char checksum[33]; -}; - -class FetcherThread : public IThread -{ -public: - FetcherThread(); - ~FetcherThread(); -public: - void RunThread(IThreadHandle *pHandle); - void OnTerminate(IThreadHandle *pHandle, bool cancel); -private: - int BuildGameDataQuery(char *buffer, int maxlen); - void ProcessGameDataQuery(int SocketDescriptor); - int RecvData(int socketDescriptor, char *buffer, int len); - int SendData(int socketDescriptor, char *buffer, int len); - int ConnectSocket(); - void HandleUpdateStatus(UpdateStatus status, short version[4]); -public: - SourceHook::CVector filenames; - bool needsRestart; - bool wasSuccess; -private: - UpdateStatus updateStatus; - BaseMemTable *memtable; - short build[4]; -}; - -extern bool g_blockGameDataLoad; - -#endif // _INCLUDE_SOURCEMOD_GAMEDATAFETCHER_H_ - diff --git a/core/Makefile b/core/Makefile index 840105aa..2b883445 100644 --- a/core/Makefile +++ b/core/Makefile @@ -19,7 +19,7 @@ OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreC sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \ MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \ frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp PhraseCollection.cpp NextMap.cpp \ - NativeOwner.cpp GameDataFetcher.cpp md5.cpp + NativeOwner.cpp md5.cpp OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \ smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \ smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \ diff --git a/core/msvc9/sourcemod_mm.vcproj b/core/msvc9/sourcemod_mm.vcproj index 6356824f..8ee550bf 100644 --- a/core/msvc9/sourcemod_mm.vcproj +++ b/core/msvc9/sourcemod_mm.vcproj @@ -1141,10 +1141,6 @@ RelativePath="..\GameConfigs.cpp" > - - @@ -1351,10 +1347,6 @@ RelativePath="..\GameConfigs.h" > - - diff --git a/tools/daemon/Makefile b/tools/daemon/Makefile deleted file mode 100644 index 10259556..00000000 --- a/tools/daemon/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -# (C)2004-2008 SourceMod Development Team -# Makefile written by David "BAILOPAN" Anderson - - -##################################### -### EDIT BELOW FOR OTHER PROJECTS ### -##################################### - -OBJECTS = smud.cpp smud_connections.cpp smud_threads.cpp - -############################################## -### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### -############################################## - -C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing -C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3 -C_GCC4_FLAGS = -fvisibility=hidden -CPP_GCC4_FLAGS = -fvisibility-inlines-hidden -CPP = gcc - -BINARY = smupdated - -LINK += -lpthread -static-libgcc - -INCLUDE += -I. - -CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \ - -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \ - -Wno-uninitialized -mfpmath=sse -msse -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32 -CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti - -################################################ -### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### -################################################ - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug - CFLAGS += $(C_DEBUG_FLAGS) -else - BIN_DIR = Release - CFLAGS += $(C_OPT_FLAGS) -endif - -GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) -ifeq "$(GCC_VERSION)" "4" - CFLAGS += $(C_GCC4_FLAGS) - CPPFLAGS += $(CPP_GCC4_FLAGS) -endif - -OBJ_LINUX := $(OBJECTS:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o) -OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o) -OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp - $(CPP) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< - -$(BIN_DIR)/%.o: %.c - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: - mkdir -p $(BIN_DIR) - $(MAKE) -f Makefile sourcemod - -sourcemod: $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -lstdc++ -o $(BIN_DIR)/$(BINARY) - -debug: - $(MAKE) -f Makefile all DEBUG=true - -default: all - -clean: - rm -rf $(BIN_DIR)/$(BINARY) diff --git a/tools/daemon/smud.cpp b/tools/daemon/smud.cpp deleted file mode 100644 index 4cd6064d..00000000 --- a/tools/daemon/smud.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include "smud.h" -#include "smud_threads.h" - -#define LISTEN_PORT 6500 -#define LISTEN_QUEUE_LENGTH 6 - -char fileNames[NUM_FILES][30] = { - "core.games.txt", - "sdktools.games.txt", - "sdktools.games.ep2.txt", - "sdktools.games.l4d.txt", - "sm-cstrike.games.txt", - "sm-tf2.games.txt", -}; - -void *fileLocations[NUM_FILES]; -int fileLength[NUM_FILES]; - -int main(int argc, char **argv) -{ - ThreadPool *pool; - struct protoent *pProtocol; - struct sockaddr_in serverAddress; - struct sockaddr_in clientAddress; - int serverSocket; - int clientSocket; - int addressLen; - int opts; - int file; - char filename[100]; - struct stat sbuf; - -#if defined DEBUG - fprintf(stdout, "Loading Gamedata files into memory\n"); -#endif - - for (int i=0; iStart()) - { - fprintf(stderr, "Could not initialize thread pool!\n"); - return 1; - } - -#if defined DEBUG - printf("Create Server Socket\n"); -#endif - - memset(&serverAddress, 0, sizeof(serverAddress)); - serverAddress.sin_family = AF_INET; - serverAddress.sin_addr.s_addr = INADDR_ANY; - serverAddress.sin_port = htons(LISTEN_PORT); - - pProtocol = getprotobyname("tcp"); - - if (pProtocol == NULL) - { - fprintf(stderr, "Could not get tcp proto: %s", strerror(errno)); - return 1; - } - - serverSocket = socket(AF_INET, SOCK_STREAM, pProtocol->p_proto); - - if (serverSocket < 0) - { - fprintf(stderr, "Could not open socket: %s", strerror(errno)); - return 1; - } - - opts = 1; - setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &opts, sizeof(opts)); - - if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) - { - fprintf(stderr, "Could not bind socket: %s", strerror(errno)); - return 1; - } - - if (listen(serverSocket, LISTEN_QUEUE_LENGTH) < 0) - { - fprintf(stderr, "Could not listen on socket: %s", strerror(errno)); - return 1; - } - - fprintf(stdout, "Server has started.\n"); - - while (1) - { - addressLen = sizeof(clientAddress); - - clientSocket = accept(serverSocket, - (struct sockaddr *)&clientAddress, - (socklen_t *)&addressLen); - if (clientSocket < 0) - { - fprintf(stderr, "Could not accept client: %s", strerror(errno)); - continue; - } - - opts = fcntl(clientSocket, F_GETFL, 0); - if (fcntl(clientSocket, F_SETFL, opts|O_NONBLOCK) < 0) - { - fprintf(stderr, "Could not non-block client: %s", strerror(errno)); - closesocket(clientSocket); - continue; - } - -#if defined DEBUG - fprintf(stdout, - "Accepting connection from client (sock %d, ip %s)", - clientSocket, - inet_ntoa(clientAddress.sin_addr)); -#endif - - pool->AddConnection(clientSocket); - } - - delete pool; -} - - - diff --git a/tools/daemon/smud.h b/tools/daemon/smud.h deleted file mode 100644 index 5c047fb8..00000000 --- a/tools/daemon/smud.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _INCLUDE_SMUD_MAIN_H_ -#define _INCLUDE_SMUD_MAIN_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define closesocket close - -#define NUM_FILES 6 - -extern char fileNames[NUM_FILES][30]; -extern void *fileLocations[NUM_FILES]; -extern int fileLength[NUM_FILES]; - -#endif //_INCLUDE_SMUD_MAIN_H_ diff --git a/tools/daemon/smud_connections.cpp b/tools/daemon/smud_connections.cpp deleted file mode 100644 index 3ffddd68..00000000 --- a/tools/daemon/smud_connections.cpp +++ /dev/null @@ -1,541 +0,0 @@ -#include -#include "smud_connections.h" -#include "smud.h" - -ConnectionPool::ConnectionPool() -{ - pthread_mutex_init(&m_AddLock, NULL); - m_timeOut = 1000; -} - -ConnectionPool::~ConnectionPool() -{ - pthread_mutex_destroy(&m_AddLock); -} - -void ConnectionPool::AddConnection( int fd ) -{ - smud_connection *connection = new smud_connection(fd); - - pthread_mutex_lock(&m_AddLock); - m_AddQueue.push_back(connection); - pthread_mutex_unlock(&m_AddLock); -} - -void ConnectionPool::Process( bool *terminate ) -{ - struct timespec ts_wait; - - ts_wait.tv_sec = 0; - ts_wait.tv_nsec = 50000000; /* 50ms */ - - std::list::iterator iter; - smud_connection *con = NULL; - - while (1) - { - if (*terminate) - { - return; - } - - iter = m_Links.begin(); - - QueryResult result = QueryResult_Continue; - int pollReturn = 0; - - /* Add all connections that want processing to the sets */ - while (iter != m_Links.end()) - { - con = *iter; - - pollReturn = poll(&(con->pollData), 1, 0); - assert(pollReturn <= 1); - - if (pollReturn == -1) - { - //Something went badly wrong or the connection closed. - result = QueryResult_Complete; - } - else if (pollReturn == 1) - { - //Poll returns the number of sockets available (which can only ever be 1) - result = ProcessConnection(con); - } - - if (result == QueryResult_Complete) - { - iter = m_Links.erase(iter); -#if defined DEBUG - fprintf(stdout, "Closing socket %d\n", con->fd); -#endif - closesocket(con->fd); - delete con; - continue; - } - - iter++; - } - - /* Add new items to process */ - - iter = m_Links.end(); - pthread_mutex_lock(&m_AddLock); - m_Links.splice(iter, m_AddQueue); - pthread_mutex_unlock(&m_AddLock); - - nanosleep(&ts_wait, NULL); - } -} - -QueryResult ConnectionPool::ProcessConnection( smud_connection *con ) -{ - switch (con->state) - { - case ConnectionState_ReadQueryHeader: - { - ReadQueryHeader(con); - break; - } - - case ConnectionState_ReadQueryData: - { - ReadQueryContent(con); - break; - } - - case ConnectionState_ReplyQuery: - { - ReplyQuery(con); - break; - } - - case ConnectionState_SendingFiles: - { - SendFile(con); - break; - } - - case ConnectionState_SendUnknownList: - { - SendUnknownList(con); - break; - } - - case ConnectionState_Complete: - { - break; - } - } - - if (con->state == ConnectionState_Complete) - { - printf("Ending connection because it marked itself as finished\n"); - return QueryResult_Complete; - } - - if (con->start + m_timeOut < time(NULL)) - { - printf("Ending connection because it has passed maximum allowed time\n"); - return QueryResult_Complete; - } - - return QueryResult_Continue; -} - -void ConnectionPool::ReadQueryHeader( smud_connection *con ) -{ - if (con->buffer == NULL) - { - con->buffer = new char[QUERY_HEADER_SIZE]; - con->writtenCount = 0; - } - - int bytesReceived = 0; - - bytesReceived = recv(con->fd, con->buffer+con->writtenCount, QUERY_HEADER_SIZE-con->writtenCount, 0); - - if (bytesReceived == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - { - con->state = ConnectionState_Complete; - delete [] con->buffer; - con->buffer = NULL; - con->writtenCount = 0; - } - - return; - } - - con->writtenCount += bytesReceived; - - assert(con->writtenCount <= QUERY_HEADER_SIZE); - - if (con->writtenCount < QUERY_HEADER_SIZE) - { - /* Don't change the connection status, so next cycle we will come back to here and continue receiving data */ - return; - } - - if (con->buffer[0] != 'A' || con->buffer[1] != 'G') - { - con->state = ConnectionState_Complete; - delete [] con->buffer; - con->buffer = NULL; - con->writtenCount = 0; - return; - } - - //Ignore the next 8 bytes for the moment. Versioning data is currently unused - // uint16[4] - source version major/minor/something/rev - - con->sentSums = con->buffer[10]; - - con->state = ConnectionState_ReadQueryData; -#if defined DEBUG - fprintf(stdout, "Query Header Read Complete, %i md5's expected\n", con->sentSums); -#endif - - delete [] con->buffer; - con->buffer = NULL; - con->writtenCount = 0; -} - -void ConnectionPool::ReplyQuery(smud_connection *con) -{ - char data[12]; - data[0] = 'A'; - data[1] = 'G'; - - data[2] = (char)Update_Unknown; //unused versioning crap - *(short *)&data[3] = 1; - *(short *)&data[5] = 0; - *(short *)&data[7] = 0; - *(short *)&data[9] = 3; - - data[11] = (char)con->sendCount; - - int bytesSent = send(con->fd, data+con->writtenCount, sizeof(data)-con->writtenCount, 0); - - if (bytesSent == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - { - con->state = ConnectionState_Complete; - con->writtenCount = 0; - } - - return; - } - - con->writtenCount += bytesSent; - - assert(con->writtenCount <= 12); - - if (con->writtenCount < 12) - { - /** Still more data needs to be sent - Return so we come back here next cycle */ - return; - } - - con->state = ConnectionState_SendingFiles; - con->writtenCount = 0; -#if defined DEBUG - printf("Query Reply Header Complete\n"); -#endif -} - -void ConnectionPool::ReadQueryContent( smud_connection *con ) -{ - if (con->buffer == NULL) - { - con->buffer = new char[QUERY_CONTENT_SIZE*con->sentSums]; - con->writtenCount = 0; - } - - int bytesReceived = 0; - - bytesReceived = recv(con->fd, con->buffer+con->writtenCount, (QUERY_CONTENT_SIZE*con->sentSums)-con->writtenCount, 0); - - if (bytesReceived == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - { - con->state = ConnectionState_Complete; - delete [] con->buffer; - con->buffer = NULL; - con->writtenCount = 0; - } - - return; - } - - con->writtenCount += bytesReceived; - - assert(con->writtenCount <= (QUERY_CONTENT_SIZE*con->sentSums)); - - if (con->writtenCount < (QUERY_CONTENT_SIZE*con->sentSums)) - { - /* Don't change the connection status, so next cycle we will come back to here and continue receiving data */ - return; - } - - con->shouldSend = new MD5Status[con->sentSums](); - con->fileLocation = new int[con->sentSums](); - con->headerSent = new bool[con->sentSums](); - - for (int i=0; isentSums; i++) - { - con->fileLocation[i] = -1; - con->shouldSend[i] = GetMD5UpdateStatus(con->buffer + (QUERY_CONTENT_SIZE*i), con, i); - - if (con->shouldSend[i] == MD5Status_NeedsUpdate) - { -#if defined DEBUG - fprintf(stdout, "File %i needs updating\n", i); -#endif - con->sendCount++; - con->headerSent[i] = false; - continue; - } - - if (con->shouldSend[i] == MD5Status_Unknown) - { -#if defined DEBUG - fprintf(stdout, "File %i is unknown\n", i); -#endif - con->unknownCount++; - } - } - - con->state = ConnectionState_ReplyQuery; - con->pollData.events = POLLOUT; - delete [] con->buffer; - con->buffer = NULL; - con->writtenCount = 0; -#if defined DEBUG - fprintf(stdout, "Query Data Read Complete\n"); -#endif -} - -MD5Status ConnectionPool::GetMD5UpdateStatus( const char *md5 , smud_connection *con, int fileNum) -{ - //Try find a file with this name in some directory. - char path[100] = "./md5/"; - char temp[4]; - char md5String[33] = ""; - - for (int i=0; i<16; i++) - { - snprintf(temp, sizeof(temp), "%02x", (unsigned char)md5[i]); - strcat(md5String, temp); - } - - strcat(path, md5String); - -#if defined DEBUG - fprintf(stdout, "checking for file \"%s\"\n", path); -#endif - - FILE *file = fopen(path, "r"); - - if (file == NULL) - { - printf("Couldn't find file!\n"); - return MD5Status_Unknown; - } - - char latestMD5[33]; - fgets(latestMD5, 33, file); -#if defined DEBUG - fprintf(stdout, "Latest md5 is: %s\n", latestMD5); -#endif - - if (strcmp(latestMD5, md5String) == 0) - { - fclose(file); - return MD5Status_Current; - } - - char filename[100]; - filename[0] = '\n'; - - while (filename[0] == '\n') - { - fgets(filename, sizeof(filename), file); - } - - if (filename[strlen(filename)-1] == '\n') - { - filename[strlen(filename)-1] = '\0'; - } - - fclose(file); - -#if defined DEBUG - fprintf(stdout, "Filename is %s\n", filename); -#endif - - //We now need to match this filename with one of our mmap'd files in memory and store it until send gets called. - for (int i=0; ifileLocation[fileNum] = i; -#if defined DEBUG - fprintf(stdout, "File %i mapped to local file %i\n", fileNum, i); -#endif - return MD5Status_NeedsUpdate; - } - } - - return MD5Status_Unknown; -} - -void ConnectionPool::SendFile( smud_connection *con ) -{ - //Find the next file to send. - while (con->writtenCount == 0 && - con->currentFile < con->sentSums && - con->shouldSend[con->currentFile] != MD5Status_NeedsUpdate) - { - con->currentFile++; - } - - //All files have been sent. - if (con->currentFile >= con->sentSums) - { -#if defined DEBUG - fprintf(stdout, "All files sent!\n"); -#endif - con->state = ConnectionState_SendUnknownList; - con->writtenCount = 0; - return; - } - - void *file = fileLocations[con->fileLocation[con->currentFile]]; - int filelength = fileLength[con->fileLocation[con->currentFile]]; - -#if defined DEBUG - fprintf(stdout, "Sending file of length %i\n", filelength); - fprintf(stdout, - "Current file index is: %i, maps to file index: %i\n", - con->currentFile, - con->fileLocation[con->currentFile]); -#endif - - int sentBytes = 0; - - if (!con->headerSent[con->currentFile]) - { - char buffer[5]; - buffer[0] = con->currentFile; - *((int *)&buffer[1]) = filelength; - - sentBytes = send(con->fd, buffer+con->writtenCount, 5-con->writtenCount, 0); - - if (sentBytes == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - { - con->state = ConnectionState_Complete; - con->writtenCount = 0; - } - - return; - } - - con->writtenCount += sentBytes; - - assert(con->writtenCount <= 5); - - if (con->writtenCount < 5) - { - return; - } - - con->headerSent[con->currentFile] = true; - con->writtenCount = 0; - } - - sentBytes = send(con->fd, (unsigned char *)file+con->writtenCount, filelength-con->writtenCount, 0); - - if (sentBytes == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - { - con->state = ConnectionState_Complete; - con->writtenCount = 0; - } - - return; - } - - con->writtenCount += sentBytes; - - assert(con->writtenCount <= filelength); - - if (con->writtenCount < filelength) - { - return; - } - - con->currentFile++; - con->writtenCount = 0; -#if defined DEBUG - fprintf(stdout, "Sent a file!: %s\n", fileNames[con->fileLocation[con->currentFile-1]]); -#endif -} - -void ConnectionPool::SendUnknownList( smud_connection *con ) -{ - int size = con->unknownCount+1; - char *packet = new char[size](); - - packet[0] = con->unknownCount; - -#if defined DEBUG - fprintf(stdout, "%i Files are unknown\n", con->unknownCount); -#endif - - int i=1; - - for (int j=0; jsentSums; j++) - { - if (con->shouldSend[j] == MD5Status_Unknown) - { - packet[i] = j; - i++; - } - } - - int sentBytes = send(con->fd, packet+con->writtenCount, size-con->writtenCount, 0); - - if (sentBytes == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - { - con->state = ConnectionState_Complete; - con->writtenCount = 0; - } - - return; - } - - con->writtenCount += sentBytes; - - assert(con->writtenCount <= size); - - if (con->writtenCount < size) - { - return; - } - - con->state = ConnectionState_Complete; - con->writtenCount = 0; -#if defined DEBUG - fprintf(stdout, "Unknowns Sent\n"); -#endif -} - diff --git a/tools/daemon/smud_connections.h b/tools/daemon/smud_connections.h deleted file mode 100644 index dbc75ac3..00000000 --- a/tools/daemon/smud_connections.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef _INCLUDE_SMUD_CONNECTION_H_ -#define _INCLUDE_SMUD_CONNECTION_H_ - -#include "smud.h" -#include -#include "poll.h" - -#define QUERY_HEADER_SIZE 11 -#define QUERY_CONTENT_SIZE 16 - -enum ConnectionState -{ - ConnectionState_ReadQueryHeader, - ConnectionState_ReadQueryData, - ConnectionState_ReplyQuery, - ConnectionState_SendingFiles, - ConnectionState_SendUnknownList, - ConnectionState_Complete, -}; - -enum QueryResult -{ - QueryResult_Continue, - QueryResult_Complete, -}; - -enum MD5Status -{ - MD5Status_Unknown, - MD5Status_Current, - MD5Status_NeedsUpdate, -}; - -enum UpdateStatus -{ - Update_Unknown = 0, /* Version wasn't recognised or version querying is unsupported */ - Update_Current = 1, /* Server is running latest version */ - Update_NewBuild = 2, /* Server is on a svn release and a newer version is available */ - Update_MinorAvailable = 3, /* Server is on a release and a minor release has superceeded it */ - Update_MajorAvailable = 4, /* Server is on a release and a major release has superceeded it */ - Update_CriticalAvailable = 5, /* A critical update has been released (security fixes etc) */ -}; - -struct smud_connection -{ - smud_connection(int fd) - { - shouldSend = NULL; - fileLocation = NULL; - headerSent = NULL; - sentSums = 0; - sendCount = 0; - currentFile = 0; - unknownCount = 0; - pollData.events = POLLIN; - start = time(NULL); - state = ConnectionState_ReadQueryHeader; - this->fd = fd; - pollData.fd = fd; - buffer = NULL; - writtenCount = 0; - } - - ~smud_connection() - { - if (shouldSend != NULL) - delete [] shouldSend; - if (fileLocation != NULL) - delete [] fileLocation; - if (headerSent != NULL) - delete [] headerSent; - } - - int fd; /** Socket file descriptor */ - time_t start; /** The time this connection was received (for timeouts) */ - ConnectionState state; /** How far through processing the connection we are */ - uint8_t sentSums; /** Number of MD5 Sums sent from the client */ - MD5Status *shouldSend; /** Arrays of statuses for each sum */ - int *fileLocation; /** Array of indexes into the global file list for each sum (only valid if shouldSend[i] == MD5Status_NeedsUpdate) */ - bool *headerSent; /** Has the header been sent yet for each sum? Header == file index and size */ - int sendCount; /** Number of files that need to be sent */ - int unknownCount; /** Number of files that were unknown */ - int currentFile; /** Current file being sent (index into the above 3 arrays) */ - pollfd pollData; /** Data to be passed into poll() */ - char *buffer; /** Temporary storage buffer to hold data until all of it is available */ - int writtenCount; /** Number of bytes written into the storage buffer */ -}; - - - -class ConnectionPool -{ -public: - ConnectionPool(); - ~ConnectionPool(); -public: - void AddConnection(int fd); - void Process(bool *terminate); -private: - QueryResult ProcessConnection(smud_connection *con); - void ReadQueryHeader(smud_connection *con); - void ReadQueryContent(smud_connection *con); - void ReplyQuery(smud_connection *con); - void SendFile(smud_connection *con); - void SendUnknownList(smud_connection *con); - - MD5Status GetMD5UpdateStatus(const char *md5, smud_connection *con, int fileNum); -private: - std::list m_Links; - std::list m_AddQueue; - pthread_mutex_t m_AddLock; - time_t m_timeOut; -}; - -#endif //_INCLUDE_SMUD_CONNECTION_H_ - diff --git a/tools/daemon/smud_threads.cpp b/tools/daemon/smud_threads.cpp deleted file mode 100644 index 1bb41156..00000000 --- a/tools/daemon/smud_threads.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "smud_threads.h" - -ThreadPool::ThreadPool() -{ -} - -ThreadPool::~ThreadPool() -{ -} - -bool ThreadPool::Start() -{ - m_pWorker = new ThreadWorker(); - - if (!m_pWorker->Start()) - { - delete m_pWorker; - return false; - } - - return true; -} - -void ThreadPool::Stop() -{ - m_pWorker->CancelAndWait(); - delete m_pWorker; -} - -void ThreadPool::AddConnection(int fd) -{ - m_pWorker->AddConnection(fd); -} - -ThreadWorker::ThreadWorker() : m_bShouldCancel(false) -{ -} - -ThreadWorker::~ThreadWorker() -{ -} - -bool ThreadWorker::Start() -{ - m_pPool = new ConnectionPool(); - pthread_mutex_init(&m_NotifyLock, NULL); - pthread_cond_init(&m_Notify, NULL); - - if (pthread_create(&m_Thread, NULL, ThreadCallback, this) != 0) - { - return false; - } - - return true; -} - -void ThreadWorker::CancelAndWait() -{ - m_bShouldCancel = true; - - pthread_join(m_Thread, NULL); - - pthread_cond_destroy(&m_Notify); - pthread_mutex_destroy(&m_NotifyLock); - - delete m_pPool; -} - -void ThreadWorker::AddConnection( int fd ) -{ - m_pPool->AddConnection(fd); -} - -void ThreadWorker::Process() -{ - m_pPool->Process(&m_bShouldCancel); -} - -void *ThreadCallback(void *data) -{ - ((ThreadWorker *)data)->Process(); - - pthread_exit(NULL); -} - - diff --git a/tools/daemon/smud_threads.h b/tools/daemon/smud_threads.h deleted file mode 100644 index 1897b160..00000000 --- a/tools/daemon/smud_threads.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _INCLUDE_SMUD_H_ -#define _INCLUDE_SMUD_H_ - -#include "smud.h" -#include "smud_connections.h" - -void *ThreadCallback(void *data); - -class ThreadWorker -{ -public: - ThreadWorker(); - ~ThreadWorker(); -public: - bool Start(); - void CancelAndWait(); - void AddConnection(int fd); - void Process(); -private: - ConnectionPool *m_pPool; - pthread_t m_Thread; - pthread_mutex_t m_NotifyLock; - pthread_cond_t m_Notify; - bool m_bShouldCancel; -}; - -class ThreadPool -{ -public: - ThreadPool(); - ~ThreadPool(); -public: - void AddConnection(int fd); - bool Start(); - void Stop(); -private: - ThreadWorker *m_pWorker; -}; - -#endif //_INCLUDE_SMUD_H_ - diff --git a/tools/daemon/updateGameData.sh b/tools/daemon/updateGameData.sh deleted file mode 100644 index 4eaaccbc..00000000 --- a/tools/daemon/updateGameData.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -FILENAME="" -SUMSFILE="" - -if [ -n "$1" ] -then - FILENAME="$1.txt" - SUMSFILE="$1.sums" -else - echo "Need to specify a gamedata filename" - exit -1 -fi - - -if [ -s $FILENAME ] -then - #run ./gamedatamd5 on this file and pipe output+filename into $1.sums - MD5=`./gamedatamd5 $FILENAME` - #need to stop here if gamedatamd5 failed. (returns -1 and prints to stderr) - echo "$MD5" > "$SUMSFILE" - echo "$FILENAME" >> "$SUMSFILE" - ln -s "$SUMSFILE" "$MD5" - - exit 0 -fi - -echo "File $FILENAME not found!" - -exit -1