daily work

This commit is contained in:
Olaf Rempel 2006-02-20 21:58:59 +01:00
parent 190be1be3c
commit 38542d7ddf
18 changed files with 191 additions and 84 deletions

View File

@ -4,9 +4,10 @@
#define DEFAULT_TIMEOUT 180 #define DEFAULT_TIMEOUT 180
GameList::GameList(Config& conf) GameList::GameList(Config& conf)
: lastUpdate(0)
{ {
int interval = conf.getInteger("global", "game_timeout", DEFAULT_TIMEOUT); int interval = conf.getInteger("global", "game_timeout", DEFAULT_TIMEOUT);
TimerService::registerTimer(new Timer(new CleanupEvent(this), interval)); TimerService::registerTimer(new Timer(new CleanupEvent(*this), interval));
} }
GameList::~GameList() GameList::~GameList()
@ -17,14 +18,15 @@ void GameList::cleanup()
{ {
} }
long GameList::getLastMod() long GameList::getLastUpdate()
{ {
return 0; lastUpdate++;
return lastUpdate;
} }
Iterator<GameEntry>* GameList::createIterator() Iterator<GameEntry>* GameList::createIterator()
{ {
return new NullIterator<GameEntry>(); return glist.createIterator();
} }
void GameList::addGame(int gameid, NetPkt* pkt) void GameList::addGame(int gameid, NetPkt* pkt)
@ -32,4 +34,6 @@ void GameList::addGame(int gameid, NetPkt* pkt)
char buf[64]; char buf[64];
pkt->show(buf, sizeof(buf)); pkt->show(buf, sizeof(buf));
LogSystem::log(LOG_NOTICE, "Adding Game %d: %s", gameid, buf); LogSystem::log(LOG_NOTICE, "Adding Game %d: %s", gameid, buf);
glist.add(new GameEntry());
} }

View File

@ -8,18 +8,17 @@
class GameEntry { class GameEntry {
public: public:
GameEntry(); GameEntry() {};
~GameEntry(); ~GameEntry() {};
struct in_addr addr;
int port1;
int port2;
int gameid;
protected: protected:
GameEntry(const GameEntry& ge); GameEntry(const GameEntry& ge);
GameEntry& operator=(const GameEntry& ge); GameEntry& operator=(const GameEntry& ge);
private:
// struct in_addr addr;
int port1;
int port2;
int gameid;
}; };
@ -31,7 +30,7 @@ public:
void cleanup(); void cleanup();
void addGame(int gameid, NetPkt* pkt); void addGame(int gameid, NetPkt* pkt);
long getLastMod(); long getLastUpdate();
Iterator<GameEntry>* createIterator(); Iterator<GameEntry>* createIterator();
protected: protected:
@ -39,18 +38,18 @@ protected:
GameList& operator=(const GameList& gl); GameList& operator=(const GameList& gl);
private: private:
class CleanupEvent : public Command { class CleanupEvent : public Event {
public: public:
CleanupEvent(GameList* gl) : gl(gl) {} CleanupEvent(GameList& gl) : gl(gl) {}
~CleanupEvent() {} ~CleanupEvent() {}
void execute() { gl->cleanup(); } void execute() { gl.cleanup(); }
private: private:
GameList* gl; GameList& gl;
}; };
List<GameEntry> glist; List<GameEntry> glist;
long lastUpdate;
}; };
#endif // _GAMELIST_H_ #endif // _GAMELIST_H_

View File

@ -3,15 +3,15 @@
#include "gamescanner.h" #include "gamescanner.h"
#define DEFAULT_INTERVAL 30 #define DEFAULT_SCAN_INTERVAL 30
GameScanner::GameScanner(Config& conf, ModuleList& modList, RecvQueue& rxQueue) GameScanner::GameScanner(Config& conf, ModuleList& modList, RecvQueue& rxQueue)
: modList(modList), rxQueue(rxQueue) : modList(modList), rxQueue(rxQueue)
{ {
msock = new MultiSock(conf); msock = new MultiSock(conf);
int interval = conf.getInteger("global", "scan_interval", DEFAULT_INTERVAL); int interval = conf.getInteger("global", "scan_interval", DEFAULT_SCAN_INTERVAL);
TimerService::registerTimer(new Timer(new ScanEvent(this), interval)); TimerService::registerTimer(new Timer(new ScanEvent(*this), interval));
} }
GameScanner::~GameScanner() GameScanner::~GameScanner()

