#include "SpielServer.h" #include #include #include #include #ifdef WIN32 #include "..\Datenbank\Datenbank.h" #else #include "Datenbank.h" #endif // Inhalt der SpielServer Klasse aus SpielServer.h // Konstruktor SpielServer::SpielServer(InitDatei* zIni) : Thread() { Network::Start(100); std::cout << "SS: Verbindung mit Datenbank wird hergestellt...\n"; db = new SSDatenbank(zIni); empfangen = 0; gesendet = 0; fehler = new Text(); ini = dynamic_cast(zIni->getThis()); id = (int)*zIni->zWert("ServerId"); server = new Server(); aServer = new SSLServer(); aServer->setPrivateKeyPassword(zIni->zWert("SSLPasswort")->getText()); aServer->setCertificateFile(zIni->zWert("SSLCert")->getText()); aServer->setPrivateKeyFile(zIni->zWert("SSLKey")->getText()); std::cout << "SS: Starten des Admin Servers...\n"; if (!aServer->verbinde((unsigned short)TextZuInt(ini->zWert("AdminServerPort")->getText(), 10), 10)) { std::cout << "SS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n"; exit(1); } db->setServerStatus(id, 2); end = 0; nichtPausiert = 0; InitializeCriticalSection(&cs); startSpielThread = new SpielFinden(this); if (zIni->zWert("Aktiv")->istGleich("TRUE")) { serverStarten(); serverFortsetzen(); } erstellt = new RCArray< SpielErstellt >(); spiele = new RCArray< Spiel >(); klients = new RCArray< SSKlient >(); spielHistorieId = new Array< int >(); historieS = new HistorieSender(this); historieS->start(); } // Destruktor SpielServer::~SpielServer() { historieS->setEnde(); historieS->warteAufThread(20000); historieS->ende(); historieS->release(); fehler->release(); server->trenne(); server->release(); aServer->trenne(); aServer->release(); ini->release(); db->release(); DeleteCriticalSection(&cs); startSpielThread->release(); erstellt->release(); spiele->release(); if (klients) klients->release(); spielHistorieId->release(); } // nicht constant void SpielServer::lock() { EnterCriticalSection(&cs); } void SpielServer::unlock() { LeaveCriticalSection(&cs); } void SpielServer::runn() { while (!end && aServer->isConnected()) { SSLSKlient* klient; klient = aServer->getKlient(); if (end && klient) { klient->trenne(); klient = (SSLSKlient*)klient->release(); Sleep(1000); return; } if (!klient) continue; SSAKlient* slHandle = new SSAKlient(klient, dynamic_cast(getThis())); slHandle->start(); } } void SpielServer::thread() { while (server->isConnected()) { SKlient* klient; klient = server->getKlient(); if (!klient) continue; Framework::getThreadRegister()->cleanUpClosedThreads(); SSKlient* slHandle = new SSKlient(klient, dynamic_cast(getThis())); slHandle->start(); } } void SpielServer::close() { db->setServerStatus(id, 1); server->trenne(); #ifdef WIN32 warteAufThread(1000); #endif lock(); for (int i = 0; i < klients->getEintragAnzahl(); i++) klients->z(i)->absturz(); if (klients) klients = (RCArray*) klients->release(); unlock(); ende(); run = 0; end = 1; Klient* klient = new Klient(); klient->verbinde(aServer->getPort(), "127.0.0.1"); Sleep(500); aServer->trenne(); klient->release(); } bool SpielServer::serverStarten() { if (nichtPausiert) { fehler->setText("Der Server konnte nicht gestartet werden: Der Server läuft bereits."); return 0; } if (server) server->release(); server = new Server(); if (server->verbinde((unsigned short)TextZuInt(ini->zWert("ServerPort")->getText(), 10), 10)) { nichtPausiert = 1; start(); startSpielThread->setSpielServerId(id); startSpielThread->start(); return 1; } else { serverBeenden(); fehler->setText("Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung."); return 0; } } bool SpielServer::serverPause() { if (!nichtPausiert) { fehler->setText("Der Server konnte nicht pausiert werden: Der Server läuft nicht."); return 0; } if (!db->setServerStatus(id, 2)) { fehler->setText("Der Server konnte nicht pausiert werden: "); fehler->append(db->getLetzterFehler()); return 0; } return 1; } bool SpielServer::serverFortsetzen() { if (!nichtPausiert) { fehler->setText("Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht."); return 0; } if (!db->setServerStatus(id, 3)) { fehler->setText("Der Server konnte nicht fortgesetzt werden: "); fehler->append(db->getLetzterFehler()); return 0; } return 1; } bool SpielServer::serverBeenden() { if (!nichtPausiert) { fehler->setText("Der Server konnte nicht beendet werden: Der Server läuft nicht."); return 0; } if (db->serverIstNichtPausiert(id)) { fehler->setText("Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden."); return 0; } startSpielThread->setEnde(); startSpielThread->warteAufThread(2000); startSpielThread->ende(); nichtPausiert = 0; ende(); if (server) server->trenne(); return 1; } bool SpielServer::setMaxSpiele(int ms) { if (!db->setMaxSpiele(id, ms)) { fehler->setText("Die maximale Anzahl der Spiele konnte nicht gesetzt werden:\n"); fehler->append(db->getLetzterFehler()); return 0; } ini->setWert("MaxSpiele", Text() += ms); return 1; } void SpielServer::addSpielErstellt(SpielErstellt* erstellt) { lock(); this->erstellt->add(erstellt); unlock(); } void SpielServer::SpielErstelltAbbruch(int spielErstelltId) { lock(); for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { if (erstellt->z(i)->getId() == spielErstelltId) { erstellt->z(i)->abbruch(); break; } } unlock(); } void SpielServer::removeSpielErstellt(int id) { lock(); bool gefunden = 0; for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { if (erstellt->z(i)->getId() == id) { SpielErstellt* zse = erstellt->get(i); erstellt->remove(i); unlock(); zse->release(); gefunden = 1; break; } } if (!gefunden) unlock(); } bool SpielServer::registerKlient(SSKlient* klient) { lock(); bool gefunden = 0; for (int i = 0; i < klients->getEintragAnzahl(); i++) { SSKlient* tmp = klients->z(i); if (tmp) { if (tmp->getAccountId() == klient->getAccountId()) { klient->getThis(); tmp->setSenden(klient); klient->release(); gefunden = 1; unlock(); return 1; } } } if (!gefunden) klients->add(klient); unlock(); return 0; } bool SpielServer::absturzKlient(int klientId) { lock(); SSKlient* zKlient = 0; for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i)->getKlientNummer() == klientId) { zKlient = klients->z(i); break; } } if (!zKlient) { unlock(); return 0; } int id = 0; int ak = db->getAktionForKlient(this->id, zKlient->getAccountId(), &id); switch (ak) { case 0: // Information Über Verwendung des Klient ist verlorengegangen (überall abmelden) for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { SpielErstellt* tmp = erstellt->z(i); if (tmp) tmp->klientGetrennt(zKlient); } for (int i = 0; i < spiele->getEintragAnzahl(); i++) { Spiel* tmp = spiele->z(i); if (tmp) tmp->klientGetrennt(zKlient); } break; case 1: // Spiel Erstellt for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { SpielErstellt* tmp = erstellt->z(i); if (tmp) { if (tmp->getId() == id) { tmp->klientGetrennt(zKlient); break; } } } break; case 2: // Spielt for (int i = 0; i < spiele->getEintragAnzahl(); i++) { Spiel* tmp = spiele->z(i); if (tmp && tmp->getId() == id) { tmp->klientGetrennt(zKlient); break; } } break; } bool gefunden = 0; for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == zKlient) { zKlient->absturz(); zKlient->getThis(); klients->remove(i); unlock(); zKlient->release(); gefunden = 1; break; } } if (!gefunden) unlock(); return 1; } bool SpielServer::verteileKlient(SSKlient* klient) { lock(); int id = 0; int ak = db->getAktionForKlient(this->id, klient->getAccountId(), &id); switch (ak) { case 0: // Keine Verwendung für den Klient unlock(); return 0; break; case 1: // Spiel Erstellt for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { SpielErstellt* tmp = erstellt->z(i); if (tmp) { if (tmp->getId() == id) { tmp->klientVerbunden(dynamic_cast(klient->getThis())); unlock(); return 1; } } } break; case 2: // Spielt for (int i = 0; i < spiele->getEintragAnzahl(); i++) { Spiel* tmp = spiele->z(i); if (tmp) { if (tmp->getId() == id) { tmp->klientVerbunden(dynamic_cast(klient->getThis())); unlock(); return 1; } } } break; } unlock(); return 0; } void SpielServer::unregisterKlient(SSKlient* zKlient) { lock(); int id = 0; int ak = db->getAktionForKlient(this->id, zKlient->getAccountId(), &id); switch (ak) { case 0: // Information Über Verwendung des Klient ist verlorengegangen (überall abmelden) for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { SpielErstellt* tmp = erstellt->z(i); if (tmp) tmp->klientGetrennt(zKlient); } for (int i = 0; i < spiele->getEintragAnzahl(); i++) { Spiel* tmp = spiele->z(i); if (tmp) tmp->klientGetrennt(zKlient); } break; case 1: // Spiel Erstellt for (int i = 0; i < erstellt->getEintragAnzahl(); i++) { SpielErstellt* tmp = erstellt->z(i); if (tmp) { if (tmp->getId() == id) { tmp->klientGetrennt(zKlient); break; } } } break; case 2: // Spielt for (int i = 0; i < spiele->getEintragAnzahl(); i++) { Spiel* tmp = spiele->z(i); if (tmp && tmp->getId() == id) { tmp->klientGetrennt(zKlient); break; } } break; } bool gefunden = 0; for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == zKlient) { zKlient->getThis(); klients->remove(i); unlock(); zKlient->release(); gefunden = 1; break; } } if (!gefunden) { unlock(); zKlient->release(); } } void SpielServer::klientsMM(SSKlient* k) { lock(); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == k) { klients->z(i)->getThis(); klients->z(i)->getThis(); klients->remove(i); } } unlock(); } void SpielServer::addSpiel(Spiel* spiel) { lock(); spiele->add(spiel); unlock(); } void SpielServer::removeSpiel(int spielId) { lock(); bool gefunden = 0; for (int i = 0; i < spiele->getEintragAnzahl(); i++) { if (spiele->z(i) && spiele->z(i)->getId() == spielId) { Spiel* zs = spiele->get(i); spiele->remove(i); unlock(); zs->release(); gefunden = 1; break; } } if (!gefunden) unlock(); } void SpielServer::addGesendet(int bytes) { gesendet += bytes; } void SpielServer::addEmpfangen(int bytes) { empfangen += bytes; } void SpielServer::addSpielHistorieId(int id) { lock(); spielHistorieId->add(id); unlock(); } bool SpielServer::hatSpielHistorieId(int id) { bool ret = 0; lock(); int anz = spielHistorieId->getEintragAnzahl(); for (int i = 0; i < anz; i++) { if (spielHistorieId->hat(i) && spielHistorieId->get(i) == id) { ret = 1; break; } } unlock(); return ret; } void SpielServer::removeSpielHistorieId(int id) { lock(); int anz = spielHistorieId->getEintragAnzahl(); for (int i = 0; i < anz; i++) { if (spielHistorieId->hat(i) && spielHistorieId->get(i) == id) { spielHistorieId->remove(i); break; } } unlock(); } // constant bool SpielServer::istAn() const { return db->serverIstNichtPausiert(id); } Server* SpielServer::zServer() const { return server; } SSDatenbank* SpielServer::zDB() const { return db; } InitDatei* SpielServer::zInit() const { return ini; } bool SpielServer::hatClients() const { return klients->hat(0); } int SpielServer::getId() const { return id; } const char* SpielServer::getLetzterFehler() const { return fehler->getText(); } const char* SpielServer::getIp() const { return ini->zWert("ServerIp")->getText(); } int SpielServer::getPort() const { if (!ini->wertExistiert("ServerPort")) return 0; return TextZuInt(ini->zWert("ServerPort")->getText(), 10); } // Inhalt der SSAKlient Klasse aus SpielServer.h // Konstruktor SSAKlient::SSAKlient(SSLSKlient* klient, SpielServer* ss) : Thread() { this->klient = klient; name = new Text(""); passwort = new Text(""); adminId = 0; version = 0; this->ss = ss; } // Destruktor SSAKlient::~SSAKlient() { klient->trenne(); klient->release(); ss->release(); name->release(); passwort->release(); } // nicht constant void SSAKlient::thread() { while (1) { char c = 0; if (!klient->getNachricht(&c, 1)) break; else { bool br = 0; switch (c) { case 1: // Login if (1) { klient->sende("\1", 1); unsigned char nLen = 0; klient->getNachricht((char*)&nLen, 1); char* n = new char[nLen + 1]; n[(int)nLen] = 0; if (nLen) klient->getNachricht(n, nLen); unsigned char pLen = 0; klient->getNachricht((char*)&pLen, 1); char* p = new char[pLen + 1]; p[(int)pLen] = 0; if (pLen) klient->getNachricht(p, pLen); int adminId = ss->zDB()->istAdministrator(n, p); if (adminId) { klient->sende("\1", 1); name->setText(n); passwort->setText(p); this->adminId = adminId; } else errorZuKlient("Falsche Kombination aus Name und Passwort."); delete[] n; delete[] p; } break; case 2: // Logout adminId = 0; name->setText(""); passwort->setText(""); klient->sende("\1", 1); break; case 3: // Trennen br = 1; klient->sende("\1", 1); break; case 4: // Server starten if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (ss->zDB()->adminHatRecht(adminId, Admin_Recht::SSStarten)) { if (!ss->serverStarten()) { Text* err = new Text(); err->append(ss->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } else klient->sende("\1", 1); } else errorZuKlient("Du bist nicht berechtigt den Server zu starten."); } break; case 5: // Server beenden if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (ss->zDB()->adminHatRecht(adminId, Admin_Recht::SSBeenden)) { if (ss->serverBeenden()) klient->sende("\1", 1); else { Text* err = new Text(); err->append(ss->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else errorZuKlient("Du bist nicht berechtigt den Server zu beenden."); } break; case 6: // Programm Schließen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { bool ok = 0; if (ss->isRunning()) { if (ss->zDB()->adminHatRecht(adminId, Admin_Recht::SSBeenden)) { if (ss->serverBeenden()) ok = 1; else { Text* err = new Text(); err->append(ss->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else errorZuKlient("Du bist nicht berechtigt den Server zu beenden."); } else ok = 1; if (ok && ss->hatClients()) { errorZuKlient("Es sind noch Klients Online. Bitte versuche es später erneut."); break; } if (ok) { klient->sende("\1", 1); std::cout << "SS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n"; ss->close(); br = 1; } } break; case 7: // Progtamm abstürzen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { bool ok = 0; if (ss->isRunning()) { if (ss->zDB()->adminHatRecht(adminId, Admin_Recht::SSBeenden)) { ss->serverBeenden(); ok = 1; } else errorZuKlient("Du bist nicht berechtigt den Server zu beenden."); } else ok = 1; if (ok) { klient->sende("\1", 1); std::cout << "sS: Der Server wurde von Benutzer " << adminId << " terminiert.\n"; ss->close(); br = 1; } } break; case 8: // Status Frage if (1) { char status = 0; if (ss->isRunning()) { status = 1; if (ss->istAn()) status = 2; } klient->sende("\1", 1); klient->sende(&status, 1); } break; case 9: // Server pausieren if (!adminId) errorZuKlient("Du musst dich einloggen."); else { klient->sende("\1", 1); char pause = 0; klient->getNachricht(&pause, 1); if (ss->zDB()->adminHatRecht(adminId, Admin_Recht::SSPausieren)) { bool ok = 0; if (pause) ok = ss->serverPause(); else ok = ss->serverFortsetzen(); if (ok) klient->sende("\1", 1); else { Text* err = new Text(); err->append(ss->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else { if (pause) errorZuKlient("Du bist nicht berechtigt den Server zu pausieren."); else errorZuKlient("Du bist nicht berechtigt den Server fortzusetzen."); } } break; case 0xA: // maximale Anzahl der Spiele setzen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { klient->sende("\1", 1); int maxS = 0; klient->getNachricht((char*)&maxS, 4); if (ss->zDB()->adminHatRecht(adminId, Admin_Recht::SSMSChange)) { if (ss->setMaxSpiele(maxS)) klient->sende("\1", 1); else { Text* err = new Text(); err->append(ss->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else errorZuKlient("Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern."); } break; case 0xB: // Spiel Historie downloaden if (adminId) errorZuKlient("Zugriff verweigert."); else { klient->sende("\1", 1); int spielId = 0; klient->getNachricht((char*)&spielId, 4); if (!ss->hatSpielHistorieId(spielId)) { errorZuKlient("Zugriff auf Spiel-Historie verweigert."); break; } Text* pfad = new Text("../spiel log/"); *pfad += spielId; *pfad += "/fertig"; if (!DateiExistiert(*pfad)) { pfad->release(); errorZuKlient("Die Spiel-Historie wurde nicht gefunden."); break; } klient->sende("\1", 1); pfad->remove("/fertig"); sendeVerzeichnisAnKlient(*pfad, pfad->getLength() + 1); pfad->release(); klient->sende("\0", 1); } break; case 0xC: // klient absturtz if (1) { klient->sende("\1", 1); int klientId = 0; klient->getNachricht((char*)&klientId, 4); if (klientId && ss->absturzKlient(klientId)) klient->sende("\1", 1); else klient->sende("\0", 1); } break; default: errorZuKlient("Unbekannte Nachricht!"); break; } if (br) break; ss->addEmpfangen(klient->getDownloadBytes(1)); ss->addGesendet(klient->getUploadBytes(1)); } } ss->addEmpfangen(klient->getDownloadBytes(1)); ss->addGesendet(klient->getUploadBytes(1)); delete this; } void SSAKlient::sendeVerzeichnisAnKlient(const char* pfad, int gpl) { Datei* d = new Datei(); d->setDatei(pfad); if (d->istOrdner()) { int dAnz = d->getUnterdateiAnzahl(); RCArray< Text >* list = d->getDateiListe(); for (int i = 0; i < dAnz; i++) { if (list->z(i)) { Text* pf = new Text(pfad); pf->append("/"); pf->append(list->z(i)->getText()); sendeVerzeichnisAnKlient(*pf, gpl); pf->release(); } } list->release(); } else if (d->existiert()) { __int64 gr = d->getSize(); if (gr && d->zPfad()->getLength() - gpl > 0 && d->open(Datei::Style::lesen)) { char pfLen = (char)(d->zPfad()->getLength() - gpl); klient->sende(&pfLen, 1); klient->sende(d->zPfad()->getText() + gpl, pfLen); klient->sende((char*)&gr, 8); char* bytes = new char[2048]; while (gr) { short len = gr > 2048 ? 2048 : (short)gr; d->lese(bytes, len); klient->sende(bytes, len); gr -= len; } delete[] bytes; d->close(); } } d->release(); } void SSAKlient::errorZuKlient(const char* nachricht) const // sendet eine Fehlernachricht zum Klient { klient->sende("\3", 1); char len = (char)textLength(nachricht); klient->sende(&len, 1); klient->sende(nachricht, len); } // Inhalt der SSKlient Klasse aus SpielServer.h // Konstruktor SSKlient::SSKlient(SKlient* klient, SpielServer* ss) : SSKlientV() { empfangen = klient; unsigned char key[20] = { 253, 234, 211, 132, 121, 230, 95, 145, 201, 13, 43, 77, 153, 223, 253, 69, 234, 43, 52, 99 }; klient->setSendeKey((char*)key, 20); klient->setEmpfangKey((char*)key, 20); senden = 0; this->ss = ss; accountId = 0; klientNummer = 0; termThread = 1; verbunden = 0; zErstellt = 0; zSpiel = 0; InitializeCriticalSection(&cs); } // Destruktor SSKlient::~SSKlient() { lock(); unlock(); if (verbunden) trenne(); if (termThread) { if (verbunden) warteAufThread(1000); if (verbunden) { if (empfangen) empfangen->trenne(); if (senden) senden->trenne(); } if (empfangen) empfangen->release(); if (senden) senden->release(); DeleteCriticalSection(&cs); ss->klientsMM(this); ss->release(); ende(); // Eventuelles Ende des Aktuellen Threades } else { if (verbunden) { if (empfangen) empfangen->trenne(); if (senden) senden->trenne(); } if (empfangen) empfangen->release(); if (senden) senden->release(); DeleteCriticalSection(&cs); ss->klientsMM(this); ss->release(); } } // nicht constant void SSKlient::lock() { EnterCriticalSection(&cs); } void SSKlient::unlock() { LeaveCriticalSection(&cs); } void SSKlient::absturz() { ende(); if (senden) senden->trenne(); empfangen->trenne(); } void SSKlient::setSpielErstellt(SpielErstellt* zErstellt) { this->zErstellt = zErstellt; } void SSKlient::setSpiel(Spiel* zSpiel) { this->zSpiel = zSpiel; } void SSKlient::nichtTrennen() { verbunden = 0; } void SSKlient::spielGefunden(int karteId) { if (!senden) return; lock(); senden->sendeEncrypted("\xB", 1); senden->sendeEncrypted((char*)&karteId, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::zeitVerbleibend(char sekunden) { if (!senden) return; lock(); senden->sendeEncrypted("\1", 1); senden->sendeEncrypted(&sekunden, 1); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungAbgebrochen(const char* grund) { if (!senden) return; char len = (char)textLength(grund); lock(); senden->sendeEncrypted("\2", 1); senden->sendeEncrypted(&len, 1); if (len) senden->sendeEncrypted(grund, len); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::backInWarteschlange(char st, char min, char sec) { if (!senden) return; lock(); senden->sendeEncrypted("\4", 1); senden->sendeEncrypted(&st, 1); senden->sendeEncrypted(&min, 1); senden->sendeEncrypted(&sec, 1); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungFortsetzen() { if (!senden) return; lock(); senden->sendeEncrypted("\5", 1); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungInitialisierung(SpielerTeamStruktur* sts) { if (!senden) return; lock(); senden->sendeEncrypted("\6", 1); senden->sendeEncrypted((char*)&sts->spielerAnzahl, 4); senden->sendeEncrypted((char*)&sts->teamAnzahl, 4); for (int i = 0; i < sts->spielerAnzahl; i++) { int f = sts->spielerFarbe->hat(i) ? sts->spielerFarbe->get(i) : 0; senden->sendeEncrypted((char*)&f, 4); } for (int i = 0; i < sts->teamAnzahl; i++) { int f = sts->teamFarbe->hat(i) ? sts->teamFarbe->get(i) : 0; senden->sendeEncrypted((char*)&f, 4); } for (int i = 0; i < sts->teamAnzahl; i++) { Text* name = sts->teamName->z(i); char len = (char)name->getLength(); senden->sendeEncrypted(&len, 1); if (len) senden->sendeEncrypted(name->getText(), len); } for (int i = 0; i < sts->teamAnzahl; i++) { int size = sts->teamSize->hat(i) ? sts->teamSize->get(i) : 0; senden->sendeEncrypted((char*)&size, 4); } unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungAddSpieler(int accountId) { if (!senden) return; lock(); senden->sendeEncrypted("\7", 1); senden->sendeEncrypted((char*)&accountId, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungRemoveSpieler(int accountId) { if (!senden) return; lock(); senden->sendeEncrypted("\x8", 1); senden->sendeEncrypted((char*)&accountId, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungSpielerTeam(int accountId, int spielerNummer) { if (!senden) return; lock(); senden->sendeEncrypted("\x9", 1); senden->sendeEncrypted((char*)&accountId, 4); senden->sendeEncrypted((char*)&spielerNummer, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::erstellungChatNachricht(const char* nachricht) { if (!senden) return; char len = (char)textLength(nachricht); if (!len) return; lock(); senden->sendeEncrypted("\xA", 1); senden->sendeEncrypted(&len, 1); senden->sendeEncrypted(nachricht, len); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::spielLadenBeginn() { if (!senden) return; lock(); senden->sendeEncrypted("\xC", 1); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::spielLadenSpielerAdd(int accId, int spielerNumer) { if (!senden) return; lock(); senden->sendeEncrypted("\xD", 1); senden->sendeEncrypted((char*)&accId, 4); senden->sendeEncrypted((char*)&spielerNumer, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::spielLadenSetSpielerProzent(int accId, int prozent) { if (!senden) return; lock(); senden->sendeEncrypted("\xE", 1); senden->sendeEncrypted((char*)&accId, 4); senden->sendeEncrypted((char*)&prozent, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::spielLadenSetSpielerPing(int accId, int ping) { if (!senden) return; lock(); senden->sendeEncrypted("\xF", 1); senden->sendeEncrypted((char*)&accId, 4); senden->sendeEncrypted((char*)&ping, 4); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } double SSKlient::ping() { if (!senden) return 0; ZeitMesser* zeit = new ZeitMesser(); char ret = 0; lock(); zeit->messungStart(); senden->sendeEncrypted("\x10", 1); senden->getNachrichtEncrypted(&ret, 1); zeit->messungEnde(); unlock(); double retVal = zeit->getSekunden(); zeit->release(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); return retVal; } void SSKlient::spielLadenFertig() { if (!senden) return; lock(); senden->sendeEncrypted("\x11", 1); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::spielNachricht(short len, const char* bytes) { if (!senden) return; lock(); senden->sendeEncrypted("\x12", 1); senden->sende((char*)&len, 2); senden->sende(bytes, len); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::statistikNachricht(short len, const char* bytes) { if (!senden) return; lock(); senden->sendeEncrypted("\x13", 1); senden->sendeEncrypted((char*)&len, 2); senden->sendeEncrypted(bytes, len); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } bool SSKlient::keepAlive() { if (!senden || !verbunden) return 0; char res = 0; lock(); senden->sendeEncrypted("\x14", 1); senden->getNachrichtEncrypted(&res, 1); unlock(); return res == 1; } void SSKlient::trenne() { if (!verbunden) return; verbunden = 0; if (!senden) return; lock(); senden->sendeEncrypted("\0", 1); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::setSenden(SSKlient* klient) { senden = klient->getKlient(); Text* key = ss->zDB()->getKlientKey(klientNummer); if (!key) { senden->sendeEncrypted("\0", 1); errorZuKlientSende("Es konnte kein Key ermittelt werden."); } else { senden->sendeEncrypted("\1", 1); senden->setEmpfangKey(*key, key->getLength()); senden->setSendeKey(*key, key->getLength()); key->release(); } verbunden = 1; if (!ss->verteileKlient(this)) ss->unregisterKlient(this); klient->nichtTrennen(); klient->release(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } void SSKlient::thread() { int unbekannt = 0; bool del = 0; while (1) { bool br = 0; char message = 0; if (empfangen->getNachrichtEncrypted(&message, 1)) { switch (message) { case 1: // Klient Identifikation empfangen->getNachrichtEncrypted((char*)&klientNummer, 4); if (!klientNummer) errorZuKlientEmpfang("Du besitzt noch keine Klient Nummer."); else { accountId = ss->zDB()->getAccountId(klientNummer); termThread = 0; if (ss->registerKlient(this)) return; termThread = 1; Text* key = ss->zDB()->getKlientKey(klientNummer); if (!key) errorZuKlientEmpfang("Es konnte kein Key ermittelt werden."); else { empfangen->sendeEncrypted("\1", 1); empfangen->setEmpfangKey(*key, key->getLength()); empfangen->setSendeKey(*key, key->getLength()); key->release(); } } break; case 2: // Main / Erhaltung Server message if (1) { char befehl = 0; empfangen->getNachrichtEncrypted(&befehl, 1); switch (befehl) { case 2: // klient absturtz if (1) { int klientId = 0; empfangen->getNachrichtEncrypted((char*)&klientId, 4); if (klientId && ss->absturzKlient(klientId)) empfangen->sendeEncrypted("\1", 1); else empfangen->sendeEncrypted("\0", 1); } break; default: errorZuKlientEmpfang("Befehl nicht bekannt!"); break; } } break; case 3: // Verbindungsende trenne(); empfangen->sendeEncrypted("\1", 1); br = 1; break; case 4: // SpielErstellt annehmen if (zErstellt) { if (zErstellt->klientNimmtAn(accountId)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } } else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Dir wurde kein erstelltes Spiel zugeteilt."); } break; case 5: // SpielErstellt ablehnen if (zErstellt) { if (zErstellt->klientLehntAb(accountId)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } } else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Dir wurde kein erstelltes Spiel zugeteilt."); } break; case 6: // SpielErstellt team wechseln if (zSpiel) { empfangen->sendeEncrypted("\1", 1); int team = 0; empfangen->getNachrichtEncrypted((char*)&team, 4); if (zSpiel->klientWechseltTeam(accountId, team)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Das Team Ist bereits voll."); } } else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Dir wurde kein erstelltes Spiel zugeteilt."); } break; case 7: // SpielErstellt chat Nachricht if (zSpiel) { empfangen->sendeEncrypted("\1", 1); unsigned char len = 0; empfangen->getNachrichtEncrypted((char*)&len, 1); char* nachricht = new char[len + 1]; nachricht[(int)len] = 0; if (len) empfangen->getNachrichtEncrypted(nachricht, len); Text* msg = ss->zDB()->getAccountRufName(accountId); msg->append(": "); msg->append(nachricht); delete[] nachricht; if (zSpiel->chatNachricht(msg->getText())) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } msg->release(); } else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Dir wurde kein erstelltes Spiel zugeteilt."); } break; case 8: // Server Message if (1) { char befehl = 0; empfangen->getNachrichtEncrypted(&befehl, 1); switch (befehl) { case 0: // Verbindung Trennen empfangen->sendeEncrypted("\1", 1); br = 1; del = 1; break; case 1: // Spiel Erstellen Abbrechen if (1) { empfangen->sendeEncrypted("\1", 1); int spielErstelltId = 0; empfangen->getNachrichtEncrypted((char*)&spielErstelltId, 4); ss->SpielErstelltAbbruch(spielErstelltId); empfangen->sendeEncrypted("\1", 1); } break; default: empfangen->sendeEncrypted("\0", 1); break; } } break; case 9: // Bereit zum Laden if (zSpiel && zSpiel->klientBereitZumLaden(accountId)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } break; case 0xA: // Bereit zum Spiel if (zSpiel && zSpiel->klientBereitZumSpiel(accountId)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } break; case 0xB: // Spiel Nachricht if (1) { unsigned short len = 0; empfangen->getNachricht((char*)&len, 2); char* bytes = new char[len]; empfangen->getNachricht(bytes, len); if (!zSpiel || !zSpiel->spielNachricht(accountId, len, bytes)) errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); delete[] bytes; } break; case 0xC: // Spiel Laden Prozent if (1) { empfangen->sendeEncrypted("\1", 1); int prozent = 0; empfangen->getNachrichtEncrypted((char*)&prozent, 4); if (zSpiel && zSpiel->klientSpielLadenProzent(accountId, prozent)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } } break; case 0xD: // Statistik Nachricht if (1) { empfangen->sendeEncrypted("\1", 1); unsigned short len = 0; empfangen->getNachrichtEncrypted((char*)&len, 2); char* bytes = new char[len]; empfangen->getNachrichtEncrypted(bytes, len); if (zSpiel && zSpiel->statistikNachricht(accountId, len, bytes)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } delete[] bytes; } break; case 0xE: // Team wählen Fertig if (1) { if (zSpiel && zSpiel->klientTeamAuswahlFertig(accountId)) empfangen->sendeEncrypted("\1", 1); else { empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Es ist ein unbekannter Fehler aufgetreten."); } } break; case 0xF: // ping if (1) { empfangen->sendeEncrypted("\1", 1); keepAlive(); } break; default: empfangen->sendeEncrypted("\0", 1); errorZuKlientSende("Unbekannte Nachricht."); unbekannt += 2; if (unbekannt > 10) { trenne(); br = 1; } break; } unbekannt--; if (unbekannt < 0) unbekannt = 0; } else { trenne(); br = 1; } if (br) break; ss->addEmpfangen(empfangen->getDownloadBytes(1)); ss->addGesendet(empfangen->getUploadBytes(1)); } ss->addEmpfangen(empfangen->getDownloadBytes(1)); ss->addGesendet(empfangen->getUploadBytes(1)); if (del || !accountId) { termThread = 0; delete this; } else { termThread = 0; ss->unregisterKlient(this); } } void SSKlient::errorZuKlientEmpfang(const char* nachricht) // sendet eine Fehlernachricht zum Klient { unsigned char len = (unsigned char)textLength(nachricht); if (!len) return; if (empfangen) { empfangen->sendeEncrypted("\3", 1); empfangen->sendeEncrypted((char*)&len, 1); empfangen->sendeEncrypted(nachricht, len); } ss->addEmpfangen(empfangen->getDownloadBytes(1)); ss->addGesendet(empfangen->getUploadBytes(1)); } void SSKlient::errorZuKlientSende(const char* nachricht) { unsigned char len = (unsigned char)textLength(nachricht); if (!len) return; if (senden) { lock(); senden->sendeEncrypted("\3", 1); senden->sendeEncrypted((char*)&len, 1); senden->sendeEncrypted(nachricht, len); unlock(); ss->addEmpfangen(senden->getDownloadBytes(1)); ss->addGesendet(senden->getUploadBytes(1)); } } // const int SSKlient::getAccountId() const { return accountId; } int SSKlient::getKlientNummer() const { return klientNummer; } SKlient* SSKlient::getKlient() const { return dynamic_cast(empfangen->getThis()); }