daily work

This commit is contained in:
Olaf Rempel 2006-03-06 20:13:26 +01:00
parent e0b98f4756
commit 33e97b1eaa
19 changed files with 681 additions and 214 deletions

View File

@ -34,6 +34,8 @@ private:
~SectionIterator();
bool hasNext();
char* next();
void add(char* part) {}
void remove() {}
void reset();
private:

View File

@ -26,7 +26,6 @@ void GameList::cleanup()
long GameList::getLastUpdate()
{
lastUpdate++;
return lastUpdate;
}
@ -35,11 +34,12 @@ Iterator<GameEntry>* GameList::createIterator()
return glist.createIterator();
}
void GameList::addGame(int gameid, NetPkt* pkt, int port2)
void GameList::addGame(int gameid, NetPkt* pkt, int port2, bool swap)
{
char buf[64];
pkt->show(buf, sizeof(buf));
LogSystem::log(LOG_NOTICE, "Adding Game %d: %s %d", gameid, buf, port2);
LogSystem::log(LOG_NOTICE, "Adding Game %d: %s", gameid, buf);
glist.add(new GameEntry());
lastUpdate++;
}

View File

@ -13,7 +13,7 @@ public:
~GameList();
void cleanup();
void addGame(int gameid, NetPkt* pkt, int port2 = 0);
void addGame(int gameid, NetPkt* pkt, int port2 = 0, bool swap = false);
long getLastUpdate();
Iterator<GameEntry>* createIterator();

View File

