get it working
This commit is contained in:
parent
c4df94c900
commit
17f64ec0f9
|
@ -3,3 +3,5 @@
|
||||||
hlswmaster
|
hlswmaster
|
||||||
hlswmaster.log
|
hlswmaster.log
|
||||||
doc/*
|
doc/*
|
||||||
|
masterquery
|
||||||
|
hlswmaster-ng.tar.gz
|
||||||
|
|
24
Makefile
24
Makefile
|
@ -1,8 +1,9 @@
|
||||||
CFLAGS := -O2 -pipe -Wall -Wunused -Wno-deprecated
|
CFLAGS := -O2 -pipe -Wall
|
||||||
|
CXXFLAGS := -O2 -pipe -Wall -Wunused -Wno-deprecated
|
||||||
LIBS := -lpthread
|
LIBS := -lpthread
|
||||||
|
|
||||||
HLSWMASTER_SRC := config.o gameentry.o gamelist.o gameparser.o gamescanner.o \
|
HLSWMASTER_SRC := config.o gameentry.o gamelist.o gameparser.o gamescanner.o \
|
||||||
hlswmaster.o hlswserver.o list.o logging.o modhelper.o modulelist.o \
|
hlswmaster.o hlswserver.o logging.o modhelper.o modulelist.o \
|
||||||
multisock.o netpkt.o recvqueue.o socket.o timerservice.o thread.o \
|
multisock.o netpkt.o recvqueue.o socket.o timerservice.o thread.o \
|
||||||
mod_d3engine.o mod_gamespy1.o mod_gamespy2.o mod_halflife.o \
|
mod_d3engine.o mod_gamespy1.o mod_gamespy2.o mod_halflife.o \
|
||||||
mod_hlswproxy.o mod_q3engine.o mod_quake2.o mod_ut.o
|
mod_hlswproxy.o mod_q3engine.o mod_quake2.o mod_ut.o
|
||||||
|
@ -10,22 +11,29 @@ HLSWMASTER_SRC := config.o gameentry.o gamelist.o gameparser.o gamescanner.o \
|
||||||
all: hlswmaster masterquery
|
all: hlswmaster masterquery
|
||||||
|
|
||||||
hlswmaster: $(HLSWMASTER_SRC) hlswmaster.o
|
hlswmaster: $(HLSWMASTER_SRC) hlswmaster.o
|
||||||
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
|
$(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@
|
||||||
|
|
||||||
masterquery: masterquery.o
|
masterquery: masterquery.o
|
||||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
$(CXX) $(CFLAGS) -c $< -o $@
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
%.d: %.cpp
|
%.d: %.cpp
|
||||||
$(CXX) $(CFLAGS) -MM -c $< -o $@
|
$(CXX) $(CXXFLAGS) -MM -c $< -o $@
|
||||||
|
|
||||||
dist:
|
dist: clean
|
||||||
git-tar-tree HEAD hlswmaster-ng | gzip -9 -c > hlswmaster-ng.tar.gz
|
ln -s . hlswmaster-ng
|
||||||
|
tar -czhf hlswmaster-ng.tar.gz hlswmaster-ng/ \
|
||||||
|
--exclude hlswmaster-ng/.git \
|
||||||
|
--exclude hlswmaster-ng/.gitignore \
|
||||||
|
--exclude hlswmaster-ng/hlswmaster-ng.tar.gz \
|
||||||
|
--exclude hlswmaster-ng/hlswmaster-ng
|
||||||
|
rm hlswmaster-ng
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f hlswmaster masterquery *.d *.o *.log
|
rm -f hlswmaster masterquery *.d *.o *.log \
|
||||||
|
hlswmaster-ng hlswmaster-ng.tar.gz
|
||||||
|
|
||||||
##DEPS := $(wildcard *.cpp)
|
##DEPS := $(wildcard *.cpp)
|
||||||
##-include $(DEPS:.cpp=.d)
|
##-include $(DEPS:.cpp=.d)
|
||||||
|
|
18
config.cpp
18
config.cpp
|
@ -42,12 +42,12 @@ bool Config::Section::addTupel(const char* name, const char* value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Tupel* t = new Tupel(name, value);
|
Tupel* t = new Tupel(name, value);
|
||||||
tupelList.addTail(t);
|
tupelList.add(t);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::Section::show() const
|
void Config::Section::show()
|
||||||
{
|
{
|
||||||
Iterator<Tupel>* it = tupelList.createIterator();
|
Iterator<Tupel>* it = tupelList.createIterator();
|
||||||
LogSystem::log(LOG_INFO, "[%s]", name);
|
LogSystem::log(LOG_INFO, "[%s]", name);
|
||||||
|
@ -60,7 +60,7 @@ void Config::Section::show() const
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Config::Section::getTupelValue(const char* name) const
|
const char* Config::Section::getTupelValue(const char* name)
|
||||||
{
|
{
|
||||||
const char* retval = 0;
|
const char* retval = 0;
|
||||||
Iterator<Tupel>* it = this->tupelList.createIterator();
|
Iterator<Tupel>* it = this->tupelList.createIterator();
|
||||||
|
@ -121,7 +121,7 @@ Config::~Config()
|
||||||
Config::Section* Config::addSection(const char* name)
|
Config::Section* Config::addSection(const char* name)
|
||||||
{
|
{
|
||||||
Section* s = new Section(name);
|
Section* s = new Section(name);
|
||||||
sectionList.addTail(s);
|
sectionList.add(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ bool Config::parseFile(const char* name)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::show() const
|
void Config::show()
|
||||||
{
|
{
|
||||||
LogSystem::log(LOG_INFO, "Config Dump:");
|
LogSystem::log(LOG_INFO, "Config Dump:");
|
||||||
Iterator<Section>* it = sectionList.createIterator();
|
Iterator<Section>* it = sectionList.createIterator();
|
||||||
|
@ -194,7 +194,7 @@ void Config::show() const
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Section* Config::getSection(const char* name) const
|
Config::Section* Config::getSection(const char* name)
|
||||||
{
|
{
|
||||||
Section* retval = 0;
|
Section* retval = 0;
|
||||||
|
|
||||||
|
@ -211,13 +211,13 @@ Config::Section* Config::getSection(const char* name) const
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Config::getParameter(const char* section, const char* option) const
|
const char* Config::getParameter(const char* section, const char* option)
|
||||||
{
|
{
|
||||||
Section* s = getSection(section);
|
Section* s = getSection(section);
|
||||||
return s ? s->getTupelValue(option) : 0;
|
return s ? s->getTupelValue(option) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Config::getString(const char* section, const char* option, char* def) const
|
const char* Config::getString(const char* section, const char* option, char* def)
|
||||||
{
|
{
|
||||||
const char* retval = getParameter(section, option);
|
const char* retval = getParameter(section, option);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
|
@ -229,7 +229,7 @@ const char* Config::getString(const char* section, const char* option, char* def
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Config::getInteger(const char* section, const char* option, int def) const
|
int Config::getInteger(const char* section, const char* option, int def)
|
||||||
{
|
{
|
||||||
const char* retval = getParameter(section, option);
|
const char* retval = getParameter(section, option);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
|
|
18
config.h
18
config.h
|
@ -8,16 +8,16 @@ public:
|
||||||
~Config();
|
~Config();
|
||||||
|
|
||||||
bool parseFile(const char* name);
|
bool parseFile(const char* name);
|
||||||
void show() const;
|
void show();
|
||||||
|
|
||||||
const char* getParameter(const char* section, const char* name) const;
|
const char* getParameter(const char* section, const char* name);
|
||||||
const char* getString(const char* section, const char* name, char* def) const;
|
const char* getString(const char* section, const char* name, char* def);
|
||||||
int getInteger(const char* section, const char* name, int def) const;
|
int getInteger(const char* section, const char* name, int def);
|
||||||
|
|
||||||
Iterator<char>* createIterator(const char* section, const char* name);
|
Iterator<char>* createIterator(const char* section, const char* name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Tupel {
|
class Tupel : private ListEntry<Tupel> {
|
||||||
public:
|
public:
|
||||||
Tupel(const char* name, const char* value);
|
Tupel(const char* name, const char* value);
|
||||||
~Tupel();
|
~Tupel();
|
||||||
|
@ -26,7 +26,7 @@ private:
|
||||||
const char* value;
|
const char* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Section {
|
class Section : private ListEntry<Section> {
|
||||||
public:
|
public:
|
||||||
class SectionIterator : public Iterator<char> {
|
class SectionIterator : public Iterator<char> {
|
||||||
public:
|
public:
|
||||||
|
@ -47,8 +47,8 @@ private:
|
||||||
~Section();
|
~Section();
|
||||||
|
|
||||||
bool addTupel(const char* name, const char* option);
|
bool addTupel(const char* name, const char* option);
|
||||||
const char* getTupelValue(const char* name) const;
|
const char* getTupelValue(const char* name);
|
||||||
void show() const;
|
void show();
|
||||||
|
|
||||||
const char* name;
|
const char* name;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
Section* addSection(const char* name);
|
Section* addSection(const char* name);
|
||||||
Section* getSection(const char* name) const;
|
Section* getSection(const char* name);
|
||||||
|
|
||||||
List<Section> sectionList;
|
List<Section> sectionList;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,24 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "gameentry.h"
|
#include "gameentry.h"
|
||||||
|
|
||||||
|
GameEntry::GameEntry(int gameid, NetPkt* pkt, int port2)
|
||||||
|
: port2(port2), gameid(gameid)
|
||||||
|
{
|
||||||
|
memcpy(&addr, &pkt->getAddress()->sin_addr, sizeof(addr));
|
||||||
|
this->port1 = pkt->getPort();
|
||||||
|
|
||||||
|
if (port2 != 0) {
|
||||||
|
this->port2 = this->port1;
|
||||||
|
this->port1 = port2;
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
int GameEntry::compare(const GameEntry* ge)
|
int GameEntry::compare(const GameEntry* ge)
|
||||||
{
|
{
|
||||||
if (this->addr.s_addr > ge->addr.s_addr)
|
if (this->addr.s_addr > ge->addr.s_addr)
|
||||||
|
@ -14,5 +33,36 @@ int GameEntry::compare(const GameEntry* ge)
|
||||||
if (this->port1 < ge->port1)
|
if (this->port1 < ge->port1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
// only compare IP:port
|
||||||
|
// gameid and port2 are useless
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GameEntry::hash(int max)
|
||||||
|
{
|
||||||
|
unsigned int hash = 0x12345678;
|
||||||
|
|
||||||
|
// IP
|
||||||
|
hash = ((hash<<5) ^ (hash>>27)) ^ ((addr.s_addr>>0) & 0xFF);
|
||||||
|
hash = ((hash<<5) ^ (hash>>27)) ^ ((addr.s_addr>>8) & 0xFF);
|
||||||
|
hash = ((hash<<5) ^ (hash>>27)) ^ ((addr.s_addr>>16) & 0xFF);
|
||||||
|
hash = ((hash<<5) ^ (hash>>27)) ^ ((addr.s_addr>>24) & 0xFF);
|
||||||
|
|
||||||
|
// port
|
||||||
|
hash = ((hash<<5) ^ (hash>>27)) ^ ((port1>>0) & 0xFF);
|
||||||
|
hash = ((hash<<5) ^ (hash>>27)) ^ ((port1>>8) & 0xFF);
|
||||||
|
|
||||||
|
return hash % max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEntry::update()
|
||||||
|
{
|
||||||
|
modtime = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameEntry::show(char* buf, int size)
|
||||||
|
{
|
||||||
|
return snprintf(buf, size, "(%2d:%15s:%5d:%5d)",
|
||||||
|
this->gameid, inet_ntoa(this->addr),
|
||||||
|
this->port1, this->port2);
|
||||||
|
}
|
||||||
|
|
12
gameentry.h
12
gameentry.h
|
@ -4,12 +4,18 @@
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
class GameEntry {
|
#include "netpkt.h"
|
||||||
|
|
||||||
|
class GameEntry : private ListEntry<GameEntry> {
|
||||||
public:
|
public:
|
||||||
GameEntry() {};
|
GameEntry(int gameid, NetPkt* pkt, int port2);
|
||||||
~GameEntry() {};
|
~GameEntry() {}
|
||||||
|
|
||||||
int compare(const GameEntry* ge);
|
int compare(const GameEntry* ge);
|
||||||
|
int hash(int max);
|
||||||
|
void update();
|
||||||
|
|
||||||
|
int show(char* buf, int size);
|
||||||
|
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
int port1;
|
int port1;
|
||||||
|
|
118
gamelist.cpp
118
gamelist.cpp
|
@ -3,43 +3,123 @@
|
||||||
|
|
||||||
#define DEFAULT_TIMEOUT 180
|
#define DEFAULT_TIMEOUT 180
|
||||||
|
|
||||||
/*
|
|
||||||
** TODO: replace list with sorted list, or even better with a hash
|
|
||||||
*/
|
|
||||||
|
|
||||||
GameList::GameList(Config& conf)
|
GameList::GameList(Config& conf)
|
||||||
: lastUpdate(0)
|
|
||||||
{
|
{
|
||||||
int interval = conf.getInteger("global", "game_timeout", DEFAULT_TIMEOUT);
|
timeout = conf.getInteger("global", "game_timeout", DEFAULT_TIMEOUT);
|
||||||
TimerService::registerTimer(new Timer(new CleanupEvent(*this), interval));
|
TimerService::registerTimer(new Timer(new CleanupEvent(*this), timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
GameList::~GameList()
|
GameList::~GameList()
|
||||||
{
|
{
|
||||||
while (!glist.isEmpty())
|
Iterator<GameEntry>* it = createIterator();
|
||||||
delete glist.get();
|
while (it->hasNext())
|
||||||
|
delete it->next();
|
||||||
|
|
||||||
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::cleanup()
|
void GameList::cleanup()
|
||||||
{
|
{
|
||||||
|
long now = time(NULL);
|
||||||
|
|
||||||
|
Iterator<GameEntry>* it = createIterator();
|
||||||
|
while (it->hasNext()) {
|
||||||
|
GameEntry* ge = it->next();
|
||||||
|
|
||||||
|
if (ge->modtime + timeout <= now) {
|
||||||
|
it->remove();
|
||||||
|
|
||||||
|
char buf[64];
|
||||||
|
ge->show(buf, sizeof(buf));
|
||||||
|
LogSystem::log(LOG_NOTICE, "Game Timeout: %s", buf);
|
||||||
|
delete ge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
long GameList::getLastUpdate()
|
void GameList::addGame(int gameid, NetPkt* pkt, int port2)
|
||||||
{
|
{
|
||||||
return lastUpdate;
|
GameEntry* ge = new GameEntry(gameid, pkt, port2);
|
||||||
|
int hash = ge->hash(MAX_BUCKETS);
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
Iterator<GameEntry>* it = buckets[hash].createIterator();
|
||||||
|
while (it->hasNext()) {
|
||||||
|
GameEntry* tmp = it->next();
|
||||||
|
if (ge->compare(tmp) == 0) {
|
||||||
|
tmp->update();
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
char buf[64];
|
||||||
|
ge->show(buf, sizeof(buf));
|
||||||
|
LogSystem::log(LOG_NOTICE, "Adding Game : %s", buf);
|
||||||
|
|
||||||
|
buckets[hash].add(ge);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
delete ge;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it holds the lock!
|
||||||
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<GameEntry>* GameList::createIterator()
|
Iterator<GameEntry>* GameList::createIterator()
|
||||||
{
|
{
|
||||||
return glist.createIterator();
|
return new GameListIterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::addGame(int gameid, NetPkt* pkt, int port2, bool swap)
|
|
||||||
|
GameList::GameListIterator::GameListIterator(GameList* gl)
|
||||||
|
: gl(gl), it(0)
|
||||||
{
|
{
|
||||||
char buf[64];
|
gl->mutex.lock();
|
||||||
pkt->show(buf, sizeof(buf));
|
reset();
|
||||||
LogSystem::log(LOG_NOTICE, "Adding Game %d: %s", gameid, buf);
|
}
|
||||||
|
|
||||||
glist.add(new GameEntry());
|
GameList::GameListIterator::~GameListIterator()
|
||||||
lastUpdate++;
|
{
|
||||||
|
delete it;
|
||||||
|
gl->mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameList::GameListIterator::hasNext()
|
||||||
|
{
|
||||||
|
if (it->hasNext())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
while (bucket < MAX_BUCKETS -1) {
|
||||||
|
delete it;
|
||||||
|
bucket++;
|
||||||
|
|
||||||
|
it = gl->buckets[bucket].createIterator();
|
||||||
|
if (it->hasNext())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEntry* GameList::GameListIterator::next()
|
||||||
|
{
|
||||||
|
return it->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::GameListIterator::remove()
|
||||||
|
{
|
||||||
|
it->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::GameListIterator::reset()
|
||||||
|
{
|
||||||
|
if (it != NULL)
|
||||||
|
delete it;
|
||||||
|
|
||||||
|
bucket = 0;
|
||||||
|
it = gl->buckets[bucket].createIterator();
|
||||||
}
|
}
|
||||||
|
|
33
gamelist.h
33
gamelist.h
|
@ -6,18 +6,19 @@
|
||||||
#include "gameentry.h"
|
#include "gameentry.h"
|
||||||
#include "timerservice.h"
|
#include "timerservice.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
// 127 is prime!
|
||||||
|
#define MAX_BUCKETS 127
|
||||||
|
|
||||||
class GameList {
|
class GameList {
|
||||||
public:
|
public:
|
||||||
GameList(Config& conf);
|
GameList(Config& conf);
|
||||||
~GameList();
|
~GameList();
|
||||||
|
|
||||||
void addGame(int gameid, NetPkt* pkt, int port2 = 0, bool swap = false);
|
|
||||||
|
|
||||||
long getLastUpdate();
|
|
||||||
Iterator<GameEntry>* createIterator();
|
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
void addGame(int gameid, NetPkt* pkt, int port2 = 0);
|
||||||
|
Iterator<GameEntry>* createIterator();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GameList(const GameList& gl);
|
GameList(const GameList& gl);
|
||||||
|
@ -34,8 +35,26 @@ private:
|
||||||
GameList& gl;
|
GameList& gl;
|
||||||
};
|
};
|
||||||
|
|
||||||
List<GameEntry> glist;
|
class GameListIterator : public Iterator<GameEntry> {
|
||||||
long lastUpdate;
|
public:
|
||||||
|
GameListIterator(GameList* gl);
|
||||||
|
~GameListIterator();
|
||||||
|
|
||||||
|
bool hasNext();
|
||||||
|
GameEntry* next();
|
||||||
|
void remove();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GameList* gl;
|
||||||
|
Iterator<GameEntry>* it;
|
||||||
|
int bucket;
|
||||||
|
};
|
||||||
|
|
||||||
|
Mutex mutex;
|
||||||
|
List<GameEntry> buckets[MAX_BUCKETS];
|
||||||
|
|
||||||
|
int timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _GAMELIST_H_
|
#endif // _GAMELIST_H_
|
||||||
|
|
|
@ -35,7 +35,7 @@ int GameParser::execute(void* arg)
|
||||||
|
|
||||||
p = pkt->showfull();
|
p = pkt->showfull();
|
||||||
LogSystem::log(LOG_DEBUG, "%s", p);
|
LogSystem::log(LOG_DEBUG, "%s", p);
|
||||||
delete p;
|
delete [] p;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
scan_port 7130
|
scan_port 7130
|
||||||
|
|
||||||
# broadcast scan every X seconds
|
# broadcast scan every X seconds
|
||||||
scan_interval 30
|
scan_interval 60
|
||||||
|
|
||||||
# use this interface(s)
|
# use this interface(s)
|
||||||
scan_deny_iface
|
scan_deny_iface
|
||||||
|
|
||||||
# server timeout after X seconds
|
# server timeout after X seconds
|
||||||
game_timeout 30
|
game_timeout 180
|
||||||
|
|
||||||
# master answers with this source IP
|
# master answers with this source IP
|
||||||
master_ip 0.0.0.0
|
master_ip 0.0.0.0
|
||||||
|
@ -20,6 +20,3 @@ rebuild_interval 5
|
||||||
# logging
|
# logging
|
||||||
logfile hlswmaster.log
|
logfile hlswmaster.log
|
||||||
logprio DEBUG
|
logprio DEBUG
|
||||||
|
|
||||||
[hlswproxy]
|
|
||||||
master_ip 10.10.0.30 10.10.0.31
|
|
||||||
|
|
|
@ -33,6 +33,11 @@ static struct option opts[] = {
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
LogSystem::init(DEFAULT_LOGPRIO, new StdErrLog());
|
LogSystem::init(DEFAULT_LOGPRIO, new StdErrLog());
|
||||||
|
|
105
hlswserver.cpp
105
hlswserver.cpp
|
@ -22,45 +22,7 @@ struct hlsw_entry {
|
||||||
#define HLSW_MAX_PACKET_SIZE (sizeof(hlsw_header) + 140 * sizeof(struct hlsw_entry))
|
#define HLSW_MAX_PACKET_SIZE (sizeof(hlsw_header) + 140 * sizeof(struct hlsw_entry))
|
||||||
#define DEFAULT_REBUILD_INTERVAL 5
|
#define DEFAULT_REBUILD_INTERVAL 5
|
||||||
|
|
||||||
HlswServer::HlswPacket::HlswPacket(HlswPacket* next)
|
|
||||||
: NetPkt(HLSW_MAX_PACKET_SIZE), next(next)
|
|
||||||
{
|
|
||||||
memcpy((void*)data, hlsw_header, sizeof(hlsw_header));
|
|
||||||
size = sizeof(hlsw_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
HlswServer::HlswPacket::~HlswPacket()
|
|
||||||
{
|
|
||||||
if (next)
|
|
||||||
delete next;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HlswServer::HlswPacket::addGame(GameEntry* ge)
|
|
||||||
{
|
|
||||||
if (size >= HLSW_MAX_PACKET_SIZE)
|
|
||||||
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((void*)(data + size), &tmp, sizeof(tmp));
|
|
||||||
size += sizeof(tmp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HlswServer::HlswPacket::send(Socket* socket, struct sockaddr_in* dst)
|
|
||||||
{
|
|
||||||
if (next)
|
|
||||||
next->send(socket, dst);
|
|
||||||
|
|
||||||
socket->sendto(this, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
HlswServer::HlswServer(Config& conf, GameList& glist)
|
HlswServer::HlswServer(Config& conf, GameList& glist)
|
||||||
: lastUpdate(0)
|
|
||||||
{
|
{
|
||||||
const char *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);
|
||||||
|
@ -74,11 +36,14 @@ HlswServer::HlswServer(Config& conf, GameList& glist)
|
||||||
int interval = conf.getInteger("global", "rebuild_interval", DEFAULT_REBUILD_INTERVAL);
|
int interval = conf.getInteger("global", "rebuild_interval", DEFAULT_REBUILD_INTERVAL);
|
||||||
TimerService::registerTimer(new Timer(new RebuildEvent(*this, glist), interval));
|
TimerService::registerTimer(new Timer(new RebuildEvent(*this, glist), interval));
|
||||||
|
|
||||||
pktlist = new HlswPacket(NULL);
|
pktlist = new List<NetPkt>();
|
||||||
}
|
}
|
||||||
|
|
||||||
HlswServer::~HlswServer()
|
HlswServer::~HlswServer()
|
||||||
{
|
{
|
||||||
|
while (!pktlist->isEmpty())
|
||||||
|
delete pktlist->get();
|
||||||
|
|
||||||
delete pktlist;
|
delete pktlist;
|
||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
@ -87,39 +52,61 @@ int HlswServer::execute(void* arg)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
NetPkt* pkt = socket->recv();
|
NetPkt* pkt = socket->recv();
|
||||||
if (!pkt->compare(0, hlsw_header, sizeof(hlsw_header))) {
|
if (!pkt->compare(0, hlsw_header, strlen(hlsw_header))) {
|
||||||
LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet");
|
LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
pktlist->send(socket, pkt->getAddress());
|
Iterator<NetPkt>* it = pktlist->createIterator();
|
||||||
mutex.unlock();
|
while (it->hasNext())
|
||||||
|
socket->sendto(it->next(), pkt->getAddress());
|
||||||
|
|
||||||
|
delete it;
|
||||||
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlswServer::rebuild(GameList& glist) {
|
void HlswServer::rebuild(GameList& glist) {
|
||||||
if (glist.getLastUpdate() > lastUpdate) {
|
List<NetPkt>* newlist = new List<NetPkt>();
|
||||||
HlswPacket* newlist = new HlswPacket(NULL);
|
|
||||||
|
|
||||||
Iterator<GameEntry>* it = glist.createIterator();
|
// header
|
||||||
while (it->hasNext()) {
|
NetPkt* pkt = new NetPkt(HLSW_MAX_PACKET_SIZE);
|
||||||
GameEntry* d = it->next();
|
pkt->append(hlsw_header, sizeof(hlsw_header));
|
||||||
if (!newlist->addGame(d)) {
|
newlist->add(pkt);
|
||||||
newlist = new HlswPacket(newlist);
|
|
||||||
newlist->addGame(d);
|
Iterator<GameEntry>* it = glist.createIterator();
|
||||||
}
|
while (it->hasNext()) {
|
||||||
|
NetPkt* last = newlist->peekTail();
|
||||||
|
if (last->getSize() == HLSW_MAX_PACKET_SIZE) {
|
||||||
|
last = new NetPkt(HLSW_MAX_PACKET_SIZE);
|
||||||
|
last->append(hlsw_header, sizeof(hlsw_header));
|
||||||
|
newlist->add(last);
|
||||||
}
|
}
|
||||||
lastUpdate = glist.getLastUpdate();
|
|
||||||
delete it;
|
|
||||||
|
|
||||||
mutex.lock();
|
addGame(last, it->next());
|
||||||
HlswPacket* oldlist = pktlist;
|
|
||||||
pktlist = newlist;
|
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
delete oldlist;
|
|
||||||
}
|
}
|
||||||
|
delete it;
|
||||||
|
|
||||||
|
mutex.lock();
|
||||||
|
List<NetPkt>* oldlist = pktlist;
|
||||||
|
pktlist = newlist;
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
while (!oldlist->isEmpty())
|
||||||
|
delete oldlist->get();
|
||||||
|
|
||||||
|
delete oldlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HlswServer::addGame(NetPkt* pkt, GameEntry* entry)
|
||||||
|
{
|
||||||
|
struct hlsw_entry tmp;
|
||||||
|
tmp.gameid = entry->gameid;
|
||||||
|
tmp.ip = entry->addr.s_addr;
|
||||||
|
tmp.port1 = entry->port1;
|
||||||
|
tmp.port2 = entry->port2;
|
||||||
|
|
||||||
|
pkt->append((char*)&tmp, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
18
hlswserver.h
18
hlswserver.h
|
@ -34,23 +34,11 @@ private:
|
||||||
GameList& gl;
|
GameList& gl;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HlswPacket : private NetPkt {
|
void addGame(NetPkt* pkt, GameEntry* entry);
|
||||||
public:
|
|
||||||
HlswPacket(HlswPacket* next);
|
|
||||||
~HlswPacket();
|
|
||||||
|
|
||||||
bool addGame(GameEntry* ge);
|
List<NetPkt>* pktlist;
|
||||||
void send(Socket* socket, struct sockaddr_in* dst);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HlswPacket* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
Socket* socket;
|
|
||||||
HlswPacket* pktlist;
|
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
|
Socket* socket;
|
||||||
long lastUpdate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _HLSWSERVER_H_
|
#endif // _HLSWSERVER_H_
|
||||||
|
|
150
list.cpp
150
list.cpp
|
@ -1,150 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "list.h"
|
|
||||||
|
|
||||||
ListBase::ListBase()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::~ListBase()
|
|
||||||
{
|
|
||||||
AutoMutex am(mutex);
|
|
||||||
while(!head.isEmpty())
|
|
||||||
head.getNext()->del();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListBase::add(const void* part)
|
|
||||||
{
|
|
||||||
ListEntryBase* entry = new ListEntryBase(part);
|
|
||||||
|
|
||||||
AutoMutex am(mutex);
|
|
||||||
entry->add(&head, head.getNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListBase::addTail(const void* part)
|
|
||||||
{
|
|
||||||
ListEntryBase* entry = new ListEntryBase(part);
|
|
||||||
|
|
||||||
AutoMutex am(mutex);
|
|
||||||
entry->add(head.getPrev(), &head);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* ListBase::get()
|
|
||||||
{
|
|
||||||
AutoMutex am(mutex);
|
|
||||||
ListEntryBase* entry = head.getNext();
|
|
||||||
void* retval = entry->getPart();
|
|
||||||
|
|
||||||
if (!head.isEmpty()) {
|
|
||||||
entry->del();
|
|
||||||
delete entry;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* ListBase::getTail()
|
|
||||||
{
|
|
||||||
AutoMutex am(mutex);
|
|
||||||
ListEntryBase* entry = head.getPrev();
|
|
||||||
void* retval = entry->getPart();
|
|
||||||
|
|
||||||
if (!head.isEmpty()) {
|
|
||||||
entry->del();
|
|
||||||
delete entry;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ListBase::isEmpty() const
|
|
||||||
{
|
|
||||||
AutoMutex am((Mutex&)mutex);
|
|
||||||
return head.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
IteratorBase* ListBase::createIterator()
|
|
||||||
{
|
|
||||||
return new ListIteratorBase(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::ListEntryBase::ListEntryBase(const void* part)
|
|
||||||
: prev(this), next(this), part(part)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::ListEntryBase::~ListEntryBase()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListBase::ListEntryBase::add(ListEntryBase* prev_, ListEntryBase* next_)
|
|
||||||
{
|
|
||||||
this->next = next_;
|
|
||||||
this->prev = prev_;
|
|
||||||
next_->prev = this;
|
|
||||||
prev_->next = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListBase::ListEntryBase::del()
|
|
||||||
{
|
|
||||||
next->prev = prev;
|
|
||||||
prev->next = next;
|
|
||||||
next = prev = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ListBase::ListEntryBase::isEmpty() const
|
|
||||||
{
|
|
||||||
return (this->prev == this) && (this->next == this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* ListBase::ListEntryBase::getPart() const
|
|
||||||
{
|
|
||||||
// const void* -> void*
|
|
||||||
return (void*)part;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::ListEntryBase* ListBase::ListEntryBase::getPrev() const
|
|
||||||
{
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::ListEntryBase* ListBase::ListEntryBase::getNext() const
|
|
||||||
{
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::ListIteratorBase::ListIteratorBase(ListBase* list)
|
|
||||||
: list(list)
|
|
||||||
{
|
|
||||||
list->mutex.lock();
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
ListBase::ListIteratorBase::~ListIteratorBase()
|
|
||||||
{
|
|
||||||
list->mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ListBase::ListIteratorBase::hasNext()
|
|
||||||
{
|
|
||||||
return (pos->getNext() != &list->head);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* ListBase::ListIteratorBase::next()
|
|
||||||
{
|
|
||||||
pos = pos->getNext();
|
|
||||||
return pos->getPart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListBase::ListIteratorBase::remove()
|
|
||||||
{
|
|
||||||
ListEntryBase* tmp = pos->getPrev();
|
|
||||||
pos->del();
|
|
||||||
pos = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListBase::ListIteratorBase::reset()
|
|
||||||
{
|
|
||||||
pos = &list->head;
|
|
||||||
}
|
|
||||||
|
|
314
list.h
314
list.h
|
@ -3,141 +3,229 @@
|
||||||
|
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
|
|
||||||
class IteratorBase {
|
|
||||||
public:
|
|
||||||
virtual ~IteratorBase() {}
|
|
||||||
virtual bool hasNext() =0;
|
|
||||||
virtual void* next() =0;
|
|
||||||
virtual void remove() =0;
|
|
||||||
virtual void reset() =0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
IteratorBase() {}
|
|
||||||
IteratorBase(const IteratorBase& it);
|
|
||||||
IteratorBase& operator=(const IteratorBase& it);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ListBase {
|
|
||||||
public:
|
|
||||||
ListBase();
|
|
||||||
~ListBase();
|
|
||||||
|
|
||||||
void add(const void* part);
|
|
||||||
void addTail(const void* part);
|
|
||||||
void* get();
|
|
||||||
void* getTail();
|
|
||||||
bool isEmpty() const;
|
|
||||||
|
|
||||||
IteratorBase* createIterator();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ListBase(const ListBase& l);
|
|
||||||
ListBase& operator=(const ListBase& l);
|
|
||||||
|
|
||||||
class ListEntryBase {
|
|
||||||
public:
|
|
||||||
ListEntryBase(const void* part = 0);
|
|
||||||
~ListEntryBase();
|
|
||||||
|
|
||||||
void add(ListEntryBase* prev, ListEntryBase* next);
|
|
||||||
void del();
|
|
||||||
bool isEmpty() const;
|
|
||||||
|
|
||||||
void* getPart() const;
|
|
||||||
ListEntryBase* getPrev() const;
|
|
||||||
ListEntryBase* getNext() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ListEntryBase(const ListEntryBase& l);
|
|
||||||
ListEntryBase& operator=(const ListEntryBase& l);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ListEntryBase* prev;
|
|
||||||
ListEntryBase* next;
|
|
||||||
const void* part;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ListIteratorBase : public IteratorBase {
|
|
||||||
public:
|
|
||||||
ListIteratorBase(ListBase* list);
|
|
||||||
~ListIteratorBase();
|
|
||||||
|
|
||||||
bool hasNext();
|
|
||||||
void* next();
|
|
||||||
void remove();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ListBase* list;
|
|
||||||
ListEntryBase* pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
ListEntryBase head;
|
|
||||||
Mutex mutex;
|
|
||||||
|
|
||||||
friend class ListIteratorBase;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class Iterator : public IteratorBase {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
virtual T* next() =0;
|
virtual ~Iterator() {}
|
||||||
|
virtual bool hasNext() =0;
|
||||||
|
virtual T* next() =0;
|
||||||
|
virtual void remove() =0;
|
||||||
|
virtual void reset() =0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Iterator() {}
|
||||||
|
Iterator(const Iterator& it);
|
||||||
|
Iterator& operator=(const Iterator& it);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class NullIterator : public Iterator<T> {
|
class NullIterator : public Iterator<T> {
|
||||||
public:
|
public:
|
||||||
NullIterator() {}
|
NullIterator() {}
|
||||||
~NullIterator() {}
|
virtual ~NullIterator() {}
|
||||||
|
virtual bool hasNext() { return false; }
|
||||||
bool hasNext() { return false; }
|
virtual T* next() { return NULL; }
|
||||||
T* next() { return NULL; }
|
virtual void remove() {}
|
||||||
void remove() {}
|
virtual void reset() {}
|
||||||
void reset() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class List : public ListBase {
|
class ListEntry;
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class List {
|
||||||
public:
|
public:
|
||||||
List() {}
|
List() : head(0), tail(0) {}
|
||||||
~List() {}
|
~List() {}
|
||||||
|
|
||||||
void add(const T* part) { ListBase::add(part); }
|
void add(T* entry)
|
||||||
void addTail(const T* part) { ListBase::addTail(part); }
|
{
|
||||||
T* get() { return (T*)ListBase::get(); }
|
ListEntry<T>* tmp = (ListEntry<T>*)entry;
|
||||||
T* getTail() { return (T*)ListBase::getTail(); }
|
tmp->next = NULL;
|
||||||
bool isEmpty() const { return ListBase::isEmpty(); }
|
|
||||||
|
|
||||||
Iterator<T>* createIterator() const { return new ListIteratorRO<T>(this); }
|
if (!head)
|
||||||
Iterator<T>* createIteratorRW() { return new ListIteratorRW<T>(this); }
|
head = tmp;
|
||||||
|
|
||||||
|
if (tail)
|
||||||
|
tail->next = tmp;
|
||||||
|
tail = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get()
|
||||||
|
{
|
||||||
|
ListEntry<T>* retval = head;
|
||||||
|
|
||||||
|
if (head)
|
||||||
|
head = head->next;
|
||||||
|
|
||||||
|
if (!head)
|
||||||
|
tail = NULL;
|
||||||
|
|
||||||
|
return (T*)retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* peekHead()
|
||||||
|
{
|
||||||
|
return (T*)head;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* peekTail()
|
||||||
|
{
|
||||||
|
return (T*)tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty()
|
||||||
|
{
|
||||||
|
return (head == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<T>* createIterator()
|
||||||
|
{
|
||||||
|
return new ListIterator<T>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
List(const List& l);
|
||||||
|
List& operator=(const List& l);
|
||||||
|
|
||||||
|
template <class TT>
|
||||||
|
class ListIterator : public Iterator<TT> {
|
||||||
|
public:
|
||||||
|
ListIterator(List<TT>* list)
|
||||||
|
: list(list)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~ListIterator() {}
|
||||||
|
|
||||||
|
virtual bool hasNext()
|
||||||
|
{
|
||||||
|
return (pos == NULL) ? (list->head != NULL) : (pos->next != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual TT* next()
|
||||||
|
{
|
||||||
|
prev = pos;
|
||||||
|
pos = (pos == NULL) ? list->head : pos->next;
|
||||||
|
return (TT*)pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void remove()
|
||||||
|
{
|
||||||
|
// remove pre-head -> bail out
|
||||||
|
if (pos == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove first
|
||||||
|
if (pos == list->head)
|
||||||
|
list->head = pos->next;
|
||||||
|
|
||||||
|
// remove middle
|
||||||
|
if (prev)
|
||||||
|
prev->next = pos->next;
|
||||||
|
|
||||||
|
// remove last
|
||||||
|
if (pos == list->tail)
|
||||||
|
list->tail = (prev == NULL) ? NULL : prev;
|
||||||
|
|
||||||
|
pos = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void reset()
|
||||||
|
{
|
||||||
|
pos = NULL;
|
||||||
|
prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ListIterator(const ListIterator& li);
|
||||||
|
ListIterator& operator=(const ListIterator& li);
|
||||||
|
|
||||||
|
List<TT>* list;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ListEntry<TT>* pos;
|
||||||
|
ListEntry<TT>* prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
ListEntry<T> *head;
|
||||||
|
ListEntry<T> *tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class ListEntry {
|
||||||
|
friend class List<T>;
|
||||||
|
friend class List<T>::ListIterator<T>;
|
||||||
|
public:
|
||||||
|
ListEntry() {}
|
||||||
|
~ListEntry() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ListEntry* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class LockedList : private List<T> {
|
||||||
|
public:
|
||||||
|
LockedList() {}
|
||||||
|
~LockedList() {}
|
||||||
|
void add(T* entry)
|
||||||
|
{
|
||||||
|
AutoMutex am(mutex);
|
||||||
|
List<T>::add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get()
|
||||||
|
{
|
||||||
|
AutoMutex am(mutex);
|
||||||
|
return List<T>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
T* peekFirst()
|
||||||
|
{
|
||||||
|
return NULL; // not with lockedlist
|
||||||
|
}
|
||||||
|
|
||||||
|
T* peekLast()
|
||||||
|
{
|
||||||
|
return NULL; // not with lockedlist
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty()
|
||||||
|
{
|
||||||
|
AutoMutex am(mutex);
|
||||||
|
return List<T>::isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<T>* createIterator()
|
||||||
|
{
|
||||||
|
return new LockedListIterator<T>(this);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class TT>
|
template <class TT>
|
||||||
class ListIteratorRO : public Iterator<TT>, private ListIteratorBase {
|
class LockedListIterator : public List<TT>::ListIterator<TT> {
|
||||||
public:
|
public:
|
||||||
ListIteratorRO(const List<TT>* list) : ListIteratorBase((ListBase*)list) {}
|
LockedListIterator(LockedList<TT>* list)
|
||||||
~ListIteratorRO() {}
|
: List<TT>::ListIterator<TT>(list)
|
||||||
|
{
|
||||||
|
list->mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
bool hasNext() { return ListIteratorBase::hasNext(); }
|
virtual ~LockedListIterator()
|
||||||
TT* next() { return (TT*)ListIteratorBase::next(); }
|
{
|
||||||
void remove() {}
|
((LockedList<TT>*)list)->mutex.unlock();
|
||||||
void reset() { ListIteratorBase::reset(); }
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <class TT>
|
|
||||||
class ListIteratorRW : public Iterator<TT>, private ListIteratorBase {
|
|
||||||
public:
|
|
||||||
ListIteratorRW(List<TT>* list) : ListIteratorBase(list) {}
|
|
||||||
~ListIteratorRW() {}
|
|
||||||
|
|
||||||
bool hasNext() { return ListIteratorBase::hasNext(); }
|
|
||||||
TT* next() { return (TT*)ListIteratorBase::next(); }
|
|
||||||
void remove() { ListIteratorBase::remove(); }
|
|
||||||
void reset() { ListIteratorBase::reset(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_LIST_H_
|
#endif //_LIST_H_
|
||||||
|
|
|
@ -45,11 +45,8 @@ ModGameSpy1::ModGameSpy1()
|
||||||
|
|
||||||
ModGameSpy1::~ModGameSpy1()
|
ModGameSpy1::~ModGameSpy1()
|
||||||
{
|
{
|
||||||
while (!list.isEmpty()) {
|
while (!list.isEmpty())
|
||||||
MultiPart* mp = list.get();
|
delete list.get();
|
||||||
delete mp->pkt;
|
|
||||||
delete mp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModGameSpy1::scan(MultiSock* msock)
|
void ModGameSpy1::scan(MultiSock* msock)
|
||||||
|
@ -98,7 +95,7 @@ int ModGameSpy1::parse(NetPkt* pkt, GameList* glist)
|
||||||
/* non-final multi-part */
|
/* non-final multi-part */
|
||||||
} else if (!final) {
|
} else if (!final) {
|
||||||
LogSystem::log(LOG_DEBUG, "non final %s (%d/%d)", buf, queryid, subid);
|
LogSystem::log(LOG_DEBUG, "non final %s (%d/%d)", buf, queryid, subid);
|
||||||
list.addTail(new MultiPart(pkt, queryid, subid));
|
list.add(new MultiPart(pkt, queryid, subid));
|
||||||
return PARSE_ACCEPT_FREED; // parser must not free pkt
|
return PARSE_ACCEPT_FREED; // parser must not free pkt
|
||||||
|
|
||||||
/* final multipart */
|
/* final multipart */
|
||||||
|
@ -125,9 +122,14 @@ ModGameSpy1::MultiPart::MultiPart(NetPkt* pkt, int queryid, int subid)
|
||||||
timeout = time(NULL) + MODGS1_GC_TIMEOUT;
|
timeout = time(NULL) + MODGS1_GC_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModGameSpy1::MultiPart::~MultiPart()
|
||||||
|
{
|
||||||
|
delete pkt;
|
||||||
|
}
|
||||||
|
|
||||||
NetPkt* ModGameSpy1::merge(NetPkt* pkt, int queryid, int subid)
|
NetPkt* ModGameSpy1::merge(NetPkt* pkt, int queryid, int subid)
|
||||||
{
|
{
|
||||||
Iterator<MultiPart>* it = list.createIteratorRW();
|
Iterator<MultiPart>* it = list.createIterator();
|
||||||
|
|
||||||
NetPkt* tmppkt = new NetPkt(NULL, 0);
|
NetPkt* tmppkt = new NetPkt(NULL, 0);
|
||||||
tmppkt->setAddress(pkt->getAddress());
|
tmppkt->setAddress(pkt->getAddress());
|
||||||
|
@ -148,8 +150,8 @@ NetPkt* ModGameSpy1::merge(NetPkt* pkt, int queryid, int subid)
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
if (searchid == mp->subid) {
|
if (searchid == mp->subid) {
|
||||||
tmppkt->append(mp->pkt);
|
tmppkt->merge(mp->pkt);
|
||||||
delete mp->pkt;
|
delete mp;
|
||||||
searchid++;
|
searchid++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +161,7 @@ NetPkt* ModGameSpy1::merge(NetPkt* pkt, int queryid, int subid)
|
||||||
|
|
||||||
delete it;
|
delete it;
|
||||||
|
|
||||||
tmppkt->append(pkt);
|
tmppkt->merge(pkt);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
delete tmppkt;
|
delete tmppkt;
|
||||||
|
@ -171,7 +173,7 @@ NetPkt* ModGameSpy1::merge(NetPkt* pkt, int queryid, int subid)
|
||||||
|
|
||||||
void ModGameSpy1::gc()
|
void ModGameSpy1::gc()
|
||||||
{
|
{
|
||||||
Iterator<MultiPart>* it = list.createIteratorRW();
|
Iterator<MultiPart>* it = list.createIterator();
|
||||||
long now = time(NULL);
|
long now = time(NULL);
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
|
@ -182,9 +184,9 @@ void ModGameSpy1::gc()
|
||||||
LogSystem::log(LOG_NOTICE, "ModGameSpy1 gc removed: %s (%d/%d)",
|
LogSystem::log(LOG_NOTICE, "ModGameSpy1 gc removed: %s (%d/%d)",
|
||||||
buf, mp->queryid, mp->subid);
|
buf, mp->queryid, mp->subid);
|
||||||
it->remove();
|
it->remove();
|
||||||
|
delete mp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +283,7 @@ int ModGameSpy1::parse_real(NetPkt* pkt, GameList* glist, int gameid)
|
||||||
* beide ports in die serverliste uebernehmen
|
* beide ports in die serverliste uebernehmen
|
||||||
*/
|
*/
|
||||||
if ((offset != -1) && (port != pkt->getPort())) {
|
if ((offset != -1) && (port != pkt->getPort())) {
|
||||||
glist->addGame(gameid, pkt, port, true);
|
glist->addGame(gameid, pkt, port);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
glist->addGame(gameid, pkt);
|
glist->addGame(gameid, pkt);
|
||||||
|
|
|
@ -17,10 +17,10 @@ public:
|
||||||
void gc();
|
void gc();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MultiPart {
|
class MultiPart : private ListEntry<MultiPart> {
|
||||||
public:
|
public:
|
||||||
MultiPart(NetPkt* pkt, int queryid, int subid);
|
MultiPart(NetPkt* pkt, int queryid, int subid);
|
||||||
~MultiPart() {}
|
~MultiPart();
|
||||||
|
|
||||||
NetPkt* pkt;
|
NetPkt* pkt;
|
||||||
int queryid;
|
int queryid;
|
||||||
|
@ -42,7 +42,7 @@ private:
|
||||||
NetPkt* merge(NetPkt* pkt, int queryid, int subid);
|
NetPkt* merge(NetPkt* pkt, int queryid, int subid);
|
||||||
int parse_real(NetPkt* pkt, GameList* glist, int gameid);
|
int parse_real(NetPkt* pkt, GameList* glist, int gameid);
|
||||||
|
|
||||||
List<MultiPart> list;
|
LockedList<MultiPart> list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _MODGAMESPY1_H_
|
#endif // _MODGAMESPY1_H_
|
||||||
|
|
|
@ -78,7 +78,7 @@ int ModGameSpy2::parse(NetPkt* pkt, GameList* glist)
|
||||||
* beide ports in die serverliste uebernehmen
|
* beide ports in die serverliste uebernehmen
|
||||||
*/
|
*/
|
||||||
if ((pos2 != -1) && (port != pkt->getPort())) {
|
if ((pos2 != -1) && (port != pkt->getPort())) {
|
||||||
glist->addGame(gameid, pkt, port, true);
|
glist->addGame(gameid, pkt, port);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
glist->addGame(gameid, pkt);
|
glist->addGame(gameid, pkt);
|
||||||
|
|
2
module.h
2
module.h
|
@ -64,7 +64,7 @@ struct game_ports {
|
||||||
int gameid;
|
int gameid;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Module {
|
class Module : private ListEntry<Module> {
|
||||||
public:
|
public:
|
||||||
virtual ~Module() {};
|
virtual ~Module() {};
|
||||||
virtual void init(Config* conf) {}
|
virtual void init(Config* conf) {}
|
||||||
|
|
|
@ -16,7 +16,7 @@ void ModuleList::reg(Module* mod)
|
||||||
{
|
{
|
||||||
LogSystem::log(LOG_NOTICE, "Registering module '%s'", mod->getName());
|
LogSystem::log(LOG_NOTICE, "Registering module '%s'", mod->getName());
|
||||||
mod->init(&conf);
|
mod->init(&conf);
|
||||||
mlist.addTail(mod);
|
mlist.add(mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleList::scan(MultiSock* msock)
|
void ModuleList::scan(MultiSock* msock)
|
||||||
|
|
13
netpkt.cpp
13
netpkt.cpp
|
@ -163,7 +163,7 @@ bool NetPkt::sameAddress(NetPkt* pkt)
|
||||||
(this->addr.sin_port == pkt->addr.sin_port);
|
(this->addr.sin_port == pkt->addr.sin_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPkt::append(NetPkt* pkt)
|
void NetPkt::merge(NetPkt* pkt)
|
||||||
{
|
{
|
||||||
unsigned int new_alloc = size + pkt->size;
|
unsigned int new_alloc = size + pkt->size;
|
||||||
|
|
||||||
|
@ -179,3 +179,14 @@ void NetPkt::append(NetPkt* pkt)
|
||||||
memcpy((void*)(data + size), pkt->data, pkt->size);
|
memcpy((void*)(data + size), pkt->data, pkt->size);
|
||||||
size += pkt->size;
|
size += pkt->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetPkt::append(const char* buf, unsigned int len)
|
||||||
|
{
|
||||||
|
if (alloc < size + len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memcpy((void*)(data + size), buf, len);
|
||||||
|
size += len;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
7
netpkt.h
7
netpkt.h
|
@ -4,6 +4,8 @@
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
#define PARSE_ACCEPT 1
|
#define PARSE_ACCEPT 1
|
||||||
#define PARSE_ACCEPT_FREED 2
|
#define PARSE_ACCEPT_FREED 2
|
||||||
#define PARSE_ACCEPT_FAKE 3
|
#define PARSE_ACCEPT_FAKE 3
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
/* avoid cyclic deps */
|
/* avoid cyclic deps */
|
||||||
class Socket;
|
class Socket;
|
||||||
|
|
||||||
class NetPkt {
|
class NetPkt : private ListEntry<NetPkt> {
|
||||||
friend class Socket;
|
friend class Socket;
|
||||||
public:
|
public:
|
||||||
NetPkt(const char* data, int size);
|
NetPkt(const char* data, int size);
|
||||||
|
@ -33,7 +35,8 @@ public:
|
||||||
struct sockaddr_in * getAddress();
|
struct sockaddr_in * getAddress();
|
||||||
bool sameAddress(NetPkt* pkt);
|
bool sameAddress(NetPkt* pkt);
|
||||||
|
|
||||||
void append(NetPkt* pkt);
|
void merge(NetPkt* pkt);
|
||||||
|
bool append(const char* buf, unsigned int len);
|
||||||
|
|
||||||
int getPort();
|
int getPort();
|
||||||
int getSize();
|
int getSize();
|
||||||
|
|
|
@ -9,7 +9,7 @@ RecvQueue::~RecvQueue()
|
||||||
void RecvQueue::addPkt(NetPkt* pkt)
|
void RecvQueue::addPkt(NetPkt* pkt)
|
||||||
{
|
{
|
||||||
if (pkt != NULL) {
|
if (pkt != NULL) {
|
||||||
pktList.addTail(pkt);
|
pktList.add(pkt);
|
||||||
pktCount.post();
|
pktCount.post();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Semaphore pktCount;
|
Semaphore pktCount;
|
||||||
List<NetPkt> pktList;
|
LockedList<NetPkt> pktList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _RECVQUEUE_H_
|
#endif // _RECVQUEUE_H_
|
||||||
|
|
Loading…
Reference in New Issue