Initial Commit
This commit is contained in:
commit
ba91546d88
22
Makefile
Normal file
22
Makefile
Normal 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
197
config.cpp
Normal 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
47
config.h
Normal 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
31
gamelist.h
Normal 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
42
gameparser.cpp
Normal 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
39
gameparser.h
Normal 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
50
gamescanner.cpp
Normal 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
49
gamescanner.h
Normal 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
16
hlswmaster.conf
Normal 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
106
hlswmaster.cpp
Normal 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
78
hlswserver.cpp
Normal 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
46
hlswserver.h
Normal 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
167
list.h
Normal 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
99
logging.cpp
Normal 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
63
logging.h
Normal 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
35
mod_example.h
Normal 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
42
modulelist.cpp
Normal 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
40
modulelist.h
Normal 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
187
multisock.cpp
Normal 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
53
multisock.h
Normal 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
35
mutex.h
Normal 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
55
netpkt.cpp
Normal 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
32
netpkt.h
Normal 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
15
recvqueue.h
Normal 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
21
semaphore.h
Normal 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
77
thread.cpp
Normal 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
30
thread.h
Normal 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
71
timerservice.cpp
Normal 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
54
timerservice.h
Normal 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_
|
Loading…
Reference in New Issue
Block a user