View File

@ -22,14 +22,14 @@ protected:
GameScanner& operator=(const GameScanner& hs); GameScanner& operator=(const GameScanner& hs);
private: private:
class ScanEvent : public Command { class ScanEvent : public Event {
public: public:
ScanEvent(GameScanner* gs) : gs(gs) {} ScanEvent(GameScanner& gs) : gs(gs) {}
~ScanEvent() {} ~ScanEvent() {}
void execute() { gs->scan(); } void execute() { gs.scan(); }
private: private:
GameScanner* gs; GameScanner& gs;
}; };
ModuleList& modList; ModuleList& modList;

View File

@ -3,7 +3,7 @@
scan_port 7130 scan_port 7130
# broadcast scan every X seconds # broadcast scan every X seconds
scan_interval 10 scan_interval 30
# use this interface(s) # use this interface(s)
scan_deny_iface scan_deny_iface
@ -14,6 +14,9 @@ game_timeout 30
# master answers with this source IP # master answers with this source IP
master_ip 0.0.0.0 master_ip 0.0.0.0
# rebuild master liste every X seconds
rebuild_interval 5
# logging # logging
logfile hlswmaster.log logfile hlswmaster.log
logprio DEBUG logprio DEBUG

View File

@ -88,10 +88,10 @@ int main(int argc, char *argv[])
GameScanner scanner(conf, modList, rxQueue); GameScanner scanner(conf, modList, rxQueue);
GameParser parser(rxQueue, modList, gameList); GameParser parser(rxQueue, modList, gameList);
HlswServer server(conf); HlswServer server(conf, gameList);
// modList.reg(new ModHalfLife()); // modList.reg(new ModHalfLife());
modList.reg(new ModQ3Engine()); // modList.reg(new ModQ3Engine());
// modList.reg(new ModD3Engine()); // modList.reg(new ModD3Engine());
// modList.reg(new ModGameSpy1()); // modList.reg(new ModGameSpy1());
// modList.reg(new ModGameSpy2()); // modList.reg(new ModGameSpy2());

View File

