delete metaserver

This commit is contained in:
Tim Felgentreff 2022-03-03 22:43:07 +01:00
parent 05f6b251f7
commit a00256e6da
11 changed files with 0 additions and 2225 deletions

View file

@ -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

View file

@ -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))

View file

@ -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;
}
//@}

View file

@ -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__

View file

@ -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;
}

View file

@ -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__

View file

@ -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;
}

View file

@ -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__

View file

@ -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;
}
//@}

View file

@ -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();
}
//@}

View file

@ -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__