@ -9,21 +9,35 @@ GameParser::GameParser(RecvQueue& rxQueue, ModuleList& modList, GameList& gameLi
int GameParser::execute(void* arg)
{
NetPkt* pkt;
char buf[64], *p;
int ret;
while (1) {
NetPkt* pkt = rxQueue.getPkt();
int ret = modList.parse(pkt, &gameList);
pkt = rxQueue.getPkt();
ret = modList.parse(pkt, &gameList);
switch (ret) {
case PARSE_REJECT:
char buf[64];
case PARSE_ACCEPT_FAKE:
pkt->show(buf, sizeof(buf));
LogSystem::log(LOG_NOTICE, "unknown Packet: %s", buf);
LogSystem::log(LOG_NOTICE, "not supported Game: %s", buf);
case PARSE_ACCEPT:
delete pkt;
case PARSE_ACCEPT_FREED:
break;
default:
case PARSE_REJECT:
pkt->show(buf, sizeof(buf));
LogSystem::log(LOG_NOTICE, "unknown Packet: %s", buf);
p = pkt->showfull();
LogSystem::log(LOG_DEBUG, "%s", p);
delete p;
delete pkt;
break;
}
}
return 0;

View File

@ -91,9 +91,9 @@ int main(int argc, char *argv[])
HlswServer server(conf, gameList);
// modList.reg(new ModHalfLife());
modList.reg(new ModQ3Engine());
// modList.reg(new ModQ3Engine());
// modList.reg(new ModD3Engine());
// modList.reg(new ModGameSpy1());
modList.reg(new ModGameSpy1());
// modList.reg(new ModGameSpy2());
server.start();

View File

@ -9,11 +9,8 @@
#include "logging.h"
#include "hlswserver.h"
#define HLSW_MASTER_PORT 7140
static const char hlsw_header[] = "\xFF\xFF\xFF\xFFHLSWLANSEARCH";
#define DEFAULT_REBUILD_INTERVAL 5
struct hlsw_entry {
uint16_t gameid;
uint32_t ip;
@ -21,11 +18,15 @@ struct hlsw_entry {
uint16_t port2;
} __attribute__ ((packed));
#define HLSW_MASTER_PORT 7140
#define HLSW_MAX_PACKET_SIZE (sizeof(hlsw_header) + 140 * sizeof(struct hlsw_entry))
#define DEFAULT_REBUILD_INTERVAL 5
HlswServer::HlswPacket::HlswPacket(HlswPacket* next)
: NetPkt(1418), next(next)
: NetPkt(HLSW_MAX_PACKET_SIZE), next(next)
{
memcpy((void*)data, hlsw_header, sizeof(hlsw_header));
used = sizeof(hlsw_header);
size = sizeof(hlsw_header);
}
HlswServer::HlswPacket::~HlswPacket()
@ -36,7 +37,7 @@ HlswServer::HlswPacket::~HlswPacket()
bool HlswServer::HlswPacket::addGame(GameEntry* ge)
{
if (used >= 1418)
if (size >= HLSW_MAX_PACKET_SIZE)
return false;
struct hlsw_entry tmp;
@ -45,8 +46,8 @@ bool HlswServer::HlswPacket::addGame(GameEntry* ge)
tmp.port1 = ge->port1;
tmp.port2 = ge->port2;
memcpy((void*)(data + used), &tmp, sizeof(tmp));
used += sizeof(tmp);
memcpy((void*)(data + size), &tmp, sizeof(tmp));
size += sizeof(tmp);
return true;
}
@ -99,7 +100,6 @@ int HlswServer::execute(void* arg)
return 0;
}
void HlswServer::rebuild(GameList& glist) {
if (glist.getLastUpdate() > lastUpdate) {
HlswPacket* newlist = new HlswPacket(NULL);

258
list.h
View File

@ -3,183 +3,145 @@
#include "mutex.h"
template <class T>
class Iterator {
class IteratorBase {
public:
virtual ~Iterator() {}
virtual ~IteratorBase() {}
virtual bool hasNext() =0;
virtual T* next() =0;
virtual void* next() =0;
virtual void add(void* part) {}; // TODO: why not =0;
virtual void remove() =0;
virtual void reset() =0;
protected:
Iterator<T>() {}
Iterator<T>(const Iterator<T>& it);
Iterator<T>& operator=(const Iterator<T>& it);
IteratorBase() {}
IteratorBase(const IteratorBase& it);
IteratorBase& operator=(const IteratorBase& it);
};
class ListBase {
public:
ListBase();
~ListBase();
void add(const void* part);
void addTail(const void* part);
void* get();
void* getTail();
bool isEmpty() const;
IteratorBase* createIterator();
protected:
ListBase(const ListBase& l);
ListBase& operator=(const ListBase& l);
class ListEntryBase {
public:
ListEntryBase(const void* part = 0);
~ListEntryBase();
void add(ListEntryBase* prev, ListEntryBase* next);
void del();
bool isEmpty() const;
void* getPart() const;
ListEntryBase* getPrev() const;
ListEntryBase* getNext() const;
protected:
ListEntryBase(const ListEntryBase& l);
ListEntryBase& operator=(const ListEntryBase& l);
private:
ListEntryBase* prev;
ListEntryBase* next;
const void* part;
};
class ListIteratorBase : public IteratorBase {
public:
ListIteratorBase(ListBase* list);
~ListIteratorBase();
bool hasNext();
void* next();
void add(void* part);
void remove();
void reset();
private:
ListBase* list;
ListEntryBase* pos;
};
private:
ListEntryBase head;
Mutex mutex;
};
template <class T>
class Iterator : public IteratorBase {
public:
virtual T* next() =0;
virtual void add(T* part) =0;
};
template <class T>
class NullIterator : public Iterator<T> {
public:
NullIterator() {}
~NullIterator() {}
bool hasNext() { return false; }
T* next() { return 0; }
void reset() {}
NullIterator() {}
~NullIterator() {}
bool hasNext() { return false; }
T* next() { return NULL; }
void add(T* part) {}
void remove() {}
void reset() {}
};
template <class T>
class List {
class List : private ListBase {
public:
List() {}
~List() {}
~List()
{
AutoMutex am(mutex);
while(!head.isEmpty())
head.getNext()->del();
}
void add(const T* part) { ListBase::add(part); }
void addTail(const T* part) { ListBase::addTail(part); }
T* get() { return (T*)ListBase::get(); }
T* getTail() { return (T*)ListBase::getTail(); }
bool isEmpty() const { return ListBase::isEmpty(); }
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);
Iterator<T>* createIterator() const { return new ListIteratorRO<T>(this); }
Iterator<T>* createIteratorRW() { return new ListIteratorRW<T>(this); }
private:
template <class TT>
class ListEntry {
class ListIteratorRO : public Iterator<TT>, private ListIteratorBase {
public:
ListEntry(const TT* part = 0)
: prev(this), next(this), part(part)
{
}
ListIteratorRO(const List<TT>* list) : ListIteratorBase((ListBase*)list) {}
~ListIteratorRO() {}
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;
bool hasNext() { return ListIteratorBase::hasNext(); }
TT* next() { return (TT*)ListIteratorBase::next(); }
void add(TT* part) {}
void remove() {}
void reset() { ListIteratorBase::reset(); }
};
ListEntry<T> head;
Mutex mutex;
template <class TT>
class ListIterator : public Iterator<TT> {
class ListIteratorRW : public Iterator<TT>, private ListIteratorBase {
public:
ListIterator(const List<TT>* list)
: list(list)
{
((List<TT>*)list)->mutex.lock();
reset();
}
ListIteratorRW(List<TT>* list) : ListIteratorBase(list) {}
~ListIteratorRW() {}
~ListIterator()
{
((List<TT>*)list)->mutex.unlock();
}
bool hasNext()
{
return (pos->getNext() != &list->head);
}
TT* next()
{
pos = pos->getNext();
return (TT*)pos->getPart();
}
void reset()
{
pos = &list->head;
}
protected:
ListIterator(const ListIterator& lit);
ListIterator& operator=(const ListIterator& lit);
private:
const List<TT>* list;
const ListEntry<TT>* pos;
bool hasNext() { return ListIteratorBase::hasNext(); }
TT* next() { return (TT*)ListIteratorBase::next(); }
void add(TT* part) { ListIteratorBase::add(part); }
void remove() { ListIteratorBase::remove(); }
void reset() { ListIteratorBase::reset(); }
};
};
#endif //_LIST_H_

View File

@ -7,8 +7,8 @@
#include "logging.h"
#define BUFLEN 1024
/* we need this for packet dumps! */
#define BUFLEN 8192
LogSystem::LogSystem() : output(0), priority(0)
{

View File

@ -25,7 +25,7 @@ int ModD3Engine::parse(NetPkt* pkt, GameList* glist)
if (!gameid)
return PARSE_REJECT;
if (pkt->compare(0, replyhead, strlen(replyhead)))
if (!pkt->compare(0, replyhead, strlen(replyhead)))
return PARSE_REJECT;
glist->addGame(gameid, pkt);

View File

@ -1,24 +1,267 @@
#include <string.h>
#include "logging.h"
#include "modhelper.h"
#include "mod_gamespy1.h"
static struct game_ports port_arr[] = {
{ 7777, 7788, ID_UT }, // ut(5), ut2k3(14), rune(18), ut2k4(33), aao(15)
{ 7777, 7788, ID_UT }, // ut, ut2k3, rune, ut2k4, aao, POSTAL2
{ 22000, 22010, ID_BF1942 }, // bf1942(16)
{ 23000, 23010, ID_BFV }, // bfv(35)
{ 26001, 26011, ID_IGI2 }, // igi2(19)
{ 27888, 27888, ID_AVP2 }, // avp2(17)
{ 27888, 27888, ID_AVP2 }, // avp2(17), FEAR
{ 0,0,0 }
};
static const char scanmsg[] = "\\status\\";
static const char search_queryid[] = "\\queryid\\";
static const char search_final[] = "\\final\\";
static const char search_hostport[] = "\\hostport\\";
static const char search_gamename[] = "\\gamename\\";
static const char search_gsgamename[] = "\\gsgamename\\";
static const char search_gameid[] = "\\game_id\\";
static const char reply_ut[] = "ut\\";
static const char reply_ut2k3[] = "ut2\\";
static const char reply_ut2k4[] = "ut2004\\";
static const char reply_bf1942[] = "bfield1942\\";
static const char reply_bfv1[] = "bfvietnam\\";
static const char reply_bfv2[] = "BFVIETNAM\\";
static const char reply_poe[] = "poe\\";
static const char reply_opk[] = "opk\\";
static const char reply_avp2[] = "avp2\\";
static const char reply_igi2[] = "projectigi2r\\";
static const char reply_aao[] = "armygame\\";
static const char reply_rune[] = "rune\\";
static const char reply_postal2[] = "postal2\\";
static const char reply_fear[] = "fear\\";
ModGameSpy1::ModGameSpy1()
{
// TODO: cleanup event
}
ModGameSpy1::~ModGameSpy1()
{
while (!list.isEmpty()) {
MultiPart* mp = list.get();
delete mp->pkt;
delete mp;
}
}
void ModGameSpy1::scan(MultiSock* msock)
{
ModHelper::send(msock, port_arr, scanmsg, strlen(scanmsg));
}
int ModGameSpy1::parse(NetPkt* pkt, GameList* slist)
int ModGameSpy1::parse(NetPkt* pkt, GameList* glist)
{
return 0;
NetPkt* pkt2;
int gameid, pos, offset, queryid, subid, retval;
bool final;
gameid = ModHelper::checkPorts(pkt, port_arr);
if (!gameid)
return PARSE_REJECT;
/* eat ut connection attemps */
if (gameid == 5 && pkt->getSize() <= 6)
return PARSE_ACCEPT_QUIRK;
offset = pkt->find(0, search_queryid, strlen(search_queryid));
if (offset == -1)
return PARSE_REJECT;
pos = offset + strlen(search_queryid);
offset = pkt->parse_int(pos, &queryid);
if (offset == 0)
return PARSE_REJECT;
pos += offset +1;
offset = pkt->parse_int(pos, &subid);
if (offset == 0)
return PARSE_REJECT;
offset = pkt->find(0, search_final, strlen(search_final));
final = (offset != -1);
/* single final packet -> shortcut */
if (final && (subid == 1)) {
LogSystem::log(LOG_DEBUG, "single final");
pkt2 = pkt;
/* non-final multi-part */
} else if (!final) {
LogSystem::log(LOG_DEBUG, "non final");
list.addTail(new MultiPart(pkt, queryid, subid));
return PARSE_ACCEPT_FREED;
/* final multipart */
} else {
LogSystem::log(LOG_DEBUG, "multi final");
pkt2 = merge(pkt, queryid, subid);
if (pkt2 == NULL) {
LogSystem::log(LOG_NOTICE, "GameSpy1: unable to merge");
return PARSE_ACCEPT_FREED;
}
}
retval = parse_real(pkt2, glist, gameid);
if (pkt2 != pkt)
delete pkt2;
return retval;
}
ModGameSpy1::MultiPart::MultiPart(NetPkt* pkt, int queryid, int subid)
: pkt(pkt), queryid(queryid), subid(subid)
{
timeout = time(NULL) + 5;
}
NetPkt* ModGameSpy1::merge(NetPkt* pkt, int queryid, int subid)
{
Iterator<MultiPart>* it = list.createIteratorRW();
NetPkt* tmppkt = new NetPkt(NULL, 0);
tmppkt->setAddress(pkt->getAddress());
bool found;
int searchid = 1;
do {
found = false;
while (it->hasNext()) {
MultiPart* mp = it->next();
if (!pkt->sameAddress(mp->pkt))
continue;
if (queryid != mp->queryid)
continue;
it->remove();
found = true;
if (searchid == mp->subid) {
tmppkt->append(mp->pkt);
searchid++;
}
}
it->reset();
} while (found && (searchid < subid));
delete it;
tmppkt->append(pkt);
delete pkt;
if (!found) {
delete tmppkt;
return NULL;
}
return tmppkt;
}
int ModGameSpy1::parse_real(NetPkt* pkt, GameList* glist, int gameid)
{
int port, offset, pos1, pos2;
pos1 = pkt->find(0, search_gamename, strlen(search_gamename));
pos1 += strlen(search_gamename);
switch (gameid) {
case ID_UT:
if (pkt->compare(pos1, reply_ut, strlen(reply_ut)))
gameid = ID_UT;
else if (pkt->compare(pos1, reply_ut2k3, strlen(reply_ut2k4)))
gameid = ID_UT2K3;
else if (pkt->compare(pos1, reply_ut2k4, strlen(reply_ut2k4)))
gameid = ID_UT2K4;
else if (pkt->compare(pos1, reply_aao, strlen(reply_aao)))
gameid = ID_AAO;
else if (pkt->compare(pos1, reply_postal2, strlen(reply_postal2)))
return PARSE_ACCEPT_FAKE;
else
return PARSE_REJECT;
break;
case ID_BF1942:
case ID_BFV:
pos2 = pkt->find(0, search_gameid, strlen(search_gameid));
pos2 += strlen(search_gameid);
if (pkt->compare(pos1, reply_bf1942, strlen(reply_bf1942)))
gameid = ID_BF1942;
else if (pkt->compare(pos2, reply_bfv1, strlen(reply_bfv1)))
gameid = ID_BFV;
else if (pkt->compare(pos2, reply_bfv2, strlen(reply_bfv2)))
gameid = ID_BFV;
else if (pkt->compare(pos2, reply_poe, strlen(reply_poe)))
gameid = ID_BFV;
else if (pkt->compare(pos2, reply_opk, strlen(reply_opk)))
gameid = ID_BFV;
else
return PARSE_REJECT;
break;
case ID_AVP2:
pos2 = pkt->find(0, search_gsgamename, strlen(search_gsgamename));
pos2 += strlen(search_gsgamename);
if (pkt->compare(pos1, reply_avp2, strlen(reply_avp2)))
gameid = ID_AVP2;
else if (pkt->compare(pos2, reply_fear, strlen(reply_fear)))
return PARSE_ACCEPT_FAKE;
else
return PARSE_REJECT;
break;
case ID_RUNE:
if (pkt->compare(pos1, reply_rune, strlen(reply_rune)))
gameid = ID_RUNE;
else
return PARSE_REJECT;
break;
case ID_IGI2:
if (pkt->compare(pos1, reply_igi2, strlen(reply_igi2)))
gameid = ID_IGI2;
else
return PARSE_REJECT;
break;
default:
return PARSE_REJECT;
}
/* hostport angabe suchen */
offset = pkt->find(0, search_hostport, strlen(search_hostport));
if (offset != -1)
pkt->parse_int(offset + strlen(search_hostport), &port);
/*
* wenn ein hostport angegeben wurde, und das nicht der src port ist
* beide ports in die serverliste uebernehmen
*/
if ((offset != -1) && (port != pkt->getPort())) {
glist->addGame(gameid, pkt, port, true);
} else {
glist->addGame(gameid, pkt);
}
return PARSE_ACCEPT;
}

View File

@ -1,17 +1,36 @@
#ifndef _MODGAMESPY1_H_
#define _MODGAMESPY1_H_
#include "list.h"
#include "module.h"
class ModGameSpy1 : public Module {
public:
ModGameSpy1() {}
~ModGameSpy1() {}
ModGameSpy1();
~ModGameSpy1();
void scan(MultiSock* msock);
int parse(NetPkt* pkt, GameList* glist);
const char* getName() { return "GameSpy 1 Protocol"; }
private:
class MultiPart {
public:
MultiPart(NetPkt* pkt, int queryid, int subid);
~MultiPart() {}
NetPkt* pkt;
int queryid;
int subid;
long timeout;
};
NetPkt* merge(NetPkt* pkt, int queryid, int subid);
int parse_real(NetPkt* pkt, GameList* glist, int gameid);
List<MultiPart> list;
};
#endif // _MODGAMESPY1_H_

View File

@ -1,25 +1,88 @@
#include <string.h>
#include "logging.h"
#include "modhelper.h"
#include "mod_gamespy2.h"
static struct game_ports port_arr[] = {
{ 7777, 7788, ID_UT }, // ut(5), ut2k3(14), rune(18), ut2k4(33), aao(15)
{ 22000, 22010, ID_BF1942 }, // bf1942(16)
{ 23000, 23010, ID_BFV }, // bfv(35)
{ 26001, 26011, ID_IGI2 }, // igi2(19)
{ 27888, 27888, ID_AVP2 }, // avp2(17)
{ 0,0,0 }
{ 2302, 2302, ID_HALO },
{ 3455, 3455, ID_PK },
{ 10481, 10482, ID_SWAT4 },
{ 29900, 29910, ID_BF2 },
{ 0, 0, 0 }
};
static const char scanmsg[] = { 0xFE, 0xFD, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0x00, 0x00 };
static const char replyhead[] = { 0x00, 0xDE, 0xAD, 0xBE, 0xEF };
static const char search_hostport[] = "hostport";
static const char search_gamename[] = "gamename";
static const char reply_bf2[] = "battlefield2";
void ModGameSpy2::scan(MultiSock* msock)
{
ModHelper::send(msock, port_arr, scanmsg, sizeof(scanmsg));
}
int ModGameSpy2::parse(NetPkt* pkt, GameList* slist)
int ModGameSpy2::parse(NetPkt* pkt, GameList* glist)
{
return 0;
int gameid, pos1, pos2, port;
gameid = ModHelper::checkPorts(pkt, port_arr);
if (!gameid)
return PARSE_REJECT;
if (!pkt->compare(0, replyhead, sizeof(replyhead)))
return PARSE_REJECT;
pos1 = pkt->find(0, search_gamename, strlen(search_gamename));
pos1 += strlen(search_gamename) +1;
/* hostport angabe suchen */
pos2 = pkt->find(0, search_hostport, strlen(search_hostport));
if (pos2 != -1) {
pos2 += strlen(search_hostport) +1;
pkt->parse_int(pos2, &port);
}
switch (gameid) {
case ID_HALO:
case ID_PK:
break;
case ID_SWAT4:
if (pos2 == -1)
return PARSE_REJECT;
break;
case ID_BF2:/* battlefield 2 */
// TODO: pos2 check noetig?
if (pos2 == -1) {
LogSystem::log(LOG_DEBUG, "no hostport found");
return PARSE_REJECT;
}
if (pkt->find(pos1, reply_bf2, strlen(reply_bf2)) == -1) {
LogSystem::log(LOG_DEBUG, "no gamename found");
return PARSE_REJECT;
}
break;
default:
return PARSE_REJECT;
break;
}
/*
* wenn ein hostport angegeben wurde, und das nicht der src port ist
* beide ports in die serverliste uebernehmen
*/
if ((pos2 != -1) && (port != pkt->getPort())) {
glist->addGame(gameid, pkt, port, true);
} else {
glist->addGame(gameid, pkt);
}
return PARSE_ACCEPT;
}

View File

@ -11,6 +11,9 @@ static const char scanmsg1[] = "\xff\xff\xff\xff""details";
static const char scanmsg2[] = "\xff\xff\xff\xff\x54";
static const char scanmsg3[] = "\xff\xff\xff\xff""TSource Engine Query";
static const char reply1[] = "m\x00";
static const char reply2[] = "I\x07";
void ModHalfLife::scan(MultiSock* msock)
{
ModHelper::send(msock, port_arr, scanmsg1, strlen(scanmsg1));
@ -18,7 +21,42 @@ void ModHalfLife::scan(MultiSock* msock)
ModHelper::send(msock, port_arr, scanmsg3, strlen(scanmsg3));
}
int ModHalfLife::parse(NetPkt* pkt, GameList* slist)
int ModHalfLife::parse(NetPkt* pkt, GameList* glist)
{
return 0;
struct in_addr tmp;
int port, count, pos;
if (ModHelper::checkPorts(pkt, port_arr) == 0)
return PARSE_REJECT;
// check 0xFF 0xFF 0xFF 0xFF
if (!pkt->compare(0, scanmsg1, 4))
return PARSE_REJECT;
/* check for short answer without ip/port */
if (pkt->compare(4, reply1, 2)) {
glist->addGame(ID_HL, pkt);
return PARSE_ACCEPT;
}
/* second query?! */
if (pkt->compare(4, reply2, 2)) {
glist->addGame(ID_HL2, pkt);
return PARSE_ACCEPT;
}
/* parse server IP */
pos = 5;
if ((count = pkt->parse_ip(pos, &tmp)) == 0)
return PARSE_REJECT;
/* parse server port */
pos += count +1;
if ((count = pkt->parse_int(pos, &port)) == 0)
return PARSE_REJECT;
// TODO: check server IP?
//glist->add(ID_HL, &tmp, port, 0);
glist->addGame(ID_HL, pkt);
return PARSE_ACCEPT;
}

View File

@ -3,10 +3,10 @@
#include "mod_q3engine.h"
static struct game_ports port_arr[] = {
{ 27960, 27960, ID_Q3A }, // q3(6), ef(7), et25), rtcw(8)
// { 28070, 28070, ID_JK2 }, // jk2(12)
// { 28960, 28963, ID_COD }, // cod(31), cod:uo(42), cod2(48)
// { 29070, 29070, ID_JK3 }, // jk3(27)
{ 27960, 27969, ID_Q3A }, // q3(6), ef(7), et25), rtcw(8)
{ 28070, 28070, ID_JK2 }, // jk2(12)
{ 28960, 28963, ID_COD }, // cod(31), cod:uo(42), cod2(48)
{ 29070, 29070, ID_JK3 }, // jk3(27)
{ 0,0,0 }
};

View File

@ -108,6 +108,6 @@ int MultiSock::sendto(NetPkt* pkt, struct sockaddr_in* dst)
delete it;
usleep(10000);
usleep(1000);
return 0;
}

View File

@ -8,25 +8,26 @@
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "logging.h"
#include "module.h"
#include "netpkt.h"
NetPkt::NetPkt(const char* data, int size)
: data(data), used(size), size(0)
: data(data), size(size), alloc(0)
{
}
NetPkt::NetPkt(int size)
: used(0), size(size)
NetPkt::NetPkt(int alloc)
: size(0), alloc(alloc)
{
data = new char[size];
data = new char[alloc];
}
NetPkt::~NetPkt()
{
if (size > 0)
if (alloc > 0)
delete data;
}
@ -35,27 +36,23 @@ int NetPkt::show(char* buf, int size)
return snprintf(buf, size, "(%s:%d) (%d/%d) bytes",
inet_ntoa(this->addr.sin_addr),
ntohs(this->addr.sin_port),
this->used, this->size);
this->size, this->alloc);
}
bool NetPkt::compare(int offset, const char* buf, int len)
bool NetPkt::compare(unsigned int offset, const char* buf, unsigned int len)
{
if (offset >= this->used)
if (offset + len >= this->size)
return false;
/* nicht ueber das paket hinaus vergleichen */
if (offset + len >= this->used)
len = this->used - offset;
return (memcmp(this->data + offset, buf, len) == 0);
}
int NetPkt::find(int offset, const char *buf, int len)
int NetPkt::find(unsigned int offset, const char *buf, unsigned int len)
{
if (offset >= this->used)
if (offset >= this->size)
return -1;
void* found = memmem(this->data + offset, this->used, buf, len);
void* found = memmem(this->data + offset, this->size, buf, len);
return (found == NULL) ? -1 : ((char*)found - this->data);
}
@ -69,3 +66,117 @@ struct sockaddr_in * NetPkt::getAddress()
{
return &addr;
}
int NetPkt::parse_int(unsigned int offset, int *val)
{
const char *max = this->data + this->size;
const char *c = this->data + offset;
/* untere grenze abtesten */
if (this->data > c || c > max)
return -1;
*val = 0;
/* ziffern einlesen */
while (isdigit(*c) && c < max)
*val = (*val * 10) + (*c++ - 0x30);
return (c - (this->data + offset));
}
int NetPkt::parse_ip(unsigned int offset, struct in_addr *ip)
{
int i, tmp, count, pos = offset;
ip->s_addr = 0;
for (i = 0; i < 4; i++) {
count = this->parse_int(pos, &tmp);
pos += count;
if (count == 0 || tmp < 0 || tmp > 255)
return 0;
ip->s_addr = ip->s_addr>>8 | tmp<<24;
if (i != 3 && this->data[pos++] != '.')
return 0;
}
return pos - offset;
}
int NetPkt::getPort()
{
return ntohs(addr.sin_port);
}
char* NetPkt::showfull()
{
unsigned int pos = 0, i = 0, j;
char *buf = new char[this->size * 4 + 64];
while (pos < this->size) {
i += sprintf(buf + i, "%04X: ", pos);
for (j = 0; j < 16; j++) {
if (pos + j < this->size)
i += sprintf(buf + i, "%02X", (unsigned char)this->data[pos + j]);
else
i += sprintf(buf + i, " ");
if (j % 2)
buf[i++] = ' ';
}
for (j = 0; j < 16; j++) {
if (pos + j < this->size) {
unsigned char val = this->data[pos + j];
if (val >= 0x20 && val < 0x80)
buf[i++] = val;
else
buf[i++] = '.';
} else {
buf[i++] = ' ';
}
}
pos += 16;
buf[i++] = '\r';
buf[i++] = '\n';
}
buf[i] = 0;
return buf;
}
int NetPkt::getSize()
{
return size;
}
bool NetPkt::sameAddress(NetPkt* pkt)
{
return (this->addr.sin_addr.s_addr == pkt->addr.sin_addr.s_addr) &&
(this->addr.sin_port == pkt->addr.sin_port);
}
void NetPkt::append(NetPkt* pkt)
{
char buf1[64], buf2[64];
this->show(buf1, sizeof(buf1));
pkt->show(buf2, sizeof(buf2));
LogSystem::log(LOG_DEBUG, "append (%s) + (%s)", buf1, buf2);
unsigned int new_alloc = size + pkt->size;
char* new_data = new char[new_alloc];
memcpy(new_data, data, size);
if (alloc)
delete data;
data = new_data;
alloc = new_alloc;
memcpy((void*)(data + size), pkt->data, pkt->size);
size += pkt->size;
delete pkt;
}

View File

@ -6,6 +6,8 @@
#define PARSE_ACCEPT 1
#define PARSE_ACCEPT_FREED 2
#define PARSE_ACCEPT_FAKE 3
#define PARSE_ACCEPT_QUIRK PARSE_ACCEPT
#define PARSE_REJECT 4
/* avoid cyclic deps */
@ -15,15 +17,26 @@ class NetPkt {
friend class Socket;
public:
NetPkt(const char* data, int size);
NetPkt(int size);
NetPkt(int alloc);
~NetPkt();
int show(char* buf, int size);
bool compare(int offset, const char* buf, int len);
int find(int offset, const char *buf, int len);
char* showfull();
bool compare(unsigned int offset, const char* buf, unsigned int len);
int find(unsigned int offset, const char *buf, unsigned int len);
int parse_int(unsigned int offset, int *val);
int parse_ip(unsigned int offset, struct in_addr *ip);
void setAddress(struct sockaddr_in *addr);
struct sockaddr_in * getAddress();
bool sameAddress(NetPkt* pkt);
void append(NetPkt* pkt);
int getPort();
int getSize();
protected:
NetPkt(const NetPkt& x);
@ -31,10 +44,10 @@ protected:
struct sockaddr_in addr;
const char *data;
int used;
unsigned int size;
private:
int size;
unsigned int alloc;
};
#endif // _NETPKT_H_

View File

@ -155,7 +155,7 @@ int Socket::sendto(NetPkt* pkt, struct sockaddr_in* dst) {
if (!dst)
dst = &pkt->addr;
if (::sendto(fd, pkt->data, pkt->used, 0, (struct sockaddr *)dst, sizeof(*dst)) < 0)
if (::sendto(fd, pkt->data, pkt->size, 0, (struct sockaddr *)dst, sizeof(*dst)) < 0)
LogSystem::log(LOG_WARN, "Socket::sendto()");
return 0;
}
@ -169,7 +169,7 @@ NetPkt* Socket::recv() {
NetPkt* pkt = new NetPkt(this->getRecvSize());
socklen_t i = sizeof(pkt->addr);
pkt->used = ::recvfrom(fd, (void*)pkt->data, pkt->size, 0, (struct sockaddr *)&pkt->addr, &i);
pkt->size = ::recvfrom(fd, (void*)pkt->data, pkt->alloc, 0, (struct sockaddr *)&pkt->addr, &i);
return pkt;
}

View File

@ -2,6 +2,8 @@
#include "timerservice.h"
// TODO: how to deregister TimerEvents?
Timer::Timer(Event* event, unsigned int timeval)
: next(0), event(event), timeval(timeval)
{