#include "Server.h" #include #include #include #include #include #include #include #include "PlayerRegister.h" // Inhalt der LoginServer Klasse aus LoginServer.h // Konstruktor FactoryCraftServer::FactoryCraftServer(InitDatei* zIni) : ReferenceCounter() { Network::Start(100); runningThreads = 0; klients = new RCArray(); ini = dynamic_cast(zIni->getThis()); id = (int)*zIni->zWert("ServerId"); sslServer = new SSLServer(); sslServer->setPrivateKeyPassword(zIni->zWert("SSLPasswort")->getText()); sslServer->setCertificateFile(zIni->zWert("SSLCert")->getText()); Framework::Logging::info() << "using cert file " << zIni->zWert("SSLCert")->getText(); sslServer->setPrivateKeyFile(zIni->zWert("SSLKey")->getText()); Framework::Logging::info() << "using private key " << zIni->zWert("SSLKey")->getText(); server = new Server(); Framework::Logging::info() << "Server Port: " << ini->zWert("Port")->getText(); if (!server->verbinde( (unsigned short)TextZuInt(ini->zWert("Port")->getText(), 10), 10)) { Framework::Logging::error() << "Der Server konnte nicht gestartet werden."; exit(1); } Framework::Logging::info() << "SSL Server Port: " << ini->zWert("SSLPort")->getText(); if (!sslServer->verbinde( (unsigned short)TextZuInt(ini->zWert("SSLPort")->getText(), 10), 10)) { Framework::Logging::error() << "Der SSL Server konnte nicht gestartet werden."; exit(2); } Game::initialize( zIni->zWert("World")->getText(), zIni->zWert("SaveDir")->getText()); new Framework::AsynchronCall("Server", [this]() { runningThreads++; while (server->isConnected()) { SKlient* klient = server->getKlient(); if (!klient) continue; unsigned short len; klient->setEmpfangTimeout(5000); klient->getNachricht((char*)&len, 2); char* key = new char[len]; klient->getNachricht((char*)key, len); bool bg; klient->getNachricht((char*)&bg, 1); klient->setEmpfangTimeout(0); bool found = 0; EnterCriticalSection(&cs); for (FCKlient* client : *klients) { if (client->matchAuthKey(key, len)) { if (bg) { klient->sende("\1", 1); client->setBackgroundClient(klient); } else { klient->sende("\1", 1); client->setForegroundClient(klient); } found = 1; break; } } LeaveCriticalSection(&cs); if (!found) { klient->sende("\0", 1); Framework::Logging::error() << "client failed to pass through authorisation"; klient->release(); } } runningThreads--; }); InitializeCriticalSection(&cs); } // Destruktor FactoryCraftServer::~FactoryCraftServer() { sslServer->trenne(); server->trenne(); while (runningThreads > 0) Sleep(100); sslServer->release(); server->release(); if (klients) klients->release(); ini->release(); DeleteCriticalSection(&cs); } // nicht constant void FactoryCraftServer::run() { runningThreads++; while (sslServer->isConnected()) { SSLSKlient* klient = sslServer->getKlient(); if (!klient) continue; Framework::getThreadRegister()->cleanUpClosedThreads(); FCKlient* clHandle = new FCKlient( klient, dynamic_cast(getThis())); EnterCriticalSection(&cs); klients->add(clHandle); LeaveCriticalSection(&cs); clHandle->start(); } runningThreads--; } void FactoryCraftServer::close() { Game::INSTANCE->save(); sslServer->trenne(); server->trenne(); EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) klients->z(i)->absturz(); LeaveCriticalSection(&cs); } bool FactoryCraftServer::removeKlient(FCKlient* zKlient) { bool gefunden = 0; getThis(); EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == zKlient) { klients->remove(i); gefunden = 1; break; } } LeaveCriticalSection(&cs); release(); return gefunden; } bool FactoryCraftServer::hatClients() const { return klients->hat(0); } int FactoryCraftServer::getUnencryptedPort() const { return server->getPort(); } // Inhalt der LSKlient aus LoginServer.h // Konstruktor FCKlient::FCKlient(SSLSKlient* klient, FactoryCraftServer* ls) : Thread() { this->klient = klient; background = 0; foreground = 0; this->ls = ls; zGameClient = 0; backgroundReader = 0; foregroundReader = 0; backgroundWriter = 0; foregroundWriter = 0; authKey = randomSecret(); } // Destruktor FCKlient::~FCKlient() { if (zGameClient) { zGameClient->logout(); zGameClient = (GameClient*)zGameClient->release(); } if (background) background->release(); if (foreground) foreground->release(); delete backgroundReader; delete foregroundReader; delete backgroundWriter; delete foregroundWriter; klient->release(); ls->release(); } // nicht constant void FCKlient::setForegroundClient(SKlient* foreground) { Framework::Logging::trace() << "foreground client connected"; this->foreground = foreground; foregroundReader = new NetworkReader(foreground); foregroundWriter = new NetworkWriter(foreground); if (foreground && background) zGameClient = Game::INSTANCE->addPlayer( dynamic_cast(getThis()), name); foregroundRunning = 1; new AsynchronCall([this]() { while (this->foreground->waitForNextMessage()) { if (zGameClient) zGameClient->addMessage(foregroundReader); if (!zGameClient) Sleep(100); } cs.lock(); foregroundRunning = 0; if (!backgroundRunning) { cs.unlock(); if (zGameClient) { zGameClient->logout(); zGameClient = (GameClient*)zGameClient->release(); } ls->removeKlient(this); } else { cs.unlock(); } }); } void FCKlient::setBackgroundClient(SKlient* background) { Framework::Logging::trace() << "background client connected"; this->background = background; backgroundReader = new NetworkReader(background); backgroundWriter = new NetworkWriter(background); if (foreground && background) zGameClient = Game::INSTANCE->addPlayer( dynamic_cast(getThis()), name); backgroundRunning = 1; new AsynchronCall([this]() { while (this->background->waitForNextMessage()) { if (zGameClient) zGameClient->addMessage(backgroundReader); if (!zGameClient) Sleep(100); } cs.lock(); backgroundRunning = 0; if (!foregroundRunning) { cs.unlock(); if (zGameClient) { zGameClient->logout(); zGameClient = (GameClient*)zGameClient->release(); } ls->removeKlient(this); } else { cs.unlock(); } }); } void FCKlient::absturz() { klient->trenne(); if (background) background->trenne(); if (foreground) foreground->trenne(); warteAufThread(10000); ende(); } void FCKlient::thread() { bool identified = 0; while (1) { char c = 0; if (!klient->getNachricht(&c, 1)) break; else { bool br = 0; switch (c) { case 1: // Klient identifikation { char len; klient->getNachricht(&len, 1); char* name = new char[len + 1]; klient->getNachricht(name, len); name[(int)len] = 0; unsigned short sLen; klient->getNachricht((char*)&sLen, 2); char* secret = new char[sLen + 1]; klient->getNachricht(secret, sLen); secret[sLen] = 0; if (!Game::INSTANCE->checkPlayer(name, secret)) { klient->sende("\0", 1); delete[] name; delete[] secret; break; } if (!Game::INSTANCE->existsPlayer(name)) { Text secret = Game::INSTANCE->createPlayer(name); klient->sende("\2", 1); short len = (short)secret.getLength(); klient->sende((char*)&len, 2); klient->sende(secret.getText(), len); identified = 1; } else { klient->sende("\1", 1); identified = 1; } short keyLen = (short)authKey.getLength(); klient->sende((char*)&keyLen, 2); klient->sende(authKey, keyLen); this->name = name; delete[] name; delete[] secret; break; } case 2: // Verbindungsende br = 1; if (zGameClient) { zGameClient->logout(); zGameClient = (GameClient*)zGameClient->release(); } klient->sende("\1", 1); break; case 3: // ping klient->sende("\1", 1); break; case 4: // check player name valid { klient->sende("\1", 1); char len; klient->getNachricht(&len, 1); char* name = new char[len + 1]; klient->getNachricht(name, len); name[(int)len] = 0; short sLen; klient->getNachricht((char*)&sLen, 2); char* secret = new char[sLen + 1]; klient->getNachricht(secret, sLen); secret[sLen] = 0; char res = 0; if (Game::INSTANCE->checkPlayer(name, secret)) res = 1; klient->sende(&res, 1); delete[] name; delete[] secret; break; } default: br = 1; break; } if (br) break; } } if (!identified) { ls->removeKlient(this); } } NetworkWriter* FCKlient::zBackgroundWriter() const { return backgroundWriter; } NetworkWriter* FCKlient::zForegroundWriter() const { return foregroundWriter; } bool FCKlient::matchAuthKey(char* key, int len) const { if (foreground && background) return 0; if (len != authKey.getLength()) return 0; for (int i = 0; i < len; i++) { if (key[i] != authKey.getText()[i]) return 0; } return 1; }