mirror of
https://github.com/glest/glest-source.git
synced 2025-08-16 21:33:59 +02:00
- added new headless server status check:
on the SAME box as the headless run: ./megaglest --headless-server-status
This commit is contained in:
@@ -89,6 +89,7 @@ public:
|
||||
static const int specialFactions = fpt_EndCount - 1;
|
||||
static const int maxPlayers= 8;
|
||||
static const int serverPort= 61357;
|
||||
static const int serverAdminPort= 61355;
|
||||
//static const int updateFps= 40;
|
||||
//static const int cameraFps= 100;
|
||||
static int updateFps;
|
||||
|
@@ -2733,6 +2733,23 @@ int glestMain(int argc, char** argv) {
|
||||
}
|
||||
createDirectoryPaths(tempDataPath);
|
||||
|
||||
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_STATUS])) == true) {
|
||||
Ip ip("localhost");
|
||||
int port = Config::getInstance().getInt("ServerAdminPort", intToStr(GameConstants::serverAdminPort).c_str());
|
||||
ClientSocket clientSocket;
|
||||
clientSocket.setBlock(false);
|
||||
clientSocket.connect(ip, port);
|
||||
if(clientSocket.isConnected() == true) {
|
||||
clientSocket.setBlock(true);
|
||||
|
||||
char szBuf[8096]="";
|
||||
clientSocket.receive(&szBuf[0],8095,false);
|
||||
std::cout << szBuf << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_SOUND]) == true ||
|
||||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
|
||||
config.setString("FactorySound","None");
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "miniftpserver.h"
|
||||
#include "window.h"
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include "map_preview.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
@@ -72,6 +73,11 @@ ServerInterface::ServerInterface(bool publishEnabled) :GameNetworkInterface() {
|
||||
lastGlobalLagCheckTime = 0;
|
||||
masterserverAdminRequestLaunch = false;
|
||||
|
||||
serverSocketAdmin = new ServerSocket(true);
|
||||
serverSocketAdmin->setBlock(false);
|
||||
serverSocketAdmin->setBindPort(Config::getInstance().getInt("ServerAdminPort", intToStr(GameConstants::serverAdminPort).c_str()));
|
||||
serverSocketAdmin->listen(5);
|
||||
|
||||
maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed", intToStr(maxFrameCountLagAllowed).c_str());
|
||||
maxFrameCountLagAllowedEver = Config::getInstance().getInt("MaxFrameCountLagAllowedEver", intToStr(maxFrameCountLagAllowedEver).c_str());
|
||||
maxClientLagTimeAllowedEver = Config::getInstance().getInt("MaxClientLagTimeAllowedEver", intToStr(maxClientLagTimeAllowedEver).c_str());
|
||||
@@ -180,6 +186,17 @@ ServerInterface::ServerInterface(bool publishEnabled) :GameNetworkInterface() {
|
||||
portNumber,GameConstants::maxPlayers,this);
|
||||
ftpServer->start();
|
||||
}
|
||||
|
||||
if(publishToMasterserverThread == NULL) {
|
||||
if(needToRepublishToMasterserver == true || GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
publishToMasterserverThread = new SimpleTaskThread(this,0,125);
|
||||
publishToMasterserverThread->setUniqueID(__FILE__);
|
||||
publishToMasterserverThread->start();
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver);
|
||||
}
|
||||
}
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
}
|
||||
|
||||
@@ -258,6 +275,8 @@ ServerInterface::~ServerInterface() {
|
||||
delete masterServerThreadAccessor;
|
||||
masterServerThreadAccessor = NULL;
|
||||
|
||||
delete serverSocketAdmin;
|
||||
serverSocketAdmin = NULL;
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
}
|
||||
|
||||
@@ -1732,13 +1751,15 @@ bool ServerInterface::launchGame(const GameSettings *gameSettings) {
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver);
|
||||
|
||||
if(needToRepublishToMasterserver == true) {
|
||||
if(publishToMasterserverThread == NULL) {
|
||||
if(needToRepublishToMasterserver == true || GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
publishToMasterserverThread = new SimpleTaskThread(this,0,125);
|
||||
publishToMasterserverThread->setUniqueID(__FILE__);
|
||||
publishToMasterserverThread->start();
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver);
|
||||
}
|
||||
}
|
||||
|
||||
if(ftpServer != NULL) {
|
||||
ftpServer->shutdownAndWait();
|
||||
@@ -1865,6 +1886,7 @@ void ServerInterface::updateListen() {
|
||||
++openSlotCount;
|
||||
}
|
||||
}
|
||||
|
||||
serverSocket.listen(openSlotCount);
|
||||
}
|
||||
|
||||
@@ -2085,6 +2107,7 @@ std::map<string,string> ServerInterface::publishToMasterserver() {
|
||||
|
||||
void ServerInterface::simpleTask(BaseThread *callingThread) {
|
||||
MutexSafeWrapper safeMutex(masterServerThreadAccessor,CODE_AT_LINE);
|
||||
|
||||
if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS) {
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
@@ -2123,9 +2146,112 @@ void ServerInterface::simpleTask(BaseThread *callingThread) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line %d] error during game status update: [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
||||
}
|
||||
}
|
||||
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
DumpStatsToLog(false);
|
||||
}
|
||||
}
|
||||
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
//printf("Attempt Accept\n");
|
||||
Socket *cli = serverSocketAdmin->accept(false);
|
||||
if(cli != NULL) {
|
||||
printf("Got status request connection, dumping info...\n");
|
||||
|
||||
string data = DumpStatsToLog(true);
|
||||
cli->send(data.c_str(),data.length());
|
||||
cli->disconnectSocket();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string ServerInterface::DumpStatsToLog(bool dumpToStringOnly) const {
|
||||
string headlessLogFile = Config::getInstance().getString("HeadlessLogFile","headless.log");
|
||||
if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
|
||||
headlessLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + headlessLogFile ;
|
||||
}
|
||||
else {
|
||||
string userData = Config::getInstance().getString("UserData_Root","");
|
||||
if(userData != "") {
|
||||
endPathWithSlash(userData);
|
||||
}
|
||||
headlessLogFile = userData + headlessLogFile ;
|
||||
}
|
||||
|
||||
ostringstream out;
|
||||
out << "=========================================" << std::endl;
|
||||
out << "Headless Server Current Game information:" << std::endl;
|
||||
out << "=========================================" << std::endl;
|
||||
|
||||
int connectedSlotCount = 0;
|
||||
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
|
||||
MutexSafeWrapper safeMutexSlot(slotAccessorMutexes[i],CODE_AT_LINE_X(i));
|
||||
ConnectionSlot *slot = slots[i];
|
||||
if(slot != NULL) {
|
||||
connectedSlotCount++;
|
||||
out << "Network connection for index: " << i << std::endl;
|
||||
out << "------------------------------" << std::endl;
|
||||
out << "Connected: " << boolToStr(slot->isConnected()) << std::endl;
|
||||
out << "Handshake received: " << boolToStr(slot->getConnectHasHandshaked()) << std::endl;
|
||||
if(slot->isConnected() == true) {
|
||||
time_t connectTime = slot->getConnectedTime();
|
||||
struct tm *loctime = localtime (&connectTime);
|
||||
char szBuf[8096]="";
|
||||
strftime(szBuf,100,"%Y-%m-%d %H:%M:%S",loctime);
|
||||
|
||||
const int HOURS_IN_DAY = 24;
|
||||
const int MINUTES_IN_HOUR = 60;
|
||||
const int SECONDS_IN_MINUTE = 60;
|
||||
int InSeconds = difftime(time(NULL),slot->getConnectedTime());
|
||||
// compute seconds
|
||||
int seconds = InSeconds % SECONDS_IN_MINUTE ;
|
||||
// throw away seconds used in previous statement and convert to minutes
|
||||
int InMinutes = InSeconds / SECONDS_IN_MINUTE ;
|
||||
// compute minutes
|
||||
int minutes = InMinutes % MINUTES_IN_HOUR ;
|
||||
|
||||
// throw away minutes used in previous statement and convert to hours
|
||||
int InHours = InMinutes / MINUTES_IN_HOUR ;
|
||||
// compute hours
|
||||
int hours = InHours % HOURS_IN_DAY ;
|
||||
|
||||
out << "Connected at: " << szBuf << std::endl;
|
||||
out << "Connection duration: " << hours << " hours " << minutes << " minutes " << seconds << " seconds." << std::endl;
|
||||
out << "Player Index: " << slot->getPlayerIndex() << std::endl;
|
||||
out << "IP Address: " << slot->getIpAddress() << std::endl;
|
||||
out << "Player name: " << slot->getName() << std::endl;
|
||||
out << "Language: " << slot->getNetworkPlayerLanguage() << std::endl;
|
||||
out << "Game Version: " << slot->getVersionString() << std::endl;
|
||||
out << "Session id: " << slot->getSessionKey() << std::endl;
|
||||
out << "Socket id: " << slot->getSocketId() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
out << "Total Slot Count: " << connectedSlotCount << std::endl;
|
||||
out << "=========================================" << std::endl;
|
||||
|
||||
std::string result = out.str();
|
||||
|
||||
if(dumpToStringOnly == false) {
|
||||
|
||||
#if defined(WIN32) && !defined(__MINGW32__)
|
||||
FILE *fp = _wfopen(utf8_decode(headlessLogFile ).c_str(), L"w");
|
||||
std::ofstream logFile(fp);
|
||||
#else
|
||||
std::ofstream logFile;
|
||||
logFile.open(headlessLogFile .c_str(), ios_base::out | ios_base::trunc);
|
||||
#endif
|
||||
logFile << result;
|
||||
logFile.close();
|
||||
#if defined(WIN32) && !defined(__MINGW32__)
|
||||
if(fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ServerInterface::notifyBadClientConnectAttempt(string ipAddress) {
|
||||
//printf("In [%s::%s Line: %d] ipAddress [%s]\n",__FILE__,__FUNCTION__,__LINE__,ipAddress.c_str());
|
||||
|
||||
|
@@ -88,6 +88,8 @@ private:
|
||||
|
||||
map<string,pair<uint64,time_t> > badClientConnectIPList;
|
||||
|
||||
ServerSocket *serverSocketAdmin;
|
||||
|
||||
public:
|
||||
ServerInterface(bool publishEnabled);
|
||||
virtual ~ServerInterface();
|
||||
@@ -197,6 +199,7 @@ public:
|
||||
virtual int isClientAllowedToGetFile(uint32 clientIp, const char *username, const char *filename);
|
||||
|
||||
void notifyBadClientConnectAttempt(string ipAddress);
|
||||
std::string DumpStatsToLog(bool dumpToStringOnly) const;
|
||||
|
||||
private:
|
||||
void broadcastMessage(const NetworkMessage *networkMessage, int excludeSlot = -1, int lockedSlotIndex = -1);
|
||||
|
@@ -247,8 +247,10 @@ protected:
|
||||
bool isBroadCastThreadRunning();
|
||||
vector<string> blockIPList;
|
||||
|
||||
bool basicMode;
|
||||
|
||||
public:
|
||||
ServerSocket();
|
||||
ServerSocket(bool basicMode = false);
|
||||
virtual ~ServerSocket();
|
||||
void bind(int port);
|
||||
void listen(int connectionQueueSize= SOMAXCONN);
|
||||
|
@@ -31,6 +31,7 @@ const char *GAME_ARGS[] = {
|
||||
"--connecthost",
|
||||
"--starthost",
|
||||
"--headless-server-mode",
|
||||
"--headless-server-status",
|
||||
"--use-ports",
|
||||
|
||||
"--load-scenario",
|
||||
@@ -84,6 +85,7 @@ enum GAME_ARG_TYPE {
|
||||
GAME_ARG_CLIENT,
|
||||
GAME_ARG_SERVER,
|
||||
GAME_ARG_MASTERSERVER_MODE,
|
||||
GAME_ARG_MASTERSERVER_STATUS,
|
||||
GAME_ARG_USE_PORTS,
|
||||
|
||||
GAME_ARG_LOADSCENARIO,
|
||||
@@ -168,6 +170,8 @@ void printParameterHelp(const char *argv0, bool foundInvalidArgs) {
|
||||
printf("\n \t\tvps - which does NOT read commands from the");
|
||||
printf("\n \t local console (for some vps's).");
|
||||
|
||||
printf("\n%s\tCheck the current status of a headless server.",GAME_ARGS[GAME_ARG_MASTERSERVER_STATUS]);
|
||||
|
||||
printf("\n%s=x,y\t\t\tForce hosted games to listen internally on port",GAME_ARGS[GAME_ARG_USE_PORTS]);
|
||||
printf("\n\t\t\t\tx, externally on port y.");
|
||||
printf("\n \t\tWhere x is the internal port # on the local");
|
||||
@@ -425,7 +429,8 @@ int mainSetup(int argc, char **argv) {
|
||||
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_HELP])) == true ||
|
||||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VERSION])) == true ||
|
||||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS])) == true ||
|
||||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
|
||||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true ||
|
||||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_STATUS]))) {
|
||||
// Use this for masterserver mode for timers like Chrono
|
||||
if(SDL_Init(SDL_INIT_TIMER) < 0) {
|
||||
std::cerr << "Couldn't initialize SDL: " << SDL_GetError() << "\n";
|
||||
|
@@ -2042,9 +2042,10 @@ void BroadCastClientSocketThread::execute() {
|
||||
// class ServerSocket
|
||||
// ===============================================
|
||||
|
||||
ServerSocket::ServerSocket() : Socket() {
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
ServerSocket::ServerSocket(bool basicMode) : Socket() {
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] basicMode = %d\n",__FILE__,__FUNCTION__,__LINE__,basicMode);
|
||||
|
||||
this->basicMode = basicMode;
|
||||
//printf("SERVER SOCKET CONSTRUCTOR\n");
|
||||
//MutexSafeWrapper safeMutexUPNP(&ServerSocket::mutexUpnpdiscoverThread,CODE_AT_LINE);
|
||||
//ServerSocket::upnpdiscoverThread = NULL;
|
||||
@@ -2052,7 +2053,9 @@ ServerSocket::ServerSocket() : Socket() {
|
||||
|
||||
portBound = false;
|
||||
broadCastThread = NULL;
|
||||
if(this->basicMode == false) {
|
||||
UPNP_Tools::enabledUPNP = false;
|
||||
}
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
}
|
||||
@@ -2064,6 +2067,7 @@ ServerSocket::~ServerSocket() {
|
||||
|
||||
stopBroadCastThread();
|
||||
|
||||
if(this->basicMode == false) {
|
||||
//printf("In [%s::%s] Line: %d safeMutexUPNP\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//printf("SERVER SOCKET DESTRUCTOR\n");
|
||||
MutexSafeWrapper safeMutexUPNP(&ServerSocket::mutexUpnpdiscoverThread,CODE_AT_LINE);
|
||||
@@ -2074,6 +2078,7 @@ ServerSocket::~ServerSocket() {
|
||||
safeMutexUPNP.ReleaseLock();
|
||||
//printf("In [%s::%s] Line: %d safeMutexUPNP\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
|
||||
//printf("In [%s::%s] Line: %d UPNP_Tools::enabledUPNP = %d\n",__FILE__,__FUNCTION__,__LINE__,UPNP_Tools::enabledUPNP);
|
||||
if (UPNP_Tools::enabledUPNP) {
|
||||
UPNP_Tools::NETremRedirects(ServerSocket::externalPort);
|
||||
@@ -2087,6 +2092,7 @@ ServerSocket::~ServerSocket() {
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
safeMutexUPNP1.ReleaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerSocket::stopBroadCastThread() {
|
||||
@@ -2184,8 +2190,7 @@ void ServerSocket::bind(int port) {
|
||||
#endif
|
||||
|
||||
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
|
||||
if(err < 0)
|
||||
{
|
||||
if(err < 0) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf, "In [%s::%s] Error binding socket sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str());
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"%s",szBuf);
|
||||
@@ -2233,6 +2238,7 @@ void ServerSocket::listen(int connectionQueueSize) {
|
||||
disconnectSocket();
|
||||
}
|
||||
|
||||
if(this->basicMode == false) {
|
||||
if(connectionQueueSize > 0) {
|
||||
if(isBroadCastThreadRunning() == false) {
|
||||
startBroadCastThread();
|
||||
@@ -2244,6 +2250,7 @@ void ServerSocket::listen(int connectionQueueSize) {
|
||||
else {
|
||||
pauseBroadcast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Socket *ServerSocket::accept(bool errorOnFail) {
|
||||
|
Reference in New Issue
Block a user