NetServerTCP3.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/NetServerTCP3.h>
00022 #include <net/NetMessagePool.h>
00023 #include <net/NetOptions.h>
00024 #include <common/Logger.h>
00025 #include <common/Clock.h>
00026 #include <limits.h>
00027 
00028 NetServerTCP3::NetServerTCP3() : 
00029         serverDestinationId_(UINT_MAX), nextDestinationId_(1),
00030         sendRecvThread_(0),
00031         serverSock_(0), serverSockSet_(0),
00032         stopped_(false)
00033 {
00034         NetOptions::instance()->readOptionsFromFile();
00035         NetOptions::instance()->writeOptionsToFile();
00036 
00037         serverSockSet_ = SDLNet_AllocSocketSet(1);
00038 }
00039 
00040 NetServerTCP3::~NetServerTCP3()
00041 {
00042         SDLNet_FreeSocketSet(serverSockSet_);
00043         serverSockSet_ = 0;
00044 }
00045 
00046 bool NetServerTCP3::started()
00047 {
00048         // Do we have a valid send/recieve thread
00049         return (sendRecvThread_ != 0);
00050 }
00051 
00052 bool NetServerTCP3::connect(const char *hostName, int portNo)
00053 {
00054         if(SDLNet_Init()==-1)
00055         {
00056                 return false;
00057         }
00058 
00059         // Resolve server address
00060         IPaddress serverAddress;
00061         if (SDLNet_ResolveHost(&serverAddress, hostName, portNo) != 0)
00062         {
00063                 Logger::log(S3D::formatStringBuffer("NetServerTCP3: Failed to resolve host %s:%i",
00064                         hostName, portNo));
00065                 return false;
00066         }
00067 
00068         // Stop any previous connections
00069         stop();
00070 
00071         // Create a new socket for the client
00072         TCPsocket clientSock = SDLNet_TCP_Open(&serverAddress);
00073         if (!clientSock)
00074         {
00075                 Logger::log(S3D::formatStringBuffer("NetServerTCP3: Failed to open client socket : %s",
00076                         SDLNet_GetError()));
00077                 return false;
00078         }
00079 
00080         // Add client socket
00081         serverDestinationId_ = addDestination(clientSock);
00082 
00083         // Start sending/recieving on the anon port
00084         if (!startProcessing()) return false;
00085 
00086         return true;
00087 }
00088 
00089 bool NetServerTCP3::start(int portNo)
00090 {
00091         if(SDLNet_Init()==-1)
00092         {
00093                 return false;
00094         }
00095 
00096         // Stop any previous connections
00097         stop();
00098 
00099         // Get the local ip address
00100         IPaddress localip;
00101         if(SDLNet_ResolveHost(&localip, NULL, portNo)==-1)
00102         {
00103                 return false;
00104         }
00105 
00106         // we seem to be able to open the same port
00107         // multiple times!!!
00108         // This is fixed as the server info port catches it
00109         serverSock_ = SDLNet_TCP_Open(&localip);
00110         if (!serverSock_)
00111         {
00112                 Logger::log(S3D::formatStringBuffer("NetServerTCP3: Failed to open server socket %i", portNo));
00113                 return false;
00114         }
00115         SDLNet_TCP_AddSocket(serverSockSet_, serverSock_);
00116 
00117         // Start sending/recieving on this socket
00118         if (!startProcessing()) return false;
00119 
00120         return true;
00121 }
00122 
00123 void NetServerTCP3::stop()
00124 {
00125         if (started())
00126         {
00127                 disconnectAllClients();
00128                 while (started()) SDL_Delay(100);
00129         }
00130 }
00131 
00132 bool NetServerTCP3::startProcessing()
00133 {
00134         // Check if we are already running
00135         DIALOG_ASSERT(!sendRecvThread_);
00136 
00137         // We are going to process all incoming message
00138         outgoingMessageHandler_.setMessageHandler(this);
00139 
00140         // Create the processing thread
00141         sendRecvThread_ = SDL_CreateThread(
00142                 NetServerTCP3::sendRecvThreadFunc, (void *) this);
00143         if (sendRecvThread_ == 0)
00144         {
00145                 Logger::log(S3D::formatStringBuffer("NetServerTCP3: Failed to create NetServerTCP3 thread"));
00146                 return false;
00147         }
00148 
00149         return true;
00150 }
00151 
00152 int NetServerTCP3::sendRecvThreadFunc(void *c)
00153 {
00154         // Call a non-static class thread to do the processing in (just for convienience)
00155         NetServerTCP3 *th = (NetServerTCP3*) c;
00156         th->actualSendRecvFunc();
00157 
00158         th->sendRecvThread_ = 0;
00159         Logger::log(S3D::formatStringBuffer("NetServerTCP3: shutdown"));
00160         return 0;
00161 }
00162 
00163 void NetServerTCP3::actualSendRecvFunc()
00164 {
00165         float timeDiff;
00166         stopped_ = false;
00167         Clock netClock;
00168         while(!stopped_)
00169         {
00170                 // Send/recv packets
00171                 checkClients();
00172                 timeDiff = netClock.getTimeDifference();
00173                 if (timeDiff > 1.0f)
00174                 {
00175                         Logger::log(S3D::formatStringBuffer(
00176                                 "NetServerTCP3: checkClients took %.2f seconds", 
00177                                 timeDiff));
00178                 }
00179 
00180                 // Check for new connections
00181                 checkNewConnections();
00182                 timeDiff = netClock.getTimeDifference();
00183                 if (timeDiff > 1.0f)
00184                 {
00185                         Logger::log(S3D::formatStringBuffer(
00186                                 "NetServerTCP3: checkNewConnections took %.2f seconds", 
00187                                 timeDiff));
00188                 }
00189 
00190                 // sleep so we don't go into an infinite loop
00191                 SDL_Delay(10);
00192                 netClock.getTimeDifference();
00193 
00194                 // Check for any new messages we should send and process them
00195                 outgoingMessageHandler_.processMessages();
00196                 timeDiff = netClock.getTimeDifference();
00197                 if (timeDiff > 1.0f)
00198                 {
00199                         Logger::log(S3D::formatStringBuffer(
00200                                 "NetServerTCP3: processMessages took %.2f seconds", 
00201                                 timeDiff));
00202                 }
00203         }
00204 
00205         if (serverSock_) SDLNet_TCP_Close(serverSock_);
00206         serverSock_ = 0;
00207 }
00208 
00209 void NetServerTCP3::checkNewConnections()
00210 {
00211         if (!serverSock_) return; // Check if we are running a server
00212 
00213         int numready = SDLNet_CheckSockets(serverSockSet_, 10);
00214         if (numready == -1) return;
00215         if (numready == 0) return;
00216 
00217         if(SDLNet_SocketReady(serverSock_))
00218         {
00219                 TCPsocket clientSock = SDLNet_TCP_Accept(serverSock_);
00220                 if (clientSock)
00221                 {
00222                         // add client
00223                         addDestination(clientSock);
00224                 }
00225         }
00226 }
00227 
00228 void NetServerTCP3::checkClients()
00229 {
00230         // Check each destination to see if it has closed
00231         std::map<unsigned int, NetServerTCP3Destination *>::iterator itor;
00232         for (itor = destinations_.begin();
00233                 itor != destinations_.end();
00234                 itor++)
00235         {
00236                 NetServerTCP3Destination *destination = itor->second;
00237                 if (destination->anyFinished())
00238                 {
00239                         destroyDestination(itor->first, NetMessage::UserDisconnect);
00240                         break;
00241                 }
00242         }
00243 
00244         // Check each destination that is closing to see if it has finished
00245         if (finishedDestinations_.empty()) return;
00246 
00247         NetServerTCP3Destination *destination = finishedDestinations_.front();
00248         if (destination->allFinished())
00249         {
00250                 delete destination;
00251                 finishedDestinations_.pop_front();
00252         }
00253 }
00254 
00255 void NetServerTCP3::processMessage(NetMessage &message)
00256 {
00257         // We have been told to send a message to a client
00258 
00259         // Check if we have been told to disconect all clients
00260         if (message.getMessageType() == NetMessage::DisconnectAllMessage)
00261         {
00262                 // Foreach client
00263                 while (!destinations_.empty())
00264                 {
00265                         // Get the first client
00266                         std::map<unsigned int, NetServerTCP3Destination *>::iterator itor =
00267                                 destinations_.begin();
00268                         unsigned int destinationId = (*itor).first;
00269                         NetServerTCP3Destination *destination = (*itor).second;
00270 
00271                         // This is a message telling us to kick the client, do so
00272                         destroyDestination(destinationId, NetMessage::KickDisconnect);
00273                 }
00274 
00275                 stopped_ = true;
00276                 return;
00277         }
00278 
00279         // Look up this destination in the list of current
00280         std::map<unsigned int, NetServerTCP3Destination *>::iterator itor = 
00281                 destinations_.find(message.getDestinationId());
00282         if (itor == destinations_.end())
00283         {
00284                 return;
00285         }
00286 
00287         NetServerTCP3Destination *destination = (*itor).second;
00288         if (message.getMessageType() == NetMessage::DisconnectMessage)
00289         {
00290                 // This is a message telling us to kick the client, do so
00291                 destroyDestination(message.getDestinationId(), NetMessage::KickDisconnect);
00292         }
00293         else
00294         {
00295                 // Add this buffer to the list of items to be sent
00296                 NetMessage *newMessage = NetMessagePool::instance()->getFromPool(
00297                         message.getMessageType(), message.getDestinationId(),
00298                         message.getIpAddress(), message.getFlags());
00299                 newMessage->getBuffer().allocate(message.getBuffer().getBufferUsed());
00300                 memcpy(newMessage->getBuffer().getBuffer(), 
00301                         message.getBuffer().getBuffer(),
00302                         message.getBuffer().getBufferUsed());
00303                 newMessage->getBuffer().setBufferUsed(message.getBuffer().getBufferUsed());
00304 
00305                 destination->sendMessage(newMessage);
00306         }
00307 }
00308 
00309 void NetServerTCP3::disconnectAllClients()
00310 {
00311         // Get a new buffer from the pool (with the discconect type set)
00312         NetMessage *message = NetMessagePool::instance()->
00313                 getFromPool(NetMessage::DisconnectAllMessage, 0, 0);
00314 
00315         // Send Mesage
00316         outgoingMessageHandler_.addMessage(message);
00317 }
00318 
00319 void NetServerTCP3::disconnectClient(unsigned int destination)
00320 {
00321         // Get a new buffer from the pool (with the discconect type set)
00322         NetMessage *message = NetMessagePool::instance()->
00323                 getFromPool(NetMessage::DisconnectMessage, destination, 0);
00324 
00325         // Send Mesage
00326         outgoingMessageHandler_.addMessage(message);
00327 }
00328 
00329 void NetServerTCP3::sendMessageServer(NetBuffer &buffer, 
00330         unsigned int flags)
00331 {
00332         // Send a message to the server
00333         sendMessageDest(buffer, serverDestinationId_, flags);
00334 }
00335 
00336 void NetServerTCP3::sendMessageDest(NetBuffer &buffer, 
00337         unsigned int destination, unsigned int flags)
00338 {
00339         // Get a new buffer from the pool
00340         NetMessage *message = NetMessagePool::instance()->
00341                 getFromPool(NetMessage::BufferMessage, 
00342                                 destination, 0, flags);
00343 
00344         // Add message to new buffer
00345         message->getBuffer().allocate(buffer.getBufferUsed());
00346         memcpy(message->getBuffer().getBuffer(), 
00347                 buffer.getBuffer(), buffer.getBufferUsed());
00348         message->getBuffer().setBufferUsed(buffer.getBufferUsed());
00349 
00350         // Send Mesage
00351         outgoingMessageHandler_.addMessage(message);
00352 }
00353 
00354 int NetServerTCP3::processMessages()
00355 {
00356         // Process any messages that we have recieved
00357         return incomingMessageHandler_.processMessages();
00358 }
00359 
00360 void NetServerTCP3::setMessageHandler(NetMessageHandlerI *handler)
00361 {
00362         // Set the message handler to process any messages that we recieve
00363         incomingMessageHandler_.setMessageHandler(handler);
00364 }
00365 
00366 void NetServerTCP3::destroyDestination(unsigned int destinationId,
00367         NetMessage::DisconnectFlags type)
00368 {
00369         // Destroy this destination
00370         std::map<unsigned int, NetServerTCP3Destination *>::iterator itor =
00371                 destinations_.find(destinationId);
00372         if (itor == destinations_.end())
00373         {
00374                 return;
00375         }
00376 
00377         if (serverDestinationId_ == destinationId)
00378         {
00379                 stopped_ = true;
00380                 serverDestinationId_ = UINT_MAX;
00381         }
00382 
00383         NetServerTCP3Destination *destination = (*itor).second;
00384 
00385         // Get a new buffer from the pool (with the discconect type set)
00386         NetMessage *message = NetMessagePool::instance()->
00387                 getFromPool(NetMessage::DisconnectMessage, 
00388                         destinationId, destination->getIpAddress());
00389         message->setFlags((unsigned int) type);
00390 
00391         destinations_.erase(itor);
00392         destination->printStats();
00393         destination->close();
00394         finishedDestinations_.push_back(destination);
00395 
00396         // Add to outgoing message pool
00397         incomingMessageHandler_.addMessage(message);
00398 }
00399 
00400 unsigned int NetServerTCP3::addDestination(TCPsocket &socket)
00401 {
00402         NetInterface::getConnects() ++;
00403 
00404         // Allocate new destination id
00405         do {
00406                 nextDestinationId_++;
00407         } while (nextDestinationId_ == 0 || nextDestinationId_ == UINT_MAX);
00408         unsigned int destinationId = nextDestinationId_;
00409 
00410         // Create new destination 
00411         NetServerTCP3Destination *destination = 
00412                 new NetServerTCP3Destination(
00413                         &incomingMessageHandler_, socket, destinationId);
00414         destinations_[destinationId] = destination;
00415 
00416         // Get a new buffer from the pool (with the connect type set)
00417         NetMessage *message = NetMessagePool::instance()->
00418                 getFromPool(NetMessage::ConnectMessage, 
00419                         destinationId, destination->getIpAddress());
00420         incomingMessageHandler_.addMessage(message);
00421 
00422         // Return new id
00423         return destinationId;
00424 }

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