NetServerTCP2.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/NetServerTCP2.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 NetServerTCP2::NetServerTCP2() : 
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 NetServerTCP2::~NetServerTCP2()
00041 {
00042         SDLNet_FreeSocketSet(serverSockSet_);
00043         serverSockSet_ = 0;
00044 }
00045 
00046 bool NetServerTCP2::started()
00047 {
00048         // Do we have a valid send/recieve thread
00049         return (sendRecvThread_ != 0);
00050 }
00051 
00052 bool NetServerTCP2::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("NetServerTCP2: 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("NetServerTCP2: 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 NetServerTCP2::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("NetServerTCP2: 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 NetServerTCP2::stop()
00124 {
00125         if (started())
00126         {
00127                 disconnectAllClients();
00128                 while (started()) SDL_Delay(100);
00129         }
00130 }
00131 
00132 bool NetServerTCP2::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                 NetServerTCP2::sendRecvThreadFunc, (void *) this);
00143         if (sendRecvThread_ == 0)
00144         {
00145                 Logger::log(S3D::formatStringBuffer("NetServerTCP2: Failed to create NetServerTCP2 thread"));
00146                 return false;
00147         }
00148 
00149         return true;
00150 }
00151 
00152 int NetServerTCP2::sendRecvThreadFunc(void *c)
00153 {
00154         // Call a non-static class thread to do the processing in (just for convienience)
00155         NetServerTCP2 *th = (NetServerTCP2*) c;
00156         th->actualSendRecvFunc();
00157 
00158         th->sendRecvThread_ = 0;
00159         Logger::log(S3D::formatStringBuffer("NetServerTCP2: shutdown"));
00160         return 0;
00161 }
00162 
00163 void NetServerTCP2::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                                 "NetServerTCP2: 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                                 "NetServerTCP2: 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                                 "NetServerTCP2: processMessages took %.2f seconds", 
00201                                 timeDiff));
00202                 }
00203         }
00204 
00205         if (serverSock_) SDLNet_TCP_Close(serverSock_);
00206         serverSock_ = 0;
00207 }
00208 
00209 void NetServerTCP2::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 NetServerTCP2::checkClients()
00229 {
00230         // Check each destination to see if it has closed
00231         std::map<unsigned int, NetServerTCP2Destination *>::iterator itor;
00232         for (itor = destinations_.begin();
00233                 itor != destinations_.end();
00234                 itor++)
00235         {
00236                 NetServerTCP2Destination *destination = itor->second;
00237                 if (destination->finished())
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         NetServerTCP2Destination *destination = finishedDestinations_.front();
00248         if (destination->finished())
00249         {
00250                 delete destination;
00251                 finishedDestinations_.pop_front();
00252         }
00253 }
00254 
00255 void NetServerTCP2::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, NetServerTCP2Destination *>::iterator itor =
00267                                 destinations_.begin();
00268                         unsigned int destinationId = (*itor).first;
00269                         NetServerTCP2Destination *destination = (*itor).second;
00270 
00271                         // This is a message telling us to kick the client, do so
00272                         //Logger::log(S3D::formatStringBuffer("Disconnected %u - kicked", destinationId));
00273                         destroyDestination(destinationId, NetMessage::KickDisconnect);
00274                 }
00275 
00276                 stopped_ = true;
00277                 return;
00278         }
00279 
00280         // Look up this destination in the list of current
00281         std::map<unsigned int, NetServerTCP2Destination *>::iterator itor = 
00282                 destinations_.find(message.getDestinationId());
00283         if (itor == destinations_.end())
00284         {
00285                 //Logger::log(S3D::formatStringBuffer(
00286                 //      "NetServerTCP2: Invalid send destination %u", 
00287                 //      message.getDestinationId()));
00288                 return;
00289         }
00290 
00291         NetServerTCP2Destination *destination = (*itor).second;
00292         if (message.getMessageType() == NetMessage::DisconnectMessage)
00293         {
00294                 // This is a message telling us to kick the client, do so
00295                 //Logger::log(S3D::formatStringBuffer("Disconnected %u - kicked", 
00296                 //      message.getDestinationId()));
00297                 destroyDestination(message.getDestinationId(), NetMessage::KickDisconnect);
00298         }
00299         else
00300         {
00301                 // Add this buffer to the list of items to be sent
00302                 NetMessage *newMessage = NetMessagePool::instance()->getFromPool(
00303                         message.getMessageType(), message.getDestinationId(),
00304                         message.getIpAddress(), message.getFlags());
00305                 newMessage->getBuffer().allocate(message.getBuffer().getBufferUsed());
00306                 memcpy(newMessage->getBuffer().getBuffer(), 
00307                         message.getBuffer().getBuffer(),
00308                         message.getBuffer().getBufferUsed());
00309                 newMessage->getBuffer().setBufferUsed(message.getBuffer().getBufferUsed());
00310 
00311                 destination->addMessage(newMessage);
00312         }
00313 }
00314 
00315 void NetServerTCP2::disconnectAllClients()
00316 {
00317         // Get a new buffer from the pool (with the discconect type set)
00318         NetMessage *message = NetMessagePool::instance()->
00319                 getFromPool(NetMessage::DisconnectAllMessage, 0, 0);
00320 
00321         // Send Mesage
00322         outgoingMessageHandler_.addMessage(message);
00323 }
00324 
00325 void NetServerTCP2::disconnectClient(unsigned int destination)
00326 {
00327         // Get a new buffer from the pool (with the discconect type set)
00328         NetMessage *message = NetMessagePool::instance()->
00329                 getFromPool(NetMessage::DisconnectMessage, destination, 0);
00330 
00331         // Send Mesage
00332         outgoingMessageHandler_.addMessage(message);
00333 }
00334 
00335 void NetServerTCP2::sendMessageServer(NetBuffer &buffer, 
00336         unsigned int flags)
00337 {
00338         // Send a message to the server
00339         sendMessageDest(buffer, serverDestinationId_, flags);
00340 }
00341 
00342 void NetServerTCP2::sendMessageDest(NetBuffer &buffer, 
00343         unsigned int destination, unsigned int flags)
00344 {
00345         // Get a new buffer from the pool
00346         NetMessage *message = NetMessagePool::instance()->
00347                 getFromPool(NetMessage::BufferMessage, 
00348                                 destination, 0, flags);
00349 
00350         // Add message to new buffer
00351         message->getBuffer().allocate(buffer.getBufferUsed());
00352         memcpy(message->getBuffer().getBuffer(), 
00353                 buffer.getBuffer(), buffer.getBufferUsed());
00354         message->getBuffer().setBufferUsed(buffer.getBufferUsed());
00355 
00356         // Send Mesage
00357         outgoingMessageHandler_.addMessage(message);
00358 }
00359 
00360 int NetServerTCP2::processMessages()
00361 {
00362         // Process any messages that we have recieved
00363         return incomingMessageHandler_.processMessages();
00364 }
00365 
00366 void NetServerTCP2::setMessageHandler(NetMessageHandlerI *handler)
00367 {
00368         // Set the message handler to process any messages that we recieve
00369         incomingMessageHandler_.setMessageHandler(handler);
00370 }
00371 
00372 void NetServerTCP2::destroyDestination(unsigned int destinationId,
00373         NetMessage::DisconnectFlags type)
00374 {
00375         // Destroy this destination
00376         std::map<unsigned int, NetServerTCP2Destination *>::iterator itor =
00377                 destinations_.find(destinationId);
00378         if (itor == destinations_.end())
00379         {
00380                 return;
00381         }
00382 
00383         if (serverDestinationId_ == destinationId)
00384         {
00385                 stopped_ = true;
00386                 serverDestinationId_ = UINT_MAX;
00387         }
00388 
00389         NetServerTCP2Destination *destination = (*itor).second;
00390 
00391         // Get a new buffer from the pool (with the discconect type set)
00392         NetMessage *message = NetMessagePool::instance()->
00393                 getFromPool(NetMessage::DisconnectMessage, 
00394                         destinationId, destination->getIpAddress());
00395         message->setFlags((unsigned int) type);
00396 
00397         destinations_.erase(itor);
00398         destination->printStats(destinationId);
00399         destination->stop();
00400         finishedDestinations_.push_back(destination);
00401 
00402         // Add to outgoing message pool
00403         incomingMessageHandler_.addMessage(message);
00404 }
00405 
00406 unsigned int NetServerTCP2::addDestination(TCPsocket &socket)
00407 {
00408         NetInterface::getConnects() ++;
00409 
00410         // Allocate new destination id
00411         do {
00412                 nextDestinationId_++;
00413         } while (nextDestinationId_ == 0 || nextDestinationId_ == UINT_MAX);
00414         unsigned int destinationId = nextDestinationId_;
00415 
00416         // Create new destination 
00417         NetServerTCP2Destination *destination = 
00418                 new NetServerTCP2Destination(
00419                         &incomingMessageHandler_, socket, destinationId);
00420         destinations_[destinationId] = destination;
00421 
00422         // Get a new buffer from the pool (with the connect type set)
00423         NetMessage *message = NetMessagePool::instance()->
00424                 getFromPool(NetMessage::ConnectMessage, 
00425                         destinationId, destination->getIpAddress());
00426         incomingMessageHandler_.addMessage(message);
00427 
00428         // Return new id
00429         return destinationId;
00430 }

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