Initial Commit

This commit is contained in:
Olaf Rempel 2006-02-02 16:55:44 +01:00
commit ba91546d88
29 changed files with 1799 additions and 0 deletions

22
Makefile Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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 Normal file
View File

@ -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:
AutoMutex(Mutex& x) : m(x) { m.lock(); }
~AutoMutex() { m.unlock(); }
protected:
AutoMutex(const AutoMutex& am);
AutoMutex& operator=(const AutoMutex& am);
private:
Mutex& m;
};
#endif //_MUTEX_H_

55
netpkt.cpp Normal file
View File

@ -0,0 +1,55 @@
#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 "netpkt.h"
NetPkt::NetPkt(int size)
:size(size)
{
LogSystem::log(LOG_DEBUG, "NetPkt()");
data = (char*)malloc(size);
}
NetPkt::~NetPkt()
{
free(data);
LogSystem::log(LOG_DEBUG, "~NetPkt()");
}
int NetPkt::readFromSocket(int fd)
{
socklen_t i = sizeof(struct sockaddr_in);
return recvfrom(fd, this->data, this->size, 0, (struct sockaddr *)&this->addr, &i);
}
int NetPkt::show(char* buf, int size)
{
return snprintf(buf, size, "(%s:%d) %d bytes",
inet_ntoa(this->addr.sin_addr),
ntohs(this->addr.sin_port),
this->size);
}
NetPkt* NetPkt::createFromSocket(int fd)
{
int recvsize = 0;
if (ioctl(fd, FIONREAD, &recvsize) == -1) {
LogSystem::log(LOG_WARNING, "NetPkt::createFromSocket()");
return NULL;
}
NetPkt* retval = new NetPkt(recvsize);
retval->readFromSocket(fd);
return retval;
}

32
netpkt.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef _NETPKT_H_
#define _NETPKT_H_
#include <net/if.h>
#include <netinet/in.h>
#define PKT_ACCEPT 1
#define PKT_ACCEPT_FREED 2
#define PKT_REJECT 4
class NetPkt {
public:
~NetPkt();
static NetPkt* createFromSocket(int fd);
NetPkt* append(NetPkt* pkt);
int show(char* buf, int size);
protected:
NetPkt(const NetPkt& x);
NetPkt& operator=(const NetPkt& x);
private:
NetPkt(int size);
int readFromSocket(int fd);
struct sockaddr_in addr;
int size;
char *data;
};
#endif // _NETPKT_H_

15
recvqueue.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef _RECVQUEUE_H_
#define _RECVQUEUE_H_
#include "netpkt.h"
class RecvQueue {
public:
virtual ~RecvQueue() {};
virtual NetPkt* getPkt() =0;
protected:
RecvQueue() {};
};
#endif // _RECVQUEUE_H_

21
semaphore.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _SEMAPHORE_H_
#define _SEMAPHORE_H_
#include <semaphore.h>
class Semaphore {
public:
Semaphore(int i) { sem_init(&s, 0, i); }
~Semaphore() { sem_destroy(&s); }
void wait() { sem_wait(&s); }
void post() { sem_post(&s); }
protected:
Semaphore(const Semaphore& s);
Semaphore& operator=(const Semaphore& s);
private:
sem_t s;
};
#endif //_SEMAPHORE_H_

77
thread.cpp Normal file
View File

@ -0,0 +1,77 @@
#include "thread.h"
#define THREAD_STACKSIZE 65536
#define THREAD_READY 0x01
#define THREAD_RUNNING 0x02
#define THREAD_ENDED 0x03
Thread::Thread()
: arg(0), tid(0), state(THREAD_READY)
{}
Thread::~Thread()
{
switch (state) {
case THREAD_RUNNING:
cancel();
case THREAD_ENDED:
join();
case THREAD_READY:
break;
}
}
int Thread::start(void* arg_)
{
pthread_attr_t attr;
if (state != THREAD_READY)
return -1;
arg = arg_;
state = THREAD_RUNNING;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, THREAD_STACKSIZE);
if (pthread_create(&tid, &attr, (Thread::entry), this) != 0) {
state = THREAD_READY;
return -1;
}
return 0;
}
void Thread::cancel()
{
pthread_cancel(tid);
state = THREAD_ENDED;
}
bool Thread::isRunning() const
{
return (state == THREAD_RUNNING);
}
int Thread::join()
{
void* retval;
pthread_join(tid, &retval);
state = THREAD_READY;
return (int)retval;
}
void* Thread::entry(void* myself)
{
Thread* thread = (Thread*)myself;
int retval = thread->execute(thread->arg);
thread->state = THREAD_ENDED;
return (void*)retval;
}

30
thread.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef _THREAD_H_
#define _THREAD_H_
#include <pthread.h>
class Thread {
public:
Thread();
virtual ~Thread();
virtual int execute(void* arg) =0;
int start(void* arg = 0);
void cancel();
int join();
bool isRunning() const;
protected:
Thread(const Thread& t);
Thread& operator=(const Thread& t);
private:
void* arg;
pthread_t tid;
volatile int state;
static void* entry(void* myself);
};
#endif // _THREAD_H_

71
timerservice.cpp Normal file
View File

@ -0,0 +1,71 @@
#include <time.h>
#include "timerservice.h"
Timer::Timer(Command* cmd, unsigned int timeval)
: next(0), cmd(cmd), timeval(timeval)
{
}
Timer::~Timer()
{
delete cmd;
}
TimerService::~TimerService()
{
Timer* search = firstTimer;
while (search != NULL) {
Timer* next = search->next;
delete search;
search = next;
}
}
void TimerService::addTimer(Timer* te, bool trigger)
{
te->timeout = time(NULL) + ((!trigger) ? te->timeval : 0);
Timer** search = &firstTimer;
while ((*search) != NULL && (*search)->timeout <= te->timeout)
search = &((*search)->next);
te->next = (*search);
(*search) = te;
}
void TimerService::checkTimeouts()
{
long now = time(NULL);
Timer* search = firstTimer;
while (search != NULL && search->timeout <= now) {
search->cmd->execute();
firstTimer = search->next;
addTimer(search, false);
search = firstTimer;
}
}
TimerService* TimerService::getInstance()
{
static TimerService ts;
return &ts;
}
void TimerService::registerTimer(Timer* te)
{
TimerService* ts = getInstance();
AutoMutex am(ts->mutex);
ts->addTimer(te, true);
}
void TimerService::checkTimers()
{
TimerService* ts = getInstance();
AutoMutex am(ts->mutex);
ts->checkTimeouts();
}

54
timerservice.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef _TIMERSERVICE_H_
#define _TIMERSERVICE_H_
#include "mutex.h"
class Command {
public:
virtual ~Command() {};
virtual void execute() =0;
protected:
Command() {};
};
class Timer {
friend class TimerService;
public:
Timer(Command* cmd, unsigned int timeval);
~Timer();
protected:
Timer(const Timer& te);
Timer& operator=(const Timer& te);
private:
Timer* next;
Command* cmd;
int timeval;
long timeout;
};
class TimerService {
public:
static void registerTimer(Timer* te);
static void checkTimers();
protected:
TimerService(const TimerService& ts);
TimerService& operator=(const TimerService& ts);
private:
TimerService() {}
~TimerService();
static TimerService* getInstance();
void addTimer(Timer* te, bool trigger);
void checkTimeouts();
Timer* firstTimer;
Mutex mutex;
};
#endif // _TIMERSERVICE_H_