@ -12,6 +12,15 @@
#define HLSW_MASTER_PORT 7140 #define HLSW_MASTER_PORT 7140
static const char hlsw_header[] = "\xFF\xFF\xFF\xFFHLSWLANSEARCH"; static const char hlsw_header[] = "\xFF\xFF\xFF\xFFHLSWLANSEARCH";
#define DEFAULT_REBUILD_INTERVAL 5
struct hlsw_entry {
uint16_t gameid;
uint32_t ip;
uint16_t port1;
uint16_t port2;
} __attribute__ ((packed));
HlswServer::HlswPacket::HlswPacket(HlswPacket* next) HlswServer::HlswPacket::HlswPacket(HlswPacket* next)
: next(next), count(0) : next(next), count(0)
{ {
@ -27,13 +36,18 @@ HlswServer::HlswPacket::~HlswPacket()
bool HlswServer::HlswPacket::addGame(GameEntry* ge) bool HlswServer::HlswPacket::addGame(GameEntry* ge)
{ {
if (count < 140) { if (count >= 140)
count++;
return true;
} else {
return false; return false;
}
struct hlsw_entry tmp;
tmp.gameid = ge->gameid;
tmp.ip = ge->addr.s_addr;
tmp.port1 = ge->port1;
tmp.port2 = ge->port2;
memcpy(data + sizeof(hlsw_header) + count * 10, &tmp, sizeof(tmp));
count++;
return true;
} }
void HlswServer::HlswPacket::send(int socket, struct sockaddr_in* dst) void HlswServer::HlswPacket::send(int socket, struct sockaddr_in* dst)
@ -47,19 +61,18 @@ void HlswServer::HlswPacket::send(int socket, struct sockaddr_in* dst)
} }
} }
HlswServer::HlswServer(Config& conf) HlswServer::HlswServer(Config& conf, GameList& glist)
: lastUpdate(0)
{ {
struct sockaddr_in dst;
const char *ip;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
LogSystem::log(LOG_CRIT, "HlswServer(): socket()"); LogSystem::log(LOG_CRIT, "HlswServer(): socket()");
return; return;
} }
ip = conf.getString("global", "master_ip", "0.0.0.0"); const char *ip = conf.getString("global", "master_ip", "0.0.0.0");
LogSystem::log(LOG_NOTICE, "HlswServer listen on %s:%d", ip, HLSW_MASTER_PORT); LogSystem::log(LOG_NOTICE, "HlswServer listen on %s:%d", ip, HLSW_MASTER_PORT);
struct sockaddr_in dst;
dst.sin_family = AF_INET; dst.sin_family = AF_INET;
dst.sin_port = htons(HLSW_MASTER_PORT); dst.sin_port = htons(HLSW_MASTER_PORT);
inet_aton(ip, &dst.sin_addr); inet_aton(ip, &dst.sin_addr);
@ -69,6 +82,9 @@ HlswServer::HlswServer(Config& conf)
return; return;
} }
int interval = conf.getInteger("global", "rebuild_interval", DEFAULT_REBUILD_INTERVAL);
TimerService::registerTimer(new Timer(new RebuildEvent(*this, glist), interval));
pktlist = new HlswPacket(NULL); pktlist = new HlswPacket(NULL);
} }
@ -90,12 +106,6 @@ int HlswServer::execute(void* arg)
len = sizeof(src); len = sizeof(src);
ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&src, &len); ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&src, &len);
if (ret != sizeof(hlsw_header)) {
LogSystem::log(LOG_NOTICE, "HlswServer: invalid packet");
continue;
}
/* testen ob es sich um ein HLSW anforderung handelt */
if (memcmp(buf, hlsw_header, sizeof(hlsw_header))) { if (memcmp(buf, hlsw_header, sizeof(hlsw_header))) {
LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet"); LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet");
continue; continue;
@ -108,23 +118,27 @@ int HlswServer::execute(void* arg)
return 0; return 0;
} }
void HlswServer::rebuild(GameList& glist) {
Iterator<GameEntry>* it = glist.createIterator();
HlswPacket* newlist = NULL;
while (it->hasNext()) {
GameEntry* d = it->next();
if (!newlist || !newlist->addGame(d)) {
newlist = new HlswPacket(newlist);
newlist->addGame(d);
}
}
mutex.lock();
HlswPacket* oldlist = pktlist;
pktlist = newlist;
mutex.unlock();
delete oldlist; void HlswServer::rebuild(GameList& glist) {
delete it; if (glist.getLastUpdate() > lastUpdate) {
HlswPacket* newlist = new HlswPacket(NULL);
Iterator<GameEntry>* it = glist.createIterator();
while (it->hasNext()) {
GameEntry* d = it->next();
if (!newlist->addGame(d)) {
newlist = new HlswPacket(newlist);
newlist->addGame(d);
}
}
lastUpdate = glist.getLastUpdate();
delete it;
mutex.lock();
HlswPacket* oldlist = pktlist;
pktlist = newlist;
mutex.unlock();
delete oldlist;
}
} }

View File

@ -10,18 +10,29 @@
class HlswServer : public Thread { class HlswServer : public Thread {
public: public:
HlswServer(Config& conf); HlswServer(Config& conf, GameList& glist);
~HlswServer(); ~HlswServer();
int execute(void* arg); int execute(void* arg);
void rebuild(GameList& glist); void rebuild(GameList& gl);
protected: protected:
HlswServer(const HlswServer& hs); HlswServer(const HlswServer& hs);
HlswServer& operator=(const HlswServer& hs); HlswServer& operator=(const HlswServer& hs);
private: private:
class RebuildEvent : public Event {
public:
RebuildEvent(HlswServer& hs, GameList& gl) : hs(hs), gl(gl) {}
~RebuildEvent() {}
void execute() { hs.rebuild(gl); }
private:
HlswServer& hs;
GameList& gl;
};
class HlswPacket { class HlswPacket {
public: public:
HlswPacket(HlswPacket* next); HlswPacket(HlswPacket* next);
@ -39,6 +50,8 @@ private:
HlswPacket* pktlist; HlswPacket* pktlist;
Mutex mutex; Mutex mutex;
int sock; int sock;
long lastUpdate;
}; };
#endif // _HLSWSERVER_H_ #endif // _HLSWSERVER_H_

4
list.h
View File

@ -146,13 +146,13 @@ private:
ListIterator(const List<TT>* list) ListIterator(const List<TT>* list)
: list(list) : list(list)
{ {
// ((ListBase*)list)->mutex.lock(); ((List<TT>*)list)->mutex.lock();
reset(); reset();
} }
~ListIterator() ~ListIterator()
{ {
// ((ListBase*)list)->mutex.unlock(); ((List<TT>*)list)->mutex.unlock();
} }
bool hasNext() bool hasNext()

View File

@ -9,7 +9,7 @@ public:
~ModGameSpy1() {} ~ModGameSpy1() {}
void scan(MultiSock* msock); void scan(MultiSock* msock);
int parse(NetPkt* pkt, GameList* slist); int parse(NetPkt* pkt, GameList* glist);
const char* getName() { return "GameSpy 1 Protocol"; } const char* getName() { return "GameSpy 1 Protocol"; }
}; };

