daily work
This commit is contained in:
parent
e0b98f4756
commit
33e97b1eaa
2
config.h
2
config.h
|
@ -34,6 +34,8 @@ private:
|
|||
~SectionIterator();
|
||||
bool hasNext();
|
||||
char* next();
|
||||
void add(char* part) {}
|
||||
void remove() {}
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
258
list.h
|
@ -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_
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
251
mod_gamespy1.cpp
251
mod_gamespy1.cpp
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -108,6 +108,6 @@ int MultiSock::sendto(NetPkt* pkt, struct sockaddr_in* dst)
|
|||
|
||||
delete it;
|
||||
|
||||
usleep(10000);
|
||||
usleep(1000);
|
||||
return 0;
|
||||
}
|
||||
|
|
141
netpkt.cpp
141
netpkt.cpp
|
@ -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;
|
||||
}
|
||||
|
|
23
netpkt.h
23
netpkt.h
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue