/*
* file com_central.c - server answers to broadcasts by clients
*
* $Id: com_central.c,v 1.4 2004/06/26 03:20:15 iskywalker Exp $
*
* Program XBLAST
* (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
* Added by Koen De Raedt for central support
*
* 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; or (at your option)
* any later version
*
* This program is distributed in the hope that it will be entertaining,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILTY 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 "com_central.h"
#include "com_browse.h"
#include "version.h"
#include "str_util.h"
#ifdef WMS
#include "timeval.h"
#endif
#include "ini_file.h"
/*
* local types
*/
#define MAX_GAMES 256
#define DEAD_GAME_TIME 30
typedef struct {
XBCommBrowse browse;
unsigned short port;
unsigned char serial;
char *addrBroadcast;
struct timeval tvSend;
} XBCommCentral;
typedef struct {
unsigned short port;
char game[48];
char host[32];
unsigned char version[3]; /* version numbers */
int gameID;
int numLives;
int numWins;
int frameRate;
time_t time;
} XBCentralGames;
XBCentralGames centralGames[MAX_GAMES];
XBBool isFree[MAX_GAMES];
XBBool isMess[MAX_GAMES];
int nextFreeSlot,usedSlots;
int
com_GetOpenGames()
{
return usedSlots;
}
void
Central_MakeGameTextFile()
{
FILE *f;
int i;
f=fopen("games.html","w");
fprintf(f,"
");
for(i=0;i| %s | ",centralGames[i].game);
} else {
fprintf(f,"| %s | %s:%d | %d | %d | %d | V%u.%u.%u |
",
centralGames[i].game,centralGames[i].host,centralGames[i].port,
centralGames[i].numLives,centralGames[i].numWins,centralGames[i].frameRate,
centralGames[i].version[0],centralGames[i].version[1],centralGames[i].version[2]);
}
/* tele.port = centralGames[i].port;
tele.version[0] = centralGames[i].version[0];
tele.version[1] = centralGames[i].version[1];
tele.version[2] = centralGames[i].version[2];
tele.numLives = centralGames[i].numLives;
tele.numWins = centralGames[i].numWins;
tele.frameRate = centralGames[i].frameRate;
strncpy (tele.game, centralGames[i].game, sizeof (tele.game));
strncpy (tele.host, centralGames[i].host, sizeof (tele.host));
Dbg_Out("Inform client of game: %s %s:%i\n", centralGames[i].game, centralGames[i].host, centralGames[i].port);
*/
}
}
fprintf(f,"
");
fclose(f);
}
void
Central_ClearOldGames()
{
int n=0,i;
time_t now;
now=time(NULL);
for(i=0;iDEAD_GAME_TIME) {
usedSlots--;
isFree[i]=XBTrue;
n++;
}
}
}
if(n>0) {Dbg_Out("%i dead game(s) removed\n",n);}
Central_MakeGameTextFile();
}
static void
HandleQuery (XBCommCentral *rComm, const XBBrowseTeleQuery *query, const char *host, unsigned short port)
{
XBBrowseTeleReply tele;
int i,n=0;
memset (&tele, 0, sizeof (tele));
/* build central */
tele.any.type = XBBT_Reply;
tele.any.serial = query->any.serial;
for(i=0;ibrowse, host, port, XBFalse, &tele.any);
n++;
//break;
}
}
/* --- */
Dbg_Out ("%i games send to client at %s:%hu\n", n,host, port);
} /* HandleQuery */
static void
HandleNewGame (XBCommCentral *rComm, const XBBrowseTeleNewGame *query, const char *host, unsigned short port)
{
XBBrowseTeleNewGameOK tele;
int i,j;
tele.any.type = XBBT_NewGameOK;
tele.any.serial = query->any.serial;
i=query->gameID;
if(((i >=0) && isFree[i]) || i < 0) {
for(i=nextFreeSlot, j=0; j<=MAX_GAMES; i=(i+1)%MAX_GAMES, j++) {
if(isFree[i] && !isMess[i]) {
usedSlots++;
nextFreeSlot=i+1;
break;
}
}
if(j==MAX_GAMES) { i=-1; }
}
if(i>=0) {
isFree[i]=XBFalse;
centralGames[i].port=query->port;
centralGames[i].version[0]=query->version[0];
centralGames[i].version[1]=query->version[1];
centralGames[i].version[2]=query->version[2];
centralGames[i].numLives=query->numLives;
centralGames[i].numWins=query->numWins;
centralGames[i].frameRate=query->frameRate;
centralGames[i].time=time(NULL);
sprintf(centralGames[i].host,"%s",host);
sprintf(centralGames[i].game,"%s",query->game);
Dbg_Out("New game %s at %s:%i\n", centralGames[i].game, centralGames[i].host, centralGames[i].port);
} else {
i=-1;
Dbg_Out(" *** Games limit reached ***\n");
}
tele.gameID=i;
Browse_Send (&rComm->browse, host, port, XBFalse, &tele.any);
/* --- */
Dbg_Out ("game id %i send to %s:%hu\n", i, host, port);
Central_MakeGameTextFile();
}
/*
* Server starts or closes the game
*/
static void
HandleCloseGame (XBCommCentral *rComm, const XBBrowseTeleNewGameOK *query, const char *host, unsigned short port)
{
int i=query->gameID;
Dbg_Out("Game closed by server, game was %s\n", isFree[i] ? "not known" : "known");
if(!isFree[i]) {
usedSlots--;
if(usedSlots<0) usedSlots=0;
isFree[i]=XBTrue;
}
}
/*
* receive central data
*/
static void
ReceiveCentral (XBCommBrowse *bComm, const XBBrowseTele *tele, const char *host, unsigned short port)
{
assert (NULL != bComm);
assert (NULL != tele);
assert (NULL != host);
switch (tele->type) {
case XBBT_Query : HandleQuery ((XBCommCentral *) bComm, &tele->query, host, port); break;
case XBBT_NewGame: HandleNewGame ((XBCommCentral *) bComm, &tele->newGame, host, port); break;
case XBBT_NewGameOK: HandleCloseGame ((XBCommCentral *) bComm, &tele->newGameOK, host, port); break;
default: break;
}
} /* ReceiveCentral */
/*
*
*/
static XBCommResult
DeleteCentral (XBComm *comm)
{
XBCommCentral *rComm = (XBCommCentral *) comm;
/* */
assert (NULL != rComm);
Browse_Finish (&rComm->browse);
free (rComm);
rComm = NULL;
return XCR_OK;
} /* DeleteCentral */
/*
* create udp socket waiting for clients' queries
*/
XBComm*
Central_CreateComm (unsigned short port)
{
XBSocket *pSocket;
XBCommCentral *rComm;
int i;
/* DAYMESSAGE */
char s[1024],q[256];
int l[16],n;
/* DAYMESSAGE */
/* create socket */
pSocket = Net_BindUdp (NULL, port);
if (NULL == pSocket) {
return NULL;
}
/* create communication data structure */
rComm = calloc (1, sizeof (*rComm));
assert (NULL != rComm);
for(i=0;ibrowse, COMM_NewGameOK, pSocket, ReceiveCentral, DeleteCentral);
/* that's all ? */
/* DAYMESSAGE */
for(i=0;ibrowse.comm;
} /* Central_CreateComm */
/*
* end of file com_central.c
*/