#include "server.h" Server::Server(LogDest log) { m_log = log; if (log == LOG_DEST::LOGFILE) { m_logfile = std::ofstream("server.log", std::ofstream::out); if (!m_logfile.is_open()) { m_log = LOG_DEST::CONSOLE; // Fallback console. Log("Ouverture fichier log: repli vers console.", true, false); } } } Server::~Server() { if (m_logfile.is_open()) m_logfile.close(); if (m_sock_udp) closesocket(m_sock_udp); if (m_sock_tcp) closesocket(m_sock_tcp); #ifdef _WIN32 WSACleanup(); #endif } int Server::Init() { Log("Initialisation du serveur...", false, false); #ifdef _WIN32 if (WSAStartup(MAKEWORD(2, 2), &m_wsaData) != 0) { /* Initialisation de l'environnement reseau (Windows only) */ Log("Initialisation WinSock.", true, true); return 1; } #endif m_sock_udp = socket(AF_INET, SOCK_DGRAM, 0); if (m_sock_udp == INVALID_SOCKET) { /* Creation du socket UDP */ Log("Creation Socket UDP.", true, true); return 2; } m_sock_tcp = socket(AF_INET, SOCK_STREAM, 0); if (m_sock_tcp == INVALID_SOCKET) { /* Creation du socket TCP */ Log("Creation Socket TCP.", true, true); return 3; } /* Creation structure donnes descripteur du socket serveur */ sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(SRV_PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(m_sock_udp, (sockaddr*)&addr, sizeof(addr)) != 0) { /* Associer le socket UDP au port */ Log("Association Socket UDP.", true, true); return 4; } if (bind(m_sock_tcp, (sockaddr*)&addr, sizeof(addr)) != 0) { /* Associer le socket TCP au port */ Log("Association Socket TCP.", true, true); return 5; } return 0; } int Server::Ready() { int nbrjoueurs = 0, nbrconn = 0; #ifdef SRV_MANUAL_SETUP do { Log("Entrez la durée de la partie: ", false, false); std::cin >> m_game.countdown; std::cout << std::endl; } while (m_game.countdown < 1); do { Log("Entrez le seed de la partie: ", false, false); std::cin >> m_game.seed; std::cout << std::endl; } while (m_game.seed < 1); do { Log("Entrez le nombre de joueurs: ", false, false); std::cin >> nbrjoueurs; std::cout << std::endl; } while (nbrjoueurs > 0 && nbrjoueurs >= MAX_CONNECTIONS); #else // setup preconfiguré m_game.countdown = 360; m_game.seed = 9370707; nbrjoueurs = 1; #endif m_game.gameType = 1; if (listen(m_sock_tcp, MAX_CONNECTIONS) < 0) { Log("Écoute sur le port TCP.", true, true); return 1; } char* buf = new char[150]; uint32_t buflen = 150; bool readystart = false; srand(time(NULL)); Log("À l'écoute sur le port: " + std::to_string(SRV_PORT), false, false); buildIdList(ID_LIST_SIZE); while (!readystart) { sockaddr_in sockad; #ifdef _WIN32 int addrlen = sizeof(sockad); #else // maudit que c'est con, ça. unsigned int addrlen = sizeof(sockad); #endif SOCKET sock = accept(m_sock_tcp, (sockaddr*)&sockad, &addrlen); if (sock < 0) Log("Erreur de connexion", true, false); else if (sock > 0) { std::string str = "Nouvelle connection provenant de: "; char* strbuf = new char[BUFFER_LENGTH]; uint32_t strbuflen = BUFFER_LENGTH; str.append(inet_ntop(AF_INET, &sockad.sin_addr, strbuf, strbuflen)).append(": ").append(std::to_string(sockad.sin_port)); if (recv(sock, buf, buflen, 0) > 0) { netprot::LoginInfo log; netprot::PlayerInfo play; if (netprot::Deserialize(&log, buf, buflen)) { log.sid = getUniqueId(); log.tid = 0; str.append(" Nom: ").append(log.name); Log(str, false, false); str = ""; str.append(log.name).append(" SID: [").append(std::to_string(log.sid).append("]")); Log(str, false, false); netprot::sendPack(sock, &log, &buf, &buflen); play.id = getUniqueId(); memcpy(play.name, log.name, std::strlen(log.name) + 1); play.tid = log.tid; netprot::sendPack(sock, &m_game, &buf, &buflen); Connection* conn = new Connection(sock, sockad, log, play); m_players[log.sid] = conn; if (++nbrconn >= nbrjoueurs) readystart = true; } } } } return 0; } void Server::Run() { char* buf = new char[BUFFER_LENGTH]; Log("Partie en cours...", false, false); while (true) { if (recv(m_sock_udp, buf, BUFFER_LENGTH, 0) > 0) { } } } inline std::string Server::LogTimestamp() { time_t rawtime; struct tm timeinfo; char buffer[80]; time(&rawtime); #ifdef _WIN32 localtime_s(&timeinfo, &rawtime); #else localtime_r(&rawtime, &timeinfo); #endif strftime(buffer, sizeof(buffer), "%d-%m-%Y %H:%M:%S", &timeinfo); std::string str(buffer); return "[" + str + "] "; } void Server::Log(std::string str, bool is_error = false, bool is_fatal = false) { switch (m_log) { case LOG_DEST::LOGFILE: m_logfile << LogTimestamp() << (is_fatal ? "FATAL " : "") << (is_error ? "ERROR " : "") << str << std::endl; break; case LOG_DEST::CONSOLE: default: std::cout << LogTimestamp() << (is_fatal ? "FATAL " : "") << (is_error ? "ERROR " : "") << str << std::endl; break; } if (is_fatal) { if (m_sock_udp) closesocket(m_sock_udp); if (m_sock_tcp) closesocket(m_sock_tcp); #ifdef _WIN32 WSACleanup(); #endif } } void Server::buildIdList(size_t size) { std::set lst; do lst.insert(((uint64_t)rand() << 25) % 8675309); // EIGHT SIX SEVENFIVE THREE AUGHT NIIIIIIiIIiiIiINE! while (lst.size() < size); m_ids = std::vector(lst.begin(), lst.end()); } uint64_t Server::getUniqueId() { uint64_t id = m_ids.back(); m_ids.pop_back(); return id; } // Test serialize/deserialize: /* netprot::LoginInfo log, log2; std::cout << "Nom? "; std::cin.getline(log.name, 32); // NO! STD::CIN >> VARIABLE;! EVEEEEEERRRR!!! log.sid = 12345; char* buf = new char[150]; uint32_t buflen = 150; netprot::Serialize(&log, &buf, &buflen); bool is_work = netprot::Deserialize(&log2, buf, buflen); std::string str; str.append(is_work ? "Y " : "N ").append(log2.name).append(": ").append(std::to_string(log2.sid)); Log(str, false, false); */ ///* Recevoir paquet */ //while (true) { // char buffer[2048]; // sockaddr_in client; // //#ifdef _WIN32 // Mais pourquoi? // int clen = sizeof(client); //#else // unsigned int clen = sizeof(client); //#endif // // int count = recvfrom(socket_udp, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&client, &clen); // // if (count < 0) { // Log("Erreur de reception de paquet.", socket_udp); // return 4; // } // // buffer[count] = '\0'; // // /* Gérer le paquet reçu */ // std::string commande(buffer); // // if (commande.find("echo ") == 0) { /* ECHO */ // std::string::size_type pos = commande.find(' '); // std::string parametres = commande.substr(pos + 1); // // sendto(socket_udp, parametres.c_str(), parametres.length(), 0, (const sockaddr*)&client, sizeof(client)); // } // else if (commande.find("date ") == 0) { /* DATE */ // time_t rawtime; // struct tm* timeinfo = new tm(); // char tbuffer[80]; // // time(&rawtime); // //#ifdef _WIN32 // localtime_s(timeinfo, &rawtime); //#else // localtime_r(&rawtime, timeinfo); //#endif // // strftime(tbuffer, 80, "%a %b %e %T %G", timeinfo); // // sendto(socket_udp, tbuffer, sizeof(tbuffer), 0, (const sockaddr*)&client, sizeof(client)); // delete timeinfo; // } // else if (commande.find("ping ") == 0) { /* PING */ // sendto(socket_udp, "pong", sizeof("pong"), 0, (const sockaddr*)&client, sizeof(client)); // } // else if (commande.find("usager ") == 0) { /* USAGER */ // std::string user; // //#ifdef _WIN32 // wchar_t userbuf[30]; // DWORD usersize = 30; // // GetUserNameW(userbuf, &usersize); // // std::wstring wuser = userbuf; // user = std::string(wuser.begin(), wuser.end()); //#else // char ptr[30]; // getlogin_r(ptr, sizeof(ptr) - 1); // user = std::string(ptr); //#endif // // sendto(socket_udp, user.c_str(), user.length(), 0, (const sockaddr*)&client, sizeof(client)); // } // else if (commande.find("exec ") == 0) { /* EXEC */ // std::string::size_type pos = commande.find(' '); // std::string parametres = commande.substr(pos + 1); // // FILE* pipe = nullptr; // char buffer[301]; // 300 caractères + '\0' // std::string reponse; // // pipe = popen(parametres.c_str(), "r"); // // if (!pipe) // reponse = "Erreur de commande!"; // else while (!feof(pipe)) { // if (fgets(buffer, sizeof(buffer) - 1, pipe)) // reponse += buffer; // } // // if (pipe) // pclose(pipe); // // if (reponse.length() > 300) // reponse = reponse.substr(0, 300); // else if (reponse.length() < 1) // reponse = "OK!"; // // sendto(socket_udp, reponse.c_str(), reponse.length(), 0, (const sockaddr*)&client, sizeof(client)); // } // else if (commande.find("bye ") == 0) { /* BYE */ // Log("", 0); // Message d'erreur pas de message d'erreur! // return 0; // } // else sendto(socket_udp, "huh?", sizeof("huh?"), 0, (const sockaddr*)&client, sizeof(client)); /* DEFAULT */ //} // ///* Ce bout de code ne devrait theoriquement jamais etre atteint, mais au cas. */ //Log("", 0); //return 0; //return false; //} //