#include #include #include #include #include #include #ifndef __WIN32 # include # include # include #else # include # include #endif #include #include #include #include "main.h" #include "list.h" #include "tux.h" #include "idManager.h" #include "myTimer.h" #include "arena.h" #include "item.h" #include "shot.h" #include "arenaFile.h" #include "proto.h" #include "modules.h" #include "net_multiplayer.h" #include "publicServer.h" #include "serverConfigFile.h" #include "highScore.h" #include "log.h" #include "dns.h" static arena_t *arena; static bool_t isSignalEnd; static arenaFile_t *choice_arenaFile; extern int errno; #define __PACKED__ __attribute__ ((__packed__)) void countRoundInc() { } char *getSetting(char *env, char *param, char *default_val) { return getParamElse(param, getServerConfigFileValue(env, default_val)); } static int registerPublicServer() { #ifndef __WIN32 int s; #else SOCKET s; #endif /* TODO: dodelat TCP makro */ struct sockaddr_in server; char *master_server_ip; master_server_ip = getIPFormDNS(NET_MASTER_SERVER_DOMAIN); //printf("master_server_ip = %s\n", master_server_ip); if (master_server_ip == NULL) // master server is down { return -1; } server.sin_family = AF_INET; server.sin_port = htons(NET_MASTER_PORT); server.sin_addr.s_addr = inet_addr(master_server_ip); free(master_server_ip); if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return 0; } /* Set to nonblocking socket mode */ #ifndef __WIN32__ int oldFlag; oldFlag = fcntl(s, F_GETFL, 0); if (fcntl(s, F_SETFL, oldFlag | O_NONBLOCK) == -1) { return -1; } #else unsigned long arg = 1; // Operation is FIONBIO. Parameter is pointer on non-zero number. if (ioctlsocket(s, FIONBIO, &arg) == SOCKET_ERROR) { WSACleanup(); return -1; } #endif if (connect(s, (struct sockaddr *) &server, sizeof(server)) == -1) { #ifndef __WIN32__ if (errno != EINPROGRESS) return -1; #else if (WSAGetLastError() != WSAEWOULDBLOCK) { WSACleanup(); return -1; } #endif } struct timeval tv; fd_set myset; FD_ZERO(&myset); FD_SET(s, &myset); tv.tv_sec = 3; tv.tv_usec = 0; int ret = select(s + 1, NULL, &myset, NULL, &tv); if (ret == -1) return -1; if (ret == 0) return -1; FD_ZERO(&myset); FD_SET(s, &myset); tv.tv_sec = 1; tv.tv_usec = 0; ret = select(s + 1, NULL, &myset, NULL, &tv); if (ret == -1) return -1; if (ret == 0) return -1; typedef struct { unsigned char cmd; unsigned port; unsigned ip; } __PACKED__ register_head; char *str = (char *) malloc(sizeof(register_head)); register_head *head = (register_head *) str; head->cmd = 'p'; head->port = atoi(getSetting("PORT4", "--port4", "6800")); head->ip = 0; // TODO /* send request for server list */ int r = send(s, str, 9, 0); free(str); if (r == -1) { #ifndef __WIN32 close(s); #else closesocket(s); #endif return -1; } #ifndef __WIN32 close(s); #else closesocket(s); #endif return 0; } static int initPublicServerNetwork() { char ip4[STR_IP_SIZE]; char ip6[STR_IP_SIZE]; char *p_ip4, *p_ip6; int port4; int port6; int ret; ret = -1; strcpy(ip4, getSetting("IP4", "--ip4", "none")); strcpy(ip6, getSetting("IP6", "--ip6", "none")); p_ip4 = ip4; if (strcmp(ip4, "none") == 0) { p_ip4 = NULL; } p_ip6 = ip6; if (strcmp(ip6, "none") == 0) { p_ip6 = NULL; } port4 = atoi(getSetting("PORT4", "--port4", "6800")); port6 = atoi(getSetting("PORT6", "--port6", "6800")); //ret = initNetMulitplayerPublicServer(p_ip4, port4, p_ip6, port6); ret = initNetMuliplayerForGameServer(p_ip4, port4, p_ip6, port6); return ret; } static void loadArena() { choice_arenaFile = getArenaFileFormNetName(getSetting("ARENA", "--arena", "FAGN")); if( choice_arenaFile == NULL ) { fprintf(stderr, _("I dont load arena %s!\n"), getSetting("ARENA", "--arena", "FAGN")); exit(-1); } arena = getArena(choice_arenaFile); setCurrentArena(arena); } int initPublicServer() { int ret; int i; initListID(); initModule(); initArenaFile(); initTux(); initItem(); initShot(); initServerConfigFile(); ret = initLog(getSetting("LOG_FILE", "--log-file", "/tmp/tuxanci-server.log")); if (ret < 0) { fprintf(stderr, _("I was unable to open config file!\n")); return -1; } initHighScore(getSetting("SCORE_FILE", "--score-file", "/tmp/highscore.txt")); loadArena(); for (i = 0; i < atoi(getSetting("ITEM", "--item", "10")); i++) { addNewItem(arena->spaceItem, ID_UNKNOWN); } isSignalEnd = FALSE; ret = initPublicServerNetwork(); if (ret < 0) { printf(_("Unable to initialize network socket!\n")); return -1; } setServerMaxClients(atoi (getSetting("MAX_CLIENTS", "--max-clients", "32"))); if (registerPublicServer() < 0) { printf(_("Unable to contact MasterServer!)\n")); } return 0; } arenaFile_t *getChoiceArena() { return choice_arenaFile; } void eventPublicServer() { static my_time_t lastActive = 0; my_time_t interval; eventNetMultiplayer(); if (isSignalEnd == TRUE) { quitPublicServer(); } if (lastActive == 0) { lastActive = getMyTime(); } interval = getMyTime() - lastActive; if (interval < 50) { return; } //printf("interval = %d\n", interval); lastActive = getMyTime(); eventArena(arena); } void my_handler_quit(int n) { DEBUG_MSG("my_handler_quit\n"); isSignalEnd = TRUE; } void quitPublicServer() { DEBUG_MSG(_("Quitting public server\n")); quitNetMultiplayer(); destroyArena(arena); quitTux(); quitItem(); quitShot(); quitArenaFile(); quitServerConfigFile(); quitModule(); quitListID(); quitHighScore(); quitLog(); exit(0); } int startPublicServer() { #ifndef __WIN32__ signal(SIGINT, my_handler_quit); signal(SIGTERM, my_handler_quit); signal(SIGQUIT, my_handler_quit); #endif if (initPublicServer() < 0) { quitPublicServer(); return -1; } while (1) { eventPublicServer(); } return 0; }