#include #include #include #include #include #include #include "config.h" #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; uint16_t port1; uint16_t port2; } __attribute__ ((packed)); HlswServer::HlswPacket::HlswPacket(HlswPacket* next) : NetPkt(1418), next(next) { memcpy((void*)data, hlsw_header, sizeof(hlsw_header)); used = sizeof(hlsw_header); } HlswServer::HlswPacket::~HlswPacket() { if (next) delete next; } bool HlswServer::HlswPacket::addGame(GameEntry* ge) { if (used >= 1418) return false; struct hlsw_entry tmp; tmp.gameid = ge->gameid; tmp.ip = ge->addr.s_addr; tmp.port1 = ge->port1; tmp.port2 = ge->port2; memcpy((void*)(data + used), &tmp, sizeof(tmp)); used += sizeof(tmp); return true; } void HlswServer::HlswPacket::send(Socket* socket, struct sockaddr_in* dst) { if (next) next->send(socket, dst); socket->sendto(this, dst); } HlswServer::HlswServer(Config& conf, GameList& glist) : lastUpdate(0) { const char *ip = conf.getString("global", "master_ip", "0.0.0.0"); LogSystem::log(LOG_NOTICE, "HlswServer listen on %s:%d", ip, HLSW_MASTER_PORT); struct sockaddr_in dst; dst.sin_family = AF_INET; dst.sin_port = htons(HLSW_MASTER_PORT); inet_aton(ip, &dst.sin_addr); socket = Socket::createSocket(&dst); int interval = conf.getInteger("global", "rebuild_interval", DEFAULT_REBUILD_INTERVAL); TimerService::registerTimer(new Timer(new RebuildEvent(*this, glist), interval)); pktlist = new HlswPacket(NULL); } HlswServer::~HlswServer() { delete pktlist; delete socket; } int HlswServer::execute(void* arg) { while (1) { NetPkt* pkt = socket->recv(); if (!pkt->compare(0, hlsw_header, sizeof(hlsw_header))) { LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet"); continue; } mutex.lock(); pktlist->send(socket, pkt->getAddress()); mutex.unlock(); } return 0; } void HlswServer::rebuild(GameList& glist) { if (glist.getLastUpdate() > lastUpdate) { HlswPacket* newlist = new HlswPacket(NULL); Iterator* it = glist.createIterator(); while (it->hasNext()) { GameEntry* d = it->next(); if (!newlist->addGame(d)) { newlist = new HlswPacket(newlist); newlist->addGame(d); } } lastUpdate = glist.getLastUpdate(); delete it; mutex.lock(); HlswPacket* oldlist = pktlist; pktlist = newlist; mutex.unlock(); delete oldlist; } }