delete metaserver
This commit is contained in:
parent
05f6b251f7
commit
a00256e6da
11 changed files with 0 additions and 2225 deletions
|
@ -1,11 +0,0 @@
|
|||
CXXFLAGS = -I../include -I/usr/include/SDL -DHAVE_STRCASESTR -W -Wall -O2 -Wno-write-strings
|
||||
LDFLAGS = -lSDL -lsqlite3
|
||||
|
||||
metaserver: cmd.o db.o games.o netdriver.o main.o lowlevel.o
|
||||
$(CXX) $^ $(LDFLAGS) -o $@
|
||||
|
||||
lowlevel.o: ../network/lowlevel.cpp
|
||||
$(CXX) -c $^ $(CXXFLAGS) -o $@
|
||||
|
||||
clean:
|
||||
$(RM) *.o metaserver
|
|
@ -1,31 +0,0 @@
|
|||
## _________ __ __
|
||||
## / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
## \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
## / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ \
|
||||
## /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
## \/ \/ \//_____/ \/
|
||||
## ______________________ ______________________
|
||||
## T H E W A R B E G I N S
|
||||
## Stratagus - A free fantasy real time strategy game engine
|
||||
##
|
||||
## Module.make - Module Makefile (included from Makefile).
|
||||
##
|
||||
## (c) Copyright 2005 by The Stratagus Team
|
||||
##
|
||||
## 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; only version 2 of the License.
|
||||
##
|
||||
## 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
|
||||
|
||||
MODULE = src/metaserver
|
||||
MSRC = cmd.cpp db.cpp games.cpp main.cpp netdriver.cpp
|
||||
|
||||
METASERVER_SRC += $(addprefix $(MODULE)/,$(MSRC))
|
|
@ -1,617 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name cmd.cpp - Client/Server Command Interpreter. */
|
||||
//
|
||||
// (c) Copyright 2005 by Edward Haase and Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "cmd.h"
|
||||
#include "netdriver.h"
|
||||
#include "db.h"
|
||||
#include "games.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#define GetNextArg(buf, arg) \
|
||||
do { \
|
||||
if (*buf == '\"') { \
|
||||
*arg = ++buf; \
|
||||
while (*buf != '\"' && *buf) ++buf; \
|
||||
if (*buf != '\"') return 1; \
|
||||
*buf++ = '\0'; \
|
||||
if (**arg == '\0') return 1; \
|
||||
if (*buf != ' ') return 1; \
|
||||
} else { \
|
||||
*arg = buf; \
|
||||
while (*buf != ' ' && *buf) ++buf; \
|
||||
if (!*buf) return 1; \
|
||||
} \
|
||||
*buf++ = '\0'; \
|
||||
} while (0)
|
||||
|
||||
#define GetLastArg(buf, arg) \
|
||||
do { \
|
||||
if (*buf == '\"') { \
|
||||
*arg = ++buf; \
|
||||
while (*buf != '\"' && *buf) ++buf; \
|
||||
if (*buf != '\"') return 1; \
|
||||
*buf++ = '\0'; \
|
||||
if (**arg == '\0') return 1; \
|
||||
if (*buf != ' ' && *buf) return 1; \
|
||||
} else { \
|
||||
*arg = buf; \
|
||||
while (*buf != ' ' && *buf) ++buf; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define GetNextAndOptionalArg(buf, arg1, arg2) \
|
||||
do { \
|
||||
if (*buf == '\"') { \
|
||||
*arg1 = ++buf; \
|
||||
while (*buf != '\"' && *buf) ++buf; \
|
||||
if (*buf != '\"') return 1; \
|
||||
*buf++ = '\0'; \
|
||||
if (**arg1 == '\0') return 1; \
|
||||
if (*buf != ' ' && *buf) return 1; \
|
||||
} else { \
|
||||
*arg1 = buf; \
|
||||
while (*buf != ' ' && *buf) ++buf; \
|
||||
} \
|
||||
if (*buf == ' ') *buf++ = '\0'; \
|
||||
\
|
||||
*arg2 = NULL; \
|
||||
while (*buf == ' ') ++buf; \
|
||||
if (!*buf) return 0; \
|
||||
\
|
||||
GetLastArg(buf, arg2); \
|
||||
} while (0)
|
||||
|
||||
#define SkipSpaces(buf) \
|
||||
do { \
|
||||
while (*buf == ' ') ++buf; \
|
||||
if (!*buf) return 1; \
|
||||
} while (0)
|
||||
|
||||
#define CheckExtraParameter(buf) \
|
||||
do { \
|
||||
if (*buf) { \
|
||||
while (*buf == ' ') ++buf; \
|
||||
if (*buf) return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int Parse1Arg(char *buf, char **arg1)
|
||||
{
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetLastArg(buf, arg1);
|
||||
CheckExtraParameter(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Parse1or2Args(char *buf, char **arg1, char **arg2)
|
||||
{
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextAndOptionalArg(buf, arg1, arg2);
|
||||
CheckExtraParameter(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Parse4Args(char *buf, char **arg1, char **arg2, char **arg3,
|
||||
char **arg4)
|
||||
{
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg1);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg2);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg3);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetLastArg(buf, arg4);
|
||||
CheckExtraParameter(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 // not used
|
||||
static int Parse5Args(char *buf, char **arg1, char **arg2, char **arg3,
|
||||
char **arg4, char **arg5)
|
||||
{
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg1);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg2);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg3);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg4);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetLastArg(buf, arg5);
|
||||
CheckExtraParameter(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int Parse5or6Args(char *buf, char **arg1, char **arg2, char **arg3,
|
||||
char **arg4, char **arg5, char **arg6)
|
||||
{
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg1);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg2);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg3);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextArg(buf, arg4);
|
||||
SkipSpaces(buf);
|
||||
|
||||
GetNextAndOptionalArg(buf, arg5, arg6);
|
||||
CheckExtraParameter(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse PING
|
||||
*/
|
||||
static void ParsePing(Session *session)
|
||||
{
|
||||
Send(session, "PING_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse USER
|
||||
*/
|
||||
static void ParseUser(Session *session, char *buf)
|
||||
{
|
||||
char *username;
|
||||
char *password;
|
||||
char *gamename;
|
||||
char *gamever;
|
||||
char pw[MAX_PASSWORD_LENGTH + 1];
|
||||
|
||||
if (Parse4Args(buf, &username, &password, &gamename, &gamever)) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(username) > MAX_USERNAME_LENGTH ||
|
||||
strlen(password) > MAX_PASSWORD_LENGTH ||
|
||||
strlen(gamename) > MAX_GAMENAME_LENGTH ||
|
||||
strlen(gamever) > MAX_VERSION_LENGTH) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DBFindUser(username, pw)) {
|
||||
DebugPrint("Username doesn't exist: %s\n" _C_ username);
|
||||
Send(session, "ERR_NOUSER\n");
|
||||
return;
|
||||
}
|
||||
if (strcmp(pw, password)) {
|
||||
DebugPrint("Bad password for user %s\n" _C_ username);
|
||||
Send(session, "ERR_BADPASSWORD\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("User logged in: %s\n" _C_ username);
|
||||
strcpy(session->UserData.Name, username);
|
||||
strcpy(session->UserData.GameName, gamename);
|
||||
strcpy(session->UserData.Version, gamever);
|
||||
session->UserData.LoggedIn = 1;
|
||||
DBUpdateLoginDate(username);
|
||||
Send(session, "USER_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse REGISTER
|
||||
*/
|
||||
static void ParseRegister(Session *session, char *buf)
|
||||
{
|
||||
char *username;
|
||||
char *password;
|
||||
char *gamename;
|
||||
char *gamever;
|
||||
char pw[MAX_PASSWORD_LENGTH + 1];
|
||||
|
||||
if (Parse4Args(buf, &username, &password, &gamename, &gamever)) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(username) > MAX_USERNAME_LENGTH ||
|
||||
strlen(password) > MAX_PASSWORD_LENGTH ||
|
||||
strlen(gamename) > MAX_GAMENAME_LENGTH ||
|
||||
strlen(gamever) > MAX_VERSION_LENGTH) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DBFindUser(username, pw)) {
|
||||
DebugPrint("Tried to register existing user: %s\n" _C_ username);
|
||||
Send(session, "ERR_USEREXISTS\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("New user registered: %s\n" _C_ username);
|
||||
session->UserData.LoggedIn = 1;
|
||||
strcpy(session->UserData.Name, username);
|
||||
strcpy(session->UserData.GameName, gamename);
|
||||
strcpy(session->UserData.Version, gamever);
|
||||
DBAddUser(username, password); // FIXME: if this fails?
|
||||
Send(session, "REGISTER_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse CREATEGAME
|
||||
*/
|
||||
static void ParseCreateGame(Session *session, char *buf)
|
||||
{
|
||||
char *description;
|
||||
char *map;
|
||||
char *players;
|
||||
char *ip;
|
||||
char *port;
|
||||
char *password;
|
||||
int players_int;
|
||||
int port_int;
|
||||
|
||||
|
||||
if (Parse5or6Args(buf, &description, &map, &players, &ip, &port, &password)) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
players_int = atoi(players);
|
||||
port_int = atoi(port);
|
||||
// FIXME: check ip
|
||||
if (strlen(description) > MAX_DESCRIPTION_LENGTH ||
|
||||
strlen(map) > MAX_MAP_LENGTH ||
|
||||
players_int < 1 || players_int > 16 ||
|
||||
port_int < 1 || port_int > 66535 ||
|
||||
(password && strlen(password) > MAX_GAME_PASSWORD_LENGTH)) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CreateGame(session, description, map, players, ip, port, password);
|
||||
|
||||
DebugPrint("%s created a game\n" _C_ session->UserData.Name);
|
||||
DBAddGame(session->Game->ID, description, map, players_int);
|
||||
Send(session, "CREATEGAME_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse CANCELGAME
|
||||
*/
|
||||
static void ParseCancelGame(Session *session, char *buf)
|
||||
{
|
||||
// No args
|
||||
while (*buf == ' ') ++buf;
|
||||
if (*buf) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (CancelGame(session)) {
|
||||
Send(session, "ERR_NOGAMECREATED\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("%s canceled a game\n" _C_ session->UserData.Name);
|
||||
Send(session, "CANCELGAME_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse STARTGAME
|
||||
*/
|
||||
static void ParseStartGame(Session *session, char *buf)
|
||||
{
|
||||
// No args
|
||||
while (*buf == ' ') ++buf;
|
||||
if (*buf) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (StartGame(session)) {
|
||||
Send(session, "ERR_NOGAMECREATED\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("%s started a game\n" _C_ session->UserData.Name);
|
||||
Send(session, "STARTGAME_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse LISTGAMES
|
||||
*/
|
||||
static void ParseListGames(Session *session, char *buf)
|
||||
{
|
||||
// No args
|
||||
while (*buf == ' ') ++buf;
|
||||
if (*buf) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ListGames(session);
|
||||
|
||||
Send(session, "LISTGAMES_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse JOINGAME
|
||||
*/
|
||||
static void ParseJoinGame(Session *session, char *buf)
|
||||
{
|
||||
char *id;
|
||||
char *password;
|
||||
int ret;
|
||||
unsigned long udphost;
|
||||
int udpport;
|
||||
|
||||
if (Parse1or2Args(buf, &id, &password)) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = JoinGame(session, atoi(id), password, &udphost, &udpport);
|
||||
if (ret == -1) {
|
||||
Send(session, "ERR_ALREADYINGAME\n");
|
||||
return;
|
||||
} else if (ret == -2) { // ID not found
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
} else if (ret == -3) {
|
||||
if (!password) {
|
||||
Send(session, "ERR_NEEDPASSWORD\n");
|
||||
} else {
|
||||
Send(session, "ERR_BADPASSWORD\n");
|
||||
}
|
||||
return;
|
||||
} else if (ret == -4) {
|
||||
Send(session, "ERR_GAMEFULL\n");
|
||||
return;
|
||||
} else if (ret == -5) {
|
||||
Send(session, "ERR_SERVERNOTREADY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char* reply = (char*)calloc(sizeof(char), strlen("JOINGAME_OK 255.255.255.255 66535\n") + 1);
|
||||
sprintf(reply, "JOINGAME_OK %d.%d.%d.%d %d\n", NIPQUAD(ntohl(UDPHost)), udpport);
|
||||
DebugPrint("%s joined game %d with %s\n" _C_ session->UserData.Name _C_ atoi(id) _C_ reply);
|
||||
Send(session, reply);
|
||||
free(reply);
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse PARTGAME
|
||||
*/
|
||||
static void ParsePartGame(Session *session, char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// No args
|
||||
while (*buf == ' ') ++buf;
|
||||
if (*buf) {
|
||||
Send(session, "ERR_BADPARAMETER\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = PartGame(session);
|
||||
if (ret == -1) {
|
||||
Send(session, "ERR_NOTINGAME\n");
|
||||
return;
|
||||
} else if (ret == -2) {
|
||||
Send(session, "ERR_GAMESTARTED\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("%s left a game\n" _C_ session->UserData.Name);
|
||||
Send(session, "PARTGAME_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse ENDGAME
|
||||
*/
|
||||
static void ParseEndGame(Session *session, char *buf)
|
||||
{
|
||||
char *result;
|
||||
|
||||
Parse1Arg(buf, &result);
|
||||
|
||||
Send(session, "ENDGAME_OK\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Parse STATS
|
||||
*/
|
||||
static void ParseStats(Session *session, char *buf)
|
||||
{
|
||||
char *result;
|
||||
int start_time = 0;
|
||||
char resultbuf[20] = {'\0'};
|
||||
|
||||
while (*buf == ' ') ++buf;
|
||||
if (*buf) {
|
||||
Parse1Arg(buf, &result);
|
||||
start_time = atoi(result);
|
||||
}
|
||||
|
||||
DebugPrint("%s requested stats\n" _C_ session->UserData.Name);
|
||||
char* reply = (char*)calloc(sizeof(char), strlen("GAMES SINCE 12345678901234567890: 12345678901234567890\n") + 1);
|
||||
DBStats(resultbuf, start_time);
|
||||
sprintf(reply, "GAMES SINCE %d: %s\n", start_time, resultbuf);
|
||||
Send(session, reply);
|
||||
Send(session, "STATS_OK\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse MSG
|
||||
*/
|
||||
static void ParseMsg(Session *session, char *buf)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** ParseBuffer: Handler client/server interaction.
|
||||
**
|
||||
** @param session Current session.
|
||||
*/
|
||||
static void ParseBuffer(Session *session)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (!session || session->Buffer[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
buf = session->Buffer;
|
||||
if (!strncmp(buf, "PING", 4)) {
|
||||
ParsePing(session);
|
||||
} else {
|
||||
if (!session->UserData.LoggedIn) {
|
||||
if (!strncmp(buf, "USER ", 5)) {
|
||||
ParseUser(session, buf + 5);
|
||||
} else if (!strncmp(buf, "REGISTER ", 9)) {
|
||||
ParseRegister(session, buf + 9);
|
||||
}
|
||||
} else {
|
||||
if (!strncmp(buf, "USER ", 5) || !strncmp(buf, "REGISTER ", 9)) {
|
||||
Send(session, "ERR_ALREADYLOGGEDIN\n");
|
||||
}
|
||||
}
|
||||
if (!strncmp(buf, "CREATEGAME ", 11)) {
|
||||
ParseCreateGame(session, buf + 11);
|
||||
} else if (!strcmp(buf, "CANCELGAME") || !strncmp(buf, "CANCELGAME ", 11)) {
|
||||
ParseCancelGame(session, buf + 10);
|
||||
} else if (!strcmp(buf, "STARTGAME") || !strncmp(buf, "STARTGAME ", 10)) {
|
||||
ParseStartGame(session, buf + 9);
|
||||
} else if (!strcmp(buf, "LISTGAMES") || !strncmp(buf, "LISTGAMES ", 10)) {
|
||||
ParseListGames(session, buf + 9);
|
||||
} else if (!strncmp(buf, "JOINGAME ", 9)) {
|
||||
ParseJoinGame(session, buf + 9);
|
||||
} else if (!strcmp(buf, "PARTGAME") || !strncmp(buf, "PARTGAME ", 9)) {
|
||||
ParsePartGame(session, buf + 8);
|
||||
} else if (!strncmp(buf, "ENDGAME ", 8)) {
|
||||
ParseEndGame(session, buf + 8);
|
||||
} else if (!strncmp(buf, "STATS ", 6)) {
|
||||
ParseStats(session, buf + 6);
|
||||
} else if (!strncmp(buf, "MSG ", 4)) {
|
||||
ParseMsg(session, buf + 4);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown command: %s\n", session->Buffer);
|
||||
Send(session, "ERR_BADCOMMAND\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse all session buffers
|
||||
*/
|
||||
int UpdateParser(void)
|
||||
{
|
||||
Session *session;
|
||||
int len;
|
||||
char *next;
|
||||
|
||||
if (!Pool || !Pool->First) {
|
||||
// No connections
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (session = Pool->First; session; session = session->Next) {
|
||||
// Confirm full message.
|
||||
while ((next = strpbrk(session->Buffer, "\r\n"))) {
|
||||
*next++ = '\0';
|
||||
if (*next == '\r' || *next == '\n') {
|
||||
++next;
|
||||
}
|
||||
|
||||
ParseBuffer(session);
|
||||
|
||||
// Remove parsed message
|
||||
len = next - session->Buffer;
|
||||
memmove(session->Buffer, next, sizeof(session->Buffer) - len);
|
||||
session->Buffer[sizeof(session->Buffer) - len] = '\0';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (strlen(UDPBuffer)) {
|
||||
// If this is a server, we'll note its external data. When clients join,
|
||||
// they'll receive this as part of the TCP response that they
|
||||
// successfully joined. This is a simplification of the full UDP hole
|
||||
// punching algorithm, which unneccessarily might go through the NAT
|
||||
// even for clients inside the same NAT. This will also not work if in
|
||||
// that case the NAT does not support hairpin translation. But we'll see
|
||||
// how common that is...
|
||||
char ip[128] = {'\0'};
|
||||
char port[128] = {'\0'};
|
||||
sscanf(UDPBuffer, "%s %s", (char*)&ip, (char*)&port);
|
||||
DebugPrint("Filling in UDP info for %s:%s\n" _C_ ip _C_ port);
|
||||
if (FillinUDPInfo(UDPHost, UDPPort, ip, port)) {
|
||||
fprintf(stderr, "Error filling in UDP info for %s:%s with %d.%d.%d.%d:%d",
|
||||
ip, port, NIPQUAD(ntohl(UDPHost)), UDPPort);
|
||||
}
|
||||
UDPBuffer[0] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@}
|
|
@ -1,43 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name cmd.h - Client/Server command interaction header. */
|
||||
//
|
||||
// (c) Copyright 2005 by Edward Haase
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef __CMD_H__
|
||||
#define __CMD_H__
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
extern int UpdateParser(void);
|
||||
|
||||
//@}
|
||||
|
||||
#endif // __CMD_H__
|
|
@ -1,303 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name db.cpp - Database routines. */
|
||||
//
|
||||
// (c) Copyright 2005 by Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "sqlite3.h"
|
||||
#include "games.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
static const char *dbfile = "metaserver.db";
|
||||
static sqlite3 *DB;
|
||||
|
||||
#define SQLCreatePlayersTable \
|
||||
"CREATE TABLE players (" \
|
||||
"username TEXT PRIMARY KEY," \
|
||||
"password TEXT," \
|
||||
"register_date INTEGER," \
|
||||
"last_login_date INTEGER" \
|
||||
");"
|
||||
|
||||
#define SQLCreateGamesTable \
|
||||
"CREATE TABLE games (" \
|
||||
"id INTEGER PRIMARY KEY," \
|
||||
"date INTEGER," \
|
||||
"gamename TEXT," \
|
||||
"mapname TEXT," \
|
||||
"slots INTEGER" \
|
||||
");"
|
||||
|
||||
#define SQLCreateGameDataTable \
|
||||
"CREATE TABLE game_data (" \
|
||||
"id INTEGER," \
|
||||
"username TEXT," \
|
||||
"result INTEGER," \
|
||||
"score INTEGER," \
|
||||
"units INTEGER," \
|
||||
"buildings INTEGER," \
|
||||
"res1 INTEGER, res2 INTEGER, res3 INTEGER, res4 INTEGER, res5 INTEGER, res6 INTEGER," \
|
||||
"res1_used INTEGER, res2_used INTEGER, res3_used INTEGER, res4_used INTEGER, res5_used INTEGER, res6_used INTEGER," \
|
||||
"kills INTEGER," \
|
||||
"razings INTEGER," \
|
||||
"gamecycle INTEGER," \
|
||||
"PRIMARY KEY (id, username));"
|
||||
|
||||
#define SQLCreateRankingsTable \
|
||||
"CREATE TABLE rankings (" \
|
||||
"username TEXT," \
|
||||
"gamename TEXT," \
|
||||
"ranking INTEGER," \
|
||||
"PRIMARY KEY (username, gamename)" \
|
||||
");"
|
||||
|
||||
#define SQLCreateMapsTable \
|
||||
"CREATE TABLE maps (" \
|
||||
"map_id INTEGER PRIMARY KEY," \
|
||||
"map_name TEXT," \
|
||||
"map_filename TEXT," \
|
||||
"map_uuid TEXT," \
|
||||
"map_size_x INTEGER," \
|
||||
"map_size_y INTEGER" \
|
||||
");"
|
||||
|
||||
#define SQLCreateTables \
|
||||
SQLCreatePlayersTable SQLCreateGamesTable SQLCreateGameDataTable \
|
||||
SQLCreateRankingsTable SQLCreateMapsTable
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
** Max id callback
|
||||
*/
|
||||
static int DBMaxIDCallback(void *password, int argc, char **argv, char **colname)
|
||||
{
|
||||
Assert(argc == 1);
|
||||
if (argv[0]) {
|
||||
GameID = atoi(argv[0]) + 1;
|
||||
}
|
||||
fprintf(stderr, "Current max game id is %d\n", GameID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize the database
|
||||
**
|
||||
** @return 0 for success, non-zero for failure
|
||||
*/
|
||||
int DBInit(void)
|
||||
{
|
||||
FILE *fd;
|
||||
int doinit;
|
||||
char *errmsg;
|
||||
|
||||
// Check if this is the first time running
|
||||
doinit = 0;
|
||||
if ((fd = fopen(dbfile, "rb"))) {
|
||||
fclose(fd);
|
||||
} else {
|
||||
doinit = 1;
|
||||
}
|
||||
|
||||
if (sqlite3_open(dbfile, &DB) != SQLITE_OK) {
|
||||
fprintf(stderr, "ERROR: sqlite3_open failed: %s\n", sqlite3_errmsg(DB));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (doinit) {
|
||||
errmsg = NULL;
|
||||
if (sqlite3_exec(DB, SQLCreateTables, NULL, NULL, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
errmsg = NULL;
|
||||
if (sqlite3_exec(DB, "SELECT MAX(id) FROM games;", DBMaxIDCallback, NULL, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Close the database
|
||||
*/
|
||||
void DBQuit(void)
|
||||
{
|
||||
sqlite3_close(DB);
|
||||
}
|
||||
|
||||
/**
|
||||
** Find user callback
|
||||
*/
|
||||
static int DBFindUserCallback(void *password, int argc, char **argv, char **colname)
|
||||
{
|
||||
Assert(argc == 1);
|
||||
strcpy((char *)password, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find a user and return the password
|
||||
**
|
||||
** @param username User name to find
|
||||
** @param password If the user is found the password will be returned here
|
||||
**
|
||||
** @return 1 if user is found, 0 otherwise
|
||||
*/
|
||||
int DBFindUser(char *username, char *password)
|
||||
{
|
||||
char buf[1024];
|
||||
char *errmsg;
|
||||
|
||||
password[0] = '\0';
|
||||
if (strchr(username, '\'')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf(buf, "SELECT password FROM players WHERE username = '%s';", username);
|
||||
if (sqlite3_exec(DB, buf, DBFindUserCallback, password, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (password[0]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Add a user
|
||||
**
|
||||
** @param username User name
|
||||
** @param password Password
|
||||
**
|
||||
** @return 0 for success, non-zero otherwise
|
||||
*/
|
||||
int DBAddUser(char *username, char *password)
|
||||
{
|
||||
char buf[1024];
|
||||
int t;
|
||||
char *errmsg;
|
||||
|
||||
t = (int)time(0);
|
||||
sprintf(buf, "INSERT INTO players VALUES('%s', '%s', %d, %d);",
|
||||
username, password, t, t);
|
||||
if (sqlite3_exec(DB, buf, NULL, NULL, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Log in a user
|
||||
**
|
||||
** @param username User name
|
||||
**
|
||||
** @return 0 for success, non-zero otherwise
|
||||
*/
|
||||
int DBUpdateLoginDate(char *username)
|
||||
{
|
||||
char buf[1024];
|
||||
int t;
|
||||
char *errmsg;
|
||||
|
||||
t = (int)time(0);
|
||||
sprintf(buf, "UPDATE players SET last_login_date = %d WHERE username = '%s'",
|
||||
t, username);
|
||||
if (sqlite3_exec(DB, buf, NULL, NULL, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DBAddGame(int id, char *description, char *mapname, int numplayers)
|
||||
{
|
||||
char buf[1024];
|
||||
int t;
|
||||
char *errmsg;
|
||||
|
||||
t = (int)time(0);
|
||||
sprintf(buf, "INSERT INTO games VALUES(%d, %d, '%s', '%s', %d);",
|
||||
id, t, description, mapname, numplayers);
|
||||
if (sqlite3_exec(DB, buf, NULL, NULL, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DBStatsCallback(void *resultbuf, int argc, char **argv, char **colname)
|
||||
{
|
||||
Assert(argc == 1);
|
||||
strcpy((char *)resultbuf, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int DBStats(char* resultbuf, int start_time)
|
||||
{
|
||||
char buf[1024];
|
||||
int t;
|
||||
char *errmsg;
|
||||
|
||||
t = (int)time(0);
|
||||
sprintf(buf, "SELECT COUNT(id) FROM games WHERE date > %d;", start_time);
|
||||
if (sqlite3_exec(DB, buf, DBStatsCallback, resultbuf, &errmsg) != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name db.h - Database routines. */
|
||||
//
|
||||
// (c) Copyright 2005 by Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef __DB_H__
|
||||
#define __DB_H__
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
extern int DBInit(void);
|
||||
extern void DBQuit(void);
|
||||
extern int DBFindUser(char *username, char *password);
|
||||
extern int DBAddUser(char *username, char *password);
|
||||
extern int DBUpdateLoginDate(char *username);
|
||||
extern int DBAddGame(int id, char *description, char *mapname, int numplayers);
|
||||
extern int DBStats(char *results, int resultlen);
|
||||
|
||||
//@}
|
||||
|
||||
#endif // __DB_H__
|
|
@ -1,265 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name games.cpp - Basic games query process. */
|
||||
//
|
||||
// (c) Copyright 2005 by Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "games.h"
|
||||
#include "netdriver.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
static GameData *Games;
|
||||
int GameID;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
** Create a game
|
||||
*/
|
||||
void CreateGame(Session *session, char *description, char *map,
|
||||
char *players, char *ip, char *port, char *password)
|
||||
{
|
||||
GameData *game;
|
||||
|
||||
game = new GameData;
|
||||
|
||||
strcpy(game->IP, ip);
|
||||
strcpy(game->Port, port);
|
||||
game->UDPHost = 0;
|
||||
game->UDPPort = 0;
|
||||
strcpy(game->Description, description);
|
||||
strcpy(game->Map, map);
|
||||
game->MaxSlots = atoi(players);
|
||||
game->OpenSlots = game->MaxSlots - 1;
|
||||
if (password) {
|
||||
strcpy(game->Password, password);
|
||||
} else {
|
||||
game->Password[0] = '\0';
|
||||
}
|
||||
|
||||
game->NumSessions = 1;
|
||||
game->Sessions[0] = session;
|
||||
game->ID = GameID++;
|
||||
game->Started = 0;
|
||||
|
||||
game->GameName = session->UserData.GameName;
|
||||
game->Version = session->UserData.Version;
|
||||
|
||||
if (Games) {
|
||||
Games->Prev = game;
|
||||
}
|
||||
game->Next = Games;
|
||||
game->Prev = NULL;
|
||||
Games = game;
|
||||
|
||||
if (session->Game) {
|
||||
PartGame(session);
|
||||
}
|
||||
session->Game = game;
|
||||
}
|
||||
|
||||
/**
|
||||
** Cancel a game
|
||||
*/
|
||||
int CancelGame(Session *session)
|
||||
{
|
||||
GameData *game;
|
||||
int i;
|
||||
|
||||
game = session->Game;
|
||||
|
||||
if (game->Sessions[0] != session) {
|
||||
return -1; // Not the host
|
||||
}
|
||||
|
||||
if (game->Next) {
|
||||
game->Next->Prev = game->Prev;
|
||||
}
|
||||
if (game->Prev) {
|
||||
game->Prev->Next = game->Next;
|
||||
}
|
||||
if (Games == game) {
|
||||
Games = game->Next;
|
||||
}
|
||||
|
||||
for (i = 0; i < game->NumSessions; ++i) {
|
||||
game->Sessions[i]->Game = NULL;
|
||||
}
|
||||
|
||||
session->Game = NULL;
|
||||
delete game;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Start a game
|
||||
*/
|
||||
int StartGame(Session *session)
|
||||
{
|
||||
if (session->Game->Sessions[0] != session) {
|
||||
return -1; // Not the host
|
||||
}
|
||||
|
||||
session->Game->Started = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Join a game
|
||||
*/
|
||||
int JoinGame(Session *session, int id, char *password, unsigned long *host, int *port)
|
||||
{
|
||||
GameData *game;
|
||||
|
||||
if (session->Game) {
|
||||
PartGame(session);
|
||||
}
|
||||
|
||||
game = Games;
|
||||
while (game) {
|
||||
if (game->ID == id) {
|
||||
break;
|
||||
}
|
||||
game = game->Next;
|
||||
}
|
||||
if (!game) {
|
||||
return -2; // ID not found
|
||||
}
|
||||
|
||||
if (game->Password[0]) {
|
||||
if (!password || strcmp(game->Password, password)) {
|
||||
return -3; // Wrong password
|
||||
}
|
||||
}
|
||||
if (!game->OpenSlots) {
|
||||
return -4; // Game full
|
||||
}
|
||||
if (!(game->UDPHost && game->UDPPort)) {
|
||||
return -5; // Server not ready
|
||||
}
|
||||
|
||||
*host = game->UDPHost;
|
||||
*port = game->UDPPort;
|
||||
game->Sessions[game->NumSessions++] = session;
|
||||
session->Game = game;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Leave a game
|
||||
*/
|
||||
int PartGame(Session *session)
|
||||
{
|
||||
GameData *game;
|
||||
int i;
|
||||
|
||||
game = session->Game;
|
||||
|
||||
if (!game) {
|
||||
return -1; // Not in a game
|
||||
}
|
||||
if (game->Started) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (game->Sessions[0] == session) {
|
||||
// The host left, cancel the game
|
||||
CancelGame(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < game->NumSessions; ++i) {
|
||||
if (game->Sessions[i] == session) {
|
||||
for (; i < game->NumSessions - 1; ++i) {
|
||||
game->Sessions[i] = game->Sessions[i + 1];
|
||||
}
|
||||
game->NumSessions--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
session->Game = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int MatchGameType(Session *session, GameData *game)
|
||||
{
|
||||
return (!session->UserData.LoggedIn) ||
|
||||
((!*game->GameName ||!strcmp(session->UserData.GameName, game->GameName)) &&
|
||||
(!*game->Version || !strcmp(session->UserData.Version, game->Version)));
|
||||
}
|
||||
|
||||
/**
|
||||
** List games
|
||||
*/
|
||||
void ListGames(Session *session)
|
||||
{
|
||||
GameData *game;
|
||||
char buf[1024];
|
||||
|
||||
game = Games;
|
||||
while (game) {
|
||||
if (!game->Started && MatchGameType(session, game)) {
|
||||
sprintf(buf, "LISTGAMES %d \"%s\" \"%s\" %d %d %s %s\n",
|
||||
game->ID, game->Description, game->Map,
|
||||
game->OpenSlots, game->MaxSlots, game->IP, game->Port);
|
||||
Send(session, buf);
|
||||
}
|
||||
game = game->Next;
|
||||
}
|
||||
}
|
||||
|
||||
int FillinUDPInfo(unsigned long udphost, int udpport, char* ip, char* port) {
|
||||
GameData *game;
|
||||
for (game = Games; game; game = Games->Next) {
|
||||
if (!strcmp(game->IP, ip) && !strcmp(game->Port, port)) {
|
||||
if (!game->UDPHost && !game->UDPPort) {
|
||||
game->UDPHost = udphost;
|
||||
game->UDPPort = udpport;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name games.h - Games header. */
|
||||
//
|
||||
// (c) Copyright 2005 by Edward Haase and Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef __GAMES_H__
|
||||
#define __GAMES_H__
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Defines
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#define MAX_GAME_PASSWORD_LENGTH 16
|
||||
#define MAX_DESCRIPTION_LENGTH 64
|
||||
#define MAX_MAP_LENGTH 64
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
class Session;
|
||||
|
||||
class GameData
|
||||
{
|
||||
public:
|
||||
char IP[16];
|
||||
char Port[6];
|
||||
char Password[MAX_GAME_PASSWORD_LENGTH + 1];
|
||||
char Description[MAX_DESCRIPTION_LENGTH + 1];
|
||||
char Map[MAX_MAP_LENGTH + 1];
|
||||
int OpenSlots;
|
||||
int MaxSlots;
|
||||
|
||||
char *GameName;
|
||||
char *Version;
|
||||
|
||||
Session *Sessions[16];
|
||||
int NumSessions;
|
||||
int ID;
|
||||
int Started;
|
||||
|
||||
unsigned long UDPHost;
|
||||
int UDPPort;
|
||||
|
||||
GameData *Next;
|
||||
GameData *Prev;
|
||||
};
|
||||
|
||||
extern int GameID;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
extern void CreateGame(Session *session, char *description, char *map,
|
||||
char *players, char *ip, char *port, char *password);
|
||||
extern int CancelGame(Session *session);
|
||||
extern int StartGame(Session *session);
|
||||
extern int JoinGame(Session *session, int id, char *password, unsigned long *host, int *port);
|
||||
extern int PartGame(Session *session);
|
||||
extern void ListGames(Session *session);
|
||||
extern int FillinUDPInfo(unsigned long udphost, int udpport, char* ip, char* port);
|
||||
|
||||
//@}
|
||||
|
||||
#endif // __GAMES_H__
|
|
@ -1,311 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name main.cpp - Primary functionality. */
|
||||
//
|
||||
// (c) Copyright 2005-2011 by Edward Haase and Pali Rohár
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "util.h"
|
||||
#include "netdriver.h"
|
||||
#include "cmd.h"
|
||||
#include "db.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
extern char *optarg;
|
||||
extern int optopt;
|
||||
extern int getopt(int argc, char *const *argv, const char *opt);
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/// @todo Needs code cleanup.
|
||||
/// @todo Needs compatibility checks.
|
||||
/// @todo Needs error message unification.
|
||||
|
||||
#if 1 // from stratagus.cpp, to avoid link issues.
|
||||
|
||||
bool EnableDebugPrint; /// if enabled, print the debug messages
|
||||
bool EnableAssert; /// if enabled, halt on assertion failures
|
||||
bool EnableUnitDebug; /// if enabled, a unit info dump will be created
|
||||
|
||||
void PrintLocation(const char *file, int line, const char *funcName)
|
||||
{
|
||||
fprintf(stdout, "%s:%d: %s: ", file, line, funcName);
|
||||
}
|
||||
|
||||
void AbortAt(const char *file, int line, const char *funcName, const char *conditionStr)
|
||||
{
|
||||
fprintf(stderr, "Assertion failed at %s:%d: %s: %s\n", file, line, funcName, conditionStr);
|
||||
abort();
|
||||
}
|
||||
|
||||
void PrintOnStdOut(const char *format, ...)
|
||||
{
|
||||
va_list valist;
|
||||
va_start(valist, format);
|
||||
vprintf(format, valist);
|
||||
va_end(valist);
|
||||
}
|
||||
|
||||
// from util.cpp
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
|
||||
int opterr = 1;
|
||||
int optind = 1;
|
||||
int optopt;
|
||||
char *optarg;
|
||||
|
||||
static void getopt_err(const char *argv0, const char *str, char opt)
|
||||
{
|
||||
if (opterr) {
|
||||
const char *x;
|
||||
|
||||
while ((x = strchr(argv0, '/'))) {
|
||||
argv0 = x + 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s%s%c\n", argv0, str, opt);
|
||||
}
|
||||
}
|
||||
|
||||
int getopt(int argc, char *const *argv, const char *opts)
|
||||
{
|
||||
static int sp = 1;
|
||||
register int c;
|
||||
register const char *cp;
|
||||
|
||||
optarg = NULL;
|
||||
|
||||
if (sp == 1) {
|
||||
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') {
|
||||
return EOF;
|
||||
} else if (!strcmp(argv[optind], "--")) {
|
||||
optind++;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
optopt = c = argv[optind][sp];
|
||||
if (c == ':' || (cp = strchr(opts, c)) == NULL) {
|
||||
getopt_err(argv[0], ": illegal option -", (char)c);
|
||||
cp = "xx"; /* make the next if false */
|
||||
c = '?';
|
||||
}
|
||||
if (*++cp == ':') {
|
||||
if (argv[optind][++sp] != '\0') {
|
||||
optarg = &argv[optind++][sp];
|
||||
} else if (++optind < argc) {
|
||||
optarg = argv[optind++];
|
||||
} else {
|
||||
getopt_err(argv[0], ": option requires an argument -", (char)c);
|
||||
c = (*opts == ':') ? ':' : '?';
|
||||
}
|
||||
sp = 1;
|
||||
} else if (argv[optind][++sp] == '\0') {
|
||||
optind++;
|
||||
sp = 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** Main loop
|
||||
*/
|
||||
static void MainLoop(void)
|
||||
{
|
||||
Uint32 ticks[2];
|
||||
int delay;
|
||||
int done;
|
||||
|
||||
//
|
||||
// Start the transactions.
|
||||
//
|
||||
done = 0;
|
||||
while (!done) {
|
||||
ticks[0] = SDL_GetTicks();
|
||||
|
||||
//
|
||||
// Update sessions and buffers.
|
||||
//
|
||||
UpdateSessions();
|
||||
UpdateParser();
|
||||
|
||||
ticks[1] = SDL_GetTicks();
|
||||
|
||||
//
|
||||
// Idle out the remainder of this loop.
|
||||
//
|
||||
if ((int)(ticks[1] - ticks[0]) > Server.PollingDelay) {
|
||||
delay = 0;
|
||||
} else {
|
||||
delay = Server.PollingDelay - (ticks[1] - ticks[0]);
|
||||
}
|
||||
|
||||
if (delay > 2000) {
|
||||
delay = 2000;
|
||||
}
|
||||
|
||||
SDL_Delay(delay);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
** The main program: initialize, parse options and arguments.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
|
||||
Server.Port = DEFAULT_PORT;
|
||||
Server.MaxConnections = DEFAULT_MAX_CONN;
|
||||
Server.IdleTimeout = DEFAULT_SESSION_TIMEOUT;
|
||||
Server.PollingDelay = DEFAULT_POLLING_DELAY;
|
||||
|
||||
//
|
||||
// Standard SDL Init.
|
||||
//
|
||||
if (SDL_Init(0) == -1) {
|
||||
printf("SDL_Init: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
|
||||
//
|
||||
// Parse the command line.
|
||||
//
|
||||
while ((i = getopt(argc, argv, "aP:pm:i:d:h")) != -1) {
|
||||
switch (i) {
|
||||
case 'a':
|
||||
EnableAssert = true;
|
||||
continue;
|
||||
case 'P':
|
||||
Server.Port = atoi(optarg);
|
||||
if (Server.Port <= 0) {
|
||||
Server.Port = DEFAULT_PORT;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
EnableDebugPrint = true;
|
||||
continue;
|
||||
case 'm':
|
||||
Server.MaxConnections = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
Server.IdleTimeout = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
Server.PollingDelay = atoi(optarg);
|
||||
break;
|
||||
case ':':
|
||||
printf("Missing argument for %c\n", optopt);
|
||||
exit(0);
|
||||
break;
|
||||
case 'h':
|
||||
printf("Arguments:\n"
|
||||
"-a\tEnable asserts\n"
|
||||
"-P\tSet port\n"
|
||||
"-p\tEnable debug print\n"
|
||||
"-m\tMax connections\n"
|
||||
"-i\tIdle timeout\n"
|
||||
"-d\tPolling delay\n");
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
printf("Unrecognized option: -%c\n", optopt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the database
|
||||
if (DBInit()) {
|
||||
fprintf(stderr, "DBInit failed\n");
|
||||
exit(1);
|
||||
}
|
||||
atexit(DBQuit);
|
||||
|
||||
//
|
||||
// Initialize server.
|
||||
//
|
||||
// Open the server to connections.
|
||||
//
|
||||
if ((status = ServerInit(Server.Port)) != 0) {
|
||||
if (status > 0) {
|
||||
fprintf(stderr, "ERROR %d: %s\n", errno, strerror(errno)); // > 0
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: %s\n", SDL_GetError()); // < 0
|
||||
}
|
||||
exit(status);
|
||||
}
|
||||
atexit(ServerQuit);
|
||||
|
||||
printf("Stratagus Metaserver Initialized on port %d.\n", Server.Port);
|
||||
|
||||
//
|
||||
// Uncomment this line for MSVC (or other default)
|
||||
// debugging of segmentation violations.
|
||||
//
|
||||
// signal(SIGSEGV, SIG_DFL);
|
||||
|
||||
MainLoop();
|
||||
|
||||
//
|
||||
// Server tasks done.
|
||||
//
|
||||
// "atexit" will take over from here for cleanup.
|
||||
//
|
||||
printf("Stratagus Metaserver Done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@}
|
|
@ -1,349 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name netdriver.cpp - Session mangement (SDL_net Socket Implementation). */
|
||||
//
|
||||
// (c) Copyright 2005 by Edward Haase and Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "games.h"
|
||||
#include "netdriver.h"
|
||||
#include "net_lowlevel.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Defines
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
** LINK
|
||||
**
|
||||
** Adds an item to a linked list.
|
||||
*/
|
||||
#define LINK(first, item, last, count) { \
|
||||
if (!first) \
|
||||
first = item; \
|
||||
if (!last) { \
|
||||
last = item; \
|
||||
} else { \
|
||||
item->Next = last->Next; \
|
||||
last->Next = item; \
|
||||
item->Prev = last; \
|
||||
last = item; \
|
||||
if (!item->Prev->Next) \
|
||||
item->Prev->Next = item;\
|
||||
} \
|
||||
++count; \
|
||||
}
|
||||
|
||||
/**
|
||||
** UNLINK
|
||||
**
|
||||
** Removes an item from the linked list.
|
||||
*/
|
||||
#define UNLINK(first, item, last, count) { \
|
||||
if (item->Prev) \
|
||||
item->Prev->Next = item->Next;\
|
||||
if (item->Next) \
|
||||
item->Next->Prev = item->Prev;\
|
||||
if (item == last) \
|
||||
last = item->Prev; \
|
||||
if (item == first) \
|
||||
first = item->Next; \
|
||||
--count; \
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
static Socket MasterSocket;
|
||||
static Socket HolePunchSocket;
|
||||
|
||||
SessionPool *Pool;
|
||||
ServerStruct Server;
|
||||
char UDPBuffer[16 /* GameData->IP */ + 6 /* GameData->Port */ + 1] = {'\0'};
|
||||
unsigned long UDPHost = 0;
|
||||
int UDPPort = 0;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
** Send a message to a session
|
||||
**
|
||||
** @param session Session to send the message to
|
||||
** @param msg Message to send
|
||||
*/
|
||||
void Send(Session *session, const char *msg)
|
||||
{
|
||||
NetSendTCP(session->Sock, msg, strlen(msg));
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize the server
|
||||
**
|
||||
** @param port Defines the port to which the server will bind.
|
||||
**
|
||||
** @return 0 for success, non-zero for failure
|
||||
*/
|
||||
int ServerInit(int port)
|
||||
{
|
||||
int code = 0;
|
||||
Pool = NULL;
|
||||
|
||||
if (NetInit() == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((MasterSocket = NetOpenTCP(NULL, port)) == (Socket)-1) {
|
||||
fprintf(stderr, "NetOpenTCP failed\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((HolePunchSocket = NetOpenUDP(INADDR_ANY, port)) == (Socket)-1) {
|
||||
fprintf(stderr, "NetOpenUDP failed\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (NetSetNonBlocking(MasterSocket) == -1) {
|
||||
fprintf(stderr, "NetSetNonBlocking TCP failed\n");
|
||||
code = -3;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (NetSetNonBlocking(HolePunchSocket) == -1) {
|
||||
fprintf(stderr, "NetSetNonBlocking UDP failed\n");
|
||||
code = -3;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (NetListenTCP(MasterSocket) == -1) {
|
||||
fprintf(stderr, "NetListenTCP failed\n");
|
||||
code = -4;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(Pool = new SessionPool)) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
code = -5;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(Pool->Sockets = new SocketSet)) {
|
||||
code = -6;
|
||||
goto error;
|
||||
}
|
||||
|
||||
Pool->First = NULL;
|
||||
Pool->Last = NULL;
|
||||
Pool->Count = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
NetCloseTCP(MasterSocket);
|
||||
NetCloseUDP(HolePunchSocket);
|
||||
NetExit();
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
** ServerQuit: Releases the server socket.
|
||||
*/
|
||||
void ServerQuit(void)
|
||||
{
|
||||
NetCloseTCP(MasterSocket);
|
||||
// begin clean up of any remaining sockets
|
||||
if (Pool) {
|
||||
Session *ptr;
|
||||
|
||||
while (Pool->First) {
|
||||
ptr = Pool->First;
|
||||
UNLINK(Pool->First, Pool->First, Pool->Last, Pool->Count);
|
||||
NetCloseTCP(ptr->Sock);
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
delete Pool->Sockets;
|
||||
delete Pool;
|
||||
}
|
||||
|
||||
NetExit();
|
||||
}
|
||||
|
||||
/**
|
||||
** Returns time (in seconds) that a session has been idle.
|
||||
**
|
||||
** @param session This is the session we are checking.
|
||||
*/
|
||||
static int IdleSeconds(Session *session)
|
||||
{
|
||||
return (int)(time(0) - session->Idle);
|
||||
}
|
||||
|
||||
/**
|
||||
** Destroys and cleans up session data.
|
||||
**
|
||||
** @param session Reference to the session to be killed.
|
||||
*/
|
||||
static int KillSession(Session *session)
|
||||
{
|
||||
DebugPrint("Closing connection from '%s'\n" _C_ session->AddrData.IPStr);
|
||||
NetCloseTCP(session->Sock);
|
||||
Pool->Sockets->DelSocket(session->Sock);
|
||||
UNLINK(Pool->First, session, Pool->Last, Pool->Count);
|
||||
PartGame(session);
|
||||
delete session;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Accept new connections
|
||||
*/
|
||||
static void AcceptConnections()
|
||||
{
|
||||
Session *new_session;
|
||||
Socket new_socket;
|
||||
unsigned long host;
|
||||
int port;
|
||||
while ((new_socket = NetAcceptTCP(MasterSocket, &host, &port)) != (Socket)-1) {
|
||||
// Check if we're at MaxConnections
|
||||
if (Pool->Count == Server.MaxConnections) {
|
||||
NetSendTCP(new_socket, "Server Full\n", 12);
|
||||
NetCloseTCP(new_socket);
|
||||
break;
|
||||
}
|
||||
|
||||
new_session = new Session;
|
||||
if (!new_session) {
|
||||
fprintf(stderr, "ERROR: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
new_session->Sock = new_socket;
|
||||
new_session->Idle = time(0);
|
||||
|
||||
new_session->AddrData.Host = host;
|
||||
sprintf(new_session->AddrData.IPStr, "%d.%d.%d.%d", NIPQUAD(ntohl(host)));
|
||||
new_session->AddrData.Port = port;
|
||||
DebugPrint("New connection from '%s'\n" _C_ new_session->AddrData.IPStr);
|
||||
|
||||
LINK(Pool->First, new_session, Pool->Last, Pool->Count);
|
||||
Pool->Sockets->AddSocket(new_socket);
|
||||
}
|
||||
if (NetSocketReady(HolePunchSocket, 0)) {
|
||||
NetRecvUDP(HolePunchSocket, UDPBuffer, sizeof(UDPBuffer), &UDPHost, &UDPPort);
|
||||
DebugPrint("New UDP %s (%d %d)\n" _C_ UDPBuffer _C_ UDPHost _C_ UDPPort);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Kick idlers
|
||||
*/
|
||||
static void KickIdlers(void)
|
||||
{
|
||||
Session *session;
|
||||
Session *next;
|
||||
|
||||
for (session = Pool->First; session; ) {
|
||||
next = session->Next;
|
||||
if (IdleSeconds(session) > Server.IdleTimeout) {
|
||||
DebugPrint("Kicking idler '%s'\n" _C_ session->AddrData.IPStr);
|
||||
KillSession(session);
|
||||
}
|
||||
session = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Read data
|
||||
*/
|
||||
static int ReadData()
|
||||
{
|
||||
int result = Pool->Sockets->Select(0);
|
||||
|
||||
if (result == 0) {
|
||||
// No sockets ready
|
||||
return 0;
|
||||
}
|
||||
if (result == -1) {
|
||||
// FIXME: print error message
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ready sockets
|
||||
for (Session *session = Pool->First; session; ) {
|
||||
Session *next = session->Next;
|
||||
if (Pool->Sockets->HasDataToRead(session->Sock)) {
|
||||
// socket ready
|
||||
session->Idle = time(0);
|
||||
int clen = strlen(session->Buffer);
|
||||
result = NetRecvTCP(session->Sock, session->Buffer + clen,
|
||||
sizeof(session->Buffer) - clen);
|
||||
if (result < 0) {
|
||||
KillSession(session);
|
||||
} else {
|
||||
session->Buffer[clen + result] = '\0';
|
||||
}
|
||||
}
|
||||
session = next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Accepts new connections, receives data, manages buffers,
|
||||
*/
|
||||
int UpdateSessions(void)
|
||||
{
|
||||
AcceptConnections();
|
||||
|
||||
if (!Pool->First) {
|
||||
// No connections
|
||||
return 0;
|
||||
}
|
||||
|
||||
KickIdlers();
|
||||
|
||||
return ReadData();
|
||||
}
|
||||
|
||||
//@}
|
|
@ -1,154 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name netdriver.h - Net driver header. */
|
||||
//
|
||||
// (c) Copyright 2005 by Edward Haase and Jimmy Salmon
|
||||
//
|
||||
// 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; only version 2 of the License.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef __NETDRIVER_H__
|
||||
#define __NETDRIVER_H__
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <time.h>
|
||||
#include "net_lowlevel.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Defines
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#define DEFAULT_PORT 7775 // Server port
|
||||
#define DEFAULT_MAX_CONN 500 // Max Connections
|
||||
#define DEFAULT_SESSION_TIMEOUT 900 // 15 miniutes
|
||||
#define DEFAULT_POLLING_DELAY 250 // MS (1000 = 1s)
|
||||
|
||||
#define MAX_USERNAME_LENGTH 32
|
||||
#define MAX_PASSWORD_LENGTH 32
|
||||
|
||||
#define MAX_GAMENAME_LENGTH 32
|
||||
#define MAX_VERSION_LENGTH 8
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
class GameData;
|
||||
|
||||
/**
|
||||
** Global server variables.
|
||||
*/
|
||||
class ServerStruct {
|
||||
public:
|
||||
ServerStruct() : Port(0), MaxConnections(0), IdleTimeout(0),
|
||||
PollingDelay(0) {}
|
||||
|
||||
int Port;
|
||||
int MaxConnections;
|
||||
int IdleTimeout;
|
||||
int PollingDelay;
|
||||
};
|
||||
|
||||
extern ServerStruct Server;
|
||||
|
||||
/**
|
||||
** Session data
|
||||
**
|
||||
** One per connection.
|
||||
*/
|
||||
class Session {
|
||||
public:
|
||||
Session() : Next(NULL), Prev(NULL), Idle(0), Sock(0), Game(NULL)
|
||||
{
|
||||
Buffer[0] = '\0';
|
||||
AddrData.Host = 0;
|
||||
AddrData.IPStr[0] = '\0';
|
||||
AddrData.Port = 0;
|
||||
UserData.Name[0] = '\0';
|
||||
UserData.GameName[0] = '\0';
|
||||
UserData.Version[0] = '\0';
|
||||
UserData.LoggedIn = 0;
|
||||
}
|
||||
|
||||
Session *Next;
|
||||
Session *Prev;
|
||||
|
||||
char Buffer[1024];
|
||||
time_t Idle;
|
||||
|
||||
Socket Sock;
|
||||
|
||||
struct {
|
||||
unsigned long Host;
|
||||
char IPStr[16];
|
||||
int Port;
|
||||
} AddrData; /// Remote address data.
|
||||
|
||||
struct {
|
||||
char Name[MAX_USERNAME_LENGTH + 1];
|
||||
char GameName[MAX_GAMENAME_LENGTH + 1];
|
||||
char Version[MAX_VERSION_LENGTH + 1];
|
||||
int LoggedIn;
|
||||
} UserData; /// Specific user data.
|
||||
|
||||
GameData *Game;
|
||||
};
|
||||
|
||||
/**
|
||||
** Global session tracking.
|
||||
*/
|
||||
class SessionPool {
|
||||
public:
|
||||
SessionPool() : First(NULL), Last(NULL), Count(0), Sockets(NULL) {}
|
||||
|
||||
Session *First;
|
||||
Session *Last;
|
||||
int Count;
|
||||
|
||||
SocketSet *Sockets;
|
||||
};
|
||||
|
||||
/// external reference to session tracking.
|
||||
extern SessionPool *Pool;
|
||||
extern char UDPBuffer[16 /* GameData->IP */ + 6 /* GameData->Port */ + 1];
|
||||
extern unsigned long UDPHost;
|
||||
extern int UDPPort;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
extern void Send(Session *session, const char *msg);
|
||||
|
||||
extern int ServerInit(int port);
|
||||
extern void ServerQuit(void);
|
||||
extern int UpdateSessions(void);
|
||||
|
||||
//@}
|
||||
|
||||
#endif // __NETDRIVER_H__
|
Loading…
Add table
Reference in a new issue