hlswmaster/src/serverlist.c

141 lines
4.3 KiB
C

/***************************************************************************
* Copyright (C) 03/2005 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>
#include "hlswmaster.h"
#include "plugin.h"
#include "list.h"
#define DEBUG 1
LIST_HEAD(server_list);
/* sichert die server liste */
static pthread_mutex_t server_list_lock = PTHREAD_MUTEX_INITIALIZER;
/**
* server_cmp()
* LIST_FIND helper
*
* @param struct game_server *a
* @param struct game_server *b
* @return true wenn es sich um den selben server handelt
*/
static inline int server_cmp(const struct game_server *a, struct game_server *b) {
return (a->gameid == b->gameid && a->ip == b->ip &&
a->port1 == b->port1 && a->port2 == b->port2);
}
/**
* server_add()
* fuegt der internen serverliste einen server hinzu
* wenn dieser server schon in der liste vorhanden ist, wird nur
* die modtime angepasst
*
* @param unsigned int gameid
* @param struct in_addr ip
* @param u_int16_t port1
* @param u_int16_t port2
* @return false bei fehler
*/
int server_add(u_int16_t gameid, u_int32_t ip, u_int16_t port1, u_int16_t port2) {
struct game_server server, *nserver;
server.gameid = gameid;
server.ip = ip;
server.port1 = port1;
server.port2 = port2;
pthread_mutex_lock(&server_list_lock);
/* diesen server in der liste suchen */
nserver = LIST_FIND(&server_list, server_cmp, struct game_server *, &server);
if (!nserver) {
/* neuen eintrag anlegen */
if (!(nserver = malloc(sizeof(struct game_server)))) {
pthread_mutex_unlock(&server_list_lock);
return 0;
}
#ifdef DEBUG
{
struct in_addr tmp;
tmp.s_addr = server.ip;
printf("server_add_new: gameid=%2d ip=%15s port1=%5d port2=%5d\n",
server.gameid, inet_ntoa(tmp), server.port1, server.port2);
}
#endif
memcpy(nserver, &server, sizeof(struct game_server));
list_add_tail(&nserver->list, &server_list);
}
/* modtime anpassen */
nserver->modtime = time(NULL);
pthread_mutex_unlock(&server_list_lock);
return 1;
}
/**
* server_collector()
* loescht alte server aus der liste
* baut aus den verbleibenden die client_liste auf
*
* TODO: timeout und intervall als config parameter (config file?)
*/
void server_collector(void) {
struct game_server *server, *tmp;
unsigned long now, timeout = 60;
while (1) {
sleep(5);
now = time(NULL);
pthread_mutex_lock(&server_list_lock);
list_for_each_entry_safe(server, tmp, &server_list, list) {
if ((server->modtime + timeout) < now) {
#ifdef DEBUG
{
struct in_addr tmp2;
tmp2.s_addr = server->ip;
printf("server timeout: gameid=%2d ip=%15s port1=%5d port2=%5d\n",
server->gameid, inet_ntoa(tmp2), server->port1, server->port2);
}
#endif
list_del(&server->list);
free(server);
continue;
}
client_pkt_add(server);
}
pthread_mutex_unlock(&server_list_lock);
client_pkt_commit();
}
}