#include "Server.h" #include #include #include #include #include #include // 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()); std::cout << "using cert file " << zIni->zWert("SSLCert")->getText() << "\n"; sslServer->setPrivateKeyFile(zIni->zWert("SSLKey")->getText()); std::cout << "using private key " << zIni->zWert("SSLKey")->getText() << "\n"; server = new Server(); std::cout << "Server Port: " << ini->zWert("Port")->getText() << "\n"; if (!server->verbinde( (unsigned short)TextZuInt(ini->zWert("Port")->getText(), 10), 10)) { std::cout << "Der Server konnte nicht gestartet werden.\n"; exit(1); } std::cout << "SSL Server Port: " << ini->zWert("SSLPort")->getText() << "\n"; if (!sslServer->verbinde( (unsigned short)TextZuInt(ini->zWert("SSLPort")->getText(), 10), 10)) { std::cout << "Der SSL Server konnte nicht gestartet werden.\n"; 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) client->setBackgroundClient(klient); else client->setForegroundClient(klient); found = 1; break; } } LeaveCriticalSection(&cs); if (!found) 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(); Game::INSTANCE->requestStop(); Game::INSTANCE->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() { sslServer->trenne(); EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) klients->z(i)->absturz(); klients = (RCArray*)klients->release(); Game::INSTANCE->save(); LeaveCriticalSection(&cs); } bool FactoryCraftServer::absturzKlient(int accountId) { bool gefunden = 0; EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) && klients->z(i)->getAccountId() == accountId) { klients->z(i)->absturz(); klients->remove(i); gefunden = 1; break; } } LeaveCriticalSection(&cs); return gefunden; } bool FactoryCraftServer::removeKlient(FCKlient* zKlient) { bool gefunden = 0; EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == zKlient) { klients->remove(i); gefunden = 1; break; } } LeaveCriticalSection(&cs); 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; accountId = 0; this->ls = ls; zGameClient = 0; backgroundReader = 0; foregroundReader = 0; backgroundWriter = 0; foregroundWriter = 0; authKey = randomKey(authKeyLen); } // 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(); delete[] authKey; } // nicht constant void FCKlient::setForegroundClient(SKlient* foreground) { this->foreground = foreground; foregroundReader = new NetworkReader(foreground); foregroundWriter = new NetworkWriter(foreground); if (foreground && background) zGameClient = Game::INSTANCE->addPlayer(dynamic_cast(getThis()), Framework::Text((int)accountId)); new AsynchronCall([this]() { while (this->foreground->waitForNextMessage()) { if (zGameClient) zGameClient->addMessage(foregroundReader); if (!zGameClient) Sleep(100); } zGameClient->logout(); ls->removeKlient(this); }); } void FCKlient::setBackgroundClient(SKlient* background) { this->background = background; backgroundReader = new NetworkReader(background); backgroundWriter = new NetworkWriter(background); if (foreground && background) zGameClient = Game::INSTANCE->addPlayer(dynamic_cast(getThis()), Framework::Text((int)accountId)); new AsynchronCall([this]() { while (this->background->waitForNextMessage()) { if (zGameClient) zGameClient->addMessage(backgroundReader); if (!zGameClient) Sleep(100); } zGameClient->logout(); ls->removeKlient(this); }); } void FCKlient::absturz() { ende(); klient->trenne(); } void FCKlient::thread() { 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); } else { klient->sende("\1", 1); } klient->sende((char*)&authKeyLen, 4); klient->sende(authKey, authKeyLen); 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; } } } int FCKlient::getAccountId() const // gibt die KlientId zurück { return accountId; } 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 != authKeyLen) return 0; for (int i = 0; i < len; i++) { if (key[i] != authKey[i]) return 0; } return 1; }