You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
6.6 KiB
299 lines
6.6 KiB
/* $Id: ogcache-client.c,v 1.7 2005/03/28 16:26:40 stpohle Exp $
|
|
* OpenGameCache-Client: this file will hold the protocol for the gameserver communication
|
|
*/
|
|
|
|
#include "basic.h"
|
|
#include "bomberclone.h"
|
|
#include "udp.h"
|
|
#include "ogcache-client.h"
|
|
|
|
int ogc_sock = -1;
|
|
struct game_entry ogc_array[MAX_OGC_ENTRYS];
|
|
char ogc_host[LEN_OGCHOST+1];
|
|
char ogc_port[LEN_OGCPORT+1];
|
|
char ogc_game[LEN_GAME+1];
|
|
int ogc_ai_family;
|
|
struct _sockaddr ogc_addr;
|
|
int ogc_browsing = 0;
|
|
int ogc_lasttimeout = 0;
|
|
|
|
/* fill out the whole gameentry */
|
|
static void fill_gameentry (char *pos, struct game_entry *ge) {
|
|
char *pos_next; /* pointer to the next seperator */
|
|
int i = 0;
|
|
|
|
while (pos != NULL)
|
|
{
|
|
/* search and test the next seperator */
|
|
pos_next = strchr (pos, '\t');
|
|
if (pos_next == NULL)
|
|
pos_next = strchr (pos, '\n');
|
|
/* if we found a return delete it..
|
|
* if we found the tab delete it */
|
|
if (pos_next != NULL)
|
|
{
|
|
if (pos_next[0] == '\n')
|
|
{ /* RETURN found */
|
|
pos_next[0] = '\0';
|
|
pos_next = NULL;
|
|
}
|
|
else
|
|
pos_next[0] = '\0';
|
|
}
|
|
|
|
/* fill the struct with our data */
|
|
switch (i)
|
|
{
|
|
case (0): /* serial */
|
|
ge->serial = atoi (pos);
|
|
break;
|
|
case (1): /* host */
|
|
strncpy (ge->host, pos, LEN_OGCHOST);
|
|
break;
|
|
case (2): /* port */
|
|
strncpy (ge->port, pos, LEN_OGCPORT);
|
|
break;
|
|
case (3): /* game */
|
|
strncpy (ge->game, pos, LEN_GAME);
|
|
break;
|
|
case (4): /* version */
|
|
strncpy (ge->version, pos, LEN_VERSION);
|
|
break;
|
|
case (5): /* nettype */
|
|
if (strcmp (pos, "IPv6") == 0)
|
|
ge->ai_family = PF_INET6;
|
|
else
|
|
ge->ai_family = PF_INET;
|
|
break;
|
|
case (6): /* netname */
|
|
strncpy (ge->gamename, pos, LEN_GAMENAME);
|
|
break;
|
|
case (7): /* state */
|
|
strncpy (ge->status, pos, LEN_STATUS);
|
|
break;
|
|
case (8): /* curplayers */
|
|
ge->curplayers = atoi (pos);
|
|
break;
|
|
case (9): /* maxplayers */
|
|
ge->maxplayers = atoi (pos);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
/* increase i for the next entry */
|
|
i++;
|
|
if (pos_next != NULL)
|
|
pos = pos_next + 1;
|
|
else
|
|
pos = NULL;
|
|
}
|
|
|
|
d_printf ("fill_gameentry [Serial:%d, Addr:%s:%s, Game:%s, Gamename:%s\n", ge->serial, ge->host, ge->port, ge->game, ge->gamename);
|
|
};
|
|
|
|
|
|
/* add a game to the list or update one */
|
|
static int ogc_listadd (char *data) {
|
|
struct game_entry ge;
|
|
int i;
|
|
|
|
/* fill out the entry and check if there was a problem */
|
|
fill_gameentry (data, &ge);
|
|
if (ge.serial == -1) return 0;
|
|
|
|
for (i = 0; (i < MAX_OGC_ENTRYS && ogc_array[i].serial != -1 && ogc_array[i].serial != ge.serial); i++);
|
|
|
|
if (i < MAX_OGC_ENTRYS && ogc_array[i].serial == ge.serial)
|
|
ogc_array[i] = ge;
|
|
else if (i < MAX_OGC_ENTRYS && ogc_array[i].serial == -1)
|
|
ogc_array[i] = ge;
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
/* delete the game from the list */
|
|
static int ogc_listdel (char *data) {
|
|
int i, serial, res = 0;
|
|
|
|
serial = atoi (data);
|
|
|
|
for (i = 0; i < MAX_OGC_ENTRYS; i++)
|
|
if (ogc_array[i].serial == serial) {
|
|
ogc_array[i].serial = -1;
|
|
res = 1;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
|
|
/* work with the incoming packet */
|
|
static int ogc_do_inpacket (char *in, int len, struct _sockaddr *addr) {
|
|
char *param_start = strchr (in, ':');
|
|
int i = 0;
|
|
|
|
/* set param_start at the place where the first parameter is
|
|
* and if there is a : delete this one */
|
|
if (param_start == NULL) {
|
|
if ((param_start = strchr (in, '\n')) != NULL) {
|
|
param_start[0] = '\0';
|
|
param_start = NULL;
|
|
}
|
|
}
|
|
else {
|
|
param_start[0] = '\0';
|
|
param_start++;
|
|
}
|
|
|
|
/*
|
|
* work with the incoming data
|
|
*/
|
|
if (strcmp (in, "ENTRY") == 0)
|
|
i = ogc_listadd (param_start);
|
|
|
|
else if (strcmp (in, "DELENTRY") == 0)
|
|
i = ogc_listdel (param_start);
|
|
|
|
return i;
|
|
};
|
|
|
|
|
|
|
|
/* start a new listen server to get the list */
|
|
int ogc_init (char *localport, char *server, char *port, char *game, int ai_family) {
|
|
int i;
|
|
|
|
ogc_sock = -1;
|
|
|
|
ogc_sock = udp_server (localport, ai_family);
|
|
d_printf ("ogc_init (Localport: %s, Server %s:%s Game %s socket=%d)\n", localport, server, port, game, ogc_sock);
|
|
if (ogc_sock <= 0)
|
|
return 0;
|
|
|
|
strncpy (ogc_host, server, LEN_OGCHOST);
|
|
strncpy (ogc_port, port, LEN_OGCPORT);
|
|
strncpy (ogc_game, game, LEN_GAME);
|
|
ogc_ai_family = ai_family;
|
|
|
|
d_printf ("ogc_host:%s ogc_port:%s ogc_game:%s ogc_ai_family:%d\n", ogc_host, ogc_port, ogc_game, ogc_ai_family);
|
|
if (dns_filladdr (ogc_host, LEN_OGCHOST, ogc_port, LEN_OGCPORT, ogc_ai_family, &ogc_addr) < 0) {
|
|
udp_close (ogc_sock);
|
|
ogc_sock = -1;
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < MAX_OGC_ENTRYS; i++)
|
|
ogc_array[i].serial = -1;
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
|
|
/* send the status of the curent game to the game cache */
|
|
int ogc_sendgamestatus (int sock, char *game, char *version, char *gamename,
|
|
int curplayers, int maxplayers, char *status) {
|
|
char data[BUF_SIZE];
|
|
|
|
if (sock <= 0 || ogc_sock <= 0) return 0;
|
|
sprintf (data, "GAME:%s\t%s\t%s", game, version, gamename);
|
|
if (ogc_ai_family == PF_INET)
|
|
sprintf (data, "%s\tIPv4", data);
|
|
else
|
|
sprintf (data, "%s\tIPv6", data);
|
|
sprintf (data, "%s\t%d\t%d\t%s", data, curplayers, maxplayers, status);
|
|
|
|
udp_send (sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
/* send to the gamecache that this game has quit */
|
|
int ogc_sendgamequit (int sock) {
|
|
char data[BUF_SIZE];
|
|
|
|
if (sock <= 0 || ogc_sock <= 0) return 0;
|
|
|
|
sprintf (data, "QUIT:");
|
|
udp_send (sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
/* send to the gamecache that this browser does not anymore exist */
|
|
void ogc_shutdown () {
|
|
if (ogc_sock <= 0)
|
|
return;
|
|
|
|
d_printf ("ogc_shutdown\n");
|
|
if (ogc_browsing)
|
|
ogc_browsestop ();
|
|
udp_close (ogc_sock);
|
|
|
|
ogc_sock = -1;
|
|
};
|
|
|
|
|
|
|
|
/* check the socket for incoming data and work
|
|
* with them if there are any */
|
|
int ogc_loop () {
|
|
int len, i = 0;
|
|
char in[BUF_SIZE];
|
|
struct _sockaddr inaddr;
|
|
|
|
if (ogc_sock <= 0)
|
|
return -1;
|
|
|
|
len = udp_get (ogc_sock, in, BUF_SIZE, &inaddr, ogc_ai_family);
|
|
|
|
if (len > 0) { /* we have got something */
|
|
d_printf ("ogc_got: %s\n", in);
|
|
i = ogc_do_inpacket (in, len, &inaddr);
|
|
}
|
|
|
|
if (ogc_browsing && (time (NULL) - ogc_lasttimeout) > 30)
|
|
ogc_browsestart ();
|
|
|
|
return i;
|
|
};
|
|
|
|
|
|
/* send to the gamecache that we want
|
|
* to browse through the open games */
|
|
void ogc_browsestart () {
|
|
char data[BUF_SIZE];
|
|
|
|
d_printf ("ogc_browsestart\n");
|
|
|
|
if (ogc_sock <= 0)
|
|
return;
|
|
|
|
sprintf (data, "LISTGAMES:%s", ogc_game);
|
|
|
|
udp_send (ogc_sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
|
ogc_browsing = 1;
|
|
|
|
ogc_lasttimeout = time (NULL);
|
|
};
|
|
|
|
|
|
/* send the gamecache that we don't want to watch the list no more */
|
|
void ogc_browsestop () {
|
|
char data[BUF_SIZE];
|
|
|
|
d_printf ("ogc_browsestop\n");
|
|
|
|
ogc_browsing = 0;
|
|
if (ogc_sock <= 0)
|
|
return;
|
|
|
|
sprintf (data, "LISTQUIT:");
|
|
|
|
udp_send (ogc_sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
|
};
|