View File

@ -9,7 +9,7 @@ public:
~ModGameSpy2() {} ~ModGameSpy2() {}
void scan(MultiSock* msock); void scan(MultiSock* msock);
int parse(NetPkt* pkt, GameList* slist); int parse(NetPkt* pkt, GameList* glist);
const char* getName() { return "GameSpy 2 Protocol"; } const char* getName() { return "GameSpy 2 Protocol"; }
}; };

View File

@ -9,7 +9,7 @@ public:
~ModHalfLife() {} ~ModHalfLife() {}
void scan(MultiSock* msock); void scan(MultiSock* msock);
int parse(NetPkt* pkt, GameList* slist); int parse(NetPkt* pkt, GameList* glist);
const char* getName() { return "HalfLife engine"; } const char* getName() { return "HalfLife engine"; }
}; };

View File

@ -1,23 +1,86 @@
#include <string.h> #include <string.h>
#include "logging.h"
#include "mod_q3engine.h" #include "mod_q3engine.h"
static struct game_ports port_arr[] = { static struct game_ports port_arr[] = {
{ 27960, 27969, ID_Q3A }, // q3(6), ef(7), et25), rtcw(8) { 27960, 27969, ID_Q3A }, // q3(6), ef(7), et25), rtcw(8)
{ 28070, 28070, ID_JK2 }, // jk2(12) // { 28070, 28070, ID_JK2 }, // jk2(12)
{ 28960, 28963, ID_COD }, // cod(31), cod:uo(42), cod2(48) // { 28960, 28963, ID_COD }, // cod(31), cod:uo(42), cod2(48)
{ 29070, 29070, ID_JK3 }, // jk3(27) // { 29070, 29070, ID_JK3 }, // jk3(27)
{ 0,0,0 } { 0,0,0 }
}; };
static const char scanmsg[] = "\xff\xff\xff\xffgetStatus"; static const char scanmsg[] = "\xff\xff\xff\xffgetStatus";
static const char replyhead[] = "\xff\xff\xff\xffstatusResponse"; static const char replyhead[] = "\xff\xff\xff\xffstatusResponse";
static const char search_version[] = "\\version\\";
static const char search_gamename[] = "\\gamename\\";
static const char reply_q3[] = "Q3 ";
static const char reply_ef[] = "ST:V HM ";
static const char reply_rtcw[] = "Wolf ";
static const char reply_et[] = "ET";
static const char reply_jk2[] = "JK2MP";
static const char reply_jk3[] = "JAmp";
static const char reply_cod[] = "Call of Duty\\";
static const char reply_coduo[] = "CoD:United Offensive\\";
static const char reply_cod2[] = "Call of Duty 2\\";
void ModQ3Engine::scan(MultiSock* msock) void ModQ3Engine::scan(MultiSock* msock)
{ {
msock->send(port_arr, scanmsg, strlen(scanmsg)); msock->send(port_arr, scanmsg, strlen(scanmsg));
} }
int ModQ3Engine::parse(NetPkt* pkt, GameList* slist) int ModQ3Engine::parse(NetPkt* pkt, GameList* glist)
{ {
int gameid = 0, pos1, pos2;
if (!pkt->checkPortArray(port_arr))
return PARSE_REJECT;
if (!pkt->compare(0, replyhead, strlen(replyhead)))
return PARSE_REJECT;
pos1 = pkt->find(0, search_version, strlen(search_version));
if (pos1 != -1) {
pos1 += strlen(search_version);
if (pkt->compare(pos1, reply_q3, strlen(reply_q3)))
gameid = ID_Q3A;
else if (pkt->compare(pos1, reply_ef, strlen(reply_ef)))
gameid = ID_EF;
else if (pkt->compare(pos1, reply_rtcw, strlen(reply_rtcw)))
gameid = ID_RTCW;
else if (pkt->compare(pos1, reply_et, strlen(reply_et)))
gameid = ID_ET;
else if (pkt->compare(pos1, reply_jk2, strlen(reply_jk2)))
gameid = ID_JK2;
else if (pkt->compare(pos1, reply_jk3, strlen(reply_jk3)))
gameid = ID_JK3;
}
pos2 = pkt->find(0, search_gamename, strlen(search_gamename));
if (gameid == 0 && pos2 != -1) {
pos2 += strlen(search_gamename);
if (pkt->compare(pos2, reply_cod, strlen(reply_cod)))
gameid = ID_COD;
else if (pkt->compare(pos2, reply_coduo, strlen(reply_coduo)))
gameid = ID_COD_UO;
else if (pkt->compare(pos2, reply_cod2, strlen(reply_cod2)))
gameid = ID_COD2;
}
if (gameid == 0)
return PARSE_REJECT;
glist->addGame(gameid, pkt);
return PARSE_ACCEPT; return PARSE_ACCEPT;
} }

