Browse Source

Initial Commit

master init
Olaf Rempel 17 years ago
commit
ba91546d88
  1. 22
      Makefile
  2. 197
      config.cpp
  3. 47
      config.h
  4. 31
      gamelist.h
  5. 42
      gameparser.cpp
  6. 39
      gameparser.h
  7. 50
      gamescanner.cpp
  8. 49
      gamescanner.h
  9. 16
      hlswmaster.conf
  10. 106
      hlswmaster.cpp
  11. 78
      hlswserver.cpp
  12. 46
      hlswserver.h
  13. 167
      list.h
  14. 99
      logging.cpp
  15. 63
      logging.h
  16. 35
      mod_example.h
  17. 42
      modulelist.cpp
  18. 40
      modulelist.h
  19. 187
      multisock.cpp
  20. 53
      multisock.h
  21. 35
      mutex.h
  22. 55
      netpkt.cpp
  23. 32
      netpkt.h
  24. 15
      recvqueue.h
  25. 21
      semaphore.h
  26. 77
      thread.cpp
  27. 30
      thread.h
  28. 71
      timerservice.cpp
  29. 54
      timerservice.h

22
Makefile

@ -0,0 +1,22 @@
CFLAGS := -O2 -pipe -Wall -Wunused -Wno-deprecated
LIBS := -lpthread
SRC := $(wildcard *.cpp)
OBJS := $(SRC:.cpp=.o)
DEPS := $(SRC:.cpp=.d)
all: hlswmaster
hlswmaster: $(OBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
%.o: %.cpp
$(CXX) $(CFLAGS) -c $< -o $@
%.d: %.cpp
$(CXX) $(CFLAGS) -MM -c $< -o $@
clean:
rm -f hlswmaster *.d *.o *.log
-include $(DEPS)

197
config.cpp

@ -0,0 +1,197 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "logging.h"
/* ------ */
Config::Tupel::Tupel(const char* name_, const char* value_)
{
name = strdup(name_);
value = strdup(value_);
}
Config::Tupel::~Tupel()
{
free(name);
free(value);
}
/* ------ */
Config::Section::Section(const char* name_)
{
name = strdup(name_);
}
Config::Section::~Section()
{
while (!tupelList.isEmpty())
delete tupelList.get();
free(name);
}
bool Config::Section::addTupel(const char* name, const char* value)
{
if (!name || !value)
return false;
Tupel* t = new Tupel(name, value);
tupelList.addTail(t);
return true;
}
void Config::Section::show() const
{
Iterator<Tupel>* it = tupelList.createIterator();
LogSystem::log(LOG_DEBUG, "[%s]", name);
while (it->hasNext()) {
Tupel* t = it->next();
LogSystem::log(LOG_DEBUG, " %s = %s", t->name, t->value);
}
delete it;
}
char* Config::Section::getTupelValue(const char* name) const
{
char* retval = 0;
Iterator<Tupel>* it = this->tupelList.createIterator();
while (it->hasNext()) {
Tupel* t = it->next();
if (!strcmp(t->name, name)) {
retval = t->value;
break;
}
}
delete it;
return retval;
}
/* ------ */
Config::~Config()
{
while (!sectionList.isEmpty())
delete sectionList.get();
}
Config::Section* Config::addSection(const char* name)
{
Section* s = new Section(name);
sectionList.addTail(s);
return s;
}
bool Config::parseFile(const char* name)
{
Config::Section* section = 0;
FILE *fz;
int i = 0;
char *row, *tok, *tok2;
bool ret = true;
if (!(row = (char*)malloc(1024))) {
LogSystem::log(LOG_CRIT, "config_parse(): malloc()");
return false;
}
if (!(fz = fopen(name, "r"))) {
LogSystem::log(LOG_ERROR, "config_parse(): can not open %s", name);
return false;
}
while (fgets(row, 1024, fz)) {
i++;
/* kommentar oder leere zeile */
if (row[0] == '#' || row[0] <= ' ') {
continue;
/* neue section */
} else if (row[0] == '[') {
tok = strtok(row +1, " ]\n");
section = addSection(tok);
if (!section) {
LogSystem::log(LOG_WARNING, "config_parse(): invalid section in row %d", i);
ret = false;
break;
}
continue;
/* option, aber es gab noch keine section */
} else if (!section) {
LogSystem::log(LOG_WARNING, "config_parse(): missing section in row %d", i);
ret = false;
break;
}
/* option */
if ((tok = strtok(row, " \n")) && (tok2 = strtok(NULL, " \n"))) {
if (!section->addTupel(tok, tok2))
LogSystem::log(LOG_WARNING, "config_parse(): invalid row %d", i);
}
}
fclose(fz);
free(row);
return ret;
}
void Config::show() const
{
LogSystem::log(LOG_DEBUG, "Config Dump:");
Iterator<Section>* it = sectionList.createIterator();
while (it->hasNext())
it->next()->show();
delete it;
}
char* Config::getParameter(const char* section, const char* option) const
{
char* retval = 0;
Iterator<Section>* it = sectionList.createIterator();
while (it->hasNext()) {
Section* s = it->next();
if (!strcmp(s->name, section)) {
retval = s->getTupelValue(option);
break;
}
}
delete it;
return retval;
}
char* Config::getString(const char* section, const char* option, char* def) const
{
char* retval = getParameter(section, option);
if (!retval) {
LogSystem::log(LOG_NOTICE,
"Config: [%s:%s] not found => using '%s'",
section, option, def);
return def;
}
return retval;
}
int Config::getInteger(const char* section, const char* option, int def) const
{
char* retval = getParameter(section, option);
if (!retval) {
LogSystem::log(LOG_NOTICE,
"Config: [%s:%s] not found => using '%d'",
section, option, def);
return def;
}
return atoi(retval);
}

47
config.h

@ -0,0 +1,47 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "list.h"
class Config {
public:
~Config();
bool parseFile(const char* name);
void show() const;
char* getParameter(const char* section, const char* name) const;
char* getString(const char* section, const char* name, char* def) const;
int getInteger(const char* section, const char* name, int def) const;
private:
class Tupel {
public:
Tupel(const char* name, const char* value);
~Tupel();
char* name;
char* value;
};
class Section {
public:
Section(const char* name);
~Section();
bool addTupel(const char* name, const char* option);
char* getTupelValue(const char* name) const;
void show() const;
char* name;
private:
List<Tupel> tupelList;
};
Section* addSection(const char* name);
List<Section> sectionList;
};
#endif // _CONFIG_H_

31
gamelist.h

@ -0,0 +1,31 @@
#ifndef _GAMELIST_H_
#define _GAMELIST_H_
class GameEntry {
public:
GameEntry();
~GameEntry();
protected:
GameEntry(const GameEntry& ge);
GameEntry& operator=(const GameEntry& ge);
private:
struct in_addr addr;
int port1;
int port2;
int gameid;
};
class GameList {
public:
virtual ~GameList() {};
virtual void cleanup() {};
protected:
GameList() {}
};
#endif // _GAMELIST_H_

42
gameparser.cpp

@ -0,0 +1,42 @@
#include "logging.h"
#include "netpkt.h"
#include "gameparser.h"
#define DEFAULT_TIMEOUT 180
GameParser::GameParser(Config& conf, RecvQueue& rxQueue, ModuleList& modList)
: rxQueue(rxQueue), modList(modList)
{
int interval = conf.getInteger("global", "game_timeout", DEFAULT_TIMEOUT);
TimerService::registerTimer(new Timer(new CleanupEvent(this), interval));
}
GameParser::~GameParser()
{
}
int GameParser::execute(void* arg)
{
while (1) {
NetPkt* pkt = rxQueue.getPkt();
int ret = modList.parse(pkt, this);
switch (ret) {
case PKT_REJECT:
char buf[64];
pkt->show(buf, sizeof(buf));
LogSystem::log(LOG_DEBUG, "unknown Packet: %s", buf);
case PKT_ACCEPT:
delete pkt;
case PKT_ACCEPT_FREED:
break;
}
}
return 0;
}
void GameParser::cleanup()
{
LogSystem::log(LOG_DEBUG, "GameParser::cleanup()");
}

39
gameparser.h

@ -0,0 +1,39 @@
#ifndef _GAMEPARSER_H_
#define _GAMEPARSER_H_
#include "gamelist.h"
#include "thread.h"
#include "config.h"
#include "recvqueue.h"
#include "modulelist.h"
#include "timerservice.h"
class GameParser : public GameList, public Thread {
public:
GameParser(Config& conf, RecvQueue& rxQueue, ModuleList& modlist);
~GameParser();
int execute(void* arg);
void cleanup();
protected:
GameParser(const GameParser& rp);
GameParser& operator=(const GameParser& rp);
private:
class CleanupEvent : public Command {
public:
CleanupEvent(GameList* sl) : sl(sl) {}
~CleanupEvent() {}
void execute() { sl->cleanup(); }
private:
GameList* sl;
};
RecvQueue& rxQueue;
ModuleList& modList;
};
#endif // _GAMEPARSER_H_

50
gamescanner.cpp

@ -0,0 +1,50 @@
#include "logging.h"
#include "timerservice.h"
#include "gamescanner.h"
#define DEFAULT_INTERVAL 30
GameScanner::GameScanner(Config& conf, ModuleList& modList)
: modList(modList)
{
msock = new MultiSock(conf);
pktCount = new Semaphore(0);
int interval = conf.getInteger("global", "scan_interval", DEFAULT_INTERVAL);
TimerService::registerTimer(new Timer(new ScanEvent(this), interval));
}
GameScanner::~GameScanner()
{
while (!pktList.isEmpty())
delete pktList.get();
delete pktCount;
delete msock;
}
int GameScanner::execute(void* arg)
{
while (1) {
int fd = msock->getRecvSocket();
NetPkt* pkt = NetPkt::createFromSocket(fd);
if (pkt != NULL) {
pktList.addTail(pkt);
pktCount->post();
}
}
return 0;
}
void GameScanner::scan()
{
modList.scan(msock);
}
NetPkt* GameScanner::getPkt()
{
pktCount->wait();
return pktList.get();
}

49
gamescanner.h

@ -0,0 +1,49 @@
#ifndef _GAMESCANNER_H_
#define _GAMESCANNER_H_
#include "recvqueue.h"
#include "thread.h"
#include "config.h"
#include "modulelist.h"
#include "multisock.h"
#include "semaphore.h"
#include "list.h"
#include "netpkt.h"
#include "timerservice.h"
class GameScanner : public RecvQueue, public Thread {
public:
GameScanner(Config& conf, ModuleList& modList);
~GameScanner();
void scan();
NetPkt* getPkt();
int execute(void* arg);
protected:
GameScanner(const GameScanner& hs);
GameScanner& operator=(const GameScanner& hs);
private:
class ScanEvent : public Command {
public:
ScanEvent(GameScanner* gs) : gs(gs) {}
~ScanEvent() {}
void execute() { gs->scan(); }
private:
GameScanner* gs;
};
ModuleList& modList;
MultiSock* msock;
Semaphore* pktCount;
List<NetPkt> pktList;
};
#endif // _SCANNER_H_

16
hlswmaster.conf

@ -0,0 +1,16 @@
[global]
# broadcast scan source port (udp)
scan_port 7130
# broadcast scan every X seconds
scan_interval 10
# server timeout after X seconds
game_timeout 30
# master answers with this source IP
master_ip 0.0.0.0
# logging
logfile hlswmaster.log
logprio 7

106
hlswmaster.cpp

@ -0,0 +1,106 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "logging.h"
#include "config.h"
#include "gamescanner.h"
#include "gameparser.h"
#include "hlswserver.h"
#include "timerservice.h"
#include "modulelist.h"
#include "mod_example.h"
#define DEFAULT_CONFIG "hlswmaster.conf"
#define DEFAULT_LOGFILE "hlswmaster.log"
static struct option opts[] = {
{"config", 1, 0, 'c'},
{"debug", 0, 0, 'd'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
LogSystem::init(LOG_DEBUG, new StdErrLog());
int arg = 0, code = 0, debug = 0;
char *configfile = DEFAULT_CONFIG;
while (code != -1) {
code = getopt_long(argc, argv, "c:dh", opts, &arg);
switch (code) {
case 'c': /* config */
configfile = optarg;
break;
case 'd': /* debug */
debug = 1;
break;
case 'h': /* help */
printf("Usage: hlsw-master [options]\n"
"Options: \n"
" --config -c configfile use this configfile\n"
" --debug -d do not fork and log to stderr\n"
" --help -h this help\n"
"\n");
exit(0);
break;
case '?': /* error */
exit(-1);
break;
default: /* unknown / all options parsed */
break;
}
}
Config conf;
conf.parseFile(configfile);
// char* logfile = conf.getString("global", "logfile", DEFAULT_LOGFILE);
// int logprio = conf.getInteger("global", "logprio", LOG_NOTICE);
// LogSystem::init(logprio, new FileLog(logfile));
LogSystem::log(LOG_EVERYTIME, "hlswmaster-ng startup");
// conf.show();
ModuleList modList;
GameScanner scanner(conf, modList);
GameParser parser(conf, scanner, modList);
HlswServer server(conf, parser);
modList.reg(new ModExample(conf));
server.start();
parser.start();
scanner.start();
while (1) {
TimerService::checkTimers();
usleep(500000);
if (!scanner.isRunning()) {
LogSystem::log(LOG_CRIT, "Scanner aborted!");
break;
}
if (!parser.isRunning()) {
LogSystem::log(LOG_CRIT, "RecvParser aborted!");
break;
}
if (!server.isRunning()) {
LogSystem::log(LOG_CRIT, "HlswServer aborted!");
break;
}
}
return -1;
}

78
hlswserver.cpp

@ -0,0 +1,78 @@
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include "config.h"
#include "logging.h"
#include "hlswserver.h"
#define HLSW_HEADER "\xFF\xFF\xFF\xFFHLSWLANSEARCH\x00"
#define HLSW_HEADER_LEN 0x12
#define HLSW_MASTER_PORT 7140
HlswServer::HlswServer(Config& conf, GameList& slist)
{
struct sockaddr_in dst;
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");
LogSystem::log(LOG_NOTICE, "HlswServer listen on %s:%d", ip, HLSW_MASTER_PORT);
dst.sin_family = AF_INET;
dst.sin_port = htons(HLSW_MASTER_PORT);
inet_aton(ip, &dst.sin_addr);
if (bind(sock, (struct sockaddr *)&dst, sizeof(dst)) < 0) {
LogSystem::log(LOG_WARNING, "HlswServer(): bind()");
return;
}
out = new HlswPacket();
}
HlswServer::~HlswServer()
{
close(sock);
}
int HlswServer::execute(void* arg)
{
struct sockaddr_in src;
unsigned char buf[32];
socklen_t len;
int ret;
while (1) {
/* auf clientanfrage warten */
len = sizeof(src);
ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&src, &len);
if (ret != HLSW_HEADER_LEN) {
LogSystem::log(LOG_WARNING, "HlswServer: invalid packet");
continue;
}
/* testen ob es sich um ein HLSW anforderung handelt */
if (memcmp(buf, HLSW_HEADER, HLSW_HEADER_LEN)) {
LogSystem::log(LOG_WARNING, "HlswServer: not a hlsw packet");
continue;
}
if (out != NULL && out->count > 0) {
HlswPacket* pkt;
for (pkt = out; pkt != NULL; pkt = pkt->next) {
sendto(sock, pkt->data, pkt->getSize(), 0,
(struct sockaddr *)&src, sizeof(src));
}
}
}
return 0;
}

46
hlswserver.h

@ -0,0 +1,46 @@
#ifndef _HLSWSERVER_H_
#define _HLSWSERVER_H_
#include <string.h>
#include "thread.h"
#include "config.h"
#include "gamelist.h"
class HlswServer : public Thread {
public:
HlswServer(Config& conf, GameList& slist);
~HlswServer();
int execute(void* arg);
protected:
HlswServer(const HlswServer& hs);
HlswServer& operator=(const HlswServer& hs);
private:
class HlswPacket {
public:
HlswPacket() : next(0), count(0)
{
memset(data, 0, sizeof(data));
}
int getSize()
{
return 12 + count * 10;
}
void addGame(void* ptr) {}
HlswPacket* next;
int count;
char data[1412];
};
HlswPacket* out;
int sock;
};
#endif // _HLSWSERVER_H_

167
list.h

@ -0,0 +1,167 @@
#ifndef _LIST_H_
#define _LIST_H_
#include "mutex.h"
template <class T>
class Iterator {
public:
virtual ~Iterator() {}
virtual bool hasNext() const =0;
virtual T* next() =0;
protected:
Iterator<T>() {}
Iterator<T>(const Iterator<T>& it);
Iterator<T>& operator=(const Iterator<T>& it);
};
template <class T>
class List {
public:
List() {}
~List()
{
AutoMutex am(mutex);
while(!head.isEmpty())
head.getNext()->del();
}
void add(const T* part)
{
ListEntry<T>* entry = new ListEntry<T>(part);
AutoMutex am(mutex);
entry->add(&head, head.getNext());
}
void addTail(const T* part)
{
ListEntry<T>* entry = new ListEntry<T>(part);
AutoMutex am(mutex);
entry->add(head.getPrev(), &head);
}
T* get()
{
AutoMutex am(mutex);
ListEntry<T>* entry = head.getNext();
T* retval = (T*)entry->getPart();
if (!head.isEmpty()) {
entry->del();
delete entry;
}
return retval;
}
T* getTail()
{
AutoMutex am(mutex);
ListEntry<T>* entry = head.getPrev();
T* retval = (T*)entry->getPart();
if (!head.isEmpty()) {
entry->del();
delete entry;
}
return retval;
}
bool isEmpty() const
{
AutoMutex am((Mutex&)mutex);
return head.isEmpty();
}
Iterator<T>* createIterator() const
{
return new ListIterator<T>(this);
}
protected:
List(const List& l);
List& operator=(const List& l);
private:
template <class TT>
class ListEntry {
public:
ListEntry(const TT* part = 0)
: prev(this), next(this), part(part)
{
}
void add(ListEntry<TT>* prev_, ListEntry<TT>* next_)
{
this->next = next_;
this->prev = prev_;
next_->prev = this;
prev_->next = this;
}
void del()
{
next->prev = prev;
prev->next = next;
next = prev = this;
}
bool isEmpty() const
{
return (this->prev == this) && (this->next == this);
}
const TT* getPart() const { return part; }
ListEntry<TT>* getPrev() const { return prev; }
ListEntry<TT>* getNext() const { return next; }
private:
ListEntry<TT>* prev;
ListEntry<TT>* next;
const TT* part;
};
ListEntry<T> head;
Mutex mutex;
template <class TT>
class ListIterator : public Iterator<TT> {
public:
ListIterator(const List<TT>* list)
: list(list)
{
// ((ListBase*)list)->mutex.lock();
pos = &list->head;
}
~ListIterator()
{
// ((ListBase*)list)->mutex.unlock();
}
bool hasNext() const
{
return (pos->getNext() != &list->head);
}
TT* next()
{
pos = pos->getNext();
return (TT*)pos->getPart();
}
protected:
ListIterator(const ListIterator& lit);
ListIterator& operator=(const ListIterator& lit);
private:
const List<TT>* list;
const ListEntry<TT>* pos;
};
};
#endif //_LIST_H_

99
logging.cpp

@ -0,0 +1,99 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include "logging.h"
#define BUFLEN 1024
LogSystem::LogSystem() : output(0), priority(0)
{
buffer = new char[BUFLEN];
}
LogSystem::~LogSystem()
{
delete buffer;
if (output)
delete output;
}
LogSystem* LogSystem::getInstance()
{
static LogSystem ls;
return &ls;
}
void LogSystem::init(int prio, LogOutput* out)
{
LogSystem* ls = getInstance();
if (ls->output)
delete ls->output;
ls->output = out;
ls->priority = prio;
}
void LogSystem::log(int prio, const char* fmt, ...)
{
LogSystem* ls = getInstance();
if (prio > ls->priority || !ls->output)
return;
va_list az;
int len;
va_start(az, fmt);
len = vsnprintf(ls->buffer, BUFLEN, fmt, az);
va_end(az);
if (errno) {
strncpy(ls->buffer + len, ": ", BUFLEN - len);
len += 2;
strncpy(ls->buffer + len, strerror(errno), BUFLEN - len);
errno = 0;
}
ls->output->write(ls->buffer);
}
/* ------- */
void StdErrLog::write(const char* buf)
{
fprintf(stderr, "%s\n", buf);
}
/* ------- */
FileLog::FileLog(const char* filename)
{
if (!(logfile = fopen(filename, "a" )))
LogSystem::log(LOG_CRIT, "Can not open logfile '%s'", filename);
fprintf(logfile, "-----------------\n");
}
FileLog::~FileLog()
{
fclose(logfile);
}
void FileLog::write(const char* buf)
{
time_t tzgr;
char tbuf[64];
time(&tzgr);
strftime(tbuf, sizeof(tbuf), "%b %d %H:%M:%S :", localtime(&tzgr));
fprintf(logfile, "%s %s\n", tbuf, buf);
fflush(logfile);
}

63
logging.h

@ -0,0 +1,63 @@
#ifndef _LOGGING_H_
#define _LOGGING_H_
#include <stdio.h>
// really noisy debugging (pkt-dumps)
#define LOG_DEBUG 5
// normal "debug" (config, recv. packets)
#define LOG_INFO 4
// interesting stuff
#define LOG_NOTICE 3
// something is not right, but programm is still working (config errors)
#define LOG_WARN 2
// something is *really* bad, but we try to keep up (mem-allocs)
#define LOG_ERROR 1
// we must bailout *now*
#define LOG_CRIT 0
#define LOG_EVERYTIME 0
class LogOutput {
public:
virtual ~LogOutput() {};
virtual void write(const char* buf) {};
};
class LogSystem {
public:
static void init(int prio, LogOutput* lo);
static void log(int prio, const char* fmt, ...);
private:
LogSystem();
~LogSystem();
static LogSystem* getInstance();
LogOutput *output;
int priority;
char* buffer;
};
class StdErrLog : public LogOutput {
public:
void write(const char* buf);
};
class FileLog : public LogOutput {
public:
FileLog(const char* filename);
~FileLog();
void write(const char* buf);
private:
FILE* logfile;
};
#endif // _LOGGING_H_

35
mod_example.h

@ -0,0 +1,35 @@
#ifndef _MODEXAMPLE_H_
#define _MODEXAMPLE_H_
#include "modulelist.h"
#include "logging.h"
class ModExample : public Module {
public:
ModExample(Config& conf)
{
}
~ModExample()
{
}
void scan(MultiSock* msock)
{
LogSystem::log(LOG_DEBUG, "ModExample::scan()");
}
int parse(NetPkt* pkt, GameList* slist)
{
LogSystem::log(LOG_DEBUG, "ModExample::parse()");
return 0;
}
char* getName() {
return "Example Module";
}
protected:
};
#endif // _MODEXAMPLE_H_

42
modulelist.cpp

@ -0,0 +1,42 @@
#include "logging.h"
#include "modulelist.h"
ModuleList::ModuleList()
{
}
ModuleList::~ModuleList()
{
while (!mlist.isEmpty())
delete mlist.get();
}
void ModuleList::reg(Module* mod)
{
LogSystem::log(LOG_INFO, "Loading Module '%s'", mod->getName());
mlist.addTail(mod);
}
void ModuleList::scan(MultiSock* msock)
{
Iterator<Module> *it = mlist.createIterator();
while (it->hasNext())
it->next()->scan(msock);
delete it;
}
int ModuleList::parse(NetPkt* pkt, GameList* slist)
{
int retval = PKT_REJECT;
Iterator<Module> *it = mlist.createIterator();
while (it->hasNext()) {
retval = it->next()->parse(pkt, slist);
if (retval != PKT_REJECT)
break;
}
delete it;
return retval;
}

40
modulelist.h

@ -0,0 +1,40 @@
#ifndef _MODULELIST_H_
#define _MODULELIST_H_
#include "multisock.h"
#include "netpkt.h"
#include "gamelist.h"
#include "config.h"
class Module {
public:
virtual ~Module() {};
virtual void scan(MultiSock* msock) =0;
virtual int parse(NetPkt* pkt, GameList* slist) =0;
virtual char* getName() =0;
protected:
Module() {};
};
class ModuleList {
public:
ModuleList();
~ModuleList();
void reg(Module* mod);
void scan(MultiSock* msock);
int parse(NetPkt* pkt, GameList* slist);
protected:
ModuleList(const ModuleList& ml);
ModuleList& operator=(const ModuleList& ml);
private:
List<Module> mlist;
};
#endif // _MODULELIST_H_

187
multisock.cpp

@ -0,0 +1,187 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "logging.h"
#include "multisock.h"
#define DEFAULT_PORT 7130
#define DEVFILE "/proc/net/dev"
#define BUFSIZE 256
MultiSock::Socket::Socket()
{
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
LogSystem::log(LOG_CRIT, "Socket: socket()");
}
MultiSock::Socket::~Socket()
{
close(fd);
}
bool MultiSock::Socket::bindToDevice(const char* name)
{
strncpy(devname, name, sizeof(devname));
int ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, devname, sizeof(devname));
if (ret < 0) {
LogSystem::log(LOG_WARNING, "Socket: setsockopt(SO_BINDTODEVICE) %s", devname);
return false;
}
return true;
}
bool MultiSock::Socket::bindToPort(int port)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, devname, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFADDR, &ifr) != 0) {
LogSystem::log(LOG_WARNING, "Socket: ioctl(SIOCGIFADDR) %s", devname);
return false;
}
memcpy(&addr, &ifr.ifr_addr, sizeof(addr));
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
LogSystem::log(LOG_WARNING, "Socket: bind() %s", devname);
return false;
}
int bcast = 1;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast))) {
LogSystem::log(LOG_WARNING, "Socket: setsockopt(SO_BROADCAST) %s", devname);
return false;
}
return true;
}
int MultiSock::Socket::show(char* buf, int size)
{
return snprintf(buf, size, "%s (%s:%d) ", devname,
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}
MultiSock::Socket* MultiSock::Socket::createSocket(const char* name, int port)
{
Socket* sock = new Socket();
if (sock->fd < 0) {
delete sock;
return NULL;
}
struct ifreq ifr;
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(sock->fd, SIOCGIFFLAGS, &ifr) != 0) {
LogSystem::log(LOG_WARNING, "Socket: ioctl(SIOCGIFFLAGS) %s", name);
delete sock;
return NULL;
}
if (!(ifr.ifr_flags & IFF_UP) || (ifr.ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
delete sock;
return NULL;
}
sock->bindToDevice(name);
if (!sock->bindToPort(port)) {
delete sock;
return NULL;
}
return sock;
}
MultiSock::MultiSock(Config& conf)
{
char* buf = (char*)malloc(BUFSIZE);
if (buf == NULL) {
LogSystem::log(LOG_CRIT, "MultiSock(): out of memory");
return;
}
FILE* fp = fopen(DEVFILE, "r");
if (fp == NULL) {
LogSystem::log(LOG_CRIT, "MultiSock(): can not open " DEVFILE);
free(buf);
return;
}
fgets(buf, BUFSIZE, fp);
fgets(buf, BUFSIZE, fp);
int port = conf.getInteger("global", "scan_port", DEFAULT_PORT);
FD_ZERO(&fdsel);
while (fgets(buf, BUFSIZE, fp) != NULL) {
char* tok = strtok(buf, " :");
// TODO: check against config list
Socket* sock = Socket::createSocket(tok, port);
if (sock) {
FD_SET(sock->getFD(), &fdsel);
sock->show(buf, BUFSIZE);
LogSystem::log(LOG_NOTICE, "adding Interface %s", buf);
ifaceList.add(sock);
}
}
fclose(fp);
free(buf);
}
MultiSock::~MultiSock()
{
while (!ifaceList.isEmpty())
delete ifaceList.get();
}
int MultiSock::getRecvSocket()
{
fd_set fdcpy;
while (1) {
memcpy(&fdcpy, &fdsel, sizeof(fdcpy));
select(FD_SETSIZE, &fdcpy, NULL, NULL, NULL);
Iterator<Socket>* it = ifaceList.createIterator();
while (it->hasNext()) {
Socket* sock = it->next();
if (FD_ISSET(sock->getFD(), &fdcpy)) {
delete it;
return sock->getFD();
}
}
delete it;
LogSystem::log(LOG_ERROR, "getRecvSocket(): select()");
}
return -1;
}

53
multisock.h

@ -0,0 +1,53 @@
#ifndef _MULTISOCK_H_
#define _MULTISOCK_H_
#include <net/if.h>
#include <netinet/in.h>
#include "list.h"
#include "config.h"
class MultiSock {
public:
MultiSock(Config& conf);
~MultiSock();
int send(struct in_addr *dstip, int dport, char* data, int size);
int getRecvSocket();
protected:
MultiSock(const MultiSock& x);
MultiSock& operator=(const MultiSock& x);
private:
class Socket {
public:
static Socket* createSocket(const char* name, int port);
int show(char* buf, int size);
int getFD() { return fd; }
~Socket();
protected:
Socket(const Socket& s);
Socket& operator=(const Socket& s);
private:
Socket();
bool bindToDevice(const char* name);
bool bindToPort(int port);
int fd;
char devname[IFNAMSIZ];
struct sockaddr_in addr;
};
void addIface(const char* name, int port);
List<Socket> ifaceList;
fd_set fdsel;
};
#endif // _MULTISOCK_H_

35
mutex.h

@ -0,0 +1,35 @@
#ifndef _MUTEX_H_
#define _MUTEX_H_
#include <pthread.h>
class Mutex {
public:
Mutex() { pthread_mutex_init(&m, 0); }
~Mutex() { pthread_mutex_destroy(&m); }
void lock() { pthread_mutex_lock(&m); }
void unlock() { pthread_mutex_unlock(&m); }
protected:
Mutex(const Mutex& m);
Mutex& operator=(const Mutex& m);
private:
pthread_mutex_t m;
};
class AutoMutex {
public: