NetServerTCP.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 <net/NetServerTCP.h>
00022 #include <net/NetBufferUtil.h>
00023 #include <net/NetMessageHandler.h>
00024 #include <net/NetMessagePool.h>
00025 #include <common/Defines.h>
00026 #include <common/Logger.h>
00027 #include <common/Clock.h>
00028 
00029 NetServerTCP::NetServerTCP(NetServerTCPProtocol *protocol) : 
00030         sockSet_(0), firstDestination_(0),
00031         server_(0), protocol_(protocol), checkDeleted_(false),
00032         lastId_(0)
00033 {
00034         sockSet_ = SDLNet_AllocSocketSet(1);
00035         setMutex_ = SDL_CreateMutex();
00036         SDL_CreateThread(NetServerTCP::threadFunc, (void *) this);
00037 }
00038 
00039 NetServerTCP::~NetServerTCP()
00040 {
00041         SDL_DestroyMutex(setMutex_); 
00042         setMutex_ = 0;
00043         SDLNet_FreeSocketSet(sockSet_);
00044         sockSet_ = 0;
00045 }
00046 
00047 void NetServerTCP::setMessageHandler(NetMessageHandlerI *handler) 
00048 { 
00049         messageHandler_.setMessageHandler(handler); 
00050 }
00051 
00052 int NetServerTCP::processMessages()
00053 { 
00054         return messageHandler_.processMessages(); 
00055 }
00056 
00057 bool NetServerTCP::started()
00058 {
00059         return (server_ != 0 || firstDestination_ != 0);
00060 }
00061 
00062 bool NetServerTCP::start(int port)
00063 {
00064         if(SDLNet_Init()==-1)
00065         {
00066                 return false;
00067         }
00068 
00069         IPaddress ip;
00070         if(SDLNet_ResolveHost(&ip,NULL,port)==-1)
00071         {
00072                 return false;
00073         }
00074 
00075         // we seem to be able to open the same port
00076         // multiple times!!!
00077         // This is fixed as the server info port catches it
00078         server_=SDLNet_TCP_Open(&ip);
00079         if (!server_)
00080         {
00081                 return false;
00082         }
00083         NetBufferUtil::setBlockingIO(server_);
00084         SDLNet_TCP_AddSocket(sockSet_, server_);
00085 
00086         return true;
00087 }
00088 
00089 void NetServerTCP::stop()
00090 {
00091         disconnectAllClients();
00092 }
00093 
00094 bool NetServerTCP::connect(const char *hostName, int portNo)
00095 {
00096         if(SDLNet_Init()==-1)
00097         {
00098                 return false;
00099         }
00100 
00101         IPaddress ip;
00102         if(SDLNet_ResolveHost(&ip,(char *) hostName,portNo)==-1)
00103         {
00104                 return false;
00105         }
00106 
00107         TCPsocket client=SDLNet_TCP_Open(&ip);
00108         if (!client)
00109         {
00110                 return false;
00111         }
00112         NetBufferUtil::setBlockingIO(client);
00113 
00114         addClient(client);
00115         return true;
00116 }
00117 
00118 int NetServerTCP::threadFunc(void *param)
00119 {
00120         NetServerTCP *netServer = (NetServerTCP *) param;
00121 
00122         Clock netClock;
00123         for (;;)
00124         {
00125                 netClock.getTimeDifference();
00126 
00127                 if (netServer->server_) 
00128                 {
00129                         netServer->pollIncoming();
00130                 }
00131                 if (netServer->checkDeleted_)
00132                 {
00133                         netServer->checkDeleted_ = false;
00134                         netServer->pollDeleted();
00135                 }
00136 
00137                 float timeDiff = netClock.getTimeDifference();
00138                 if (timeDiff > 1.0f)
00139                 {
00140                         Logger::log(S3D::formatStringBuffer("Warning: Net loop took %.2f seconds, server", 
00141                                 timeDiff));
00142                 }
00143 
00144                 SDL_Delay(100);
00145         }
00146 
00147         return 0;
00148 }
00149 
00150 bool NetServerTCP::pollIncoming()
00151 {
00152         DIALOG_ASSERT(sockSet_ && server_);
00153         int numready = SDLNet_CheckSockets(sockSet_, 10);
00154         if (numready == -1) return false;
00155         if (numready == 0) return true;
00156 
00157         if(SDLNet_SocketReady(server_))
00158         {
00159                 TCPsocket sock = SDLNet_TCP_Accept(server_);
00160                 if (sock)
00161                 {
00162                         NetBufferUtil::setBlockingIO(sock);
00163                         addClient(sock);
00164                         getConnects()++;
00165                 }
00166         }
00167 
00168         return true;
00169 }
00170 
00171 bool NetServerTCP::pollDeleted()
00172 {
00173         SDL_LockMutex(setMutex_);
00174         std::list<unsigned int> remove;
00175         std::map<unsigned int, NetServerTCPRead *>::iterator itor;
00176         for (itor = connections_.begin();
00177                 itor != connections_.end();
00178                 itor++)
00179         {
00180                 NetServerTCPRead *serverRead = (*itor).second;
00181                 unsigned int id = (*itor).first;
00182                 if (serverRead->getDisconnect())
00183                 {
00184                         delete serverRead;
00185                         remove.push_back(id);
00186                 }
00187         }
00188         std::list<unsigned int>::iterator itor2;
00189         for (itor2 = remove.begin();
00190                 itor2 != remove.end();
00191                 itor2++)
00192         {
00193                 unsigned int id = (*itor2);
00194                 connections_.erase(id);
00195         }
00196         SDL_UnlockMutex(setMutex_);
00197         return true;
00198 }
00199 
00200 void NetServerTCP::addClient(TCPsocket client)
00201 {
00202         // Calculate the current client id
00203         // Mutex protect incase addClient is called from different threads
00204         // (unlikely)
00205         SDL_LockMutex(setMutex_);
00206         if (++lastId_ == 0) ++lastId_;
00207         unsigned int currentId = lastId_;
00208         SDL_UnlockMutex(setMutex_);
00209 
00210         // Create the thread to read this socket
00211         NetServerTCPRead *serverRead = new NetServerTCPRead(
00212                 currentId, client, protocol_, &messageHandler_, &checkDeleted_);
00213 
00214         // Add this to the collection of sockets (connections)
00215         SDL_LockMutex(setMutex_);
00216         connections_[currentId] = serverRead;
00217         firstDestination_ = currentId;
00218         SDL_UnlockMutex(setMutex_);
00219 
00220         // Start the sockets
00221         serverRead->start();
00222 }
00223 
00224 void NetServerTCP::disconnectAllClients()
00225 {
00226         SDL_LockMutex(setMutex_);
00227         std::map<unsigned int, NetServerTCPRead *>::iterator itor;
00228         for (itor = connections_.begin();
00229                 itor != connections_.end();
00230                 itor++)
00231         {
00232                 unsigned int id = (*itor).first;
00233                 disconnectClient(id);
00234         }
00235         SDL_UnlockMutex(setMutex_);
00236 }
00237 
00238 void NetServerTCP::disconnectClient(unsigned int dest)
00239 {
00240         NetMessage *message = NetMessagePool::instance()->
00241                 getFromPool(NetMessage::DisconnectMessage, 
00242                                 dest, getIpAddress(dest));
00243 
00244         // Add the message to the list of out going
00245         sendMessage(dest, message);
00246 }
00247 
00248 void NetServerTCP::sendMessageServer(NetBuffer &buffer, 
00249         unsigned int flags)
00250 {
00251         sendMessageDest(buffer, firstDestination_, flags);
00252 }
00253 
00254 void NetServerTCP::sendMessageDest(NetBuffer &buffer, 
00255         unsigned int destination, unsigned int flags)
00256                                                         
00257 {
00258         // Get a new buffer from the pool
00259         NetMessage *message = NetMessagePool::instance()->
00260                 getFromPool(NetMessage::NoMessage, 
00261                                 destination, getIpAddress(destination), flags);
00262 
00263         // Add message to new buffer
00264         message->getBuffer().allocate(buffer.getBufferUsed());
00265         memcpy(message->getBuffer().getBuffer(), 
00266                 buffer.getBuffer(), buffer.getBufferUsed());
00267         message->getBuffer().setBufferUsed(buffer.getBufferUsed());
00268 
00269         // Send Mesage
00270         sendMessage(destination, message);
00271 }
00272 
00273 void NetServerTCP::sendMessage(unsigned int client, NetMessage *message)
00274 {
00275         // Find the client
00276         SDL_LockMutex(setMutex_);
00277         std::map<unsigned int, NetServerTCPRead *>::iterator itor = 
00278                 connections_.find(client);
00279         if (itor != connections_.end()) 
00280         {
00281                 // Add the message to the list of out going
00282                 NetServerTCPRead *serverRead = (*itor).second;
00283                 serverRead->addMessage(message);
00284         }
00285         else
00286         {
00287                 NetMessagePool::instance()->addToPool(message);
00288                 Logger::log(S3D::formatStringBuffer("Unknown sendMessage destination %u",
00289                         client));
00290         }
00291         SDL_UnlockMutex(setMutex_);
00292 }
00293 
00294 unsigned int NetServerTCP::getIpAddress(unsigned int destination)
00295 {
00296         unsigned int addr = 0;
00297         SDL_LockMutex(setMutex_);
00298         std::map<unsigned int, NetServerTCPRead *>::iterator itor = 
00299                 connections_.find(destination);
00300         if (itor != connections_.end()) 
00301         {
00302                 NetServerTCPRead *read = (*itor).second;
00303                 addr = read->getIpAddress();
00304         }
00305         SDL_UnlockMutex(setMutex_);
00306 
00307         return addr;
00308 }
00309 

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