View File

@ -9,7 +9,7 @@ public:
~ModQ3Engine() {} ~ModQ3Engine() {}
void scan(MultiSock* msock); void scan(MultiSock* msock);
int parse(NetPkt* pkt, GameList* slist); int parse(NetPkt* pkt, GameList* glist);
const char* getName() { return "Quake3 engine"; } const char* getName() { return "Quake3 engine"; }
}; };

View File

@ -78,3 +78,13 @@ bool NetPkt::compare(int offset, const char* buf, int len)
return (memcmp(this->data + offset, buf, len) == 0); return (memcmp(this->data + offset, buf, len) == 0);
} }
int NetPkt::find(int offset, const char *buf, int len)
{
if (offset >= this->size)
return -1;
void* found = memmem(this->data + offset, this->size, buf, len);
return (found == NULL) ? -1 : ((char*)found - this->data);
}

View File

@ -17,6 +17,7 @@ public:
int checkPortArray(struct game_ports* arr); int checkPortArray(struct game_ports* arr);
bool compare(int offset, const char* buf, int len); bool compare(int offset, const char* buf, int len);
int find(int offset, const char *buf, int len);
protected: protected:
NetPkt(const NetPkt& x); NetPkt(const NetPkt& x);

View File

@ -2,14 +2,14 @@
#include "timerservice.h" #include "timerservice.h"
Timer::Timer(Command* cmd, unsigned int timeval) Timer::Timer(Event* event, unsigned int timeval)
: next(0), cmd(cmd), timeval(timeval) : next(0), event(event), timeval(timeval)
{ {
} }
Timer::~Timer() Timer::~Timer()
{ {
delete cmd; delete event;
} }
TimerService::~TimerService() TimerService::~TimerService()
@ -39,7 +39,7 @@ void TimerService::checkTimeouts()
long now = time(NULL); long now = time(NULL);
Timer* search = firstTimer; Timer* search = firstTimer;
while (search != NULL && search->timeout <= now) { while (search != NULL && search->timeout <= now) {
search->cmd->execute(); search->event->execute();
firstTimer = search->next; firstTimer = search->next;
addTimer(search, false); addTimer(search, false);

View File

@ -3,19 +3,19 @@
#include "mutex.h" #include "mutex.h"
class Command { class Event {
public: public:
virtual ~Command() {}; virtual ~Event() {};
virtual void execute() =0; virtual void execute() =0;
protected: protected:
Command() {}; Event() {};
}; };
class Timer { class Timer {
friend class TimerService; friend class TimerService;
public: public:
Timer(Command* cmd, unsigned int timeval); Timer(Event* event, unsigned int timeval);
~Timer(); ~Timer();
protected: protected:
@ -24,7 +24,7 @@ protected:
private: private:
Timer* next; Timer* next;
Command* cmd; Event* event;
int timeval; int timeval;
long timeout; long timeout;
}; };