From 38542d7ddf994e4c55d7656e30c03d6bd5a2785c Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Mon, 20 Feb 2006 21:58:59 +0100 Subject: [PATCH] daily work --- gamelist.cpp | 12 ++++--- gamelist.h | 27 ++++++++-------- gamescanner.cpp | 6 ++-- gamescanner.h | 8 ++--- hlswmaster.conf | 5 ++- hlswmaster.cpp | 4 +-- hlswserver.cpp | 84 ++++++++++++++++++++++++++++-------------------- hlswserver.h | 17 ++++++++-- list.h | 4 +-- mod_gamespy1.h | 2 +- mod_gamespy2.h | 2 +- mod_halflife.h | 2 +- mod_q3engine.cpp | 71 +++++++++++++++++++++++++++++++++++++--- mod_q3engine.h | 2 +- netpkt.cpp | 10 ++++++ netpkt.h | 1 + timerservice.cpp | 8 ++--- timerservice.h | 10 +++--- 18 files changed, 191 insertions(+), 84 deletions(-) diff --git a/gamelist.cpp b/gamelist.cpp index d17211c..c3ebd15 100644 --- a/gamelist.cpp +++ b/gamelist.cpp @@ -4,9 +4,10 @@ #define DEFAULT_TIMEOUT 180 GameList::GameList(Config& conf) +: lastUpdate(0) { 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() @@ -17,14 +18,15 @@ void GameList::cleanup() { } -long GameList::getLastMod() +long GameList::getLastUpdate() { - return 0; + lastUpdate++; + return lastUpdate; } Iterator* GameList::createIterator() { - return new NullIterator(); + return glist.createIterator(); } void GameList::addGame(int gameid, NetPkt* pkt) @@ -32,4 +34,6 @@ void GameList::addGame(int gameid, NetPkt* pkt) char buf[64]; pkt->show(buf, sizeof(buf)); LogSystem::log(LOG_NOTICE, "Adding Game %d: %s", gameid, buf); + + glist.add(new GameEntry()); } diff --git a/gamelist.h b/gamelist.h index 9594457..b654099 100644 --- a/gamelist.h +++ b/gamelist.h @@ -8,18 +8,17 @@ class GameEntry { public: - GameEntry(); - ~GameEntry(); + GameEntry() {}; + ~GameEntry() {}; + + struct in_addr addr; + int port1; + int port2; + int gameid; protected: GameEntry(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 addGame(int gameid, NetPkt* pkt); - long getLastMod(); + long getLastUpdate(); Iterator* createIterator(); protected: @@ -39,18 +38,18 @@ protected: GameList& operator=(const GameList& gl); private: - class CleanupEvent : public Command { + class CleanupEvent : public Event { public: - CleanupEvent(GameList* gl) : gl(gl) {} + CleanupEvent(GameList& gl) : gl(gl) {} ~CleanupEvent() {} - void execute() { gl->cleanup(); } + void execute() { gl.cleanup(); } private: - GameList* gl; + GameList& gl; }; - List glist; + long lastUpdate; }; #endif // _GAMELIST_H_ diff --git a/gamescanner.cpp b/gamescanner.cpp index 519e15d..7f51983 100644 --- a/gamescanner.cpp +++ b/gamescanner.cpp @@ -3,15 +3,15 @@ #include "gamescanner.h" -#define DEFAULT_INTERVAL 30 +#define DEFAULT_SCAN_INTERVAL 30 GameScanner::GameScanner(Config& conf, ModuleList& modList, RecvQueue& rxQueue) : modList(modList), rxQueue(rxQueue) { msock = new MultiSock(conf); - int interval = conf.getInteger("global", "scan_interval", DEFAULT_INTERVAL); - TimerService::registerTimer(new Timer(new ScanEvent(this), interval)); + int interval = conf.getInteger("global", "scan_interval", DEFAULT_SCAN_INTERVAL); + TimerService::registerTimer(new Timer(new ScanEvent(*this), interval)); } GameScanner::~GameScanner() diff --git a/gamescanner.h b/gamescanner.h index eda6c42..e224ef3 100644 --- a/gamescanner.h +++ b/gamescanner.h @@ -22,14 +22,14 @@ protected: GameScanner& operator=(const GameScanner& hs); private: - class ScanEvent : public Command { + class ScanEvent : public Event { public: - ScanEvent(GameScanner* gs) : gs(gs) {} + ScanEvent(GameScanner& gs) : gs(gs) {} ~ScanEvent() {} - void execute() { gs->scan(); } + void execute() { gs.scan(); } private: - GameScanner* gs; + GameScanner& gs; }; ModuleList& modList; diff --git a/hlswmaster.conf b/hlswmaster.conf index 39c0f32..26d110b 100644 --- a/hlswmaster.conf +++ b/hlswmaster.conf @@ -3,7 +3,7 @@ scan_port 7130 # broadcast scan every X seconds -scan_interval 10 +scan_interval 30 # use this interface(s) scan_deny_iface @@ -14,6 +14,9 @@ game_timeout 30 # master answers with this source IP master_ip 0.0.0.0 +# rebuild master liste every X seconds +rebuild_interval 5 + # logging logfile hlswmaster.log logprio DEBUG diff --git a/hlswmaster.cpp b/hlswmaster.cpp index 7c04c4d..a388a16 100644 --- a/hlswmaster.cpp +++ b/hlswmaster.cpp @@ -88,10 +88,10 @@ int main(int argc, char *argv[]) GameScanner scanner(conf, modList, rxQueue); GameParser parser(rxQueue, modList, gameList); - HlswServer server(conf); + HlswServer server(conf, gameList); // modList.reg(new ModHalfLife()); - modList.reg(new ModQ3Engine()); +// modList.reg(new ModQ3Engine()); // modList.reg(new ModD3Engine()); // modList.reg(new ModGameSpy1()); // modList.reg(new ModGameSpy2()); diff --git a/hlswserver.cpp b/hlswserver.cpp index 1fee34e..88b9393 100644 --- a/hlswserver.cpp +++ b/hlswserver.cpp @@ -12,6 +12,15 @@ #define HLSW_MASTER_PORT 7140 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) : next(next), count(0) { @@ -27,13 +36,18 @@ HlswServer::HlswPacket::~HlswPacket() bool HlswServer::HlswPacket::addGame(GameEntry* ge) { - if (count < 140) { - count++; - - return true; - } else { + if (count >= 140) 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) @@ -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) { LogSystem::log(LOG_CRIT, "HlswServer(): socket()"); 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); + struct sockaddr_in dst; dst.sin_family = AF_INET; dst.sin_port = htons(HLSW_MASTER_PORT); inet_aton(ip, &dst.sin_addr); @@ -69,6 +82,9 @@ HlswServer::HlswServer(Config& conf) return; } + int interval = conf.getInteger("global", "rebuild_interval", DEFAULT_REBUILD_INTERVAL); + TimerService::registerTimer(new Timer(new RebuildEvent(*this, glist), interval)); + pktlist = new HlswPacket(NULL); } @@ -90,12 +106,6 @@ int HlswServer::execute(void* arg) len = sizeof(src); 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))) { LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet"); continue; @@ -108,23 +118,27 @@ int HlswServer::execute(void* arg) return 0; } -void HlswServer::rebuild(GameList& glist) { - Iterator* 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; - delete it; +void HlswServer::rebuild(GameList& glist) { + if (glist.getLastUpdate() > lastUpdate) { + HlswPacket* newlist = new HlswPacket(NULL); + + Iterator* 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; + } } diff --git a/hlswserver.h b/hlswserver.h index b704c2d..9d13c49 100644 --- a/hlswserver.h +++ b/hlswserver.h @@ -10,18 +10,29 @@ class HlswServer : public Thread { public: - HlswServer(Config& conf); + HlswServer(Config& conf, GameList& glist); ~HlswServer(); int execute(void* arg); - void rebuild(GameList& glist); + void rebuild(GameList& gl); protected: HlswServer(const HlswServer& hs); HlswServer& operator=(const HlswServer& hs); 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 { public: HlswPacket(HlswPacket* next); @@ -39,6 +50,8 @@ private: HlswPacket* pktlist; Mutex mutex; int sock; + + long lastUpdate; }; #endif // _HLSWSERVER_H_ diff --git a/list.h b/list.h index 655b94b..0d2d6ae 100644 --- a/list.h +++ b/list.h @@ -146,13 +146,13 @@ private: ListIterator(const List* list) : list(list) { - // ((ListBase*)list)->mutex.lock(); + ((List*)list)->mutex.lock(); reset(); } ~ListIterator() { - // ((ListBase*)list)->mutex.unlock(); + ((List*)list)->mutex.unlock(); } bool hasNext() diff --git a/mod_gamespy1.h b/mod_gamespy1.h index 62fd84f..e29ef99 100644 --- a/mod_gamespy1.h +++ b/mod_gamespy1.h @@ -9,7 +9,7 @@ public: ~ModGameSpy1() {} void scan(MultiSock* msock); - int parse(NetPkt* pkt, GameList* slist); + int parse(NetPkt* pkt, GameList* glist); const char* getName() { return "GameSpy 1 Protocol"; } }; diff --git a/mod_gamespy2.h b/mod_gamespy2.h index 004aae7..9a5e0eb 100644 --- a/mod_gamespy2.h +++ b/mod_gamespy2.h @@ -9,7 +9,7 @@ public: ~ModGameSpy2() {} void scan(MultiSock* msock); - int parse(NetPkt* pkt, GameList* slist); + int parse(NetPkt* pkt, GameList* glist); const char* getName() { return "GameSpy 2 Protocol"; } }; diff --git a/mod_halflife.h b/mod_halflife.h index d82519d..73da759 100644 --- a/mod_halflife.h +++ b/mod_halflife.h @@ -9,7 +9,7 @@ public: ~ModHalfLife() {} void scan(MultiSock* msock); - int parse(NetPkt* pkt, GameList* slist); + int parse(NetPkt* pkt, GameList* glist); const char* getName() { return "HalfLife engine"; } }; diff --git a/mod_q3engine.cpp b/mod_q3engine.cpp index f936e89..6fa2043 100644 --- a/mod_q3engine.cpp +++ b/mod_q3engine.cpp @@ -1,23 +1,86 @@ #include + +#include "logging.h" #include "mod_q3engine.h" static struct game_ports port_arr[] = { { 27960, 27969, ID_Q3A }, // q3(6), ef(7), et25), rtcw(8) - { 28070, 28070, ID_JK2 }, // jk2(12) - { 28960, 28963, ID_COD }, // cod(31), cod:uo(42), cod2(48) - { 29070, 29070, ID_JK3 }, // jk3(27) +// { 28070, 28070, ID_JK2 }, // jk2(12) +// { 28960, 28963, ID_COD }, // cod(31), cod:uo(42), cod2(48) +// { 29070, 29070, ID_JK3 }, // jk3(27) { 0,0,0 } }; static const char scanmsg[] = "\xff\xff\xff\xffgetStatus"; 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) { 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; } diff --git a/mod_q3engine.h b/mod_q3engine.h index 28c6142..ff17f49 100644 --- a/mod_q3engine.h +++ b/mod_q3engine.h @@ -9,7 +9,7 @@ public: ~ModQ3Engine() {} void scan(MultiSock* msock); - int parse(NetPkt* pkt, GameList* slist); + int parse(NetPkt* pkt, GameList* glist); const char* getName() { return "Quake3 engine"; } }; diff --git a/netpkt.cpp b/netpkt.cpp index 8c3a833..ed21da0 100644 --- a/netpkt.cpp +++ b/netpkt.cpp @@ -78,3 +78,13 @@ bool NetPkt::compare(int offset, const char* buf, int len) 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); +} diff --git a/netpkt.h b/netpkt.h index 2dfbce1..3b8a4ee 100644 --- a/netpkt.h +++ b/netpkt.h @@ -17,6 +17,7 @@ public: int checkPortArray(struct game_ports* arr); bool compare(int offset, const char* buf, int len); + int find(int offset, const char *buf, int len); protected: NetPkt(const NetPkt& x); diff --git a/timerservice.cpp b/timerservice.cpp index eb80af0..0935c25 100644 --- a/timerservice.cpp +++ b/timerservice.cpp @@ -2,14 +2,14 @@ #include "timerservice.h" -Timer::Timer(Command* cmd, unsigned int timeval) -: next(0), cmd(cmd), timeval(timeval) +Timer::Timer(Event* event, unsigned int timeval) +: next(0), event(event), timeval(timeval) { } Timer::~Timer() { - delete cmd; + delete event; } TimerService::~TimerService() @@ -39,7 +39,7 @@ void TimerService::checkTimeouts() long now = time(NULL); Timer* search = firstTimer; while (search != NULL && search->timeout <= now) { - search->cmd->execute(); + search->event->execute(); firstTimer = search->next; addTimer(search, false); diff --git a/timerservice.h b/timerservice.h index 1bb11db..6f33bf3 100644 --- a/timerservice.h +++ b/timerservice.h @@ -3,19 +3,19 @@ #include "mutex.h" -class Command { +class Event { public: - virtual ~Command() {}; + virtual ~Event() {}; virtual void execute() =0; protected: - Command() {}; + Event() {}; }; class Timer { friend class TimerService; public: - Timer(Command* cmd, unsigned int timeval); + Timer(Event* event, unsigned int timeval); ~Timer(); protected: @@ -24,7 +24,7 @@ protected: private: Timer* next; - Command* cmd; + Event* event; int timeval; long timeout; };