- added new headless server status check:

on the SAME box as the headless run:
./megaglest --headless-server-status
This commit is contained in:
Mark Vejvoda
2012-03-25 06:55:43 +00:00
parent bc3cc07aba
commit d356e5f5de
7 changed files with 201 additions and 40 deletions

View File

@@ -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;

View File

@@ -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");

View File

@@ -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());

View File

@@ -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);

View File

@@ -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);

View File

@@ -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";

View File

@@ -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) {