ServerBrowserRefresh.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <XML/XMLStringBuffer.h>
00022 #include <serverbrowser/ServerBrowserRefresh.h>
00023 #include <serverbrowser/ServerBrowser.h>
00024 #include <common/Defines.h>
00025 #include <time.h>
00026 
00027 ServerBrowserRefreshEntry::ServerBrowserRefreshEntry() :
00028         retries_(0), sentTime_(0), recieved_(0)
00029 {
00030 }
00031 
00032 ServerBrowserRefreshEntry::ServerBrowserRefreshEntry(
00033         const char *address,
00034         int position) : 
00035         address_(address),
00036         position_(position),
00037         retries_(0), sentTime_(0), recieved_(0)
00038 {
00039 }
00040 
00041 ServerBrowserRefresh::ServerBrowserRefresh(ServerBrowserServerList &list) :
00042         list_(list), 
00043         cancel_(false)
00044 {
00045         recvPacket_ = SDLNet_AllocPacket(10000);
00046         sendPacketStatus_ = SDLNet_AllocPacket(20);
00047         sendPacketStatus_->len = 7;
00048         memcpy(sendPacketStatus_->data, "status", 7);
00049         sendPacketPlayers_ = SDLNet_AllocPacket(20);
00050         sendPacketPlayers_->len = 8;
00051         memcpy(sendPacketPlayers_->data, "players", 8);
00052 }
00053 
00054 ServerBrowserRefresh::~ServerBrowserRefresh()
00055 {
00056 }
00057 
00058 void ServerBrowserRefresh::refreshList()
00059 {
00060         for (int i=0; i<list_.getNoEntries(); i++)
00061         {
00062                 const char *address = list_.getEntryValue(i, "address");
00063                 if (address && address[0])
00064                 {
00065                         ServerBrowserRefreshEntry entry(address, i);
00066                         refreshEntries_.push_back(entry);
00067                 }
00068         }
00069 
00070         while ((!refreshEntries_.empty() || !entryMap_.empty()) && !cancel_)
00071         {
00072                 time_t theTime = time(0);
00073 
00074                 // Add a number of new entries
00075                 for (int i=entryMap_.size(); i<20 && !refreshEntries_.empty(); i++)
00076                 {
00077                         ServerBrowserRefreshEntry entry = refreshEntries_.front();
00078                         refreshEntries_.pop_front();
00079 
00080                         sendNextEntry(entry, theTime);
00081                 }
00082                 SDL_Delay(1000);
00083 
00084                 // Process all new messages
00085                 processMessages(theTime);
00086         }
00087 
00088         // Tidy incase of cancel
00089         std::map<UDPsocket, ServerBrowserRefreshEntry>::iterator cleanitor;
00090         for (cleanitor = entryMap_.begin();
00091                 cleanitor != entryMap_.end();
00092                 cleanitor++)
00093         {
00094                 UDPsocket socket = (*cleanitor).first;
00095                 SDLNet_UDP_Close(socket);
00096         }
00097         refreshEntries_.clear();
00098         entryMap_.clear();
00099 }
00100 
00101 void ServerBrowserRefresh::sendNextEntry(
00102         ServerBrowserRefreshEntry &entry, time_t theTime)
00103 {
00104         char buffer[256];
00105         snprintf(buffer, sizeof(buffer), "%s", entry.address_.c_str());
00106         char *port = strchr(buffer, ':');
00107         if (!port) return;
00108         *port = '\0';
00109         port++;
00110 
00111         IPaddress address;
00112         if (SDLNet_ResolveHost(&address, buffer, atoi(port)+1) != 0) return;
00113 
00114         // Connect to the client
00115         UDPsocket udpsock = SDLNet_UDP_Open(0);
00116         if (!udpsock) return;
00117 
00118         int chan = SDLNet_UDP_Bind(udpsock, -1, &address);
00119         if (chan == -1) return;
00120 
00121         // Add the client to the map of currently processed clients
00122         entry.retries_ ++;
00123         entry.sentTime_ = (unsigned int) theTime;
00124         entry.recieved_ = 0;
00125         entryMap_[udpsock] = entry;
00126 
00127         // Send the request for info
00128         SDLNet_UDP_Send(udpsock, chan, sendPacketStatus_);
00129         SDLNet_UDP_Send(udpsock, chan, sendPacketPlayers_);
00130 }
00131 
00132 void ServerBrowserRefresh::processMessages(time_t theTime)
00133 {
00134         std::list<UDPsocket> finished;
00135         std::map<UDPsocket, ServerBrowserRefreshEntry>::iterator itor;
00136         for (itor = entryMap_.begin();
00137                 itor != entryMap_.end();
00138                 itor++)
00139         {
00140                 UDPsocket socket = (*itor).first;
00141                 ServerBrowserRefreshEntry &entry = (*itor).second;
00142 
00143                 if (theTime - entry.sentTime_ > 5)
00144                 {
00145                         if (entry.retries_ < 3) refreshEntries_.push_back(entry);
00146                         finished.push_back(socket);
00147                 }
00148                 else
00149                 {
00150                         while (SDLNet_UDP_Recv(socket, recvPacket_))
00151                         {
00152                                 processMessage(recvPacket_, entry);
00153                                 entry.recieved_ ++;
00154 
00155                                 if (entry.recieved_ == 2) finished.push_back(socket);
00156                         }
00157                 }
00158         }
00159 
00160         while (finished.size())
00161         {
00162                 UDPsocket socket = finished.front();
00163                 finished.pop_front();
00164 
00165                 entryMap_.erase(socket);
00166                 SDLNet_UDP_Close(socket);
00167         }
00168 }
00169 
00170 void ServerBrowserRefresh::processMessage(UDPpacket *packet, ServerBrowserRefreshEntry &entry)
00171 {
00172         const char *buffer = (char *) packet->data;
00173         unsigned int len = packet->len - 1;
00174 
00175         // Parse the buffer
00176         XMLStringBuffer xmlBuffer;
00177         if (xmlBuffer.create(buffer, len))
00178         {
00179                 // Itterate all of the keys in the buffer
00180                 std::list<XMLNode *>::iterator childrenItor;
00181                 std::list<XMLNode *> &children = xmlBuffer.getRootNode()->getParameters();
00182                 for (childrenItor = children.begin();
00183                         childrenItor != children.end();
00184                         childrenItor++)
00185                 {
00186                         XMLNode *currentNode = (*childrenItor);
00187                         list_.addEntryValue(entry.position_,
00188                                 currentNode->getName(),
00189                                 currentNode->getContent());
00190                 }
00191         }
00192 }
00193 

Generated on Mon Feb 16 15:14:47 2009 for Scorched3D by  doxygen 1.5.3