/*************************************************************************** * Copyright (C) 04/2006 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include "hlswserver.h" #include "logging.h" static const char hlsw_header[] = "\xFF\xFF\xFF\xFFHLSWLANSEARCH"; struct hlsw_entry { uint16_t gameid; uint32_t ip; uint16_t port1; 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::HlswServer(Config& conf, GameList& glist) { 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 List(); } HlswServer::~HlswServer() { while (!pktlist->isEmpty()) delete pktlist->get(); delete pktlist; delete socket; } int HlswServer::execute(void* arg) { while (1) { NetPkt* pkt = socket->recv(); if (!pkt->compare(0, hlsw_header, strlen(hlsw_header))) { LogSystem::log(LOG_NOTICE, "HlswServer: not a hlsw packet"); continue; } mutex.lock(); Iterator* it = pktlist->createIterator(); while (it->hasNext()) socket->sendto(it->next(), pkt->getAddress()); delete it; mutex.unlock(); } return 0; } void HlswServer::rebuild(GameList& glist) { List* newlist = new List(); // header NetPkt* pkt = new NetPkt(HLSW_MAX_PACKET_SIZE); pkt->append(hlsw_header, sizeof(hlsw_header)); newlist->add(pkt); Iterator* it = glist.createIterator(); while (it->hasNext()) { NetPkt* last = newlist->peekTail(); if (last->getSize() == HLSW_MAX_PACKET_SIZE) { last = new NetPkt(HLSW_MAX_PACKET_SIZE); last->append(hlsw_header, sizeof(hlsw_header)); newlist->add(last); } addGame(last, it->next()); } delete it; mutex.lock(); List* oldlist = pktlist; pktlist = newlist; mutex.unlock(); while (!oldlist->isEmpty()) delete oldlist->get(); delete oldlist; } void HlswServer::addGame(NetPkt* pkt, GameEntry* entry) { struct hlsw_entry tmp; tmp.gameid = entry->gameid; tmp.ip = entry->addr.s_addr; tmp.port1 = entry->port1; tmp.port2 = entry->port2; pkt->append((char*)&tmp, sizeof(tmp)); }