#include #include #include #include #include #include #ifndef __WIN32__ #include #include #include #else /* __WIN32__ */ #include #include #endif /* __WIN32__ */ #include #include #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 world_inc_round() { } char *public_server_get_setting(char *env, char *param, char *default_val) { return getParamElse(param, server_configFile_get_value(env, default_val)); } /** * Send the process to the background */ static void daemonize() { #ifndef __WIN32__ pid_t pid, sid; FILE *pid_file; /* are we already a daemon? */ if (getppid() == 1) { return; } /* fork off the parent process */ pid = fork(); if (pid < 0) { exit(1); /* if we got a good PID, then we can exit the parent process */ } else if (pid > 0) { exit(0); } /* ↓ at this point we are executing as the child process ↓ */ /* change the file mode mask */ umask(027); /* create a new SID for the child process */ sid = setsid(); if (sid < 0) { exit(1); } /* Change the current working directory. This prevents the current * directory from being locked; hence not being able to remove it. * /tmp seems to be the best place where to create temporary files ;c) */ if (chdir("/tmp") < 0) { exit(1); } /* say loudly what PID we got */ printf("The Tuxanci game server started with the PID %d\n", sid); /* write the PID to the PID file */ pid_file = fopen(public_server_get_setting("PID_FILE", "--pid-file", "/var/run/tuxanci-server.pid"), "w"); fprintf(pid_file, "%d\n", sid); fclose(pid_file); /* redirect standard files to /dev/null */ freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); #endif /* __WIN32__ */ } static int public_server_register() { #ifndef __WIN32__ int s; #else /* __WIN32__ */ SOCKET s; #endif /* __WIN32__ */ struct sockaddr_in server; char *master_server_ip; master_server_ip = dns_resolv(NET_MASTER_SERVER_DOMAIN); if (master_server_ip == NULL) { warning("Did not obtained IP of the MasterServer"); 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, IPPROTO_TCP)) < 0) { warning("Unable to open socket for connection to MasterServer"); return -1; } /* connect to MasterServer */ if (connect(s, (struct sockaddr *) &server, sizeof(server)) < 0) { warning("Unable to estabilish connection to MasterServer"); return -1; } typedef struct { unsigned char cmd; unsigned port; unsigned ip; } __PACKED__ register_head; register_head *head = (register_head *) malloc(sizeof(register_head)); head->cmd = 'p'; head->port = atoi(public_server_get_setting("PORT4", "--port4", "6800")); head->ip = 0; /* TODO */ /* send request for server list */ int r = send(s, head, sizeof(register_head), 0); free(head); #ifndef __WIN32__ close(s); #else /* __WIN32__ */ closesocket(s); #endif /* __WIN32__ */ if (r == -1) { return -1; } else { return 0; } } static int public_server_initNetwork() { char ip4[STR_IP_SIZE]; char ip6[STR_IP_SIZE]; char *p_ip4, *p_ip6; int port; int ret; ret = -1; strcpy(ip4, public_server_get_setting("IP4", "--ip4", "none")); strcpy(ip6, public_server_get_setting("IP6", "--ip6", "none")); p_ip4 = ip4; if (strcmp(ip4, "none") == 0 || strcmp(ip6, "::") == 0) { p_ip4 = NULL; } p_ip6 = ip6; if (strcmp(ip6, "none") == 0) { p_ip6 = NULL; } port = atoi(public_server_get_setting("PORT", "--port", "6800")); ret = net_multiplayer_init_for_game_server(p_ip4, p_ip6, port); return ret; } static void load_arena() { choice_arenaFile = arena_file_get_file_format_net_name(public_server_get_setting("ARENA", "--arena", "FAGN")); if (choice_arenaFile == NULL) { error("Unable to load arena [%s]", public_server_get_setting("ARENA", "--arena", "FAGN")); /* TODO: Why not to log it? */ exit(-1); } arena = arena_file_get_arena(choice_arenaFile); arena_set_current(arena); } int public_server_init() { int ret; int i; id_init_list(); module_init(); arena_file_init(); tux_init(); item_init(); shot_init(); server_configFile_init(); ret = log_init(public_server_get_setting("LOG_FILE", "--log-file", "/tmp/tuxanci-server.log")); if (ret < 0) { /* Error message has been already printed */ return -1; } high_score_init(public_server_get_setting("SCORE_FILE", "--score-file", "/tmp/highscore.txt")); load_arena(); for (i = 0; i < atoi(public_server_get_setting("ITEM", "--item", "10")); i++) { item_add_new_item(arena->spaceItem, ID_UNKNOWN); } isSignalEnd = FALSE; ret = public_server_initNetwork(); if (ret < 0) { error("Unable to initialize network socket"); /* TODO: Why not to log it? */ return -1; } server_set_max_clients(atoi(public_server_get_setting("MAX_CLIENTS", "--max-clients", "32"))); if (atoi(public_server_get_setting("LAN_ONLY", "--lan-only", "0")) == 0) { if (public_server_register() < 0) { error("Unable to contact MasterServer"); /* TODO: Why not to log it? */ } } else { debug("Starting LAN-only server"); } return 0; } arenaFile_t *choice_arena_get() { return choice_arenaFile; } void public_server_event() { static my_time_t lastActive = 0; my_time_t interval; net_multiplayer_event(); if (isSignalEnd == TRUE) { public_server_quit(); } if (lastActive == 0) { lastActive = timer_get_current_time(); } interval = timer_get_current_time() - lastActive; if (interval < 50) { return; } lastActive = timer_get_current_time(); arena_event(arena); } void my_handler_quit(int n) { debug("Received signal %d", n); /* TODO: Why not to log it? */ isSignalEnd = TRUE; public_server_quit(); } void public_server_quit() { debug("Shutting down the Tuxanci game server"); /* TODO: Why not to log it? */ net_multiplayer_quit(); arena_destroy(arena); tux_quit(); item_quiy(); shot_quit(); /* remove the PID file */ remove(public_server_get_setting("PID_FILE", "--pid-file", "/var/run/tuxanci-server.pid")); arena_file_quit(); server_configFile_quit(); module_quit(); id_quit_list(); high_score_quit(); log_quit(); exit(0); } int public_server_start() { #ifndef __WIN32__ signal(SIGINT, my_handler_quit); signal(SIGTERM, my_handler_quit); signal(SIGQUIT, my_handler_quit); #endif /* __WIN32__ */ if (public_server_init() < 0) { public_server_quit(); return -1; } char *s = public_server_get_setting("DAEMON", "--daemon", "0"); if (atoi(s)) { daemonize(); } for (;;) { public_server_event(); } return 0; }