#include "Server.h" #include #include #include #include #include #include #include "Game.h" #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; cs.lock(); 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; } } cs.unlock(); if (!found) { klient->sende("\0", 1); Framework::Logging::error() << "client failed to pass through authorisation"; klient->release(); } } runningThreads--; }); } // Destruktor FactoryCraftServer::~FactoryCraftServer() { sslServer->trenne(); server->trenne(); while (runningThreads > 0) Sleep(100); sslServer->release(); server->release(); if (klients) klients->release(); ini->release(); } // 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())); cs.lock(); klients->add(clHandle); cs.unlock(); clHandle->start(); } runningThreads--; } void FactoryCraftServer::close() { Game::INSTANCE->save(); sslServer->trenne(); server->trenne(); cs.lock(); for (int i = 0; i < klients->getEintragAnzahl(); i++) klients->z(i)->absturz(); cs.unlock(); } bool FactoryCraftServer::removeKlient(FCKlient* zKlient) { bool gefunden = 0; getThis(); cs.lock(); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == zKlient) { klients->remove(i); gefunden = 1; break; } } cs.unlock(); 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(); } void FCKlient::onInitialized() { RCArray filesToTransfer; checkResources("data/images", filesToTransfer); checkResources("data/models", filesToTransfer); checkResources("data/textures", filesToTransfer); short endSignal = 0; foreground->sende((char*)&endSignal, 2); char* buffer = new char[4096]; for (Text* path : filesToTransfer) { Datei file(path->getText()); __int64 length = file.getSize(); file.open(Datei::Style::lesen); int count = 0; while (count < length) { int l = MIN(4096, (int)length - count); file.lese(buffer, l); foreground->sende(buffer, l); count += l; } file.close(); } delete[] buffer; zGameClient = Game::INSTANCE->addPlayer(dynamic_cast(getThis()), name); } void FCKlient::checkResources(const char* path, RCArray& filesToTransfer) { Datei file(path); if (file.istOrdner()) { RCArray* names = file.getDateiListe(); for (Text* name : *names) { Text tmp(path); tmp.append() << "/" << *name; checkResources(tmp, filesToTransfer); } names->release(); } else { short len = (short)textLength(path); foreground->sende((char*)&len, 2); foreground->sende(path, len); Datei resFile(path); Zeit* zeit = resFile.getLastChange(); int tmp = zeit->zDatum()->getJahr(); foreground->sende((char*)&tmp, 4); tmp = zeit->zDatum()->getMonat(); foreground->sende((char*)&tmp, 4); tmp = zeit->zDatum()->getTag(); foreground->sende((char*)&tmp, 4); tmp = (zeit->zUhrzeit()->getStunde() * 60 + zeit->zUhrzeit()->getMinute()) * 60 + zeit->zUhrzeit()->getSekunde(); foreground->sende((char*)&tmp, 4); bool needed = 0; foreground->getNachricht((char*)&needed, 1); if (needed) { __int64 size = resFile.getSize(); foreground->sende((char*)&size, 8); filesToTransfer.add(new Text(path)); } zeit->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) { onInitialized(); } 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) { onInitialized(); } 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; }